Branch data Line data Source code
1 : : /*
2 : : * International Chemical Identifier (InChI)
3 : : * Version 1
4 : : * Software version 1.07
5 : : * April 30, 2024
6 : : *
7 : : * MIT License
8 : : *
9 : : * Copyright (c) 2024 IUPAC and InChI Trust
10 : : *
11 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
12 : : * of this software and associated documentation files (the "Software"), to deal
13 : : * in the Software without restriction, including without limitation the rights
14 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 : : * copies of the Software, and to permit persons to whom the Software is
16 : : * furnished to do so, subject to the following conditions:
17 : : *
18 : : * The above copyright notice and this permission notice shall be included in all
19 : : * copies or substantial portions of the Software.
20 : : *
21 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 : : * SOFTWARE.
28 : : *
29 : : * The InChI library and programs are free software developed under the
30 : : * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
31 : : * Originally developed at NIST.
32 : : * Modifications and additions by IUPAC and the InChI Trust.
33 : : * Some portions of code were developed/changed by external contributors
34 : : * (either contractor or volunteer) which are listed in the file
35 : : * 'External-contributors' included in this distribution.
36 : : *
37 : : * info@inchi-trust.org
38 : : *
39 : : */
40 : :
41 : : #include <string.h>
42 : : #include <stdlib.h>
43 : : #include <ctype.h>
44 : :
45 : : #include "mode.h"
46 : :
47 : : #if defined(COMPILE_ANSI_ONLY) && defined(__APPLE__)
48 : : /* For build under OSX, advice from Burt Leland */
49 : : #include "ichicomp.h" /* Needed for __isascii define */
50 : : #endif
51 : :
52 : : /* djb-rwth: defining __isascii */
53 : : #if defined(__isascii)
54 : : #define is_ascii __isascii
55 : : #elif defined(isascii)
56 : : #define is_ascii isascii
57 : : #else
58 : : #define is_ascii(c) ((unsigned)(c) < 0x80)
59 : : #endif
60 : :
61 : : #include "util.h"
62 : : #include "extr_ct.h"
63 : :
64 : : #include "bcf_s.h"
65 : :
66 : :
67 : : /* CHEMICAL ELEMENTS & ATOMIC VALENCE MODEL
68 : : FOR VARIOUS OXIDATION STATES
69 : : */
70 : : const ELDATA ElData[] =
71 : : {
72 : : /* avg norm El No -------- Valence(s) of an ion or neutral atom -------------*/
73 : : /* mw mass exact mw type neg H -2 -1 0 +1 +2 */
74 : : { "H", 1, 1, 1.007825035, 0 , 21, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
75 : : { "D", 2, 2, 2.014101778, 0 , 21, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
76 : : { "T", 3, 3, 3.016049268, 0 , 21, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
77 : : { "He", 4, 4, 4.002600000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
78 : : { "Li", 7, 7, 7.016000000, METAL , 10, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
79 : : { "Be", 9, 9, 9.012180000, METAL , 15, 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
80 : : { "B", 11, 11, 11.009300000, 0 , 20, 0, {{3,}, {4,}, {3,}, {2,}, {1,} }},
81 : : { "C", 12, 12, 12.000000000, 0 , 25, 0, {{2,}, {3,}, {4,}, {3,}, {2,} }},
82 : : { "N", 14, 14, 14.003074000, 0 , 30, 0, {{1,}, {2,}, {3,5}, {4,}, {3,} }},
83 : : { "O", 16, 16, 15.994914630, 0 , 35, 0, {{0,}, {1,}, {2,}, {3,5,}, {4,} }},
84 : : { "F", 19, 19, 18.998403220, 0 , 40, 0, {{0,}, {0,}, {1,}, {2,}, {3,5} }},
85 : : { "Ne", 20, 20, 19.992440000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
86 : : { "Na", 23, 23, 22.989770000, METAL , 9, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
87 : : { "Mg", 24, 24, 23.985000000, METAL , 12, 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
88 : : { "Al", 27, 27, 26.981540000, METAL , 15, 0, {{3,5,}, {4,}, {3,}, {2,}, {1,} }},
89 : : { "Si", 28, 28, 27.976927100, 0 , 18, 0, {{2,}, {3,5}, {4,}, {3,}, {2,} }},
90 : : { "P", 31, 31, 30.973762000, 0 , 21, 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {4,}, {3,} }},
91 : : { "S", 32, 32, 31.972070700, 0 , 25, 0, {{0,}, {1,3,5,7,}, {2,4,6}, {3,5,}, {4,} }},
92 : : { "Cl", 35, 35, 34.968852730, 0 , 30, 0, {{0,}, {0,}, {1,3,5,7}, {2,4,6}, {3,5,} }},
93 : : { "Ar", 40, 40, 39.962400000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
94 : : { "K", 39, 39, 38.963700000, METAL , 8, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
95 : : { "Ca", 40, 40, 39.962600000, METAL , 10, 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
96 : : { "Sc", 45, 45, 44.955910000, METAL , 13, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
97 : : { "Ti", 48, 48, 47.947950000, METAL , 15, 1, {{0,}, {0,}, {3,4}, {0,}, {0,} }},
98 : : { "V", 51, 51, 50.943960000, METAL , 16, 1, {{0,}, {0,}, {2,3,4,5,}, {0,}, {0,} }},
99 : : { "Cr", 52, 52, 51.940500000, METAL , 16, 1, {{0,}, {0,}, {2,3,6,}, {0,}, {0,} }},
100 : : { "Mn", 55, 55, 54.938050000, METAL2, 15, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
101 : : { "Fe", 56, 56, 55.934900000, METAL2, 18, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
102 : : { "Co", 59, 59, 58.933200000, METAL2, 18, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
103 : : { "Ni", 59, 58, 57.935300000, METAL2, 18, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
104 : : { "Cu", 64, 63, 62.929600000, METAL , 19, 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }},
105 : : { "Zn", 65, 64, 63.929147000, METAL , 16, 1, {{0,}, {0,}, {2,}, {0,}, {0,} }},
106 : : { "Ga", 70, 69, 68.925600000, METAL , 18, 0, {{3,5,}, {4,}, {3,}, {0,}, {1,} }},
107 : : { "Ge", 73, 74, 73.921177400, 0 , 18, 0, {{2,4,6,}, {3,5,}, {4,}, {3,}, {0,} }},
108 : : { "As", 75, 75, 74.921594200, 0 , 20, 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {4,}, {3,} }},
109 : : { "Se", 79, 80, 79.916519600, 0 , 24, 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {4,} }},
110 : : { "Br", 80, 79, 78.918336100, 0 , 28, 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6,}, {3,5,} }},
111 : : { "Kr", 84, 84, 83.911500000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
112 : : { "Rb", 85, 85, 84.911800000, METAL , 8, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
113 : : { "Sr", 88, 88, 87.905600000, METAL , 10, 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
114 : : { "Y", 89, 89, 88.905860000, METAL , 12, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
115 : : { "Zr", 91, 90, 89.904700000, METAL , 14, 1, {{0,}, {0,}, {4,}, {0,}, {0,} }},
116 : : { "Nb", 93, 93, 92.906400000, METAL , 16, 1, {{0,}, {0,}, {3,5,}, {0,}, {0,} }},
117 : : { "Mo", 96, 98, 97.905400000, METAL , 18, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
118 : : { "Tc", 98, 98, 97.907200000, METAL , 19, 1, {{0,}, {0,}, {7,}, {0,}, {0,} }},
119 : : { "Ru", 101, 102, 101.904300000, METAL , 22, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
120 : : { "Rh", 103, 103, 102.905500000, METAL , 22, 1, {{0,}, {0,}, {2,3,4,}, {0,}, {0,} }},
121 : : { "Pd", 106, 106, 105.903500000, METAL , 22, 1, {{0,}, {0,}, {2,4,}, {0,}, {0,} }},
122 : : { "Ag", 108, 107, 106.905100000, METAL , 19, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
123 : : { "Cd", 112, 114, 113.903400000, METAL , 17, 1, {{0,}, {0,}, {2,}, {0,}, {0,} }},
124 : : { "In", 115, 115, 114.903900000, METAL , 17, 0, {{3,5,}, {2,4,}, {3,}, {0,}, {1,} }},
125 : : { "Sn", 119, 120, 119.902200000, METAL2, 18, 0, {{2,4,6,}, {3,5}, {2,4,}, {3,}, {0,} }},
126 : : { "Sb", 122, 121, 120.903800000, METAL, 19, 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, {3,} }},
127 : : { "Te", 128, 130, 129.906200000, 0 , 21, 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,} }},
128 : : { "I", 127, 127, 126.904500000, 0 , 25, 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6}, {3,5,} }},
129 : : { "Xe", 131, 132, 131.904100000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
130 : : { "Cs", 133, 133, 132.905430000, METAL , 7, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
131 : : { "Ba", 137, 138, 137.905200000, METAL , 9, 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
132 : : { "La", 139, 139, 138.906360000, METAL , 11, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
133 : : { "Ce", 140, 140, 139.905400000, METAL2, 0, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
134 : : { "Pr", 141, 141, 140.907660000, METAL2, 0, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
135 : : { "Nd", 144, 142, 141.907719000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
136 : : { "Pm", 145, 145, 144.912800000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
137 : : { "Sm", 150, 152, 151.919700000, METAL2, 0, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
138 : : { "Eu", 152, 153, 152.921200000, METAL2, 0, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
139 : : { "Gd", 157, 158, 157.924099000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
140 : : { "Tb", 159, 159, 158.925350000, METAL2, 0, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
141 : : { "Dy", 163, 164, 163.929200000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }}, /* mw rounding uncertain */
142 : : { "Ho", 165, 165, 164.930300000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
143 : : { "Er", 167, 166, 165.930300000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
144 : : { "Tm", 169, 169, 168.934230000, METAL2, 0, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
145 : : { "Yb", 173, 174, 173.938900000, METAL2, 0, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
146 : : { "Lu", 175, 175, 174.940800000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
147 : : { "Hf", 178, 180, 179.946600000, METAL , 13, 1, {{0,}, {0,}, {4,}, {0,}, {0,} }},
148 : : { "Ta", 181, 181, 180.948010000, METAL , 15, 1, {{0,}, {0,}, {5,}, {0,}, {0,} }},
149 : : { "W", 184, 184, 183.951000000, METAL2, 17, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
150 : : { "Re", 186, 187, 186.955800000, METAL2, 19, 1, {{0,}, {0,}, {2,4,6,7,}, {0,}, {0,} }},
151 : : { "Os", 190, 192, 191.961500000, METAL2, 22, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
152 : : { "Ir", 192, 193, 192.962900000, METAL2, 22, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
153 : : { "Pt", 195, 195, 194.964800000, METAL2, 22, 1, {{0,}, {0,}, {2,4,}, {0,}, {0,} }},
154 : : { "Au", 197, 197, 196.966560000, METAL , 24, 1, {{0,}, {0,}, {1,3,}, {0,}, {0,} }},
155 : : { "Hg", 201, 202, 201.970617000, METAL2, 19, 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }},
156 : : { "Tl", 204, 205, 204.974400000, METAL2, 18, 0, {{3,5,}, {2,4,}, {1,3,}, {0,}, {0,} }},
157 : : { "Pb", 207, 208, 207.976627000, METAL2, 18, 0, {{2,4,6,}, {3,5}, {2,4,}, {3,}, {0,} }},
158 : : { "Bi", 209, 209, 208.980390000, METAL , 19, 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, {3,} }},
159 : : { "Po", 209, 209, 208.982400000, METAL2, 20, 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,} }},
160 : : { "At", 210, 210, 209.987100000, 0 , 22, 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6}, {3,5,} }},
161 : : { "Rn", 222, 222, 222.017500000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
162 : : { "Fr", 223, 223, 223.019700000, METAL , 0, 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
163 : : { "Ra", 226, 226, 226.025410000, METAL , 0, 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
164 : : { "Ac", 227, 227, 227.027750000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
165 : : { "Th", 232, 232, 232.038050000, METAL2, 0, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
166 : : { "Pa", 231, 231, 231.035880000, METAL2, 0, 1, {{0,}, {0,}, {3,4,5,}, {0,}, {0,} }},
167 : : { "U", 238, 238, 238.050790000, METAL2, 0, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
168 : : { "Np", 237, 237, 237.048170000, METAL2, 0, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
169 : : { "Pu", 244, 244, 244.064200000, METAL2, 0, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
170 : : { "Am", 243, 243, 243.061370000, METAL2, 0, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
171 : : { "Cm", 247, 247, 247.070300000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
172 : : { "Bk", 247, 247, 247.070300000, METAL , 0, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
173 : : { "Cf", 251, 251, 251.079600000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
174 : : { "Es", 252, 252, 252.082800000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
175 : : { "Fm", 257, 257, 257.095100000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
176 : : { "Md", 258, 258, 258.098600000, METAL , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
177 : : { "No", 259, 259, 259.100900000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
178 : : { "Lr", 260, 260, 260.105400000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
179 : : { "Rf", 261, 261, 261.108700000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
180 : :
181 : : /*
182 : : The elements below were added after v. 1.03.
183 : : When available, the mass is given for isotope with the longest half-life.
184 : : Standard valences given here are just placeholders.
185 : : v. 1.04: added elements 105-112.
186 : : Ref.: M. E. WIESER AND T. B. COPLEN.
187 : : Atomic weights of the elements 2009 (IUPAC Technical Report).
188 : : Pure Appl. Chem., Vol. 83, No. 2, pp. 359-396, 2011.
189 : : v. 1.05: added elements 114 and 116;
190 : : updated data for elements 105-112.
191 : : Ref.: J. Meija, T.B. Coplen, M.Berglund et al.
192 : : Atomic weights of the elements 2013 (IUPAC Technical Report).
193 : : Pure Appl. Chem., Vol. 88, No. 3, pp. 265-291, 2016.
194 : : added elements 113, 115, 117, and 118, according to IUPAC provisional recommendations:
195 : : Ref.: L. Ohrstrom, J. Reedijk.
196 : : Names and Symbols of the Elements with Atomic Numbers 113, 115, 117 and 118.
197 : : Pure Appl. Chem., May 1, 2016, Manuscript ID PAC-REC-16-05-01
198 : : http://iupac.org/cms/wp-content/uploads/2016/06/names-and-symbols-of-elements.pdf
199 : : */
200 : :
201 : : /* 105 dubnium Db ? Like: Ta */
202 : : { "Db", 270, 270, 270.131000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
203 : : /* 106 seaborgium Sg ? Like: W */
204 : : { "Sg", 269, 269, 269.129000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
205 : : /* 107 bohrium Bh ? Like: Re */
206 : : { "Bh", 270, 270, 270.133000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
207 : : /* 108 hassium Hs ? Like: Os */
208 : : { "Hs", 270, 270, 270.134000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
209 : : /* 109 meitnerium Mt ? Like: Ir */
210 : : { "Mt", 278, 278, 278.156000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
211 : : /* 110 darmstadtium Ds ? Like: Pt */
212 : : { "Ds", 281, 281, 281.165000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
213 : : /* 111 roentgenium Rg ? Like: Au */
214 : : { "Rg", 281, 281, 281.166000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
215 : : /* 112 copernicium Cn ? Like: Hg */
216 : : { "Cn", 285, 285, 285.177000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
217 : : /* 113 nihonium Nh ? Like: ? */
218 : : { "Nh", 278, 278, 278.000000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
219 : : /* 114 flerovium Fl ? Like: Pb */
220 : : { "Fl", 289, 289, 289.190000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
221 : : /* 115 moscovium Mc ? Like: ? */
222 : : { "Mc", 289, 289, 289.000000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
223 : : /* 116 livermorium Lv ? Like: Po */
224 : : { "Lv", 293, 293, 293.204000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
225 : : /* 117 tennessine Ts ? Like: ? */
226 : : { "Ts", 297, 297, 297.000000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
227 : : /* 118 oganesson Og ? Like: ? */
228 : : { "Og", 294, 294, 294.000000000, METAL , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
229 : : /* End of added in v. 1.04 - 1.05 */
230 : : { "Zy", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
231 : : { "Zz", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
232 : : #ifdef INCHI_ZFRAG
233 : : { "Zu", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
234 : : { "Zv", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {2,}, {0,}, {0,} }},
235 : : { "Zw", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
236 : : { "Zx", 0, 0, 0.000000000, 0 , 0, 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }},
237 : : #endif
238 : :
239 : : { "", 0, 0, 0.000000000, 0 , 0, 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
240 : : };
241 : :
242 : :
243 : : const int ERR_ELEM = 255;
244 : : const int nElDataLen = sizeof( ElData ) / sizeof( ElData[0] ) - 1;
245 : :
246 : :
247 : :
248 : : /*
249 : : MISC. CHEMICAL-STRUCTURE RELATED UTILITIES AND HELPERS
250 : : */
251 : :
252 : :
253 : : /****************************************************************************
254 : : Finds chemical symbol for element of given number.
255 : : Returns 0 if OK and -1 if element was not found.
256 : : ****************************************************************************/
257 : 1182 : int get_element_chemical_symbol( int nAtNum, char *szElement )
258 : : {
259 : 1182 : nAtNum -= 1;
260 : :
261 [ + - ]: 1182 : if ( 0 < nAtNum )
262 : : {
263 : 1182 : nAtNum += 2; /* bypass D, T */
264 : : }
265 : :
266 [ + - + - ]: 1182 : if ( 0 <= nAtNum && nAtNum < nElDataLen )
267 : : {
268 : : /* valid element symbol found */
269 : 1182 : strcpy(szElement, ElData[nAtNum].szElName);
270 : 1182 : return 0;
271 : : }
272 : :
273 : : /* not found */
274 : 0 : strcpy(szElement, "??");
275 : 0 : return -1;
276 : : }
277 : :
278 : :
279 : : /****************************************************************************
280 : : Finds symbol for element of given number.
281 : : Accounts for (translates)pseudoelements.
282 : : Returns 0 if OK and -1 if element was not found.
283 : : ****************************************************************************/
284 : 264 : int get_element_or_pseudoelement_symbol( int nAtNum,
285 : : char *szElement )
286 : : {
287 : 264 : nAtNum -= 1;
288 : :
289 [ + + ]: 264 : if ( 0 < nAtNum )
290 : : {
291 : 263 : nAtNum += 2; /* bypass D, T */
292 : : }
293 : :
294 [ + - + - ]: 264 : if ( 0 <= nAtNum && nAtNum < nElDataLen )
295 : : {
296 : : /* valid element symbol found */
297 : 264 : strcpy(szElement, ElData[nAtNum].szElName);
298 : :
299 [ - + ]: 264 : if (!strcmp( szElement, "Zy" ))
300 : : {
301 : 0 : strcpy(szElement, "Zz");
302 : : }
303 : :
304 : 264 : return 0;
305 : : }
306 : :
307 : : /* not found */
308 : 0 : strcpy(szElement, "??");
309 : :
310 : 0 : return -1;
311 : : }
312 : :
313 : :
314 : : /****************************************************************************/
315 : 2027 : int el_number_in_internal_ref_table( const char* elname )
316 : : {
317 : : int i;
318 : : const char* p;
319 : :
320 [ + - + + ]: 24532 : for (i = 0; ( p = ElData[i].szElName )[0] && strcmp( p, elname ); i++)
321 : : {
322 : : ;
323 : : }
324 : :
325 [ + - ]: 2027 : return p[0] ? i : ERR_ELEM;
326 : : }
327 : :
328 : :
329 : : /****************************************************************************
330 : : Get element number by symbol
331 : : ****************************************************************************/
332 : 1238 : int get_periodic_table_number( const char* elname )
333 : : {
334 : : int num;
335 : :
336 [ - + ]: 1238 : if (elname == NULL)
337 : : {
338 : 0 : return ERR_ELEM;
339 : : }
340 : :
341 [ - + ]: 1238 : if (strlen(elname) == 0)
342 : : {
343 : 0 : return ERR_ELEM;
344 : : }
345 : :
346 : : /* the single letter (common) elements */
347 [ + + ]: 1238 : if (!elname[1])
348 : : {
349 [ + - + + : 1014 : switch (elname[0])
+ - - + -
+ ]
350 : : {
351 : 2 : case 'H':
352 : 2 : return EL_NUMBER_H;
353 : : break;
354 : 0 : case 'B':
355 : 0 : return EL_NUMBER_B;
356 : : break;
357 : 832 : case 'C':
358 : 832 : return EL_NUMBER_C;
359 : : break;
360 : 34 : case 'N':
361 : 34 : return EL_NUMBER_N;
362 : : break;
363 : 124 : case 'O':
364 : 124 : return EL_NUMBER_O;
365 : : break;
366 : 0 : case 'P':
367 : 0 : return EL_NUMBER_P;
368 : : break;
369 : 0 : case 'S':
370 : 0 : return EL_NUMBER_S;
371 : : break;
372 : 20 : case 'F':
373 : 20 : return EL_NUMBER_F;
374 : : break;
375 : 0 : case 'I':
376 : 0 : return EL_NUMBER_I;
377 : : break;
378 : : }
379 : : }
380 : :
381 : 226 : num = el_number_in_internal_ref_table( elname );
382 : :
383 [ + - ]: 226 : if ( num < ERR_ELEM )
384 : : {
385 : : /* account for D,T in internal table (but not Mendeleev's table) */
386 : 226 : num = inchi_max( 1, num - 1 );
387 : : }
388 : :
389 : 226 : return num;
390 : : }
391 : :
392 : :
393 : : /****************************************************************************
394 : : Check if no H addition allowed
395 : : ****************************************************************************/
396 : 1182 : int if_skip_add_H( int nPeriodicNum )
397 : : /* was called if_skip_add_H(, renamed to avoid confusion with other procedures */
398 : : {
399 : : return
400 [ + - ]: 1182 : ElData[nPeriodicNum > 1 ? nPeriodicNum + 1 : 0].bSkipAddingH;
401 : : }
402 : :
403 : :
404 : : /****************************************************************************
405 : : Get reference value of atom valence at given charge
406 : : ****************************************************************************/
407 : 14415 : int get_el_valence( int nPeriodicNum, int charge, int val_num )
408 : : {
409 [ + - + - : 14415 : if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE || val_num >= MAX_NUM_VALENCES )
- + ]
410 : : {
411 : 0 : return 0;
412 : : }
413 : :
414 : : return
415 [ + + ]: 14415 : ElData[nPeriodicNum > 1 ? nPeriodicNum + 1 : 0].cValence[NEUTRAL_STATE + charge][val_num];
416 : : }
417 : :
418 : :
419 : : /****************************************************************************
420 : : Output valence needed to unambiguosly reconstruct bonds
421 : : ****************************************************************************/
422 : 617 : int get_unusual_el_valence( int nPeriodicNum,
423 : : int charge,
424 : : int radical,
425 : : int bonds_valence,
426 : : int num_H,
427 : : int num_bonds )
428 : : {
429 : : int i, num_found, chem_valence, rad_adj, known_chem_valence, exact_found;
430 : :
431 [ + + - + ]: 617 : if ( !num_bonds && !num_H )
432 : : {
433 : 0 : return 0;
434 : : }
435 : :
436 [ + - - + ]: 617 : if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE )
437 : : {
438 [ # # ]: 0 : if ( bonds_valence == num_bonds )
439 : : {
440 : 0 : return 0; /* all single bonds */
441 : : }
442 : 0 : return bonds_valence;
443 : : }
444 : :
445 [ + + + - ]: 617 : if (!get_el_valence( nPeriodicNum, charge, 0 ) && bonds_valence == num_bonds)
446 : : {
447 : 1 : return 0;
448 : : }
449 : :
450 : 616 : chem_valence = bonds_valence + num_H;
451 : 616 : rad_adj = 0;
452 : 616 : num_found = 0;
453 : 616 : exact_found = 0;
454 : :
455 : : /* Take into account a radical */
456 [ - + ]: 616 : if ( radical == RADICAL_DOUBLET )
457 : : {
458 : 0 : rad_adj = 1;
459 : : }
460 [ - + ]: 616 : else if ( radical == RADICAL_TRIPLET )
461 : : {
462 : 0 : rad_adj = 2;
463 : : }
464 : :
465 [ + + ]: 633 : for ( i = 0; i < MAX_NUM_VALENCES; i++ )
466 : : {
467 [ + + + + ]: 631 : if (0 < ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) - rad_adj ) &&
468 [ + - ]: 617 : num_bonds <= known_chem_valence && known_chem_valence <= chem_valence)
469 : : {
470 : 617 : num_found++;
471 [ + + ]: 617 : if ( known_chem_valence == chem_valence )
472 : : {
473 : 614 : exact_found = 1;
474 : 614 : break;
475 : : }
476 : : }
477 : : }
478 : :
479 [ + + + + ]: 616 : return ( exact_found && 1 == num_found ) ? 0 : chem_valence;
480 : : }
481 : :
482 : :
483 : : /****************************************************************************
484 : : Output valence needed to unambiguosly reconstruct number of H
485 : : ****************************************************************************/
486 : 1182 : int needed_unusual_el_valence( int nPeriodicNum,
487 : : int charge,
488 : : int radical,
489 : : int bonds_valence,
490 : : int actual_bonds_valence,
491 : : int num_H, int
492 : : num_bonds )
493 : : {
494 : : int chem_valence, num_H_expected; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
495 : : char szElement[4];
496 : :
497 : : /*
498 : : if ( !num_bonds && !num_H )
499 : : return 0;
500 : : */
501 : :
502 [ + - + - ]: 1182 : if (num_bonds && get_element_chemical_symbol( nPeriodicNum, szElement ) != -1)
503 : : {
504 : 1182 : num_H_expected = get_num_H( szElement, 0, NULL, charge, radical, actual_bonds_valence, 0, 0, 0, 0 );
505 : : }
506 : : else
507 : : {
508 : 0 : num_H_expected = num_H;
509 : : }
510 : :
511 : 1182 : chem_valence = bonds_valence + num_H;
512 : :
513 : : #if ( (BUILD_WITH_ENG_OPTIONS==1) && (SDF_OUTPUT_HETERO_VALENCE==1) )
514 : : if ((nPeriodicNum == 1 && chem_valence != 1) /* H */ || (nPeriodicNum == 6 && chem_valence != 4) /* C */ ||
515 : : (nPeriodicNum != 1 && nPeriodicNum != 6) || charge || radical) /* djb-rwth: addressing LLVM warning */
516 : : {
517 : : return chem_valence ? chem_valence : -1;
518 : : }
519 : : else
520 : : {
521 : : return 0;
522 : : }
523 : : #else
524 : : {
525 : : int i, num_found, num_found_known, rad_adj, known_chem_valence, exact_found;
526 : :
527 [ + - + - : 2364 : if (charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE ||
+ - ]
528 [ + + ]: 2364 : !get_el_valence( nPeriodicNum, charge, 0 ) ||
529 [ + + - + ]: 2362 : if_skip_add_H( nPeriodicNum ) || bonds_valence != actual_bonds_valence ||
530 : : num_H_expected != num_H)
531 : : {
532 [ + + + - : 22 : if ( !num_H && !num_H_expected && bonds_valence == actual_bonds_valence )
- + ]
533 : : {
534 : 0 : return 0; /* no H */
535 : : }
536 : 22 : return chem_valence; /* needs to add H-atoms */
537 : : }
538 : :
539 : : /* take into account radical */
540 [ - + ]: 1160 : if ( radical == RADICAL_DOUBLET )
541 : : {
542 : 0 : rad_adj = 1;
543 : : }
544 [ - + ]: 1160 : else if ( radical == RADICAL_TRIPLET )
545 : : {
546 : 0 : rad_adj = 2;
547 : : }
548 : : else
549 : : {
550 : 1160 : rad_adj = 0;
551 : : }
552 : :
553 : 1160 : num_found_known = 0;
554 : 1160 : num_found = 0;
555 : 1160 : exact_found = 0;
556 : :
557 [ + - ]: 1160 : for ( i = 0; i < MAX_NUM_VALENCES; i++ )
558 : : {
559 [ + - ]: 1160 : if (0 < ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) ) &&
560 [ + - ]: 1160 : bonds_valence <= ( known_chem_valence -= rad_adj ))
561 : : {
562 : : /* found known valence that fits without H */
563 : 1160 : num_found_known++;
564 [ + - ]: 1160 : if ( known_chem_valence <= chem_valence )
565 : : {
566 : : /* known valence is large enough to accommodate (implicit) H */
567 : 1160 : num_found++;
568 : : }
569 [ + - ]: 1160 : if ( known_chem_valence == chem_valence )
570 : : {
571 : 1160 : exact_found = 1;
572 : 1160 : break;
573 : : }
574 : : }
575 : : }
576 : :
577 [ + - - + ]: 1160 : return ( exact_found && 1 == num_found && 1 == num_found_known )
578 : : ? 0
579 [ + - - - ]: 2320 : : chem_valence ? chem_valence : -1; /* needs zero */
580 : : }
581 : : #endif
582 : : }
583 : :
584 : :
585 : : /****************************************************************************
586 : : Output valence that does not fit any known valences
587 : : ****************************************************************************/
588 : 3931 : int detect_unusual_el_valence( int nPeriodicNum,
589 : : int charge,
590 : : int radical,
591 : : int bonds_valence,
592 : : int num_H,
593 : : int num_bonds )
594 : : {
595 : : int i, chem_valence, rad_adj, known_chem_valence;
596 : :
597 [ + + + - ]: 3931 : if ( !num_bonds && !num_H )
598 : : {
599 : 4 : return 0;
600 : : }
601 : :
602 [ + - - + ]: 3927 : if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE )
603 : : {
604 [ # # ]: 0 : if ( bonds_valence == num_bonds )
605 : : {
606 : 0 : return 0; /* all single bonds */
607 : : }
608 : 0 : return bonds_valence;
609 : : }
610 : :
611 [ + + + - ]: 3927 : if (!get_el_valence( nPeriodicNum, charge, 0 ) && bonds_valence == num_bonds)
612 : : {
613 : 4 : return 0;
614 : : }
615 : :
616 : 3923 : chem_valence = bonds_valence + num_H;
617 : 3923 : rad_adj = 0;
618 : :
619 : : /* take into account radical */
620 [ - + ]: 3923 : if ( radical == RADICAL_DOUBLET )
621 : : {
622 : 0 : rad_adj = 1;
623 : : }
624 [ + - - + ]: 3923 : else if ( radical == RADICAL_TRIPLET || radical == RADICAL_SINGLET )
625 : : {
626 : 0 : rad_adj = 2;
627 : : }
628 : :
629 [ + + ]: 4043 : for ( i = 0; i < MAX_NUM_VALENCES; i++ )
630 : : {
631 [ + + ]: 4026 : if (0 < ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) - rad_adj ))
632 : : {
633 [ + + ]: 3961 : if ( known_chem_valence == chem_valence )
634 : : {
635 : 3906 : return 0;
636 : : }
637 : : }
638 : : }
639 : :
640 : 17 : return chem_valence;
641 : : }
642 : :
643 : :
644 : : /****************************************************************************
645 : : Return element type
646 : : ****************************************************************************/
647 : 1790 : int get_el_type( int nPeriodicNum )
648 : : {
649 : 1790 : return ElData[nPeriodicNum + 1].nType;
650 : : }
651 : :
652 : :
653 : : /****************************************************************************
654 : : Check if element is metal
655 : : ****************************************************************************/
656 : 6214 : int is_el_a_metal( int nPeriodicNum )
657 : : {
658 : 6214 : return 0 != ( ElData[nPeriodicNum + 1].nType & IS_METAL );
659 : : }
660 : :
661 : :
662 : : /*#ifndef TARGET_API_LIB*/
663 : :
664 : :
665 : : /****************************************************************************
666 : : Extract radicals and charges
667 : : ****************************************************************************/
668 : 0 : int extract_charges_and_radicals( char *elname, int *pnRadical, int *pnCharge )
669 : : {
670 : : char *q, *r, *p;
671 : 0 : int nCharge = 0, nRad = 0, charge_len = 0, k, nVal, nSign, nLastSign = 1; /* djb-rwth: removing redundant variables */
672 : :
673 : 0 : p = elname;
674 : :
675 : : /* extract radicals & charges */
676 [ # # ]: 0 : while ( (q = strpbrk(p, "+-^")) ) /* djb-rwth: addressing LLVM warning */
677 : : {
678 [ # # # ]: 0 : switch ( *q )
679 : : {
680 : 0 : case '+':
681 : : case '-':
682 [ # # # # ]: 0 : for (k = 0, nVal = 0; ( nSign = ( '+' == q[k] ) ) || ( nSign = -( '-' == q[k] ) ); k++)
683 : : {
684 : 0 : nVal += ( nLastSign = nSign );
685 : 0 : charge_len++;
686 : : }
687 [ # # ]: 0 : if ((nSign = (int)strtol(q + k, &r, 10))) /* djb-rwth: addressing LLVM warning */
688 : : {
689 : : /* fixed 12-5-2001 */
690 : 0 : nVal += nLastSign * ( nSign - 1 );
691 : : }
692 : 0 : charge_len = (int) ( r - q );
693 : 0 : nCharge += nVal;
694 : 0 : break;
695 : : /* case '.': */ /* singlet '.' may be confused with '.' in formulas like CaO.H2O */
696 : 0 : case '^':
697 : 0 : nRad = 1; /* doublet here is 1. See below */
698 : 0 : charge_len = 1;
699 [ # # ]: 0 : for (k = 1; q[0] == q[k]; k++)
700 : : {
701 : 0 : nRad++;
702 : 0 : charge_len++;
703 : : }
704 : 0 : break;
705 : : }
706 : 0 : memmove(q, q + charge_len, strlen(q + charge_len) + 1);
707 : : }
708 : :
709 : : /* djb-rwth: removing redundant code */
710 : :
711 : : /* radical */
712 [ # # # # ]: 0 : if (( q = strrchr( p, ':' ) ) && !q[1])
713 : : {
714 : 0 : nRad = RADICAL_SINGLET;
715 : 0 : q[0] = '\0';
716 : : /* djb-rwth: removing redundant code */
717 : : }
718 : : else
719 : : {
720 [ # # # # ]: 0 : while (( q = strrchr( p, '.' ) ) && !q[1])
721 : : {
722 : 0 : nRad++;
723 : 0 : q[0] = '\0';
724 : : /* djb-rwth: removing redundant code */
725 : : }
726 : :
727 [ # # ]: 0 : nRad = nRad == 1 ? RADICAL_DOUBLET :
728 [ # # ]: 0 : nRad == 2 ? RADICAL_TRIPLET : 0;
729 : : }
730 : :
731 : 0 : *pnRadical = nRad;
732 : 0 : *pnCharge = nCharge;
733 : :
734 [ # # # # ]: 0 : return ( nRad || nCharge );
735 : : }
736 : :
737 : :
738 : : /*#endif*/
739 : :
740 : :
741 : : /****************************************************************************/
742 : 0 : int extract_H_atoms( char *elname, S_CHAR num_iso_H[] )
743 : : {
744 : : int i, len, c, k, num_H, val;
745 : : char* q;
746 : 0 : char elname1 = '\0';
747 : :
748 : 0 : i = 0;
749 : 0 : num_H = 0;
750 : 0 : len = (int) strlen( elname );
751 : 0 : c = UCINT elname[0];
752 : :
753 [ # # ]: 0 : if ( len > 1 )
754 : : {
755 : 0 : elname1 = elname[1];
756 : : }
757 : :
758 [ # # ]: 0 : while ( i < len )
759 : : {
760 [ # # # # ]: 0 : switch ( c )
761 : : {
762 : 0 : case 'H':
763 : 0 : k = 0;
764 : 0 : break;
765 : 0 : case 'D':
766 : 0 : k = 1;
767 : 0 : break;
768 : 0 : case 'T':
769 : 0 : k = 2;
770 : 0 : break;
771 : 0 : default:
772 : 0 : k = -1;
773 : 0 : break;
774 : : }
775 : :
776 : 0 : q = elname + i + 1; /* pointer to the next to elname[i] character */
777 : 0 : c = UCINT q[0];
778 : :
779 [ # # # # ]: 0 : if (k >= 0 && !islower( c ))
780 : : {
781 : : /* found a hydrogen */
782 [ # # ]: 0 : if (isdigit( c ))
783 : : {
784 : 0 : val = (int) strtol( q, &q, 10 );
785 : : /* q = pointer to the next to number of hydrogen atom(s) character */
786 : : }
787 : : else
788 : : {
789 : 0 : val = 1;
790 : : }
791 [ # # ]: 0 : if ( k )
792 : : {
793 : 0 : num_iso_H[k] += val;
794 : : }
795 : : else
796 : : {
797 : 0 : num_H += val;
798 : : }
799 : :
800 : : /* remove the hydrogen atom from the string */
801 : 0 : len -= (int) ( q - elname ) - i;
802 : 0 : memmove(elname + i, q, (long long)len + 1); /* djb-rwth: cast operator added */
803 : : /* c = UCINT elname[i]; */
804 : : }
805 : : else
806 : : {
807 : 0 : i++;
808 : : }
809 : :
810 : 0 : c = UCINT elname[i]; /* moved here 11-04-2002 */
811 : : }
812 : :
813 : 0 : len = (int) strlen( elname );
814 [ # # ]: 0 : if (len == 2)
815 : : {
816 [ # # ]: 0 : if ( elname[1] != elname1 )
817 : : /* Error, incorrect 2nd char of elname appears after 'subtracting' {H,D,T} */
818 : : /* See a bug reported to inchi-discuss by A. Dalke for alias atom "pH4d" */
819 : : /*^^^ 2017-01-06 */
820 : 0 : elname[1] = '?';
821 : : }
822 : :
823 : 0 : return num_H;
824 : : }
825 : :
826 : :
827 : : /****************************************************************************
828 : : Return number of attached hydrogens
829 : : ****************************************************************************/
830 : 1801 : int get_num_H( const char* elname,
831 : : int inp_num_H,
832 : : S_CHAR inp_num_iso_H[],
833 : : int charge,
834 : : int radical,
835 : : int chem_bonds_valence,
836 : : int atom_input_valence,
837 : : int bAliased,
838 : : int bDoNotAddH,
839 : : int bHasMetalNeighbor )
840 : : {
841 : 1801 : int val, i, el_number, num_H = 0, num_iso_H;
842 : : static int intl_el_number_N = 0, intl_el_number_S=0, intl_el_number_O=0, intl_el_number_C=0;
843 : :
844 [ + + ]: 1801 : if ( !intl_el_number_N )
845 : : {
846 : 3 : intl_el_number_N = el_number_in_internal_ref_table( "N" );
847 : : }
848 [ + + ]: 1801 : if ( !intl_el_number_S )
849 : : {
850 : 3 : intl_el_number_S = el_number_in_internal_ref_table( "S" );
851 : : }
852 [ + + ]: 1801 : if ( !intl_el_number_O )
853 : : {
854 : 3 : intl_el_number_O = el_number_in_internal_ref_table( "O" );
855 : : }
856 [ + + ]: 1801 : if ( !intl_el_number_C )
857 : : {
858 : 3 : intl_el_number_C = el_number_in_internal_ref_table( "C" );
859 : : }
860 : :
861 : :
862 : : /* atom_input_valence (cValence) cannot be specified in case of */
863 : : /* aliased MOLFile atom with known inp_num_H or inp_num_iso_H[] */
864 : :
865 [ - + ]: 1801 : if ( bAliased )
866 : : {
867 : 0 : num_H = inp_num_H;
868 : : }
869 [ + + - + : 1801 : else if (atom_input_valence && ( atom_input_valence != 15 || chem_bonds_valence ))
- - ]
870 : : {
871 : 12 : num_H = inchi_max( 0, atom_input_valence - chem_bonds_valence );
872 : : }
873 [ - + - - ]: 1789 : else if ( atom_input_valence == 15 && !chem_bonds_valence )
874 : : {
875 : 0 : num_H = 0;
876 : : }
877 [ + - + - ]: 1789 : else if (MIN_ATOM_CHARGE <= charge &&
878 : 1789 : MAX_ATOM_CHARGE >= charge &&
879 [ + - ]: 1789 : ERR_ELEM != ( el_number = el_number_in_internal_ref_table( elname ) ) &&
880 [ + + + - ]: 1789 : !ElData[el_number].bSkipAddingH && !bDoNotAddH)
881 : : {
882 : : /* add hydrogen atoms according to standard element valence */
883 [ - + - - ]: 1780 : if ( radical && radical != RADICAL_SINGLET )
884 : : {
885 [ # # ]: 0 : if ( (val = ElData[el_number].cValence[NEUTRAL_STATE + charge][0]) ) /* djb-rwth: addressing LLVM warning */
886 : : {
887 : 0 : val -= ( radical == RADICAL_DOUBLET ) ? 1
888 [ # # # # : 0 : : ( radical == RADICAL_SINGLET || radical == RADICAL_TRIPLET ) ? 2 : val;
# # ]
889 : : /* if unknown radical then do not add H */
890 : 0 : num_H = inchi_max( 0, val - chem_bonds_valence );
891 : : }
892 : : }
893 : : else
894 : : {
895 : : /* find the smallest valence that is greater than the sum of the chemical bond valences */
896 : 1780 : for (i = 0;
897 [ + - - + ]: 1780 : ( val = ElData[el_number].cValence[NEUTRAL_STATE + charge][i] ) &&
898 : : val < chem_bonds_valence;
899 : 0 : i++)
900 : : {
901 : : ;
902 : : }
903 : :
904 : : /* special case: do not add H to N(IV), S(III), S+(II), S-(II) */ /* S ions added 2004-05-10 */
905 [ + + + - : 1780 : if ( el_number == intl_el_number_N && !charge && !radical && val == 5 )
+ - - + ]
906 : : {
907 : 0 : val = 3;
908 : : }
909 : : /*else if ( el_number == el_number_N && !charge && !radical && val == 3 &&
910 : : chem_bonds_valence == 2 && bHasMetalNeighbor )
911 : : {
912 : : val = 2;
913 : : }
914 : : */
915 [ - + - - : 1780 : else if ( el_number == intl_el_number_S && !charge && !radical && val == 4 && chem_bonds_valence == 3 )
- - - - -
- ]
916 : : {
917 : 0 : val = 3;
918 : : }
919 [ - + - - : 1780 : else if ( bHasMetalNeighbor && el_number != intl_el_number_C && val > 0 )
- - ]
920 : : {
921 : 0 : val--;
922 : : }
923 : : /*
924 : : if ( (el_number == el_number_S || el_number == el_number_O) &&
925 : : abs(charge)==1 && !radical && val == 3 && chem_bonds_valence == 2 && bHasMetalNeighbor )
926 : : {
927 : : val = 2;
928 : : }
929 : : else
930 : : */
931 : :
932 : 1780 : num_H = inchi_max( 0, val - chem_bonds_valence );
933 : : }
934 : :
935 : 1780 : num_iso_H = 0;
936 [ + + ]: 1780 : if ( inp_num_iso_H )
937 : : {
938 [ + + ]: 2400 : for ( i = 0; i < NUM_H_ISOTOPES; i++ )
939 : : {
940 : 1800 : num_iso_H += inp_num_iso_H[i];
941 : : }
942 : : }
943 : :
944 : : /* should not happen because atom here is not aliased */
945 [ - + ]: 1780 : if ( num_iso_H )
946 : : {
947 [ # # ]: 0 : if ( num_H >= num_iso_H )
948 : : {
949 : 0 : num_H -= num_iso_H;
950 : : }
951 : : else
952 : : {
953 : 0 : num_H = inp_num_H; /* as requested in the alias */
954 : : /* num_H = (num_iso_H - num_H) % 2; */ /* keep unchanged parity of the total number of H atoms */
955 : : }
956 : : }
957 : :
958 : : /* should not happen because atom here is not aliased */
959 [ - + ]: 1780 : if ( inp_num_H > num_H )
960 : : {
961 : 0 : num_H = inp_num_H; /* as requested in the alias */
962 : : /* num_H = inp_num_H + (inp_num_H - num_H)%2; */ /* keep unchanged parity of the number of non-isotopic H atoms */
963 : : }
964 : : }
965 : : else
966 : : {
967 : 9 : num_H = inp_num_H;
968 : : }
969 : :
970 : 1801 : return num_H;
971 : : }
972 : :
973 : :
974 : : /****************************************************************************/
975 : 0 : int get_atomic_mass_from_elnum( int nAtNum )
976 : : {
977 : 0 : nAtNum -= 1;
978 : :
979 [ # # ]: 0 : if ( 0 < nAtNum )
980 : : {
981 : 0 : nAtNum += 2; /* bypass D, T */
982 : : }
983 : :
984 [ # # # # ]: 0 : if ( 0 <= nAtNum && nAtNum < nElDataLen )
985 : : {
986 : 0 : return (int) ElData[nAtNum].nAtMass;
987 : : }
988 : :
989 : 0 : return 0;
990 : : }
991 : :
992 : :
993 : : /****************************************************************************
994 : : int get_mw(char elname[])
995 : : {
996 : : int i;
997 : :
998 : : for (i=0; i<NUMEL; i++)
999 : : if (strcmp(elname,elements[i])==0)
1000 : : return(atomic_wt[i]);
1001 : : return(0);
1002 : : }
1003 : : ****************************************************************************/
1004 : :
1005 : :
1006 : :
1007 : : /****************************************************************************/
1008 : 0 : int get_atomic_mass( const char *elname )
1009 : : {
1010 : : int el_number, atw;
1011 [ # # ]: 0 : if (ERR_ELEM != ( el_number = el_number_in_internal_ref_table( elname ) ))
1012 : : {
1013 : 0 : atw = ElData[el_number].nAtMass;
1014 : : }
1015 : : else
1016 : : {
1017 : 0 : atw = 0;
1018 : : }
1019 : :
1020 : 0 : return atw;
1021 : : }
1022 : :
1023 : :
1024 : : /****************************************************************************
1025 : : Check if atom is in the list
1026 : : ****************************************************************************/
1027 : 2274 : AT_NUMB *is_in_the_list( AT_NUMB *pathAtom, AT_NUMB nNextAtom, int nPathLen )
1028 : : {
1029 [ + + + + ]: 4533 : for ( ; nPathLen && *pathAtom != nNextAtom; nPathLen--, pathAtom++ )
1030 : : {
1031 : : ;
1032 : : }
1033 [ + + ]: 2274 : return nPathLen ? pathAtom : NULL;
1034 : : }
1035 : :
1036 : : /****************************************************************************
1037 : : Check if integer is in the list
1038 : : ****************************************************************************/
1039 : 0 : int *is_in_the_ilist( int *pathAtom, int nNextAtom, int nPathLen )
1040 : : {
1041 [ # # # # ]: 0 : for ( ; nPathLen && *pathAtom != nNextAtom; nPathLen--, pathAtom++ )
1042 : : {
1043 : : ;
1044 : : }
1045 [ # # ]: 0 : return nPathLen ? pathAtom : NULL;
1046 : : }
1047 : :
1048 : :
1049 : : /****************************************************************************
1050 : : Check if list (of integers) is within the embedding list2
1051 : : ****************************************************************************/
1052 : 0 : int is_ilist_inside( int *ilist, int nlist, int *ilist2, int nlist2 )
1053 : : {
1054 : : int k;
1055 [ # # ]: 0 : for ( k = 0; k < nlist; k++ )
1056 : : {
1057 [ # # ]: 0 : if (!is_in_the_ilist( ilist2, ilist[k], nlist2 ))
1058 : : {
1059 : 0 : return 0;
1060 : : }
1061 : : }
1062 : 0 : return 1;
1063 : : }
1064 : :
1065 : :
1066 : : /****************************************************************************/
1067 : 0 : int nBondsValToMetal( inp_ATOM* at, int iat )
1068 : : {
1069 : 0 : int i, bond_type, nVal2Metal = 0; /* djb-rwth: removing redundant variables */
1070 : 0 : inp_ATOM* a = at + iat;
1071 : :
1072 [ # # ]: 0 : for ( i = 0; i < a->valence; i++ )
1073 : : {
1074 : : /* djb-rwth: removing redundant code */
1075 : :
1076 [ # # ]: 0 : if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
1077 : : {
1078 : 0 : bond_type = a->bond_type[i];
1079 : :
1080 [ # # ]: 0 : if ( bond_type <= BOND_TYPE_TRIPLE )
1081 : : {
1082 : 0 : nVal2Metal += bond_type;
1083 : : }
1084 : : else
1085 : : {
1086 : 0 : return -1; /* bond to metal order is not well defined */
1087 : : }
1088 : : }
1089 : : }
1090 : :
1091 : 0 : return nVal2Metal;
1092 : : }
1093 : :
1094 : :
1095 : : /****************************************************************************/
1096 : 4 : int num_of_H( inp_ATOM *at, int iat )
1097 : : {
1098 : : static int el_number_H = (int)EL_NUMBER_H;
1099 : 4 : int i, n, num_explicit_H = 0;
1100 : 4 : inp_ATOM *a = at + iat;
1101 : :
1102 [ + + ]: 20 : for (i = 0; i < a->valence; i++)
1103 : : {
1104 : 16 : n = a->neighbor[i];
1105 [ + - - + ]: 16 : num_explicit_H += ( 1 == at[n].valence && el_number_H == at[n].el_number );
1106 : : }
1107 : :
1108 : 4 : return num_explicit_H + NUMH( at, iat );
1109 : : }
1110 : :
1111 : : /****************************************************************************/
1112 : : /* Get the element group of an element. The base element rather than the */
1113 : : /* periodic group is used to aid readability. */
1114 : : /* - NitrogenGroup = 7 (EL_NUMBER_N) */
1115 : : /* - OxygenGroup = 8 (EL_NUMBER_O) */
1116 : : /* - Cargbon = 6 (EL_NUMBER_C) */
1117 : : /****************************************************************************/
1118 : 10 : U_CHAR ion_el_group( int el )
1119 : : {
1120 [ + - - + ]: 10 : switch ( el )
1121 : : {
1122 : 4 : case EL_NUMBER_C: /* fallthrough */
1123 : : #if ( FIX_REM_ION_PAIRS_Si_BUG == 1 )
1124 : : case EL_NUMBER_SI:
1125 : : #endif
1126 : 4 : return EL_NUMBER_C;
1127 : 0 : case EL_NUMBER_N: /* fallthrough */
1128 : : case EL_NUMBER_P:
1129 : : case EL_NUMBER_AS:
1130 : : case EL_NUMBER_SB:
1131 : 0 : return EL_NUMBER_N;
1132 : 0 : case EL_NUMBER_O: /* fallthrough */
1133 : : case EL_NUMBER_S:
1134 : : case EL_NUMBER_SE:
1135 : : case EL_NUMBER_TE:
1136 : 0 : return EL_NUMBER_O;
1137 : 6 : default:
1138 : 6 : return 0;
1139 : : }
1140 : : }
1141 : :
1142 : 0 : int has_other_ion_neigh( inp_ATOM *at,
1143 : : int iat,
1144 : : int iat_ion_neigh)
1145 : : {
1146 : 0 : int charge = at[iat_ion_neigh].charge;
1147 : : int i, neigh;
1148 : :
1149 [ # # ]: 0 : for ( i = 0; i < at[iat].valence; i++ )
1150 : : {
1151 : 0 : neigh = at[iat].neighbor[i];
1152 : :
1153 [ # # # # : 0 : if (neigh != iat_ion_neigh && at[neigh].charge == charge &&
# # ]
1154 : 0 : ion_el_group( at[neigh].el_number ))
1155 : : {
1156 : 0 : return 1;
1157 : : }
1158 : : }
1159 : :
1160 : 0 : return 0;
1161 : : }
1162 : :
1163 : :
1164 : : /****************************************************************************
1165 : : Check if has_other_ion_in_sphere_2
1166 : : BFS r=2
1167 : : ****************************************************************************/
1168 : 0 : int has_other_ion_in_sphere_2( inp_ATOM *at, int iat,
1169 : : int iat_ion_neigh )
1170 : : {
1171 : : #define MAXQ 16
1172 : : AT_NUMB q[MAXQ];
1173 : 0 : int lenq = 0, lenq2, dist = 0, i = 0, iq, neigh, j, nRet = 0;
1174 : 0 : q[lenq++] = iat;
1175 : 0 : at[iat].cFlags = 1;
1176 : :
1177 : 0 : iq = 0;
1178 : 0 : dist = 1;
1179 : : /* use at->cFlags as an indicator */
1180 : :
1181 [ # # ]: 0 : while ( dist <= 2 )
1182 : : {
1183 [ # # ]: 0 : for ( lenq2 = lenq; iq < lenq2; iq++ )
1184 : : {
1185 : 0 : i = q[iq];
1186 : :
1187 [ # # ]: 0 : for ( j = 0; j < at[i].valence; j++ )
1188 : : {
1189 : 0 : neigh = at[i].neighbor[j];
1190 : :
1191 [ # # ]: 0 : if (!at[neigh].cFlags &&
1192 [ # # # # ]: 0 : at[neigh].valence <= 3 &&
1193 : 0 : ion_el_group( at[neigh].el_number ))
1194 : : {
1195 : 0 : q[lenq++] = neigh;
1196 : 0 : at[neigh].cFlags = 1;
1197 [ # # ]: 0 : if (neigh != iat_ion_neigh &&
1198 [ # # ]: 0 : at[iat_ion_neigh].charge == at[neigh].charge)
1199 : : {
1200 : 0 : nRet++;
1201 : : }
1202 : : }
1203 : : }
1204 : : }
1205 : :
1206 : 0 : dist++;
1207 : : }
1208 : :
1209 [ # # ]: 0 : for ( iq = 0; iq < lenq; iq++ )
1210 : : {
1211 : 0 : i = q[iq];
1212 : 0 : at[i].cFlags = 0;
1213 : : }
1214 : :
1215 : 0 : return nRet;
1216 : : }
1217 : :
1218 : :
1219 : : /****************************************************************************/
1220 : 144 : int nNoMetalNumBonds( inp_ATOM *at, int at_no )
1221 : : {
1222 : : int i;
1223 : :
1224 : 144 : inp_ATOM *a = at + at_no;
1225 : 144 : int num_H = NUMH( a, 0 );
1226 : 144 : int std_chem_bonds_valence = get_el_valence( a->el_number, a->charge, 0 );
1227 : :
1228 [ + + ]: 144 : if ( a->chem_bonds_valence + num_H > std_chem_bonds_valence )
1229 : : {
1230 : 72 : int valence_to_metal = 0;
1231 : 72 : int num_bonds_to_metal = 0;
1232 : :
1233 [ + + ]: 280 : for ( i = 0; i < a->valence; i++ )
1234 : : {
1235 [ + + ]: 272 : if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
1236 : : {
1237 [ + - ]: 64 : if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
1238 : : {
1239 : 64 : return a->valence; /* fall back */
1240 : : }
1241 : 0 : num_bonds_to_metal++;
1242 : 0 : valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
1243 : : }
1244 : : }
1245 : :
1246 [ - + ]: 8 : if ( a->chem_bonds_valence + num_H - valence_to_metal == std_chem_bonds_valence )
1247 : : {
1248 : : /* removing bonds to metal produces standard valence */
1249 : 0 : return a->valence - num_bonds_to_metal;
1250 : : }
1251 : : }
1252 : :
1253 : : #if ( S_VI_O_PLUS_METAL_FIX_BOND == 1 )
1254 : : else
1255 : : {
1256 [ - + - - ]: 72 : if (1 == a->charge && 2 == get_endpoint_valence( a->el_number ) &&
1257 [ # # ]: 0 : a->chem_bonds_valence + num_H == std_chem_bonds_valence)
1258 : : {
1259 : 0 : int valence_to_metal = 0;
1260 : 0 : int num_bonds_to_metal = 0;
1261 [ # # ]: 0 : for ( i = 0; i < a->valence; i++ )
1262 : : {
1263 [ # # ]: 0 : if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
1264 : : {
1265 [ # # ]: 0 : if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
1266 : : {
1267 : 0 : return a->valence; /* fall back */
1268 : : }
1269 : 0 : num_bonds_to_metal++;
1270 : 0 : valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
1271 : : }
1272 : : }
1273 [ # # ]: 0 : if ( 1 == valence_to_metal )
1274 : : {
1275 : : /* removing bonds to metal produces standard valence */
1276 : 0 : return a->valence - num_bonds_to_metal;
1277 : : }
1278 : : }
1279 : : }
1280 : : #endif
1281 : :
1282 : 80 : return a->valence;
1283 : : }
1284 : :
1285 : :
1286 : : /****************************************************************************/
1287 : 4 : int nNoMetalBondsValence( inp_ATOM *at, int at_no )
1288 : : {
1289 : : int i;
1290 : :
1291 : 4 : inp_ATOM *a = at + at_no;
1292 : 4 : int num_H = NUMH( a, 0 );
1293 : 4 : int std_chem_bonds_valence = get_el_valence( a->el_number, a->charge, 0 );
1294 : :
1295 [ + - ]: 4 : if ( a->chem_bonds_valence + num_H > std_chem_bonds_valence )
1296 : : {
1297 : 4 : int valence_to_metal = 0;
1298 : : /*int num_bonds_to_metal = 0;*/
1299 : :
1300 [ + + ]: 20 : for ( i = 0; i < a->valence; i++ )
1301 : : {
1302 [ - + ]: 16 : if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
1303 : : {
1304 [ # # ]: 0 : if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
1305 : : {
1306 : 0 : return a->valence; /* fall back */
1307 : : }
1308 : : /* num_bonds_to_metal ++;*/
1309 : 0 : valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
1310 : : }
1311 : : }
1312 : :
1313 [ - + ]: 4 : if ( a->chem_bonds_valence + num_H - valence_to_metal == std_chem_bonds_valence )
1314 : : {
1315 : : /* removing bonds to metal produces standard valence */
1316 : 0 : return a->chem_bonds_valence - valence_to_metal;
1317 : : }
1318 : : }
1319 : :
1320 : : #if ( S_VI_O_PLUS_METAL_FIX_BOND == 1 )
1321 [ # # # # ]: 0 : else if (1 == a->charge && 2 == get_endpoint_valence( a->el_number ) &&
1322 [ # # ]: 0 : a->chem_bonds_valence + num_H == std_chem_bonds_valence)
1323 : : {
1324 : :
1325 : 0 : int valence_to_metal = 0;
1326 : : /* int num_bonds_to_metal = 0;*/
1327 : :
1328 [ # # ]: 0 : for ( i = 0; i < a->valence; i++ )
1329 : : {
1330 [ # # ]: 0 : if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
1331 : : {
1332 [ # # ]: 0 : if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
1333 : : {
1334 : 0 : return a->valence; /* fall back */
1335 : : }
1336 : : /* num_bonds_to_metal ++;*/
1337 : 0 : valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
1338 : : }
1339 : : }
1340 : :
1341 [ # # ]: 0 : if (1 == valence_to_metal)
1342 : : {/* removing bonds to metal produces standard valence */
1343 : 0 : return a->chem_bonds_valence - valence_to_metal;
1344 : : }
1345 : : }
1346 : : #endif
1347 : :
1348 : 4 : return a->chem_bonds_valence;
1349 : : }
1350 : :
1351 : :
1352 : : /****************************************************************************/
1353 : 0 : int nNoMetalNeighIndex( inp_ATOM *at, int at_no )
1354 : : {
1355 : : int i;
1356 : :
1357 : 0 : inp_ATOM* a = at + at_no;
1358 : :
1359 [ # # ]: 0 : for ( i = 0; i < a->valence; i++ )
1360 : : {
1361 [ # # ]: 0 : if (!is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
1362 : : {
1363 : 0 : return i;
1364 : : }
1365 : : }
1366 : :
1367 : 0 : return -1;
1368 : : }
1369 : :
1370 : :
1371 : : /****************************************************************************/
1372 : 0 : int nNoMetalOtherNeighIndex( inp_ATOM *at, int at_no, int cur_neigh )
1373 : : {
1374 : : int i, neigh;
1375 : :
1376 : 0 : inp_ATOM* a = at + at_no;
1377 : :
1378 [ # # ]: 0 : for ( i = 0; i < a->valence; i++ )
1379 : : {
1380 : 0 : neigh = (int) a->neighbor[i];
1381 : :
1382 [ # # # # ]: 0 : if (neigh != cur_neigh && !is_el_a_metal( at[neigh].el_number ))
1383 : : {
1384 : 0 : return i;
1385 : : }
1386 : : }
1387 : :
1388 : 0 : return -1;
1389 : : }
1390 : :
1391 : :
1392 : : /****************************************************************************/
1393 : 0 : int nNoMetalOtherNeighIndex2( inp_ATOM *at,
1394 : : int at_no,
1395 : : int cur_neigh,
1396 : : int cur_neigh2 )
1397 : : {
1398 : : int i, neigh;
1399 : :
1400 : 0 : inp_ATOM* a = at + at_no;
1401 : :
1402 [ # # ]: 0 : for ( i = 0; i < a->valence; i++ )
1403 : : {
1404 : 0 : neigh = (int) a->neighbor[i];
1405 : :
1406 [ # # # # : 0 : if (neigh != cur_neigh && neigh != cur_neigh2 && !is_el_a_metal( at[neigh].el_number ))
# # ]
1407 : : {
1408 : 0 : return i;
1409 : : }
1410 : : }
1411 : :
1412 : 0 : return -1;
1413 : : }
1414 : :
1415 : :
1416 : :
1417 : : #ifndef COMPILE_ANSI_ONLY
1418 : :
1419 : :
1420 : : /****************************************************************************/
1421 : : int MakeRemovedProtonsString( int nNumRemovedProtons,
1422 : : NUM_H *nNumExchgIsotopicH,
1423 : : NUM_H *nNumRemovedProtonsIsotopic,
1424 : : int bIsotopic,
1425 : : char *szRemovedProtons,
1426 : : int *num_removed_iso_H )
1427 : : {
1428 : : int i, j, len, num;
1429 : :
1430 : : len = 0;
1431 : :
1432 : : if ( nNumRemovedProtons )
1433 : : {
1434 : : len = sprintf(szRemovedProtons, "Proton balance: %c %d H+",
1435 : : nNumRemovedProtons >= 0 ? '+' : '-', abs(nNumRemovedProtons));
1436 : : }
1437 : :
1438 : : if (bIsotopic && ( nNumRemovedProtonsIsotopic || nNumExchgIsotopicH ))
1439 : : {
1440 : :
1441 : : for ( i = 0, j = 0; i < NUM_H_ISOTOPES; i++ )
1442 : : {
1443 : :
1444 : : num = ( nNumExchgIsotopicH ? nNumExchgIsotopicH[i] : 0 ) +
1445 : : ( nNumRemovedProtonsIsotopic ? nNumRemovedProtonsIsotopic[i] : 0 );
1446 : :
1447 : : if ( num )
1448 : : {
1449 : : len += sprintf(szRemovedProtons + len, "%s %d^%dH",
1450 : : j ? ", " : " [ removed ", num, i + 1);
1451 : : j++;
1452 : : }
1453 : : }
1454 : :
1455 : : if ( j )
1456 : : {
1457 : : len += sprintf(szRemovedProtons + len, " ]");
1458 : : if ( num_removed_iso_H )
1459 : : {
1460 : : *num_removed_iso_H = j;
1461 : : }
1462 : : }
1463 : : }
1464 : :
1465 : : if ( !len )
1466 : : {
1467 : : szRemovedProtons[0] = '\0';
1468 : : }
1469 : :
1470 : : return len;
1471 : : }
1472 : : #endif
1473 : :
1474 : :
1475 : : /****************************************************************************/
1476 : 3475 : int get_endpoint_valence( U_CHAR el_number )
1477 : : {
1478 [ + + + ]: 3475 : switch (el_number)
1479 : : {
1480 : 434 : case EL_NUMBER_O: /* fallthrough */
1481 : : case EL_NUMBER_S:
1482 : : case EL_NUMBER_SE:
1483 : : case EL_NUMBER_TE:
1484 : 434 : return 2;
1485 : 102 : case EL_NUMBER_N:
1486 : 102 : return 3;
1487 : 2939 : default:
1488 : 2939 : return 0;
1489 : : }
1490 : : }
1491 : :
1492 : :
1493 : : #if ( KETO_ENOL_TAUT == 1 ) /* post v.1 feature */
1494 : :
1495 : :
1496 : : /****************************************************************************/
1497 : 0 : int get_endpoint_valence_KET( U_CHAR el_number )
1498 : : {
1499 [ # # # ]: 0 : switch (el_number)
1500 : : {
1501 : 0 : case EL_NUMBER_C:
1502 : 0 : return 4;
1503 : 0 : case EL_NUMBER_O:
1504 : 0 : return 2;
1505 : 0 : default:
1506 : 0 : return 0;
1507 : : }
1508 : : }
1509 : : #endif
1510 : :
1511 : :
1512 : : /*
1513 : : MEMORY MANAGEMENT
1514 : : */
1515 : :
1516 : :
1517 : : #ifndef inchi_malloc
1518 : : /****************************************************************************/
1519 : : void *inchi_malloc( size_t c )
1520 : : {
1521 : : return malloc( c );
1522 : : }
1523 : : #endif
1524 : :
1525 : :
1526 : : #ifndef inchi_calloc
1527 : : /****************************************************************************/
1528 : : void *inchi_calloc( size_t c, size_t n )
1529 : : {
1530 : : return calloc( c, n );
1531 : : }
1532 : : #endif
1533 : :
1534 : :
1535 : : #ifndef inchi_free
1536 : : /****************************************************************************/
1537 : : void inchi_free( void *p )
1538 : : {
1539 : : if ( p )
1540 : : {
1541 : : inchi_free( p ); /*added check if zero*/
1542 : : }
1543 : : }
1544 : : #endif
1545 : :
1546 : :
1547 : : /*
1548 : : STRINGS AND TEXT HANDLING
1549 : : */
1550 : :
1551 : :
1552 : : /****************************************************************************
1553 : : Remove leading & trailing spaces, replace consecutive
1554 : : spaces with a single space.
1555 : : ****************************************************************************/
1556 : 0 : int normalize_string( char* name )
1557 : : {
1558 : : int i, len, n;
1559 : :
1560 : 0 : len = (int) strlen( name );
1561 : :
1562 [ # # ]: 0 : for ( i = 0, n = 0; i < len; i++ )
1563 : : {
1564 [ # # ]: 0 : if (isspace( UCINT name[i] ) /*|| !isprint( UCINT name[i] )*/)
1565 : : {
1566 : 0 : name[i] = ' '; /* exterminate tabs !!! */
1567 : 0 : n++;
1568 : : }
1569 : : else
1570 : : {
1571 [ # # ]: 0 : if ( n > 0 )
1572 : : {
1573 : 0 : memmove((void*)&name[i - n], (void*)&name[i], (long long)len - (long long)i + 1); /* djb-rwth: cast operators added */
1574 : 0 : i -= n;
1575 : 0 : len -= n;
1576 : : }
1577 : 0 : n = -1;
1578 : : }
1579 : : }
1580 [ # # ]: 0 : if ( n == len ) /* empty line */
1581 : : {
1582 : 0 : name[len = 0] = '\0';
1583 : : }
1584 [ # # # # ]: 0 : else if ( ++n && n <= len )
1585 : : {
1586 : 0 : len -= n;
1587 : 0 : name[len] = '\0';
1588 : : }
1589 : :
1590 : 0 : return len;
1591 : : }
1592 : :
1593 : :
1594 : : /****************************************************************************
1595 : : Replace non-ASCII characters with '.', return number of replacements
1596 : : ****************************************************************************/
1597 : 0 : int dotify_non_printable_chars( char *line )
1598 : : {
1599 : 0 : int i, c, num = 0;
1600 : :
1601 [ # # ]: 0 : if ( line )
1602 : : {
1603 [ # # ]: 0 : for ( i = 0; (c = UCINT line[i]); i++ ) /* djb-rwth: addressing LLVM warning */
1604 : : {
1605 : : /* assuming ASCII charset */
1606 [ # # # # ]: 0 : if ( c < ' ' || c >= 0x7F )
1607 : : {
1608 : 0 : line[i] = '.';
1609 : 0 : num++;
1610 : : }
1611 : : }
1612 : : }
1613 : :
1614 : 0 : return num;
1615 : : }
1616 : :
1617 : :
1618 : : /****************************************************************************
1619 : : Reads char sequence pointed to by *pstring ( char *p = *ppstring) for
1620 : : not more than maxlen bytes) to 'field' up to first occurrence of any of
1621 : : delimiters in 'delims' or end of line, whichever occurs first.
1622 : : Sets *pstring to point to character which matches delimiter.
1623 : : Returns number of bytes copied, -1 on error.
1624 : : ****************************************************************************/
1625 : 7340 : int read_upto_delim( char **pstring, char *field, int maxlen, char* delims )
1626 : : {
1627 : : int i, n;
1628 : 7340 : char* p = *pstring;
1629 : :
1630 [ + + ]: 7340 : if ( !p )
1631 : : {
1632 : 1 : return -1;
1633 : : }
1634 : :
1635 : : /* skip leading spaces */
1636 [ + - + + ]: 12722 : for (i = 0; p[i] && isspace( UCINT p[i] ); i++)
1637 : : {
1638 : : ;
1639 : : }
1640 : 7339 : p += i;
1641 : :
1642 : : /* read up to next delim or eol */
1643 : 7339 : n = 0;
1644 [ + + + + ]: 28373 : while (p[n] && !is_matching_any_delim( p[n], delims ))
1645 : : {
1646 : 21034 : n++;
1647 : : }
1648 : :
1649 [ - + ]: 7339 : if ( n + 1 > maxlen )
1650 : : {
1651 : 0 : return -1;
1652 : : }
1653 : :
1654 : 7339 : mystrncpy( field, p, n + 1 );
1655 : 7339 : field[n + 1] = '\0';
1656 : :
1657 [ + + ]: 7339 : if ( !p[n] )
1658 : : {
1659 : : /* reached EOL */
1660 : 1278 : *pstring = NULL;
1661 : : }
1662 : : else
1663 : : {
1664 : : /* advance reading pos */
1665 : 6061 : *pstring = *pstring + i + n;
1666 : : }
1667 : :
1668 : 7339 : return n;
1669 : : }
1670 : :
1671 : :
1672 : : /****************************************************************************
1673 : : Check if a character is in the list of possible delimiters
1674 : : NB: same as isspace if delims is " \t\n\v\f\r"
1675 : : (0x20 and 0x09-0x0D)
1676 : : ****************************************************************************/
1677 : 27095 : int is_matching_any_delim( char c, char* delims )
1678 : : {
1679 : 27095 : int ic = UCINT c;
1680 [ + + ]: 160149 : while ( *delims )
1681 : : {
1682 [ + + ]: 139115 : if ( ic == *delims )
1683 : : {
1684 : 6061 : return 1;
1685 : : }
1686 : 133054 : delims++;
1687 : : }
1688 : 21034 : return 0;
1689 : : }
1690 : :
1691 : :
1692 : : /****************************************************************************
1693 : : Remove trailing spaces
1694 : : ****************************************************************************/
1695 : 1640 : void remove_trailing_spaces( char* p )
1696 : : {
1697 : : int len;
1698 [ + - + + ]: 22252 : for (len = (int) strlen( p ) - 1; len >= 0 && isspace( UCINT p[len] ); len--)
1699 : : {
1700 : : ;
1701 : : }
1702 : 1640 : p[++len] = '\0';
1703 : 1640 : }
1704 : :
1705 : :
1706 : : /****************************************************************************/
1707 : 2022 : void remove_one_lf( char* p )
1708 : : {
1709 : : size_t len;
1710 [ + - + - : 2022 : if (p && 0 < ( len = strlen( p ) ) && p[len - 1] == '\n')
+ + ]
1711 : : {
1712 : 333 : p[len - 1] = '\0';
1713 [ + + - + ]: 333 : if ( len >= 2 && p[len - 2] == '\r' )
1714 : : {
1715 : 0 : p[len - 2] = '\0';
1716 : : }
1717 : : }
1718 : 2022 : }
1719 : :
1720 : :
1721 : : /****************************************************************************
1722 : : Copies up to maxlen characters INCLUDING end null from source to target
1723 : : Fills out the rest of the target with null bytes
1724 : :
1725 : : protected from non-zero-terminated source and overlapped target/source.
1726 : : ****************************************************************************/
1727 : 9608 : int mystrncpy( char *target, const char *source, unsigned maxlen )
1728 : : {
1729 : : const char *p;
1730 : : unsigned len, source_len;
1731 : :
1732 [ + - + - : 9608 : if ( target == NULL || maxlen == 0 || source == NULL )
- + ]
1733 : : {
1734 : 0 : return 0;
1735 : : }
1736 : :
1737 : : /* giallu: PR #163 */
1738 : : /* Find actual source length first to limit memchr search */
1739 : 9608 : source_len = (unsigned)strlen(source);
1740 : :
1741 [ + + ]: 9608 : if (source_len < maxlen)
1742 : : {
1743 : : /* Source is shorter than maxlen, use actual source length */
1744 : 3512 : len = source_len;
1745 : : }
1746 [ - + ]: 6096 : else if ((p = (const char*)memchr(source, 0, maxlen))) /* djb-rwth: addressing LLVM warning */
1747 : : {
1748 : : /* maxlen does not include the found zero termination */
1749 : 0 : len = (int) ( p - source );
1750 : : }
1751 : : else
1752 : : {
1753 : : /* reduced length does not include one more byte for zero termination */
1754 : 6096 : len = maxlen - 1;
1755 : : }
1756 : :
1757 [ + - ]: 9608 : if ( len )
1758 : : {
1759 : 9608 : memmove(target, source, len);
1760 : : }
1761 : :
1762 : 9608 : memset(target + len, 0, maxlen - len); /* zero termination */ /* djb-rwth: memset_s C11/Annex K variant? */
1763 : :
1764 : 9608 : return 1;
1765 : : }
1766 : :
1767 : :
1768 : : /****************************************************************************
1769 : : Remove leading and trailing white spaces
1770 : : ****************************************************************************/
1771 : 3570 : char* lrtrim( char *p, int* nLen )
1772 : : {
1773 : 3570 : int i, len = 0;
1774 : :
1775 [ + - + - ]: 3570 : if (p && ( len = (int) strlen( p ) ))
1776 : : {
1777 [ + - + - : 20202 : for (i = 0; i < len && is_ascii( p[i] ) && isspace( p[i] ); i++)
+ + ]
1778 : : {
1779 : : ;
1780 : : }
1781 [ + - ]: 3570 : if ( i )
1782 : : {
1783 : 3570 : len -= i; /* djb-rwth: variable has to be decreased before memmove */
1784 : 3570 : (memmove)(p, p + i, ((long long)len + 1)); /* djb-rwth: now cast operator can be added */
1785 : : }
1786 : :
1787 [ + - + - : 3570 : for (; 0 < len && is_ascii( p[len - 1] ) && isspace( p[len - 1] ); len--)
- + ]
1788 : : {
1789 : : ;
1790 : : }
1791 : 3570 : p[len] = '\0';
1792 : : }
1793 : :
1794 [ + - ]: 3570 : if ( nLen )
1795 : : {
1796 : 3570 : *nLen = len;
1797 : : }
1798 : :
1799 : 3570 : return p;
1800 : : }
1801 : :
1802 : :
1803 : : /****************************************************************************
1804 : : Extract InChI substring embedded into a longer string.
1805 : :
1806 : : InChI should start from "InChI=".
1807 : :
1808 : : As for the end of InChI,
1809 : : consider that according to
1810 : : http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:inchi/
1811 : : an InChI identifier may contain the following characters:
1812 : : A-Z
1813 : : a-z
1814 : : 0-9
1815 : : ()*+,-./;=?@
1816 : :
1817 : : Here we treat any character not conforming this specification as a whitespace
1818 : : which marks the end of the InChI string.
1819 : : For example:
1820 : : "InChI=1/Ar%"
1821 : : "InChI=1/Ar\n"
1822 : : "InChI=1/Ar\r\t"
1823 : : all will be trimmed to
1824 : : "InChI=1/Ar"
1825 : :
1826 : : ****************************************************************************/
1827 : 0 : void extract_inchi_substring( char ** buf, const char *str, size_t slen )
1828 : : {
1829 : : size_t i;
1830 : : const char *p;
1831 : : char* bufp;
1832 : : char pp;
1833 : :
1834 : 0 : bufp = *buf;
1835 : 0 : *buf = NULL;
1836 : :
1837 [ # # ]: 0 : if ( str == NULL )
1838 : : {
1839 : 0 : return;
1840 : : }
1841 [ # # ]: 0 : if (strlen( str ) < 1)
1842 : : {
1843 : 0 : return;
1844 : : }
1845 : :
1846 : 0 : p = strstr( str, "InChI=" );
1847 [ # # ]: 0 : if (NULL == p)
1848 : 0 : return;
1849 : :
1850 [ # # ]: 0 : for ( i = 0; i < slen; i++ )
1851 : : {
1852 : 0 : pp = p[i];
1853 : :
1854 [ # # # # ]: 0 : if (pp >= 'A' && pp <= 'Z') continue;
1855 [ # # # # ]: 0 : if (pp >= 'a' && pp <= 'z') continue;
1856 [ # # # # ]: 0 : if (pp >= '0' && pp <= '9') continue;
1857 [ # # ]: 0 : switch (pp)
1858 : : {
1859 : 0 : case '(':
1860 : : case ')':
1861 : : case '*':
1862 : : case '+':
1863 : : case ',':
1864 : : case '-':
1865 : : case '.':
1866 : : case '/':
1867 : : case ';':
1868 : : case '=':
1869 : : case '?':
1870 : 0 : case '@': continue;
1871 : :
1872 : 0 : default: break;
1873 : : }
1874 : :
1875 : 0 : break;
1876 : : }
1877 : :
1878 : 0 : *buf = (char*) inchi_calloc( i + 1, sizeof( char ) );
1879 : 0 : memcpy(*buf, p, i);
1880 [ # # ]: 0 : if ( *buf )
1881 : 0 : (*buf)[i] = '\0';
1882 : :
1883 : 0 : return;
1884 : : }
1885 : :
1886 : :
1887 : : /****************************************************************************/
1888 : 0 : void extract_auxinfo_substring( char ** buf, const char *str, size_t slen )
1889 : : {
1890 : : size_t i;
1891 : : const char *p;
1892 : : char* bufp;
1893 : : char pp;
1894 : :
1895 : 0 : bufp = *buf;
1896 : 0 : *buf = NULL;
1897 : :
1898 [ # # ]: 0 : if ( str == NULL )
1899 : : {
1900 : 0 : return;
1901 : : }
1902 [ # # ]: 0 : if (strlen( str ) < 1)
1903 : : {
1904 : 0 : return;
1905 : : }
1906 : :
1907 : 0 : p = strstr( str, "AuxInfo=" );
1908 [ # # ]: 0 : if (NULL == p)
1909 : : {
1910 : 0 : return;
1911 : : }
1912 : :
1913 [ # # ]: 0 : for ( i = 0; i < slen; i++ )
1914 : : {
1915 : 0 : pp = p[i];
1916 [ # # ]: 0 : if (isspace( UCINT pp )) break;
1917 : : }
1918 : :
1919 : 0 : *buf = (char*) inchi_calloc( i + 1, sizeof( char ) );
1920 : 0 : memcpy(*buf, p, i);
1921 [ # # ]: 0 : if ( *buf )
1922 : 0 : (*buf)[i] = '\0';
1923 : :
1924 : 0 : return;
1925 : : }
1926 : :
1927 : :
1928 : : /****************************************************************************
1929 : : For compatibility: local implementation of non-ANSI
1930 : : (MS-specific) functions, prefixed with "inchi_"
1931 : : ****************************************************************************/
1932 : :
1933 : :
1934 : : #define __MYTOLOWER(c) ( ((c) >= 'A') && ((c) <= 'Z') ? ((c) - 'A' + 'a') : (c) )
1935 : :
1936 : :
1937 : : /****************************************************************************/
1938 : 213 : int inchi_memicmp( const void * p1, const void * p2, size_t length )
1939 : : {
1940 : 213 : const U_CHAR *s1 = (const U_CHAR*) p1;
1941 : 213 : const U_CHAR *s2 = (const U_CHAR*) p2;
1942 [ + - ]: 637 : while (length--)
1943 : : {
1944 [ + + + + ]: 897 : if (*s1 == *s2 ||
1945 [ + + + + : 260 : __MYTOLOWER( (int) *s1 ) == __MYTOLOWER( (int) *s2 ))
+ + + - ]
1946 : : {
1947 : 424 : s1++;
1948 : 424 : s2++;
1949 : : }
1950 : : else
1951 : : {
1952 : : return
1953 [ + + + + : 213 : __MYTOLOWER( (int) *s1 ) - __MYTOLOWER( (int) *s2 );
+ + + - ]
1954 : : }
1955 : : }
1956 : :
1957 : 0 : return 0;
1958 : : }
1959 : :
1960 : :
1961 : : /****************************************************************************/
1962 : 784 : int inchi_stricmp( const char *s1, const char *s2 )
1963 : : {
1964 [ + + ]: 1985 : while ( *s1 )
1965 : : {
1966 [ + + - + ]: 2663 : if (*s1 == *s2 ||
1967 [ + - + + : 731 : __MYTOLOWER( (int) *s1 ) == __MYTOLOWER( (int) *s2 ))
+ - + - ]
1968 : : {
1969 : 1201 : s1++;
1970 : 1201 : s2++;
1971 : : }
1972 : : else
1973 : : {
1974 : : return
1975 [ + - + + : 731 : __MYTOLOWER( (int) *s1 ) - __MYTOLOWER( (int) *s2 );
+ - + - ]
1976 : : }
1977 : : }
1978 : :
1979 [ - + ]: 53 : if ( *s2 )
1980 : : {
1981 : 0 : return -1;
1982 : : }
1983 : :
1984 : 53 : return 0;
1985 : : }
1986 : :
1987 : :
1988 : : /****************************************************************************/
1989 : 0 : char *inchi__strnset( char *s, int val, size_t length )
1990 : : {
1991 : 0 : char* ps = s;
1992 [ # # # # ]: 0 : while ( length-- && *ps )
1993 : : {
1994 : 0 : *ps++ = (char) val;
1995 : : }
1996 : :
1997 : 0 : return s;
1998 : : }
1999 : :
2000 : :
2001 : : /****************************************************************************/
2002 : 54 : char *inchi__strdup( const char *string )
2003 : : {
2004 : 54 : char* p = NULL;
2005 [ - + ]: 54 : if ( string )
2006 : : {
2007 : 0 : size_t length = strlen( string );
2008 : 0 : p = (char *) inchi_malloc( length + 1 );
2009 [ # # ]: 0 : if (p)
2010 : : {
2011 : 0 : strcpy(p, string);
2012 : : }
2013 : : }
2014 : :
2015 : 54 : return p;
2016 : : }
2017 : :
2018 : :
2019 : : #undef __MYTOLOWER
|