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,558 @@
1
+ /* =================================
2
+ * Rino - The InChI Toolkit for Ruby
3
+ * =================================
4
+ *
5
+ * Project Info: http://rino.rubyforge.org
6
+ *
7
+ * Copyright (C) 2006 Richard L. Apodaca
8
+ *
9
+ * This library is free software; you can redistribute it and/or
10
+ * modify it under the terms of the GNU Lesser General Public
11
+ * License version 2.1 as published by the Free Software
12
+ * Foundation.
13
+ *
14
+ * This library is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ * Lesser General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU Lesser General Public
20
+ * License along with this library; if not, write to the Free
21
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
22
+ * Boston, MA 02111-1301, USA.
23
+ *
24
+ * This file originally appeared as 'inchi_main.c' distributed in
25
+ * InChI Software Version 1.00 developed at NIST, and has been
26
+ * modified.
27
+ */
28
+
29
+ /*
30
+ * International Union of Pure and Applied Chemistry (IUPAC)
31
+ * International Chemical Identifier (InChI)
32
+ * Version 1
33
+ * Software version 1.00
34
+ * April 13, 2005
35
+ * Developed at NIST
36
+ */
37
+
38
+ #include <stdio.h>
39
+ #include <stdlib.h>
40
+
41
+ #include <string.h>
42
+ #include <ctype.h>
43
+ #include <stdarg.h>
44
+ #include <errno.h>
45
+ #include <limits.h>
46
+ #include <float.h>
47
+
48
+ #include "ruby.h"
49
+ #include "rubyio.h"
50
+ #include "e_mode.h"
51
+ #include "inchi_api.h"
52
+ #include "e_inchi_atom.h"
53
+ #include "e_ctl_data.h"
54
+ #include "e_ichi_parms.h"
55
+ #include "e_util.h"
56
+ #include "e_ichi_io.h"
57
+ #include "e_ichierr.h"
58
+ #include "e_readstru.h"
59
+ #include "e_ichicomp.h"
60
+ #ifdef CREATE_0D_PARITIES
61
+ #include "e_0dstereo.h"
62
+ #endif
63
+
64
+ static VALUE cMain;
65
+ static int e_bInterrupted = 0;
66
+
67
+ static int main_copy(int argc, char *argv[]);
68
+
69
+ static void run(VALUE self, VALUE argvVal)
70
+ {
71
+ int arg_count = RARRAY(argvVal)->len;
72
+ int argc = arg_count;
73
+ int i;
74
+ char *argv[argc];
75
+
76
+ for (i = 0; i < arg_count; i++)
77
+ {
78
+ VALUE arg = rb_ary_entry(argvVal, i);
79
+ argv[i] = RSTRING(arg)->ptr;
80
+ }
81
+
82
+ main_copy(argc, argv);
83
+ }
84
+
85
+ static int main_copy( int argc, char *argv[ ] )
86
+ {
87
+ STRUCT_DATA struct_data;
88
+ STRUCT_DATA *sd = &struct_data;
89
+ FILE *inp_file = NULL, *output_file = NULL, *log_file = NULL, *prb_file = NULL;
90
+
91
+ long num_inp, num_err, num_output;
92
+ char szSdfDataValue[MAX_SDF_VALUE+1];
93
+ const char *p1, *p2;
94
+
95
+ unsigned long ulDisplTime = 0; /* infinite, milliseconds */
96
+ unsigned long ulTotalProcessingTime = 0;
97
+ INPUT_PARMS inp_parms;
98
+ INPUT_PARMS *ip = &inp_parms;
99
+ char szInchiCmdLine[512];
100
+
101
+ inchi_Input inchi_inp, *pInp = &inchi_inp;
102
+ inchi_Output inchi_out, *pOut = &inchi_out;
103
+
104
+
105
+ int bReleaseVersion = bRELEASE_VERSION;
106
+ #define nStrLen 256
107
+ char pStrInchiId[nStrLen], pStrLogId[nStrLen];
108
+ int nRet = 0, nRet1, i, k, tot_len;
109
+ int inp_index, out_index;
110
+ long lSdfId;
111
+ int nStructNo;
112
+
113
+ #if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
114
+ int num_repeat = REPEAT_ALL;
115
+ #endif
116
+
117
+
118
+ #if( TRACE_MEMORY_LEAKS == 1 )
119
+ _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
120
+ /* for execution outside of the VC++ debugger uncomment one of the following two */
121
+ /*#define MY_REPORT_FILE _CRTDBG_FILE_STDERR */
122
+ /*#define MY_REPORT_FILE _CRTDBG_FILE_STDOUT */
123
+ #ifdef MY_REPORT_FILE
124
+ _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
125
+ _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
126
+ _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
127
+ _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
128
+ _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
129
+ _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
130
+ #else
131
+ _CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG);
132
+ #endif
133
+ /* turn on floating point exceptions */
134
+ {
135
+ /* Get the default control word. */
136
+ int cw = _controlfp( 0,0 );
137
+
138
+ /* Set the exception masks OFF, turn exceptions on. */
139
+ /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
140
+ cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_ZERODIVIDE|EM_DENORMAL);
141
+
142
+ /* Set the control word. */
143
+ _controlfp( cw, MCW_EM );
144
+
145
+ }
146
+ #endif
147
+
148
+ /*****************************************************************
149
+ *
150
+ * Set Ctrl+C trap; works under Win32 + MS VC++
151
+ *
152
+ *****************************************************************/
153
+ #if( defined( _WIN32 ) && defined( _CONSOLE ) && defined(_MSC_VER) && _MSC_VER >= 800 && defined(ADD_WIN_CTLC))
154
+ if ( SetConsoleCtrlHandler( MyHandlerRoutine, 1 ) ) {
155
+ /*ConsoleQuit = WasInterrupted*/;
156
+ }
157
+ #endif
158
+
159
+
160
+
161
+ #if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
162
+ repeat:
163
+ inp_file = output_file = log_file = prb_file = NULL;
164
+ #endif
165
+
166
+ num_inp = 0;
167
+ num_err = 0;
168
+ num_output = 0;
169
+
170
+ if ( argc < 2 || argc==2 && ( argv[1][0]==INCHI_OPTION_PREFX ) &&
171
+ (!strcmp(argv[1]+1, "?") || !stricmp(argv[1]+1, "help") ) ) {
172
+ e_HelpCommandLineParms(stdout);
173
+ return 0;
174
+ }
175
+ /* original input structure */
176
+ memset( pInp, 0, sizeof(*pInp) );
177
+ memset( pOut, 0, sizeof(*pOut) );
178
+
179
+ memset( szSdfDataValue , 0, sizeof( szSdfDataValue ) );
180
+
181
+ /* explicitly cast to (const char **) to avoid a warning about "incompatible pointer type":*/
182
+ if ( 0 > e_ReadCommandLineParms( argc, (const char **)argv, ip, szSdfDataValue, &ulDisplTime, bReleaseVersion, NULL ) ) {
183
+ goto exit_function;
184
+ }
185
+ if ( !e_OpenFiles( &inp_file, &output_file, &log_file, &prb_file, ip ) ) {
186
+ goto exit_function;
187
+ }
188
+ if ( ip->bNoStructLabels ) {
189
+ ip->pSdfLabel = NULL;
190
+ ip->pSdfValue = NULL;
191
+ } else
192
+ if ( ip->nInputType == INPUT_INCHI_PLAIN ||
193
+ ip->nInputType == INPUT_INCHI_XML ||
194
+ ip->nInputType == INPUT_CMLFILE ) {
195
+ /* the input may contain both the header and the label of the structure */
196
+ if ( !ip->pSdfLabel )
197
+ ip->pSdfLabel = ip->szSdfDataHeader;
198
+ if ( !ip->pSdfValue )
199
+ ip->pSdfValue = szSdfDataValue;
200
+ }
201
+ e_PrintInputParms( log_file, ip );
202
+ pStrInchiId[0] = '\0';
203
+ /******************************************************************/
204
+ /* Main cycle */
205
+ /* read input structures and create their InChI */
206
+ ulTotalProcessingTime = 0;
207
+
208
+ out_index = 0;
209
+ while ( !e_bInterrupted ) {
210
+ int bHasTimeout = 0;
211
+ if ( ip->last_struct_number && num_inp >= ip->last_struct_number ) {
212
+ nRet = _IS_EOF; /* simulate end of file */
213
+ goto exit_function;
214
+ }
215
+ /* create command line */
216
+ szInchiCmdLine[0] = '\0';
217
+ for ( i = 1; i < argc; i ++ ) {
218
+ if ( argv[i] && INCHI_OPTION_PREFX == argv[i][0] && argv[i][1] ) {
219
+ /* omit certrain options */
220
+ if ( !memicmp( argv[i]+1, "start:", 6) ||
221
+ !memicmp( argv[i]+1, "end:", 4) ||
222
+ !stricmp( argv[i]+1, "Tabbed" )
223
+ ) {
224
+ continue;
225
+ }
226
+ if ( !memicmp( argv[i]+1, "w", 1 ) && isdigit( UCINT argv[i][2] ) ) {
227
+ bHasTimeout = 1;
228
+ }
229
+ /* add option to szInchiCmdLine */
230
+ if ( strlen(szInchiCmdLine)+strlen(argv[i]) + 4 < sizeof(szInchiCmdLine) ) {
231
+ if ( szInchiCmdLine[0] )
232
+ strcat( szInchiCmdLine, " " );
233
+ k = ( !(k=strcspn( argv[i], " \t" )) || argv[i][k] ); /* k means enclose in "" */
234
+ if ( k )
235
+ strcat( szInchiCmdLine, "\"" );
236
+ strcat( szInchiCmdLine, argv[i] );
237
+ if ( k )
238
+ strcat( szInchiCmdLine, "\"" );
239
+ } else {
240
+ e_my_fprintf( stderr, "Too many options. Option \"%s\" ignored\n", argv[i] );
241
+ }
242
+ }
243
+ }
244
+ if ( !bHasTimeout ) {
245
+ /* add default timeout option -W60: 60 seconds */
246
+ char p1[] = " W60";
247
+ p1[1] = INCHI_OPTION_PREFX;
248
+ if ( strlen(szInchiCmdLine) + strlen( p1 ) < sizeof(szInchiCmdLine) ) {
249
+ strcat( szInchiCmdLine, p1 );
250
+ } else {
251
+ e_my_fprintf( stderr, "Too many options. Option \"%s\" ignored\n", p1 );
252
+ }
253
+ }
254
+
255
+ inp_index = out_index;
256
+ /* read one structure from input */
257
+ e_FreeInchi_Input( pInp );
258
+ //e_my_fprintf( stderr, "\rStructure: %d.................\r", num_inp+1 );
259
+ nRet = e_ReadStructure( sd, ip, inp_file, log_file, output_file, prb_file, pInp, num_inp+1,
260
+ /* for CML:*/ inp_index, &out_index );
261
+ /* simulate INChI structure header */
262
+ lSdfId = ( ip->bGetSdfileId )? ip->lSdfId : 0; /* if requested then CAS r.n. otherwise struct. number*/
263
+ nStructNo = ( ip->lMolfileNumber > 0 )? ip->lMolfileNumber : num_inp+1;
264
+ e_MakeOutputHeader( ip->pSdfLabel, ip->pSdfValue, lSdfId, nStructNo, pStrInchiId, pStrLogId );
265
+ if ( sd->pStrErrStruct && sd->pStrErrStruct[0] ) {
266
+ p1 = "; ";
267
+ p2 = sd->pStrErrStruct;
268
+ } else {
269
+ p1 = p2 = "";
270
+ }
271
+ /* e_ReadStructure() outputs the error/warning messages, so we do not need to re-output them here */
272
+ switch ( nRet ) {
273
+ case _IS_FATAL:
274
+ num_inp ++;
275
+ num_err ++;
276
+ goto exit_function;
277
+ case _IS_EOF:
278
+ //e_my_fprintf( stderr, "\rStructure %d could not be read: Detected end of file. \r", num_inp+1 );
279
+ goto exit_function;
280
+ case _IS_ERROR:
281
+ num_inp ++;
282
+ num_err ++;
283
+ continue;
284
+ case _IS_SKIP:
285
+ num_inp ++;
286
+ continue;
287
+ }
288
+ if ( nRet != _IS_WARNING ) {
289
+ //e_my_fprintf( stderr, "\r%s \r", pStrLogId );
290
+ }
291
+ /* chiral flag */
292
+ /* *****************************************************************************
293
+ * Chiral flags are set in:
294
+ * - RunICHI.c #1610 -- ReadTheStructure() -- cInChI, wInChI
295
+ * - e_IchiMain.c #273 -- main() -- C example of calling InChI dll (here)
296
+ * - inchi_dll.c #1662 -- ExtractOneStructure -- InChI dll code
297
+ *******************************************************************************/
298
+
299
+ p1 = NULL;
300
+ if ( (ip->nMode & REQ_MODE_CHIR_FLG_STEREO) && (ip->nMode & REQ_MODE_STEREO) &&
301
+ ( ip->bChiralFlag & (FLAG_SET_INP_AT_CHIRAL | FLAG_SET_INP_AT_NONCHIRAL) ) ) {
302
+ ; /* cmd line has priority over the chiral flag in Molfile */
303
+ } else
304
+ if ( sd->bChiralFlag & FLAG_INP_AT_CHIRAL ) {
305
+ p1 = e_GetChiralFlagString( 1 ); /* input file has chiral flag */
306
+ } else
307
+ if ( (ip->nMode & REQ_MODE_CHIR_FLG_STEREO) && (ip->nMode & REQ_MODE_STEREO) ||
308
+ (sd->bChiralFlag & FLAG_INP_AT_NONCHIRAL) ) { /* fix 04/05/2005 D.T.*/
309
+ /* chiral flag requested (/SUCF) or input has non-chiral flag */
310
+ p1 = e_GetChiralFlagString( 0 );
311
+ }
312
+ if ( p1 ) {
313
+ if ( strlen(szInchiCmdLine) + strlen( p1 ) < sizeof(szInchiCmdLine) ) {
314
+ strcat( szInchiCmdLine, p1 );
315
+ } else {
316
+ e_my_fprintf( stderr, "Too many options. Option \"%s\" ignored\n", p1 );
317
+ }
318
+ }
319
+
320
+ /* create INChI for each connected component of the structure and optionally display them */
321
+ /* output INChI for the whole structure */
322
+ FreeINCHI ( pOut );
323
+ pInp->szOptions = szInchiCmdLine;
324
+ #ifdef CREATE_0D_PARITIES
325
+ if ( !pInp->stereo0D && !pInp->num_stereo0D ) {
326
+ int bPointedEdgeStereo = (0 != (TG_FLAG_POINTED_EDGE_STEREO & ip->bTautFlags));
327
+ set_0D_stereo_parities( pInp, bPointedEdgeStereo );
328
+ Clear3D2Dstereo(pInp);
329
+ }
330
+ #endif
331
+ #ifdef NEIGH_ONLY_ONCE
332
+ e_RemoveRedundantNeighbors( pInp );
333
+ #endif
334
+ /********************************************
335
+ *
336
+ * CREATE INCHI
337
+ *
338
+ ********************************************/
339
+ nRet1 = GetINCHI( pInp, pOut );
340
+
341
+ ulTotalProcessingTime += sd->ulStructTime;
342
+ nRet = nRet1;
343
+ #ifdef MAKE_INCHI_FROM_AUXINFO
344
+ /**************************************************
345
+ *
346
+ * CREATE one more INCHI FROM AuxInfo and compare
347
+ *
348
+ * it to to the first INCHI
349
+ *
350
+ * Note: This should double the elapsed CPU time
351
+ *
352
+ **************************************************/
353
+ if ( nRet1 == inchi_Ret_OKAY || nRet1 == inchi_Ret_WARNING ) {
354
+ char *szInchiAuxInfo = pOut->szAuxInfo, *p1 /* shadowing previous definition */;
355
+ int bDoNotAddH = ip->bDoNotAddH;
356
+ int nRet2;
357
+ inchi_Input inchi_inp2, *pInp2 = &inchi_inp2;
358
+ inchi_Output inchi_out2, *pOut2 = &inchi_out2;
359
+ InchiInpData idat;
360
+ /* setup input for Get_inchi_Input_FromAuxInfo */
361
+ idat.pInp = pInp2;
362
+ pInp2->szOptions = NULL; /* not needed */
363
+
364
+ /* Make InChI input out of AuxInfo */
365
+ nRet2 = Get_inchi_Input_FromAuxInfo( szInchiAuxInfo, bDoNotAddH, &idat );
366
+
367
+ if ( inchi_Ret_OKAY == nRet2 || inchi_Ret_WARNING == nRet2 ) {
368
+ /* set chiral flag */
369
+ p1 = NULL;
370
+ if ( (ip->nMode & REQ_MODE_CHIR_FLG_STEREO) && (ip->nMode & REQ_MODE_STEREO) &&
371
+ ( ip->bChiralFlag & (FLAG_SET_INP_AT_CHIRAL | FLAG_SET_INP_AT_NONCHIRAL) ) ) {
372
+ ; /* cmd line has priority over the chiral flag in Molfile */
373
+ } else
374
+ if ( idat.bChiral & FLAG_INP_AT_CHIRAL ) { /* fix 04/05/2005 D.T.*/
375
+ p1 = e_GetChiralFlagString( 1 ); /* input file has chiral flag */
376
+ } else
377
+ if ( (ip->nMode & REQ_MODE_CHIR_FLG_STEREO) && (ip->nMode & REQ_MODE_STEREO) ||
378
+ (idat.bChiral & FLAG_INP_AT_NONCHIRAL) ) { /* fix 04/05/2005 D.T.*/
379
+ /* chiral flag requested (/SUCF) or input has non-chiral flag */
380
+ p1 = e_GetChiralFlagString( 0 );
381
+ }
382
+ if ( p1 ) {
383
+ if ( strlen(szInchiCmdLine) + strlen( p1 ) < sizeof(szInchiCmdLine) ) {
384
+ strcat( szInchiCmdLine, p1 );
385
+ } else {
386
+ e_my_fprintf( stderr, "Too many options. Option \"%s\" ignored\n", p1 );
387
+ }
388
+ }
389
+
390
+ /* Make InChI out of InChI input out of AuxInfo */
391
+ pInp2->szOptions = pInp->szOptions;
392
+ memset( pOut2, 0, sizeof(*pOut2) );
393
+ nRet2 = GetINCHI( pInp2, pOut2 );
394
+ /* Compare the two InChI */
395
+ if ( nRet2 == inchi_Ret_OKAY || nRet2 == inchi_Ret_WARNING ) {
396
+ if ( !pOut2->szInChI || strcmp( pOut->szInChI, pOut2->szInChI ) ) {
397
+ e_my_fprintf( stderr, "InChI from AuxInfo Is Different!\n" );
398
+ }
399
+ } else {
400
+ e_my_fprintf( stderr, "InChI from AuxInfo could not be produced: \"%s\"\n", pOut2->szMessage );
401
+ }
402
+ FreeINCHI( pOut2 );
403
+ }
404
+ Free_inchi_Input( pInp2 );
405
+ }
406
+ #endif
407
+
408
+ /*****************************/
409
+ /* output err/warn */
410
+ /*****************************/
411
+ if ( pOut->szMessage && pOut->szMessage[0] ) {
412
+ p1 = "; ";
413
+ p2 = pOut->szMessage;
414
+ } else {
415
+ p1 = p2 = "";
416
+ }
417
+ switch ( nRet ) {
418
+ case inchi_Ret_UNKNOWN:
419
+ case inchi_Ret_FATAL: /* fatal processing error -- typically, memory allocation error */
420
+ num_inp ++;
421
+ num_err ++;
422
+ #if( defined(EXIT_ON_ERR) && defined(REPEAT_ALL) && REPEAT_ALL > 0 )
423
+ num_repeat = 0;
424
+ #endif
425
+ e_my_fprintf( log_file, "Fatal Error (No INChI%s%s) %s\n", p1, p2, pStrLogId );
426
+ goto exit_function;
427
+ case inchi_Ret_EOF: /* typically, no input structure provided or help requested */
428
+ /* output previous structure number and message */
429
+ e_my_fprintf( log_file, "End of file detected after structure %d\n", num_inp );
430
+ goto exit_function;
431
+ case inchi_Ret_ERROR:
432
+ num_inp ++;
433
+ num_err ++;
434
+ e_my_fprintf( log_file, "Error (No INChI%s%s) %s\n", p1, p2, pStrLogId );
435
+ #if( defined(EXIT_ON_ERR) && defined(REPEAT_ALL) && REPEAT_ALL > 0 )
436
+ num_repeat = 0;
437
+ goto exit_function;
438
+ #endif
439
+ continue;
440
+ case inchi_Ret_SKIP:
441
+ num_inp ++;
442
+ e_my_fprintf( log_file, "Skipped %s\n", pStrLogId );
443
+ goto exit_function;
444
+ case inchi_Ret_OKAY:
445
+ break;
446
+ case inchi_Ret_WARNING:
447
+ e_my_fprintf( log_file, "Warning (%s) %s\n", p2, pStrLogId );
448
+ break; /* ok */
449
+ }
450
+
451
+ num_inp ++;
452
+ tot_len = 0;
453
+ if ( pOut->szInChI && pOut->szInChI[0] ) {
454
+ if (ip->bINChIOutputOptions & INCHI_OUT_SDFILE_ONLY ) {
455
+ /*****************************/
456
+ /* output SDfile */
457
+ /*****************************/
458
+ char *start;
459
+ unsigned len;
460
+ int bAddLabel = 0;
461
+ /*******************************************************************************/
462
+ /* output a SDfile. pOut->szInChI contains Molfile ending with "$$$$\n" line. */
463
+ /* Replace the 1st line with the structure number */
464
+ /* Replace the last line with the SDfile header, label, and new "$$$$\n" line */
465
+ /*******************************************************************************/
466
+ /* 1. remove the 1st line (later replace it with the actual structure number) */
467
+ if ( start = strchr( pOut->szInChI, '\n' ) ) {
468
+ e_inchi_print( output_file, "Structure #%ld", nStructNo );
469
+ } else {
470
+ start = pOut->szInChI;
471
+ }
472
+ /* 2. SDfile header and data: write zero to the 1st byte of
473
+ * the last line "$$$$\n" to remove this line with purpose to relpace it */
474
+ if ( ip->pSdfLabel && ip->pSdfLabel[0] && ip->pSdfValue && ip->pSdfValue[0] &&
475
+ (len = strlen(start)) && len > 5 && '$' == start[len-5] && '\n' == start[len-6] ) {
476
+ start[len-5] = '\0';
477
+ bAddLabel = 1;
478
+ }
479
+ /* 3. Output the whole Molfile */
480
+ e_inchi_print( output_file, "%s", start );
481
+ if ( bAddLabel ) {
482
+ e_inchi_print( output_file, "> <%s>\n%s\n\n$$$$\n", ip->pSdfLabel, ip->pSdfValue );
483
+ }
484
+
485
+ } else {
486
+ /*****************************/
487
+ /* output InChI */
488
+ /*****************************/
489
+ int bTabbed = 0 != ( ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT );
490
+ int bAuxInfo = !( ip->bINChIOutputOptions & INCHI_OUT_ONLY_AUX_INFO ) &&
491
+ pOut->szAuxInfo && pOut->szAuxInfo[0];
492
+ const char *pLF = "\n";
493
+ const char *pTAB = bTabbed? "\t" : pLF;
494
+ if ( !ip->bNoStructLabels ) {
495
+ /* or print a previously created label string */
496
+ e_inchi_print( output_file, "%s%s", pStrInchiId, pTAB );
497
+ }
498
+ /* output INChI Identifier */
499
+ e_inchi_print( output_file, "%s%s", pOut->szInChI, bAuxInfo? pTAB : pLF );
500
+ /* output INChI Aux Info */
501
+ if ( bAuxInfo ) {
502
+ e_inchi_print( output_file, "%s\n",pOut->szAuxInfo );
503
+ }
504
+ }
505
+ }
506
+ }
507
+
508
+ exit_function:
509
+ //e_my_fprintf( log_file, "\nProcessed %d structure%s, %d error%s.\n",
510
+ //num_inp, (num_inp==1)?"":"s", num_err, (num_err==1)?"":"s" );
511
+
512
+
513
+ e_FreeInchi_Input( pInp );
514
+ FreeINCHI ( pOut );
515
+
516
+ #if( ADD_CMLPP == 1 )
517
+ /* BILLY 8/6/04 */
518
+ /* free CML memory */
519
+ FreeCml ();
520
+ FreeCmlDoc( 1 );
521
+ #endif
522
+
523
+ if ( inp_file && inp_file != stdin) {
524
+ fclose ( inp_file );
525
+ }
526
+ if ( prb_file ) {
527
+ fclose ( prb_file );
528
+ }
529
+ if ( output_file && output_file != stdout ) {
530
+ fclose( output_file );
531
+ }
532
+
533
+ if ( log_file && log_file != stderr ) {
534
+ fclose( log_file );
535
+ }
536
+ for ( i = 0; i < MAX_NUM_PATHS; i ++ ) {
537
+ if ( ip->path[i] ) {
538
+ e_inchi_free( (void*) ip->path[i] ); /* cast deliberately discards 'const' qualifier */
539
+ ip->path[i] = NULL;
540
+ }
541
+ }
542
+
543
+ #if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
544
+ if ( --num_repeat > 0 ) {
545
+ goto repeat;
546
+ }
547
+ #endif
548
+
549
+
550
+ return 0;
551
+ }
552
+
553
+ void Init_ruby_inchi_main()
554
+ {
555
+ cMain = rb_define_class("Main", rb_cObject);
556
+
557
+ rb_define_method(cMain, "run", run, 1);
558
+ }