rino 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +44 -0
- data/Rakefile +123 -0
- data/ext/extconf.rb +26 -0
- data/ext/ruby_inchi_main.so +0 -0
- data/ext/src/aux2atom.h +2786 -0
- data/ext/src/comdef.h +148 -0
- data/ext/src/e_0dstereo.c +3014 -0
- data/ext/src/e_0dstereo.h +31 -0
- data/ext/src/e_comdef.h +57 -0
- data/ext/src/e_ctl_data.h +147 -0
- data/ext/src/e_ichi_io.c +498 -0
- data/ext/src/e_ichi_io.h +40 -0
- data/ext/src/e_ichi_parms.c +37 -0
- data/ext/src/e_ichi_parms.h +41 -0
- data/ext/src/e_ichicomp.h +50 -0
- data/ext/src/e_ichierr.h +40 -0
- data/ext/src/e_ichimain.c +593 -0
- data/ext/src/e_ichisize.h +43 -0
- data/ext/src/e_inchi_atom.c +75 -0
- data/ext/src/e_inchi_atom.h +33 -0
- data/ext/src/e_inpdef.h +41 -0
- data/ext/src/e_mode.h +706 -0
- data/ext/src/e_mol2atom.c +649 -0
- data/ext/src/e_readinch.c +58 -0
- data/ext/src/e_readmol.c +54 -0
- data/ext/src/e_readmol.h +180 -0
- data/ext/src/e_readstru.c +251 -0
- data/ext/src/e_readstru.h +33 -0
- data/ext/src/e_util.c +284 -0
- data/ext/src/e_util.h +61 -0
- data/ext/src/extr_ct.h +251 -0
- data/ext/src/ichi.h +206 -0
- data/ext/src/ichi_bns.c +7999 -0
- data/ext/src/ichi_bns.h +231 -0
- data/ext/src/ichican2.c +5000 -0
- data/ext/src/ichicano.c +2195 -0
- data/ext/src/ichicano.h +49 -0
- data/ext/src/ichicans.c +1625 -0
- data/ext/src/ichicant.h +379 -0
- data/ext/src/ichicomn.h +260 -0
- data/ext/src/ichicomp.h +50 -0
- data/ext/src/ichidrp.h +119 -0
- data/ext/src/ichierr.h +124 -0
- data/ext/src/ichiisot.c +101 -0
- data/ext/src/ichilnct.c +286 -0
- data/ext/src/ichimain.h +132 -0
- data/ext/src/ichimak2.c +1189 -0
- data/ext/src/ichimake.c +3812 -0
- data/ext/src/ichimake.h +205 -0
- data/ext/src/ichimap1.c +851 -0
- data/ext/src/ichimap2.c +2856 -0
- data/ext/src/ichimap4.c +1609 -0
- data/ext/src/ichinorm.c +741 -0
- data/ext/src/ichinorm.h +67 -0
- data/ext/src/ichiparm.c +45 -0
- data/ext/src/ichiparm.h +1441 -0
- data/ext/src/ichiprt1.c +3612 -0
- data/ext/src/ichiprt2.c +1511 -0
- data/ext/src/ichiprt3.c +3011 -0
- data/ext/src/ichiqueu.c +1003 -0
- data/ext/src/ichiring.c +326 -0
- data/ext/src/ichiring.h +49 -0
- data/ext/src/ichisize.h +35 -0
- data/ext/src/ichisort.c +539 -0
- data/ext/src/ichister.c +3538 -0
- data/ext/src/ichister.h +35 -0
- data/ext/src/ichitaut.c +3843 -0
- data/ext/src/ichitaut.h +387 -0
- data/ext/src/ichitime.h +74 -0
- data/ext/src/inchi_api.h +670 -0
- data/ext/src/inchi_dll.c +1480 -0
- data/ext/src/inchi_dll.h +34 -0
- data/ext/src/inchi_dll_main.c +23 -0
- data/ext/src/inchi_dll_main.h +31 -0
- data/ext/src/inpdef.h +328 -0
- data/ext/src/lreadmol.h +1246 -0
- data/ext/src/mode.h +706 -0
- data/ext/src/ruby_inchi_main.c +558 -0
- data/ext/src/runichi.c +4179 -0
- data/ext/src/strutil.c +3861 -0
- data/ext/src/strutil.h +182 -0
- data/ext/src/util.c +1130 -0
- data/ext/src/util.h +85 -0
- data/lib/clean_tempfile.rb +220 -0
- data/lib/rino.rb +111 -0
- data/test/test.rb +386 -0
- metadata +130 -0
data/ext/src/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
|
+
|