rino 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. data/README +44 -0
  2. data/Rakefile +123 -0
  3. data/ext/extconf.rb +26 -0
  4. data/ext/ruby_inchi_main.so +0 -0
  5. data/ext/src/aux2atom.h +2786 -0
  6. data/ext/src/comdef.h +148 -0
  7. data/ext/src/e_0dstereo.c +3014 -0
  8. data/ext/src/e_0dstereo.h +31 -0
  9. data/ext/src/e_comdef.h +57 -0
  10. data/ext/src/e_ctl_data.h +147 -0
  11. data/ext/src/e_ichi_io.c +498 -0
  12. data/ext/src/e_ichi_io.h +40 -0
  13. data/ext/src/e_ichi_parms.c +37 -0
  14. data/ext/src/e_ichi_parms.h +41 -0
  15. data/ext/src/e_ichicomp.h +50 -0
  16. data/ext/src/e_ichierr.h +40 -0
  17. data/ext/src/e_ichimain.c +593 -0
  18. data/ext/src/e_ichisize.h +43 -0
  19. data/ext/src/e_inchi_atom.c +75 -0
  20. data/ext/src/e_inchi_atom.h +33 -0
  21. data/ext/src/e_inpdef.h +41 -0
  22. data/ext/src/e_mode.h +706 -0
  23. data/ext/src/e_mol2atom.c +649 -0
  24. data/ext/src/e_readinch.c +58 -0
  25. data/ext/src/e_readmol.c +54 -0
  26. data/ext/src/e_readmol.h +180 -0
  27. data/ext/src/e_readstru.c +251 -0
  28. data/ext/src/e_readstru.h +33 -0
  29. data/ext/src/e_util.c +284 -0
  30. data/ext/src/e_util.h +61 -0
  31. data/ext/src/extr_ct.h +251 -0
  32. data/ext/src/ichi.h +206 -0
  33. data/ext/src/ichi_bns.c +7999 -0
  34. data/ext/src/ichi_bns.h +231 -0
  35. data/ext/src/ichican2.c +5000 -0
  36. data/ext/src/ichicano.c +2195 -0
  37. data/ext/src/ichicano.h +49 -0
  38. data/ext/src/ichicans.c +1625 -0
  39. data/ext/src/ichicant.h +379 -0
  40. data/ext/src/ichicomn.h +260 -0
  41. data/ext/src/ichicomp.h +50 -0
  42. data/ext/src/ichidrp.h +119 -0
  43. data/ext/src/ichierr.h +124 -0
  44. data/ext/src/ichiisot.c +101 -0
  45. data/ext/src/ichilnct.c +286 -0
  46. data/ext/src/ichimain.h +132 -0
  47. data/ext/src/ichimak2.c +1189 -0
  48. data/ext/src/ichimake.c +3812 -0
  49. data/ext/src/ichimake.h +205 -0
  50. data/ext/src/ichimap1.c +851 -0
  51. data/ext/src/ichimap2.c +2856 -0
  52. data/ext/src/ichimap4.c +1609 -0
  53. data/ext/src/ichinorm.c +741 -0
  54. data/ext/src/ichinorm.h +67 -0
  55. data/ext/src/ichiparm.c +45 -0
  56. data/ext/src/ichiparm.h +1441 -0
  57. data/ext/src/ichiprt1.c +3612 -0
  58. data/ext/src/ichiprt2.c +1511 -0
  59. data/ext/src/ichiprt3.c +3011 -0
  60. data/ext/src/ichiqueu.c +1003 -0
  61. data/ext/src/ichiring.c +326 -0
  62. data/ext/src/ichiring.h +49 -0
  63. data/ext/src/ichisize.h +35 -0
  64. data/ext/src/ichisort.c +539 -0
  65. data/ext/src/ichister.c +3538 -0
  66. data/ext/src/ichister.h +35 -0
  67. data/ext/src/ichitaut.c +3843 -0
  68. data/ext/src/ichitaut.h +387 -0
  69. data/ext/src/ichitime.h +74 -0
  70. data/ext/src/inchi_api.h +670 -0
  71. data/ext/src/inchi_dll.c +1480 -0
  72. data/ext/src/inchi_dll.h +34 -0
  73. data/ext/src/inchi_dll_main.c +23 -0
  74. data/ext/src/inchi_dll_main.h +31 -0
  75. data/ext/src/inpdef.h +328 -0
  76. data/ext/src/lreadmol.h +1246 -0
  77. data/ext/src/mode.h +706 -0
  78. data/ext/src/ruby_inchi_main.c +558 -0
  79. data/ext/src/runichi.c +4179 -0
  80. data/ext/src/strutil.c +3861 -0
  81. data/ext/src/strutil.h +182 -0
  82. data/ext/src/util.c +1130 -0
  83. data/ext/src/util.h +85 -0
  84. data/lib/clean_tempfile.rb +220 -0
  85. data/lib/rino.rb +111 -0
  86. data/test/test.rb +386 -0
  87. metadata +130 -0
@@ -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
+