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