Branch data Line data Source code
1 : : /*
2 : : * SPDX-License-Identifier: MIT
3 : : * Copyright (c) 2024 IUPAC and InChI Trust
4 : : */
5 : :
6 : : /* InChIKey: calculation of hash for InChI string. Uses truncated SHA-256 function. */
7 : :
8 : : #ifdef _MSC_VER
9 : : #if _MSC_VER > 1000
10 : : #pragma warning( disable : 4996 )
11 : : #endif
12 : : #endif
13 : :
14 : : #include <stdlib.h>
15 : : #include <string.h>
16 : : #include <ctype.h>
17 : :
18 : : #include "sha2.h"
19 : : #include "ikey_base26.h"
20 : :
21 : : #include "mode.h"
22 : : #include "inchi_api.h"
23 : : #include "util.h"
24 : :
25 : : #include "bcf_s.h"
26 : :
27 : : /* Local options */
28 : :
29 : : #define INCHIKEY_DEBUG 0 /* 2 */
30 : :
31 : : #define INCHIKEY_FLAG_OK 0
32 : : #define INCHIKEY_NOT_VALID_FLAG 1
33 : :
34 : : enum { MINOUTLENGTH = 256 };
35 : :
36 : :
37 : :
38 : : /* Local functions */
39 : :
40 : : void fprint_digest( FILE* fw, const char *header, unsigned char *a );
41 : :
42 : :
43 : : /*
44 : : EXPORTED FUNCTIONS
45 : : */
46 : :
47 : :
48 : : /****************************************************************************/
49 : : EXPIMP_TEMPLATE INCHI_API
50 : 0 : int INCHI_DECL GetStdINCHIKeyFromStdINCHI( const char* szINCHISource,
51 : : char* szINCHIKey )
52 : : {
53 [ # # ]: 0 : if (strlen( szINCHISource ) < LEN_INCHI_STRING_PREFIX + 3)
54 : : {
55 : 0 : return INCHIKEY_INVALID_STD_INCHI;
56 : : }
57 [ # # ]: 0 : if (szINCHISource[LEN_INCHI_STRING_PREFIX + 1] != 'S')
58 : : {
59 : 0 : return INCHIKEY_INVALID_STD_INCHI;
60 : : }
61 : :
62 : 0 : return GetINCHIKeyFromINCHI( szINCHISource,
63 : : 0, 0,
64 : : szINCHIKey,
65 : : (char *) NULL, (char *) NULL );
66 : : }
67 : :
68 : :
69 : : /****************************************************************************/
70 : : EXPIMP_TEMPLATE INCHI_API
71 : 0 : int INCHI_DECL GetINCHIKeyFromINCHI( const char* szINCHISource,
72 : : const int xtra1,
73 : : const int xtra2,
74 : : char* szINCHIKey,
75 : : char* szXtra1,
76 : : char* szXtra2 )
77 : : {
78 : 0 : int ret = INCHIKEY_OK;
79 : 0 : int ret1 = INCHIKEY_OK;
80 : : int cn;
81 : 0 : size_t slen, i, j, jproto = 0, ncp, pos_slash1 = 0;
82 : 0 : char *str = NULL, *smajor = NULL, *sminor = NULL,
83 : 0 : *sproto = NULL, *stmp = NULL, tmp[MINOUTLENGTH];
84 : : unsigned char
85 : : digest_major[32], digest_minor[32];
86 : :
87 : 0 : char flagstd = 'S', /* standard key */
88 : 0 : flagnonstd = 'N', /* non-standard key */
89 : 0 : flagexptl = 'B', /* experimental ('beta') key */
90 : 0 : flagver = 'A', /* InChI v. 1 */
91 : 0 : flagproto = 'N'; /* no [de]protonization , by default */
92 : : int nprotons;
93 : : /*
94 : : Protonization encoding:
95 : : N 0
96 : : O +1 P +2 Q +3 R +4 S +5 T +6 U +7 V +8 W +9 X +10 Y +11 Z +12
97 : : M -1 L-2 K -3 J -4 I -5 H -6 G -7 F -8 E -9 D -10 C -11 B -12
98 : : A < -12 or > +12
99 : : */
100 : : static const char *pplus = "OPQRSTUVWXYZ";
101 : : static const char *pminus = "MLKJIHGFEDCB";
102 : 0 : int is_stdinchi = 0; /* 0 - non-standard,
103 : : 1 standard
104 : : -1 experimental ('beta') */
105 : :
106 : :
107 : :
108 [ # # ]: 0 : if (NULL != szXtra1) /* Software version 1.06 added check to fix bug with NULL szXtra, thanks to WDI */
109 : : {
110 : 0 : szXtra1[0] = '\0';
111 : : }
112 [ # # ]: 0 : if (NULL != szXtra2)
113 : : {
114 : 0 : szXtra2[0] = '\0';
115 : : }
116 : :
117 : : /* Check if input is a valid InChI string */
118 : :
119 : : /* .. non-empty */
120 [ # # ]: 0 : if (szINCHISource == NULL)
121 : : {
122 : 0 : return INCHIKEY_EMPTY_INPUT;
123 : : }
124 : :
125 : 0 : slen = strlen( szINCHISource );
126 : :
127 : : /* .. has valid prefix */
128 [ # # ]: 0 : if (slen < LEN_INCHI_STRING_PREFIX + 3)
129 : : {
130 : 0 : return INCHIKEY_INVALID_INCHI_PREFIX;
131 : : }
132 [ # # ]: 0 : if (memcmp( szINCHISource, INCHI_STRING_PREFIX, LEN_INCHI_STRING_PREFIX ))
133 : : {
134 : 0 : return INCHIKEY_INVALID_INCHI_PREFIX;
135 : : }
136 : :
137 : : /* .. has InChI version 1 */
138 : : /* if (!isdigit(szINCHISource[LEN_INCHI_STRING_PREFIX]) ) */
139 [ # # ]: 0 : if (szINCHISource[LEN_INCHI_STRING_PREFIX] != '1')
140 : 0 : return INCHIKEY_INVALID_INCHI_PREFIX;
141 : :
142 : : /* .. optionally has a 'standard' flag character */
143 : 0 : pos_slash1 = LEN_INCHI_STRING_PREFIX + 1;
144 [ # # ]: 0 : if (szINCHISource[pos_slash1] == 'S')
145 : : {
146 : : /* Standard InChI ==> standard InChIKey */
147 : 0 : is_stdinchi = 1;
148 : 0 : pos_slash1++;
149 : : }
150 [ # # ]: 0 : else if (szINCHISource[pos_slash1] == 'B')
151 : : {
152 : : /* v. 1.05 Experimental ('beta') InChI ==> corresponding InChIKey */
153 : 0 : is_stdinchi = -1;
154 : 0 : pos_slash1++;
155 : : }
156 : :
157 : : /* .. has trailing slash in the right place */
158 [ # # ]: 0 : if (szINCHISource[pos_slash1] != '/')
159 : : {
160 : 0 : return INCHIKEY_INVALID_INCHI_PREFIX;
161 : : }
162 : :
163 : : /* .. the rest of source string contains at least one a..Z0.9 or slash */
164 [ # # ]: 0 : if (!isalnum( szINCHISource[pos_slash1 + 1] ))
165 : : {
166 : 0 : int valid_empty_inchi = szINCHISource[pos_slash1 + 1] == '/';
167 : 0 : int allowed_and_valid_err_inchi = 0;
168 [ # # ]: 0 : if (!valid_empty_inchi)
169 : : {
170 : 0 : allowed_and_valid_err_inchi = szINCHISource[pos_slash1 + 1] == '?';
171 [ # # ]: 0 : if (!allowed_and_valid_err_inchi)
172 : : {
173 : 0 : return INCHIKEY_INVALID_INCHI;
174 : : }
175 : : }
176 : : }
177 : :
178 : : /* Ok. Will use a local copy of the source. */
179 : :
180 : 0 : extract_inchi_substring( &str, szINCHISource, slen );
181 [ # # ]: 0 : if (NULL == str)
182 : : {
183 : 0 : ret = INCHIKEY_NOT_ENOUGH_MEMORY;
184 : 0 : goto fin;
185 : : }
186 : 0 : slen = strlen( str );
187 : :
188 : :
189 : : /* Make buffers. */
190 : 0 : smajor = (char*) inchi_calloc( slen + 1, sizeof( char ) );
191 [ # # ]: 0 : if (NULL == smajor)
192 : : {
193 : 0 : ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin;
194 : : }
195 : 0 : sminor = (char*) inchi_calloc( 2 * slen + 2, sizeof( char ) ); /* we may double the length ... */
196 [ # # ]: 0 : if (NULL == sminor)
197 : : {
198 : 0 : ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin;
199 : : }
200 : 0 : stmp = (char*) inchi_calloc( slen + 1, sizeof( char ) );
201 [ # # ]: 0 : if (NULL == stmp)
202 : : {
203 : 0 : ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin;
204 : : }
205 : 0 : sproto = (char*) inchi_calloc( slen + 1, sizeof( char ) );
206 [ # # ]: 0 : if (NULL == sproto)
207 : : {
208 : 0 : ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin;
209 : : }
210 : :
211 : 0 : szINCHIKey[0] = '\0';
212 : :
213 : : /* Extract the major block */
214 : 0 : smajor[0] = '\0';
215 [ # # ]: 0 : for (j = pos_slash1 + 1; j < slen - 1; j++)
216 : : {
217 [ # # ]: 0 : if (str[j] == '/')
218 : : {
219 : 0 : cn = str[j + 1];
220 [ # # # # ]: 0 : switch (cn)
221 : : {
222 : : /* anything allowed from a major part */
223 : 0 : case 'c':
224 : : case 'h':
225 : 0 : case 'q': continue;
226 : :
227 : : /* "/p"; protons now go to to special string, not to minor hash */
228 : 0 : case 'p':
229 : 0 : jproto = j;
230 : 0 : continue;
231 : :
232 : : /* "/f", "/r" : may not occur in stdInChI */
233 : 0 : case 'f':
234 : : case 'r':
235 [ # # ]: 0 : if (is_stdinchi==1)
236 : : {
237 : 0 : ret = INCHIKEY_INVALID_STD_INCHI;
238 : 0 : goto fin;
239 : : }
240 : 0 : break;
241 : :
242 : : /* anything allowed from a minor part */
243 : 0 : default:
244 : 0 : break;
245 : : }
246 : 0 : break;
247 : : }
248 : : }
249 : 0 : j++;
250 [ # # ]: 0 : if (j == slen)
251 : : {
252 : 0 : j++;
253 : : }
254 : : else
255 : : {
256 : 0 : j--;
257 : : }
258 : :
259 [ # # ]: 0 : if (jproto)
260 : : {
261 : 0 : ncp = jproto - pos_slash1 - 1;
262 : : }
263 : : else
264 : : {
265 : 0 : ncp = j - pos_slash1 - 1;
266 : : }
267 : :
268 : :
269 : : /* Trim 'InChI=1[S]/' */
270 : 0 : memcpy(smajor, str + pos_slash1 + 1, ncp * sizeof(str[0]));
271 : 0 : smajor[ncp] = '\0';
272 : :
273 : :
274 : : /* Treat protonization */
275 [ # # ]: 0 : if (jproto)
276 : : {
277 : : /* 2009-01-07 fix bug/typo: assigned incorrect length to the protonation segment of
278 : : source string ( was sproto[ncp]='\0'; should be sproto[lenproto]='\0'; ) */
279 : 0 : int lenproto = j - (int) jproto;
280 [ # # ]: 0 : if (lenproto < 3)
281 : : {
282 : : /* empty "/p", should not occur */
283 : 0 : ret = INCHIKEY_INVALID_INCHI;
284 : 0 : goto fin;
285 : : }
286 : :
287 : 0 : memcpy(sproto, str + pos_slash1 + ncp + 1, lenproto * sizeof(str[0]));
288 : 0 : sproto[lenproto] = '\0';
289 : :
290 : 0 : nprotons = strtol( sproto + 2, NULL, 10 );
291 : :
292 [ # # ]: 0 : if (nprotons > 0)
293 : : {
294 [ # # ]: 0 : if (nprotons > 12)
295 : : {
296 : 0 : flagproto = 'A';
297 : : }
298 : : else
299 : : {
300 : 0 : flagproto = pplus[nprotons - 1];
301 : : }
302 : : }
303 [ # # ]: 0 : else if (nprotons < 0)
304 : : {
305 [ # # ]: 0 : if (nprotons < -12)
306 : : {
307 : 0 : flagproto = 'A';
308 : : }
309 : : else
310 : : {
311 : 0 : flagproto = pminus[-nprotons - 1];
312 : : }
313 : : }
314 : : else
315 : : {
316 : : /* should never occur */
317 : 0 : ret = INCHIKEY_INVALID_STD_INCHI;
318 : 0 : goto fin;
319 : : }
320 : : }
321 : :
322 : : /* Extract the minor block. */
323 : :
324 [ # # ]: 0 : if (j != slen + 1) /* check that something exists at right.*/
325 : : {
326 : 0 : ncp = slen - j;
327 : 0 : memcpy(sminor, str + j, (ncp) * sizeof(str[0]));
328 : 0 : sminor[ncp] = '\0';
329 : : }
330 : : else
331 : : {
332 : 0 : sminor[0] = '\0';
333 : : }
334 : :
335 : :
336 : : #if INCHIKEY_DEBUG
337 : : ITRACE_( "Source: {%-s}\n", str );
338 : : ITRACE_( "SMajor: {%-s}\n", smajor );
339 : : ITRACE_( "SMinor: {%-s}\n", sminor );
340 : : ITRACE_( "SProto: {%-s}\n", sproto );
341 : : #endif
342 : :
343 : : /* Compute and compose the InChIKey string. */
344 : :
345 : : /* Major hash sub-string. */
346 [ # # ]: 0 : for (i = 0; i < 32; i++)
347 : : {
348 : 0 : digest_major[i] = 0;
349 : : }
350 : :
351 : 0 : sha2_csum( (unsigned char *) smajor, (int) strlen( smajor ), digest_major );
352 : :
353 : 0 : sprintf(tmp, "%-.3s%-.3s%-.3s%-.3s%-.2s",
354 : : base26_triplet_1(digest_major), base26_triplet_2(digest_major),
355 : : base26_triplet_3(digest_major), base26_triplet_4(digest_major),
356 : : base26_dublet_for_bits_56_to_64(digest_major));
357 : 0 : strcat(szINCHIKey, tmp);
358 : : #if (INCHIKEY_DEBUG>1)
359 : : fprint_digest( stderr, "Major hash, full SHA-256", digest_major );
360 : : #endif
361 : :
362 : :
363 : : /* Minor hash sub-string. */
364 [ # # ]: 0 : for (i = 0; i < 32; i++)
365 : : {
366 : 0 : digest_minor[i] = 0;
367 : : }
368 : 0 : slen = strlen( sminor );
369 [ # # # # ]: 0 : if (( slen > 0 ) && ( slen < 255 ))
370 : : {
371 : 0 : strcpy(stmp, sminor);
372 : 0 : strcpy(sminor + slen, stmp);
373 : : }
374 : :
375 : 0 : sha2_csum( (unsigned char *) sminor, (int) strlen( sminor ), digest_minor );
376 : :
377 : : #if (INCHIKEY_DEBUG>1)
378 : : fprint_digest( stderr, "Minor hash, full SHA-256", digest_minor );
379 : : #endif
380 : :
381 : 0 : strcat(szINCHIKey, "-");
382 : 0 : sprintf(tmp, "%-.3s%-.3s%-.2s",
383 : : base26_triplet_1(digest_minor),
384 : : base26_triplet_2(digest_minor),
385 : : base26_dublet_for_bits_28_to_36(digest_minor));
386 : 0 : strcat(szINCHIKey, tmp);
387 : : /* Append a standard/non-standard flag */
388 : 0 : slen = strlen( szINCHIKey );
389 [ # # ]: 0 : if (is_stdinchi == 1)
390 : : {
391 : 0 : szINCHIKey[slen] = flagstd;
392 : : }
393 [ # # ]: 0 : else if (is_stdinchi == -1)
394 : : {
395 : 0 : szINCHIKey[slen] = flagexptl;
396 : : }
397 : : else
398 : : {
399 : 0 : szINCHIKey[slen] = flagnonstd;
400 : : }
401 : :
402 : : /* Append InChI v.1 flag */
403 : 0 : szINCHIKey[slen + 1] = flagver;
404 : :
405 : : /* Append dash */
406 : 0 : szINCHIKey[slen + 2] = '-';
407 : :
408 : : /* Append protonization flag */
409 : 0 : szINCHIKey[slen + 3] = flagproto;
410 : 0 : szINCHIKey[slen + 4] = '\0';
411 : :
412 : :
413 : : #if INCHIKEY_DEBUG
414 : : ITRACE_( "szINCHIKey: {%-s}\n", szINCHIKey );
415 : : #endif
416 : :
417 : : /* Hash extensions */
418 [ # # # # ]: 0 : if (xtra1 && szXtra1)
419 : : {
420 : 0 : get_xtra_hash_major_hex( digest_major, szXtra1 );
421 : : #if INCHIKEY_DEBUG
422 : : fprintf( stderr, "XHash1=%-s\n", szXtra1 );
423 : : fprintf( stderr, "j=%-d\n", j );
424 : : #endif
425 : : }
426 [ # # # # ]: 0 : if (xtra2 && szXtra2)
427 : : {
428 : 0 : get_xtra_hash_minor_hex( digest_minor, szXtra2 );
429 : : #if INCHIKEY_DEBUG
430 : : fprintf( stderr, "XHash2=%-s\n", szXtra2 );
431 : : fprintf( stderr, "j=%-d\n", j );
432 : : #endif
433 : : }
434 : :
435 : :
436 : 0 : fin:
437 : : /* djb-rwth: fixing GH issue #87 (thanks to Ricardo Rodriguez) and oss-fuzz issue #66746 */
438 [ # # ]: 0 : if (NULL != str)
439 : : {
440 [ # # ]: 0 : inchi_free( str );
441 : : }
442 [ # # ]: 0 : if (NULL != smajor)
443 : : {
444 [ # # ]: 0 : inchi_free( smajor );
445 : : }
446 [ # # ]: 0 : if (NULL != sminor)
447 : : {
448 [ # # ]: 0 : inchi_free( sminor );
449 : 0 : sminor = NULL;
450 : : }
451 [ # # ]: 0 : if (NULL != stmp)
452 : : {
453 [ # # ]: 0 : inchi_free( stmp );
454 : : }
455 [ # # ]: 0 : if (NULL != sproto)
456 : : {
457 [ # # ]: 0 : inchi_free( sproto );
458 : : }
459 [ # # # # ]: 0 : if (( ret == INCHIKEY_OK ) && ( ret1 != INCHIKEY_OK ))
460 : : {
461 : 0 : ret = ret1;
462 : : }
463 : :
464 : 0 : return ret;
465 : : }
466 : :
467 : :
468 : : /****************************************************************************
469 : : Check if the string represents valid InChIKey.
470 : : ****************************************************************************/
471 : 0 : EXPIMP_TEMPLATE INCHI_API int INCHI_DECL CheckINCHIKey( const char *szINCHIKey )
472 : : {
473 : : size_t slen, j;
474 : :
475 : :
476 : 0 : slen = strlen( szINCHIKey );
477 : :
478 : :
479 : : /* Proper length is 27 */
480 [ # # ]: 0 : if (slen != 27)
481 : : {
482 : 0 : return INCHIKEY_INVALID_LENGTH;
483 : : }
484 : :
485 : : /* Should have dash in 14-th position */
486 [ # # ]: 0 : if (szINCHIKey[14] != '-')
487 : : {
488 : 0 : return INCHIKEY_INVALID_LAYOUT;
489 : : }
490 : : /* Should have dash in 25-th position */
491 [ # # ]: 0 : if (szINCHIKey[25] != '-')
492 : : {
493 : 0 : return INCHIKEY_INVALID_LAYOUT;
494 : : }
495 : :
496 : : /* All other should be uppercase */
497 [ # # ]: 0 : for (j = 0; j < 14; j++)
498 : : {
499 [ # # # # ]: 0 : if (!isbase26( szINCHIKey[j] ))
500 : : {
501 : 0 : return INCHIKEY_INVALID_LAYOUT; /* first block */
502 : : }
503 : : }
504 [ # # ]: 0 : for (j = 15; j < 25; j++)
505 : : {
506 [ # # # # ]: 0 : if (!isbase26( szINCHIKey[j] ))
507 : : {
508 : 0 : return INCHIKEY_INVALID_LAYOUT; /* second block */
509 : : }
510 : : }
511 : :
512 [ # # # # ]: 0 : if (!isbase26( szINCHIKey[26] ))
513 : : {
514 : 0 : return INCHIKEY_INVALID_LAYOUT; /* (de)protonation flag */
515 : : }
516 : :
517 : :
518 : : /* No 'E' may appear in 0,3,6,and 9 positions of the 1st block ... */
519 [ # # ]: 0 : for (j = 0; j < 10; j += 3)
520 : : {
521 [ # # ]: 0 : if (szINCHIKey[j] == 'E')
522 : : {
523 : 0 : return INCHIKEY_INVALID_LAYOUT;
524 : : }
525 : : }
526 : : /* ... and 0 and 3 pos. of the second block. */
527 [ # # ]: 0 : for (j = 15; j < 19; j += 3)
528 : : {
529 [ # # ]: 0 : if (szINCHIKey[j] == 'E')
530 : : {
531 : 0 : return INCHIKEY_INVALID_LAYOUT;
532 : : }
533 : : }
534 : :
535 : : /* Check for version (only 1 allowed) */
536 [ # # ]: 0 : if (szINCHIKey[24] != 'A')
537 : : {
538 : 0 : return INCHIKEY_INVALID_VERSION;
539 : : }
540 : :
541 : : /* Check for standard-ness */
542 [ # # ]: 0 : if (szINCHIKey[23] == 'S')
543 : : {
544 : 0 : return INCHIKEY_VALID_STANDARD;
545 : : }
546 [ # # ]: 0 : else if (szINCHIKey[23] == 'N')
547 : : {
548 : 0 : return INCHIKEY_VALID_NON_STANDARD;
549 : : }
550 : : else
551 : : {
552 : 0 : return INCHIKEY_INVALID_LAYOUT;
553 : : }
554 : :
555 : : }
556 : :
557 : :
558 : : /****************************************************************************/
559 : 0 : void fprint_digest( FILE* fw, const char *header, unsigned char *a )
560 : : {
561 : 0 : size_t i, bytelen = 32;
562 : 0 : fprintf( fw, "%s\n", header );
563 [ # # ]: 0 : for (i = 0; i < bytelen; i++)
564 : : {
565 : 0 : fprintf( fw, "%02x ", a[i] );
566 : : }
567 : 0 : fprintf( fw, "\n" );
568 : 0 : }
569 : :
570 : :
571 : : /****************************************************************************/
572 : :
573 : : #if ( defined( _WIN32 ) && defined( _MSC_VER ) && _MSC_VER >= 800 && defined(_USRDLL) && defined(BUILD_LINK_AS_DLL) )
574 : : /* Win32 & MS VC ++, compile and link as a DLL */
575 : : /*********************************************************/
576 : : /* C calling conventions export from Win32 dll */
577 : : /*********************************************************/
578 : : /* prototypes */
579 : : #ifndef COMPILE_ALL_CPP
580 : : #ifdef __cplusplus
581 : : extern "C" {
582 : : #endif
583 : : #endif
584 : :
585 : : int cdecl_CheckINCHIKey( const char *szINCHIKey );
586 : : int cdecl_GetINCHIKeyFromINCHI( const char* szINCHISource,
587 : : const int xtra1, const int xtra2,
588 : : char* szINCHIKey, char* szXtra1, char* szXtra2 );
589 : : int cdecl_GetStdINCHIKeyFromStdINCHI( const char* szINCHISource, char* szINCHIKey );
590 : :
591 : : #ifndef COMPILE_ALL_CPP
592 : : #ifdef __cplusplus
593 : : }
594 : : #endif
595 : : #endif
596 : :
597 : : /* implementation */
598 : : /* libinchi.def provides export without cdecl_ prefixes */
599 : :
600 : : /****************************************************************************/
601 : : int cdecl_GetStdINCHIKeyFromStdINCHI( const char* szINCHISource, char* szINCHIKey )
602 : : {
603 : : return GetStdINCHIKeyFromStdINCHI( szINCHISource, szINCHIKey );
604 : : }
605 : :
606 : :
607 : : /****************************************************************************/
608 : : int cdecl_CheckINCHIKey( const char *szINCHIKey )
609 : : {
610 : : return CheckINCHIKey( szINCHIKey );
611 : : }
612 : :
613 : :
614 : : /****************************************************************************/
615 : : int cdecl_GetINCHIKeyFromINCHI( const char* szINCHISource,
616 : : const int xtra1, const int xtra2,
617 : : char* szINCHIKey, char* szXtra1, char* szXtra2 )
618 : : {
619 : : return GetINCHIKeyFromINCHI( szINCHISource, xtra1, xtra2, szINCHIKey, szXtra1, szXtra2 );
620 : : }
621 : : #endif
622 : :
623 : :
624 : :
625 : : #if ( defined(__GNUC__) && __GNUC__ >= 3 && defined(__MINGW32__) && defined(_WIN32) )
626 : : #include <windows.h>
627 : :
628 : :
629 : : /****************************************************************************
630 : : Pacal calling conventions export from Win32 dll
631 : : ****************************************************************************/
632 : : #ifndef COMPILE_ALL_CPP
633 : : #ifdef __cplusplus
634 : : extern "C" {
635 : : #endif
636 : : #endif
637 : : /* prototypes */
638 : : int PASCAL pasc_CheckINCHIKey( const char *szINCHIKey );
639 : : #ifndef COMPILE_ALL_CPP
640 : : #ifdef __cplusplus
641 : : }
642 : : #endif
643 : : #endif
644 : :
645 : : /* implementation */
646 : : /* libinchi.def provides export without PASCAL pasc_ prefixes */
647 : :
648 : : /****************************************************************************/
649 : : int PASCAL pasc_CheckINCHIKey( const char *szINCHIKey )
650 : : {
651 : : return CheckINCHIKey( szINCHIKey );
652 : : }
653 : :
654 : : #endif
|