rino 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/README +44 -0
  2. data/Rakefile +123 -0
  3. data/ext/extconf.rb +26 -0
  4. data/ext/ruby_inchi_main.so +0 -0
  5. data/ext/src/aux2atom.h +2786 -0
  6. data/ext/src/comdef.h +148 -0
  7. data/ext/src/e_0dstereo.c +3014 -0
  8. data/ext/src/e_0dstereo.h +31 -0
  9. data/ext/src/e_comdef.h +57 -0
  10. data/ext/src/e_ctl_data.h +147 -0
  11. data/ext/src/e_ichi_io.c +498 -0
  12. data/ext/src/e_ichi_io.h +40 -0
  13. data/ext/src/e_ichi_parms.c +37 -0
  14. data/ext/src/e_ichi_parms.h +41 -0
  15. data/ext/src/e_ichicomp.h +50 -0
  16. data/ext/src/e_ichierr.h +40 -0
  17. data/ext/src/e_ichimain.c +593 -0
  18. data/ext/src/e_ichisize.h +43 -0
  19. data/ext/src/e_inchi_atom.c +75 -0
  20. data/ext/src/e_inchi_atom.h +33 -0
  21. data/ext/src/e_inpdef.h +41 -0
  22. data/ext/src/e_mode.h +706 -0
  23. data/ext/src/e_mol2atom.c +649 -0
  24. data/ext/src/e_readinch.c +58 -0
  25. data/ext/src/e_readmol.c +54 -0
  26. data/ext/src/e_readmol.h +180 -0
  27. data/ext/src/e_readstru.c +251 -0
  28. data/ext/src/e_readstru.h +33 -0
  29. data/ext/src/e_util.c +284 -0
  30. data/ext/src/e_util.h +61 -0
  31. data/ext/src/extr_ct.h +251 -0
  32. data/ext/src/ichi.h +206 -0
  33. data/ext/src/ichi_bns.c +7999 -0
  34. data/ext/src/ichi_bns.h +231 -0
  35. data/ext/src/ichican2.c +5000 -0
  36. data/ext/src/ichicano.c +2195 -0
  37. data/ext/src/ichicano.h +49 -0
  38. data/ext/src/ichicans.c +1625 -0
  39. data/ext/src/ichicant.h +379 -0
  40. data/ext/src/ichicomn.h +260 -0
  41. data/ext/src/ichicomp.h +50 -0
  42. data/ext/src/ichidrp.h +119 -0
  43. data/ext/src/ichierr.h +124 -0
  44. data/ext/src/ichiisot.c +101 -0
  45. data/ext/src/ichilnct.c +286 -0
  46. data/ext/src/ichimain.h +132 -0
  47. data/ext/src/ichimak2.c +1189 -0
  48. data/ext/src/ichimake.c +3812 -0
  49. data/ext/src/ichimake.h +205 -0
  50. data/ext/src/ichimap1.c +851 -0
  51. data/ext/src/ichimap2.c +2856 -0
  52. data/ext/src/ichimap4.c +1609 -0
  53. data/ext/src/ichinorm.c +741 -0
  54. data/ext/src/ichinorm.h +67 -0
  55. data/ext/src/ichiparm.c +45 -0
  56. data/ext/src/ichiparm.h +1441 -0
  57. data/ext/src/ichiprt1.c +3612 -0
  58. data/ext/src/ichiprt2.c +1511 -0
  59. data/ext/src/ichiprt3.c +3011 -0
  60. data/ext/src/ichiqueu.c +1003 -0
  61. data/ext/src/ichiring.c +326 -0
  62. data/ext/src/ichiring.h +49 -0
  63. data/ext/src/ichisize.h +35 -0
  64. data/ext/src/ichisort.c +539 -0
  65. data/ext/src/ichister.c +3538 -0
  66. data/ext/src/ichister.h +35 -0
  67. data/ext/src/ichitaut.c +3843 -0
  68. data/ext/src/ichitaut.h +387 -0
  69. data/ext/src/ichitime.h +74 -0
  70. data/ext/src/inchi_api.h +670 -0
  71. data/ext/src/inchi_dll.c +1480 -0
  72. data/ext/src/inchi_dll.h +34 -0
  73. data/ext/src/inchi_dll_main.c +23 -0
  74. data/ext/src/inchi_dll_main.h +31 -0
  75. data/ext/src/inpdef.h +328 -0
  76. data/ext/src/lreadmol.h +1246 -0
  77. data/ext/src/mode.h +706 -0
  78. data/ext/src/ruby_inchi_main.c +558 -0
  79. data/ext/src/runichi.c +4179 -0
  80. data/ext/src/strutil.c +3861 -0
  81. data/ext/src/strutil.h +182 -0
  82. data/ext/src/util.c +1130 -0
  83. data/ext/src/util.h +85 -0
  84. data/lib/clean_tempfile.rb +220 -0
  85. data/lib/rino.rb +111 -0
  86. data/test/test.rb +386 -0
  87. metadata +130 -0
data/ext/src/util.c ADDED
@@ -0,0 +1,1130 @@
1
+ /*
2
+ * International Union of Pure and Applied Chemistry (IUPAC)
3
+ * International Chemical Identifier (InChI)
4
+ * Version 1
5
+ * Software version 1.00
6
+ * April 13, 2005
7
+ * Developed at NIST
8
+ */
9
+
10
+ #include <stdio.h>
11
+ #include <string.h>
12
+ #include <stdlib.h>
13
+ #include <ctype.h>
14
+
15
+ #include "mode.h"
16
+
17
+ #include "comdef.h"
18
+ #include "inpdef.h"
19
+ #include "util.h"
20
+ #include "extr_ct.h"
21
+
22
+
23
+ #include "ichicomp.h"
24
+
25
+ #define MIN_ATOM_CHARGE (-2)
26
+ #define MAX_ATOM_CHARGE 2
27
+ #define NEUTRAL_STATE (-MIN_ATOM_CHARGE)
28
+ #define NUM_ATOM_CHARGES (MAX_ATOM_CHARGE - MIN_ATOM_CHARGE + 1)
29
+ #define MAX_NUM_VALENCES 5 /* max. number + 1 to provide zero termination */
30
+
31
+ typedef struct tagElData {
32
+ const char *szElName;
33
+ int nAtMass; /* Avg. atomic mass from the Periodic Chart of the Elements (Fisher cat. no. 05-702-10) */
34
+ int nNormAtMass; /* Atomic mass of the most abundant isotope */
35
+ double dAtMass; /* exact mw of the most abundant isotope */
36
+ int nType; /* METAL or METAL2 */
37
+ int bDoNotAddH; /* InChI does not add imlicit H to atoms that have bDoNotAddH != 0 */
38
+ S_CHAR cValence[NUM_ATOM_CHARGES][MAX_NUM_VALENCES];
39
+ } ELDATA;
40
+
41
+ /* 2004=05-10: Added valences {1,3,5,7,} for As(2-) */
42
+
43
+ const ELDATA ElData[] = {
44
+ /* avg norm No -------- Valence(s) of an ion or neutral atom -------------*/
45
+ /* mw mass exact mw type H -2 -1 0 +1 +2 */
46
+ { "H", 1, 1, 1.007825035, 0 , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
47
+ { "D", 2, 2, 2.014101778, 0 , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
48
+ { "T", 3, 3, 3.016049268, 0 , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
49
+ { "He", 4, 4, 4.002600000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
50
+ { "Li", 7, 7, 7.016000000, METAL , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
51
+ { "Be", 9, 9, 9.012180000, METAL , 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
52
+ { "B", 11, 11, 11.009300000, 0 , 0, {{3,}, {4,}, {3,}, {2,}, {1,} }},
53
+ { "C", 12, 12, 12.000000000, 0 , 0, {{2,}, {3,}, {4,}, {3,}, {2,} }},
54
+ { "N", 14, 14, 14.003074000, 0 , 0, {{1,}, {2,}, {3,5}, {4,}, {3,} }},
55
+ { "O", 16, 16, 15.994914630, 0 , 0, {{0,}, {1,}, {2,}, {3,5,}, {4,} }},
56
+ { "F", 19, 19, 18.998403220, 0 , 0, {{0,}, {0,}, {1,}, {2,}, {3,5} }},
57
+ { "Ne", 20, 20, 19.992440000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
58
+ { "Na", 23, 23, 22.989770000, METAL , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
59
+ { "Mg", 24, 24, 23.985000000, METAL , 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
60
+ { "Al", 27, 27, 26.981540000, METAL , 0, {{3,5,}, {4,}, {3,}, {2,}, {1,} }},
61
+ { "Si", 28, 28, 27.976927100, 0 , 0, {{2,}, {3,5}, {4,}, {3,}, {2,} }},
62
+ { "P", 31, 31, 30.973762000, 0 , 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {4,}, {3,} }},
63
+ { "S", 32, 32, 31.972070700, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6}, {3,5,}, {4,} }},
64
+ { "Cl", 35, 35, 34.968852730, 0 , 0, {{0,}, {0,}, {1,3,5,7}, {2,4,6}, {3,5,} }},
65
+ { "Ar", 40, 40, 39.962400000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
66
+ { "K", 39, 39, 38.963700000, METAL , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
67
+ { "Ca", 40, 40, 39.962600000, METAL , 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
68
+ { "Sc", 45, 45, 44.955910000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
69
+ { "Ti", 48, 48, 47.947950000, METAL , 1, {{0,}, {0,}, {3,4}, {0,}, {0,} }},
70
+ { "V", 51, 51, 50.943960000, METAL , 1, {{0,}, {0,}, {2,3,4,5,}, {0,}, {0,} }},
71
+ { "Cr", 52, 52, 51.940500000, METAL , 1, {{0,}, {0,}, {2,3,6,}, {0,}, {0,} }},
72
+ { "Mn", 55, 55, 54.938050000, METAL2, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
73
+ { "Fe", 56, 56, 55.934900000, METAL2, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
74
+ { "Co", 59, 59, 58.933200000, METAL2, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
75
+ { "Ni", 59, 58, 57.935300000, METAL2, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
76
+ { "Cu", 64, 63, 62.929600000, METAL , 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }},
77
+ { "Zn", 65, 64, 63.929147000, METAL , 1, {{0,}, {0,}, {2,}, {0,}, {0,} }},
78
+ { "Ga", 70, 69, 68.925600000, METAL , 0, {{3,5,}, {4,}, {3,}, {0,}, {1,} }},
79
+ { "Ge", 73, 74, 73.921177400, 0 , 0, {{2,4,6,}, {3,5,}, {4,}, {3,}, {0,} }},
80
+ { "As", 75, 75, 74.921594200, 0 , 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {4,}, {3,} }},
81
+ { "Se", 79, 80, 79.916519600, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {4,} }},
82
+ { "Br", 80, 79, 78.918336100, 0 , 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6,}, {3,5,} }},
83
+ { "Kr", 84, 84, 83.911500000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
84
+ { "Rb", 85, 85, 84.911800000, METAL , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
85
+ { "Sr", 88, 88, 87.905600000, METAL , 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
86
+ { "Y", 89, 89, 88.905860000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
87
+ { "Zr", 91, 90, 89.904700000, METAL , 1, {{0,}, {0,}, {4,}, {0,}, {0,} }},
88
+ { "Nb", 93, 93, 92.906400000, METAL , 1, {{0,}, {0,}, {3,5,}, {0,}, {0,} }},
89
+ { "Mo", 96, 98, 97.905400000, METAL , 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
90
+ { "Tc", 98, 98, 97.907200000, METAL , 1, {{0,}, {0,}, {7,}, {0,}, {0,} }},
91
+ { "Ru", 101, 102, 101.904300000, METAL , 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
92
+ { "Rh", 103, 103, 102.905500000, METAL , 1, {{0,}, {0,}, {2,3,4,}, {0,}, {0,} }},
93
+ { "Pd", 106, 106, 105.903500000, METAL , 1, {{0,}, {0,}, {2,4,}, {0,}, {0,} }},
94
+ { "Ag", 108, 107, 106.905100000, METAL , 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
95
+ { "Cd", 112, 114, 113.903400000, METAL , 1, {{0,}, {0,}, {2,}, {0,}, {0,} }},
96
+ { "In", 115, 115, 114.903900000, METAL , 0, {{3,5,}, {2,4,}, {3,}, {0,}, {1,} }},
97
+ { "Sn", 119, 120, 119.902200000, METAL2, 0, {{2,4,6,}, {3,5}, {2,4,}, {3,}, {0,} }},
98
+ { "Sb", 122, 121, 120.903800000, METAL, 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, {3,} }},
99
+ { "Te", 128, 130, 129.906200000, 0 , 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,} }},
100
+ { "I", 127, 127, 126.904500000, 0 , 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6}, {3,5,} }},
101
+ { "Xe", 131, 132, 131.904100000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
102
+ { "Cs", 133, 133, 132.905430000, METAL , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
103
+ { "Ba", 137, 138, 137.905200000, METAL , 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
104
+ { "La", 139, 139, 138.906360000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
105
+ { "Ce", 140, 140, 139.905400000, METAL2, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
106
+ { "Pr", 141, 141, 140.907660000, METAL2, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
107
+ { "Nd", 144, 142, 141.907719000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
108
+ { "Pm", 145, 145, 144.912800000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
109
+ { "Sm", 150, 152, 151.919700000, METAL2, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
110
+ { "Eu", 152, 153, 152.921200000, METAL2, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
111
+ { "Gd", 157, 158, 157.924099000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
112
+ { "Tb", 159, 159, 158.925350000, METAL2, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
113
+ { "Dy", 163, 164, 163.929200000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }}, /* mw rounding uncertain */
114
+ { "Ho", 165, 165, 164.930300000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
115
+ { "Er", 167, 166, 165.930300000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
116
+ { "Tm", 169, 169, 168.934230000, METAL2, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
117
+ { "Yb", 173, 174, 173.938900000, METAL2, 1, {{0,}, {0,}, {2,3,}, {0,}, {0,} }},
118
+ { "Lu", 175, 175, 174.940800000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
119
+ { "Hf", 178, 180, 179.946600000, METAL , 1, {{0,}, {0,}, {4,}, {0,}, {0,} }},
120
+ { "Ta", 181, 181, 180.948010000, METAL , 1, {{0,}, {0,}, {5,}, {0,}, {0,} }},
121
+ { "W", 184, 184, 183.951000000, METAL2, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
122
+ { "Re", 186, 187, 186.955800000, METAL2, 1, {{0,}, {0,}, {2,4,6,7,}, {0,}, {0,} }},
123
+ { "Os", 190, 192, 191.961500000, METAL2, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
124
+ { "Ir", 192, 193, 192.962900000, METAL2, 1, {{0,}, {0,}, {2,3,4,6,}, {0,}, {0,} }},
125
+ { "Pt", 195, 195, 194.964800000, METAL2, 1, {{0,}, {0,}, {2,4,}, {0,}, {0,} }},
126
+ { "Au", 197, 197, 196.966560000, METAL , 1, {{0,}, {0,}, {1,3,}, {0,}, {0,} }},
127
+ { "Hg", 201, 202, 201.970617000, METAL2, 1, {{0,}, {0,}, {1,2,}, {0,}, {0,} }},
128
+ { "Tl", 204, 205, 204.974400000, METAL2, 0, {{3,5,}, {2,4,}, {1,3,}, {0,}, {0,} }},
129
+ { "Pb", 207, 208, 207.976627000, METAL2, 0, {{2,4,6,}, {3,5}, {2,4,}, {3,}, {0,} }},
130
+ { "Bi", 209, 209, 208.980390000, METAL , 0, {{1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,}, {3,} }},
131
+ { "Po", 209, 209, 208.982400000, METAL2, 0, {{0,}, {1,3,5,7,}, {2,4,6,}, {3,5,}, {2,4,} }},
132
+ { "At", 210, 210, 209.987100000, 0 , 0, {{0,}, {0,}, {1,3,5,7,}, {2,4,6}, {3,5,} }},
133
+ { "Rn", 222, 222, 222.017500000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
134
+ { "Fr", 223, 223, 223.019700000, METAL , 0, {{0,}, {0,}, {1,}, {0,}, {0,} }},
135
+ { "Ra", 226, 226, 226.025410000, METAL , 0, {{0,}, {0,}, {2,}, {1,}, {0,} }},
136
+ { "Ac", 227, 227, 227.027750000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
137
+ { "Th", 232, 232, 232.038050000, METAL2, 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
138
+ { "Pa", 231, 231, 231.035880000, METAL2, 1, {{0,}, {0,}, {3,4,5,}, {0,}, {0,} }},
139
+ { "U", 238, 238, 238.050790000, METAL2, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
140
+ { "Np", 237, 237, 237.048170000, METAL2, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
141
+ { "Pu", 244, 244, 244.064200000, METAL2, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
142
+ { "Am", 243, 243, 243.061370000, METAL2, 1, {{0,}, {0,}, {3,4,5,6,}, {0,}, {0,} }},
143
+ { "Cm", 247, 247, 247.070300000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
144
+ { "Bk", 247, 247, 247.070300000, METAL , 1, {{0,}, {0,}, {3,4,}, {0,}, {0,} }},
145
+ { "Cf", 251, 251, 251.079600000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
146
+ { "Es", 252, 252, 252.082800000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
147
+ { "Fm", 257, 257, 257.095100000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
148
+ { "Md", 258, 258, 258.098600000, METAL , 1, {{0,}, {0,}, {3,}, {0,}, {0,} }},
149
+ { "No", 259, 259, 259.100900000, METAL , 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
150
+ { "Lr", 260, 260, 260.105400000, METAL , 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
151
+ { "Rf", 261, 261, 261.108700000, METAL , 1, {{0,}, {0,}, {1,}, {0,}, {0,} }},
152
+ { "", 0, 0, 0.000000000, 0 , 0, {{0,}, {0,}, {0,}, {0,}, {0,} }},
153
+
154
+ };
155
+ /*
156
+ #ifdef __cplusplus
157
+ }
158
+ #endif
159
+ */
160
+
161
+ int ERR_ELEM = 255;
162
+ int nElDataLen = sizeof(ElData)/sizeof(ElData[0])-1;
163
+
164
+ /***********************************************************************************/
165
+ int GetElementFormulaFromAtNum(int nAtNum, char *szElement )
166
+ {
167
+ nAtNum -= 1;
168
+ if ( 0 < nAtNum )
169
+ nAtNum += 2; /* bypass D, T */
170
+ if ( 0 <= nAtNum && nAtNum < nElDataLen ) {
171
+ strcpy( szElement, ElData[nAtNum].szElName );
172
+ return 0;
173
+ }
174
+ strcpy( szElement, "??" );
175
+ return -1;
176
+ }
177
+ /***********************************************************************************/
178
+ int get_el_number( const char* elname )
179
+ {
180
+ int i;
181
+ const char *p;
182
+ for ( i = 0; (p=ElData[i].szElName)[0] && strcmp( p, elname ); i++ )
183
+ ;
184
+ return p[0]? i : ERR_ELEM;
185
+ }
186
+ /***********************************************************************************/
187
+ int get_periodic_table_number( const char* elname )
188
+ {
189
+ int num;
190
+ num = get_el_number( elname );
191
+ if ( num < ERR_ELEM )
192
+ num = inchi_max(1, num-1);
193
+ return num;
194
+ }
195
+ /***********************************************************************************/
196
+ int do_not_add_H( int nPeriodicNum )
197
+ {
198
+ return ElData[nPeriodicNum>1? nPeriodicNum+1:0].bDoNotAddH;
199
+ }
200
+ /***********************************************************************************/
201
+ int get_el_valence( int nPeriodicNum, int charge, int val_num )
202
+ {
203
+ if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE || val_num >= MAX_NUM_VALENCES )
204
+ return 0;
205
+ return ElData[nPeriodicNum>1? nPeriodicNum+1:0].cValence[NEUTRAL_STATE+charge][val_num];
206
+ }
207
+ /***********************************************************************************
208
+ * output valence needed to unumbiguosly reconstruct bonds
209
+ ***********************************************************************************/
210
+ int get_unusual_el_valence( int nPeriodicNum, int charge, int radical, int bonds_valence, int num_H, int num_bonds )
211
+ {
212
+ int i, num_found, chem_valence, rad_adj, known_chem_valence, exact_found;
213
+ if ( !num_bonds && !num_H )
214
+ return 0;
215
+ if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE ) {
216
+ if ( bonds_valence == num_bonds )
217
+ return 0; /* all single bonds */
218
+ return bonds_valence;
219
+ }
220
+ if ( !get_el_valence( nPeriodicNum, charge, 0 ) && bonds_valence == num_bonds )
221
+ return 0;
222
+
223
+ chem_valence = bonds_valence + num_H;
224
+ rad_adj = 0;
225
+ num_found = 0;
226
+ exact_found = 0;
227
+
228
+ /* take into account radical */
229
+ if (radical==RADICAL_DOUBLET)
230
+ rad_adj = 1;
231
+ else
232
+ if (radical==RADICAL_TRIPLET )
233
+ rad_adj = 2;
234
+
235
+ for ( i = 0; i < MAX_NUM_VALENCES; i ++ ) {
236
+ if ( 0 < (known_chem_valence = get_el_valence( nPeriodicNum, charge, i )-rad_adj) &&
237
+ num_bonds <= known_chem_valence && known_chem_valence <= chem_valence ) {
238
+ num_found ++;
239
+ if ( known_chem_valence == chem_valence ) {
240
+ exact_found = 1;
241
+ break;
242
+ }
243
+ }
244
+ }
245
+ return (exact_found && 1 == num_found)? 0 : chem_valence;
246
+ }
247
+ /***********************************************************************************
248
+ * output valence needed to unumbiguosly reconstruct number of H
249
+ ***********************************************************************************/
250
+ int needed_unusual_el_valence( int nPeriodicNum, int charge, int radical, int bonds_valence, int num_H, int num_bonds )
251
+ {
252
+ int i, num_found, num_found_known, chem_valence, rad_adj, known_chem_valence, exact_found;
253
+ /*
254
+ if ( !num_bonds && !num_H )
255
+ return 0;
256
+ */
257
+ chem_valence = bonds_valence + num_H;
258
+ if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE ||
259
+ !get_el_valence( nPeriodicNum, charge, 0 ) ||
260
+ do_not_add_H( nPeriodicNum ) ) {
261
+ if ( !num_H )
262
+ return 0; /* no H */
263
+ return chem_valence; /* needs to add H-atoms */
264
+ }
265
+
266
+ /* take into account radical */
267
+ if (radical==RADICAL_DOUBLET)
268
+ rad_adj = 1;
269
+ else
270
+ if (radical==RADICAL_TRIPLET )
271
+ rad_adj = 2;
272
+ else
273
+ rad_adj = 0;
274
+
275
+ num_found_known = 0;
276
+ num_found = 0;
277
+ exact_found = 0;
278
+
279
+ for ( i = 0; i < MAX_NUM_VALENCES; i ++ ) {
280
+ if ( 0 < (known_chem_valence = get_el_valence( nPeriodicNum, charge, i )) &&
281
+ bonds_valence <= (known_chem_valence -= rad_adj) ) {
282
+ /* found known valence that fits without H */
283
+ num_found_known ++;
284
+ if ( known_chem_valence <= chem_valence ) {
285
+ /* known valence is large enough to accommodate (implicit) H */
286
+ num_found ++;
287
+ }
288
+ if ( known_chem_valence == chem_valence ) {
289
+ exact_found = 1;
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ return (exact_found && 1 == num_found && 1 == num_found_known)? 0 : chem_valence? chem_valence : -1 /* needs zero */;
295
+ }
296
+ /***********************************************************************************
297
+ * output valence that does not fit any known valences
298
+ ***********************************************************************************/
299
+ int detect_unusual_el_valence( int nPeriodicNum, int charge, int radical, int bonds_valence, int num_H, int num_bonds )
300
+ {
301
+ int i, chem_valence, rad_adj, known_chem_valence;
302
+
303
+ if ( !num_bonds && !num_H )
304
+ return 0;
305
+
306
+ if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE ) {
307
+ if ( bonds_valence == num_bonds )
308
+ return 0; /* all single bonds */
309
+ return bonds_valence;
310
+ }
311
+ if ( !get_el_valence( nPeriodicNum, charge, 0 ) && bonds_valence == num_bonds )
312
+ return 0;
313
+
314
+ chem_valence = bonds_valence + num_H;
315
+ rad_adj = 0;
316
+
317
+ /* take into account radical */
318
+ if (radical==RADICAL_DOUBLET)
319
+ rad_adj = 1;
320
+ else
321
+ if (radical==RADICAL_TRIPLET || radical==RADICAL_SINGLET )
322
+ rad_adj = 2;
323
+
324
+ for ( i = 0; i < MAX_NUM_VALENCES; i ++ ) {
325
+ if ( 0 < (known_chem_valence = get_el_valence( nPeriodicNum, charge, i )-rad_adj) ) {
326
+ if ( known_chem_valence == chem_valence ) {
327
+ return 0;
328
+ }
329
+ }
330
+ }
331
+ return chem_valence;
332
+ }
333
+ /***********************************************************************************/
334
+ int get_el_type( int nPeriodicNum )
335
+ {
336
+ return ElData[nPeriodicNum+1].nType;
337
+ }
338
+ /***********************************************************************************/
339
+ int is_el_a_metal( int nPeriodicNum )
340
+ {
341
+ return 0!=(ElData[nPeriodicNum+1].nType & IS_METAL);
342
+ }
343
+ /******************************************************************************************************/
344
+ /*#ifndef INCHI_LIBRARY*/
345
+ int extract_ChargeRadical( char *elname, int *pnRadical, int *pnCharge )
346
+ {
347
+ char *q, *r, *p;
348
+ int nCharge=0, nRad = 0, charge_len = 0, k, nVal, nSign, nLastSign=1, len;
349
+
350
+ p = elname;
351
+
352
+ /* extract radicals & charges */
353
+ while ( q = strpbrk( p, "+-^" ) ) {
354
+ switch ( *q ) {
355
+ case '+':
356
+ case '-':
357
+ for ( k = 0, nVal=0; (nSign = ('+' == q[k])) || (nSign = -('-' == q[k])); k++ ) {
358
+ nVal += (nLastSign = nSign);
359
+ charge_len ++;
360
+ }
361
+ if ( nSign = (int)strtol( q+k, &r, 10 ) ) { /* fixed 12-5-2001 */
362
+ nVal += nLastSign * (nSign-1);
363
+ }
364
+ charge_len = r - q;
365
+ nCharge += nVal;
366
+ break;
367
+ /* case '.': */ /* singlet '.' may be confused with '.' in formulas like CaO.H2O */
368
+ case '^':
369
+ nRad = 1; /* doublet here is 1. See below */
370
+ charge_len = 1;
371
+ for ( k = 1; q[0] == q[k]; k++ ) {
372
+ nRad ++;
373
+ charge_len ++;
374
+ }
375
+ break;
376
+ }
377
+ memmove( q, q+charge_len, strlen(q+charge_len)+1 );
378
+ }
379
+ len = strlen(p);
380
+ /* radical */
381
+ if ( (q = strrchr( p, ':' )) && !q[1]) {
382
+ nRad = RADICAL_SINGLET;
383
+ q[0] = '\0';
384
+ len --;
385
+ } else {
386
+ while( (q = strrchr( p, '.' )) && !q[1] ) {
387
+ nRad ++;
388
+ q[0] = '\0';
389
+ len --;
390
+ }
391
+
392
+ nRad = nRad == 1? RADICAL_DOUBLET :
393
+ nRad == 2? RADICAL_TRIPLET : 0;
394
+ }
395
+ *pnRadical = nRad;
396
+ *pnCharge = nCharge;
397
+ return ( nRad || nCharge );
398
+
399
+ }
400
+ /*#endif*/
401
+ /****************************************************************/
402
+ int extract_H_atoms( char *elname, S_CHAR num_iso_H[] )
403
+ {
404
+ int i, len, c, k, num_H, val;
405
+ char *q;
406
+ i = 0;
407
+ num_H = 0;
408
+ len = (int)strlen(elname);
409
+ c = UCINT elname[0];
410
+ while ( i < len ) {
411
+ switch ( c ) {
412
+ case 'H':
413
+ k = 0;
414
+ break;
415
+ case 'D':
416
+ k = 1;
417
+ break;
418
+ case 'T':
419
+ k = 2;
420
+ break;
421
+ default:
422
+ k = -1;
423
+ break;
424
+ }
425
+ q = elname+i+1; /* pointer to the next to elname[i] character */
426
+ c = UCINT q[0];
427
+ if ( k >= 0 && !islower( c ) ) {
428
+ /* found a hydrogen */
429
+ if ( isdigit( c ) ) {
430
+ val = (int)strtol( q, &q, 10 );
431
+ /* q = pointer to the next to number of hydrogen atom(s) character */
432
+ } else {
433
+ val = 1;
434
+ }
435
+ if ( k ) {
436
+ num_iso_H[k] += val;
437
+ } else {
438
+ num_H += val;
439
+ }
440
+ /* remove the hydrogen atom from the string */
441
+ len -= (q-elname)-i;
442
+ memmove( elname+i, q, len + 1 );
443
+ /* c = UCINT elname[i]; */
444
+ } else {
445
+ i ++;
446
+ }
447
+ c = UCINT elname[i]; /* moved here 11-04-2002 */
448
+ }
449
+ return num_H;
450
+ }
451
+ /***********************************************************************************/
452
+ int get_num_H (const char* elname, int inp_num_H, S_CHAR inp_num_iso_H[],
453
+ int charge, int radical, int chem_bonds_valence, int atom_input_valence,
454
+ int bAliased, int bDoNotAddH, int bHasMetalNeighbor )
455
+ {
456
+ int val, i, el_number, num_H = 0, num_iso_H;
457
+ static int el_number_N = 0, el_number_S, el_number_O, el_number_C;
458
+ if ( !el_number_N ) {
459
+ el_number_N = get_el_number( "N" );
460
+ el_number_S = get_el_number( "S" );
461
+ el_number_O = get_el_number( "O" );
462
+ el_number_C = get_el_number( "C" );
463
+ }
464
+ /* atom_input_valence (cValence) cannot be specified in case of */
465
+ /* aliased MOLFile atom with known inp_num_H or inp_num_iso_H[] */
466
+ if ( bAliased ) {
467
+ num_H = inp_num_H;
468
+ } else
469
+ if ( atom_input_valence && (atom_input_valence !=15 || chem_bonds_valence) ) {
470
+ num_H = inchi_max( 0, atom_input_valence - chem_bonds_valence );
471
+ } else
472
+ if ( atom_input_valence == 15 && !chem_bonds_valence ) {
473
+ num_H = 0;
474
+ } else
475
+ if ( MIN_ATOM_CHARGE <= charge &&
476
+ MAX_ATOM_CHARGE >= charge &&
477
+ ERR_ELEM != (el_number = get_el_number( elname ) ) &&
478
+ !ElData[el_number].bDoNotAddH && !bDoNotAddH ) {
479
+ /* add hydrogen atoms according to standard element valence */
480
+ if ( radical && radical != RADICAL_SINGLET ) {
481
+ if ( val = ElData[el_number].cValence[NEUTRAL_STATE+charge][0] ) {
482
+ val -= (radical==RADICAL_DOUBLET)? 1 :
483
+ (radical==RADICAL_SINGLET || radical==RADICAL_TRIPLET )? 2 : val;
484
+ /* if unknown radical then do not add H */
485
+ num_H = inchi_max( 0, val - chem_bonds_valence );
486
+ }
487
+ } else {
488
+ /* find the smallest valence that is greater than the sum of the chemical bond valences */
489
+ for ( i = 0;
490
+ (val=ElData[el_number].cValence[NEUTRAL_STATE+charge][i]) &&
491
+ val < chem_bonds_valence;
492
+ i++ )
493
+ ;
494
+ /* special case: do not add H to N(IV), S(III), S+(II), S-(II) */ /* S ions added 2004-05-10 */
495
+ if ( el_number == el_number_N && !charge && !radical && val == 5 )
496
+ val = 3;
497
+ else
498
+ /*
499
+ if ( el_number == el_number_N && !charge && !radical && val == 3 &&
500
+ chem_bonds_valence == 2 && bHasMetalNeighbor )
501
+ val = 2;
502
+ else
503
+ */
504
+ if ( el_number == el_number_S && !charge && !radical && val == 4 && chem_bonds_valence == 3 )
505
+ val = 3;
506
+ else
507
+ if ( bHasMetalNeighbor && el_number != el_number_C && val > 0 ) {
508
+ val --;
509
+ }
510
+ /*
511
+ if ( (el_number == el_number_S || el_number == el_number_O) &&
512
+ abs(charge)==1 && !radical && val == 3 && chem_bonds_valence == 2 && bHasMetalNeighbor )
513
+ val = 2;
514
+ else
515
+ */
516
+ num_H = inchi_max( 0, val - chem_bonds_valence );
517
+ }
518
+ for ( i = 0, num_iso_H = 0; i < NUM_H_ISOTOPES; i ++ ) {
519
+ num_iso_H += inp_num_iso_H[i];
520
+ }
521
+ /* should not happen because atom here is not aliased */
522
+ if ( num_iso_H ) {
523
+ if ( num_H >= num_iso_H ) {
524
+ num_H -= num_iso_H;
525
+ } else {
526
+ num_H = inp_num_H; /* as requested in the alias */
527
+ /* num_H = (num_iso_H - num_H) % 2; */ /* keep unchanged parity of the total number of H atoms */
528
+ }
529
+ }
530
+ /* should not happen because atom here is not aliased */
531
+ if ( inp_num_H > num_H ) {
532
+ num_H = inp_num_H; /* as requested in the alias */
533
+ /* num_H = inp_num_H + (inp_num_H - num_H)%2; */ /* keep unchanged parity of the number of non-isotopic H atoms */
534
+ }
535
+ } else {
536
+ num_H = inp_num_H;
537
+ }
538
+ return num_H;
539
+ }
540
+ /***********************************************************************************/
541
+ int get_atw_from_elnum( int nAtNum )
542
+ {
543
+ nAtNum -= 1;
544
+ if ( 0 < nAtNum )
545
+ nAtNum += 2; /* bypass D, T */
546
+ if ( 0 <= nAtNum && nAtNum < nElDataLen ) {
547
+ return (int)ElData[nAtNum].nAtMass;
548
+ }
549
+ return 0;
550
+ }
551
+ /***********************************************************************************/
552
+ /*
553
+ int get_mw(char elname[])
554
+ {
555
+ int i;
556
+
557
+ for (i=0; i<NUMEL; i++)
558
+ if (strcmp(elname,elements[i])==0)
559
+ return(atomic_wt[i]);
560
+ return(0);
561
+ }
562
+ */
563
+ /***********************************************************************************/
564
+ #ifndef INCHI_LIBRARY
565
+ /***********************************************************************************/
566
+ int get_atw(const char *elname)
567
+ {
568
+ int el_number, atw;
569
+ if ( ERR_ELEM != (el_number = get_el_number( elname )) ) {
570
+ atw = ElData[el_number].nAtMass;
571
+ } else {
572
+ atw = 0;
573
+ }
574
+ return atw;
575
+ }
576
+ /***********************************************************************************/
577
+ int normalize_name( char* name )
578
+ {
579
+ /* remove leading & trailing spaces; replace consecutive spaces with a single space */
580
+ /* Treat non-printable characters (Greeks) as spaces. 11-23-99 DCh. */
581
+ int i, len, n;
582
+ len = (int)strlen(name);
583
+ for ( i = 0, n = 0; i < len; i++ ) {
584
+ if ( isspace( UCINT name[i] ) /*|| !isprint( UCINT name[i] )*/ ) {
585
+ name[i] = ' '; /* exterminate tabs !!! */
586
+ n++;
587
+ } else {
588
+ if ( n > 0 ) {
589
+ memmove( (void*) &name[i-n], (void*) &name[i], len-i+1 );
590
+ i -= n;
591
+ len -= n;
592
+ }
593
+ n = -1;
594
+ }
595
+ }
596
+ if ( n == len ) /* empty line */
597
+ name[len=0] = '\0';
598
+ else
599
+ if ( ++n && n <= len ) {
600
+ len -= n;
601
+ name[len] = '\0';
602
+ }
603
+ return len;
604
+ }
605
+ #endif /* ifndef INCHI_LIBRARY */
606
+ /************************************************/
607
+ #ifndef inchi_malloc
608
+ void *inchi_malloc(size_t c)
609
+ {
610
+ return malloc(c);
611
+ }
612
+ #endif
613
+ #ifndef inchi_calloc
614
+ void *inchi_calloc(size_t c, size_t n)
615
+ {
616
+ return calloc(c,n);
617
+ }
618
+ #endif
619
+ #ifndef inchi_free
620
+ void inchi_free(void *p)
621
+ {
622
+ if(p) {
623
+ free(p); /*added check if zero*/
624
+ }
625
+ }
626
+ #endif
627
+
628
+ #ifndef INCHI_LIBRARY
629
+ /*******************************************************************/
630
+ char *fgetsTab( char *szLine, int len, FILE *f );
631
+ /*******************************************************************/
632
+ /* read up to len or tab or LF; if empty read next until finds non-empty line */
633
+ /* remove leading and trailing white spaces; keep zero termination */
634
+ /*******************************************************************/
635
+ char *fgetsTab( char *szLine, int len, FILE *f )
636
+ {
637
+ int length=0, c;
638
+ len --;
639
+ while ( length < len && EOF != (c = fgetc( f )) ) {
640
+ if ( c == '\t' )
641
+ c = '\n';
642
+ szLine[length++] = (char)c;
643
+ if ( c == '\n' )
644
+ break;
645
+ }
646
+ if ( !length && EOF == c ) {
647
+ return NULL;
648
+ }
649
+ szLine[length] = '\0';
650
+ return szLine;
651
+ }
652
+ /*******************************************************************/
653
+ /* read up to len or tab or LF; if empty read next until finds non-empty line */
654
+ /* remove leading and trailing white spaces; keep zero termination */
655
+ /*******************************************************************/
656
+ int my_fgetsTab( char *szLine, int len, FILE *f, int *bTooLongLine )
657
+ {
658
+ int length;
659
+ char *p;
660
+ do {
661
+ p = fgetsTab( szLine, len-1, f );
662
+ if ( !p ) {
663
+ *bTooLongLine = 0;
664
+ return -1; /* end of file or cannot read */
665
+ }
666
+ szLine[len-1] = '\0';
667
+ /*
668
+ *bTooLongLine = !strchr( szLine, '\n' );
669
+ */
670
+ p = strchr( szLine, '\n' );
671
+ *bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
672
+ LtrimRtrim( szLine, &length );
673
+ } while ( !length );
674
+ return length;
675
+ }
676
+ /*******************************************************************/
677
+ int my_fgetsTab1( char *szLine, int len, FILE *f, int *bTooLongLine )
678
+ {
679
+ int length;
680
+ char *p;
681
+ /*do {*/
682
+ p = fgetsTab( szLine, len-1, f );
683
+ if ( !p ) {
684
+ *bTooLongLine = 0;
685
+ return -1; /* end of file or cannot read */
686
+ }
687
+ szLine[len-1] = '\0';
688
+ /*
689
+ *bTooLongLine = !strchr( szLine, '\n' );
690
+ */
691
+ p = strchr( szLine, '\n' );
692
+ *bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
693
+ LtrimRtrim( szLine, &length );
694
+ /*} while ( !length );*/
695
+ return length;
696
+ }
697
+ #endif
698
+
699
+ #ifndef INCHI_LIBRARY
700
+ /*******************************************************************/
701
+ /* read up to len; if empty read next until found non-empty line */
702
+ /* remove leading and trailing white spaces; keep zero termination */
703
+ /*******************************************************************/
704
+ int my_fgets( char *szLine, int len, FILE *f, int *bTooLongLine )
705
+ {
706
+ int length;
707
+ char *p;
708
+ do {
709
+ p = fgets( szLine, len-1, f );
710
+ if ( !p ) {
711
+ *bTooLongLine = 0;
712
+ return -1; /* end of file or cannot read */
713
+ }
714
+ szLine[len-1] = '\0';
715
+ p = strchr( szLine, '\n' );
716
+ *bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
717
+ LtrimRtrim( szLine, &length );
718
+ } while ( !length );
719
+ return length;
720
+ }
721
+ /********************************************************************/
722
+ int my_fgetsUpToLfOrTab( char *szLine, int len, FILE *f )
723
+ {
724
+ int length;
725
+ char *p;
726
+ char szSkip[256];
727
+ int bTooLongLine = 0;
728
+ do {
729
+ p = fgetsTab( szLine, len-1, f );
730
+ if ( !p ) {
731
+ return -1; /* end of file or cannot read */
732
+ }
733
+ szLine[len-1] = '\0';
734
+ /*
735
+ bTooLongLine = !strchr( szLine, '\n' );
736
+ */
737
+ bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
738
+ LtrimRtrim( szLine, &length );
739
+ } while ( !length );
740
+ if ( bTooLongLine ) {
741
+ while ( p = fgetsTab( szSkip, sizeof(szSkip)-1, f ) ) {
742
+ szSkip[sizeof(szSkip)-1] = '\0';
743
+ if ( strchr( szSkip, '\n' ) )
744
+ break;
745
+ }
746
+ }
747
+ return length;
748
+ }
749
+ /******************************************************************/
750
+ /* read not more than line_len bytes from an lf-terminated line */
751
+ /* if input line is too long quietly ignore the rest of the line */
752
+ char* fgets_up_to_lf( char* line, int line_len, FILE* inp )
753
+ {
754
+ char *p, *q;
755
+ memset( line, 0, line_len );
756
+ if ( NULL != (p = fgets( line, line_len, inp ) ) && NULL == strchr(p, '\n' ) ){
757
+ char temp[64]; /* bypass up to '\n' or up to end of file whichever comes first*/
758
+ while ( NULL != fgets( temp, sizeof(temp), inp ) && NULL == strchr(temp,'\n') )
759
+ ;
760
+ }
761
+ if ( p && (q = strchr(line, '\r')) ) { /* fix CR CR LF line terminator. */
762
+ q[0] = '\n';
763
+ q[1] = '\0';
764
+ }
765
+ return p;
766
+ }
767
+ /*************************************************************************/
768
+ void remove_trailing_spaces( char* p )
769
+ {
770
+ int len;
771
+ for( len = (int)strlen( p ) - 1; len >= 0 && isspace( UCINT p[len] ); len-- )
772
+ ;
773
+ p[++len] = '\0';
774
+ }
775
+ /*************************************************************************/
776
+ void remove_one_lf( char* p)
777
+ {
778
+ size_t len;
779
+ if ( p && 0 < (len = strlen(p)) && p[len-1] == '\n' ){
780
+ p[len-1] = '\0';
781
+ if ( len >= 2 && p[len-2] == '\r' )
782
+ p[len-2] = '\0';
783
+ }
784
+ }
785
+ #endif /* ifndef INCHI_LIBRARY */
786
+ /***************************************************************************/
787
+ /* Copies up to maxlen characters INCLUDING end null from source to target */
788
+ /* Fills out the rest of the target with null bytes */
789
+ int mystrncpy(char *target,const char *source,unsigned maxlen)
790
+ { /* protected from non-zero-terminated source and overlapped target/source. 7-9-99 DCh. */
791
+ const char *p;
792
+ unsigned len;
793
+
794
+ if (target==NULL || maxlen == 0 || source == NULL)
795
+ return 0;
796
+ if ( p = (const char*)memchr(source, 0, maxlen) ) {
797
+ len = p-source; /* maxlen does not include the found zero termination */
798
+ } else {
799
+ len = maxlen-1; /* reduced length does not include one more byte for zero termination */
800
+ }
801
+ if ( len )
802
+ memmove( target, source, len );
803
+ /* target[len] = '\0'; */
804
+ memset( target+len, 0, maxlen-len); /* zero termination */
805
+ return 1;
806
+ }
807
+ /************************************************************************/
808
+ /* Remove leading and trailing white spaces */
809
+ char* LtrimRtrim( char *p, int* nLen )
810
+ {
811
+ int i, len=0;
812
+ if ( p && (len = strlen( p )) ) {
813
+ for ( i = 0; i < len && __isascii( p[i] ) && isspace( p[i] ); i++ )
814
+ ;
815
+ if ( i )
816
+ (memmove)( p, p+i, (len -= i)+1 );
817
+ for ( ; 0 < len && __isascii( p[len-1] ) && isspace( p[len-1] ); len-- )
818
+ ;
819
+ p[len] = '\0';
820
+ }
821
+ if ( nLen )
822
+ *nLen = len;
823
+ return p;
824
+ }
825
+ /*************************************************************************/
826
+ AT_NUMB *is_in_the_list( AT_NUMB *pathAtom, AT_NUMB nNextAtom, int nPathLen )
827
+ {
828
+ for ( ; nPathLen && *pathAtom != nNextAtom; nPathLen--, pathAtom++ )
829
+ ;
830
+ return nPathLen? pathAtom : NULL;
831
+ }
832
+ /************************************************************************/
833
+ int num_of_H( inp_ATOM *at, int iat )
834
+ {
835
+ static int el_number_H;
836
+ int i, n, num_explicit_H = 0;
837
+ inp_ATOM *a = at + iat;
838
+ if ( !el_number_H )
839
+ el_number_H = get_periodic_table_number( "H" );
840
+ for ( i = 0; i < a->valence; i ++ ) {
841
+ n = a->neighbor[i];
842
+ num_explicit_H += ( 1 == at[n].valence && el_number_H == at[n].el_number );
843
+ }
844
+ return num_explicit_H+NUMH(at,iat);
845
+ }
846
+ /************************************************************************/
847
+ int has_other_ion_neigh( inp_ATOM *at, int iat, int iat_ion_neigh, const char *el, int el_len )
848
+ {
849
+ int charge = at[iat_ion_neigh].charge;
850
+ int i, neigh;
851
+ for ( i = 0; i < at[iat].valence; i ++ ) {
852
+ neigh = at[iat].neighbor[i];
853
+ if ( neigh != iat_ion_neigh && at[neigh].charge == charge &&
854
+ NULL != memchr( el, at[neigh].el_number, el_len ) ) {
855
+ return 1;
856
+ }
857
+ }
858
+ return 0;
859
+ }
860
+ /************************************************************************/
861
+ /* BFS r=2 */
862
+ int has_other_ion_in_sphere_2(inp_ATOM *at, int iat, int iat_ion_neigh, const char *el, int el_len )
863
+ {
864
+ #define MAXQ 16
865
+ AT_NUMB q[MAXQ];
866
+ int lenq=0, lenq2, dist = 0, i = 0, iq, neigh, j, nRet=0;
867
+ q[lenq++] = iat;
868
+ at[iat].cFlags = 1;
869
+
870
+ iq = 0;
871
+ dist = 1;
872
+ /* use at->cFlags as an indicator */
873
+ while ( dist <= 2 ) {
874
+ for ( lenq2 = lenq; iq < lenq2; iq ++ ) {
875
+ i = q[iq];
876
+ for ( j = 0; j < at[i].valence; j ++ ) {
877
+ neigh = at[i].neighbor[j];
878
+ if ( !at[neigh].cFlags &&
879
+ at[neigh].valence <= 3 &&
880
+ NULL != memchr( el, at[neigh].el_number, el_len ) ) {
881
+ q[lenq ++] = neigh;
882
+ at[neigh].cFlags = 1;
883
+ if ( neigh != iat_ion_neigh &&
884
+ at[iat_ion_neigh].charge == at[neigh].charge ) {
885
+ nRet ++;
886
+ }
887
+ }
888
+ }
889
+ }
890
+ dist ++;
891
+ }
892
+ for ( iq = 0; iq < lenq; iq ++ ) {
893
+ i = q[iq];
894
+ at[i].cFlags = 0;
895
+ }
896
+ return nRet;
897
+ }
898
+ /************************************************************************/
899
+ int nNoMetalNumBonds( inp_ATOM *at, int at_no )
900
+ {
901
+ inp_ATOM *a = at + at_no;
902
+ int num_H = NUMH(a, 0);
903
+ int std_chem_bonds_valence = get_el_valence( a->el_number, a->charge, 0 );
904
+ int i;
905
+ if ( a->chem_bonds_valence + num_H > std_chem_bonds_valence ) {
906
+ int valence_to_metal = 0;
907
+ int num_bonds_to_metal = 0;
908
+ for ( i = 0; i < a->valence; i ++ ) {
909
+ if ( is_el_a_metal( at[(int)a->neighbor[i]].el_number ) ) {
910
+ if ( (a->bond_type[i] & BOND_TYPE_MASK) >= BOND_TYPE_ALTERN ) {
911
+ return a->valence; /* fall back */
912
+ }
913
+ num_bonds_to_metal ++;
914
+ valence_to_metal += (a->bond_type[i] & BOND_TYPE_MASK);
915
+ }
916
+ }
917
+ if ( a->chem_bonds_valence + num_H - valence_to_metal == std_chem_bonds_valence ) {
918
+ /* removing bonds to metal produces standard valence */
919
+ return a->valence - num_bonds_to_metal;
920
+ }
921
+ }
922
+ #if( S_VI_O_PLUS_METAL_FIX_BOND == 1 )
923
+ else
924
+ if ( 1 == a->charge && 2 == get_endpoint_valence(a->el_number) &&
925
+ a->chem_bonds_valence + num_H == std_chem_bonds_valence ) {
926
+ int valence_to_metal = 0;
927
+ int num_bonds_to_metal = 0;
928
+ for ( i = 0; i < a->valence; i ++ ) {
929
+ if ( is_el_a_metal( at[(int)a->neighbor[i]].el_number ) ) {
930
+ if ( (a->bond_type[i] & BOND_TYPE_MASK) >= BOND_TYPE_ALTERN ) {
931
+ return a->valence; /* fall back */
932
+ }
933
+ num_bonds_to_metal ++;
934
+ valence_to_metal += (a->bond_type[i] & BOND_TYPE_MASK);
935
+ }
936
+ }
937
+ if ( 1 == valence_to_metal ) {
938
+ /* removing bonds to metal produces standard valence */
939
+ return a->valence - num_bonds_to_metal;
940
+ }
941
+ }
942
+ #endif
943
+
944
+ return a->valence;
945
+ }
946
+ /************************************************************************/
947
+ int nNoMetalBondsValence( inp_ATOM *at, int at_no )
948
+ {
949
+ inp_ATOM *a = at + at_no;
950
+ int num_H = NUMH(a, 0);
951
+ int std_chem_bonds_valence = get_el_valence( a->el_number, a->charge, 0 );
952
+ int i;
953
+ if ( a->chem_bonds_valence + num_H > std_chem_bonds_valence ) {
954
+ int valence_to_metal = 0;
955
+ /*int num_bonds_to_metal = 0;*/
956
+ for ( i = 0; i < a->valence; i ++ ) {
957
+ if ( is_el_a_metal( at[(int)a->neighbor[i]].el_number ) ) {
958
+ if ( (a->bond_type[i] & BOND_TYPE_MASK) >= BOND_TYPE_ALTERN ) {
959
+ return a->valence; /* fall back */
960
+ }
961
+ /*num_bonds_to_metal ++;*/
962
+ valence_to_metal += (a->bond_type[i] & BOND_TYPE_MASK);
963
+ }
964
+ }
965
+ if ( a->chem_bonds_valence + num_H - valence_to_metal == std_chem_bonds_valence ) {
966
+ /* removing bonds to metal produces standard valence */
967
+ return a->chem_bonds_valence - valence_to_metal;
968
+ }
969
+ }
970
+ #if( S_VI_O_PLUS_METAL_FIX_BOND == 1 )
971
+ else
972
+ if ( 1 == a->charge && 2 == get_endpoint_valence(a->el_number) &&
973
+ a->chem_bonds_valence + num_H == std_chem_bonds_valence ) {
974
+ int valence_to_metal = 0;
975
+ /*int num_bonds_to_metal = 0;*/
976
+ for ( i = 0; i < a->valence; i ++ ) {
977
+ if ( is_el_a_metal( at[(int)a->neighbor[i]].el_number ) ) {
978
+ if ( (a->bond_type[i] & BOND_TYPE_MASK) >= BOND_TYPE_ALTERN ) {
979
+ return a->valence; /* fall back */
980
+ }
981
+ /*num_bonds_to_metal ++;*/
982
+ valence_to_metal += (a->bond_type[i] & BOND_TYPE_MASK);
983
+ }
984
+ }
985
+ if ( 1 == valence_to_metal ) {
986
+ /* removing bonds to metal produces standard valence */
987
+ return a->chem_bonds_valence - valence_to_metal;
988
+ }
989
+ }
990
+ #endif
991
+ return a->chem_bonds_valence;
992
+ }
993
+ /************************************************************************/
994
+ int nNoMetalNeighIndex( inp_ATOM *at, int at_no )
995
+ {
996
+ inp_ATOM *a = at + at_no;
997
+ int i;
998
+ for ( i = 0; i < a->valence; i ++ ) {
999
+ if ( !is_el_a_metal( at[(int)a->neighbor[i]].el_number ) ) {
1000
+ return i;
1001
+ }
1002
+ }
1003
+ return -1;
1004
+ }
1005
+ /************************************************************************/
1006
+ int nNoMetalOtherNeighIndex( inp_ATOM *at, int at_no, int cur_neigh )
1007
+ {
1008
+ inp_ATOM *a = at + at_no;
1009
+ int i, neigh;
1010
+ for ( i = 0; i < a->valence; i ++ ) {
1011
+ neigh = (int)a->neighbor[i];
1012
+ if ( neigh != cur_neigh && !is_el_a_metal( at[neigh].el_number ) ) {
1013
+ return i;
1014
+ }
1015
+ }
1016
+ return -1;
1017
+ }
1018
+ /************************************************************************/
1019
+ int nNoMetalOtherNeighIndex2( inp_ATOM *at, int at_no, int cur_neigh, int cur_neigh2 )
1020
+ {
1021
+ inp_ATOM *a = at + at_no;
1022
+ int i, neigh;
1023
+ for ( i = 0; i < a->valence; i ++ ) {
1024
+ neigh = (int)a->neighbor[i];
1025
+ if ( neigh != cur_neigh && neigh != cur_neigh2 && !is_el_a_metal( at[neigh].el_number ) ) {
1026
+ return i;
1027
+ }
1028
+ }
1029
+ return -1;
1030
+ }
1031
+
1032
+
1033
+ #ifndef INCHI_ANSI_ONLY
1034
+ /**************************************************************************/
1035
+ int MakeRemovedProtonsString( int nNumRemovedProtons, NUM_H *nNumExchgIsotopicH, NUM_H *nNumRemovedProtonsIsotopic,
1036
+ int bIsotopic, char *szRemovedProtons, int *num_removed_iso_H )
1037
+ {
1038
+ int i, j, len, num;
1039
+ len = 0;
1040
+ if ( nNumRemovedProtons ) {
1041
+ len = sprintf ( szRemovedProtons, "Proton balance: %c %d H+",
1042
+ nNumRemovedProtons>=0? '+':'-', abs(nNumRemovedProtons) );
1043
+ }
1044
+ if ( bIsotopic && (nNumRemovedProtonsIsotopic || nNumExchgIsotopicH) ) {
1045
+ for ( i = 0, j = 0; i < NUM_H_ISOTOPES; i ++ ) {
1046
+ num = (nNumExchgIsotopicH? nNumExchgIsotopicH[i]:0) +
1047
+ (nNumRemovedProtonsIsotopic? nNumRemovedProtonsIsotopic[i]:0);
1048
+ if ( num ) {
1049
+ len += sprintf( szRemovedProtons+len, "%s %d^%dH",
1050
+ j? ", ":" [ removed ", num, i+1);
1051
+ j ++;
1052
+ }
1053
+ }
1054
+ if ( j ) {
1055
+ len += sprintf( szRemovedProtons+len, " ]" );
1056
+ if ( num_removed_iso_H )
1057
+ *num_removed_iso_H = j;
1058
+ }
1059
+ }
1060
+ if ( !len ) {
1061
+ szRemovedProtons[0] = '\0';
1062
+ }
1063
+ return len;
1064
+ }
1065
+ #endif
1066
+
1067
+ #ifdef INCHI_ANSI_ONLY
1068
+ /*************************************************************************/
1069
+ /************* non-ANSI functions ****************/
1070
+ /*************************************************************************/
1071
+ #define __MYTOLOWER(c) ( ((c) >= 'A') && ((c) <= 'Z') ? ((c) - 'A' + 'a') : (c) )
1072
+
1073
+ #if ( !defined(_MSC_VER) || defined(__STDC__) && __STDC__ == 1 )
1074
+ /* support (VC++ Language extensions) = OFF && defined(INCHI_ANSI_ONLY) */
1075
+ int memicmp ( const void * p1, const void * p2, size_t length )
1076
+ {
1077
+ const U_CHAR *s1 = (const U_CHAR*)p1;
1078
+ const U_CHAR *s2 = (const U_CHAR*)p2;
1079
+ while ( length-- ) {
1080
+ if ( *s1 == *s2 ||
1081
+ __MYTOLOWER( (int)*s1 ) == __MYTOLOWER( (int)*s2 )) {
1082
+ s1 ++;
1083
+ s2 ++;
1084
+ } else {
1085
+ return __MYTOLOWER( (int)*s1 ) - __MYTOLOWER( (int)*s2 );
1086
+ }
1087
+ }
1088
+ return 0;
1089
+ }
1090
+ /*************************************************************************/
1091
+ int stricmp( const char *s1, const char *s2 )
1092
+ {
1093
+ while ( *s1 ) {
1094
+ if ( *s1 == *s2 ||
1095
+ __MYTOLOWER( (int)*s1 ) == __MYTOLOWER( (int)*s2 )) {
1096
+ s1 ++;
1097
+ s2 ++;
1098
+ } else {
1099
+ return __MYTOLOWER( (int)*s1 ) - __MYTOLOWER( (int)*s2 );
1100
+ }
1101
+ }
1102
+ if ( *s2 )
1103
+ return -1;
1104
+ return 0;
1105
+ }
1106
+ /*************************************************************************/
1107
+ char *_strnset( char *s, int val, size_t length )
1108
+ {
1109
+ char *ps = s;
1110
+ while (length-- && *ps)
1111
+ *ps++ = (char)val;
1112
+ return s;
1113
+ }
1114
+ /*************************************************************************/
1115
+ char *_strdup( const char *string )
1116
+ {
1117
+ char *p = NULL;
1118
+ if ( string ) {
1119
+ size_t length = strlen( string );
1120
+ p = (char *)inchi_malloc( length + 1 );
1121
+ if ( p ) {
1122
+ strcpy( p, string );
1123
+ }
1124
+ }
1125
+ return p;
1126
+ }
1127
+ #endif
1128
+ #endif
1129
+
1130
+