rino 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +44 -0
- data/Rakefile +123 -0
- data/ext/extconf.rb +26 -0
- data/ext/ruby_inchi_main.so +0 -0
- data/ext/src/aux2atom.h +2786 -0
- data/ext/src/comdef.h +148 -0
- data/ext/src/e_0dstereo.c +3014 -0
- data/ext/src/e_0dstereo.h +31 -0
- data/ext/src/e_comdef.h +57 -0
- data/ext/src/e_ctl_data.h +147 -0
- data/ext/src/e_ichi_io.c +498 -0
- data/ext/src/e_ichi_io.h +40 -0
- data/ext/src/e_ichi_parms.c +37 -0
- data/ext/src/e_ichi_parms.h +41 -0
- data/ext/src/e_ichicomp.h +50 -0
- data/ext/src/e_ichierr.h +40 -0
- data/ext/src/e_ichimain.c +593 -0
- data/ext/src/e_ichisize.h +43 -0
- data/ext/src/e_inchi_atom.c +75 -0
- data/ext/src/e_inchi_atom.h +33 -0
- data/ext/src/e_inpdef.h +41 -0
- data/ext/src/e_mode.h +706 -0
- data/ext/src/e_mol2atom.c +649 -0
- data/ext/src/e_readinch.c +58 -0
- data/ext/src/e_readmol.c +54 -0
- data/ext/src/e_readmol.h +180 -0
- data/ext/src/e_readstru.c +251 -0
- data/ext/src/e_readstru.h +33 -0
- data/ext/src/e_util.c +284 -0
- data/ext/src/e_util.h +61 -0
- data/ext/src/extr_ct.h +251 -0
- data/ext/src/ichi.h +206 -0
- data/ext/src/ichi_bns.c +7999 -0
- data/ext/src/ichi_bns.h +231 -0
- data/ext/src/ichican2.c +5000 -0
- data/ext/src/ichicano.c +2195 -0
- data/ext/src/ichicano.h +49 -0
- data/ext/src/ichicans.c +1625 -0
- data/ext/src/ichicant.h +379 -0
- data/ext/src/ichicomn.h +260 -0
- data/ext/src/ichicomp.h +50 -0
- data/ext/src/ichidrp.h +119 -0
- data/ext/src/ichierr.h +124 -0
- data/ext/src/ichiisot.c +101 -0
- data/ext/src/ichilnct.c +286 -0
- data/ext/src/ichimain.h +132 -0
- data/ext/src/ichimak2.c +1189 -0
- data/ext/src/ichimake.c +3812 -0
- data/ext/src/ichimake.h +205 -0
- data/ext/src/ichimap1.c +851 -0
- data/ext/src/ichimap2.c +2856 -0
- data/ext/src/ichimap4.c +1609 -0
- data/ext/src/ichinorm.c +741 -0
- data/ext/src/ichinorm.h +67 -0
- data/ext/src/ichiparm.c +45 -0
- data/ext/src/ichiparm.h +1441 -0
- data/ext/src/ichiprt1.c +3612 -0
- data/ext/src/ichiprt2.c +1511 -0
- data/ext/src/ichiprt3.c +3011 -0
- data/ext/src/ichiqueu.c +1003 -0
- data/ext/src/ichiring.c +326 -0
- data/ext/src/ichiring.h +49 -0
- data/ext/src/ichisize.h +35 -0
- data/ext/src/ichisort.c +539 -0
- data/ext/src/ichister.c +3538 -0
- data/ext/src/ichister.h +35 -0
- data/ext/src/ichitaut.c +3843 -0
- data/ext/src/ichitaut.h +387 -0
- data/ext/src/ichitime.h +74 -0
- data/ext/src/inchi_api.h +670 -0
- data/ext/src/inchi_dll.c +1480 -0
- data/ext/src/inchi_dll.h +34 -0
- data/ext/src/inchi_dll_main.c +23 -0
- data/ext/src/inchi_dll_main.h +31 -0
- data/ext/src/inpdef.h +328 -0
- data/ext/src/lreadmol.h +1246 -0
- data/ext/src/mode.h +706 -0
- data/ext/src/ruby_inchi_main.c +558 -0
- data/ext/src/runichi.c +4179 -0
- data/ext/src/strutil.c +3861 -0
- data/ext/src/strutil.h +182 -0
- data/ext/src/util.c +1130 -0
- data/ext/src/util.h +85 -0
- data/lib/clean_tempfile.rb +220 -0
- data/lib/rino.rb +111 -0
- data/test/test.rb +386 -0
- metadata +130 -0
data/ext/src/ichiprt1.c
ADDED
@@ -0,0 +1,3612 @@
|
|
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 <stdlib.h>
|
12
|
+
#include <string.h>
|
13
|
+
#include <ctype.h>
|
14
|
+
#include <math.h>
|
15
|
+
|
16
|
+
#include "mode.h"
|
17
|
+
|
18
|
+
#include "inpdef.h"
|
19
|
+
#include "ichi.h"
|
20
|
+
#include "strutil.h"
|
21
|
+
#include "util.h"
|
22
|
+
#include "extr_ct.h"
|
23
|
+
#include "ichitaut.h"
|
24
|
+
#include "ichinorm.h"
|
25
|
+
#include "ichicant.h"
|
26
|
+
#include "ichicano.h"
|
27
|
+
#include "ichicomn.h"
|
28
|
+
#include "ichister.h"
|
29
|
+
|
30
|
+
#include "ichicomp.h"
|
31
|
+
#include "ichimain.h"
|
32
|
+
#include "ichimake.h"
|
33
|
+
|
34
|
+
int PrintXmlStartTag( char *pStr, int indent, int bEnd, const char *tag,
|
35
|
+
const char *l1, int v1, const char *l2, int v2, const char *l3, int v3,
|
36
|
+
const char *l4, int v4, const char *l5, int v5, const char *l6, int v6);
|
37
|
+
int Needs2addXmlEntityRefs( const char *s );
|
38
|
+
int AddXmlEntityRefs( const char *p, char *d );
|
39
|
+
#if( TEST_RENUMB_ATOMS == 1 ) /* { */
|
40
|
+
int CompareStereoINChI( INChI_Stereo *s1, INChI_Stereo *s2 );
|
41
|
+
#endif
|
42
|
+
|
43
|
+
int str_LineStart( const char *tag, char *tag2, int val2, char *pStr, int ind );
|
44
|
+
int str_LineEnd( const char *tag, int tot_len, int nStrLen, int *bOverflow, char *pStr, int ind, int bPlainTextTags );
|
45
|
+
int CleanOrigCoord( MOL_COORD szCoord, int delim );
|
46
|
+
int WriteOrigCoord( int num_inp_atoms, MOL_COORD *szMolCoord, int *i, char *szBuf, int buf_len);
|
47
|
+
int WriteOrigAtoms( int num_inp_atoms, inp_ATOM *at, int *i, char *szBuf, int buf_len, STRUCT_DATA *sd);
|
48
|
+
int WriteOrigBonds( int num_inp_atoms, inp_ATOM *at, int *i, char *szBuf, int buf_len, STRUCT_DATA *sd);
|
49
|
+
|
50
|
+
|
51
|
+
char VER_STRING[64];
|
52
|
+
|
53
|
+
const char sCompDelim[] = ";"; /* component delimiter */
|
54
|
+
const char sIdenticalValues[] = "*"; /* identical component */
|
55
|
+
|
56
|
+
const char x_space[] = " ";
|
57
|
+
|
58
|
+
/* xml output: words & additional tags */
|
59
|
+
const char x_inchi[] = INCHI_NAME;
|
60
|
+
const char x_inchi_ver[] = "version"; /* "InChI.version"; */
|
61
|
+
const char x_curr_ver[] = INCHI_VERSION;
|
62
|
+
|
63
|
+
const char x_structure[] = "structure";
|
64
|
+
const char x_number[] = "number";
|
65
|
+
const char x_header[] = "id.name";
|
66
|
+
const char x_value[] = "id.value";
|
67
|
+
|
68
|
+
const char x_empty[] = "";
|
69
|
+
|
70
|
+
const char x_type[] = "type";
|
71
|
+
|
72
|
+
const char x_message[] = "message";
|
73
|
+
const char x_text[] = "value";
|
74
|
+
|
75
|
+
const char x_ferr[] = "fatal (aborted)";
|
76
|
+
const char x_err[] = "error (no InChI)";
|
77
|
+
const char x_warn[] = "warning";
|
78
|
+
|
79
|
+
const char x_basic[] = "identifier";
|
80
|
+
const char x_tautomeric[] = "mobile-H";
|
81
|
+
const char x_reconnected[] = "reconnected";
|
82
|
+
|
83
|
+
const char x_ver[] = "version";
|
84
|
+
|
85
|
+
const char x_type_alpha[] = "alpha";
|
86
|
+
const char x_type_numer[] = "numeric";
|
87
|
+
const char x_type_predec[] = "sct";
|
88
|
+
const char x_type_normal[] = "normal";
|
89
|
+
const char x_type_short[] = "compressed";
|
90
|
+
const char x_basic_layer[] = "basic";
|
91
|
+
|
92
|
+
const char x_aux_basic[] = "identifier.auxiliary-info";
|
93
|
+
const char x_aux_comm[] = "!-- This section is NOT a part of the identifier, it is not unique --";
|
94
|
+
|
95
|
+
const char x_ign_uu_sp2[] = "omit_undef_dbond";
|
96
|
+
const char x_ign_uu_sp3[] = "omit_undef_sp3";
|
97
|
+
|
98
|
+
const char x_line_opening[] = "<";
|
99
|
+
const char x_line_closing[] = "</";
|
100
|
+
const char x_close_line[] = ">";
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
const char x_abs[] = "1";
|
105
|
+
const char x_rel[] = "2";
|
106
|
+
const char x_rac[] = "3";
|
107
|
+
|
108
|
+
|
109
|
+
#define MAX_TAG_LEN 64
|
110
|
+
|
111
|
+
typedef struct tagInchiTag {
|
112
|
+
const char *szPlainLabel;
|
113
|
+
const char *szPlainComment;
|
114
|
+
const char *szXmlLabel;
|
115
|
+
int bAlwaysOutput;
|
116
|
+
} INCHI_TAG;
|
117
|
+
|
118
|
+
/* identifier */
|
119
|
+
const INCHI_TAG IdentLbl[] = {
|
120
|
+
/* prefixes: may be combined in this order */
|
121
|
+
/* IL_FIXH_ORD, */ { "/", "fixed_H", "fixed-H", 0 }, /* fixed H */
|
122
|
+
/* IL_ISOT_ORD, */ { "/", "isotopic", "isotopic", 0 }, /* isotopic */
|
123
|
+
/* IL_STER_ORD, */ { "/", "stereo", "stereo", 0 }, /* stereo */
|
124
|
+
/* items */
|
125
|
+
/* IL_VERS_ORD, */ { "" , "version", "version", 1 },
|
126
|
+
/* IL_FML__ORD, */ { "/", "formula", "formula", 1 }, /* basic part formula */
|
127
|
+
/* IL_CONN_ORD, */ { "/c", "connections", "connections", 1 },
|
128
|
+
/* IL_ALLH_ORD, */ { "/h", "H_atoms", "H", 1 },
|
129
|
+
/* IL_CHRG_ORD, */ { "/q", "charge", "charge", 1 },
|
130
|
+
/* IL_PROT_ORD, */ { "/p", "protons", "protons", 0 },
|
131
|
+
/* stereo */
|
132
|
+
/* IL_DBND_ORD, */ { "/b", "dbond", "dbond", 0 },
|
133
|
+
/* IL_SP3S_ORD, */ { "/t", "sp3", "sp3", 0 },
|
134
|
+
/* IL_INVS_ORD, */ { "/m", "sp3:inverted", "abs.inverted", 0 }, /* mirrored */
|
135
|
+
/* IL_TYPS_ORD, */ { "/s", "type (1=abs, 2=rel, 3=rac)", "type", 0 }, /* stereo type */
|
136
|
+
/* isotopic */
|
137
|
+
/* IL_ATMS_ORD, */ { "/i", "atoms", "atoms", 1 },
|
138
|
+
/* isotopic mobile H only */
|
139
|
+
/* IL_XCGA_ORD, */ { "/h", "exchangeable_H", "H-isotopic", 1 },
|
140
|
+
/* fixed H only */
|
141
|
+
/* IL_FMLF_ORD, */ { "/f", "formula", "formula", 1 }, /* fixed H formula */
|
142
|
+
/* IL_HFIX_ORD, */ { "/h", "H_fixed" , "H-fixed" , 1 }, /* fixed-H */
|
143
|
+
/* IL_TRNS_ORD, */ { "/o", "transposition", "transposition", 0 }, /* order */
|
144
|
+
/* IL_REC__ORD, */ { "/r", "reconnected bond(s) to metal(s) formula", "formula", 0 }
|
145
|
+
|
146
|
+
};
|
147
|
+
/*
|
148
|
+
|
149
|
+
Parsing plain text InChI (FML is a chemical formula)
|
150
|
+
========================
|
151
|
+
|
152
|
+
1.12Beta/FML /i /f[FML] /i [/o] /rFML /i /f[FML] /i [/o] end
|
153
|
+
| | | | | | | | |
|
154
|
+
Labels | chqpbtms | hbtms | hqbtms | btms | chqpbtms | hbtms | hqbtms | btms |
|
155
|
+
inside: | | | | | | | | |
|
156
|
+
| non-iso- | iso- | fix- | iso- | non-iso- | iso- | fix- | iso- |
|
157
|
+
meaning: | topic | topic | ed H | topic | topic | topic | ed H | topic |
|
158
|
+
|----------+-------+--------+---------|----------+-------+--------+---------|
|
159
|
+
| mobile-H | fixed-H | mobile-H | fixed-H |
|
160
|
+
|----------+-------+--------+---------|----------+-------+--------+---------|
|
161
|
+
| | |
|
162
|
+
| normal or disconected metal | reconnected bonds to metal |
|
163
|
+
|_____________________________________|_____________________________________|
|
164
|
+
|
165
|
+
meanings of h:
|
166
|
+
|
167
|
+
/h - immobile H & mobile H group(s)
|
168
|
+
/i/h - exchangeable isotopic H (common)
|
169
|
+
/f/h - fixed-H
|
170
|
+
/f/i/h - never happens
|
171
|
+
|
172
|
+
*/
|
173
|
+
|
174
|
+
typedef enum tagIdentLblOrd {
|
175
|
+
|
176
|
+
IL_FIXH_ORD,
|
177
|
+
IL_ISOT_ORD,
|
178
|
+
IL_STER_ORD,
|
179
|
+
|
180
|
+
IL_VERS_ORD,
|
181
|
+
IL_FML__ORD,
|
182
|
+
IL_CONN_ORD,
|
183
|
+
IL_ALLH_ORD,
|
184
|
+
IL_CHRG_ORD,
|
185
|
+
IL_PROT_ORD,
|
186
|
+
|
187
|
+
IL_DBND_ORD,
|
188
|
+
IL_SP3S_ORD,
|
189
|
+
IL_INVS_ORD,
|
190
|
+
IL_TYPS_ORD,
|
191
|
+
|
192
|
+
IL_ATMS_ORD,
|
193
|
+
|
194
|
+
IL_XCGA_ORD,
|
195
|
+
|
196
|
+
IL_FMLF_ORD,
|
197
|
+
IL_HFIX_ORD,
|
198
|
+
IL_TRNS_ORD,
|
199
|
+
IL_REC__ORD,
|
200
|
+
|
201
|
+
IL_MAX_ORD /* max number of tags */
|
202
|
+
|
203
|
+
} IDENT_LBL_ORD;
|
204
|
+
|
205
|
+
typedef enum tagIdentLblBit {
|
206
|
+
|
207
|
+
IL_FIXH = 1 << IL_FIXH_ORD,
|
208
|
+
IL_ISOT = 1 << IL_ISOT_ORD,
|
209
|
+
IL_STER = 1 << IL_STER_ORD,
|
210
|
+
|
211
|
+
IL_VERS = 1 << IL_VERS_ORD,
|
212
|
+
IL_FML_ = 1 << IL_FML__ORD,
|
213
|
+
IL_CONN = 1 << IL_CONN_ORD,
|
214
|
+
IL_ALLH = 1 << IL_ALLH_ORD,
|
215
|
+
IL_CHRG = 1 << IL_CHRG_ORD,
|
216
|
+
IL_PROT = 1 << IL_PROT_ORD,
|
217
|
+
|
218
|
+
IL_DBND = 1 << IL_DBND_ORD,
|
219
|
+
IL_SP3S = 1 << IL_SP3S_ORD,
|
220
|
+
IL_INVS = 1 << IL_INVS_ORD,
|
221
|
+
IL_TYPS = 1 << IL_TYPS_ORD,
|
222
|
+
|
223
|
+
IL_ATMS = 1 << IL_ATMS_ORD,
|
224
|
+
|
225
|
+
IL_XCGA = 1 << IL_XCGA_ORD,
|
226
|
+
|
227
|
+
IL_FMLF = 1 << IL_FMLF_ORD,
|
228
|
+
IL_HFIX = 1 << IL_HFIX_ORD,
|
229
|
+
IL_TRNS = 1 << IL_TRNS_ORD,
|
230
|
+
IL_REC_ = 1 << IL_REC__ORD
|
231
|
+
|
232
|
+
} IDENT_LBL_BIT;
|
233
|
+
|
234
|
+
|
235
|
+
/* aux info */
|
236
|
+
const INCHI_TAG AuxLbl[] = {
|
237
|
+
|
238
|
+
/* prefixes may be combined in this order */
|
239
|
+
/* AL_FIXH_ORD, */ { "/", "fixed_H", "fixed-H", 0 }, /* fixed-H */
|
240
|
+
/* AL_ISOT_ORD, */ { "/", "isotopic", "isotopic", 0 }, /* isotopic */
|
241
|
+
/* AL_STER_ORD, */ { "/", "abs_stereo_inverted", "stereo.abs.inverted", 0 }, /* inv abs sp3 stereo */
|
242
|
+
/* AL_REVR_ORD, */ { "/", "reversibility", "reversibility", 0 }, /* reversibility */
|
243
|
+
/* items */
|
244
|
+
/* AL_VERS_ORD, */ { "", "version", "version", 1 },
|
245
|
+
/* AL_NORM_ORD, */ { "/", "normalization_type", "norm-type", 1 },
|
246
|
+
/* AL_ANBR_ORD, */ { "/N:", "original_atom_numbers", "atom.orig-nbr", 1 },
|
247
|
+
/* AL_AEQU_ORD, */ { "/E:", "atom_equivalence", "atom.equivalence", 0 },
|
248
|
+
/* AL_GEQU_ORD, */ { "/gE:", "group_equivalence", "group.equivalence", 0 },
|
249
|
+
/* inv abs sp3 stereo */
|
250
|
+
/* AL_SP3I_ORD, */ { "/it:", "sp3", "sp3", 0 },
|
251
|
+
/* AL_SP3N_ORD, */ { "/iN:", "original_atom_numbers", "atom.orig-nbr", 0 },
|
252
|
+
|
253
|
+
/* AL_CRV__ORD, */ { "/CRV:", "charge_radical_valence", "charges-rad-val", 0 },
|
254
|
+
/* reversibility */
|
255
|
+
/* AL_ATMR_ORD, */ { "/rA:", "atoms", "atoms", 0 },
|
256
|
+
/* AL_BNDR_ORD, */ { "/rB:", "bonds", "bonds", 0 },
|
257
|
+
/* AL_XYZR_ORD, */ { "/rC:", "xyz", "xyz", 0 },
|
258
|
+
/* fixed-H only */
|
259
|
+
/* AL_FIXN_ORD, */ { "/F:", "original_atom_numbers", "atom.orig-nbr", 1 },
|
260
|
+
/* isotopic only */
|
261
|
+
/* AL_ISON_ORD, */ { "/I:", "original_atom_numbers", "atom.orig-nbr", 1 },
|
262
|
+
|
263
|
+
/* AL_REC__ORD, */ { "/R:", "reconnected bond(s) to metal(s) part", "", 1 }
|
264
|
+
|
265
|
+
};
|
266
|
+
|
267
|
+
typedef enum tagAuxLblOrd {
|
268
|
+
|
269
|
+
AL_FIXH_ORD,
|
270
|
+
AL_ISOT_ORD,
|
271
|
+
AL_STER_ORD,
|
272
|
+
AL_REVR_ORD,
|
273
|
+
|
274
|
+
AL_VERS_ORD,
|
275
|
+
AL_NORM_ORD,
|
276
|
+
AL_ANBR_ORD,
|
277
|
+
AL_AEQU_ORD,
|
278
|
+
AL_GEQU_ORD,
|
279
|
+
|
280
|
+
AL_SP3I_ORD,
|
281
|
+
AL_SP3N_ORD,
|
282
|
+
|
283
|
+
AL_CRV__ORD,
|
284
|
+
|
285
|
+
AL_ATMR_ORD,
|
286
|
+
AL_BNDR_ORD,
|
287
|
+
AL_XYZR_ORD,
|
288
|
+
|
289
|
+
AL_FIXN_ORD,
|
290
|
+
|
291
|
+
AL_ISON_ORD,
|
292
|
+
|
293
|
+
AL_REC__ORD,
|
294
|
+
|
295
|
+
AL_MAX_ORD /* max number of tags */
|
296
|
+
|
297
|
+
} AUX_LBL_ORD;
|
298
|
+
|
299
|
+
|
300
|
+
typedef enum tagAuxLblBit {
|
301
|
+
|
302
|
+
AL_FIXH = 1 << AL_FIXH_ORD,
|
303
|
+
AL_ISOT = 1 << AL_ISOT_ORD,
|
304
|
+
AL_STER = 1 << AL_STER_ORD,
|
305
|
+
AL_REVR = 1 << AL_REVR_ORD,
|
306
|
+
|
307
|
+
AL_VERS = 1 << AL_VERS_ORD,
|
308
|
+
AL_NORM = 1 << AL_NORM_ORD,
|
309
|
+
AL_ANBR = 1 << AL_ANBR_ORD,
|
310
|
+
AL_AEQU = 1 << AL_AEQU_ORD,
|
311
|
+
AL_GEQU = 1 << AL_GEQU_ORD,
|
312
|
+
|
313
|
+
AL_SP3I = 1 << AL_SP3I_ORD,
|
314
|
+
AL_SP3N = 1 << AL_SP3N_ORD,
|
315
|
+
|
316
|
+
AL_CRV_ = 1 << AL_CRV__ORD,
|
317
|
+
|
318
|
+
AL_ATMR = 1 << AL_ATMR_ORD,
|
319
|
+
AL_BNDR = 1 << AL_BNDR_ORD,
|
320
|
+
AL_XYZR = 1 << AL_XYZR_ORD,
|
321
|
+
|
322
|
+
AL_FIXN = 1 << AL_FIXN_ORD,
|
323
|
+
|
324
|
+
AL_ISON = 1 << AL_ISON_ORD,
|
325
|
+
|
326
|
+
AL_REC_ = 1 << AL_REC__ORD
|
327
|
+
|
328
|
+
} AUX_LBL_BIT;
|
329
|
+
|
330
|
+
const int MAX_TAG_NUM = inchi_max((int)IL_MAX_ORD, (int)AL_MAX_ORD);
|
331
|
+
|
332
|
+
char *szGetTag( const INCHI_TAG *Tag, int nTag, int bTag, char *szTag, int *bAlways );
|
333
|
+
|
334
|
+
|
335
|
+
#define SP(N) (x_space+sizeof(x_space)-1-(N))
|
336
|
+
/**********************************************************************************************/
|
337
|
+
typedef struct tagXmlEntityRef {
|
338
|
+
char nChar;
|
339
|
+
const char *pRef;
|
340
|
+
} X_REF;
|
341
|
+
X_REF xmlRef[] = { {'<', "<"}, {'&', "&"}, {'>', ">"}, {'"', """}, {'\'', "'"}, {0, NULL}, };
|
342
|
+
const char szRefChars[sizeof(xmlRef)/sizeof(xmlRef[0])] = {'<', '&', '>', '"', '\'', '\0' };
|
343
|
+
/**********************************************************************************************/
|
344
|
+
int PrintXmlStartTag( char *pStr, int indent, int bEnd, const char *tag,
|
345
|
+
const char *l1, int v1, const char *l2, int v2, const char *l3, int v3,
|
346
|
+
const char *l4, int v4, const char *l5, int v5, const char *l6, int v6)
|
347
|
+
{
|
348
|
+
int len=0;
|
349
|
+
if ( tag ) {
|
350
|
+
len += sprintf( pStr+len, "%s<%s", SP(indent), tag);
|
351
|
+
}
|
352
|
+
if ( l1 ) {
|
353
|
+
len += sprintf( pStr+len, " %s=\"%d\"", l1, v1);
|
354
|
+
}
|
355
|
+
if ( l2 ) {
|
356
|
+
len += sprintf( pStr+len, " %s=\"%d\"", l2, v2);
|
357
|
+
}
|
358
|
+
if ( l3 ) {
|
359
|
+
len += sprintf( pStr+len, " %s=\"%d\"", l3, v3);
|
360
|
+
}
|
361
|
+
if ( l4 ) {
|
362
|
+
len += sprintf( pStr+len, " %s=\"%d\"", l4, v4);
|
363
|
+
}
|
364
|
+
if ( l5 ) {
|
365
|
+
len += sprintf( pStr+len, " %s=\"%d\"", l5, v5);
|
366
|
+
}
|
367
|
+
if ( l6 ) {
|
368
|
+
len += sprintf( pStr+len, " %s=\"%d\"", l6, v6);
|
369
|
+
}
|
370
|
+
if ( (bEnd & 3) ) {
|
371
|
+
len += sprintf( pStr+len, "%s%s", (bEnd & 1)?"/":"", (bEnd & 2)?">":"");
|
372
|
+
}
|
373
|
+
return len;
|
374
|
+
}
|
375
|
+
/**********************************************************************************************/
|
376
|
+
int Needs2addXmlEntityRefs( const char *s )
|
377
|
+
{
|
378
|
+
int len = 0;
|
379
|
+
const X_REF *q = xmlRef, *r;
|
380
|
+
const char *p;
|
381
|
+
if ( s && *s ) {
|
382
|
+
for ( q = xmlRef, len = 0; q->nChar; q ++ ) {
|
383
|
+
for ( p = s; p = strchr( p, q->nChar ); p ++ ) {
|
384
|
+
if ( q->nChar == '&' ) {
|
385
|
+
for ( r = xmlRef; r->nChar; r ++ ) {
|
386
|
+
if ( !memcmp( p, r->pRef, strlen(r->pRef) ) )
|
387
|
+
goto DoNotSubstitute;
|
388
|
+
}
|
389
|
+
}
|
390
|
+
len += strlen(q->pRef)-1;
|
391
|
+
DoNotSubstitute:;
|
392
|
+
}
|
393
|
+
}
|
394
|
+
if ( len ) {
|
395
|
+
len += strlen( s );
|
396
|
+
}
|
397
|
+
}
|
398
|
+
return len;
|
399
|
+
}
|
400
|
+
/**********************************************************************************************/
|
401
|
+
int AddXmlEntityRefs( const char *p, char *d )
|
402
|
+
{
|
403
|
+
int len_d, n;
|
404
|
+
const X_REF *q = xmlRef, *r;
|
405
|
+
|
406
|
+
len_d = 0;
|
407
|
+
while ( *p ) {
|
408
|
+
n = strcspn( p, szRefChars );
|
409
|
+
if ( n > 0 ) {
|
410
|
+
/* first n characters of p do not contain referenced chars; copy them */
|
411
|
+
strncpy( d+len_d, p, n ); /* does not have zero termination */
|
412
|
+
len_d += n; /* new destination length */
|
413
|
+
p += n; /* position of the referenced char in the source */
|
414
|
+
}
|
415
|
+
if ( *p ) {
|
416
|
+
if ( *p == '&' ) {
|
417
|
+
for ( r = xmlRef; r->nChar; r ++ ) {
|
418
|
+
if ( !memcmp( p, r->pRef, strlen(r->pRef) ) ) {
|
419
|
+
d[len_d++] = *p;
|
420
|
+
goto DoNotSubstitute;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
}
|
424
|
+
q = xmlRef + (strchr( szRefChars, UCINT *p) - szRefChars);
|
425
|
+
strcpy( d+len_d, q->pRef ); /* add entity reference and zero termination */
|
426
|
+
len_d += strlen( d + len_d ); /* new destination length */
|
427
|
+
DoNotSubstitute:
|
428
|
+
p ++;
|
429
|
+
} else {
|
430
|
+
d[len_d] = '\0'; /* add zero termination */
|
431
|
+
}
|
432
|
+
|
433
|
+
}
|
434
|
+
return len_d;
|
435
|
+
}
|
436
|
+
|
437
|
+
/**********************************************************************************************/
|
438
|
+
int OutputINChIXmlRootStartTag( INCHI_FILE *output_file )
|
439
|
+
{
|
440
|
+
char pStr[128];
|
441
|
+
sprintf( pStr, "<%s %s=\"%s\">", x_inchi, x_inchi_ver, x_curr_ver );
|
442
|
+
inchi_print_nodisplay( output_file, "%s\n", pStr );
|
443
|
+
return 0;
|
444
|
+
}
|
445
|
+
/**********************************************************************************************/
|
446
|
+
int OutputINChIXmlRootEndTag( INCHI_FILE *output_file )
|
447
|
+
{
|
448
|
+
char pStr[128];
|
449
|
+
sprintf( pStr, "</%s>", x_inchi );
|
450
|
+
inchi_print_nodisplay( output_file, "%s\n", pStr );
|
451
|
+
return 0;
|
452
|
+
}
|
453
|
+
|
454
|
+
/**********************************************************************************************/
|
455
|
+
int OutputINChIXmlStructStartTag( INCHI_FILE *output_file, char *pStr, int ind /* indent*/, int nStrLen, int bNoStructLabels,
|
456
|
+
int num_input_struct, const char *szSdfLabel, const char *szSdfValue )
|
457
|
+
{
|
458
|
+
char szBuf[64];
|
459
|
+
int nEstLen1;
|
460
|
+
int nEstLen2;
|
461
|
+
int ret = 0;
|
462
|
+
int tot_len;
|
463
|
+
char *pSdfLabel = NULL, *pSdfValue = NULL, *p;
|
464
|
+
/* substitute special characters (see szRefChars[]) with xml Entity References */
|
465
|
+
int len;
|
466
|
+
if ( bNoStructLabels ) {
|
467
|
+
/* no labela at all */
|
468
|
+
inchi_print( output_file, "%s\n", "" ); /* empty line */
|
469
|
+
tot_len = 0;
|
470
|
+
tot_len += sprintf(pStr+tot_len, "%s<%s", SP(ind), x_structure);
|
471
|
+
tot_len += sprintf(pStr+tot_len, ">" );
|
472
|
+
inchi_print( output_file, "%s\n", pStr );
|
473
|
+
ret = 1; /* success */
|
474
|
+
} else
|
475
|
+
if ( !(szSdfLabel && szSdfLabel[0]) && !(szSdfValue && szSdfValue[0]) ) {
|
476
|
+
/* only structure number if present */
|
477
|
+
inchi_print( output_file, "%s\n", "" ); /* empty line */
|
478
|
+
tot_len = 0;
|
479
|
+
tot_len += sprintf(pStr+tot_len, "%s<%s", SP(ind), x_structure);
|
480
|
+
if ( num_input_struct > 0 ) {
|
481
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%d\"", x_number, num_input_struct);
|
482
|
+
}
|
483
|
+
tot_len += sprintf(pStr+tot_len, ">" );
|
484
|
+
inchi_print( output_file, "%s\n", pStr );
|
485
|
+
ret = 1; /* success */
|
486
|
+
} else {
|
487
|
+
if ( len = Needs2addXmlEntityRefs( szSdfLabel ) ) {
|
488
|
+
if ( p = (char*)inchi_malloc( len+1 ) ) {
|
489
|
+
AddXmlEntityRefs( szSdfLabel, p );
|
490
|
+
szSdfLabel = pSdfLabel = p;
|
491
|
+
}
|
492
|
+
}
|
493
|
+
if ( len = Needs2addXmlEntityRefs( szSdfValue ) ) {
|
494
|
+
if ( p = (char*)inchi_malloc( len+1 ) ) {
|
495
|
+
AddXmlEntityRefs( szSdfValue, p );
|
496
|
+
szSdfValue = pSdfValue = p;
|
497
|
+
}
|
498
|
+
}
|
499
|
+
nEstLen1 = ind + 1 + sizeof(x_structure)-1
|
500
|
+
+ 1 + sizeof(x_number)-1 + 1 + sprintf(szBuf,"\"%d\"", num_input_struct) + 2;
|
501
|
+
nEstLen2 = 1 + sizeof(x_header)-1 + 1 + 2 + (szSdfLabel? strlen(szSdfLabel):0)
|
502
|
+
+ 1 + sizeof(x_value) -1 + 1 + 2 + (szSdfValue? strlen(szSdfValue):0) + 2;
|
503
|
+
if ( nEstLen1 <= nStrLen ) {
|
504
|
+
inchi_print( output_file, "%s\n", "" ); /* empty line */
|
505
|
+
tot_len = 0;
|
506
|
+
tot_len += sprintf(pStr+tot_len, "%s<%s", SP(ind), x_structure);
|
507
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%d\"", x_number, num_input_struct);
|
508
|
+
if ( nEstLen1 + nEstLen2 <= nStrLen ) {
|
509
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%s\"", x_header, szSdfLabel? szSdfLabel:x_empty);
|
510
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%s\"", x_value, szSdfValue? szSdfValue:x_empty);
|
511
|
+
}
|
512
|
+
tot_len += sprintf(pStr+tot_len, ">" );
|
513
|
+
inchi_print( output_file, "%s\n", pStr );
|
514
|
+
ret = 1; /* success */
|
515
|
+
}
|
516
|
+
if ( pSdfValue ) {
|
517
|
+
inchi_free ( pSdfValue );
|
518
|
+
}
|
519
|
+
if ( pSdfLabel ) {
|
520
|
+
inchi_free( pSdfLabel );
|
521
|
+
}
|
522
|
+
}
|
523
|
+
return ret; /* 0 => Buffer overflow */
|
524
|
+
}
|
525
|
+
/**********************************************************************************************/
|
526
|
+
int OutputINChIXmlStructEndTag( INCHI_FILE *output_file, char *pStr, int nStrLen, int ind )
|
527
|
+
{
|
528
|
+
if ( output_file && pStr ) {
|
529
|
+
int nEstLen1 = ind + 1 + 1 + sizeof(x_structure)-1 + 2;
|
530
|
+
if ( nEstLen1 <= nStrLen ) {
|
531
|
+
sprintf(pStr, "%s</%s>", SP(ind), x_structure);
|
532
|
+
inchi_print( output_file, "%s\n", pStr );
|
533
|
+
return 1;
|
534
|
+
}
|
535
|
+
}
|
536
|
+
return 0;
|
537
|
+
}
|
538
|
+
|
539
|
+
/**********************************************************************************************/
|
540
|
+
int OutputINChIXmlError( INCHI_FILE *output_file, char *pStr, int nStrLen, int ind,
|
541
|
+
/*int nErrorNumber,*/ char *pErrorText, int bError )
|
542
|
+
{
|
543
|
+
/* char szBuf[64]; */
|
544
|
+
const char *pErr;
|
545
|
+
char *pNewErrorText=NULL, *szErrorText = pErrorText;
|
546
|
+
int nEstLen, len=0, ret = 0;
|
547
|
+
|
548
|
+
switch( bError ) {
|
549
|
+
case _IS_WARNING:
|
550
|
+
pErr = x_warn;
|
551
|
+
break;
|
552
|
+
case _IS_ERROR:
|
553
|
+
pErr = x_err;
|
554
|
+
break;
|
555
|
+
default: /* _IS_FATAL */
|
556
|
+
pErr = x_ferr;
|
557
|
+
break;
|
558
|
+
}
|
559
|
+
|
560
|
+
#if( ENTITY_REFS_IN_XML_MESSAGES == 1 )
|
561
|
+
/* insert xml entity references if necessary */
|
562
|
+
if ( len = Needs2addXmlEntityRefs( szErrorText ) ) {
|
563
|
+
if ( pNewErrorText = (char*)inchi_malloc( len+1 ) ) {
|
564
|
+
AddXmlEntityRefs( szErrorText, pNewErrorText );
|
565
|
+
szErrorText = pNewErrorText;
|
566
|
+
}
|
567
|
+
}
|
568
|
+
#else
|
569
|
+
szErrorText = pErrorText;
|
570
|
+
#endif
|
571
|
+
|
572
|
+
|
573
|
+
nEstLen = ind + 1 + sizeof(x_message)-1
|
574
|
+
+ 1 + sizeof(x_type)-1 + 1 + 1 + strlen(pErr)-1
|
575
|
+
/* + 1 + sizeof(x_code)-1 + 1 + sprintf(szBuf, "%d", nErrorNumber) */
|
576
|
+
+ 1 + sizeof(x_text)-1 + 1 + 1 + strlen(szErrorText) + 2;
|
577
|
+
if ( nEstLen <= nStrLen ) {
|
578
|
+
/*
|
579
|
+
sprintf( pStr, "%s<%s %s=\"%s\" %s=\"%d\" %s=\"%s\"/>",
|
580
|
+
SP(ind), x_message, x_type, pErr, x_code, nErrorNumber, x_text, szErrorText );
|
581
|
+
*/
|
582
|
+
sprintf( pStr, "%s<%s %s=\"%s\" %s=\"%s\"/>",
|
583
|
+
SP(ind), x_message, x_type, pErr, x_text, szErrorText );
|
584
|
+
inchi_print( output_file, "%s\n", pStr );
|
585
|
+
/*
|
586
|
+
pErrorText[0] = '\0'; // do not repeat same output
|
587
|
+
*/
|
588
|
+
ret = 1;
|
589
|
+
}
|
590
|
+
if ( pNewErrorText )
|
591
|
+
inchi_free( pNewErrorText );
|
592
|
+
return ret;
|
593
|
+
|
594
|
+
}
|
595
|
+
/**********************************************************************************************/
|
596
|
+
int OutputINChIPlainError( INCHI_FILE *output_file, char *pStr, int nStrLen,
|
597
|
+
char *pErrorText, int bError )
|
598
|
+
{
|
599
|
+
/* char szBuf[64]; */
|
600
|
+
const char *pErr;
|
601
|
+
char *pNewErrorText=NULL, *szErrorText = pErrorText;
|
602
|
+
int nEstLen, ret = 0;
|
603
|
+
|
604
|
+
switch( bError ) {
|
605
|
+
case _IS_WARNING:
|
606
|
+
pErr = x_warn;
|
607
|
+
break;
|
608
|
+
case _IS_ERROR:
|
609
|
+
pErr = x_err;
|
610
|
+
break;
|
611
|
+
default: /* _IS_FATAL */
|
612
|
+
pErr = x_ferr;
|
613
|
+
break;
|
614
|
+
}
|
615
|
+
/* <%s: >, x_message */
|
616
|
+
nEstLen = sizeof(x_message)-1 + 1 + 1
|
617
|
+
/* <%s=\"%s\">, x_type, pErr */
|
618
|
+
+ sizeof(x_type)-1 + 1 + 1 + strlen(pErr) + 1
|
619
|
+
/* < %s=\"%s\"\n>, x_text, szErrorText */
|
620
|
+
+ 1 + sizeof(x_text)-1 + 1 + 1 + strlen(szErrorText) + 1 + 1;
|
621
|
+
if ( nEstLen < nStrLen ) {
|
622
|
+
sprintf( pStr, "%s: %s=\"%s\" %s=\"%s\"",
|
623
|
+
x_message, x_type, pErr, x_text, szErrorText );
|
624
|
+
inchi_print( output_file, "%s\n", pStr );
|
625
|
+
ret = 1;
|
626
|
+
}
|
627
|
+
if ( pNewErrorText )
|
628
|
+
inchi_free( pNewErrorText );
|
629
|
+
return ret;
|
630
|
+
|
631
|
+
}
|
632
|
+
|
633
|
+
/**************************************************************************/
|
634
|
+
|
635
|
+
#ifndef OUT_TN /* defined in mode.h; quoted here for reference purposes only */
|
636
|
+
|
637
|
+
#define OUT_N1 0 /* non-tautomeric only */
|
638
|
+
#define OUT_T1 1 /* tautomeric if present otherwise non-tautomeric */
|
639
|
+
#define OUT_NT 2 /* only non-taut representations of tautomeric */
|
640
|
+
#define OUT_TN 3 /* tautomeric if present otherwise non-tautomeric;
|
641
|
+
sepatately output non-taut representations of tautomeric if present */
|
642
|
+
/* OUT_TN = OUT_T1 + OUT_NT */
|
643
|
+
#endif
|
644
|
+
|
645
|
+
|
646
|
+
/******************************************************************/
|
647
|
+
const char *EquString( int EquVal )
|
648
|
+
{
|
649
|
+
int bFrom = EquVal & (iiSTEREO | iiSTEREO_INV | iiNUMB | iiEQU );
|
650
|
+
int bType = EquVal & (iitISO | iitNONTAUT );
|
651
|
+
int bEq2 = EquVal & (iiEq2NONTAUT | iiEq2ISO | iiEq2INV );
|
652
|
+
const char *r = "";
|
653
|
+
|
654
|
+
switch ( bFrom ) {
|
655
|
+
|
656
|
+
case iiSTEREO: /* ------------ Stereo --------------------*/
|
657
|
+
switch ( bType ) {
|
658
|
+
case iitISO: /* iso main stereo =... */
|
659
|
+
switch( bEq2 ) {
|
660
|
+
case 0:
|
661
|
+
r = "m"; /* iso main stereo = main stereo */
|
662
|
+
break;
|
663
|
+
default:
|
664
|
+
r = "??"; /* should not happen */
|
665
|
+
break;
|
666
|
+
}
|
667
|
+
break;
|
668
|
+
case iitNONTAUT: /* non-taut stereo =... */
|
669
|
+
switch( bEq2 ) {
|
670
|
+
case 0:
|
671
|
+
r = "m"; /* non-taut stereo = main stereo */
|
672
|
+
break;
|
673
|
+
default:
|
674
|
+
r = "??"; /* should not happen */
|
675
|
+
break;
|
676
|
+
}
|
677
|
+
break;
|
678
|
+
case (iitNONTAUT | iitISO): /* iso non-taut stereo = ... */
|
679
|
+
switch( bEq2 ) {
|
680
|
+
case 0:
|
681
|
+
r = "m"; /* iso non-taut stereo = main stereo */
|
682
|
+
break;
|
683
|
+
case iiEq2ISO:
|
684
|
+
r = "M"; /* iso non-taut stereo = main iso stereo */
|
685
|
+
break;
|
686
|
+
case iiEq2NONTAUT:
|
687
|
+
r = "n"; /* iso non-taut stereo = non-taut stereo */
|
688
|
+
break;
|
689
|
+
default:
|
690
|
+
r = "??"; /* should not happen */
|
691
|
+
break;
|
692
|
+
}
|
693
|
+
break;
|
694
|
+
default:
|
695
|
+
r = "??"; /* should not happen */
|
696
|
+
break;
|
697
|
+
}
|
698
|
+
break;
|
699
|
+
|
700
|
+
case iiSTEREO_INV: /*---------- Inverted Aux Stereo ------*/
|
701
|
+
if ( bEq2 & iiEq2INV ) { /* stereo = Inverted(another stereo) */
|
702
|
+
bEq2 &= ~iiEq2INV;
|
703
|
+
switch( bType ) {
|
704
|
+
case 0: /* main = ...*/
|
705
|
+
switch( bEq2 ) {
|
706
|
+
case 0:
|
707
|
+
r = "im"; /* main = Inv(main) */
|
708
|
+
break;
|
709
|
+
case iiEq2ISO:
|
710
|
+
r = "iM"; /* main = Inv(main iso) */
|
711
|
+
break;
|
712
|
+
case iiEq2NONTAUT:
|
713
|
+
r = "in"; /* maim = Inv(non-taut) */
|
714
|
+
break;
|
715
|
+
case (iiEq2NONTAUT | iiEq2ISO):
|
716
|
+
r = "iN"; /* maim = Inv(non-taut iso ) */
|
717
|
+
break;
|
718
|
+
default:
|
719
|
+
r = "??"; /* should not happen */
|
720
|
+
break;
|
721
|
+
}
|
722
|
+
break;
|
723
|
+
case iitISO: /* main iso = ...*/
|
724
|
+
switch( bEq2 ) {
|
725
|
+
case 0:
|
726
|
+
r = "im"; /* main iso = Inv(main) */
|
727
|
+
break;
|
728
|
+
case iiEq2ISO:
|
729
|
+
r = "iM"; /* main iso = Inv(main iso) */
|
730
|
+
break;
|
731
|
+
case iiEq2NONTAUT:
|
732
|
+
r = "in"; /* maim iso = Inv(non-taut) */
|
733
|
+
break;
|
734
|
+
case (iiEq2NONTAUT | iiEq2ISO):
|
735
|
+
r = "iN"; /* maim = Inv(non-taut iso ) */
|
736
|
+
break;
|
737
|
+
default:
|
738
|
+
r = "??"; /* should not happen */
|
739
|
+
break;
|
740
|
+
}
|
741
|
+
break;
|
742
|
+
case iitNONTAUT: /* non-taut = ... */
|
743
|
+
switch( bEq2 ) {
|
744
|
+
case 0:
|
745
|
+
r = "im"; /* non-taut = Inv(main) */
|
746
|
+
break;
|
747
|
+
case iiEq2ISO:
|
748
|
+
r = "iM"; /* non-taut = Inv(main iso) */
|
749
|
+
break;
|
750
|
+
case iiEq2NONTAUT:
|
751
|
+
r = "in"; /* non-taut = Inv(non-taut) */
|
752
|
+
break;
|
753
|
+
case (iiEq2NONTAUT | iiEq2ISO):
|
754
|
+
r = "iN"; /* non-taut = Inv(non-taut iso ) */
|
755
|
+
break;
|
756
|
+
default:
|
757
|
+
r = "??"; /* should not happen */
|
758
|
+
break;
|
759
|
+
}
|
760
|
+
break;
|
761
|
+
case (iitNONTAUT | iitISO):
|
762
|
+
switch( bEq2 ) {
|
763
|
+
case 0:
|
764
|
+
r = "im"; /* non-taut iso = Inv(main) */
|
765
|
+
break;
|
766
|
+
case iiEq2ISO:
|
767
|
+
r = "iM"; /* non-taut iso = Inv(main iso) */
|
768
|
+
break;
|
769
|
+
case iiEq2NONTAUT:
|
770
|
+
r = "in"; /* non-taut iso = Inv(non-taut) */
|
771
|
+
break;
|
772
|
+
case (iiEq2NONTAUT | iiEq2ISO):
|
773
|
+
r = "iN"; /* non-taut iso = Inv(non-taut iso ) */
|
774
|
+
break;
|
775
|
+
default:
|
776
|
+
r = "??"; /* should not happen */
|
777
|
+
}
|
778
|
+
break;
|
779
|
+
default:
|
780
|
+
r = "??"; /* should not happen */
|
781
|
+
break;
|
782
|
+
}
|
783
|
+
|
784
|
+
} else { /* Inv stereo = another (non-inverted) stereo */
|
785
|
+
|
786
|
+
switch( bType ) {
|
787
|
+
case iitISO: /* main iso = ...*/
|
788
|
+
switch( bEq2 ) {
|
789
|
+
case 0:
|
790
|
+
r = "m"; /* main = (inverted aux) main */
|
791
|
+
break;
|
792
|
+
default:
|
793
|
+
r = "??"; /* should not happen */
|
794
|
+
break;
|
795
|
+
}
|
796
|
+
break;
|
797
|
+
case iitNONTAUT: /* non-taut = ... */
|
798
|
+
switch( bEq2 ) {
|
799
|
+
case 0:
|
800
|
+
r = "m"; /* non-taut = (inverted aux) main */
|
801
|
+
break;
|
802
|
+
default:
|
803
|
+
r = "??"; /* should not happen */
|
804
|
+
break;
|
805
|
+
}
|
806
|
+
break;
|
807
|
+
case (iitNONTAUT | iitISO): /* non-taut iso = ...*/
|
808
|
+
switch( bEq2 ) {
|
809
|
+
case 0:
|
810
|
+
r = "m"; /* non-taut iso = (inverted aux) main */
|
811
|
+
break;
|
812
|
+
case iiEq2ISO:
|
813
|
+
r = "M"; /* non-taut iso = (inverted aux) main iso */
|
814
|
+
break;
|
815
|
+
case iiEq2NONTAUT:
|
816
|
+
r = "n"; /* non-taut iso = (inverted aux) non-taut */
|
817
|
+
break;
|
818
|
+
default:
|
819
|
+
r = "??"; /* should not happen */
|
820
|
+
break;
|
821
|
+
}
|
822
|
+
break;
|
823
|
+
default:
|
824
|
+
r = "??"; /* should not happen */
|
825
|
+
break;
|
826
|
+
}
|
827
|
+
}
|
828
|
+
break;
|
829
|
+
|
830
|
+
case ( iiNUMB | iiSTEREO_INV): /*------------- Inv Stereo Numbering ------------*/
|
831
|
+
switch( bType ) {
|
832
|
+
case 0: /* inv stereo numb main = ...*/
|
833
|
+
switch( bEq2 ) {
|
834
|
+
case 0:
|
835
|
+
r = "m"; /* inv stereo numb main = main numb */
|
836
|
+
break;
|
837
|
+
default:
|
838
|
+
r = "??"; /* should not happen */
|
839
|
+
break;
|
840
|
+
}
|
841
|
+
break;
|
842
|
+
case iitISO: /* inv stereo iso numb main = ...*/
|
843
|
+
switch( bEq2 ) {
|
844
|
+
case 0:
|
845
|
+
r = "m"; /* inv stereo iso numb main = main numb */
|
846
|
+
break;
|
847
|
+
case iiEq2INV:
|
848
|
+
r = "im"; /* inv stereo iso numb main = InvStereo(main) numb */
|
849
|
+
break;
|
850
|
+
case iiEq2ISO:
|
851
|
+
r = "M"; /* inv stereo iso numb main = isotopic main numb */
|
852
|
+
break;
|
853
|
+
default:
|
854
|
+
r = "??"; /* should not happen */
|
855
|
+
break;
|
856
|
+
}
|
857
|
+
break;
|
858
|
+
case iitNONTAUT: /* inv stereo numb non-taut = ... */
|
859
|
+
switch( bEq2 ) {
|
860
|
+
case 0:
|
861
|
+
r = "m"; /* inv stereo numb non-taut = main numb */
|
862
|
+
break;
|
863
|
+
case iiEq2NONTAUT:
|
864
|
+
r = "n"; /* inv stereo numb non-taut = non-taut numb */
|
865
|
+
break;
|
866
|
+
case iiEq2INV:
|
867
|
+
r = "im"; /* inv stereo numb non-taut = InvStereo(main) numb */
|
868
|
+
break;
|
869
|
+
default:
|
870
|
+
r = "??"; /* should not happen */
|
871
|
+
break;
|
872
|
+
}
|
873
|
+
break;
|
874
|
+
case (iitNONTAUT | iitISO): /* inv stereo numb non-taut iso = ... */
|
875
|
+
switch( bEq2 ) {
|
876
|
+
case 0:
|
877
|
+
r = "m"; /* inv stereo numb non-taut iso = main numb */
|
878
|
+
break;
|
879
|
+
case iiEq2ISO:
|
880
|
+
r = "M"; /* inv stereo numb non-taut iso = main numb iso */
|
881
|
+
break;
|
882
|
+
case (iiEq2ISO | iiEq2INV):
|
883
|
+
r = "iM"; /* inv stereo numb non-taut iso = InvStereo(main iso) numb */
|
884
|
+
break;
|
885
|
+
case iiEq2NONTAUT:
|
886
|
+
r = "n"; /* inv stereo numb non-taut iso = non-taut numb */
|
887
|
+
break;
|
888
|
+
case (iiEq2NONTAUT | iiEq2ISO):
|
889
|
+
r = "N"; /* inv stereo numb non-taut iso = non-taut iso numb */
|
890
|
+
break;
|
891
|
+
case iiEq2INV:
|
892
|
+
r = "im"; /* inv stereo numb non-taut iso = InvStereo(main) numb */
|
893
|
+
break;
|
894
|
+
case (iiEq2NONTAUT | iiEq2INV):
|
895
|
+
r = "in"; /* inv stereo numb non-taut iso = InvStereo(non-taut) numb ) */
|
896
|
+
break;
|
897
|
+
default:
|
898
|
+
r = "??"; /* should not happen */
|
899
|
+
break;
|
900
|
+
}
|
901
|
+
break;
|
902
|
+
default:
|
903
|
+
r = "??"; /* should not happen */
|
904
|
+
break;
|
905
|
+
}
|
906
|
+
break;
|
907
|
+
|
908
|
+
case iiNUMB: /*------------- Canonical Numbering ------------*/
|
909
|
+
switch( bType ) {
|
910
|
+
case 0: /* numb main = ...*/
|
911
|
+
r = "??"; /* should not happen */
|
912
|
+
break;
|
913
|
+
case iitISO: /* iso numb main = ...*/
|
914
|
+
switch( bEq2 ) {
|
915
|
+
case 0:
|
916
|
+
r = "m"; /* iso numb main = main numb */
|
917
|
+
break;
|
918
|
+
default:
|
919
|
+
r = "??"; /* should not happen */
|
920
|
+
}
|
921
|
+
break;
|
922
|
+
case iitNONTAUT: /* numb non-taut = ... */
|
923
|
+
switch( bEq2 ) {
|
924
|
+
case 0:
|
925
|
+
r = "m"; /* numb non-taut = main numb */
|
926
|
+
break;
|
927
|
+
default:
|
928
|
+
r = "??"; /* should not happen */
|
929
|
+
}
|
930
|
+
break;
|
931
|
+
case (iitNONTAUT | iitISO): /* numb non-taut iso = ... */
|
932
|
+
switch( bEq2 ) {
|
933
|
+
case 0:
|
934
|
+
r = "m"; /* numb non-taut iso = main numb */
|
935
|
+
break;
|
936
|
+
case iiEq2ISO:
|
937
|
+
r = "M"; /* numb non-taut iso = main numb iso */
|
938
|
+
break;
|
939
|
+
case iiEq2NONTAUT:
|
940
|
+
r = "n"; /* numb non-taut iso = non-taut numb */
|
941
|
+
break;
|
942
|
+
default:
|
943
|
+
r = "??"; /* should not happen */
|
944
|
+
break;
|
945
|
+
}
|
946
|
+
break;
|
947
|
+
default:
|
948
|
+
r = "??"; /* should not happen */
|
949
|
+
break;
|
950
|
+
}
|
951
|
+
break;
|
952
|
+
|
953
|
+
case iiEQU: /*------------- Atom Equivalence ------------*/
|
954
|
+
switch( bType ) {
|
955
|
+
case 0: /* equivalence main = ...*/
|
956
|
+
r = "??"; /* should not happen */
|
957
|
+
break;
|
958
|
+
case iitISO: /* equivalence main iso = ...*/
|
959
|
+
switch( bEq2 ) {
|
960
|
+
case 0:
|
961
|
+
r = "m"; /* equivalence main = main equ */
|
962
|
+
break;
|
963
|
+
default:
|
964
|
+
r = "??"; /* should not happen */
|
965
|
+
break;
|
966
|
+
}
|
967
|
+
break;
|
968
|
+
case iitNONTAUT: /* equivalence non-taut = ... */
|
969
|
+
switch( bEq2 ) {
|
970
|
+
case 0:
|
971
|
+
r = "m"; /* equivalence non-taut = main equ */
|
972
|
+
break;
|
973
|
+
default:
|
974
|
+
r = "??"; /* should not happen */
|
975
|
+
break;
|
976
|
+
}
|
977
|
+
break;
|
978
|
+
case (iitNONTAUT | iitISO): /* equivalence non-taut iso = ... */
|
979
|
+
switch( bEq2 ) {
|
980
|
+
case 0:
|
981
|
+
r = "m"; /* equivalence non-taut iso = main equ */
|
982
|
+
break;
|
983
|
+
case iiEq2ISO:
|
984
|
+
r = "M"; /* equivalence non-taut iso = main iso equ */
|
985
|
+
break;
|
986
|
+
case iiEq2NONTAUT:
|
987
|
+
r = "n"; /* equivalence non-taut iso = non-taut equ */
|
988
|
+
break;
|
989
|
+
default:
|
990
|
+
r = "??"; /* should not happen */
|
991
|
+
break;
|
992
|
+
}
|
993
|
+
break;
|
994
|
+
default:
|
995
|
+
r = "??"; /* should not happen */
|
996
|
+
break;
|
997
|
+
}
|
998
|
+
break;
|
999
|
+
default:
|
1000
|
+
r = "??"; /* should not happen */
|
1001
|
+
break;
|
1002
|
+
}
|
1003
|
+
return r;
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
/**********************************************************************************************/
|
1007
|
+
|
1008
|
+
#define OUT_NONTAUT OUT_NN /* was OUT_NT until 2004-04-07 */
|
1009
|
+
|
1010
|
+
/**********************************************************************************************/
|
1011
|
+
int OutputINChI2( char *pStr, int nStrLen, INCHI_SORT *pINChISortTautAndNonTaut2[][TAUT_NUM], int iINChI,
|
1012
|
+
ORIG_STRUCT *pOrigStruct,
|
1013
|
+
int bDisconnectedCoord, int bOutputType, int bINChIOutputOptions, int bXml, int bAbcNumbers,
|
1014
|
+
int bCtPredecessors, int bNoStructLabels,
|
1015
|
+
int num_components2[], int num_non_taut2[], int num_taut2[],
|
1016
|
+
INCHI_FILE *output_file, INCHI_FILE *log_file, int num_input_struct,
|
1017
|
+
const char *szSdfLabel, const char *szSdfValue, long lSdfId, int *pSortPrintINChIFlags )
|
1018
|
+
{
|
1019
|
+
int bINChIOutputOptions0 = bINChIOutputOptions & ~(INCHI_OUT_XML | INCHI_OUT_PLAIN_TEXT | INCHI_OUT_PLAIN_TEXT_COMMENTS);
|
1020
|
+
int bINChIOutputOptionsCur;
|
1021
|
+
int bCurOption, ret, i;
|
1022
|
+
|
1023
|
+
ret = 0;
|
1024
|
+
|
1025
|
+
for ( i = 0; i < 3; i ++ ) {
|
1026
|
+
switch( i ) {
|
1027
|
+
case 0:
|
1028
|
+
bCurOption = INCHI_OUT_XML;
|
1029
|
+
break;
|
1030
|
+
case 1:
|
1031
|
+
bCurOption = INCHI_OUT_PLAIN_TEXT;
|
1032
|
+
break;
|
1033
|
+
case 2:
|
1034
|
+
bCurOption = INCHI_OUT_PLAIN_TEXT_COMMENTS;
|
1035
|
+
break;
|
1036
|
+
default:
|
1037
|
+
continue;
|
1038
|
+
}
|
1039
|
+
if ( bINChIOutputOptions & bCurOption ) {
|
1040
|
+
bINChIOutputOptionsCur = bINChIOutputOptions0 | bCurOption;
|
1041
|
+
if ( i != 1 ) {
|
1042
|
+
bINChIOutputOptionsCur &= ~INCHI_OUT_TABBED_OUTPUT;
|
1043
|
+
}
|
1044
|
+
ret |= OutputINChI1( pStr, nStrLen, pINChISortTautAndNonTaut2, iINChI,
|
1045
|
+
pOrigStruct, bDisconnectedCoord, bOutputType, bINChIOutputOptionsCur, bXml, bAbcNumbers,
|
1046
|
+
bCtPredecessors, bNoStructLabels,
|
1047
|
+
num_components2, num_non_taut2, num_taut2,
|
1048
|
+
output_file, log_file, num_input_struct,
|
1049
|
+
szSdfLabel, szSdfValue, lSdfId, pSortPrintINChIFlags );
|
1050
|
+
}
|
1051
|
+
}
|
1052
|
+
return ret;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
/**********************************************************************************/
|
1056
|
+
char *szGetTag( const INCHI_TAG *Tag, int nTag, int bTag, char *szTag, int *bAlways )
|
1057
|
+
{
|
1058
|
+
int i, j, bit, num, len;
|
1059
|
+
if ( 0 < nTag && nTag < 3 ) {
|
1060
|
+
/* no plain text comments: pick up the last tag */
|
1061
|
+
for ( i = 0, j = -1, bit = 1; i < MAX_TAG_NUM; i ++, bit <<= 1 ) {
|
1062
|
+
if ( bTag & bit ) {
|
1063
|
+
j = i;
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
if ( j >= 0 ) {
|
1067
|
+
strcpy( szTag, nTag == 1? Tag[j].szXmlLabel : nTag == 2? Tag[j].szPlainLabel : "???" );
|
1068
|
+
if ( nTag != 2 ) {
|
1069
|
+
*bAlways = Tag[j].bAlwaysOutput;
|
1070
|
+
}
|
1071
|
+
return szTag;
|
1072
|
+
}
|
1073
|
+
} else
|
1074
|
+
if ( nTag == 3 ) {
|
1075
|
+
/* plain text with comments */
|
1076
|
+
szTag[0] = '{';
|
1077
|
+
szTag[1] = '\0';
|
1078
|
+
for ( i = 0, j = -1, bit = 1, num=0; i < MAX_TAG_NUM; i ++, bit <<= 1 ) {
|
1079
|
+
if ( bTag & bit ) {
|
1080
|
+
j = i;
|
1081
|
+
if ( num ++ ) {
|
1082
|
+
strcat( szTag, ":" );
|
1083
|
+
}
|
1084
|
+
strcat( szTag, Tag[i].szPlainComment );
|
1085
|
+
}
|
1086
|
+
}
|
1087
|
+
if ( num ) {
|
1088
|
+
strcat( szTag, "}" );
|
1089
|
+
num = strlen( Tag[j].szPlainLabel );
|
1090
|
+
len = strlen( szTag );
|
1091
|
+
if ( len ) {
|
1092
|
+
memmove( szTag + num, szTag, len+1 );
|
1093
|
+
memcpy( szTag, Tag[j].szPlainLabel, num );
|
1094
|
+
} else {
|
1095
|
+
strcpy ( szTag, Tag[j].szPlainLabel );
|
1096
|
+
}
|
1097
|
+
*bAlways = Tag[j].bAlwaysOutput;
|
1098
|
+
} else {
|
1099
|
+
strcpy( szTag, "???" );
|
1100
|
+
}
|
1101
|
+
return szTag;
|
1102
|
+
}
|
1103
|
+
strcpy( szTag, "???" );
|
1104
|
+
return szTag;
|
1105
|
+
}
|
1106
|
+
|
1107
|
+
|
1108
|
+
/**********************************************************************************************/
|
1109
|
+
/* sorting in descending order: return -1 if *p1 > *p2, return +1 if *p1 < *p2 */
|
1110
|
+
/**********************************************************************************************/
|
1111
|
+
int OutputINChI1( char *pStr, int nStrLen, INCHI_SORT *pINChISortTautAndNonTaut2[][TAUT_NUM], int iINChI,
|
1112
|
+
ORIG_STRUCT *pOrigStruct,
|
1113
|
+
int bDisconnectedCoord, int bOutputType, int bINChIOutputOptions, int bXml, int bAbcNumbers,
|
1114
|
+
int bCtPredecessors, int bNoStructLabels,
|
1115
|
+
int num_components2[], int num_non_taut2[], int num_taut2[],
|
1116
|
+
INCHI_FILE *output_file, INCHI_FILE *log_file, int num_input_struct,
|
1117
|
+
const char *szSdfLabel, const char *szSdfValue, long lSdfId, int *pSortPrintINChIFlags )
|
1118
|
+
{
|
1119
|
+
/*
|
1120
|
+
bINChIOutputOptions bits:
|
1121
|
+
|
1122
|
+
INCHI_OUT_NO_AUX_INFO 0x0001 do not output Aux Info
|
1123
|
+
INCHI_OUT_SHORT_AUX_INFO 0x0002 output short version of Aux Info
|
1124
|
+
INCHI_OUT_ONLY_AUX_INFO 0x0004 output only Aux Info
|
1125
|
+
INCHI_OUT_EMBED_REC 0x0008 embed reconnected INChI into disconnected INChI
|
1126
|
+
|
1127
|
+
*/
|
1128
|
+
/*int ATOM_MODE = ((bAbcNumbers?2:0)|5|(bCtPredecessors?8:0));*/
|
1129
|
+
int ATOM_MODE = ((bAbcNumbers?CT_MODE_ABC_NUMBERS:0)
|
1130
|
+
| CT_MODE_ATOM_COUNTS
|
1131
|
+
| CT_MODE_NO_ORPHANS
|
1132
|
+
#if( EQL_H_NUM_TOGETHER == 1 )
|
1133
|
+
| CT_MODE_EQL_H_TOGETHER
|
1134
|
+
#endif
|
1135
|
+
#if( ABC_CT_NUM_CLOSURES == 1 )
|
1136
|
+
| (bAbcNumbers && bCtPredecessors? CT_MODE_ABC_NUM_CLOSURES:0)
|
1137
|
+
#endif
|
1138
|
+
| (bCtPredecessors?CT_MODE_PREDECESSORS:0));
|
1139
|
+
|
1140
|
+
int TAUT_MODE = (bAbcNumbers?CT_MODE_ABC_NUMBERS:0);
|
1141
|
+
char sDifSegs[DIFL_LENGTH][DIFS_LENGTH];
|
1142
|
+
/* bOutputType =
|
1143
|
+
TAUT_YES => tautomeric only (if no tautomeric components then no output;
|
1144
|
+
TAUT_NON => only non-tautomeric output (if no non-taut present then no output;
|
1145
|
+
TAUT_BOTH => tautomeric and non-tautomeric */
|
1146
|
+
|
1147
|
+
int i, j, ii, jj, /*ii2, jj2,*/ tot_len, tot_len2, bOverflow, bEmbeddedOutputCalled=0;
|
1148
|
+
int bIsotopic, bTautIsoHNum, bTautIsoAt, bHasIsotopicAtoms[TAUT_NUM];
|
1149
|
+
int bStereoSp2[TAUT_NUM], bStereoSp3[TAUT_NUM];
|
1150
|
+
int bIsotopicStereoSp2[TAUT_NUM], bIsotopicStereoSp3[TAUT_NUM];
|
1151
|
+
int bStereoAbsInverted[TAUT_NUM], bIsotopicStereoAbsInverted[TAUT_NUM];
|
1152
|
+
int bStereoAbs[TAUT_NUM], bIsotopicStereoAbs[TAUT_NUM];
|
1153
|
+
int bAtomEqu[TAUT_NUM], bTautEqu[TAUT_NUM], bIsotopicAtomEqu[TAUT_NUM], bIsotopicTautEqu[TAUT_NUM];
|
1154
|
+
int bInvStereo[TAUT_NUM], bInvIsotopicStereo[TAUT_NUM];
|
1155
|
+
int bInvStereoOrigNumb[TAUT_NUM], bInvIsotopicStereoOrigNumb[TAUT_NUM], bIsotopicOrigNumb[TAUT_NUM];
|
1156
|
+
int bTautomeric, bNonTautomeric, bTautomericAcid, bHardAddRemProton, iCurTautMode;
|
1157
|
+
int bRequestedRacemicStereo=0, bRequestedRelativeStereo = 0, bRelRac;
|
1158
|
+
int bRacemicStereo[TAUT_NUM], bRelativeStereo[TAUT_NUM];
|
1159
|
+
int bIsotopicRacemicStereo[TAUT_NUM], bIsotopicRelativeStereo[TAUT_NUM];
|
1160
|
+
int bChargesRadVal[TAUT_NUM], bOrigCoord[TAUT_NUM];
|
1161
|
+
int bIgn_UU_Sp3[TAUT_NUM], bIgn_UU_Sp2[TAUT_NUM];
|
1162
|
+
int bIgn_UU_Sp3_Iso[TAUT_NUM], bIgn_UU_Sp2_Iso[TAUT_NUM];
|
1163
|
+
int ind, inc, bNonTautIsIdenticalToTaut = 1;
|
1164
|
+
int bNonTautNonIsoIdentifierNotEmpty = 0, bNonTautIsoIdentifierNotEmpty = 0;
|
1165
|
+
INCHI_SORT **pINChISortTautAndNonTaut = pINChISortTautAndNonTaut2[iINChI];
|
1166
|
+
INCHI_SORT *pINChISort =pINChISortTautAndNonTaut[TAUT_YES];
|
1167
|
+
INCHI_SORT *pINChISort2=pINChISortTautAndNonTaut[TAUT_YES];
|
1168
|
+
INCHI_SORT *is, *is2;
|
1169
|
+
INChI *pINChI /*, *pINChI2*/;
|
1170
|
+
INChI_Aux *pINChI_Aux = NULL;
|
1171
|
+
|
1172
|
+
int ret = 0; /* 0=>failed, 1=>success */
|
1173
|
+
int bOutType = bOutputType; /* ??? */
|
1174
|
+
int nTag;
|
1175
|
+
int bTautomericOutputAllowed, bSecondNonTautPass;
|
1176
|
+
int num_components = num_components2[iINChI];
|
1177
|
+
int num_comp[TAUT_NUM], max_num_comp;
|
1178
|
+
int num_iso_H[NUM_H_ISOTOPES], bHasIsoH;
|
1179
|
+
int nNumRemovedProtons, nNumMovedProtons;
|
1180
|
+
int bTautAndNonTaut, bTautIsNonTaut;
|
1181
|
+
|
1182
|
+
int bAlways = 0;
|
1183
|
+
int bUseMulipliers = 1;
|
1184
|
+
int bOmitRepetitions = 1;
|
1185
|
+
int bPlainTextTags = 2; /* 0 => no plain tags, 1=> plain text tags, 2=>plaintext tags without consecutive // */
|
1186
|
+
int bPlainText = 0 != (bINChIOutputOptions & (INCHI_OUT_PLAIN_TEXT | INCHI_OUT_PLAIN_TEXT_COMMENTS));
|
1187
|
+
int bPlainTextCommnts = 0 != (bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT_COMMENTS);
|
1188
|
+
int bPlainTabbedOutput;
|
1189
|
+
int bTag1, bTag2, bTag3, bFhTag; /* tag bits */
|
1190
|
+
int nCurINChISegment, nSegmAction;
|
1191
|
+
char szTag1[MAX_TAG_LEN], szTag2[MAX_TAG_LEN], szTag3[MAX_TAG_LEN];
|
1192
|
+
const char *pLF, *pTAB;
|
1193
|
+
bXml = 0 != (bINChIOutputOptions & INCHI_OUT_XML);
|
1194
|
+
nTag = bPlainTextCommnts? 3 : bPlainText? 2 : bXml? 1 : 0; /* tag type */
|
1195
|
+
ind = bXml? 1 : -1;
|
1196
|
+
inc = bXml? 1 : -1;
|
1197
|
+
pLF = bPlainTextCommnts? "\n" : "\0";
|
1198
|
+
bFhTag = 0;
|
1199
|
+
bPlainTabbedOutput = 0 != (bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT) &&
|
1200
|
+
bPlainText && !bXml && !bPlainTextCommnts;
|
1201
|
+
#if ( !defined(INCHI_LIBRARY) && !defined(INCHI_LIB) )
|
1202
|
+
pTAB = bPlainTabbedOutput? "\t" : "\n";
|
1203
|
+
#else
|
1204
|
+
pTAB = "\n";
|
1205
|
+
#endif
|
1206
|
+
|
1207
|
+
memset( sDifSegs, DIFV_BOTH_EMPTY, sizeof(sDifSegs) );
|
1208
|
+
|
1209
|
+
if ( !pStr ) {
|
1210
|
+
my_fprintf( log_file, "Cannot allocate output buffer. No output for structure #%d.%s%s%s%s\n", num_input_struct, SDF_LBL_VAL(szSdfLabel, szSdfValue) );
|
1211
|
+
return ret;
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
bSecondNonTautPass = 0;
|
1215
|
+
/* -- commented out to allow empty InChI --
|
1216
|
+
if (!num_components ) {
|
1217
|
+
return 0;
|
1218
|
+
}
|
1219
|
+
*/
|
1220
|
+
/* init version string */
|
1221
|
+
if ( !VER_STRING[0] ) {
|
1222
|
+
strcpy(VER_STRING, "(V");
|
1223
|
+
strcat(VER_STRING, INCHI_VERSION);
|
1224
|
+
strcat(VER_STRING, ")");
|
1225
|
+
}
|
1226
|
+
for ( i = 0; i < TAUT_NUM; i ++ ) {
|
1227
|
+
bHasIsotopicAtoms[i] = num_comp[i] =
|
1228
|
+
bStereoSp2[i] = bStereoSp3[i] =
|
1229
|
+
bIsotopicStereoSp2[i] = bIsotopicStereoSp3[i] =
|
1230
|
+
bIsotopicOrigNumb[i] =
|
1231
|
+
bStereoAbs[i] = bIsotopicStereoAbs[i] =
|
1232
|
+
bStereoAbsInverted[i] = bIsotopicStereoAbsInverted[i] =
|
1233
|
+
bRacemicStereo[i] = bRelativeStereo[i] =
|
1234
|
+
bIsotopicRacemicStereo[i] = bIsotopicRelativeStereo[i] =
|
1235
|
+
bAtomEqu[i] = bTautEqu[i] =
|
1236
|
+
bIsotopicAtomEqu[i] = bIsotopicTautEqu[i] =
|
1237
|
+
bInvStereo[i] = bInvIsotopicStereo[i] =
|
1238
|
+
bInvStereoOrigNumb[i] = bInvIsotopicStereoOrigNumb[i] =
|
1239
|
+
bIgn_UU_Sp3[i] = bIgn_UU_Sp2[i] =
|
1240
|
+
bIgn_UU_Sp3_Iso[i] = bIgn_UU_Sp2_Iso[i] =
|
1241
|
+
bChargesRadVal[i] = bOrigCoord[i] = 0;
|
1242
|
+
}
|
1243
|
+
/* find if it is isotopic */
|
1244
|
+
bIsotopic = bTautomeric = bNonTautomeric =
|
1245
|
+
bTautomericAcid = bHardAddRemProton = bTautIsoHNum = bTautIsoAt = 0;
|
1246
|
+
bTautAndNonTaut = bTautIsNonTaut = 0;
|
1247
|
+
/*
|
1248
|
+
x = bStereo, bStereoSp2, bStereoSp3, bStereoAbsInverted,
|
1249
|
+
bIsotopicStereo, bIsotopicStereoSp2, bIsotopicStereoSp3, bIsotopicStereoAbsInverted
|
1250
|
+
|
1251
|
+
OUT_N1: x[TAUT_NON] refers to non-tautomeric only
|
1252
|
+
OUT_T1: x[TAUT_YES] refers to tautomeric if exists otherwise non-tautomeric
|
1253
|
+
OUT_NT: x[TAUT_NON] refers to non-taut representations of tautomeric
|
1254
|
+
OUT_TN: x[TAUT_YES] refers to tautomeric if exists otherwise non-tautomeric
|
1255
|
+
x[TAUT_NON] refers to non-taut representations of tautomeric
|
1256
|
+
*/
|
1257
|
+
|
1258
|
+
memset( num_iso_H, 0, sizeof(num_iso_H) );
|
1259
|
+
nNumRemovedProtons = 0;
|
1260
|
+
nNumMovedProtons = 0;
|
1261
|
+
bHasIsoH = 0;
|
1262
|
+
bTautomericOutputAllowed = (bOutType==OUT_T1 || bOutType== OUT_TN);
|
1263
|
+
pINChISort=pINChISortTautAndNonTaut[bTautomericOutputAllowed? TAUT_YES : TAUT_NON];
|
1264
|
+
is = pINChISort;
|
1265
|
+
is2 = (bOutType== OUT_TN)? pINChISortTautAndNonTaut[TAUT_NON] : NULL;
|
1266
|
+
for ( i = 0, is2 = pINChISortTautAndNonTaut[TAUT_NON]; i < num_components; i ++, is ++, is2? is2++:NULL ) {
|
1267
|
+
CompINChILayers( is, is2, sDifSegs );
|
1268
|
+
bNonTautIsIdenticalToTaut = bNonTautIsIdenticalToTaut && !CompINChITautVsNonTaut(is, is2, 1);
|
1269
|
+
if ( is && (pINChI_Aux = is->pINChI_Aux[TAUT_YES]) ) {
|
1270
|
+
for ( j = 0; j < NUM_H_ISOTOPES; j ++ ) {
|
1271
|
+
bHasIsoH += abs(pINChI_Aux->nNumRemovedIsotopicH[j]);
|
1272
|
+
num_iso_H[j] += pINChI_Aux->nNumRemovedIsotopicH[j];
|
1273
|
+
}
|
1274
|
+
nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
|
1275
|
+
nNumMovedProtons += abs(pINChI_Aux->nNumRemovedProtons);
|
1276
|
+
}
|
1277
|
+
if ( bTautomericOutputAllowed ) {
|
1278
|
+
/* check for removed isotopic H */
|
1279
|
+
for ( j = TAUT_YES; j < TAUT_NUM; j ++ ) {
|
1280
|
+
switch ( bOutType ) {
|
1281
|
+
case OUT_N1: /* x[TAUT_NON]: non-tautomeric only -- never happens */
|
1282
|
+
jj = GET_II(bOutType,is);
|
1283
|
+
if ( jj != j )
|
1284
|
+
continue;
|
1285
|
+
ii = TAUT_NON;
|
1286
|
+
break;
|
1287
|
+
case OUT_T1: /* x[TAUT_YES]: tautomeric if present otherwise non-tautomeric */
|
1288
|
+
jj = GET_II(bOutType,is);
|
1289
|
+
if ( jj != j )
|
1290
|
+
continue;
|
1291
|
+
ii = TAUT_YES;
|
1292
|
+
break;
|
1293
|
+
case OUT_NT: /* x[TAUT_NON]: only non-taut representations of tautomeric -- never happens */
|
1294
|
+
jj = GET_II(bOutType,is);
|
1295
|
+
if ( jj != j )
|
1296
|
+
continue;
|
1297
|
+
ii = TAUT_NON;
|
1298
|
+
break;
|
1299
|
+
/* main path of control flow */
|
1300
|
+
case OUT_TN: /* x[TAUT_YES]: tautomeric if present otherwise non-tautomeric;
|
1301
|
+
* x[TAUT_NON]: non-taut only if tautomeric is present */
|
1302
|
+
jj = ( j == TAUT_YES )? GET_II(OUT_T1,is) : ( j == TAUT_NON )? GET_II(OUT_NT,is) : -1;
|
1303
|
+
if ( jj == TAUT_YES ) { /* Fix12 */
|
1304
|
+
if ( is->pINChI[jj]->lenTautomer > 0 ) {
|
1305
|
+
bTautAndNonTaut += (!is->pINChI[jj]->bDeleted && HAS_N(is));
|
1306
|
+
} else {
|
1307
|
+
bTautIsNonTaut ++;
|
1308
|
+
}
|
1309
|
+
}
|
1310
|
+
if ( jj < 0 )
|
1311
|
+
continue;
|
1312
|
+
ii = j;
|
1313
|
+
break;
|
1314
|
+
default:
|
1315
|
+
continue;
|
1316
|
+
}
|
1317
|
+
if ( jj != j )
|
1318
|
+
continue;
|
1319
|
+
if ( (pINChI = is->pINChI[jj]) && pINChI->nNumberOfAtoms > 0 && (pINChI_Aux = is->pINChI_Aux[jj]) ) {
|
1320
|
+
bTautIsoHNum += (pINChI_Aux->nNumRemovedIsotopicH[0] +
|
1321
|
+
pINChI_Aux->nNumRemovedIsotopicH[1] +
|
1322
|
+
pINChI_Aux->nNumRemovedIsotopicH[2]);
|
1323
|
+
bTautIsoAt += (pINChI->nNumberOfIsotopicAtoms>0 || pINChI->nNumberOfIsotopicTGroups > 0 );
|
1324
|
+
}
|
1325
|
+
}
|
1326
|
+
}
|
1327
|
+
}
|
1328
|
+
sDifSegs[DIFL_M ][DIFS_p_PROTONS] = nNumRemovedProtons? DIFV_NEQ2PRECED : DIFV_BOTH_EMPTY;
|
1329
|
+
sDifSegs[DIFL_MI][DIFS_h_H_ATOMS] = bHasIsoH? DIFV_NEQ2PRECED : DIFV_BOTH_EMPTY;
|
1330
|
+
|
1331
|
+
MarkUnusedAndEmptyLayers( sDifSegs );
|
1332
|
+
|
1333
|
+
|
1334
|
+
|
1335
|
+
|
1336
|
+
bNonTautIsIdenticalToTaut = bNonTautIsIdenticalToTaut && !bTautIsoHNum;
|
1337
|
+
/*********************************************************************************************/
|
1338
|
+
for ( i = 0, is = pINChISort; i < num_components; i ++, is ++ )
|
1339
|
+
{
|
1340
|
+
int bCurIso, bCurStereo, bCurIsoStereo, bCurHasIsoStereo /* Fix14 */, bCurTaut /*, bCurTaut2*/;
|
1341
|
+
int bCompExists, bCurIsoHPos, bCurIsoHStereo;
|
1342
|
+
int bCurStereoSp2, bCurIsoStereoSp2, bCurStereoSp3, bCurIsoStereoSp3, bCurIsoStereoSp3Inv;
|
1343
|
+
int bCurRacemic, bCurRelative, bCurIsoRacemic, bCurIsoRelative;
|
1344
|
+
bCompExists = 0;
|
1345
|
+
for ( j = TAUT_NON; j < TAUT_NUM; j ++ ) {
|
1346
|
+
switch ( bOutType ) {
|
1347
|
+
case OUT_N1: /* x[TAUT_NON]: non-tautomeric only */
|
1348
|
+
jj = GET_II(bOutType,is);
|
1349
|
+
if ( jj != j )
|
1350
|
+
continue;
|
1351
|
+
ii = TAUT_NON;
|
1352
|
+
break;
|
1353
|
+
case OUT_T1: /* x[TAUT_YES]: tautomeric if present otherwise non-tautomeric */
|
1354
|
+
jj = GET_II(bOutType,is);
|
1355
|
+
if ( jj != j )
|
1356
|
+
continue;
|
1357
|
+
ii = TAUT_YES;
|
1358
|
+
break;
|
1359
|
+
case OUT_NT: /* x[TAUT_NON]: only non-taut representations of tautomeric */
|
1360
|
+
jj = GET_II(bOutType,is);
|
1361
|
+
if ( jj != j )
|
1362
|
+
continue;
|
1363
|
+
ii = TAUT_NON;
|
1364
|
+
break;
|
1365
|
+
/* main control flow comes here: requested both mobile and fixed H results */
|
1366
|
+
case OUT_TN: /* x[TAUT_YES]: tautomeric if present otherwise non-tautomeric;
|
1367
|
+
* x[TAUT_NON]: non-taut only if tautomeric is present */
|
1368
|
+
jj = ( j == TAUT_YES )? GET_II(OUT_T1,is) : ( j == TAUT_NON )? GET_II(OUT_NT,is) : -1;
|
1369
|
+
if ( jj < 0 ) {
|
1370
|
+
/* Fix12 */
|
1371
|
+
if ( bTautAndNonTaut && bTautIsNonTaut &&
|
1372
|
+
j == TAUT_NON && 0 <= (jj = GET_II(OUT_T1,is)) &&
|
1373
|
+
!is->pINChI[jj]->bDeleted && !is->pINChI[jj]->lenTautomer ) {
|
1374
|
+
; /* the requested non-tautomeric component is in tautomeric position
|
1375
|
+
(is->pINChI[TAUT_YES]);
|
1376
|
+
process it also as non-tautomeric if Fixed-H layer was requested */
|
1377
|
+
} else {
|
1378
|
+
continue;
|
1379
|
+
}
|
1380
|
+
}
|
1381
|
+
ii = j; /* ii is what we wanted; jj is what we found (0 = TAUT_NON: fixed_H, 1 = TAUT_YES: mobile_H) */
|
1382
|
+
/* -- not used 2004-09-16 ---
|
1383
|
+
if ( is2 ) {
|
1384
|
+
jj2 = ( j == TAUT_YES )? GET_II(OUT_T1,is2) : ( j == TAUT_NON )? GET_II(OUT_NT,is2) : -1;
|
1385
|
+
if ( jj2 >= 0 ) {
|
1386
|
+
ii2 = j;
|
1387
|
+
} else {
|
1388
|
+
ii2 = -1;
|
1389
|
+
}
|
1390
|
+
} else {
|
1391
|
+
jj2 = ii2 = -1;
|
1392
|
+
}
|
1393
|
+
-----------------------------*/
|
1394
|
+
break;
|
1395
|
+
default:
|
1396
|
+
continue;
|
1397
|
+
}
|
1398
|
+
if ( (pINChI = is->pINChI[jj]) && pINChI->nNumberOfAtoms > 0 ) {
|
1399
|
+
/*pINChI_Aux = is->pINChI_Aux[jj];*/
|
1400
|
+
bCompExists ++;
|
1401
|
+
bCurTaut = (pINChI->lenTautomer > 0);
|
1402
|
+
bCurIso = (pINChI->nNumberOfIsotopicAtoms>0 || pINChI->nNumberOfIsotopicTGroups > 0 );
|
1403
|
+
bCurIsoHPos = (pINChI->nPossibleLocationsOfIsotopicH && pINChI->nPossibleLocationsOfIsotopicH[0] > 1 || pINChI->lenTautomer > 1);
|
1404
|
+
/* present isotopic H + their possible positions AND/OR isotopic atoms */
|
1405
|
+
bCurIsoHStereo = bCurIsoHPos && (bTautIsoHNum || bTautIsoAt) || bCurIso;
|
1406
|
+
if ( jj == j && pINChI->bDeleted ) {
|
1407
|
+
num_comp[j] --;
|
1408
|
+
if ( bCurTaut ) {
|
1409
|
+
bTautomeric |= 1; /* tautomeric representation is present */
|
1410
|
+
bNonTautomeric |= HAS_N(is);
|
1411
|
+
}
|
1412
|
+
bIsotopic |= bCurIso;
|
1413
|
+
continue; /* deleted H(+) in tautomeric representation */
|
1414
|
+
}
|
1415
|
+
bCurStereoSp2 = pINChI->Stereo && (pINChI->Stereo->nNumberOfStereoBonds > 0);
|
1416
|
+
bCurHasIsoStereo =
|
1417
|
+
bCurStereoSp3 = pINChI->Stereo && (pINChI->Stereo->nNumberOfStereoCenters > 0 );
|
1418
|
+
bCurIsoStereoSp2 = bCurIsoHStereo && pINChI->StereoIsotopic && (pINChI->StereoIsotopic->nNumberOfStereoBonds > 0);
|
1419
|
+
bCurIsoStereoSp3 = bCurIsoHStereo && pINChI->StereoIsotopic && (pINChI->StereoIsotopic->nNumberOfStereoCenters > 0);
|
1420
|
+
bCurIsoStereoSp3Inv = bCurIsoStereoSp3 && pINChI->StereoIsotopic->nCompInv2Abs; /* inversion changes sp3 stereo */
|
1421
|
+
bRequestedRacemicStereo |= (0!=(pINChI->nFlags & INCHI_FLAG_RAC_STEREO));
|
1422
|
+
bRequestedRelativeStereo |= (0!=(pINChI->nFlags & INCHI_FLAG_REL_STEREO));
|
1423
|
+
/* check whether isotopic stereo is same as non-isotopic; if same than do not output isotopic stereo */
|
1424
|
+
if ( bCurStereoSp2 && bCurIsoStereoSp2 ) {
|
1425
|
+
bCurIsoStereoSp2 = !Eql_INChI_Stereo( pINChI->Stereo, EQL_SP2, pINChI->StereoIsotopic, EQL_SP2, 0 );
|
1426
|
+
}
|
1427
|
+
if ( bCurStereoSp3 && bCurIsoStereoSp3 ) {
|
1428
|
+
/* bCurIsoStereoSp3=0 means (iso stereo sp3) = (non-iso stereo sp3) or (iso stereo sp3) = Inv(non-iso stereo sp3) */
|
1429
|
+
bCurIsoStereoSp3 = !Eql_INChI_Stereo( pINChI->Stereo, EQL_SP3, pINChI->StereoIsotopic, EQL_SP3,
|
1430
|
+
(pINChI->nFlags & INCHI_FLAG_RAC_STEREO) || (pINChI->nFlags & INCHI_FLAG_REL_STEREO) );
|
1431
|
+
if ( !bCurIsoStereoSp3 ) {
|
1432
|
+
/* inversion changes iso sp3 differently from non-iso sp3 Fix11 */
|
1433
|
+
bCurIsoStereoSp3Inv &= (pINChI->StereoIsotopic->nCompInv2Abs != pINChI->Stereo->nCompInv2Abs);
|
1434
|
+
}
|
1435
|
+
}
|
1436
|
+
|
1437
|
+
bCurRelative = bRequestedRelativeStereo && bCurStereoSp3;
|
1438
|
+
#if( REL_RAC_STEREO_IGN_1_SC == 1 )
|
1439
|
+
bCurRelative = bCurRelative &&
|
1440
|
+
(pINChI->Stereo->nNumberOfStereoCenters > 1 ) &&
|
1441
|
+
(pINChI->Stereo->nCompInv2Abs != 0) &&
|
1442
|
+
#endif
|
1443
|
+
|
1444
|
+
|
1445
|
+
|
1446
|
+
bCurIsoRelative = bRequestedRelativeStereo && (bCurIsoStereoSp3 || bCurIsoStereoSp3Inv);
|
1447
|
+
#if( REL_RAC_STEREO_IGN_1_SC == 1 )
|
1448
|
+
bCurIsoRelative = bCurIsoRelative &&
|
1449
|
+
(pINChI->StereoIsotopic->nNumberOfStereoCenters > 1 ) &&
|
1450
|
+
(pINChI->StereoIsotopic->nCompInv2Abs != 0) &&
|
1451
|
+
#endif
|
1452
|
+
|
1453
|
+
|
1454
|
+
bCurRacemic = bRequestedRacemicStereo && bCurStereoSp3;
|
1455
|
+
#if( REL_RAC_STEREO_IGN_1_SC == 1 )
|
1456
|
+
bCurRacemic = bCurRacemic &&
|
1457
|
+
(pINChI->Stereo->nCompInv2Abs != 0) &&
|
1458
|
+
(pINChI->Stereo->nNumberOfStereoCenters > 0 ) ?
|
1459
|
+
pINChI->Stereo->nNumberOfStereoCenters : 0;
|
1460
|
+
#endif
|
1461
|
+
|
1462
|
+
bCurIsoRacemic = bRequestedRacemicStereo && (bCurIsoStereoSp3 || bCurIsoStereoSp3Inv);
|
1463
|
+
#if( REL_RAC_STEREO_IGN_1_SC == 1 )
|
1464
|
+
bCurIsoRacemic = bCurIsoRacemic &
|
1465
|
+
(pINChI->StereoIsotopic->nCompInv2Abs != 0) &&
|
1466
|
+
(pINChI->StereoIsotopic->nNumberOfStereoCenters > 0 ) ?
|
1467
|
+
pINChI->StereoIsotopic->nNumberOfStereoCenters : 0;
|
1468
|
+
#endif
|
1469
|
+
if ( bRequestedRelativeStereo ) {
|
1470
|
+
bCurStereoSp3 = bCurRelative || bCurStereoSp3 && (pINChI->Stereo->nNumberOfStereoCenters > 1 ); /* Fix11 */
|
1471
|
+
bCurIsoStereoSp3 = bCurIsoRelative ? bCurIsoStereoSp3 : 0;
|
1472
|
+
} else
|
1473
|
+
if ( bRequestedRacemicStereo ) {
|
1474
|
+
bCurStereoSp3 = bCurRacemic > 1 || bCurStereoSp3 && (pINChI->Stereo->nNumberOfStereoCenters > 1 ); /* Fix11 */
|
1475
|
+
bCurIsoStereoSp3 = bCurIsoRacemic > 1? bCurIsoStereoSp3 : 0;
|
1476
|
+
}
|
1477
|
+
bCurStereo = bCurStereoSp2 || bCurStereoSp3;
|
1478
|
+
bCurIsoStereo = bCurIsoStereoSp2 || bCurIsoStereoSp3;
|
1479
|
+
|
1480
|
+
bIsotopic |= bCurIso;
|
1481
|
+
bHasIsotopicAtoms[ii] |= bCurIso;
|
1482
|
+
bStereoSp2[ii] |= bCurStereoSp2;
|
1483
|
+
bStereoSp3[ii] |= bCurStereoSp3;
|
1484
|
+
bIgn_UU_Sp3[ii] |= !bCurStereoSp3 && (pINChI->nFlags & INCHI_FLAG_SC_IGN_ALL_UU);
|
1485
|
+
bIgn_UU_Sp2[ii] |= !bCurStereoSp2 && (pINChI->nFlags & INCHI_FLAG_SB_IGN_ALL_UU);
|
1486
|
+
bIsotopicStereoSp2[ii] |= bCurIsoStereoSp2;
|
1487
|
+
bIsotopicStereoSp3[ii] |= bCurIsoStereoSp3;
|
1488
|
+
bIgn_UU_Sp3_Iso[ii] |= !bCurIsoStereoSp3 && (pINChI->nFlags & INCHI_FLAG_SC_IGN_ALL_ISO_UU);
|
1489
|
+
bIgn_UU_Sp2_Iso[ii] |= !bCurIsoStereoSp2 && (pINChI->nFlags & INCHI_FLAG_SB_IGN_ALL_ISO_UU);
|
1490
|
+
bStereoAbs[ii] |= bCurStereoSp3 && (pINChI->Stereo->nCompInv2Abs != 0);
|
1491
|
+
bStereoAbsInverted[ii] |= bCurStereoSp3 && (pINChI->Stereo->nCompInv2Abs < 0);
|
1492
|
+
/* Fix08: missing isotopic inverted flag if isotopic = inverted non-isotopic */
|
1493
|
+
bIsotopicStereoAbsInverted[ii] |= bCurIsoStereoSp3 && (pINChI->StereoIsotopic->nCompInv2Abs < 0) ||
|
1494
|
+
!bCurIsoStereoSp3 && pINChI->StereoIsotopic && pINChI->Stereo &&
|
1495
|
+
pINChI->StereoIsotopic->nCompInv2Abs &&
|
1496
|
+
pINChI->StereoIsotopic->nCompInv2Abs != pINChI->Stereo->nCompInv2Abs;
|
1497
|
+
/* Fix 11: missing /s1 if only isotopic stereo is inverted */
|
1498
|
+
bIsotopicStereoAbs[ii] |= bCurIsoStereoSp3 && (pINChI->StereoIsotopic->nCompInv2Abs != 0) ||
|
1499
|
+
!bCurIsoStereoSp3 && pINChI->StereoIsotopic && pINChI->Stereo &&
|
1500
|
+
pINChI->StereoIsotopic->nCompInv2Abs &&
|
1501
|
+
pINChI->StereoIsotopic->nCompInv2Abs != pINChI->Stereo->nCompInv2Abs;
|
1502
|
+
|
1503
|
+
bRelativeStereo[ii] |= bCurRelative;
|
1504
|
+
bIsotopicRelativeStereo[ii] |= bCurIsoRelative;
|
1505
|
+
bRacemicStereo[ii] |= bCurRacemic;
|
1506
|
+
bIsotopicRacemicStereo[ii] |= bCurIsoRacemic;
|
1507
|
+
|
1508
|
+
bTautomericAcid |= (0!=(pINChI->nFlags & INCHI_FLAG_ACID_TAUT));
|
1509
|
+
bHardAddRemProton |= (0!=(pINChI->nFlags & INCHI_FLAG_HARD_ADD_REM_PROTON));
|
1510
|
+
if ( bCurTaut ) {
|
1511
|
+
bTautomeric |= 1; /* tautomeric representation is present */
|
1512
|
+
/* does tautomeric structure have also a non-tautomeric repesentation? */
|
1513
|
+
bNonTautomeric |= HAS_N(is);
|
1514
|
+
}
|
1515
|
+
|
1516
|
+
/* auxiliary info */
|
1517
|
+
if ( !(bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) && (pINChI_Aux = is->pINChI_Aux[jj]) ) {
|
1518
|
+
/* detect presence of constitutional equivalence onfo */
|
1519
|
+
int bCurEqu, bCurTautEqu=0, bCurIsoEqu=0, bCurIsoTautEqu=0; /* Fix15-disabled */
|
1520
|
+
bAtomEqu[ii] |= (bCurEqu = bHasEquString( pINChI_Aux->nConstitEquNumbers,
|
1521
|
+
pINChI_Aux->nNumberOfAtoms));
|
1522
|
+
if ( bCurTaut ) {
|
1523
|
+
bTautEqu[ii] |= (bCurTautEqu = bHasEquString( pINChI_Aux->nConstitEquTGroupNumbers,
|
1524
|
+
pINChI_Aux->nNumberOfTGroups));
|
1525
|
+
}
|
1526
|
+
if ( bCurIso ) {
|
1527
|
+
bIsotopicAtomEqu[ii] |= (bCurIsoEqu = bHasEquString( pINChI_Aux->nConstitEquIsotopicNumbers,
|
1528
|
+
pINChI_Aux->nNumberOfAtoms)) /*|| bCurEqu*/;
|
1529
|
+
if ( bCurTaut ) {
|
1530
|
+
bIsotopicTautEqu[ii] |= (bCurIsoTautEqu = bHasEquString( pINChI_Aux->nConstitEquIsotopicTGroupNumbers,
|
1531
|
+
pINChI_Aux->nNumberOfTGroups)) /*|| bCurTautEqu*/;
|
1532
|
+
}
|
1533
|
+
/* non-zero if isotopic numbering for inverted isotopic stereo is different */
|
1534
|
+
bIsotopicOrigNumb[ii] |= bCurHasIsoStereo && /* Fix14 */
|
1535
|
+
pINChI_Aux->nOrigAtNosInCanonOrdInv &&
|
1536
|
+
pINChI_Aux->nIsotopicOrigAtNosInCanonOrd &&
|
1537
|
+
(0 != memcmp( pINChI_Aux->nOrigAtNosInCanonOrdInv,
|
1538
|
+
pINChI_Aux->nIsotopicOrigAtNosInCanonOrd,
|
1539
|
+
sizeof(pINChI_Aux->nOrigAtNosInCanonOrdInv[0])
|
1540
|
+
* pINChI_Aux->nNumberOfAtoms));
|
1541
|
+
|
1542
|
+
}
|
1543
|
+
/* inverted stereo */
|
1544
|
+
if ( bCurStereoSp3 && pINChI->Stereo->nCompInv2Abs ) {
|
1545
|
+
bInvStereo[ii] |= 1;
|
1546
|
+
bInvStereoOrigNumb[ii] |= pINChI_Aux->nOrigAtNosInCanonOrd &&
|
1547
|
+
pINChI_Aux->nOrigAtNosInCanonOrdInv &&
|
1548
|
+
(0 != memcmp( pINChI_Aux->nOrigAtNosInCanonOrd,
|
1549
|
+
pINChI_Aux->nOrigAtNosInCanonOrdInv,
|
1550
|
+
sizeof(pINChI_Aux->nOrigAtNosInCanonOrd[0])
|
1551
|
+
* pINChI_Aux->nNumberOfAtoms));
|
1552
|
+
}
|
1553
|
+
/* inverted isotopic stereo */
|
1554
|
+
if ( bCurIsoStereoSp3 && pINChI->StereoIsotopic->nCompInv2Abs ) {
|
1555
|
+
bInvIsotopicStereo[ii] |= 1;
|
1556
|
+
bInvIsotopicStereoOrigNumb[ii] |= pINChI_Aux->nIsotopicOrigAtNosInCanonOrd &&
|
1557
|
+
pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv &&
|
1558
|
+
(0 != memcmp( pINChI_Aux->nIsotopicOrigAtNosInCanonOrd,
|
1559
|
+
pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv,
|
1560
|
+
sizeof(pINChI_Aux->nIsotopicOrigAtNosInCanonOrd[0])
|
1561
|
+
* pINChI_Aux->nNumberOfAtoms));
|
1562
|
+
}
|
1563
|
+
if ( pINChI_Aux->OrigInfo && bHasOrigInfo(pINChI_Aux->OrigInfo, pINChI_Aux->nNumberOfAtoms) ) {
|
1564
|
+
bChargesRadVal[ii] |= 1;
|
1565
|
+
}
|
1566
|
+
}
|
1567
|
+
}
|
1568
|
+
}
|
1569
|
+
if ( bCompExists ) {
|
1570
|
+
for ( j = TAUT_NON; j < TAUT_NUM; j ++ ) {
|
1571
|
+
num_comp[j] ++;
|
1572
|
+
}
|
1573
|
+
}
|
1574
|
+
}
|
1575
|
+
if ( bTautomeric /*&& bTautomericAcid*/ ) { /* "&& bTautomericAcid" commented out 2004-06-02 */
|
1576
|
+
bTautomeric += bTautomericAcid; /* long-range tautomerism */
|
1577
|
+
bTautomeric += (bHardAddRemProton? 4 : 0);
|
1578
|
+
}
|
1579
|
+
if ( bRequestedRacemicStereo || bRequestedRelativeStereo ) {
|
1580
|
+
/* do not output inverted stereo info */
|
1581
|
+
for ( i = 0; i < TAUT_NUM; i ++ ) {
|
1582
|
+
/* Fix11 */
|
1583
|
+
bStereoAbsInverted[i] =
|
1584
|
+
bStereoAbs[i] =
|
1585
|
+
bInvStereo[i] =
|
1586
|
+
bInvStereoOrigNumb[i] = 0;
|
1587
|
+
/* bIsotopicRelativeStereo[i]=0 may happen because iso stereo is same or inverted non-iso stereo */
|
1588
|
+
bIsotopicStereoAbsInverted[i] =
|
1589
|
+
bIsotopicStereoAbs[i] =
|
1590
|
+
bInvIsotopicStereo[i] =
|
1591
|
+
bInvIsotopicStereoOrigNumb[i] = 0;
|
1592
|
+
/* -- commented out: Fix11--
|
1593
|
+
if ( bRacemicStereo[i] || bRelativeStereo[i] ) {
|
1594
|
+
bStereoAbsInverted[i] =
|
1595
|
+
bStereoAbs[i] =
|
1596
|
+
bInvStereo[i] =
|
1597
|
+
bInvStereoOrigNumb[i] = 0;
|
1598
|
+
}
|
1599
|
+
if ( bIsotopicRacemicStereo[i] || bIsotopicRelativeStereo[i] ) {
|
1600
|
+
bIsotopicStereoAbsInverted[i] =
|
1601
|
+
bIsotopicStereoAbs[i] =
|
1602
|
+
bInvIsotopicStereo[i] =
|
1603
|
+
bInvIsotopicStereoOrigNumb[i] = 0;
|
1604
|
+
}
|
1605
|
+
*/
|
1606
|
+
}
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
|
1610
|
+
iCurTautMode = bOutType == OUT_N1? TAUT_NON: /* only non-taut */
|
1611
|
+
bOutType == OUT_T1? TAUT_YES: /* tautomeric if present, otherwise non-tautomeric */
|
1612
|
+
bOutType == OUT_NT? TAUT_NON: /* only non-taut representations of tautomeric */
|
1613
|
+
bOutType == OUT_TN? TAUT_YES: /* tautomeric if present otherwise non-tautomeric; */
|
1614
|
+
-1; /* separately output non-taut representations of tautomeric if present */
|
1615
|
+
|
1616
|
+
if ( iCurTautMode < 0 ) {
|
1617
|
+
return 0; /* error */
|
1618
|
+
}
|
1619
|
+
|
1620
|
+
if ( bXml ) {
|
1621
|
+
ind += inc* (1+iINChI);
|
1622
|
+
}
|
1623
|
+
|
1624
|
+
bOverflow = 0;
|
1625
|
+
|
1626
|
+
num_components = num_comp[iCurTautMode];
|
1627
|
+
|
1628
|
+
max_num_comp = inchi_max(num_comp[TAUT_NON], num_comp[TAUT_YES]);
|
1629
|
+
|
1630
|
+
if ( bINChIOutputOptions & INCHI_OUT_ONLY_AUX_INFO ) {
|
1631
|
+
goto output_aux_info;
|
1632
|
+
}
|
1633
|
+
|
1634
|
+
nCurINChISegment = DIFL_M;
|
1635
|
+
|
1636
|
+
/******************************************
|
1637
|
+
*
|
1638
|
+
* Structure (Compound) Header
|
1639
|
+
*
|
1640
|
+
******************************************/
|
1641
|
+
if ( bXml ) {
|
1642
|
+
/* -- moved to the line above goto output_aux_info;
|
1643
|
+
ind += inc* (1+iINChI);
|
1644
|
+
*/
|
1645
|
+
/* basic title, version */
|
1646
|
+
if ( INCHI_BAS == iINChI ) {
|
1647
|
+
inchi_print( output_file, "\n" ); /* empty line */
|
1648
|
+
}
|
1649
|
+
tot_len = sprintf(pStr, "%s<%s %s=\"%s\"",
|
1650
|
+
SP(ind), x_basic, x_ver, x_curr_ver);
|
1651
|
+
if ( INCHI_REC == iINChI || INCHI_BAS == iINChI && bDisconnectedCoord ) {
|
1652
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%d\"", x_reconnected, iINChI );
|
1653
|
+
}
|
1654
|
+
if ( bAbcNumbers || bCtPredecessors ) {
|
1655
|
+
const char *pNumber = "";
|
1656
|
+
const char *pDelim = "";
|
1657
|
+
const char *pCtType = "";
|
1658
|
+
if ( bAbcNumbers && bCtPredecessors ) {
|
1659
|
+
pNumber = x_type_short;
|
1660
|
+
} else {
|
1661
|
+
pNumber = bAbcNumbers? x_type_alpha : x_type_numer;
|
1662
|
+
pDelim = (bAbcNumbers && bCtPredecessors)? "-":"";
|
1663
|
+
pCtType = bCtPredecessors? x_type_predec:"";
|
1664
|
+
}
|
1665
|
+
/* type */
|
1666
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%s%s%s\"", x_type, pNumber, pDelim, pCtType);
|
1667
|
+
}
|
1668
|
+
sprintf(pStr+tot_len,">");
|
1669
|
+
inchi_print( output_file, "%s\n", pStr );
|
1670
|
+
ind += inc;
|
1671
|
+
} else
|
1672
|
+
if ( INCHI_BAS == iINChI ) { /* eliminate empty line in plain text output */
|
1673
|
+
if ( bNoStructLabels ) {
|
1674
|
+
;
|
1675
|
+
/* -- removed empty line before InChI ---
|
1676
|
+
#ifndef INCHI_LIBRARY
|
1677
|
+
inchi_print( output_file, "\n" );
|
1678
|
+
#else
|
1679
|
+
;
|
1680
|
+
#endif
|
1681
|
+
*/
|
1682
|
+
} else
|
1683
|
+
if ( !(szSdfLabel && szSdfLabel[0]) && !(szSdfValue && szSdfValue[0]) ) {
|
1684
|
+
tot_len = sprintf( pStr, "%sStructure: %d", pLF, num_input_struct );
|
1685
|
+
inchi_print( output_file, "%s%s", pStr, pTAB );
|
1686
|
+
} else {
|
1687
|
+
tot_len = sprintf( pStr, "%sStructure: %d.%s%s%s%s",
|
1688
|
+
pLF,
|
1689
|
+
num_input_struct,
|
1690
|
+
SDF_LBL_VAL(szSdfLabel, szSdfValue) );
|
1691
|
+
if ( lSdfId ) {
|
1692
|
+
tot_len --;
|
1693
|
+
tot_len += sprintf( pStr + tot_len, ":%ld", lSdfId );
|
1694
|
+
}
|
1695
|
+
inchi_print( output_file, "%s%s", pStr, pTAB );
|
1696
|
+
}
|
1697
|
+
inchi_print( output_file, "%s%s=%s", pLF, INCHI_NAME, pLF );
|
1698
|
+
}
|
1699
|
+
/*****************************************************
|
1700
|
+
*
|
1701
|
+
* version (10-29-2003)
|
1702
|
+
*
|
1703
|
+
****************************************************/
|
1704
|
+
if ( INCHI_BAS == iINChI || !(bINChIOutputOptions & INCHI_OUT_EMBED_REC) /* || !bXml */) {
|
1705
|
+
/* xml: only if the first or not embedded; plain: always */
|
1706
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_VERS, szTag1, &bAlways );
|
1707
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1708
|
+
tot_len += sprintf(pStr + tot_len, "%s", x_curr_ver);
|
1709
|
+
/*if ( bXml ) {*/ /* avoid leading slash in plain output */
|
1710
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
1711
|
+
goto exit_function;
|
1712
|
+
/*}*/
|
1713
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1714
|
+
}
|
1715
|
+
/*****************************************************
|
1716
|
+
*
|
1717
|
+
* atoms, connection tables and tautomeric info
|
1718
|
+
*
|
1719
|
+
****************************************************/
|
1720
|
+
/******************* constitution: dot-disconnected Hill formulas: <formula> */
|
1721
|
+
if ( num_components2[0] || num_components2[1] ) {
|
1722
|
+
szGetTag( IdentLbl, nTag, bTag1 = INCHI_REC == iINChI? IL_REC_ : IL_FML_, szTag1, &bAlways );
|
1723
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1724
|
+
tot_len = str_HillFormula(pINChISort, pStr, nStrLen, tot_len,
|
1725
|
+
&bOverflow, bOutType, num_components, bUseMulipliers);
|
1726
|
+
|
1727
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, 1 ) )
|
1728
|
+
goto exit_function;
|
1729
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1730
|
+
}
|
1731
|
+
/**************** semicolon/dot-disconnected connection tables */
|
1732
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_CONN, szTag1, &bAlways );
|
1733
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1734
|
+
tot_len2 = str_Connections(pINChISort, pStr, nStrLen, tot_len,
|
1735
|
+
&bOverflow, bOutType, ATOM_MODE, num_components, bUseMulipliers);
|
1736
|
+
/* current version does not output empty (";;;;") connectivity */
|
1737
|
+
if ( tot_len != tot_len2 /*|| !bXml*/ ) { /* 2004-06-30: never output empty connection table */
|
1738
|
+
tot_len = tot_len2;
|
1739
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -2, bPlainTextTags ) )
|
1740
|
+
goto exit_function; /* pStr overfow */
|
1741
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1742
|
+
}
|
1743
|
+
/************** hydrogen atoms; do not output empty */
|
1744
|
+
if ( INCHI_SEGM_FILL == INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_h_H_ATOMS] ) ) {
|
1745
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_ALLH, szTag1, &bAlways );
|
1746
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1747
|
+
tot_len2 = str_H_atoms(pINChISort, pStr, nStrLen, tot_len,
|
1748
|
+
&bOverflow, bOutType, ATOM_MODE, TAUT_MODE,
|
1749
|
+
num_components, bUseMulipliers);
|
1750
|
+
if ( tot_len != tot_len2 /*|| !bXml*/ ) { /* 2004-06-21: never output empty */
|
1751
|
+
tot_len = tot_len2;
|
1752
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -2, 1 ) )
|
1753
|
+
goto exit_function;
|
1754
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1755
|
+
}
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
bFhTag = 0;
|
1759
|
+
|
1760
|
+
repeat_INChI_output:
|
1761
|
+
/*****************************************************
|
1762
|
+
* charge
|
1763
|
+
*/
|
1764
|
+
nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_q_CHARGE] );
|
1765
|
+
if ( nSegmAction ) {
|
1766
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_CHRG | bFhTag, szTag1, &bAlways );
|
1767
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1768
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
1769
|
+
tot_len = str_Charge2(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
1770
|
+
&bOverflow, bOutType, num_components,
|
1771
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
1772
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1773
|
+
}
|
1774
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1775
|
+
goto exit_function;
|
1776
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1777
|
+
} else
|
1778
|
+
if ( !bXml ) {
|
1779
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
1780
|
+
}
|
1781
|
+
|
1782
|
+
/*****************************************************
|
1783
|
+
* removed protons
|
1784
|
+
*/
|
1785
|
+
|
1786
|
+
if ( iCurTautMode == TAUT_YES && !bSecondNonTautPass ) {
|
1787
|
+
nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_p_PROTONS] );
|
1788
|
+
if ( nSegmAction ) {
|
1789
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_PROT | bFhTag, szTag1, &bAlways );
|
1790
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1791
|
+
tot_len += sprintf( pStr + tot_len, "%+d", nNumRemovedProtons );
|
1792
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1793
|
+
goto exit_function;
|
1794
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1795
|
+
} else
|
1796
|
+
if ( !bXml ) {
|
1797
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
1798
|
+
}
|
1799
|
+
}
|
1800
|
+
|
1801
|
+
/**************************************************
|
1802
|
+
*
|
1803
|
+
* non-isotopic stereo
|
1804
|
+
*/
|
1805
|
+
|
1806
|
+
if ( INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_b_SBONDS] ) ||
|
1807
|
+
INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_t_SATOMS] ) ||
|
1808
|
+
INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_m_SP3INV] ) ||
|
1809
|
+
INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_s_STYPE] ) )
|
1810
|
+
{
|
1811
|
+
/* stereo */
|
1812
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_STER | bFhTag, szTag1, &bAlways );
|
1813
|
+
if ( bXml ) {
|
1814
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1815
|
+
inchi_print( output_file, "%s\n", pStr );
|
1816
|
+
ind += inc;
|
1817
|
+
}
|
1818
|
+
/* sp2 */
|
1819
|
+
/*if ( bStereoSp2[iCurTautMode] )*/
|
1820
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_b_SBONDS] ) )
|
1821
|
+
{
|
1822
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_DBND, szTag2, &bAlways );
|
1823
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1824
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
1825
|
+
tot_len = str_Sp2(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
1826
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
1827
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
1828
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1829
|
+
}
|
1830
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1831
|
+
goto exit_function;
|
1832
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1833
|
+
} else
|
1834
|
+
if ( !bXml ) {
|
1835
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* sp2 */
|
1836
|
+
}
|
1837
|
+
|
1838
|
+
/* sp3 */
|
1839
|
+
/*if ( bStereoSp3[iCurTautMode] )*/
|
1840
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_t_SATOMS] ) )
|
1841
|
+
{
|
1842
|
+
bRelRac = bRelativeStereo[iCurTautMode] || bRacemicStereo[iCurTautMode];
|
1843
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_SP3S, szTag2, &bAlways );
|
1844
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1845
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
1846
|
+
tot_len = str_Sp3(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
1847
|
+
&bOverflow, bOutType, TAUT_MODE, num_components, bRelRac,
|
1848
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
1849
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1850
|
+
}
|
1851
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1852
|
+
goto exit_function;
|
1853
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1854
|
+
} else
|
1855
|
+
if ( !bXml ) {
|
1856
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* sp3 */
|
1857
|
+
}
|
1858
|
+
|
1859
|
+
/* bStereoAbsInverted[iCurTautMode] */
|
1860
|
+
/*if ( bStereoAbs[iCurTautMode] )*/
|
1861
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_m_SP3INV] ) )
|
1862
|
+
{
|
1863
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_INVS, szTag2, &bAlways );
|
1864
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1865
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
1866
|
+
tot_len = str_StereoAbsInv(pINChISort, pStr, nStrLen, tot_len,
|
1867
|
+
&bOverflow, bOutType, num_components);
|
1868
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1869
|
+
}
|
1870
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1871
|
+
goto exit_function;
|
1872
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1873
|
+
} else
|
1874
|
+
if ( !bXml ) {
|
1875
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* stereo-abs-inv */
|
1876
|
+
}
|
1877
|
+
|
1878
|
+
/* stereo type */
|
1879
|
+
/*if ( bRacemicStereo[iCurTautMode] || bRelativeStereo[iCurTautMode] || bStereoAbs[iCurTautMode] )*/
|
1880
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_s_STYPE] ) )
|
1881
|
+
{
|
1882
|
+
const char *p_stereo = bRelativeStereo[iCurTautMode]? x_rel :
|
1883
|
+
bRacemicStereo[iCurTautMode] ? x_rac : x_abs;
|
1884
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_TYPS, szTag2, &bAlways );
|
1885
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1886
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
1887
|
+
tot_len += MakeDelim( p_stereo, pStr + tot_len, nStrLen-tot_len, &bOverflow);
|
1888
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1889
|
+
}
|
1890
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1891
|
+
goto exit_function;
|
1892
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1893
|
+
}
|
1894
|
+
if ( !bXml ) {
|
1895
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* no abs, inv or racemic stereo */
|
1896
|
+
}
|
1897
|
+
if ( bXml ) {
|
1898
|
+
/* close stereo */
|
1899
|
+
ind -= inc;
|
1900
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
1901
|
+
goto exit_function;
|
1902
|
+
inchi_print( output_file, "%s", pStr );
|
1903
|
+
}
|
1904
|
+
} else
|
1905
|
+
if ( !bXml ) {
|
1906
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "////" ); /* sp3, sp2, abs-inv, stereo.type */
|
1907
|
+
}
|
1908
|
+
/****************************************************
|
1909
|
+
*
|
1910
|
+
* Isotopic canonical results
|
1911
|
+
*
|
1912
|
+
****************************************************/
|
1913
|
+
nCurINChISegment ++; /* switch from M to MI or from F to FI */
|
1914
|
+
|
1915
|
+
/*if ( bIsotopic || !bSecondNonTautPass && bHasIsoH )*/
|
1916
|
+
if ( INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_i_IATOMS] ) )
|
1917
|
+
{
|
1918
|
+
/* isotopic #1: composition -- atoms -- do not output in xml if empty */
|
1919
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_ISOT | bFhTag, szTag1, &bAlways );
|
1920
|
+
if ( bXml ) {
|
1921
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
1922
|
+
inchi_print( output_file, "%s\n", pStr );
|
1923
|
+
ind += inc;
|
1924
|
+
}
|
1925
|
+
/* isotopic atoms without mobile H.
|
1926
|
+
* Fixed 2004-06-15: always output if not bXml. Note:
|
1927
|
+
* Previous condition if( bHasIsotopicAtoms[iCurTautMode] || bIsotopic && !bXml)
|
1928
|
+
* did not optput /i in case of only mobile isotopic H
|
1929
|
+
*/
|
1930
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_i_IATOMS] ) )
|
1931
|
+
{
|
1932
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_ATMS, szTag2, &bAlways );
|
1933
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1934
|
+
/*if ( bHasIsotopicAtoms[iCurTautMode] )*/
|
1935
|
+
if ( INCHI_SEGM_FILL == nSegmAction )
|
1936
|
+
{
|
1937
|
+
tot_len2 = str_IsoAtoms(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
1938
|
+
&bOverflow, bOutType, TAUT_MODE, num_components, bAbcNumbers,
|
1939
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
1940
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1941
|
+
} else {
|
1942
|
+
tot_len2 = tot_len;
|
1943
|
+
}
|
1944
|
+
|
1945
|
+
tot_len = tot_len2;
|
1946
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1947
|
+
goto exit_function;
|
1948
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1949
|
+
|
1950
|
+
}
|
1951
|
+
/* isotopic #1a: composition -- exchangeable isotopic H (mobile H only) */
|
1952
|
+
/*if ( !bSecondNonTautPass && bHasIsoH )*/
|
1953
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_h_H_ATOMS] ) )
|
1954
|
+
{
|
1955
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_XCGA, szTag2, &bAlways );
|
1956
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1957
|
+
tot_len += MakeIsoHString( num_iso_H, pStr + tot_len, nStrLen-tot_len, TAUT_MODE, &bOverflow);
|
1958
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1959
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1960
|
+
goto exit_function;
|
1961
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
1962
|
+
}
|
1963
|
+
|
1964
|
+
/***************************************************
|
1965
|
+
*
|
1966
|
+
* Isotopic stereo
|
1967
|
+
*
|
1968
|
+
***************************************************/
|
1969
|
+
|
1970
|
+
/*if ( bIsotopicStereo[iCurTautMode] )*/
|
1971
|
+
if ( INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_b_SBONDS] ) ||
|
1972
|
+
INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_t_SATOMS] ) ||
|
1973
|
+
INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_m_SP3INV] ) ||
|
1974
|
+
INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_s_STYPE] ) )
|
1975
|
+
{
|
1976
|
+
/* stereo */
|
1977
|
+
szGetTag( IdentLbl, nTag, bTag2 = bTag1 | IL_STER, szTag2, &bAlways );
|
1978
|
+
if ( bXml ) {
|
1979
|
+
str_LineStart( szTag2, NULL, 0, pStr, ind );
|
1980
|
+
inchi_print( output_file, "%s\n", pStr );
|
1981
|
+
ind += inc;
|
1982
|
+
}
|
1983
|
+
/************************
|
1984
|
+
isotopic #2: sp2
|
1985
|
+
************************/
|
1986
|
+
/*if ( bIsotopicStereoSp2[iCurTautMode] )*/
|
1987
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_b_SBONDS] ) )
|
1988
|
+
{
|
1989
|
+
szGetTag( IdentLbl, nTag, bTag3 = bTag2 | IL_DBND, szTag3, &bAlways );
|
1990
|
+
tot_len = str_LineStart( szTag3, NULL, 0, pStr, ind );
|
1991
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
1992
|
+
tot_len = str_IsoSp2(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
1993
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
1994
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
1995
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
1996
|
+
}
|
1997
|
+
if ( str_LineEnd( szTag3, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
1998
|
+
goto exit_function;
|
1999
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2000
|
+
} else
|
2001
|
+
if ( !bXml ) {
|
2002
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* iso sp2 */
|
2003
|
+
}
|
2004
|
+
/************************
|
2005
|
+
isotopic #3: sp3
|
2006
|
+
************************/
|
2007
|
+
/*if ( bIsotopicStereoSp3[iCurTautMode] )*/
|
2008
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_t_SATOMS] ) )
|
2009
|
+
{
|
2010
|
+
bRelRac = bIsotopicRelativeStereo[iCurTautMode] || bIsotopicRacemicStereo[iCurTautMode];
|
2011
|
+
szGetTag( IdentLbl, nTag, bTag3 = bTag2 | IL_SP3S, szTag3, &bAlways );
|
2012
|
+
tot_len = str_LineStart( szTag3, NULL, 0, pStr, ind );
|
2013
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
2014
|
+
tot_len = str_IsoSp3(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2015
|
+
&bOverflow, bOutType, TAUT_MODE, num_components, bRelRac,
|
2016
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
2017
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
2018
|
+
}
|
2019
|
+
if ( str_LineEnd( szTag3, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
2020
|
+
goto exit_function;
|
2021
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2022
|
+
} else
|
2023
|
+
if ( !bXml ) {
|
2024
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* iso-sp3 */
|
2025
|
+
}
|
2026
|
+
/* isotopic #4: abs inverted */
|
2027
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_m_SP3INV] ) )
|
2028
|
+
{
|
2029
|
+
szGetTag( IdentLbl, nTag, bTag3 = bTag2 | IL_INVS, szTag3, &bAlways );
|
2030
|
+
tot_len = str_LineStart( szTag3, NULL, 0, pStr, ind );
|
2031
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
2032
|
+
tot_len = str_IsoStereoAbsInv(pINChISort, pStr, nStrLen, tot_len,
|
2033
|
+
&bOverflow, bOutType, num_components);
|
2034
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
2035
|
+
}
|
2036
|
+
if ( str_LineEnd( szTag3, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
2037
|
+
goto exit_function;
|
2038
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2039
|
+
} else
|
2040
|
+
if ( !bXml ) {
|
2041
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2042
|
+
}
|
2043
|
+
/* isotopic #5: stereo type. Do not output if it has already been output in non-iso */
|
2044
|
+
if ( nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_s_STYPE] ) )
|
2045
|
+
{
|
2046
|
+
const char *p_stereo = bIsotopicRelativeStereo[iCurTautMode]? x_rel :
|
2047
|
+
bIsotopicRacemicStereo[iCurTautMode] ? x_rac : x_abs;
|
2048
|
+
szGetTag( IdentLbl, nTag, bTag3 = bTag2 | IL_TYPS, szTag3, &bAlways );
|
2049
|
+
tot_len = str_LineStart( szTag3, NULL, 0, pStr, ind );
|
2050
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
2051
|
+
tot_len += MakeDelim( p_stereo, pStr + tot_len, nStrLen-tot_len, &bOverflow);
|
2052
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
2053
|
+
}
|
2054
|
+
if ( str_LineEnd( szTag3, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
2055
|
+
goto exit_function;
|
2056
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2057
|
+
}
|
2058
|
+
if ( !bXml ) {
|
2059
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" ); /* no abs, inv or racemic stereo */
|
2060
|
+
}
|
2061
|
+
if ( bXml ) {
|
2062
|
+
/************************
|
2063
|
+
close isotopic stereo
|
2064
|
+
************************/
|
2065
|
+
ind -= inc;
|
2066
|
+
if ( str_LineEnd( szTag2, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2067
|
+
goto exit_function;
|
2068
|
+
inchi_print( output_file, "%s", pStr );
|
2069
|
+
}
|
2070
|
+
}
|
2071
|
+
else
|
2072
|
+
if ( !bXml ) { /* no isotopic stereo */
|
2073
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "////" ); /* sp3, sp2, abs-inv, stereo.type */
|
2074
|
+
}
|
2075
|
+
|
2076
|
+
/* close isotopic */
|
2077
|
+
if ( bXml ) {
|
2078
|
+
ind -= inc;
|
2079
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2080
|
+
goto exit_function;
|
2081
|
+
inchi_print( output_file, "%s", pStr );
|
2082
|
+
}
|
2083
|
+
} else
|
2084
|
+
if ( !bXml ) {
|
2085
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "///" ); /* isotopic composition, sp2, sp3 */
|
2086
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "//" ); /* inv or racemic stereo */
|
2087
|
+
}
|
2088
|
+
#if( CANON_FIXH_TRANS == 1 )
|
2089
|
+
if ( bOutType == OUT_NONTAUT && bOutputType == OUT_TN && bSecondNonTautPass &&
|
2090
|
+
INCHI_SEGM_FILL == INChI_SegmentAction( sDifSegs[DIFL_F][DIFS_o_TRANSP] )) {
|
2091
|
+
/* find and print non-tautomeric components transposition, if non-trivial */
|
2092
|
+
AT_NUMB *nTrans_n, *nTrans_s;
|
2093
|
+
|
2094
|
+
if ( 0 < bin_AuxTautTrans(pINChISort, pINChISort2, &nTrans_n, &nTrans_s, bOutType, num_components) ) {
|
2095
|
+
/* a non-trivial transposition does exist; output start tag */
|
2096
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_TRNS | bFhTag, szTag1, &bAlways );
|
2097
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2098
|
+
/* print the transposition, cycle after cycle */
|
2099
|
+
tot_len = str_AuxTautTrans(nTrans_n, nTrans_s, pStr, nStrLen, tot_len,
|
2100
|
+
&bOverflow, TAUT_MODE, num_components);
|
2101
|
+
bNonTautIsoIdentifierNotEmpty += bSecondNonTautPass;
|
2102
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2103
|
+
goto exit_function;
|
2104
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2105
|
+
/* detected transposition */
|
2106
|
+
*pSortPrintINChIFlags |= (INCHI_BAS == iINChI)? FLAG_SORT_PRINT_TRANSPOS_BAS :
|
2107
|
+
FLAG_SORT_PRINT_TRANSPOS_REC;
|
2108
|
+
} else
|
2109
|
+
if ( !bXml ) {
|
2110
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2111
|
+
}
|
2112
|
+
}
|
2113
|
+
#endif
|
2114
|
+
|
2115
|
+
|
2116
|
+
/**************************************************************
|
2117
|
+
At this point the INChI part of the output has been done.
|
2118
|
+
If this INChI is tautomeric and non-tautomeric results exist
|
2119
|
+
then we need to output non-tautomeric data:
|
2120
|
+
fixed H,
|
2121
|
+
stereo,
|
2122
|
+
isotopic
|
2123
|
+
isotopic stereo
|
2124
|
+
***************************************************************/
|
2125
|
+
if ( bOutType == OUT_TN && !bSecondNonTautPass &&
|
2126
|
+
bNonTautIsIdenticalToTaut && bTautomeric && bNonTautomeric ) {
|
2127
|
+
/* Fixed-H layer is empty in the Identifier */
|
2128
|
+
*pSortPrintINChIFlags |= (INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_NFIX_H_BAS :
|
2129
|
+
FLAG_SORT_PRINT_NO_NFIX_H_REC;
|
2130
|
+
*pSortPrintINChIFlags |= (INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_IFIX_H_BAS :
|
2131
|
+
FLAG_SORT_PRINT_NO_IFIX_H_REC;
|
2132
|
+
}
|
2133
|
+
if ( bOutType == OUT_TN && !bNonTautIsIdenticalToTaut /* added 2004-10-04 Fix16 */
|
2134
|
+
#ifdef OLD_ITEM_DISCOVERY
|
2135
|
+
&& bTautomeric && bNonTautomeric
|
2136
|
+
#endif
|
2137
|
+
&& INChI_SegmentAction( sDifSegs[DIFL_F][DIFS_f_FORMULA] )
|
2138
|
+
/* special case: removed isolated H(+): */
|
2139
|
+
/* || iCurTautMode == TAUT_YES && num_comp[TAUT_YES] < num_comp[TAUT_NON] &&
|
2140
|
+
0 < num_comp[TAUT_NON]*/
|
2141
|
+
) {
|
2142
|
+
/* add the second (non-tautomeric) output */
|
2143
|
+
bOutType = OUT_NONTAUT; /* pick up only non-tautomeric representation of tautomeric */
|
2144
|
+
iCurTautMode = TAUT_NON;
|
2145
|
+
pINChISort = pINChISortTautAndNonTaut[TAUT_NON];
|
2146
|
+
bSecondNonTautPass = 1;
|
2147
|
+
nCurINChISegment = DIFL_F;
|
2148
|
+
num_components = num_comp[iCurTautMode]; /* number of components could change due to removal of isolated H(+) from tautomeric */
|
2149
|
+
bFhTag = IL_FIXH;
|
2150
|
+
szGetTag( IdentLbl, nTag, bTag1 = bFhTag, szTag1, &bAlways );
|
2151
|
+
if ( bXml ) { /* open non-tautomeric */
|
2152
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2153
|
+
inchi_print( output_file, "%s\n", pStr );
|
2154
|
+
ind += inc;
|
2155
|
+
}
|
2156
|
+
/***** constitution non-taut: dot-disconnected Hill formulas: <formula> -- only if different */
|
2157
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_FMLF | bFhTag, szTag1, &bAlways );
|
2158
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2159
|
+
nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_f_FORMULA] );
|
2160
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
2161
|
+
tot_len2 = str_HillFormula2(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2162
|
+
&bOverflow, bOutType, num_components, bUseMulipliers);
|
2163
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
2164
|
+
} else {
|
2165
|
+
tot_len2 = tot_len;
|
2166
|
+
}
|
2167
|
+
tot_len = tot_len2;
|
2168
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
2169
|
+
goto exit_function;
|
2170
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2171
|
+
|
2172
|
+
nSegmAction = INChI_SegmentAction( sDifSegs[nCurINChISegment][DIFS_h_H_ATOMS] );
|
2173
|
+
if ( INCHI_SEGM_FILL == nSegmAction ) {
|
2174
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_HFIX | bFhTag, szTag1, &bAlways );
|
2175
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind ); /* open H-fixed */
|
2176
|
+
/* output the second non-tautomeric item: fixed H -- do not output in xml if empty */
|
2177
|
+
tot_len2 = str_FixedH_atoms(pINChISort, pStr, nStrLen, tot_len,
|
2178
|
+
&bOverflow, bOutType, ATOM_MODE, num_components, bUseMulipliers);
|
2179
|
+
tot_len = tot_len2;
|
2180
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -nSegmAction, bPlainTextTags ) )
|
2181
|
+
goto exit_function;
|
2182
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2183
|
+
bNonTautNonIsoIdentifierNotEmpty += bSecondNonTautPass;
|
2184
|
+
}
|
2185
|
+
goto repeat_INChI_output;
|
2186
|
+
} else
|
2187
|
+
if ( bOutType == OUT_NONTAUT && bOutputType == OUT_TN && bSecondNonTautPass /* && bTautomeric && bNonTautomeric*/ ) {
|
2188
|
+
/* the second (non-taut) output has been done; restore variables */
|
2189
|
+
bOutType = OUT_TN;
|
2190
|
+
iCurTautMode = TAUT_YES;
|
2191
|
+
pINChISort = pINChISortTautAndNonTaut[TAUT_YES];
|
2192
|
+
bSecondNonTautPass = 0;
|
2193
|
+
num_components = num_comp[iCurTautMode];
|
2194
|
+
if ( !bNonTautNonIsoIdentifierNotEmpty ) {
|
2195
|
+
/* Fixed-H layer is empty in the Identifier */
|
2196
|
+
*pSortPrintINChIFlags |= (INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_NFIX_H_BAS :
|
2197
|
+
FLAG_SORT_PRINT_NO_NFIX_H_REC;
|
2198
|
+
}
|
2199
|
+
if ( !bNonTautIsoIdentifierNotEmpty ) {
|
2200
|
+
/* Fixed-H layer is empty in the Identifier */
|
2201
|
+
*pSortPrintINChIFlags |= (INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_IFIX_H_BAS :
|
2202
|
+
FLAG_SORT_PRINT_NO_IFIX_H_REC;
|
2203
|
+
}
|
2204
|
+
if ( bXml ) {
|
2205
|
+
/* close non-tautomeric */
|
2206
|
+
ind -= inc;
|
2207
|
+
szGetTag( IdentLbl, nTag, bTag1 = bFhTag, szTag1, &bAlways );
|
2208
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2209
|
+
goto exit_function;
|
2210
|
+
inchi_print( output_file, "%s", pStr );
|
2211
|
+
}
|
2212
|
+
bFhTag = 0;
|
2213
|
+
}
|
2214
|
+
|
2215
|
+
/************************************************
|
2216
|
+
* output INChI of the reconnected structure *
|
2217
|
+
************************************************/
|
2218
|
+
bEmbeddedOutputCalled = 0;
|
2219
|
+
if ( bDisconnectedCoord && INCHI_BAS == iINChI &&
|
2220
|
+
(bINChIOutputOptions & INCHI_OUT_EMBED_REC) && num_components2[INCHI_REC] ) {
|
2221
|
+
int nRet;
|
2222
|
+
bEmbeddedOutputCalled = 1;
|
2223
|
+
|
2224
|
+
if ( !bXml ) {
|
2225
|
+
/* output blank line before /R: in case of bPlainTextCommnts=1 */
|
2226
|
+
inchi_print( output_file, "%s", pLF );
|
2227
|
+
}
|
2228
|
+
/* end of disconnected INChI output */
|
2229
|
+
nRet = OutputINChI1( pStr, nStrLen, pINChISortTautAndNonTaut2, INCHI_REC, NULL,
|
2230
|
+
0 /*bDisconnectedCoord*/, bOutputType, bINChIOutputOptions | INCHI_OUT_NO_AUX_INFO,
|
2231
|
+
bXml, bAbcNumbers, bCtPredecessors, bNoStructLabels,
|
2232
|
+
num_components2, num_non_taut2, num_taut2,
|
2233
|
+
output_file, log_file, num_input_struct,
|
2234
|
+
szSdfLabel, szSdfValue, lSdfId, pSortPrintINChIFlags );
|
2235
|
+
|
2236
|
+
if ( !nRet ) {
|
2237
|
+
goto exit_function; /* error */
|
2238
|
+
}
|
2239
|
+
}
|
2240
|
+
|
2241
|
+
if ( bXml ) {
|
2242
|
+
/* close INChI identifier (basic) */
|
2243
|
+
ind -= inc;
|
2244
|
+
if ( str_LineEnd( x_basic, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2245
|
+
goto exit_function;
|
2246
|
+
inchi_print( output_file, "%s", pStr );
|
2247
|
+
} else
|
2248
|
+
if ( !bEmbeddedOutputCalled && !bPlainTextCommnts ) { /* plain text comment earlier ended with LF */
|
2249
|
+
inchi_print( output_file, "%s%s", (!num_components2[0] && !num_components2[1])? "//":"", /* empty InChI=// */
|
2250
|
+
(bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO)? "\n" : pTAB );
|
2251
|
+
/* end of INChI= output */
|
2252
|
+
}
|
2253
|
+
|
2254
|
+
output_aux_info:
|
2255
|
+
bFhTag = 0;
|
2256
|
+
if( !(bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) ) { /* output aux info */
|
2257
|
+
/*************************************************************
|
2258
|
+
*
|
2259
|
+
* Aux info non-isotopic
|
2260
|
+
*
|
2261
|
+
*************************************************************/
|
2262
|
+
num_components = num_comp[iCurTautMode];
|
2263
|
+
if ( bXml ) {
|
2264
|
+
/* aux. info header */
|
2265
|
+
/* empty line if INChI output has been printed */
|
2266
|
+
if ( !(bINChIOutputOptions & INCHI_OUT_ONLY_AUX_INFO) ) {
|
2267
|
+
inchi_print( output_file, "\n" );
|
2268
|
+
}
|
2269
|
+
/* basic.aux-info title, version */
|
2270
|
+
tot_len = sprintf(pStr, "%s<%s %s=\"%s\"",
|
2271
|
+
SP(ind), x_aux_basic, x_ver, x_curr_ver );
|
2272
|
+
if ( INCHI_REC == iINChI || INCHI_BAS == iINChI && bDisconnectedCoord ) {
|
2273
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%d\"", x_reconnected, iINChI );
|
2274
|
+
}
|
2275
|
+
if ( bAbcNumbers ) {
|
2276
|
+
/* type */
|
2277
|
+
const char *pNumber = x_type_short;
|
2278
|
+
tot_len += sprintf(pStr+tot_len, " %s=\"%s\"", x_type, pNumber);
|
2279
|
+
}
|
2280
|
+
|
2281
|
+
sprintf(pStr+tot_len,">");
|
2282
|
+
inchi_print( output_file, "%s\n", pStr );
|
2283
|
+
ind += inc;
|
2284
|
+
if ( !(bINChIOutputOptions & INCHI_OUT_ONLY_AUX_INFO) ) {
|
2285
|
+
/* comment */
|
2286
|
+
tot_len = sprintf( pStr, "%s<%s>", SP(ind), x_aux_comm );
|
2287
|
+
inchi_print( output_file, "%s\n", pStr );
|
2288
|
+
}
|
2289
|
+
} else {
|
2290
|
+
if ( INCHI_BAS == iINChI ) {
|
2291
|
+
tot_len = sprintf( pStr, "AuxInfo=" ); /* in wINChI window, separate INChI: from AuxInfo: with blank line */
|
2292
|
+
inchi_print( output_file, "%s%s%s",
|
2293
|
+
/* blank line before AuxInfo in winchi window unless it is an annotation */
|
2294
|
+
(bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW) ? "\n":"",
|
2295
|
+
pStr,
|
2296
|
+
pLF);
|
2297
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_VERS, szTag1, &bAlways );
|
2298
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2299
|
+
tot_len += sprintf(pStr + tot_len, "%s", x_curr_ver);
|
2300
|
+
/* avoid leading slash in plain output */
|
2301
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2302
|
+
goto exit_function;
|
2303
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2304
|
+
} else
|
2305
|
+
if ( INCHI_REC == iINChI ) {
|
2306
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_REC_, szTag1, &bAlways );
|
2307
|
+
inchi_print( output_file, "%s%s", szTag1, pLF );
|
2308
|
+
}
|
2309
|
+
|
2310
|
+
}
|
2311
|
+
/* normalization type */
|
2312
|
+
if ( num_components2[0] || num_components2[1] ) {
|
2313
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_NORM, szTag1, &bAlways );
|
2314
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2315
|
+
tot_len += sprintf( pStr + tot_len, "%d", (bTautomeric && bTautomericOutputAllowed)? bTautomeric : 0);
|
2316
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2317
|
+
goto exit_function;
|
2318
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2319
|
+
}
|
2320
|
+
|
2321
|
+
repeat_INChI_Aux_output:
|
2322
|
+
|
2323
|
+
/**************************************************************
|
2324
|
+
* Original atom numbers in order of canonical numbers
|
2325
|
+
**************************************************************/
|
2326
|
+
if ( num_components2[0] || num_components2[1] ) {
|
2327
|
+
szGetTag( AuxLbl, nTag, bTag1 = (bSecondNonTautPass? AL_FIXN : AL_ANBR) | bFhTag, szTag1, &bAlways );
|
2328
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2329
|
+
/* original numbering output */
|
2330
|
+
tot_len = str_AuxNumb(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2331
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2332
|
+
bSecondNonTautPass, bOmitRepetitions);
|
2333
|
+
|
2334
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2335
|
+
goto exit_function;
|
2336
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2337
|
+
}
|
2338
|
+
/**********************************************
|
2339
|
+
* Symmetry numbers (constit. equivalence)
|
2340
|
+
**********************************************/
|
2341
|
+
if ( bAtomEqu[iCurTautMode] ) {
|
2342
|
+
/* aux equ atoms */
|
2343
|
+
/* 1. Compare to tautomeric equivalence (in case of second, non-taut, pass only) */
|
2344
|
+
/* 2. Compare to the previous component if (1) failed to find equivalence */
|
2345
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_AEQU | bFhTag, szTag1, &bAlways );
|
2346
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2347
|
+
tot_len = str_AuxEqu(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2348
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2349
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
2350
|
+
|
2351
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2352
|
+
goto exit_function;
|
2353
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2354
|
+
} else
|
2355
|
+
if ( !bXml ) {
|
2356
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2357
|
+
}
|
2358
|
+
/*****************************************************
|
2359
|
+
* Tautomeric groups equivalence
|
2360
|
+
*****************************************************/
|
2361
|
+
if ( bTautomericOutputAllowed && bTautomeric && bTautEqu[iCurTautMode] && !bSecondNonTautPass ) {
|
2362
|
+
/*****************************************************
|
2363
|
+
* Tautomeric groups constitutional equivalence
|
2364
|
+
*/
|
2365
|
+
/* aux tgroup equ */
|
2366
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_GEQU | bFhTag, szTag1, &bAlways );
|
2367
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2368
|
+
tot_len = str_AuxTgroupEqu(pINChISort, pStr, nStrLen, tot_len,
|
2369
|
+
&bOverflow, bOutType, TAUT_MODE,
|
2370
|
+
num_components, bUseMulipliers);
|
2371
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2372
|
+
goto exit_function;
|
2373
|
+
inchi_print( output_file, "%s", pStr );
|
2374
|
+
} else
|
2375
|
+
if ( !bXml && bTautomericOutputAllowed && bTautomeric ) {
|
2376
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2377
|
+
}
|
2378
|
+
/****************************************************
|
2379
|
+
* Inverted stereo -- sp3 only + canonical numbering
|
2380
|
+
****************************************************/
|
2381
|
+
if ( bInvStereo[iCurTautMode] ) {
|
2382
|
+
|
2383
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_STER | bFhTag, szTag1, &bAlways );
|
2384
|
+
if ( bXml ) {
|
2385
|
+
/***************************
|
2386
|
+
inv stereo start tag
|
2387
|
+
****************************/
|
2388
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2389
|
+
inchi_print( output_file, "%s\n", pStr );
|
2390
|
+
ind += inc;
|
2391
|
+
}
|
2392
|
+
/****************************
|
2393
|
+
inverted sp3 start tag
|
2394
|
+
*****************************/
|
2395
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_SP3I, szTag2, &bAlways );
|
2396
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2397
|
+
tot_len = str_AuxInvSp3(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2398
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2399
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
2400
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2401
|
+
goto exit_function;
|
2402
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2403
|
+
/*************************************
|
2404
|
+
inverted sp3 canonical numbering
|
2405
|
+
**************************************/
|
2406
|
+
if ( bInvStereoOrigNumb[iCurTautMode] ) {
|
2407
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_SP3N, szTag2, &bAlways );
|
2408
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2409
|
+
tot_len = str_AuxInvSp3Numb(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2410
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2411
|
+
bSecondNonTautPass, bOmitRepetitions);
|
2412
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2413
|
+
goto exit_function;
|
2414
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2415
|
+
} else
|
2416
|
+
if ( !bXml ) {
|
2417
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2418
|
+
}
|
2419
|
+
if ( bXml ) {
|
2420
|
+
/* close sp3 inv */
|
2421
|
+
ind -= inc;
|
2422
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2423
|
+
goto exit_function;
|
2424
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2425
|
+
}
|
2426
|
+
} else
|
2427
|
+
if ( !bXml ) {
|
2428
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "//" );
|
2429
|
+
} /* Inverted stereo -- sp3 only + canonical numbering */
|
2430
|
+
|
2431
|
+
|
2432
|
+
/* omitted undefined/unknown non-isotopic stereo */
|
2433
|
+
if ( bXml ) {
|
2434
|
+
if ( bIgn_UU_Sp2[iCurTautMode] || bIgn_UU_Sp3[iCurTautMode] ) {
|
2435
|
+
/* <stereo omit_undef_dbond="1" omit_undef_sp3="1"/> */
|
2436
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_STER, szTag1, &bAlways );
|
2437
|
+
tot_len = PrintXmlStartTag( pStr, ind, 3, szTag1,
|
2438
|
+
(bIgn_UU_Sp2[iCurTautMode])? x_ign_uu_sp2 : NULL, 1,
|
2439
|
+
(bIgn_UU_Sp3[iCurTautMode])? x_ign_uu_sp3 : NULL, 1,
|
2440
|
+
NULL, 0, NULL, 0, NULL, 0, NULL, 0 );
|
2441
|
+
inchi_print( output_file, "%s\n", pStr );
|
2442
|
+
}
|
2443
|
+
}
|
2444
|
+
|
2445
|
+
/***************************************************************
|
2446
|
+
*
|
2447
|
+
* Additional information: charges, radicals,
|
2448
|
+
* special valences, coordinates
|
2449
|
+
*
|
2450
|
+
***************************************************************/
|
2451
|
+
/**************************************************************
|
2452
|
+
*
|
2453
|
+
* Aux info isotopic
|
2454
|
+
*
|
2455
|
+
**************************************************************/
|
2456
|
+
repeat_INChI_Aux_Iso_output:
|
2457
|
+
/* if InChI Fixed-H isotopic is empty then do not output corresponding AuxInfo */
|
2458
|
+
i = bSecondNonTautPass &&
|
2459
|
+
(*pSortPrintINChIFlags & ((INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_IFIX_H_BAS :
|
2460
|
+
FLAG_SORT_PRINT_NO_IFIX_H_REC ));
|
2461
|
+
|
2462
|
+
if ( bIsotopic && !i &&
|
2463
|
+
(bIsotopicOrigNumb[iCurTautMode] ||
|
2464
|
+
bIsotopicAtomEqu[iCurTautMode] ||
|
2465
|
+
bTautomericOutputAllowed && bTautomeric && bIsotopicTautEqu[iCurTautMode] ||
|
2466
|
+
bInvIsotopicStereo[iCurTautMode] ||
|
2467
|
+
bXml && ( bIgn_UU_Sp3_Iso[iCurTautMode] || bIgn_UU_Sp2_Iso[iCurTautMode] ) ) ) {
|
2468
|
+
/*************************************/
|
2469
|
+
/* isotopic aux info header */
|
2470
|
+
/*************************************/
|
2471
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_ISOT | bFhTag, szTag1, &bAlways );
|
2472
|
+
if ( bXml ) {
|
2473
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2474
|
+
inchi_print( output_file, "%s\n", pStr );
|
2475
|
+
ind += inc;
|
2476
|
+
} else {
|
2477
|
+
pStr[tot_len = 0] = '\0';
|
2478
|
+
}
|
2479
|
+
/*****************************************************************
|
2480
|
+
* Original atom numbers in order of isotopic canonical numbers
|
2481
|
+
*****************************************************************/
|
2482
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_ISON, szTag2, &bAlways );
|
2483
|
+
if ( bIsotopicOrigNumb[iCurTautMode] ) {
|
2484
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2485
|
+
tot_len = str_AuxIsoNumb(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2486
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2487
|
+
bSecondNonTautPass, bOmitRepetitions);
|
2488
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2489
|
+
goto exit_function;
|
2490
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2491
|
+
} else
|
2492
|
+
if ( !bXml ) {
|
2493
|
+
/*if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );*/
|
2494
|
+
inchi_print( output_file, "%s%s", szTag2, pLF ); /* mark isotopic output */
|
2495
|
+
}
|
2496
|
+
/*************************/
|
2497
|
+
/* Isotopic symmetry */
|
2498
|
+
/*************************/
|
2499
|
+
if ( bIsotopicAtomEqu[iCurTautMode] ) {
|
2500
|
+
/* atoms */
|
2501
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_AEQU, szTag2, &bAlways );
|
2502
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2503
|
+
tot_len = str_AuxIsoEqu(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2504
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2505
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
2506
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -2/*was -1: Fix15*/, bPlainTextTags ) )
|
2507
|
+
goto exit_function;
|
2508
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2509
|
+
} else
|
2510
|
+
if ( !bXml ) {
|
2511
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2512
|
+
}
|
2513
|
+
|
2514
|
+
/********************************/
|
2515
|
+
/* Tautomeric groups, isotopic */
|
2516
|
+
/********************************/
|
2517
|
+
if ( bTautomericOutputAllowed && bTautomeric && bIsotopicTautEqu[iCurTautMode] ) {
|
2518
|
+
/********************************************/
|
2519
|
+
/* Isotopic tautomeric groups equivalence */
|
2520
|
+
/********************************************/
|
2521
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_GEQU, szTag2, &bAlways );
|
2522
|
+
tot_len = str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2523
|
+
tot_len = str_AuxIsoTgroupEqu(pINChISort, pStr, nStrLen, tot_len,
|
2524
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2525
|
+
bOmitRepetitions, bUseMulipliers);
|
2526
|
+
if ( str_LineEnd( szTag2, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -2/*was -1: Fix15*/, bPlainTextTags ) )
|
2527
|
+
goto exit_function;
|
2528
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2529
|
+
} else
|
2530
|
+
if ( !bXml && bTautomericOutputAllowed && bTautomeric ) {
|
2531
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2532
|
+
}
|
2533
|
+
|
2534
|
+
/*************************************
|
2535
|
+
* Isotopic inverted stereo
|
2536
|
+
*************************************/
|
2537
|
+
if ( bInvIsotopicStereo[iCurTautMode] ) {
|
2538
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_STER, szTag2, &bAlways );
|
2539
|
+
if ( bXml ) {
|
2540
|
+
/************************************
|
2541
|
+
inv isotopic stereo start tag
|
2542
|
+
*************************************/
|
2543
|
+
str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2544
|
+
inchi_print( output_file, "%s\n", pStr );
|
2545
|
+
ind += inc;
|
2546
|
+
}
|
2547
|
+
/*************************************
|
2548
|
+
inverted isotopic sp3 start tag
|
2549
|
+
**************************************/
|
2550
|
+
szGetTag( AuxLbl, nTag, bTag3 = bTag2 | AL_SP3I, szTag3, &bAlways );
|
2551
|
+
tot_len = str_LineStart( szTag3, NULL, 0, pStr, ind );
|
2552
|
+
tot_len = str_AuxInvIsoSp3(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2553
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2554
|
+
bSecondNonTautPass, bOmitRepetitions, bUseMulipliers);
|
2555
|
+
if ( str_LineEnd( szTag3, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2556
|
+
goto exit_function;
|
2557
|
+
inchi_print( output_file, "%s", pStr );
|
2558
|
+
/*********************************************
|
2559
|
+
inverted isotopic sp3 canonical numbering
|
2560
|
+
**********************************************/
|
2561
|
+
if ( bInvIsotopicStereoOrigNumb[iCurTautMode] ) {
|
2562
|
+
szGetTag( AuxLbl, nTag, bTag3 = bTag2 | AL_SP3N, szTag3, &bAlways );
|
2563
|
+
tot_len = str_LineStart( szTag3, NULL, 0, pStr, ind );
|
2564
|
+
tot_len = str_AuxInvIsoSp3Numb(pINChISort, pINChISort2, pStr, nStrLen, tot_len,
|
2565
|
+
&bOverflow, bOutType, TAUT_MODE, num_components,
|
2566
|
+
bSecondNonTautPass, bOmitRepetitions);
|
2567
|
+
if ( str_LineEnd( szTag3, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2568
|
+
goto exit_function;
|
2569
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2570
|
+
} else
|
2571
|
+
if ( !bXml ) {
|
2572
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2573
|
+
}
|
2574
|
+
if ( bXml ) {
|
2575
|
+
/* close sp3 inv */
|
2576
|
+
ind -= inc;
|
2577
|
+
if ( str_LineEnd( szTag2, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2578
|
+
goto exit_function;
|
2579
|
+
inchi_print( output_file, "%s", pStr );
|
2580
|
+
}
|
2581
|
+
} else
|
2582
|
+
if ( !bXml ) {
|
2583
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "//" );
|
2584
|
+
}
|
2585
|
+
|
2586
|
+
/* totally omitted undefined/unknown isotopic stereo */
|
2587
|
+
if ( bXml ) {
|
2588
|
+
if ( bIgn_UU_Sp3_Iso[iCurTautMode] || bIgn_UU_Sp2_Iso[iCurTautMode] ) {
|
2589
|
+
/* <stereo omit_undef_dbond="1" omit_undef_sp3="1"/> */
|
2590
|
+
szGetTag( IdentLbl, nTag, bTag1 = IL_STER, szTag1, &bAlways );
|
2591
|
+
tot_len = PrintXmlStartTag( pStr, ind, 3, szTag1,
|
2592
|
+
(bIgn_UU_Sp2_Iso[iCurTautMode])? x_ign_uu_sp2 : NULL, 1,
|
2593
|
+
(bIgn_UU_Sp3_Iso[iCurTautMode])? x_ign_uu_sp3 : NULL, 1,
|
2594
|
+
NULL, 0, NULL, 0, NULL, 0, NULL, 0 );
|
2595
|
+
inchi_print( output_file, "%s\n", pStr );
|
2596
|
+
}
|
2597
|
+
}
|
2598
|
+
|
2599
|
+
|
2600
|
+
if ( bXml ) {
|
2601
|
+
/***************** close isotopic ***********************/
|
2602
|
+
ind -= inc;
|
2603
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2604
|
+
goto exit_function;
|
2605
|
+
inchi_print( output_file, "%s", pStr );
|
2606
|
+
}
|
2607
|
+
} /* Aux info isotopic */
|
2608
|
+
|
2609
|
+
#if( CANON_FIXH_TRANS != 1 )
|
2610
|
+
if ( bSecondNonTautPass ) {
|
2611
|
+
/* find and print non-tautomeric components transposition, if non-trivial */
|
2612
|
+
AT_NUMB *nTrans_n, *nTrans_s;
|
2613
|
+
if ( 0 < bin_AuxTautTrans(pINChISort, pINChISort2, &nTrans_n, &nTrans_s, bOutType, num_components) ) {
|
2614
|
+
/* a non-trivial transposition does exist; output start tag */
|
2615
|
+
tot_len = str_LineStart( tag=x_aux_trans, NULL, 0, pStr, ind );
|
2616
|
+
/* print the transposition, cycle after cycle */
|
2617
|
+
tot_len = str_AuxTautTrans(nTrans_n, nTrans_s, pStr, nStrLen, tot_len,
|
2618
|
+
&bOverflow, TAUT_MODE, num_components);
|
2619
|
+
if ( str_LineEnd( bXml? tag:p_aux_at_inv_nbr, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2620
|
+
goto exit_function;
|
2621
|
+
inchi_print( output_file, "%s", pStr );
|
2622
|
+
/* detected transposition */
|
2623
|
+
*pSortPrintINChIFlags |= (INCHI_BAS == iINChI)? FLAG_SORT_PRINT_TRANSPOS_BAS :
|
2624
|
+
FLAG_SORT_PRINT_TRANSPOS_REC;
|
2625
|
+
} else
|
2626
|
+
if ( !bXml ) {
|
2627
|
+
if ( bPlainTextTags == 1 ) inchi_print( output_file, "/" );
|
2628
|
+
}
|
2629
|
+
}
|
2630
|
+
#endif
|
2631
|
+
|
2632
|
+
/**************************************************************
|
2633
|
+
At this point the INChI_Aux part of the output has been copleted.
|
2634
|
+
If this INChI is tautomeric and non-tautomeric results exist
|
2635
|
+
then we need to output non-tautomeric auxilialy data
|
2636
|
+
(same as above excluding tautomeric information)
|
2637
|
+
Currently this is enabled for xml output only
|
2638
|
+
***************************************************************/
|
2639
|
+
|
2640
|
+
if ( bOutType == OUT_TN && bTautomeric && bNonTautomeric &&
|
2641
|
+
/* Check whether the Fixed-H layer is empty */
|
2642
|
+
(*pSortPrintINChIFlags & ((INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_NFIX_H_BAS :
|
2643
|
+
FLAG_SORT_PRINT_NO_NFIX_H_REC )) &&
|
2644
|
+
(*pSortPrintINChIFlags & ((INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_IFIX_H_BAS :
|
2645
|
+
FLAG_SORT_PRINT_NO_IFIX_H_REC ))
|
2646
|
+
) {
|
2647
|
+
bNonTautomeric = 0; /* bNonTautIdentifierNotEmpty == 0 => no fixed H info 02-10-2995 */
|
2648
|
+
}
|
2649
|
+
if ( bOutType == OUT_TN && bTautomeric && bNonTautomeric ) {
|
2650
|
+
/* add the second (non-tautomeric) output */
|
2651
|
+
bOutType = OUT_NONTAUT;
|
2652
|
+
iCurTautMode = TAUT_NON;
|
2653
|
+
pINChISort = pINChISortTautAndNonTaut[TAUT_NON];
|
2654
|
+
bSecondNonTautPass = 1;
|
2655
|
+
num_components = num_comp[iCurTautMode];
|
2656
|
+
bFhTag = AL_FIXH;
|
2657
|
+
if ( bXml ) {
|
2658
|
+
szGetTag( AuxLbl, nTag, bTag1 = bFhTag, szTag1, &bAlways );
|
2659
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2660
|
+
inchi_print( output_file, "%s\n", pStr );
|
2661
|
+
ind += inc;
|
2662
|
+
} else {
|
2663
|
+
pStr[tot_len=0] = '\0';
|
2664
|
+
}
|
2665
|
+
/* if InChI Fixed-H isotopic is empty then do not output corresponding AuxInfo */
|
2666
|
+
if ( !(*pSortPrintINChIFlags &
|
2667
|
+
((INCHI_BAS == iINChI)? FLAG_SORT_PRINT_NO_NFIX_H_BAS :
|
2668
|
+
FLAG_SORT_PRINT_NO_NFIX_H_REC ))
|
2669
|
+
) {
|
2670
|
+
goto repeat_INChI_Aux_output;
|
2671
|
+
} else {
|
2672
|
+
goto repeat_INChI_Aux_Iso_output;
|
2673
|
+
}
|
2674
|
+
} else
|
2675
|
+
if ( bOutType == OUT_NONTAUT && bOutputType == OUT_TN && bTautomeric && bNonTautomeric ) {
|
2676
|
+
/* the second (non-taut) output has been done; restore variables */
|
2677
|
+
bOutType = OUT_TN;
|
2678
|
+
iCurTautMode = TAUT_YES;
|
2679
|
+
pINChISort = pINChISortTautAndNonTaut[TAUT_YES];
|
2680
|
+
bSecondNonTautPass = 0;
|
2681
|
+
/* set correct num components for the reversibility info 02-10-2005 */
|
2682
|
+
num_components = num_comp[iCurTautMode];
|
2683
|
+
if ( bXml ) {
|
2684
|
+
/* close non-tautomeric */
|
2685
|
+
szGetTag( AuxLbl, nTag, bTag1 = bFhTag, szTag1, &bAlways );
|
2686
|
+
ind -= inc;
|
2687
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2688
|
+
goto exit_function;
|
2689
|
+
inchi_print( output_file, "%s", pStr );
|
2690
|
+
}
|
2691
|
+
bFhTag = 0;
|
2692
|
+
}
|
2693
|
+
|
2694
|
+
/***************************************/
|
2695
|
+
/* charges, radicals, unusual valences */
|
2696
|
+
/***************************************/
|
2697
|
+
if ( !bSecondNonTautPass && bChargesRadVal[iCurTautMode] ) {
|
2698
|
+
/* aux equ atoms */
|
2699
|
+
/* 1. Compare to tautomeric equivalence (in case of second, non-taut, pass only) */
|
2700
|
+
/* 2. Compare to the previous component if (1) failed to find equivalence */
|
2701
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_CRV_ | bFhTag, szTag1, &bAlways );
|
2702
|
+
tot_len = str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2703
|
+
tot_len = str_AuxChargeRadVal(pINChISort, pStr, nStrLen, tot_len,
|
2704
|
+
&bOverflow, bOutType, TAUT_MODE,
|
2705
|
+
num_components, bUseMulipliers);
|
2706
|
+
if ( str_LineEnd( szTag1, tot_len, nStrLen, &bOverflow, pStr, bXml? 0 : -1, bPlainTextTags ) )
|
2707
|
+
goto exit_function;
|
2708
|
+
inchi_print( output_file, "%s%s", pStr, pLF );
|
2709
|
+
}
|
2710
|
+
|
2711
|
+
/* output the original input structure -- quick fix */
|
2712
|
+
if ( !bSecondNonTautPass && pOrigStruct && pOrigStruct->num_atoms &&
|
2713
|
+
pOrigStruct->szAtoms && pOrigStruct->szBonds && pOrigStruct->szCoord ) {
|
2714
|
+
int length, cur_pos, line_len, last_pos, nMaxLineLen;
|
2715
|
+
char *p;
|
2716
|
+
nMaxLineLen = inchi_min( 80, nStrLen ); /* restrict line length to 80 characters */
|
2717
|
+
/**********************
|
2718
|
+
reversibility info
|
2719
|
+
**********************/
|
2720
|
+
szGetTag( AuxLbl, nTag, bTag1 = AL_REVR | bFhTag, szTag1, &bAlways );
|
2721
|
+
if ( bXml ) {
|
2722
|
+
str_LineStart( szTag1, NULL, 0, pStr, ind );
|
2723
|
+
inchi_print( output_file, "%s\n", pStr );
|
2724
|
+
ind += inc;
|
2725
|
+
}
|
2726
|
+
/* === atoms === */
|
2727
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_ATMR, szTag2, &bAlways );
|
2728
|
+
if ( bXml ) {
|
2729
|
+
str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2730
|
+
inchi_print( output_file, "%s\n", pStr );
|
2731
|
+
ind += inc;
|
2732
|
+
/* first line indent */
|
2733
|
+
strcpy( pStr, SP(ind));
|
2734
|
+
tot_len = ind;
|
2735
|
+
} else {
|
2736
|
+
pStr[tot_len = 0] = '\0';
|
2737
|
+
inchi_print( output_file, "%s%s", szTag2, pStr );
|
2738
|
+
}
|
2739
|
+
p = pOrigStruct->szAtoms;
|
2740
|
+
length = strlen( p );
|
2741
|
+
line_len = nMaxLineLen - tot_len;
|
2742
|
+
for ( cur_pos = 0; cur_pos < length; cur_pos = last_pos ) {
|
2743
|
+
if ( length - cur_pos >= line_len ) {
|
2744
|
+
last_pos = cur_pos + line_len;
|
2745
|
+
/* search backward for the nearest first atom letter (always uppercase) */
|
2746
|
+
while ( cur_pos < last_pos && !isupper( UCINT p[last_pos] ) ) {
|
2747
|
+
last_pos --;
|
2748
|
+
}
|
2749
|
+
} else {
|
2750
|
+
last_pos = length;
|
2751
|
+
}
|
2752
|
+
if ( last_pos > cur_pos ) {
|
2753
|
+
memcpy( pStr + tot_len, p+cur_pos, last_pos - cur_pos );
|
2754
|
+
pStr[tot_len + last_pos - cur_pos] = '\0';
|
2755
|
+
inchi_print( output_file, "%s%s", pStr, !bXml && bPlainTextTags? "" : "\n" );
|
2756
|
+
} else {
|
2757
|
+
break;
|
2758
|
+
}
|
2759
|
+
}
|
2760
|
+
if ( bXml ) {
|
2761
|
+
ind -= inc;
|
2762
|
+
pStr[0] = '\0';
|
2763
|
+
if ( str_LineEnd( szTag2, 0, nMaxLineLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2764
|
+
goto exit_function;
|
2765
|
+
inchi_print( output_file, "%s", pStr );
|
2766
|
+
} else
|
2767
|
+
if ( pLF[0] ) {
|
2768
|
+
inchi_print( output_file, "%s", pLF );
|
2769
|
+
}
|
2770
|
+
|
2771
|
+
/* === bonds === */
|
2772
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_BNDR, szTag2, &bAlways );
|
2773
|
+
if ( bXml ) {
|
2774
|
+
str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2775
|
+
inchi_print( output_file, "%s\n", pStr );
|
2776
|
+
ind += inc;
|
2777
|
+
/* first line indent */
|
2778
|
+
strcpy( pStr, SP(ind));
|
2779
|
+
tot_len = ind;
|
2780
|
+
} else {
|
2781
|
+
pStr[tot_len = 0] = '\0';
|
2782
|
+
inchi_print( output_file, "%s%s", szTag2, pStr );
|
2783
|
+
}
|
2784
|
+
p = pOrigStruct->szBonds;
|
2785
|
+
length = strlen( p );
|
2786
|
+
line_len = nMaxLineLen - tot_len;
|
2787
|
+
for ( cur_pos = 0; cur_pos < length; cur_pos = last_pos ) {
|
2788
|
+
if ( length - cur_pos >= line_len ) {
|
2789
|
+
last_pos = cur_pos + line_len - 1;
|
2790
|
+
/* search backward for the nearest first bond delimiter ";" */
|
2791
|
+
while ( cur_pos < last_pos && p[last_pos] != ';' ) {
|
2792
|
+
last_pos --;
|
2793
|
+
}
|
2794
|
+
if ( cur_pos < last_pos ) {
|
2795
|
+
last_pos ++; /* include ';' at the end of the line */
|
2796
|
+
}
|
2797
|
+
} else {
|
2798
|
+
last_pos = length;
|
2799
|
+
}
|
2800
|
+
if ( last_pos > cur_pos ) {
|
2801
|
+
memcpy( pStr + tot_len, p+cur_pos, last_pos - cur_pos );
|
2802
|
+
pStr[tot_len + last_pos - cur_pos] = '\0';
|
2803
|
+
inchi_print( output_file, "%s%s", pStr, !bXml && bPlainTextTags? "" : "\n" );
|
2804
|
+
} else {
|
2805
|
+
break;
|
2806
|
+
}
|
2807
|
+
}
|
2808
|
+
if ( bXml ) {
|
2809
|
+
ind -= inc;
|
2810
|
+
pStr[0] = '\0';
|
2811
|
+
if ( str_LineEnd( szTag2, 0, nMaxLineLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2812
|
+
goto exit_function;
|
2813
|
+
inchi_print( output_file, "%s", pStr );
|
2814
|
+
} else
|
2815
|
+
if ( pLF[0] ) {
|
2816
|
+
inchi_print( output_file, "%s", pLF );
|
2817
|
+
}
|
2818
|
+
|
2819
|
+
/* === coordinates === */
|
2820
|
+
szGetTag( AuxLbl, nTag, bTag2 = bTag1 | AL_XYZR, szTag2, &bAlways );
|
2821
|
+
if ( bXml ) {
|
2822
|
+
str_LineStart( szTag2, NULL, 0, pStr, ind );
|
2823
|
+
inchi_print( output_file, "%s\n", pStr );
|
2824
|
+
ind += inc;
|
2825
|
+
/* first line indent */
|
2826
|
+
strcpy( pStr, SP(ind));
|
2827
|
+
tot_len = ind;
|
2828
|
+
} else {
|
2829
|
+
pStr[tot_len = 0] = '\0';
|
2830
|
+
inchi_print( output_file, "%s%s", szTag2, pStr );
|
2831
|
+
}
|
2832
|
+
p = pOrigStruct->szCoord;
|
2833
|
+
length = strlen( p );
|
2834
|
+
line_len = nMaxLineLen - tot_len;
|
2835
|
+
for ( cur_pos = 0; cur_pos < length; cur_pos = last_pos ) {
|
2836
|
+
if ( length - cur_pos >= line_len ) {
|
2837
|
+
last_pos = cur_pos + line_len - 1;
|
2838
|
+
/* search backward for the nearest first coord. delimiter ";" */
|
2839
|
+
while ( cur_pos < last_pos && p[last_pos] != ';' ) {
|
2840
|
+
last_pos --;
|
2841
|
+
}
|
2842
|
+
if ( cur_pos < last_pos ) {
|
2843
|
+
last_pos ++; /* include ';' at the end of the line */
|
2844
|
+
}
|
2845
|
+
} else {
|
2846
|
+
last_pos = length;
|
2847
|
+
}
|
2848
|
+
if ( last_pos > cur_pos ) {
|
2849
|
+
memcpy( pStr + tot_len, p+cur_pos, last_pos - cur_pos );
|
2850
|
+
pStr[tot_len + last_pos - cur_pos] = '\0';
|
2851
|
+
inchi_print( output_file, "%s%s", pStr, !bXml && bPlainTextTags? "" : "\n" );
|
2852
|
+
} else {
|
2853
|
+
break;
|
2854
|
+
}
|
2855
|
+
}
|
2856
|
+
if ( bXml ) {
|
2857
|
+
ind -= inc;
|
2858
|
+
pStr[0] = '\0';
|
2859
|
+
if ( str_LineEnd( szTag2, 0, nMaxLineLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2860
|
+
goto exit_function;
|
2861
|
+
inchi_print( output_file, "%s", pStr );
|
2862
|
+
} else
|
2863
|
+
if ( pLF[0] ) {
|
2864
|
+
inchi_print( output_file, "%s", pLF );
|
2865
|
+
}
|
2866
|
+
if ( bXml ) {
|
2867
|
+
/***************************
|
2868
|
+
close reversibility info
|
2869
|
+
***************************/
|
2870
|
+
ind -= inc;
|
2871
|
+
if ( str_LineEnd( szTag1, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2872
|
+
goto exit_function;
|
2873
|
+
inchi_print( output_file, "%s", pStr );
|
2874
|
+
}
|
2875
|
+
}
|
2876
|
+
|
2877
|
+
|
2878
|
+
|
2879
|
+
/************************************************
|
2880
|
+
* output INChI_Aux of the reconnected structure *
|
2881
|
+
************************************************/
|
2882
|
+
bEmbeddedOutputCalled = 0;
|
2883
|
+
if ( bDisconnectedCoord && INCHI_BAS == iINChI && (bINChIOutputOptions & INCHI_OUT_EMBED_REC) &&
|
2884
|
+
num_components2[INCHI_REC] && !(bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) ) {
|
2885
|
+
int nRet;
|
2886
|
+
bEmbeddedOutputCalled = 1;
|
2887
|
+
if ( !bXml ) {
|
2888
|
+
inchi_print( output_file, "%s", pLF );
|
2889
|
+
}
|
2890
|
+
nRet = OutputINChI1( pStr, nStrLen, pINChISortTautAndNonTaut2, INCHI_REC, NULL,
|
2891
|
+
0 /*bDisconnectedCoord*/, bOutputType, INCHI_OUT_ONLY_AUX_INFO | bINChIOutputOptions,
|
2892
|
+
bXml, bAbcNumbers, bCtPredecessors, bNoStructLabels,
|
2893
|
+
num_components2, num_non_taut2, num_taut2,
|
2894
|
+
output_file, log_file, num_input_struct,
|
2895
|
+
szSdfLabel, szSdfValue, lSdfId, pSortPrintINChIFlags );
|
2896
|
+
if ( !nRet ) {
|
2897
|
+
goto exit_function; /* error */
|
2898
|
+
}
|
2899
|
+
}
|
2900
|
+
/* close INChI_Aux */
|
2901
|
+
if ( bXml ) {
|
2902
|
+
ind -= inc;
|
2903
|
+
if ( str_LineEnd( x_aux_basic, 0, nStrLen, &bOverflow, pStr, ind, bPlainTextTags ) )
|
2904
|
+
goto exit_function;
|
2905
|
+
inchi_print( output_file, "%s", pStr );
|
2906
|
+
} else
|
2907
|
+
if ( !bEmbeddedOutputCalled && !bPlainTextCommnts ) {
|
2908
|
+
inchi_print( output_file, "%s\n", (!num_components2[0] && !num_components2[1])? "//":"" );
|
2909
|
+
/* plain text comment earlier ended with LF */
|
2910
|
+
}
|
2911
|
+
} /* end of output aux info */
|
2912
|
+
ret = 1;
|
2913
|
+
exit_function:
|
2914
|
+
|
2915
|
+
if ( bOverflow ) {
|
2916
|
+
strcpy( pStr, "Output buffer overflow");
|
2917
|
+
if ( bXml ) {
|
2918
|
+
OutputINChIXmlError( output_file, pStr, nStrLen, ind /*, 0*/ /* err number */, pStr, _IS_FATAL );
|
2919
|
+
} else {
|
2920
|
+
inchi_print( output_file, "\nFATAL ERROR: %s\n", pStr );
|
2921
|
+
}
|
2922
|
+
}
|
2923
|
+
|
2924
|
+
/* inchi_free( pStr ); */
|
2925
|
+
return ret;
|
2926
|
+
}
|
2927
|
+
|
2928
|
+
/***************************************************************/
|
2929
|
+
int str_LineStart( const char *tag, char *tag2, int val2, char *pStr, int ind )
|
2930
|
+
{
|
2931
|
+
int tot_len = 0;
|
2932
|
+
if ( ind >= 0 ) {
|
2933
|
+
if ( ind > 0 ) {
|
2934
|
+
/* xml: indent */
|
2935
|
+
memset( pStr + tot_len, ' ', ind );
|
2936
|
+
tot_len += ind;
|
2937
|
+
}
|
2938
|
+
/* xml: tag */
|
2939
|
+
strcpy( pStr + tot_len, x_line_opening );
|
2940
|
+
strcat( pStr + tot_len, tag );
|
2941
|
+
if ( tag2 ) {
|
2942
|
+
tot_len += strlen(pStr + tot_len);
|
2943
|
+
tot_len += sprintf( pStr + tot_len, " %s=\"%d\"%s", tag2, val2, x_close_line );
|
2944
|
+
|
2945
|
+
} else {
|
2946
|
+
strcat( pStr + tot_len, x_close_line );
|
2947
|
+
tot_len += strlen(pStr + tot_len);
|
2948
|
+
}
|
2949
|
+
} else {
|
2950
|
+
pStr[tot_len] = '\0';
|
2951
|
+
}
|
2952
|
+
return tot_len;
|
2953
|
+
}
|
2954
|
+
/***************************************************************/
|
2955
|
+
int str_LineEnd( const char *tag, int tot_len, int nStrLen, int *bOverflow, char *pStr, int ind, int bPlainTextTags )
|
2956
|
+
{
|
2957
|
+
static int add_tag_len = sizeof(x_line_closing)-1 + sizeof(x_close_line)-1;
|
2958
|
+
int tag_len;
|
2959
|
+
/* check buffer overflow */
|
2960
|
+
if ( *bOverflow )
|
2961
|
+
return 1;
|
2962
|
+
if ( ind >= 0 ) { /* xml */
|
2963
|
+
tag_len = ind + add_tag_len + strlen(tag);
|
2964
|
+
if ( tot_len + tag_len < nStrLen - 2 ) {
|
2965
|
+
/* output " </tag>\n" */
|
2966
|
+
tot_len += sprintf( pStr + tot_len, "%s%s%s%s\n", SP(ind), x_line_closing, tag, x_close_line );
|
2967
|
+
} else {
|
2968
|
+
*bOverflow += 1;
|
2969
|
+
return 1;
|
2970
|
+
}
|
2971
|
+
} else { /* plain */
|
2972
|
+
pStr[tot_len] = '\0'; /* add zero termination 2004-04-26 */
|
2973
|
+
/* insert plain text tag if:
|
2974
|
+
(a) pStr has non-zero length, or
|
2975
|
+
(b) ind < -1
|
2976
|
+
*/
|
2977
|
+
if ( pStr[0] || ind < -1 ) {
|
2978
|
+
tag_len = bPlainTextTags? strlen( tag ):0;
|
2979
|
+
if ( tot_len + tag_len < nStrLen - 2 ) {
|
2980
|
+
if ( tag_len > 0 ) {
|
2981
|
+
/* insert plain text tag */
|
2982
|
+
memmove( pStr+tag_len, pStr, tot_len + 1 );
|
2983
|
+
memcpy( pStr, tag, tag_len );
|
2984
|
+
}
|
2985
|
+
} else {
|
2986
|
+
*bOverflow += 1;
|
2987
|
+
return 1;
|
2988
|
+
}
|
2989
|
+
}/* else
|
2990
|
+
if ( bPlainTextTags == 1 ) {
|
2991
|
+
strcpy( pStr, "/" );
|
2992
|
+
}*/
|
2993
|
+
}
|
2994
|
+
return 0;
|
2995
|
+
}
|
2996
|
+
/**********************************************************************************************/
|
2997
|
+
int CleanOrigCoord( MOL_COORD szCoord, int delim )
|
2998
|
+
{
|
2999
|
+
#define MIN_BOND_LENGTH (1.0e-6)
|
3000
|
+
char szVal[LEN_COORD+1];
|
3001
|
+
MOL_COORD szBuf;
|
3002
|
+
char *q;
|
3003
|
+
int len, last, fst, dec_pnt, num_zer=0, len_buf = 0, e;
|
3004
|
+
int k, i;
|
3005
|
+
double coord;
|
3006
|
+
|
3007
|
+
for ( k = 0; k < NUM_COORD*LEN_COORD; k += LEN_COORD ) {
|
3008
|
+
memcpy( szVal, szCoord+k, LEN_COORD );
|
3009
|
+
szVal[LEN_COORD] = '\0';
|
3010
|
+
LtrimRtrim(szVal, &len);
|
3011
|
+
coord = strtod(szVal, &q);
|
3012
|
+
if ( MIN_BOND_LENGTH > fabs(coord) ) {
|
3013
|
+
strcpy( szVal, "0" );
|
3014
|
+
len = 1;
|
3015
|
+
num_zer ++;
|
3016
|
+
} else {
|
3017
|
+
len = q - szVal;
|
3018
|
+
/* last = (last mantissa digit position + 1) */
|
3019
|
+
if ( (q = strchr(szVal, 'e')) || (q = strchr(szVal, 'E')) ||
|
3020
|
+
(q = strchr(szVal, 'd')) || (q = strchr(szVal, 'D')) ) {
|
3021
|
+
/* floating point */
|
3022
|
+
last = q - szVal;
|
3023
|
+
/* remove (+) and leading zeroes from the exponent */
|
3024
|
+
e = (int)strtol( szVal+last+1, &q, 10 ); /* exponent */
|
3025
|
+
if ( e ) {
|
3026
|
+
/* new exp; update the length */
|
3027
|
+
len = last+1+sprintf( szVal+last+1, "%d", e ); /* print exp without leading zeroes and '+' */
|
3028
|
+
} else {
|
3029
|
+
/* exponent is zero */
|
3030
|
+
len = last;
|
3031
|
+
}
|
3032
|
+
} else {
|
3033
|
+
last = len;
|
3034
|
+
}
|
3035
|
+
/* fst = (first mantissa digit); fst=1 if the sign is present, otherwise 0 */
|
3036
|
+
fst = (szVal[0]!='.' && !isdigit( UCINT szVal[0] ));
|
3037
|
+
/* dec_pnt = (decimal point position) or last */
|
3038
|
+
if ( q = strchr(szVal, '.') ) {
|
3039
|
+
dec_pnt = q - szVal;
|
3040
|
+
} else {
|
3041
|
+
dec_pnt = last;
|
3042
|
+
}
|
3043
|
+
last -= 1; /* last mantissa digit position */
|
3044
|
+
/* remove trailing zeroes in the range dec_pnt+1..last-1 */
|
3045
|
+
for ( i = last; dec_pnt < i && '0' == szVal[i]; i -- )
|
3046
|
+
;
|
3047
|
+
if ( i == dec_pnt ) {
|
3048
|
+
i --; /* remove decimal point, too */
|
3049
|
+
}
|
3050
|
+
if ( i < last ) {
|
3051
|
+
memmove( szVal+i+1, szVal+last+1, len-last );
|
3052
|
+
len -= last-i;
|
3053
|
+
}
|
3054
|
+
/* remove leading zeroes */
|
3055
|
+
for ( i = fst; i < len && '0' == szVal[i]; i ++ )
|
3056
|
+
;
|
3057
|
+
if ( i > fst ) {
|
3058
|
+
memmove( szVal + fst, szVal+i, len-fst );
|
3059
|
+
len -= i-fst;
|
3060
|
+
}
|
3061
|
+
}
|
3062
|
+
if ( len_buf )
|
3063
|
+
szBuf[len_buf++] = delim;
|
3064
|
+
memcpy( szBuf + len_buf, szVal, len ); /* does not copy zero termination*/
|
3065
|
+
len_buf += len;
|
3066
|
+
}
|
3067
|
+
/* zero termination */
|
3068
|
+
if ( len_buf < (int)sizeof(MOL_COORD) ) {
|
3069
|
+
memset( szBuf+len_buf, 0, sizeof(MOL_COORD) - len_buf);
|
3070
|
+
}
|
3071
|
+
memcpy( szCoord, szBuf, sizeof(MOL_COORD) );
|
3072
|
+
return num_zer;
|
3073
|
+
#undef MIN_BOND_LENGTH
|
3074
|
+
}
|
3075
|
+
|
3076
|
+
/******************************************************************************************/
|
3077
|
+
int WriteOrigCoord( int num_inp_atoms, MOL_COORD *szMolCoord, int *i, char *szBuf, int buf_len )
|
3078
|
+
{
|
3079
|
+
|
3080
|
+
int j, num_zer, len, cur_len;
|
3081
|
+
char *p;
|
3082
|
+
MOL_COORD szCurCoord;
|
3083
|
+
cur_len = 0;
|
3084
|
+
for ( j = *i; j < num_inp_atoms; ) {
|
3085
|
+
memcpy( szCurCoord, szMolCoord[j], sizeof(szCurCoord));
|
3086
|
+
num_zer = CleanOrigCoord( szCurCoord, ',' );
|
3087
|
+
if ( NUM_COORD == num_zer ) {
|
3088
|
+
len = 0;
|
3089
|
+
} else {
|
3090
|
+
if ( p = (char *)memchr( szCurCoord, '\0', sizeof(szCurCoord)) ) {
|
3091
|
+
len = p - szCurCoord;
|
3092
|
+
} else {
|
3093
|
+
len = sizeof(szCurCoord);
|
3094
|
+
}
|
3095
|
+
}
|
3096
|
+
if ( len + cur_len + 1 < buf_len ) {
|
3097
|
+
if ( len ) {
|
3098
|
+
memcpy( szBuf + cur_len, szCurCoord, len * sizeof(szBuf[0]) );
|
3099
|
+
}
|
3100
|
+
szBuf[cur_len += len] = ';';
|
3101
|
+
cur_len ++;
|
3102
|
+
j ++;
|
3103
|
+
} else {
|
3104
|
+
break;
|
3105
|
+
}
|
3106
|
+
}
|
3107
|
+
szBuf[cur_len] = '\0';
|
3108
|
+
*i = j; /* next item */
|
3109
|
+
return cur_len;
|
3110
|
+
}
|
3111
|
+
/******************************************************************************************/
|
3112
|
+
/*
|
3113
|
+
number of atoms
|
3114
|
+
[c|n] chiral/nonchiral
|
3115
|
+
|
3116
|
+
Element
|
3117
|
+
#valence
|
3118
|
+
+/-[charge>1]
|
3119
|
+
.#rad (#rad=1, 2, 3: singlet, doulet, triplet)
|
3120
|
+
[.]i#iso_mass
|
3121
|
+
[.]{o|e|u|?} atom parity = {1:2:3:4}
|
3122
|
+
[.]h[#of 1H>1]
|
3123
|
+
[.]d[#of 2H>1]
|
3124
|
+
[.]t[#of 3H>1]
|
3125
|
+
|
3126
|
+
Note: . occurs only once and only if radical or 1-character element
|
3127
|
+
*/
|
3128
|
+
int WriteOrigAtoms( int num_inp_atoms, inp_ATOM *at, int *i, char *szBuf, int buf_len, STRUCT_DATA *sd)
|
3129
|
+
{
|
3130
|
+
int j, k, n, len, len0, cur_len, val, mw, parity, num_trans, is_ok, b_self;
|
3131
|
+
static char szIsoH[] = "hdt";
|
3132
|
+
char szCurAtom[32];
|
3133
|
+
AT_NUMB nNeighOrder[MAXVAL], neigh;
|
3134
|
+
|
3135
|
+
cur_len = 0;
|
3136
|
+
if ( 0 == *i ) {
|
3137
|
+
cur_len = sprintf( szBuf, "%d%s", num_inp_atoms,
|
3138
|
+
(sd->bChiralFlag & FLAG_INP_AT_CHIRAL)? "c" :
|
3139
|
+
(sd->bChiralFlag & FLAG_INP_AT_NONCHIRAL)? "n" : "" );
|
3140
|
+
}
|
3141
|
+
for ( j = *i; j < num_inp_atoms; ) {
|
3142
|
+
/* tetrahedral parity treatment */
|
3143
|
+
parity = 0;
|
3144
|
+
num_trans = 0;
|
3145
|
+
if ( at[j].p_parity ) {
|
3146
|
+
/* verify neighbors */
|
3147
|
+
is_ok = 1;
|
3148
|
+
b_self = 0;
|
3149
|
+
for ( n = 0, k = 0; n < MAX_NUM_STEREO_ATOM_NEIGH; n ++ ) {
|
3150
|
+
neigh = at[j].p_orig_at_num[n]-1;
|
3151
|
+
if ( is_in_the_list( at[j].neighbor, neigh, at[j].valence ) &&
|
3152
|
+
at[neigh].orig_at_number == at[j].p_orig_at_num[n] ) {
|
3153
|
+
/* real neighbor */
|
3154
|
+
nNeighOrder[k ++] = at[j].p_orig_at_num[n];
|
3155
|
+
} else
|
3156
|
+
if ( (int)neigh == j && at[neigh].orig_at_number == at[j].p_orig_at_num[n] ) {
|
3157
|
+
/* central atom is a neighbor */
|
3158
|
+
num_trans = n; /* move this neighbor to 0 position permutation parity */
|
3159
|
+
b_self ++;
|
3160
|
+
} else {
|
3161
|
+
is_ok = 0;
|
3162
|
+
break;
|
3163
|
+
}
|
3164
|
+
}
|
3165
|
+
if ( is_ok && b_self <= 1 && b_self + k == MAX_NUM_STEREO_ATOM_NEIGH ) {
|
3166
|
+
num_trans += insertions_sort( nNeighOrder, k, sizeof(nNeighOrder[0]), comp_AT_RANK );
|
3167
|
+
if ( ATOM_PARITY_WELL_DEF( at[j].p_parity ) ) {
|
3168
|
+
parity = 2 - (num_trans + at[j].p_parity) % 2;
|
3169
|
+
} else
|
3170
|
+
if ( ATOM_PARITY_ILL_DEF( at[j].p_parity ) ) {
|
3171
|
+
parity = at[j].p_parity;
|
3172
|
+
} else {
|
3173
|
+
; /* invalid atom parity */
|
3174
|
+
}
|
3175
|
+
} else {
|
3176
|
+
;/* add error message here */
|
3177
|
+
}
|
3178
|
+
}
|
3179
|
+
|
3180
|
+
len = len0 = strlen( at[j].elname );
|
3181
|
+
memcpy( szCurAtom, at[j].elname, len );
|
3182
|
+
if ( (val=needed_unusual_el_valence( at[j].el_number, at[j].charge, at[j].radical,
|
3183
|
+
at[j].chem_bonds_valence, at[j].num_H, at[j].valence )) ||
|
3184
|
+
at[j].charge || at[j].radical || at[j].iso_atw_diff || NUM_ISO_H(at,j) || parity ) {
|
3185
|
+
/* valence */
|
3186
|
+
if ( val ) {
|
3187
|
+
len += sprintf( szCurAtom + len, "%d", val > 0? val : 0 );
|
3188
|
+
}
|
3189
|
+
/* charge */
|
3190
|
+
if ( val = at[j].charge ) {
|
3191
|
+
szCurAtom[len++] = val>0? '+' : '-';
|
3192
|
+
if ( (val = abs(val)) > 1 ) {
|
3193
|
+
len += sprintf( szCurAtom + len, "%d", val );
|
3194
|
+
}
|
3195
|
+
}
|
3196
|
+
/* radical */
|
3197
|
+
if ( val = at[j].radical ) {
|
3198
|
+
len += sprintf(szCurAtom + len, ".%d", val);
|
3199
|
+
}
|
3200
|
+
/* isotopic shift */
|
3201
|
+
if ( val = at[j].iso_atw_diff ) {
|
3202
|
+
mw = get_atw_from_elnum( at[j].el_number );
|
3203
|
+
if ( val == 1 )
|
3204
|
+
val = mw;
|
3205
|
+
else
|
3206
|
+
if ( val > 0 )
|
3207
|
+
val = mw + val -1;
|
3208
|
+
else
|
3209
|
+
val = mw + val;
|
3210
|
+
len += sprintf( szCurAtom + len, "%si%d", len == len0? ".":"", val );
|
3211
|
+
}
|
3212
|
+
/* parity */
|
3213
|
+
if ( parity ) {
|
3214
|
+
len += sprintf( szCurAtom + len, "%s%s", len == len0? ".":"",
|
3215
|
+
parity == AB_PARITY_ODD? "o" :
|
3216
|
+
parity == AB_PARITY_EVEN? "e" :
|
3217
|
+
parity == AB_PARITY_UNKN? "u" :
|
3218
|
+
parity == AB_PARITY_UNDF? "?" : "" );
|
3219
|
+
}
|
3220
|
+
/* implicit isotopic H */
|
3221
|
+
if ( NUM_ISO_H(at,j) ) {
|
3222
|
+
for ( k = 0; k < NUM_H_ISOTOPES; k ++ ) {
|
3223
|
+
if ( val = at[j].num_iso_H[k] ) {
|
3224
|
+
len += sprintf( szCurAtom + len, "%s%c", len == len0? ".":"", szIsoH[k] );
|
3225
|
+
if ( val > 1 ) {
|
3226
|
+
len += sprintf(szCurAtom + len, "%d", val);
|
3227
|
+
}
|
3228
|
+
}
|
3229
|
+
}
|
3230
|
+
}
|
3231
|
+
}
|
3232
|
+
if ( len + cur_len < buf_len ) {
|
3233
|
+
memcpy( szBuf + cur_len, szCurAtom, len );
|
3234
|
+
cur_len += len;
|
3235
|
+
j ++;
|
3236
|
+
} else {
|
3237
|
+
break;
|
3238
|
+
}
|
3239
|
+
szBuf[cur_len] = '\0';
|
3240
|
+
*i = j;
|
3241
|
+
|
3242
|
+
}
|
3243
|
+
return cur_len;
|
3244
|
+
}
|
3245
|
+
/******************************************************************************************/
|
3246
|
+
/*
|
3247
|
+
<bonds> bpA;bpAbpA... </bonds>
|
3248
|
+
|
3249
|
+
b = bond type:
|
3250
|
+
=============
|
3251
|
+
v = undefined stereo, single
|
3252
|
+
w = undefined stereo, double
|
3253
|
+
s = single
|
3254
|
+
d = double
|
3255
|
+
t = triple
|
3256
|
+
a = aromatic
|
3257
|
+
p = up from the current atom to the neighbor
|
3258
|
+
P = uP from the neighbor to the current atom
|
3259
|
+
n = down from the current atom to the neighbor
|
3260
|
+
N = dowN from the neighbor to the current atom
|
3261
|
+
|
3262
|
+
p = bond parity:
|
3263
|
+
================
|
3264
|
+
- = odd
|
3265
|
+
+ = even
|
3266
|
+
u = unknown
|
3267
|
+
? = undefined
|
3268
|
+
= no parity (empty)
|
3269
|
+
|
3270
|
+
|
3271
|
+
A=orig. number
|
3272
|
+
===============
|
3273
|
+
of the neighbor < number of the current atom
|
3274
|
+
Number of the current atom: 2 until first ";", 3 until 2nd ";", etc.
|
3275
|
+
|
3276
|
+
*/
|
3277
|
+
|
3278
|
+
/************************************************************************************/
|
3279
|
+
/* output bonds in ascending order of the neighboring atom original numbers */
|
3280
|
+
int WriteOrigBonds( int num_inp_atoms, inp_ATOM *at, int *i, char *szBuf, int buf_len, STRUCT_DATA *sd)
|
3281
|
+
{
|
3282
|
+
int j, k, k2, kk, len, cur_len, j2=0, bond_stereo, bond_char, bond_parity, bond_parityNM, num_trans;
|
3283
|
+
char szCurBonds[5*MAXVAL+1+2*MAXVAL]; /* 1 byte bond type + up to 4 digits per neighbor number + 1 + 2*sign for bond parity; */
|
3284
|
+
AT_RANK nNeighOrder[MAXVAL];
|
3285
|
+
int chain_len, pnxt_atom, pinxt2cur, pinxt_sb_parity_ord;
|
3286
|
+
int chain_len2, pnxt_atom2, pinxt2cur2, pinxt_sb_parity_ord2, m1, m2;
|
3287
|
+
int pcur_atom, picur2nxt, picur_sb_parity_ord;
|
3288
|
+
|
3289
|
+
cur_len = 0;
|
3290
|
+
for ( j = *i; j < num_inp_atoms; ) {
|
3291
|
+
len = 0;
|
3292
|
+
if ( at[j].valence > 1 ) {
|
3293
|
+
for ( k = 0; k < at[j].valence; k ++ ) {
|
3294
|
+
nNeighOrder[k] = k;
|
3295
|
+
}
|
3296
|
+
pn_RankForSort = at[j].neighbor;
|
3297
|
+
num_trans = insertions_sort( nNeighOrder, at[j].valence, sizeof(nNeighOrder[0]), CompRank );
|
3298
|
+
} else {
|
3299
|
+
num_trans = 0;
|
3300
|
+
nNeighOrder[0] = 0;
|
3301
|
+
}
|
3302
|
+
for ( kk = 0; kk < at[j].valence; kk ++ ) {
|
3303
|
+
k = nNeighOrder[kk];
|
3304
|
+
j2 = at[j].neighbor[k];
|
3305
|
+
bond_parity = 0;
|
3306
|
+
bond_parityNM = 0;
|
3307
|
+
if ( j2 < j ) {
|
3308
|
+
bond_stereo = at[j].bond_stereo[k];
|
3309
|
+
switch( at[j].bond_type[k] ) {
|
3310
|
+
case BOND_TYPE_SINGLE:
|
3311
|
+
switch( bond_stereo ) {
|
3312
|
+
case STEREO_SNGL_UP:
|
3313
|
+
bond_char = 'p';
|
3314
|
+
break;
|
3315
|
+
case -STEREO_SNGL_UP:
|
3316
|
+
bond_char = 'P';
|
3317
|
+
break;
|
3318
|
+
case STEREO_SNGL_DOWN:
|
3319
|
+
bond_char = 'n';
|
3320
|
+
break;
|
3321
|
+
case -STEREO_SNGL_DOWN:
|
3322
|
+
bond_char = 'N';
|
3323
|
+
break;
|
3324
|
+
case STEREO_SNGL_EITHER:
|
3325
|
+
case -STEREO_SNGL_EITHER:
|
3326
|
+
bond_char = 'v';
|
3327
|
+
break;
|
3328
|
+
default:
|
3329
|
+
bond_char = 's';
|
3330
|
+
break;
|
3331
|
+
}
|
3332
|
+
break;
|
3333
|
+
case BOND_TYPE_DOUBLE:
|
3334
|
+
switch( bond_stereo ) {
|
3335
|
+
case STEREO_DBLE_EITHER:
|
3336
|
+
case -STEREO_DBLE_EITHER:
|
3337
|
+
bond_char = 'w';
|
3338
|
+
break;
|
3339
|
+
default:
|
3340
|
+
bond_char = 'd';
|
3341
|
+
break;
|
3342
|
+
}
|
3343
|
+
break;
|
3344
|
+
case BOND_TYPE_TRIPLE:
|
3345
|
+
bond_char = 't';
|
3346
|
+
break;
|
3347
|
+
case BOND_TYPE_ALTERN:
|
3348
|
+
bond_char = 'a';
|
3349
|
+
break;
|
3350
|
+
default:
|
3351
|
+
bond_char = 's';
|
3352
|
+
break;
|
3353
|
+
}
|
3354
|
+
/* check for allene/cumulene */
|
3355
|
+
k2 = is_in_the_list( at[j2].neighbor, (AT_NUMB)j, at[j2].valence ) - at[j2].neighbor;
|
3356
|
+
chain_len = chain_len2 = 0;
|
3357
|
+
if ( at[j].sb_parity[0] ) {
|
3358
|
+
for ( m1 = 0; m1 < MAX_NUM_STEREO_BONDS && at[j].sb_parity[m1]; m1 ++ ) {
|
3359
|
+
if ( k == at[j].sb_ord[m1] ) {
|
3360
|
+
chain_len = get_opposite_sb_atom( at, j, k,
|
3361
|
+
&pnxt_atom, &pinxt2cur, &pinxt_sb_parity_ord );
|
3362
|
+
break;
|
3363
|
+
}
|
3364
|
+
}
|
3365
|
+
}
|
3366
|
+
if ( at[j2].sb_parity[0] ) {
|
3367
|
+
for ( m2 = 0; m2 < MAX_NUM_STEREO_BONDS && at[j2].sb_parity[m2]; m2 ++ ) {
|
3368
|
+
if ( k2 == at[j2].sb_ord[m2] ) {
|
3369
|
+
chain_len2 = get_opposite_sb_atom( at, j2, k2,
|
3370
|
+
&pnxt_atom2, &pinxt2cur2, &pinxt_sb_parity_ord2 );
|
3371
|
+
break;
|
3372
|
+
}
|
3373
|
+
}
|
3374
|
+
}
|
3375
|
+
if ( chain_len == 1 && chain_len2 == 1 || /* regular stereobond */
|
3376
|
+
chain_len > 1 && j > pnxt_atom ) { /* j is a cumulene endpoint */
|
3377
|
+
int m;
|
3378
|
+
pcur_atom = j; /* pcur_atom > pnxt_atom */
|
3379
|
+
picur2nxt = k;
|
3380
|
+
picur_sb_parity_ord = -1;
|
3381
|
+
for ( m = 0; m < MAX_NUM_STEREO_BONDS && at[pcur_atom].sb_parity[m]; m ++ ) {
|
3382
|
+
if ( at[pcur_atom].sb_ord[m] == k ) {
|
3383
|
+
picur_sb_parity_ord = m;
|
3384
|
+
break;
|
3385
|
+
}
|
3386
|
+
}
|
3387
|
+
chain_len2 = 0;
|
3388
|
+
} else
|
3389
|
+
if ( chain_len2 > 1 && j2 > pnxt_atom2 ) { /* j2 is a cumulene endpoint */
|
3390
|
+
int m;
|
3391
|
+
pcur_atom = j2;
|
3392
|
+
picur2nxt = k2;
|
3393
|
+
pnxt_atom = pnxt_atom2;
|
3394
|
+
pinxt2cur = pinxt2cur2;
|
3395
|
+
pinxt_sb_parity_ord = pinxt_sb_parity_ord2;
|
3396
|
+
picur_sb_parity_ord = -1;
|
3397
|
+
for ( m = 0; m < MAX_NUM_STEREO_BONDS && at[pcur_atom].sb_parity[m]; m ++ ) {
|
3398
|
+
if ( at[pcur_atom].sb_ord[m] == k2 )
|
3399
|
+
picur_sb_parity_ord = m;
|
3400
|
+
}
|
3401
|
+
chain_len = chain_len2;
|
3402
|
+
chain_len2 = 0;
|
3403
|
+
} else {
|
3404
|
+
chain_len = chain_len2 = 0;
|
3405
|
+
}
|
3406
|
+
|
3407
|
+
/*len += sprintf( szCurBonds + len, "%c%d", bond_char, val+1);*/
|
3408
|
+
if ( chain_len ) {
|
3409
|
+
/* both atoms belong to a stereo bond */
|
3410
|
+
int kc;
|
3411
|
+
int p1, p2, p1NM, p2NM, neigh, neigh1, neigh2, bHasMetal, bWellDef;
|
3412
|
+
int bNeighSwitched1, bNeighSwitched2;
|
3413
|
+
|
3414
|
+
p1 = SB_PARITY_1(at[pcur_atom].sb_parity[picur_sb_parity_ord]);
|
3415
|
+
p1NM = SB_PARITY_2(at[pcur_atom].sb_parity[picur_sb_parity_ord]);
|
3416
|
+
p2 = SB_PARITY_1(at[pnxt_atom].sb_parity[pinxt_sb_parity_ord]);
|
3417
|
+
p2NM = SB_PARITY_2(at[pnxt_atom].sb_parity[pinxt_sb_parity_ord]);
|
3418
|
+
|
3419
|
+
bWellDef = ATOM_PARITY_WELL_DEF(p1) && ATOM_PARITY_WELL_DEF(p2);
|
3420
|
+
bHasMetal = ATOM_PARITY_WELL_DEF(p1NM) && ATOM_PARITY_WELL_DEF(p2NM);
|
3421
|
+
|
3422
|
+
bNeighSwitched1 = bNeighSwitched2 = 0;
|
3423
|
+
|
3424
|
+
if ( bWellDef || bHasMetal ) {
|
3425
|
+
|
3426
|
+
neigh1 = num_inp_atoms;
|
3427
|
+
for ( kc = 0; kc < at[pcur_atom].valence; kc ++ ) {
|
3428
|
+
if ( kc == picur2nxt )
|
3429
|
+
continue;
|
3430
|
+
neigh = at[pcur_atom].neighbor[kc];
|
3431
|
+
if ( bHasMetal && is_el_a_metal( at[neigh].el_number ) )
|
3432
|
+
continue;
|
3433
|
+
if ( neigh < neigh1 )
|
3434
|
+
neigh1 = neigh;
|
3435
|
+
}
|
3436
|
+
if ( neigh1 < num_inp_atoms ) {
|
3437
|
+
bNeighSwitched1 = (neigh1 != at[pcur_atom].neighbor[(int)at[pcur_atom].sn_ord[picur_sb_parity_ord]]);
|
3438
|
+
} else {
|
3439
|
+
AddMOLfileError(sd->pStrErrStruct, "Cannot find 0D stereobond neighbor");
|
3440
|
+
/*
|
3441
|
+
sd->nStructReadError = 99;
|
3442
|
+
sd->nErrorType = _IS_ERROR;
|
3443
|
+
*/
|
3444
|
+
|
3445
|
+
}
|
3446
|
+
|
3447
|
+
neigh2 = num_inp_atoms;
|
3448
|
+
for ( kc = 0; kc < at[pnxt_atom].valence; kc ++ ) {
|
3449
|
+
if ( kc == pinxt2cur )
|
3450
|
+
continue;
|
3451
|
+
neigh = at[pnxt_atom].neighbor[kc];
|
3452
|
+
if ( bHasMetal && is_el_a_metal( at[neigh].el_number ) )
|
3453
|
+
continue;
|
3454
|
+
if ( neigh < neigh2 )
|
3455
|
+
neigh2 = neigh;
|
3456
|
+
}
|
3457
|
+
if ( neigh2 < num_inp_atoms ) {
|
3458
|
+
bNeighSwitched2 = (neigh2 != at[pnxt_atom].neighbor[(int)at[pnxt_atom].sn_ord[pinxt_sb_parity_ord]]);
|
3459
|
+
} else {
|
3460
|
+
AddMOLfileError(sd->pStrErrStruct, "Cannot find 0D stereobond neighbor");
|
3461
|
+
/*
|
3462
|
+
sd->nStructReadError = 99;
|
3463
|
+
sd->nErrorType = _IS_ERROR;
|
3464
|
+
*/
|
3465
|
+
|
3466
|
+
}
|
3467
|
+
|
3468
|
+
if ( neigh1 < num_inp_atoms && neigh2 < num_inp_atoms ) {
|
3469
|
+
if ( ATOM_PARITY_WELL_DEF(p1) && ATOM_PARITY_WELL_DEF(p2) ) {
|
3470
|
+
bond_parity = 2 - (p1 + p2 + bNeighSwitched1 + bNeighSwitched2) % 2;
|
3471
|
+
} else {
|
3472
|
+
bond_parity = inchi_min( p1, p2 );
|
3473
|
+
}
|
3474
|
+
|
3475
|
+
if ( bHasMetal ) {
|
3476
|
+
bond_parityNM = 2 - (p1NM + p2NM + bNeighSwitched1 + bNeighSwitched2) % 2;
|
3477
|
+
} else
|
3478
|
+
if ( p1NM && p2NM ) {
|
3479
|
+
bond_parityNM = inchi_min( p1NM, p2NM );
|
3480
|
+
}
|
3481
|
+
}
|
3482
|
+
} else {
|
3483
|
+
if ( p1 && p2 ) {
|
3484
|
+
bond_parity = inchi_min( p1, p2 );
|
3485
|
+
}
|
3486
|
+
if ( p1NM && p2NM ) {
|
3487
|
+
bond_parityNM = inchi_min( p1NM, p2NM );
|
3488
|
+
}
|
3489
|
+
if ( bond_parityNM && !bond_parity ) {
|
3490
|
+
bond_parity = AB_PARITY_UNDF;
|
3491
|
+
}
|
3492
|
+
}
|
3493
|
+
}
|
3494
|
+
len += sprintf( szCurBonds + len, "%c%s%s%d",
|
3495
|
+
|
3496
|
+
bond_char,
|
3497
|
+
|
3498
|
+
(bond_parity == AB_PARITY_ODD)? "-" :
|
3499
|
+
(bond_parity == AB_PARITY_EVEN)? "+" :
|
3500
|
+
(bond_parity == AB_PARITY_UNKN)? "u" :
|
3501
|
+
(bond_parity == AB_PARITY_UNDF)? "?" : "",
|
3502
|
+
|
3503
|
+
(bond_parityNM == AB_PARITY_ODD)? "-" :
|
3504
|
+
(bond_parityNM == AB_PARITY_EVEN)? "+" :
|
3505
|
+
(bond_parityNM == AB_PARITY_UNKN)? "u" :
|
3506
|
+
(bond_parityNM == AB_PARITY_UNDF)? "?" : "",
|
3507
|
+
|
3508
|
+
j2+1);
|
3509
|
+
}
|
3510
|
+
}
|
3511
|
+
if ( len + cur_len + 2 < buf_len ) {
|
3512
|
+
memcpy( szBuf + cur_len, szCurBonds, len );
|
3513
|
+
cur_len += len;
|
3514
|
+
szBuf[ cur_len ++ ] = ';';
|
3515
|
+
j ++;
|
3516
|
+
} else {
|
3517
|
+
break;
|
3518
|
+
}
|
3519
|
+
}
|
3520
|
+
szBuf[cur_len] = '\0';
|
3521
|
+
*i = num_inp_atoms>0? j : 0;
|
3522
|
+
return cur_len;
|
3523
|
+
}
|
3524
|
+
|
3525
|
+
|
3526
|
+
#define ORIG_STR_BUFLEN 64 /* > 5*MAXVAL+2 = 52 */
|
3527
|
+
/******************************************************************************************/
|
3528
|
+
int FillOutOrigStruct( ORIG_ATOM_DATA *orig_inp_data, ORIG_STRUCT *pOrigStruct, STRUCT_DATA *sd )
|
3529
|
+
{
|
3530
|
+
char szBuf[ORIG_STR_BUFLEN];
|
3531
|
+
int i, len, len_coord, len_atoms, len_bonds;
|
3532
|
+
/* coordinates */
|
3533
|
+
len_coord = i = 0;
|
3534
|
+
|
3535
|
+
if (orig_inp_data->szCoord) {
|
3536
|
+
|
3537
|
+
while ( len = WriteOrigCoord( orig_inp_data->num_inp_atoms,
|
3538
|
+
orig_inp_data->szCoord, &i, szBuf, sizeof(szBuf) )) {
|
3539
|
+
len_coord += len;
|
3540
|
+
}
|
3541
|
+
pOrigStruct->szCoord = (char*) inchi_malloc( (len_coord + 1)*sizeof(pOrigStruct->szCoord[0]) );
|
3542
|
+
i = 0;
|
3543
|
+
if ( pOrigStruct->szCoord &&
|
3544
|
+
len_coord == WriteOrigCoord( orig_inp_data->num_inp_atoms,
|
3545
|
+
orig_inp_data->szCoord, &i, pOrigStruct->szCoord, len_coord+1 ) &&
|
3546
|
+
i == orig_inp_data->num_inp_atoms ) {
|
3547
|
+
/* success */
|
3548
|
+
if ( orig_inp_data->szCoord ) {
|
3549
|
+
inchi_free( orig_inp_data->szCoord );
|
3550
|
+
orig_inp_data->szCoord = NULL;
|
3551
|
+
}
|
3552
|
+
} else {
|
3553
|
+
return -1;
|
3554
|
+
}
|
3555
|
+
|
3556
|
+
}
|
3557
|
+
|
3558
|
+
/* atoms */
|
3559
|
+
len_atoms = i = 0;
|
3560
|
+
while ( len = WriteOrigAtoms( orig_inp_data->num_inp_atoms,
|
3561
|
+
orig_inp_data->at, &i, szBuf, sizeof(szBuf), sd)) {
|
3562
|
+
len_atoms += len;
|
3563
|
+
if ( !orig_inp_data->num_inp_atoms )
|
3564
|
+
break;
|
3565
|
+
}
|
3566
|
+
pOrigStruct->szAtoms = (char*) inchi_malloc( (len_atoms + 1)*sizeof(pOrigStruct->szAtoms[0]) );
|
3567
|
+
i = 0;
|
3568
|
+
if ( pOrigStruct->szAtoms &&
|
3569
|
+
len_atoms == WriteOrigAtoms( orig_inp_data->num_inp_atoms,
|
3570
|
+
orig_inp_data->at, &i, pOrigStruct->szAtoms, len_atoms+1, sd ) &&
|
3571
|
+
i == orig_inp_data->num_inp_atoms ) {
|
3572
|
+
; /* success */
|
3573
|
+
} else {
|
3574
|
+
return -1;
|
3575
|
+
}
|
3576
|
+
/* bonds */
|
3577
|
+
len_bonds = 0;
|
3578
|
+
i = 1;
|
3579
|
+
while ( len = WriteOrigBonds( orig_inp_data->num_inp_atoms,
|
3580
|
+
orig_inp_data->at, &i, szBuf, sizeof(szBuf), NULL)) {
|
3581
|
+
len_bonds += len;
|
3582
|
+
if ( !orig_inp_data->num_inp_atoms )
|
3583
|
+
break;
|
3584
|
+
}
|
3585
|
+
pOrigStruct->szBonds = (char*) inchi_malloc( (len_bonds + 2)*sizeof(pOrigStruct->szBonds[0]) );
|
3586
|
+
i = 1;
|
3587
|
+
if ( pOrigStruct->szBonds &&
|
3588
|
+
len_bonds == WriteOrigBonds( orig_inp_data->num_inp_atoms,
|
3589
|
+
orig_inp_data->at, &i, pOrigStruct->szBonds, len_bonds+2, sd ) &&
|
3590
|
+
i == orig_inp_data->num_inp_atoms ) {
|
3591
|
+
; /* success */
|
3592
|
+
} else {
|
3593
|
+
return -1;
|
3594
|
+
}
|
3595
|
+
pOrigStruct->num_atoms = orig_inp_data->num_inp_atoms;
|
3596
|
+
return 0;
|
3597
|
+
}
|
3598
|
+
/*****************************************************************/
|
3599
|
+
void FreeOrigStruct( ORIG_STRUCT *pOrigStruct)
|
3600
|
+
{
|
3601
|
+
if ( pOrigStruct ) {
|
3602
|
+
if ( pOrigStruct->szAtoms )
|
3603
|
+
inchi_free( pOrigStruct->szAtoms );
|
3604
|
+
if ( pOrigStruct->szBonds )
|
3605
|
+
inchi_free( pOrigStruct->szBonds );
|
3606
|
+
if ( pOrigStruct->szCoord )
|
3607
|
+
inchi_free( pOrigStruct->szCoord );
|
3608
|
+
memset( pOrigStruct, 0, sizeof(*pOrigStruct) );
|
3609
|
+
|
3610
|
+
}
|
3611
|
+
}
|
3612
|
+
|