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/inchi_dll.c
ADDED
@@ -0,0 +1,1480 @@
|
|
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 "mode.h"
|
11
|
+
|
12
|
+
#include <stdio.h>
|
13
|
+
#include <stdlib.h>
|
14
|
+
#include <string.h>
|
15
|
+
#include <ctype.h>
|
16
|
+
#include <stdarg.h>
|
17
|
+
#include <errno.h>
|
18
|
+
#include <limits.h>
|
19
|
+
#include <float.h>
|
20
|
+
#include <math.h>
|
21
|
+
|
22
|
+
#include "inpdef.h"
|
23
|
+
#include "ichi.h"
|
24
|
+
#include "strutil.h"
|
25
|
+
#include "util.h"
|
26
|
+
#include "ichierr.h"
|
27
|
+
#include "ichimain.h"
|
28
|
+
#include "extr_ct.h"
|
29
|
+
|
30
|
+
#include "ichicomp.h"
|
31
|
+
#include "inchi_api.h"
|
32
|
+
#include "inchi_dll.h"
|
33
|
+
|
34
|
+
/*************************************************************************
|
35
|
+
*
|
36
|
+
* Local protopypes
|
37
|
+
*
|
38
|
+
*************************************************************************/
|
39
|
+
|
40
|
+
|
41
|
+
int SetAtomProperties( inp_ATOM *at, MOL_COORD *szCoord, inchi_Atom *ati,
|
42
|
+
int a1, int *nDim, char *pStrErr, int *err );
|
43
|
+
int SetBondProperties( inp_ATOM *at, inchi_Atom *ati, int a1, int j,
|
44
|
+
int nNumAtoms, int *nNumBonds, char *pStrErr, int *err );
|
45
|
+
int SetAtomAndBondProperties( inp_ATOM *at, inchi_Atom *ati, int a1,
|
46
|
+
int bDoNotAddH, char *pStrErr, int *err );
|
47
|
+
void SetNumImplicitH(inp_ATOM* at, int num_atoms);
|
48
|
+
int Extract0DParities( inp_ATOM *at, int nNumAtoms, inchi_Stereo0D *stereo0D,
|
49
|
+
int num_stereo0D, char *pStrErr, int *err );
|
50
|
+
int parse_options_string ( char *cmd, const char *argv[], int maxargs );
|
51
|
+
|
52
|
+
/*************************************************************************/
|
53
|
+
|
54
|
+
int bInterrupted = 0;
|
55
|
+
|
56
|
+
#if( defined( _WIN32 ) && defined( _CONSOLE ) )
|
57
|
+
|
58
|
+
#ifndef INCHI_ANSI_ONLY
|
59
|
+
BOOL WINAPI MyHandlerRoutine(
|
60
|
+
DWORD dwCtrlType /* control signal type */
|
61
|
+
) {
|
62
|
+
if ( dwCtrlType == CTRL_C_EVENT ||
|
63
|
+
dwCtrlType == CTRL_BREAK_EVENT ||
|
64
|
+
dwCtrlType == CTRL_CLOSE_EVENT ||
|
65
|
+
dwCtrlType == CTRL_LOGOFF_EVENT ) {
|
66
|
+
bInterrupted = 1;
|
67
|
+
return TRUE;
|
68
|
+
}
|
69
|
+
return FALSE;
|
70
|
+
}
|
71
|
+
#endif
|
72
|
+
int WasInterrupted(void) {
|
73
|
+
#ifdef _DEBUG
|
74
|
+
if ( bInterrupted ) {
|
75
|
+
int stop=1; /* for debug only <BRKPT> */
|
76
|
+
}
|
77
|
+
#endif
|
78
|
+
return bInterrupted;
|
79
|
+
}
|
80
|
+
|
81
|
+
#endif
|
82
|
+
|
83
|
+
|
84
|
+
/********************************************************************
|
85
|
+
*
|
86
|
+
* INCHI API: DEALLOCATE INCHI OUTPUT
|
87
|
+
*
|
88
|
+
********************************************************************/
|
89
|
+
void INCHI_DECL FreeINCHI( inchi_Output *out )
|
90
|
+
{
|
91
|
+
if ( out->szInChI ) {
|
92
|
+
inchi_free( out->szInChI );
|
93
|
+
}
|
94
|
+
if ( out->szLog ) {
|
95
|
+
inchi_free( out->szLog );
|
96
|
+
}
|
97
|
+
if ( out->szMessage ) {
|
98
|
+
inchi_free( out->szMessage );
|
99
|
+
}
|
100
|
+
memset( out, 0, sizeof(*out) );
|
101
|
+
}
|
102
|
+
/********************************************************************/
|
103
|
+
#define INCHI_MAX_NUM_ARG 32
|
104
|
+
/********************************************************************
|
105
|
+
*
|
106
|
+
* INCHI API: MAIN ENTRY POINT
|
107
|
+
*
|
108
|
+
********************************************************************/
|
109
|
+
|
110
|
+
int bLibInchiSemaphore = 0;
|
111
|
+
|
112
|
+
int INCHI_DECL GetINCHI( inchi_Input *inp, inchi_Output *out )
|
113
|
+
{
|
114
|
+
|
115
|
+
STRUCT_DATA struct_data;
|
116
|
+
STRUCT_DATA *sd = &struct_data;
|
117
|
+
FILE *inp_file = NULL;
|
118
|
+
INCHI_FILE inchi_file[3];
|
119
|
+
INCHI_FILE *output_file = inchi_file, *log_file = inchi_file+1, *prb_file = inchi_file+2;
|
120
|
+
char szTitle[MAX_SDF_HEADER+MAX_SDF_VALUE+256];
|
121
|
+
|
122
|
+
int i, num_inp, num_err, num_output;
|
123
|
+
char szSdfDataValue[MAX_SDF_VALUE+1];
|
124
|
+
PINChI2 *pINChI[INCHI_NUM];
|
125
|
+
PINChI_Aux2 *pINChI_Aux[INCHI_NUM];
|
126
|
+
|
127
|
+
unsigned long ulDisplTime = 0; /* infinite, milliseconds */
|
128
|
+
unsigned long ulTotalProcessingTime = 0;
|
129
|
+
|
130
|
+
INPUT_PARMS inp_parms;
|
131
|
+
INPUT_PARMS *ip = &inp_parms;
|
132
|
+
|
133
|
+
ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */
|
134
|
+
ORIG_ATOM_DATA *orig_inp_data = &OrigAtData;
|
135
|
+
ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */
|
136
|
+
ORIG_ATOM_DATA *prep_inp_data = PrepAtData;
|
137
|
+
int bReleaseVersion = bRELEASE_VERSION;
|
138
|
+
const int nStrLen = 64000;
|
139
|
+
char *pStr = NULL;
|
140
|
+
int nRet = 0, nRet1;
|
141
|
+
|
142
|
+
STRUCT_FPTRS *pStructPtrs = NULL;
|
143
|
+
|
144
|
+
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
|
145
|
+
int num_repeat = REPEAT_ALL;
|
146
|
+
#endif
|
147
|
+
|
148
|
+
const char *argv[INCHI_MAX_NUM_ARG+1];
|
149
|
+
int argc;
|
150
|
+
char *szOptions = NULL;
|
151
|
+
|
152
|
+
if ( bLibInchiSemaphore ) { /* does not work properly under sufficient stress */
|
153
|
+
return inchi_Ret_BUSY;
|
154
|
+
}
|
155
|
+
bLibInchiSemaphore = 1;
|
156
|
+
|
157
|
+
#if( TRACE_MEMORY_LEAKS == 1 )
|
158
|
+
_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
|
159
|
+
/* for execution outside the VC++ debugger uncomment one of the following two */
|
160
|
+
#ifdef MY_REPORT_FILE
|
161
|
+
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
|
162
|
+
_CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
|
163
|
+
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
|
164
|
+
_CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
|
165
|
+
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
|
166
|
+
_CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
|
167
|
+
#else
|
168
|
+
_CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG);
|
169
|
+
#endif
|
170
|
+
|
171
|
+
/* turn on floating point exceptions */
|
172
|
+
{
|
173
|
+
/* Get the default control word. */
|
174
|
+
int cw = _controlfp( 0,0 );
|
175
|
+
|
176
|
+
/* Set the exception masks OFF, turn exceptions on. */
|
177
|
+
/*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
|
178
|
+
cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_ZERODIVIDE|EM_DENORMAL);
|
179
|
+
|
180
|
+
/* Set the control word. */
|
181
|
+
_controlfp( cw, MCW_EM );
|
182
|
+
|
183
|
+
}
|
184
|
+
#endif
|
185
|
+
|
186
|
+
|
187
|
+
#if( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( INCHI_ANSI_ONLY ) )
|
188
|
+
if ( SetConsoleCtrlHandler( MyHandlerRoutine, 1 ) ) {
|
189
|
+
ConsoleQuit = WasInterrupted;
|
190
|
+
}
|
191
|
+
#endif
|
192
|
+
|
193
|
+
memset( inchi_file, 0, sizeof(inchi_file) );
|
194
|
+
|
195
|
+
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
|
196
|
+
repeat:
|
197
|
+
inp_file = output_file = log_file = prb_file = NULL;
|
198
|
+
pStr = NULL;
|
199
|
+
#endif
|
200
|
+
|
201
|
+
num_inp = 0;
|
202
|
+
num_err = 0;
|
203
|
+
num_output = 0;
|
204
|
+
sd->bUserQuit = 0;
|
205
|
+
|
206
|
+
/* clear original input structure */
|
207
|
+
memset( pINChI, 0, sizeof(pINChI ) );
|
208
|
+
memset( pINChI_Aux, 0, sizeof(pINChI_Aux) );
|
209
|
+
memset( sd, 0, sizeof(*sd) );
|
210
|
+
memset( ip, 0, sizeof(*ip) );
|
211
|
+
memset( orig_inp_data , 0, sizeof( *orig_inp_data ) );
|
212
|
+
memset( prep_inp_data , 0, 2*sizeof( *prep_inp_data ) );
|
213
|
+
memset( szSdfDataValue , 0, sizeof( szSdfDataValue ) );
|
214
|
+
|
215
|
+
if ( !out ) {
|
216
|
+
nRet = _IS_ERROR;
|
217
|
+
goto exit_function;
|
218
|
+
}
|
219
|
+
memset( out, 0, sizeof(*out) );
|
220
|
+
|
221
|
+
/* options */
|
222
|
+
if ( inp && inp->szOptions ) {
|
223
|
+
szOptions = (char*)inchi_malloc( strlen(inp->szOptions) + 1 );
|
224
|
+
if ( szOptions ) {
|
225
|
+
strcpy( szOptions, inp->szOptions );
|
226
|
+
argc = parse_options_string ( szOptions, argv, INCHI_MAX_NUM_ARG );
|
227
|
+
} else {
|
228
|
+
nRet = _IS_FATAL;
|
229
|
+
goto translate_RetVal; /* emergency exit */
|
230
|
+
}
|
231
|
+
} else {
|
232
|
+
argc = 1;
|
233
|
+
argv[0] = "";
|
234
|
+
argv[1] = NULL;
|
235
|
+
}
|
236
|
+
|
237
|
+
if ( argc == 1
|
238
|
+
#ifdef INCHI_LIBRARY
|
239
|
+
&& (!inp || inp->num_atoms <= 0 || !inp->atom)
|
240
|
+
#endif
|
241
|
+
|| argc==2 && ( argv[1][0]==INCHI_OPTION_PREFX ) &&
|
242
|
+
(!strcmp(argv[1]+1, "?") || !stricmp(argv[1]+1, "help") ) ) {
|
243
|
+
HelpCommandLineParms(log_file);
|
244
|
+
out->szLog = log_file->pStr;
|
245
|
+
memset( log_file, 0, sizeof(*log_file) );
|
246
|
+
nRet = _IS_EOF;
|
247
|
+
goto translate_RetVal;
|
248
|
+
}
|
249
|
+
|
250
|
+
nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue, &ulDisplTime, bReleaseVersion, log_file );
|
251
|
+
if ( szOptions ) {
|
252
|
+
inchi_free( szOptions );
|
253
|
+
szOptions = NULL;
|
254
|
+
}
|
255
|
+
/* INChI DLL specific */
|
256
|
+
ip->bNoStructLabels = 1;
|
257
|
+
|
258
|
+
if ( 0 > nRet1 ) {
|
259
|
+
goto exit_function;
|
260
|
+
}
|
261
|
+
#ifndef INCHI_LIBRARY
|
262
|
+
if ( !OpenFiles( &inp_file, &output_file, &log_file, &prb_file, ip ) ) {
|
263
|
+
goto exit_function;
|
264
|
+
}
|
265
|
+
#endif
|
266
|
+
if ( ip->bNoStructLabels ) {
|
267
|
+
ip->pSdfLabel = NULL;
|
268
|
+
ip->pSdfValue = NULL;
|
269
|
+
} else
|
270
|
+
if ( ip->nInputType == INPUT_INCHI_XML || ip->nInputType == INPUT_INCHI_PLAIN || ip->nInputType == INPUT_CMLFILE ) {
|
271
|
+
/* the input may contain both the header and the label of the structure */
|
272
|
+
if ( !ip->pSdfLabel )
|
273
|
+
ip->pSdfLabel = ip->szSdfDataHeader;
|
274
|
+
if ( !ip->pSdfValue )
|
275
|
+
ip->pSdfValue = szSdfDataValue;
|
276
|
+
}
|
277
|
+
PrintInputParms( log_file, ip );
|
278
|
+
if ( !(pStr = (char*)inchi_malloc(nStrLen))) {
|
279
|
+
my_fprintf( log_file, "Cannot allocate output buffer. Terminating\n");
|
280
|
+
goto exit_function;
|
281
|
+
}
|
282
|
+
pStr[0] = '\0';
|
283
|
+
|
284
|
+
/**********************************************************************************************/
|
285
|
+
/* Main cycle */
|
286
|
+
/* read input structures and create their INChI */
|
287
|
+
ulTotalProcessingTime = 0;
|
288
|
+
|
289
|
+
if ( pStructPtrs ) {
|
290
|
+
memset ( pStructPtrs, 0, sizeof(pStructPtrs[0]) );
|
291
|
+
}
|
292
|
+
|
293
|
+
/* === TOMORROW: remove while cycling and convert inp to orig_inp_data ==== */
|
294
|
+
#ifdef INCHI_LIBRARY
|
295
|
+
if ( !sd->bUserQuit && !bInterrupted )
|
296
|
+
#else
|
297
|
+
while ( !sd->bUserQuit && !bInterrupted )
|
298
|
+
#endif
|
299
|
+
{
|
300
|
+
if ( ip->last_struct_number && num_inp >= ip->last_struct_number ) {
|
301
|
+
nRet = _IS_EOF; /* simulate end of file */
|
302
|
+
goto exit_function;
|
303
|
+
}
|
304
|
+
|
305
|
+
#ifndef INCHI_LIBRARY
|
306
|
+
/* read one structure from input and display optionally it */
|
307
|
+
nRet = GetOneStructure( sd, ip, szTitle, inp_file, log_file, output_file, prb_file,
|
308
|
+
orig_inp_data, &num_inp, pStr, nStrLen, pStructPtrs );
|
309
|
+
#else
|
310
|
+
nRet = ExtractOneStructure( sd, ip, szTitle, inp, log_file, output_file, prb_file,
|
311
|
+
orig_inp_data, &num_inp, pStr, nStrLen );
|
312
|
+
#endif
|
313
|
+
|
314
|
+
|
315
|
+
if ( pStructPtrs ) {
|
316
|
+
pStructPtrs->cur_fptr ++;
|
317
|
+
}
|
318
|
+
|
319
|
+
#ifndef INCHI_LIBRARY
|
320
|
+
if ( sd->bUserQuit ) {
|
321
|
+
break;
|
322
|
+
}
|
323
|
+
#endif
|
324
|
+
switch ( nRet ) {
|
325
|
+
case _IS_FATAL:
|
326
|
+
num_err ++;
|
327
|
+
goto exit_function;
|
328
|
+
case _IS_EOF:
|
329
|
+
goto exit_function;
|
330
|
+
case _IS_ERROR:
|
331
|
+
num_err ++;
|
332
|
+
goto exit_function;
|
333
|
+
#ifndef INCHI_LIBRARY
|
334
|
+
case _IS_SKIP:
|
335
|
+
continue;
|
336
|
+
#endif
|
337
|
+
}
|
338
|
+
|
339
|
+
/* create INChI for each connected component of the structure and optionally display them */
|
340
|
+
/* output INChI for the whole structure */
|
341
|
+
nRet1 = ProcessOneStructure( sd, ip, szTitle, pINChI, pINChI_Aux,
|
342
|
+
inp_file, log_file, output_file, prb_file,
|
343
|
+
orig_inp_data, prep_inp_data,
|
344
|
+
num_inp, pStr, nStrLen );
|
345
|
+
|
346
|
+
/* free INChI memory */
|
347
|
+
FreeAllINChIArrays( pINChI, pINChI_Aux, sd->num_components );
|
348
|
+
/* free structure data */
|
349
|
+
FreeOrigAtData( orig_inp_data );
|
350
|
+
FreeOrigAtData( prep_inp_data );
|
351
|
+
FreeOrigAtData( prep_inp_data+1 );
|
352
|
+
|
353
|
+
ulTotalProcessingTime += sd->ulStructTime;
|
354
|
+
nRet = inchi_max(nRet, nRet1);
|
355
|
+
switch ( nRet ) {
|
356
|
+
case _IS_FATAL:
|
357
|
+
num_err ++;
|
358
|
+
goto exit_function;
|
359
|
+
case _IS_ERROR:
|
360
|
+
num_err ++;
|
361
|
+
#ifndef INCHI_LIBRARY
|
362
|
+
continue;
|
363
|
+
#endif
|
364
|
+
}
|
365
|
+
|
366
|
+
}
|
367
|
+
|
368
|
+
exit_function:
|
369
|
+
if ( (ip->bINChIOutputOptions & INCHI_OUT_XML) && sd->bXmlStructStarted > 0 ) {
|
370
|
+
if ( !OutputINChIXmlStructEndTag( output_file, pStr, nStrLen, 1 ) ) {
|
371
|
+
my_fprintf( log_file, "Cannot create end xml tag for structure #%d.%s%s%s%s Terminating.\n", num_inp, SDF_LBL_VAL(ip->pSdfLabel,ip->pSdfValue) );
|
372
|
+
sd->bXmlStructStarted = -1; /* do not repeat same message */
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
|
377
|
+
if ( (ip->bINChIOutputOptions & INCHI_OUT_XML) && ip->bXmlStarted ) {
|
378
|
+
OutputINChIXmlRootEndTag( output_file );
|
379
|
+
ip->bXmlStarted = 0;
|
380
|
+
}
|
381
|
+
|
382
|
+
|
383
|
+
/* avoid memory leaks in case of fatal error */
|
384
|
+
if ( pStructPtrs && pStructPtrs->fptr ) {
|
385
|
+
inchi_free( pStructPtrs->fptr );
|
386
|
+
}
|
387
|
+
|
388
|
+
/* free INChI memory */
|
389
|
+
FreeAllINChIArrays( pINChI, pINChI_Aux, sd->num_components );
|
390
|
+
/* free structure data */
|
391
|
+
FreeOrigAtData( orig_inp_data );
|
392
|
+
FreeOrigAtData( prep_inp_data );
|
393
|
+
FreeOrigAtData( prep_inp_data+1 );
|
394
|
+
|
395
|
+
#if( ADD_CMLPP == 1 )
|
396
|
+
/* BILLY 8/6/04 */
|
397
|
+
/* free CML memory */
|
398
|
+
FreeCml ();
|
399
|
+
FreeCmlDoc( 1 );
|
400
|
+
#endif
|
401
|
+
|
402
|
+
#ifndef INCHI_LIBRARY
|
403
|
+
if ( inp_file && inp_file != stdin) {
|
404
|
+
fclose ( inp_file );
|
405
|
+
}
|
406
|
+
if ( prb_file ) {
|
407
|
+
fclose ( prb_file );
|
408
|
+
}
|
409
|
+
if ( output_file && output_file != stdout ) {
|
410
|
+
fclose( output_file );
|
411
|
+
}
|
412
|
+
|
413
|
+
if ( log_file )
|
414
|
+
{
|
415
|
+
int hours, minutes, seconds, mseconds;
|
416
|
+
SplitTime( ulTotalProcessingTime, &hours, &minutes, &seconds, &mseconds );
|
417
|
+
my_fprintf( log_file, "Finished processing %d structure%s: %d error%s, processing time %d:%02d:%02d.%02d\n",
|
418
|
+
num_inp, num_inp==1?"":"s",
|
419
|
+
num_err, num_err==1?"":"s",
|
420
|
+
hours, minutes, seconds,mseconds/10);
|
421
|
+
}
|
422
|
+
|
423
|
+
if ( log_file && log_file != stderr ) {
|
424
|
+
fclose( log_file );
|
425
|
+
}
|
426
|
+
#endif
|
427
|
+
|
428
|
+
if ( pStr ) {
|
429
|
+
inchi_free( pStr );
|
430
|
+
}
|
431
|
+
|
432
|
+
for ( i = 0; i < MAX_NUM_PATHS; i ++ ) {
|
433
|
+
if ( ip->path[i] ) {
|
434
|
+
inchi_free( (void*) ip->path[i] ); /* cast deliberately discards 'const' qualifier */
|
435
|
+
ip->path[i] = NULL;
|
436
|
+
}
|
437
|
+
}
|
438
|
+
|
439
|
+
SetBitFree( );
|
440
|
+
|
441
|
+
|
442
|
+
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
|
443
|
+
if ( num_repeat-- > 0 ) {
|
444
|
+
goto repeat;
|
445
|
+
}
|
446
|
+
#endif
|
447
|
+
|
448
|
+
#ifndef INCHI_LIBRARY
|
449
|
+
#if( bRELEASE_VERSION != 1 && defined(_DEBUG) )
|
450
|
+
if ( inp_file && inp_file != stdin ) {
|
451
|
+
user_quit("Press Enter to exit ?", ulDisplTime);
|
452
|
+
}
|
453
|
+
#endif
|
454
|
+
#endif
|
455
|
+
|
456
|
+
|
457
|
+
#ifdef INCHI_LIBRARY
|
458
|
+
/* output */
|
459
|
+
if ( sd->pStrErrStruct[0] ) {
|
460
|
+
if ( out && (out->szMessage = (char *)inchi_malloc( strlen(sd->pStrErrStruct) + 1 )) ) {
|
461
|
+
strcpy( out->szMessage, sd->pStrErrStruct );
|
462
|
+
}
|
463
|
+
}
|
464
|
+
if ( output_file->pStr && output_file->nUsedLength > 0 && out ) {
|
465
|
+
char *p;
|
466
|
+
out->szInChI = output_file->pStr;
|
467
|
+
out->szAuxInfo = NULL;
|
468
|
+
for ( p = strchr(out->szInChI, '\n'); p; p = strchr(p+1, '\n') ) {
|
469
|
+
if ( !memcmp( p, "\nAuxInfo", 8 ) ) {
|
470
|
+
*p = '\0'; /* remove LF after INChI */
|
471
|
+
out->szAuxInfo = p+1; /* save pointer to AuxInfo */
|
472
|
+
} else
|
473
|
+
if ( out->szAuxInfo || !p[1]) { /* remove LF after aux info or from the last char */
|
474
|
+
*p = '\0';
|
475
|
+
break;
|
476
|
+
}
|
477
|
+
}
|
478
|
+
output_file->pStr = NULL;
|
479
|
+
}
|
480
|
+
if ( log_file->pStr && log_file->nUsedLength > 0 ) {
|
481
|
+
while ( log_file->nUsedLength && '\n' == log_file->pStr[log_file->nUsedLength-1] ) {
|
482
|
+
log_file->pStr[-- log_file->nUsedLength] = '\0'; /* remove last LF */
|
483
|
+
}
|
484
|
+
if ( out ) {
|
485
|
+
out->szLog = log_file->pStr;
|
486
|
+
log_file->pStr = NULL;
|
487
|
+
}
|
488
|
+
}
|
489
|
+
if ( output_file->pStr )
|
490
|
+
inchi_free( output_file->pStr );
|
491
|
+
if ( log_file->pStr )
|
492
|
+
inchi_free( log_file->pStr );
|
493
|
+
|
494
|
+
|
495
|
+
#endif
|
496
|
+
|
497
|
+
translate_RetVal:
|
498
|
+
|
499
|
+
switch (nRet) {
|
500
|
+
case _IS_SKIP : nRet = inchi_Ret_SKIP ; break; /* not used in INChI dll */
|
501
|
+
case _IS_EOF : nRet = inchi_Ret_EOF ; break; /* no structural data has been provided */
|
502
|
+
case _IS_OKAY : nRet = inchi_Ret_OKAY ; break; /* Success; break; no errors or warnings */
|
503
|
+
case _IS_WARNING: nRet = inchi_Ret_WARNING; break; /* Success; break; warning(s) issued */
|
504
|
+
case _IS_ERROR : nRet = inchi_Ret_ERROR ; break; /* Error: no INChI has been created */
|
505
|
+
case _IS_FATAL : nRet = inchi_Ret_FATAL ; break; /* Severe error: no INChI has been created (typically; break; memory allocation failed) */
|
506
|
+
case _IS_UNKNOWN:
|
507
|
+
default : nRet = inchi_Ret_UNKNOWN; break; /* Unlnown program error */
|
508
|
+
}
|
509
|
+
bLibInchiSemaphore = 0;
|
510
|
+
return nRet;
|
511
|
+
}
|
512
|
+
|
513
|
+
|
514
|
+
/*************************************************************************/
|
515
|
+
/******************************** from readmol.c *************************/
|
516
|
+
/*************************************************************************/
|
517
|
+
int AddMOLfileError( char *pStrErr, const char *szMsg )
|
518
|
+
{
|
519
|
+
if ( pStrErr && szMsg && szMsg[0] ) {
|
520
|
+
int lenStrErr = strlen( pStrErr );
|
521
|
+
int lenMsg = strlen( szMsg );
|
522
|
+
char *p = strstr( pStrErr, szMsg );
|
523
|
+
if ( p && (p==pStrErr || *(p-1) == ' ' && (*(p-2) == ';' || *(p-2) == ':' )) &&
|
524
|
+
(p+lenMsg == pStrErr+lenStrErr ||
|
525
|
+
p[lenMsg] == ';' && p[lenMsg+1] == ' ' ||
|
526
|
+
p[lenMsg-1]==':' && p[lenMsg]==' ') ) {
|
527
|
+
return 1; /* reject duplicates */
|
528
|
+
}
|
529
|
+
if ( lenStrErr + lenMsg + 2*(lenStrErr > 0) < STR_ERR_LEN ) {
|
530
|
+
/* enough room to add */
|
531
|
+
if (lenStrErr > 0) {
|
532
|
+
if ( pStrErr[lenStrErr-1] != ':' ) {
|
533
|
+
strcat( pStrErr, ";" );
|
534
|
+
}
|
535
|
+
strcat( pStrErr, " " );
|
536
|
+
}
|
537
|
+
strcat( pStrErr, szMsg );
|
538
|
+
return 1;
|
539
|
+
}
|
540
|
+
/* no room */
|
541
|
+
if ( strstr( pStrErr, "..." ) ) {
|
542
|
+
return 0; /* no room mark has already been set */
|
543
|
+
}
|
544
|
+
if ( lenStrErr + 3 < STR_ERR_LEN ) {
|
545
|
+
strcat( pStrErr, "..." );
|
546
|
+
}
|
547
|
+
}
|
548
|
+
return 0;
|
549
|
+
}
|
550
|
+
/****************************************************************/
|
551
|
+
int CopyMOLfile(FILE *inp_file, long fPtrStart, long fPtrEnd, INCHI_FILE *prb_file, long lNumb)
|
552
|
+
{
|
553
|
+
return 0; /* dummy */
|
554
|
+
}
|
555
|
+
/****************************************************************/
|
556
|
+
/************************** from mol2atom.c *********************/
|
557
|
+
/****************************************************************/
|
558
|
+
void SetNumImplicitH(inp_ATOM* at, int num_atoms)
|
559
|
+
{
|
560
|
+
int bNonMetal;
|
561
|
+
int a1/*, n1*/;
|
562
|
+
|
563
|
+
/* special valences */
|
564
|
+
for ( bNonMetal = 0; bNonMetal < 2; bNonMetal ++ ) {
|
565
|
+
for ( a1 = 0; a1 < num_atoms; a1 ++ ) {
|
566
|
+
int bHasMetalNeighbor /*, j*/;
|
567
|
+
if ( bNonMetal != is_el_a_metal( at[a1].el_number ) ) {
|
568
|
+
continue; /* first process all metals, after that all non-metals */
|
569
|
+
}
|
570
|
+
|
571
|
+
bHasMetalNeighbor = 0;
|
572
|
+
/***********************************************************************
|
573
|
+
* Set number of hydrogen atoms
|
574
|
+
*/
|
575
|
+
at[a1].num_H = get_num_H( at[a1].elname, at[a1].num_H, at[a1].num_iso_H,
|
576
|
+
at[a1].charge, at[a1].radical,
|
577
|
+
at[a1].chem_bonds_valence,
|
578
|
+
0, /* instead of valence entered by the user: it does not exist here*/
|
579
|
+
(at[a1].at_type & 1) /* bAliased */,
|
580
|
+
!(at[a1].at_type & 2) /* bDoNotAddH */,
|
581
|
+
bHasMetalNeighbor );
|
582
|
+
at[a1].at_type = 0;
|
583
|
+
}
|
584
|
+
}
|
585
|
+
}
|
586
|
+
|
587
|
+
/******************************************************************************************************/
|
588
|
+
void FreeInpAtom( inp_ATOM **at )
|
589
|
+
{
|
590
|
+
if ( at && *at ) {
|
591
|
+
inchi_free( *at );
|
592
|
+
*at = NULL;
|
593
|
+
}
|
594
|
+
}
|
595
|
+
/******************************************************************************************************/
|
596
|
+
inp_ATOM *CreateInpAtom( int num_atoms )
|
597
|
+
{
|
598
|
+
/*
|
599
|
+
void *p = inchi_calloc(num_atoms, sizeof(inp_ATOM) );
|
600
|
+
if ( p == (void*)0x009143A8 ) {
|
601
|
+
int stop = 1;
|
602
|
+
}
|
603
|
+
return (inp_ATOM* )p;
|
604
|
+
*/
|
605
|
+
return (inp_ATOM* ) inchi_calloc(num_atoms, sizeof(inp_ATOM) );
|
606
|
+
}
|
607
|
+
/******************************************************************************************************/
|
608
|
+
void FreeInpAtomData( INP_ATOM_DATA *inp_at_data )
|
609
|
+
{
|
610
|
+
FreeInpAtom( &inp_at_data->at );
|
611
|
+
FreeInpAtom( &inp_at_data->at_fixed_bonds );
|
612
|
+
memset( inp_at_data, 0, sizeof(*inp_at_data) );
|
613
|
+
}
|
614
|
+
/******************************************************************************************************/
|
615
|
+
int CreateInpAtomData( INP_ATOM_DATA *inp_at_data, int num_atoms, int create_at_fixed_bonds )
|
616
|
+
{
|
617
|
+
FreeInpAtomData( inp_at_data );
|
618
|
+
if ( (inp_at_data->at = CreateInpAtom( num_atoms )) &&
|
619
|
+
(!create_at_fixed_bonds || (inp_at_data->at_fixed_bonds = CreateInpAtom( num_atoms) ) ) ) {
|
620
|
+
inp_at_data->num_at = num_atoms;
|
621
|
+
return 1;
|
622
|
+
}
|
623
|
+
FreeInpAtomData( inp_at_data );
|
624
|
+
return 0;
|
625
|
+
}
|
626
|
+
/******************************************************************************************************/
|
627
|
+
void FreeCompAtomData( COMP_ATOM_DATA *inp_at_data )
|
628
|
+
{
|
629
|
+
FreeInpAtom( &inp_at_data->at );
|
630
|
+
if ( inp_at_data->nOffsetAtAndH )
|
631
|
+
inchi_free( inp_at_data->nOffsetAtAndH );
|
632
|
+
memset( inp_at_data, 0, sizeof(*inp_at_data) );
|
633
|
+
}
|
634
|
+
/******************************************************************************************************/
|
635
|
+
#if( TEST_RENUMB_ATOMS == 1 ) /* { */
|
636
|
+
/******************************************************************************************************/
|
637
|
+
int CopyInpAtomData( INP_ATOM_DATA *dest_inp_at_data, INP_ATOM_DATA *src_inp_at_data )
|
638
|
+
{
|
639
|
+
int ret = 1;
|
640
|
+
if ( !dest_inp_at_data->at || dest_inp_at_data->num_at != src_inp_at_data->num_at ) {
|
641
|
+
ret = CreateInpAtomData( dest_inp_at_data, src_inp_at_data->num_at, (NULL != src_inp_at_data->at_fixed_bonds) );
|
642
|
+
} else {
|
643
|
+
inp_ATOM *at = dest_inp_at_data->at; /* save ptr to already allocated memory */
|
644
|
+
inp_ATOM *at2 = dest_inp_at_data->at_fixed_bonds;
|
645
|
+
*dest_inp_at_data = *src_inp_at_data; /* copy all other (scalar) data */
|
646
|
+
dest_inp_at_data->at = at; /* restore ptr to already allocated memory */
|
647
|
+
dest_inp_at_data->at_fixed_bonds = at2;
|
648
|
+
}
|
649
|
+
if ( ret ) {
|
650
|
+
memcpy( dest_inp_at_data->at, src_inp_at_data->at,
|
651
|
+
src_inp_at_data->num_at*sizeof(dest_inp_at_data->at[0]) );
|
652
|
+
if ( dest_inp_at_data->at_fixed_bonds && src_inp_at_data->at_fixed_bonds ) {
|
653
|
+
memcpy( dest_inp_at_data->at_fixed_bonds, src_inp_at_data->at_fixed_bonds,
|
654
|
+
src_inp_at_data->num_at*sizeof(dest_inp_at_data->at_fixed_bonds[0]) );
|
655
|
+
}
|
656
|
+
}
|
657
|
+
return ret;
|
658
|
+
}
|
659
|
+
/******************************************************************************************************/
|
660
|
+
void RenumbInpAtomData( INP_ATOM_DATA *dest_inp_at_data, INP_ATOM_DATA *src_inp_at_data, AT_RANK *new_ord )
|
661
|
+
{
|
662
|
+
int j, n, m, val;
|
663
|
+
#if( TEST_RENUMB_NEIGH == 1 )
|
664
|
+
int i, k;
|
665
|
+
#endif
|
666
|
+
int num_atoms = src_inp_at_data->num_at;
|
667
|
+
inp_ATOM *dest_at = dest_inp_at_data->at;
|
668
|
+
for ( n = 0; n < num_atoms; n ++ ) {
|
669
|
+
m = new_ord[n];
|
670
|
+
dest_at[m] = src_inp_at_data->at[n];
|
671
|
+
dest_at[m].orig_compt_at_numb = (AT_NUMB)(m+1); /* new ordering number within the component */
|
672
|
+
val = dest_at[m].valence;
|
673
|
+
for ( j = 0; j < val; j ++ ) {
|
674
|
+
dest_at[m].neighbor[j] = new_ord[dest_at[m].neighbor[j]];
|
675
|
+
}
|
676
|
+
#if( TEST_RENUMB_NEIGH == 1 )
|
677
|
+
for ( i = 0; i < 3*val; i ++ ) {
|
678
|
+
j = (rand() * val) / (RAND_MAX+1);
|
679
|
+
k = (rand() * val) / (RAND_MAX+1);
|
680
|
+
if ( j >= val || k >= val || j == k ) {
|
681
|
+
continue;
|
682
|
+
}
|
683
|
+
swap( (char*)&dest_at[m].neighbor[j], (char*)&dest_at[m].neighbor[k], sizeof(dest_at[0].neighbor[0]) );
|
684
|
+
swap( (char*)&dest_at[m].bond_stereo[j], (char*)&dest_at[m].bond_stereo[k], sizeof(dest_at[0].bond_stereo[0]) );
|
685
|
+
swap( (char*)&dest_at[m].bond_type[j], (char*)&dest_at[m].bond_type[k], sizeof(dest_at[0].bond_type[0]) );
|
686
|
+
/* adjust stereo bond links */
|
687
|
+
if ( dest_at[m].sb_parity[0] ) {
|
688
|
+
int a;
|
689
|
+
for ( a = 0; a < MAX_NUM_STEREO_BONDS && dest_at[m].sb_parity[a]; a ++ ) {
|
690
|
+
|
691
|
+
if ( k == (int)dest_at[m].sb_ord[a] ) {
|
692
|
+
dest_at[m].sb_ord[a] = j;
|
693
|
+
} else
|
694
|
+
if ( j == (int)dest_at[m].sb_ord[a] ) {
|
695
|
+
dest_at[m].sb_ord[a] = k;
|
696
|
+
}
|
697
|
+
|
698
|
+
if ( k == (int)dest_at[m].sn_ord[a] ) {
|
699
|
+
dest_at[m].sn_ord[a] = j;
|
700
|
+
} else
|
701
|
+
if ( j == (int)dest_at[m].sn_ord[a] ) {
|
702
|
+
dest_at[m].sn_ord[a] = k;
|
703
|
+
}
|
704
|
+
}
|
705
|
+
}
|
706
|
+
}
|
707
|
+
#endif
|
708
|
+
}
|
709
|
+
|
710
|
+
}
|
711
|
+
/******************************************************************************************************/
|
712
|
+
void MakeNewOrd( int num_atoms, AT_RANK *new_ord )
|
713
|
+
{
|
714
|
+
int i, j, k;
|
715
|
+
for ( i = 0; i < 3*num_atoms; i ++ ) {
|
716
|
+
j = (rand() * num_atoms) / (RAND_MAX+1);
|
717
|
+
k = (rand() * num_atoms) / (RAND_MAX+1);
|
718
|
+
if ( j >= num_atoms || k >= num_atoms || j == k ) {
|
719
|
+
continue;
|
720
|
+
}
|
721
|
+
swap( (char*)&new_ord[j], (char*)&new_ord[k], sizeof(new_ord[0]) );
|
722
|
+
}
|
723
|
+
}
|
724
|
+
#endif /* } TEST_RENUMB_ATOMS == 1 */
|
725
|
+
/**********************************************************************************/
|
726
|
+
void FreeOrigAtData( ORIG_ATOM_DATA *orig_at_data )
|
727
|
+
{
|
728
|
+
if ( !orig_at_data )
|
729
|
+
return;
|
730
|
+
FreeInpAtom( &orig_at_data->at );
|
731
|
+
if ( orig_at_data->nCurAtLen ) {
|
732
|
+
inchi_free( orig_at_data->nCurAtLen );
|
733
|
+
}
|
734
|
+
if ( orig_at_data->nOldCompNumber ) {
|
735
|
+
inchi_free( orig_at_data->nOldCompNumber );
|
736
|
+
}
|
737
|
+
if ( orig_at_data->szCoord ) {
|
738
|
+
inchi_free( orig_at_data->szCoord );
|
739
|
+
}
|
740
|
+
if ( orig_at_data->nEquLabels ) {
|
741
|
+
inchi_free( orig_at_data->nEquLabels );
|
742
|
+
}
|
743
|
+
if ( orig_at_data->nSortedOrder ) {
|
744
|
+
inchi_free( orig_at_data->nSortedOrder );
|
745
|
+
}
|
746
|
+
memset( orig_at_data, 0, sizeof(*orig_at_data) );
|
747
|
+
}
|
748
|
+
/********************************************************************/
|
749
|
+
|
750
|
+
#define REPEAT_ALL 0
|
751
|
+
/********************************************************************/
|
752
|
+
int parse_options_string ( char *cmd, const char *argv[], int maxargs )
|
753
|
+
{
|
754
|
+
char *p;
|
755
|
+
char *pArgCurChar;
|
756
|
+
int bInsideQuotes;
|
757
|
+
int bCopyCharToArg;
|
758
|
+
int nNumBackSlashes;
|
759
|
+
int i;
|
760
|
+
|
761
|
+
i = 0;
|
762
|
+
argv[i++] = ""; /* zeroth argument is not used */
|
763
|
+
p = cmd;
|
764
|
+
bInsideQuotes = 0;
|
765
|
+
|
766
|
+
/* arguments, one by one */
|
767
|
+
while( i < maxargs-1 ) {
|
768
|
+
/* bypass spaces */
|
769
|
+
while ( *p == ' ' || *p == '\t' )
|
770
|
+
p ++;
|
771
|
+
if ( !*p )
|
772
|
+
break;
|
773
|
+
/* scan an argument */
|
774
|
+
argv[i++] = pArgCurChar = p; /* store preliminary ptr to arg */
|
775
|
+
while ( 1 ) {
|
776
|
+
bCopyCharToArg = 1;
|
777
|
+
nNumBackSlashes = 0;
|
778
|
+
while (*p == '\\') {
|
779
|
+
++p;
|
780
|
+
++nNumBackSlashes;
|
781
|
+
}
|
782
|
+
/* each pair of backslashes => one backslash; one more backslash => literal quote */
|
783
|
+
if ( *p == '\"' ) {
|
784
|
+
/* one " found */
|
785
|
+
if ( nNumBackSlashes % 2 == 0 ) {
|
786
|
+
if (bInsideQuotes) {
|
787
|
+
if (*(p+1) == '\"') {
|
788
|
+
p++;
|
789
|
+
} else {
|
790
|
+
bCopyCharToArg = 0;
|
791
|
+
}
|
792
|
+
} else {
|
793
|
+
bCopyCharToArg = 0;
|
794
|
+
}
|
795
|
+
bInsideQuotes = !bInsideQuotes;
|
796
|
+
}
|
797
|
+
nNumBackSlashes /= 2; /* divide nNumBackSlashes by two */
|
798
|
+
}
|
799
|
+
while (nNumBackSlashes--) {
|
800
|
+
*pArgCurChar++ = '\\';
|
801
|
+
}
|
802
|
+
if (!*p) {
|
803
|
+
break;
|
804
|
+
}
|
805
|
+
if (!bInsideQuotes && (*p == ' ' || *p == '\t')) {
|
806
|
+
p ++;
|
807
|
+
/* move to the next char because this char may become
|
808
|
+
* zero due to *pArgCurChar++ = '\0'; line below */
|
809
|
+
break;
|
810
|
+
}
|
811
|
+
if (bCopyCharToArg) {
|
812
|
+
*pArgCurChar++ = *p;
|
813
|
+
}
|
814
|
+
++p;
|
815
|
+
}
|
816
|
+
*pArgCurChar++ = '\0'; /* argument zero termination */
|
817
|
+
}
|
818
|
+
/* The last argument is NULL */
|
819
|
+
argv[i] = NULL;
|
820
|
+
return i;
|
821
|
+
}
|
822
|
+
/*****************************************************************/
|
823
|
+
#define MIN_BOND_LENGTH (1.0e-6)
|
824
|
+
int SetAtomProperties( inp_ATOM *at, MOL_COORD *szCoord, inchi_Atom *ati, int a1, int *nDim, char *pStrErr, int *err )
|
825
|
+
{
|
826
|
+
S_CHAR cRadical;
|
827
|
+
/* element, check later */
|
828
|
+
|
829
|
+
strcpy( at[a1].elname, ati[a1].elname );
|
830
|
+
|
831
|
+
/* charge */
|
832
|
+
|
833
|
+
at[a1].charge = ati[a1].charge;
|
834
|
+
|
835
|
+
/* radical */
|
836
|
+
|
837
|
+
switch ( ati[a1].radical ) {
|
838
|
+
case INCHI_RADICAL_NONE:
|
839
|
+
cRadical = 0;
|
840
|
+
break;
|
841
|
+
case INCHI_RADICAL_SINGLET:
|
842
|
+
#if( SINGLET_IS_TRIPLET == 1) /* 'singlet' means two electrons make a lone pair instead of 2 bonds*/
|
843
|
+
/* its effect on valence is same as the effect of a triplet */
|
844
|
+
cRadical = RADICAL_TRIPLET;
|
845
|
+
#else
|
846
|
+
cRadical = RADICAL_SINGLET;
|
847
|
+
#endif
|
848
|
+
break;
|
849
|
+
case INCHI_RADICAL_DOUBLET:
|
850
|
+
cRadical = RADICAL_DOUBLET;
|
851
|
+
break;
|
852
|
+
case INCHI_RADICAL_TRIPLET:
|
853
|
+
cRadical = RADICAL_TRIPLET;
|
854
|
+
break;
|
855
|
+
default:
|
856
|
+
{
|
857
|
+
char szRadicalType[16];
|
858
|
+
sprintf( szRadicalType, "%d", ati[a1].radical );
|
859
|
+
MOLFILE_ERR_SET (*err, 0, "Radical center type ignored:");
|
860
|
+
MOLFILE_ERR_SET (*err, 0, szRadicalType);
|
861
|
+
*err |= 8; /* Unrecognized Radical replaced with non-radical */
|
862
|
+
cRadical = 0;
|
863
|
+
}
|
864
|
+
break;
|
865
|
+
}
|
866
|
+
at[a1].radical = cRadical;
|
867
|
+
|
868
|
+
/* coordinates */
|
869
|
+
at[a1].x = ati[a1].x;
|
870
|
+
at[a1].y = ati[a1].y;
|
871
|
+
at[a1].z = ati[a1].z;
|
872
|
+
|
873
|
+
if ( szCoord ) {
|
874
|
+
/* store text coordinates */
|
875
|
+
char str[32];
|
876
|
+
MOL_COORD * coord_p = szCoord + a1;
|
877
|
+
WriteCoord( str, ati[a1].x );
|
878
|
+
memcpy( *coord_p, str, 10 );
|
879
|
+
WriteCoord( str, ati[a1].y );
|
880
|
+
memcpy( *coord_p+10, str, 10 );
|
881
|
+
WriteCoord( str, ati[a1].z );
|
882
|
+
memcpy( *coord_p+20, str, 10 );
|
883
|
+
}
|
884
|
+
|
885
|
+
if ( MIN_BOND_LENGTH < fabs(ati[a1].x) || MIN_BOND_LENGTH < fabs(ati[a1].y) || MIN_BOND_LENGTH < fabs(ati[a1].z) ) {
|
886
|
+
if ( MIN_BOND_LENGTH < fabs(ati[a1].z) ) {
|
887
|
+
*nDim |= 3;
|
888
|
+
} else {
|
889
|
+
*nDim |= 2;
|
890
|
+
}
|
891
|
+
}
|
892
|
+
|
893
|
+
/* orig. at. number */
|
894
|
+
at[a1].orig_at_number = a1+1;
|
895
|
+
return 0;
|
896
|
+
#undef MIN_BOND_LENGTH
|
897
|
+
}
|
898
|
+
/*********************************************************************/
|
899
|
+
int SetBondProperties( inp_ATOM *at, inchi_Atom *ati, int a1, int j,
|
900
|
+
int nNumAtoms, int *nNumBonds, char *pStrErr, int *err )
|
901
|
+
{
|
902
|
+
int a2;
|
903
|
+
S_CHAR cBondType, cStereoType1, cStereoType2;
|
904
|
+
AT_NUMB *p1, *p2;
|
905
|
+
int n1, n2;
|
906
|
+
|
907
|
+
/* bond type */
|
908
|
+
switch( ati[a1].bond_type[j] ) {
|
909
|
+
case INCHI_BOND_TYPE_SINGLE:
|
910
|
+
cBondType = BOND_TYPE_SINGLE;
|
911
|
+
break;
|
912
|
+
case INCHI_BOND_TYPE_DOUBLE:
|
913
|
+
cBondType = BOND_TYPE_DOUBLE;
|
914
|
+
break;
|
915
|
+
case INCHI_BOND_TYPE_TRIPLE:
|
916
|
+
cBondType = BOND_TYPE_TRIPLE;
|
917
|
+
break;
|
918
|
+
case INCHI_BOND_TYPE_ALTERN:
|
919
|
+
cBondType = BOND_TYPE_ALTERN;
|
920
|
+
break;
|
921
|
+
default:
|
922
|
+
{
|
923
|
+
char szBondType[16];
|
924
|
+
sprintf( szBondType, "%d", ati[a1].bond_type[j] );
|
925
|
+
MOLFILE_ERR_SET (*err, 0, "Unrecognized bond type:");
|
926
|
+
MOLFILE_ERR_SET (*err, 0, szBondType);
|
927
|
+
*err |= 8; /* Unrecognized Bond type replaced with single bond */
|
928
|
+
cBondType = BOND_TYPE_SINGLE;
|
929
|
+
}
|
930
|
+
break;
|
931
|
+
}
|
932
|
+
|
933
|
+
/* 2D stereo */
|
934
|
+
|
935
|
+
switch( ati[a1].bond_stereo[j] ) {
|
936
|
+
/* stereocenter-related; positive: the sharp end points to this atom */
|
937
|
+
case INCHI_BOND_STEREO_NONE:
|
938
|
+
cStereoType1 = 0;
|
939
|
+
cStereoType2 = 0;
|
940
|
+
break;
|
941
|
+
case INCHI_BOND_STEREO_SINGLE_1UP:
|
942
|
+
cStereoType1 = STEREO_SNGL_UP;
|
943
|
+
cStereoType2 = -STEREO_SNGL_UP;
|
944
|
+
break;
|
945
|
+
case INCHI_BOND_STEREO_SINGLE_1EITHER:
|
946
|
+
cStereoType1 = STEREO_SNGL_EITHER;
|
947
|
+
cStereoType2 = -STEREO_SNGL_EITHER;
|
948
|
+
break;
|
949
|
+
case INCHI_BOND_STEREO_SINGLE_1DOWN:
|
950
|
+
cStereoType1 = STEREO_SNGL_DOWN;
|
951
|
+
cStereoType2 = -STEREO_SNGL_DOWN;
|
952
|
+
break;
|
953
|
+
/* stereocenter-related; negative: the sharp end points to the opposite atom */
|
954
|
+
case INCHI_BOND_STEREO_SINGLE_2UP:
|
955
|
+
cStereoType1 = -STEREO_SNGL_UP;
|
956
|
+
cStereoType2 = STEREO_SNGL_UP;
|
957
|
+
break;
|
958
|
+
case INCHI_BOND_STEREO_SINGLE_2EITHER:
|
959
|
+
cStereoType1 = -STEREO_SNGL_EITHER;
|
960
|
+
cStereoType2 = STEREO_SNGL_EITHER;
|
961
|
+
break;
|
962
|
+
case INCHI_BOND_STEREO_SINGLE_2DOWN:
|
963
|
+
cStereoType1 = -STEREO_SNGL_DOWN;
|
964
|
+
cStereoType2 = STEREO_SNGL_DOWN;
|
965
|
+
break;
|
966
|
+
/* stereobond-related */
|
967
|
+
case INCHI_BOND_STEREO_DOUBLE_EITHER:
|
968
|
+
case -INCHI_BOND_STEREO_DOUBLE_EITHER:
|
969
|
+
cStereoType1 = STEREO_DBLE_EITHER;
|
970
|
+
cStereoType2 = STEREO_DBLE_EITHER;
|
971
|
+
break;
|
972
|
+
default:
|
973
|
+
{
|
974
|
+
char szBondType[16];
|
975
|
+
sprintf( szBondType, "%d", ati[a1].bond_stereo[j] );
|
976
|
+
MOLFILE_ERR_SET (*err, 0, "Unrecognized bond stereo:");
|
977
|
+
MOLFILE_ERR_SET (*err, 0, szBondType);
|
978
|
+
*err |= 8; /* Unrecognized Bond stereo replaced with non-stereo bond */
|
979
|
+
cStereoType1 = 0;
|
980
|
+
cStereoType2 = 0;
|
981
|
+
}
|
982
|
+
break;
|
983
|
+
}
|
984
|
+
|
985
|
+
/* neighbor */
|
986
|
+
|
987
|
+
if ( ati[a1].neighbor[j] < 0 || ati[a1].neighbor[j] >= nNumAtoms ) {
|
988
|
+
*err |= 1; /* bond for impossible atom number(s); ignored */
|
989
|
+
MOLFILE_ERR_SET (*err, 0, "Bond to nonexistent atom");
|
990
|
+
goto err_exit;
|
991
|
+
}
|
992
|
+
a2 = (AT_NUMB) ati[a1].neighbor[j];
|
993
|
+
if ( a2 == a1 ) {
|
994
|
+
*err |= 1; /* bond for impossible atom number(s); ignored */
|
995
|
+
MOLFILE_ERR_SET (*err, 0, "Atom has a bond to itself");
|
996
|
+
goto err_exit;
|
997
|
+
}
|
998
|
+
|
999
|
+
/* consistency check; locate the bond in the opposite atom */
|
1000
|
+
|
1001
|
+
p1 = is_in_the_list( at[a1].neighbor, (AT_NUMB)a2, at[a1].valence );
|
1002
|
+
p2 = is_in_the_list( at[a2].neighbor, (AT_NUMB)a1, at[a2].valence );
|
1003
|
+
if ( p1 && p2 ) {
|
1004
|
+
n1 = (p1 - at[a1].neighbor);
|
1005
|
+
n2 = (p2 - at[a2].neighbor);
|
1006
|
+
if ( n1+1 < at[a1].valence && is_in_the_list( at[a1].neighbor+n1+1, (AT_NUMB)a2, at[a1].valence-n1-1 ) ||
|
1007
|
+
n2+1 < at[a2].valence && is_in_the_list( at[a2].neighbor+n2+1, (AT_NUMB)a1, at[a2].valence-n2-1 ) ) {
|
1008
|
+
MOLFILE_ERR_SET (*err, 0, "Multiple bonds between two atoms");
|
1009
|
+
*err |= 2; /* multiple bonds between atoms */
|
1010
|
+
} else
|
1011
|
+
if ( n1 < at[a1].valence && n2 < at[a2].valence &&
|
1012
|
+
cBondType == at[a2].bond_type[n2] &&
|
1013
|
+
cBondType == at[a1].bond_type[n1] &&
|
1014
|
+
cStereoType1 == at[a1].bond_stereo[n1] &&
|
1015
|
+
cStereoType2 == at[a2].bond_stereo[n2] ) {
|
1016
|
+
/*MOLFILE_ERR_SET (*err, 0, "Duplicated bond(s) between two atoms");*/
|
1017
|
+
} else {
|
1018
|
+
MOLFILE_ERR_SET (*err, 0, "Multiple bonds between two atoms");
|
1019
|
+
*err |= 2; /* multiple bonds between atoms */
|
1020
|
+
}
|
1021
|
+
} else
|
1022
|
+
if ( (p1 || p2) && (p1 || at[a1].valence < MAXVAL) && (p2 || at[a2].valence < MAXVAL) ) {
|
1023
|
+
n1 = p1? (p1 - at[a1].neighbor) : at[a1].valence ++;
|
1024
|
+
n2 = p2? (p2 - at[a2].neighbor) : at[a2].valence ++;
|
1025
|
+
/* the bond is present in one atom only: possibly program error */
|
1026
|
+
if ( p1 && (cBondType != at[a1].bond_type[n1] || at[a1].bond_stereo[n1] != cStereoType1 )||
|
1027
|
+
p2 && (cBondType != at[a2].bond_type[n2] || at[a2].bond_stereo[n2] != cStereoType2 ) ) {
|
1028
|
+
MOLFILE_ERR_SET (*err, 0, "Multiple bonds between two atoms");
|
1029
|
+
*err |= 2; /* multiple bonds between atoms */
|
1030
|
+
} else {
|
1031
|
+
MOLFILE_ERR_SET (*err, 0, "Duplicated bond(s) between two atoms");
|
1032
|
+
/* warning */
|
1033
|
+
}
|
1034
|
+
} else
|
1035
|
+
if ( !p1 && !p2 && at[a1].valence < MAXVAL && at[a2].valence < MAXVAL ) {
|
1036
|
+
n1 = at[a1].valence ++;
|
1037
|
+
n2 = at[a2].valence ++;
|
1038
|
+
(*nNumBonds) ++;
|
1039
|
+
} else {
|
1040
|
+
char szMsg[64];
|
1041
|
+
*err |= 4; /* too large number of bonds. Some bonds ignored. */
|
1042
|
+
sprintf( szMsg, "Atom '%s' has more than %d bonds",
|
1043
|
+
at[a1].valence>= MAXVAL? at[a1].elname:at[a2].elname, MAXVAL );
|
1044
|
+
MOLFILE_ERR_SET (*err, 0, szMsg);
|
1045
|
+
goto err_exit;
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
/* store the connection */
|
1049
|
+
|
1050
|
+
/* bond type */
|
1051
|
+
at[a1].bond_type[n1] =
|
1052
|
+
at[a2].bond_type[n2] = cBondType;
|
1053
|
+
/* connection */
|
1054
|
+
at[a1].neighbor[n1] = (AT_NUMB)a2;
|
1055
|
+
at[a2].neighbor[n2] = (AT_NUMB)a1;
|
1056
|
+
/* stereo */
|
1057
|
+
at[a1].bond_stereo[n1] = cStereoType1; /* >0: the wedge (pointed) end is at this atom */
|
1058
|
+
at[a2].bond_stereo[n2] = cStereoType2; /* <0: the wedge (pointed) end is at the opposite atom */
|
1059
|
+
return 0;
|
1060
|
+
err_exit:
|
1061
|
+
return 1;
|
1062
|
+
}
|
1063
|
+
/******************************************************************/
|
1064
|
+
int SetAtomAndBondProperties( inp_ATOM *at, inchi_Atom *ati, int a1,
|
1065
|
+
int bDoNotAddH, char *pStrErr, int *err )
|
1066
|
+
{
|
1067
|
+
int valence, chem_valence, num_alt_bonds, j, n1;
|
1068
|
+
int nRadical, nCharge;
|
1069
|
+
static int el_number_H = 0;
|
1070
|
+
|
1071
|
+
if ( !el_number_H ) {
|
1072
|
+
el_number_H = get_periodic_table_number( "H" );
|
1073
|
+
}
|
1074
|
+
|
1075
|
+
nRadical = nCharge = 0;
|
1076
|
+
valence = at[a1].valence;
|
1077
|
+
chem_valence = num_alt_bonds = 0;
|
1078
|
+
for ( j = 0; j < valence; j ++ ) {
|
1079
|
+
if ( at[a1].bond_type[j] <= BOND_TYPE_TRIPLE ) {
|
1080
|
+
chem_valence += at[a1].bond_type[j];
|
1081
|
+
} else {
|
1082
|
+
num_alt_bonds ++;
|
1083
|
+
}
|
1084
|
+
}
|
1085
|
+
switch( num_alt_bonds ) {
|
1086
|
+
case 0:
|
1087
|
+
break;
|
1088
|
+
case 2:
|
1089
|
+
chem_valence += 3; /* -C= */
|
1090
|
+
break;
|
1091
|
+
case 3:
|
1092
|
+
chem_valence += 4; /* >C= */
|
1093
|
+
break;
|
1094
|
+
default:
|
1095
|
+
{
|
1096
|
+
char szMsg[64];
|
1097
|
+
*err |= 8; /* wrong number of alt. bonds */
|
1098
|
+
sprintf( szMsg, "Atom '%s' has %d alternating bonds",
|
1099
|
+
at[a1].elname, num_alt_bonds );
|
1100
|
+
MOLFILE_ERR_SET (*err, 0, szMsg);
|
1101
|
+
}
|
1102
|
+
break;
|
1103
|
+
}
|
1104
|
+
at[a1].chem_bonds_valence = chem_valence;
|
1105
|
+
|
1106
|
+
/* aliased hydrogen atoms */
|
1107
|
+
if ( ERR_ELEM == (n1 = get_periodic_table_number( at[a1].elname ) ) ) {
|
1108
|
+
/* Case when elname contains more than 1 element: extract number of H if possible */
|
1109
|
+
if ( extract_ChargeRadical( at[a1].elname, &nRadical, &nCharge ) ) {
|
1110
|
+
if ( nRadical && at[a1].radical && nRadical != at[a1].radical ||
|
1111
|
+
nCharge && at[a1].charge && nCharge != at[a1].charge ) {
|
1112
|
+
MOLFILE_ERR_SET (*err, 0, "Ignored charge/radical redefinition:");
|
1113
|
+
MOLFILE_ERR_SET (*err, 0, ati[a1].elname);
|
1114
|
+
} else {
|
1115
|
+
if ( nRadical )
|
1116
|
+
at[a1].radical = nRadical;
|
1117
|
+
if ( nCharge )
|
1118
|
+
at[a1].charge = nCharge;
|
1119
|
+
}
|
1120
|
+
}
|
1121
|
+
at[a1].num_H = extract_H_atoms( at[a1].elname, at[a1].num_iso_H );
|
1122
|
+
if ( !at[a1].elname[0] && NUMH(at, a1) ) {
|
1123
|
+
/* alias contains only H. Added 2004-07-21, fixed 2004-07-22
|
1124
|
+
* move the heaviest isotope to the "central atom"
|
1125
|
+
* Note: this must be consistent with H-H treatment in remove_terminal_HDT()
|
1126
|
+
*/
|
1127
|
+
strcpy( at[a1].elname, "H" );
|
1128
|
+
if ( NUM_ISO_H(at,a1) ) {
|
1129
|
+
for ( j = NUM_H_ISOTOPES-1; 0 <= j; j -- ) {
|
1130
|
+
if ( at[a1].num_iso_H[j] ) {
|
1131
|
+
at[a1].num_iso_H[j] --;
|
1132
|
+
at[a1].iso_atw_diff = 1 + j;
|
1133
|
+
break;
|
1134
|
+
}
|
1135
|
+
}
|
1136
|
+
} else {
|
1137
|
+
at[a1].num_H --;
|
1138
|
+
}
|
1139
|
+
}
|
1140
|
+
if ( ERR_ELEM == (n1 = get_periodic_table_number( at[a1].elname ) ) ) {
|
1141
|
+
n1 = 0;
|
1142
|
+
}
|
1143
|
+
if ( n1 ) {
|
1144
|
+
at[a1].at_type |= 1; /* "Aliased" atom: data in the element name */
|
1145
|
+
MOLFILE_ERR_SET (*err, 0, "Parsed compound atom(s):");
|
1146
|
+
MOLFILE_ERR_SET (*err, 0, ati[a1].elname);
|
1147
|
+
}
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
at[a1].el_number = (U_CHAR) n1;
|
1151
|
+
if ( !n1 ) {
|
1152
|
+
*err |= 64; /* Unrecognized aromatic bond(s) replaced with single */
|
1153
|
+
MOLFILE_ERR_SET (*err, 0, "Unknown element(s):");
|
1154
|
+
MOLFILE_ERR_SET (*err, 0, at[a1].elname);
|
1155
|
+
} else
|
1156
|
+
/* replace explicit D or T with isotopic H (added 2003-06-02) */
|
1157
|
+
if ( el_number_H == n1 && !at[a1].iso_atw_diff ) {
|
1158
|
+
switch( at[a1].elname[0] ) {
|
1159
|
+
case 'D':
|
1160
|
+
at[a1].iso_atw_diff = 2;
|
1161
|
+
mystrncpy( at[a1].elname, "H", sizeof(at->elname) );
|
1162
|
+
break;
|
1163
|
+
case 'T':
|
1164
|
+
at[a1].iso_atw_diff = 3;
|
1165
|
+
mystrncpy( at[a1].elname, "H", sizeof(at->elname) );
|
1166
|
+
break;
|
1167
|
+
case 'H':
|
1168
|
+
if ( 1 <= ati[a1].isotopic_mass ) {
|
1169
|
+
AT_NUM iso_atw_diff;
|
1170
|
+
if ( ISOTOPIC_SHIFT_FLAG - ISOTOPIC_SHIFT_MAX <= ati[a1].isotopic_mass &&
|
1171
|
+
ISOTOPIC_SHIFT_FLAG + ISOTOPIC_SHIFT_MAX >= ati[a1].isotopic_mass ) {
|
1172
|
+
/* ati[a1].isotopic_mass is isotopic iso_atw_diff + ISOTOPIC_SHIFT_FLAG */
|
1173
|
+
iso_atw_diff = ati[a1].isotopic_mass - ISOTOPIC_SHIFT_FLAG;
|
1174
|
+
} else {
|
1175
|
+
/* ati[a1].isotopic_mass is isotopic mass */
|
1176
|
+
iso_atw_diff = get_atw_from_elnum( (int) at[a1].el_number );
|
1177
|
+
iso_atw_diff = ati[a1].isotopic_mass - iso_atw_diff;
|
1178
|
+
}
|
1179
|
+
if ( iso_atw_diff >= 0 )
|
1180
|
+
iso_atw_diff ++;
|
1181
|
+
/* reproduce Bug04: allowed non-terminal H heavier than T */
|
1182
|
+
if ( 1 <= iso_atw_diff &&
|
1183
|
+
(at[a1].valence != 1 || iso_atw_diff <= NUM_H_ISOTOPES) ) {
|
1184
|
+
at[a1].iso_atw_diff = (S_CHAR)iso_atw_diff;
|
1185
|
+
}
|
1186
|
+
}
|
1187
|
+
}
|
1188
|
+
} else
|
1189
|
+
/* isotopic shift */
|
1190
|
+
if ( ati[a1].isotopic_mass ) {
|
1191
|
+
AT_NUM iso_atw_diff;
|
1192
|
+
if ( ISOTOPIC_SHIFT_FLAG - ISOTOPIC_SHIFT_MAX <= ati[a1].isotopic_mass &&
|
1193
|
+
ISOTOPIC_SHIFT_FLAG + ISOTOPIC_SHIFT_MAX >= ati[a1].isotopic_mass ) {
|
1194
|
+
/* ati[a1].isotopic_mass is isotopic iso_atw_diff + ISOTOPIC_SHIFT_FLAG */
|
1195
|
+
iso_atw_diff = ati[a1].isotopic_mass - ISOTOPIC_SHIFT_FLAG;
|
1196
|
+
} else {
|
1197
|
+
/* ati[a1].isotopic_mass is isotopic mass */
|
1198
|
+
iso_atw_diff = get_atw_from_elnum( (int) at[a1].el_number );
|
1199
|
+
iso_atw_diff = ati[a1].isotopic_mass - iso_atw_diff;
|
1200
|
+
}
|
1201
|
+
if ( iso_atw_diff >= 0 )
|
1202
|
+
iso_atw_diff ++;
|
1203
|
+
at[a1].iso_atw_diff = (S_CHAR)iso_atw_diff;
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
/* add implicit hydrogen atoms flag */
|
1207
|
+
|
1208
|
+
if ( ati[a1].num_iso_H[0] == -1 ) {
|
1209
|
+
if ( !bDoNotAddH ) {
|
1210
|
+
at[a1].at_type |= 2; /* user requested to add H */
|
1211
|
+
}
|
1212
|
+
} else {
|
1213
|
+
at[a1].num_H = ati[a1].num_iso_H[0];
|
1214
|
+
}
|
1215
|
+
for ( j = 0; j < NUM_H_ISOTOPES; j ++ ) {
|
1216
|
+
at[a1].num_iso_H[j] = ati[a1].num_iso_H[j+1];
|
1217
|
+
}
|
1218
|
+
if ( num_alt_bonds ) {
|
1219
|
+
/* atom has aromatic bonds AND the chemical valence is not known */
|
1220
|
+
int num_H = NUMH(at, a1);
|
1221
|
+
int chem_valence_alt = at[a1].chem_bonds_valence + num_H;
|
1222
|
+
int bUnusualValenceArom =
|
1223
|
+
detect_unusual_el_valence( (int)at[a1].el_number, at[a1].charge,
|
1224
|
+
at[a1].radical, chem_valence_alt,
|
1225
|
+
num_H, at[a1].valence );
|
1226
|
+
int bUnusualValenceNoArom =
|
1227
|
+
detect_unusual_el_valence( (int)at[a1].el_number, at[a1].charge,
|
1228
|
+
at[a1].radical, chem_valence_alt-1,
|
1229
|
+
num_H, at[a1].valence );
|
1230
|
+
if ( bUnusualValenceArom && !bUnusualValenceNoArom ) {
|
1231
|
+
/* typically NH in 5-member aromatic ring */
|
1232
|
+
at[a1].chem_bonds_valence --;
|
1233
|
+
}
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
return 0;
|
1237
|
+
}
|
1238
|
+
/****************************************************************************************/
|
1239
|
+
int ExtractOneStructure( STRUCT_DATA *sd, INPUT_PARMS *ip, char *szTitle,
|
1240
|
+
inchi_Input *inp, INCHI_FILE *log_file, INCHI_FILE *output_file,
|
1241
|
+
INCHI_FILE *prb_file, ORIG_ATOM_DATA *orig_inp_data, int *num_inp,
|
1242
|
+
char *pStr, int nStrLen )
|
1243
|
+
{
|
1244
|
+
int *err = &sd->nStructReadError;
|
1245
|
+
char *pStrErr = sd->pStrErrStruct;
|
1246
|
+
inp_ATOM *at = NULL;
|
1247
|
+
MOL_COORD *szCoord = NULL;
|
1248
|
+
inchi_Atom *ati = NULL;
|
1249
|
+
int nNumAtoms = 0;
|
1250
|
+
int a1, j, valence, nDim, nNumBonds, nRet = 0;
|
1251
|
+
|
1252
|
+
/********************************************************
|
1253
|
+
*
|
1254
|
+
* Extract the structure
|
1255
|
+
*
|
1256
|
+
********************************************************/
|
1257
|
+
|
1258
|
+
FreeOrigAtData( orig_inp_data );
|
1259
|
+
nDim = 0;
|
1260
|
+
nNumBonds = 0;
|
1261
|
+
|
1262
|
+
if ( !inp || (nNumAtoms = inp->num_atoms) <= 0 || !(ati = inp->atom) ) {
|
1263
|
+
MOLFILE_ERR_SET (*err, 0, "Empty structure");
|
1264
|
+
*err = 98;
|
1265
|
+
goto err_exit;
|
1266
|
+
}
|
1267
|
+
if ( nNumAtoms >= MAX_ATOMS ) {
|
1268
|
+
MOLFILE_ERR_SET (*err, 0, "Too many atoms");
|
1269
|
+
*err = 70;
|
1270
|
+
orig_inp_data->num_inp_atoms = -1;
|
1271
|
+
goto err_exit;
|
1272
|
+
}
|
1273
|
+
|
1274
|
+
at = (inp_ATOM *) inchi_calloc( nNumAtoms, sizeof(at[0]) );
|
1275
|
+
szCoord = (MOL_COORD *) inchi_calloc (inchi_max(nNumAtoms, 1), sizeof (MOL_COORD));
|
1276
|
+
|
1277
|
+
if ( !at || !szCoord ) {
|
1278
|
+
MOLFILE_ERR_SET (*err, 0, "Out of RAM");
|
1279
|
+
*err = -1;
|
1280
|
+
goto err_exit;
|
1281
|
+
}
|
1282
|
+
/********************************************************
|
1283
|
+
*
|
1284
|
+
* Extract typical for Molfile structural data
|
1285
|
+
*
|
1286
|
+
********************************************************/
|
1287
|
+
/* extract atoms and bonds */
|
1288
|
+
for ( a1 = 0; a1 < nNumAtoms; a1 ++ ) {
|
1289
|
+
/* extract atoms */
|
1290
|
+
SetAtomProperties( at, szCoord, ati, a1, &nDim, pStrErr, err );
|
1291
|
+
if ( *err ) {
|
1292
|
+
goto err_exit;
|
1293
|
+
}
|
1294
|
+
/* extract connections */
|
1295
|
+
valence = ati[a1].num_bonds;
|
1296
|
+
for ( j = 0; j < valence; j ++ ) {
|
1297
|
+
SetBondProperties( at, ati, a1, j, nNumAtoms, &nNumBonds, pStrErr, err );
|
1298
|
+
}
|
1299
|
+
if ( *err ) {
|
1300
|
+
goto err_exit;
|
1301
|
+
}
|
1302
|
+
}
|
1303
|
+
|
1304
|
+
orig_inp_data->num_inp_atoms = nNumAtoms;
|
1305
|
+
orig_inp_data->num_inp_bonds = nNumBonds;
|
1306
|
+
orig_inp_data->num_dimensions = nDim;
|
1307
|
+
|
1308
|
+
/* extract elements, chemical valences, implicit H, isotopic shifts */
|
1309
|
+
for ( a1 = 0; a1 < nNumAtoms; a1 ++ ) {
|
1310
|
+
/* set temp flags in at[a1].at_type (1: data in atom name; 2: request to add H) */
|
1311
|
+
SetAtomAndBondProperties( at, ati, a1, ip->bDoNotAddH, pStrErr, err );
|
1312
|
+
if ( *err ) {
|
1313
|
+
goto err_exit;
|
1314
|
+
}
|
1315
|
+
}
|
1316
|
+
/* clear temp flags in at[].at_type; add implicit H */
|
1317
|
+
SetNumImplicitH( at, nNumAtoms );
|
1318
|
+
if ( *err ) {
|
1319
|
+
goto err_exit;
|
1320
|
+
}
|
1321
|
+
|
1322
|
+
/********************************************************
|
1323
|
+
*
|
1324
|
+
* Extract the 0D parities (typical for CML)
|
1325
|
+
*
|
1326
|
+
********************************************************/
|
1327
|
+
Extract0DParities( at, nNumAtoms, inp->stereo0D, inp->num_stereo0D, pStrErr, err );
|
1328
|
+
if ( *err ) {
|
1329
|
+
goto err_exit;
|
1330
|
+
}
|
1331
|
+
orig_inp_data->at = at; at = NULL;
|
1332
|
+
orig_inp_data->num_dimensions = nDim;
|
1333
|
+
orig_inp_data->num_inp_atoms = nNumAtoms;
|
1334
|
+
orig_inp_data->num_inp_bonds = nNumBonds;
|
1335
|
+
orig_inp_data->szCoord = szCoord; szCoord = NULL;
|
1336
|
+
|
1337
|
+
/* chiral flag */
|
1338
|
+
/* *****************************************************************************
|
1339
|
+
* Chiral flags are set in:
|
1340
|
+
* - RunICHI.c #1610 -- ReadTheStructure() -- cInChI, wInChI
|
1341
|
+
* - e_IchiMain.c #273 -- main() -- C example of calling InChI dll
|
1342
|
+
* - inchi_dll.c #1662 -- ExtractOneStructure -- InChI dll code (here)
|
1343
|
+
*******************************************************************************/
|
1344
|
+
if ( (ip->nMode & REQ_MODE_CHIR_FLG_STEREO) && (ip->nMode & REQ_MODE_STEREO) ) {
|
1345
|
+
if ( ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL ) {
|
1346
|
+
/* absolute stereo */
|
1347
|
+
ip->nMode &= ~(REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO);
|
1348
|
+
sd->bChiralFlag &= ~FLAG_INP_AT_NONCHIRAL;
|
1349
|
+
sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
|
1350
|
+
} else
|
1351
|
+
/*if ( ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL )*/ {
|
1352
|
+
/* relative stereo */
|
1353
|
+
ip->nMode &= ~(REQ_MODE_RACEMIC_STEREO);
|
1354
|
+
ip->nMode |= REQ_MODE_RELATIVE_STEREO;
|
1355
|
+
sd->bChiralFlag &= ~FLAG_INP_AT_CHIRAL;
|
1356
|
+
sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as non-chiral */
|
1357
|
+
}
|
1358
|
+
} else
|
1359
|
+
if ( ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL ) {
|
1360
|
+
sd->bChiralFlag &= ~FLAG_INP_AT_NONCHIRAL;
|
1361
|
+
sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
|
1362
|
+
} else
|
1363
|
+
if ( ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL ) {
|
1364
|
+
sd->bChiralFlag &= ~FLAG_INP_AT_CHIRAL;
|
1365
|
+
sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as non-chiral */
|
1366
|
+
}
|
1367
|
+
|
1368
|
+
*num_inp += 1;
|
1369
|
+
|
1370
|
+
err_exit:
|
1371
|
+
|
1372
|
+
if ( at )
|
1373
|
+
inchi_free( at );
|
1374
|
+
if ( szCoord )
|
1375
|
+
inchi_free( szCoord );
|
1376
|
+
|
1377
|
+
nRet = TreatReadTheStructureErrors( sd, ip, LOG_MASK_NO_WARN, NULL, log_file, output_file, prb_file,
|
1378
|
+
orig_inp_data, num_inp, pStr, nStrLen );
|
1379
|
+
|
1380
|
+
return nRet;
|
1381
|
+
|
1382
|
+
}
|
1383
|
+
/********************************************************/
|
1384
|
+
int INCHI_DECL GetStringLength( char *p )
|
1385
|
+
{
|
1386
|
+
if ( p ) {
|
1387
|
+
return strlen(p);
|
1388
|
+
} else {
|
1389
|
+
return 0;
|
1390
|
+
}
|
1391
|
+
}
|
1392
|
+
#if( defined( _WIN32 ) && defined( _MSC_VER ) && _MSC_VER >= 800 && defined(_USRDLL) && defined(INCHI_LINK_AS_DLL) )
|
1393
|
+
/* Win32 & MS VC ++, compile and link as a DLL */
|
1394
|
+
/*********************************************************/
|
1395
|
+
/* C calling conventions export from Win32 dll */
|
1396
|
+
/*********************************************************/
|
1397
|
+
/* prototypes */
|
1398
|
+
int cdecl_GetINCHI( inchi_Input *inp, inchi_Output *out );
|
1399
|
+
void cdecl_FreeINCHI( inchi_Output *out );
|
1400
|
+
int cdecl_GetStringLength( char *p );
|
1401
|
+
int cdecl_Get_inchi_Input_FromAuxInfo
|
1402
|
+
( char *szInchiAuxInfo, int bDoNotAddH, InchiInpData *pInchiInp );
|
1403
|
+
void cdecl_Free_inchi_Input( inchi_Input *pInp );
|
1404
|
+
|
1405
|
+
/* implementation */
|
1406
|
+
/* vc6_libinchi.def provides export withou cdecl_ prefixes */
|
1407
|
+
/********************************************************/
|
1408
|
+
int cdecl_GetINCHI( inchi_Input *inp, inchi_Output *out )
|
1409
|
+
{
|
1410
|
+
return GetINCHI( inp, out );
|
1411
|
+
}
|
1412
|
+
/********************************************************/
|
1413
|
+
void cdecl_FreeINCHI( inchi_Output *out )
|
1414
|
+
{
|
1415
|
+
FreeINCHI( out );
|
1416
|
+
}
|
1417
|
+
/********************************************************/
|
1418
|
+
int cdecl_GetStringLength( char *p )
|
1419
|
+
{
|
1420
|
+
return GetStringLength( p );
|
1421
|
+
}
|
1422
|
+
/********************************************************/
|
1423
|
+
int cdecl_Get_inchi_Input_FromAuxInfo
|
1424
|
+
( char *szInchiAuxInfo, int bDoNotAddH, InchiInpData *pInchiInp )
|
1425
|
+
{
|
1426
|
+
return Get_inchi_Input_FromAuxInfo
|
1427
|
+
( szInchiAuxInfo, bDoNotAddH, pInchiInp );
|
1428
|
+
}
|
1429
|
+
/********************************************************/
|
1430
|
+
void cdecl_Free_inchi_Input( inchi_Input *pInp )
|
1431
|
+
{
|
1432
|
+
Free_inchi_Input( pInp );
|
1433
|
+
}
|
1434
|
+
#endif
|
1435
|
+
|
1436
|
+
#if( defined(__GNUC__) && __GNUC__ >= 3 && defined(__MINGW32__) && defined(_WIN32) )
|
1437
|
+
#include <windows.h>
|
1438
|
+
/*********************************************************/
|
1439
|
+
/* Pacal calling conventions export from Win32 dll */
|
1440
|
+
/*********************************************************/
|
1441
|
+
/* prototypes */
|
1442
|
+
int PASCAL pasc_GetINCHI( inchi_Input *inp, inchi_Output *out );
|
1443
|
+
void PASCAL pasc_FreeINCHI( inchi_Output *out );
|
1444
|
+
int PASCAL pasc_GetStringLength( char *p );
|
1445
|
+
int PASCAL pasc_Get_inchi_Input_FromAuxInfo
|
1446
|
+
( char *szInchiAuxInfo, int bDoNotAddH, InchiInpData *pInchiInp );
|
1447
|
+
void PASCAL pasc_Free_inchi_Input( inchi_Input *pInp );
|
1448
|
+
|
1449
|
+
/* implementation */
|
1450
|
+
/* vc6_libinchi.def provides export withou PASCAL pasc_ prefixes */
|
1451
|
+
/********************************************************/
|
1452
|
+
int PASCAL pasc_GetINCHI( inchi_Input *inp, inchi_Output *out )
|
1453
|
+
{
|
1454
|
+
return GetINCHI( inp, out );
|
1455
|
+
}
|
1456
|
+
/********************************************************/
|
1457
|
+
void PASCAL pasc_FreeINCHI( inchi_Output *out )
|
1458
|
+
{
|
1459
|
+
FreeINCHI( out );
|
1460
|
+
}
|
1461
|
+
/********************************************************/
|
1462
|
+
int PASCAL pasc_GetStringLength( char *p )
|
1463
|
+
{
|
1464
|
+
return GetStringLength( p );
|
1465
|
+
}
|
1466
|
+
/********************************************************/
|
1467
|
+
int PASCAL pasc_Get_inchi_Input_FromAuxInfo
|
1468
|
+
( char *szInchiAuxInfo, int bDoNotAddH, InchiInpData *pInchiInp )
|
1469
|
+
{
|
1470
|
+
return Get_inchi_Input_FromAuxInfo
|
1471
|
+
( szInchiAuxInfo, bDoNotAddH, pInchiInp );
|
1472
|
+
}
|
1473
|
+
/********************************************************/
|
1474
|
+
void PASCAL pasc_Free_inchi_Input( inchi_Input *pInp )
|
1475
|
+
{
|
1476
|
+
Free_inchi_Input( pInp );
|
1477
|
+
}
|
1478
|
+
#endif
|
1479
|
+
|
1480
|
+
|