rino 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|