Esempio n. 1
0
QUEUE *QueueDelete( QUEUE *q )
{
    if ( q ) {
        if ( q->Val ) inchi_free(q->Val);
        inchi_free( q );
    }
    return NULL;
}
Esempio n. 2
0
void FreeNeighList( NEIGH_LIST *pp )
{
    if ( pp ) {
        if ( pp[0] ) {
            inchi_free( pp[0] );
        }
        inchi_free( pp );
    }
}
Esempio n. 3
0
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_STRING,
        flush INCHI_IOSTREAM string buffer to file (if non-NULL) and
        another file f2 supplied as parameter (typically, it will be stderr); then free buffer.
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_FILE, just flush the both files.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
void inchi_ios_flush2(INCHI_IOSTREAM* ios, FILE *f2)
{
    if (ios->type == INCHI_IOSTREAM_STRING) 
    {
        if (ios->s.pStr)
        {
            if (ios->s.nUsedLength > 0)
            {       
                if (ios->f)
                {
                    fprintf(ios->f,"%-s", ios->s.pStr); 
                    fflush(ios->f);
                }
                if (f2!=ios->f)
                    fprintf(f2,"%-s", ios->s.pStr); 
                
                inchi_free(ios->s.pStr );
                ios->s.pStr = NULL; 
                ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
            }       
        }
    }
    else if (ios->type == INCHI_IOSTREAM_FILE)
    {
        /* output to plain file: just flush it. */
        if ( (ios->f) && (ios->f!=stderr) && (ios->f!=stdout) )
            fflush(ios->f);
        if ( f2 && f2!=stderr && f2!=stdout)
            fflush(f2);


    }

    return;
}
Esempio n. 4
0
void CurTreeFree( CUR_TREE *cur_tree )
{
    if ( cur_tree ) {
        inchi_free( cur_tree->tree );
        memset( cur_tree, 0, sizeof(*cur_tree) );
    }
}
Esempio n. 5
0
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_STRING,
        flush INCHI_IOSTREAM string buffer to file (if non-NULL); then free buffer.
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_FILE, just flush the file.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
void inchi_ios_flush(INCHI_IOSTREAM* ios)
{
    if (ios->type == INCHI_IOSTREAM_STRING) 
    {
        if (ios->s.pStr)
        {
            if (ios->s.nUsedLength > 0)
            {       
                if (ios->f)
                {
                    fprintf(ios->f,"%-s", ios->s.pStr); 
                    fflush(ios->f);
                }
                inchi_free(ios->s.pStr );
                ios->s.pStr = NULL; 
                ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
            }       
        }
    }
    else if (ios->type == INCHI_IOSTREAM_FILE)
    {
        /* output to plain file: just flush it. */
        fflush(ios->f);
    }
    return;
}
Esempio n. 6
0
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Close INCHI_IOSTREAM: free string buffer and close the file.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
void inchi_ios_close(INCHI_IOSTREAM* ios)
{
    if (ios->s.pStr)
        inchi_free(ios->s.pStr);
    ios->s.pStr = NULL; 
    ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
    if ( (ios->f) && (ios->f!=stderr) && (ios->f!=stdout) && (ios->f!=stdin))
        fclose(ios->f);
    return;
}
Esempio n. 7
0
/*    Reset INCHI_IOSTREAM: set string buffer ptr to NULL
    (after freeing memory) but do not close associated file. */
void inchi_ios_free_str(INCHI_IOSTREAM *ios)
{
    if ( NULL==ios )
        return;
    if ( ios->s.pStr && ios->s.nAllocatedLength)
        inchi_free(ios->s.pStr);
    ios->s.pStr = NULL;
    ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;

    return;
}
Esempio n. 8
0
QUEUE *QueueCreate( int nTotLength, int nSize )
{
    QUEUE     *q   = NULL;
    QINT_TYPE *Val = NULL;
    if ( nTotLength < 1 || nSize != (int)sizeof(QINT_TYPE) ||
         !(q   = (QUEUE     *) inchi_calloc( 1, sizeof(QUEUE)) ) ||
         !(Val = (QINT_TYPE *) inchi_calloc( nTotLength, nSize) )) {
        if ( q ) inchi_free(q);
        return NULL;
    }
    q->Val        = Val;
    /* q->nSize      = nSize; */
    q->nTotLength = nTotLength;
    return q;
}
Esempio n. 9
0
int CurTreeReAlloc( CUR_TREE *cur_tree )
{
    if ( cur_tree ) {
        if ( cur_tree->tree && cur_tree->max_len > 0 && cur_tree->incr_len > 0 ) {
            void *p = cur_tree->tree;
            if ( cur_tree->tree = (AT_NUMB *)inchi_calloc( cur_tree->max_len + cur_tree->incr_len, sizeof(cur_tree->tree[0]) ) ) {
                memcpy( cur_tree->tree, p, cur_tree->cur_len * sizeof(cur_tree->tree[0]) );
                inchi_free( p );
                cur_tree->max_len += cur_tree->incr_len;
                return 0; /*  ok */
            }
        }
    }
    return -1; /*  error */ /*   <BRKPT> */
}
Esempio n. 10
0
/*    Close INCHI_IOSTREAM: free string buffer and close associated file. */
void inchi_ios_close(INCHI_IOSTREAM* ios)
{
    if ( NULL==ios )
        return;
    if (ios->s.pStr)
    {
        inchi_free(ios->s.pStr);
    }
    ios->s.pStr = NULL;
    ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;

    if ( NULL!=ios->f && stdout!=ios->f && stderr!=ios->f && stdin!=ios->f )
            fclose(ios->f);

    return;
}
Esempio n. 11
0
/*    This function's flushes previously hidden output and resets string stream
    returns n chars on success, otherwise -1
*/
int inchi_ios_flush_not_displayed( INCHI_IOSTREAM * ios )
{
char *obuf = NULL;
int ret;

    if ( !ios )        return -1;

    obuf = (char *) inchi_calloc( ios->s.nUsedLength + 1, sizeof(char) );

    if ( !obuf )    return -1;

    strcpy( obuf, ios->s.pStr);
    ios->s.nUsedLength = 0;
    ret = inchi_ios_print( ios, "%s", obuf );
    inchi_free( obuf );

    return ret;
}
Esempio n. 12
0
int CurTreeAlloc( CUR_TREE *cur_tree, int num_atoms )
{
    if ( cur_tree ) {
        if ( cur_tree->tree && cur_tree->max_len > 0 && !(cur_tree->max_len % num_atoms) ) {
            /*  do not reallocate */
            cur_tree->cur_len = 0;
            cur_tree->incr_len = num_atoms;
            memset( cur_tree->tree, 0, cur_tree->max_len * sizeof(cur_tree->tree[0]) );
            return 0; /*  ok */
        }
        inchi_free( cur_tree->tree );
        memset( cur_tree, 0, sizeof(*cur_tree) );
        if ( cur_tree->tree = (AT_NUMB *)inchi_calloc( num_atoms, sizeof(cur_tree->tree[0]) ) ) {
            cur_tree->incr_len =
            cur_tree->max_len  = num_atoms;
            return 0; /*  ok */
        }
    }
    return -1; /*  error */ /*   <BRKPT> */
}
Esempio n. 13
0
/*    Make a copy of INCHI_IOSTREAM    */
int inchi_ios_create_copy(INCHI_IOSTREAM* ios, INCHI_IOSTREAM* ios0)
{
    if ( ios )
        memset( ios, 0, sizeof(*ios) );
    ios->type = ios0->type;
    if ( ios->type == INCHI_IOSTREAM_TYPE_STRING )
    {
        if ( ios->s.pStr )
            inchi_free( ios->s.pStr );
        ios->s.pStr = (char *) inchi_calloc( ios0->s.nAllocatedLength, sizeof(char) );
        if ( ios->s.pStr )
        {
            ios->s.nUsedLength = ios0->s.nUsedLength;
            ios->s.nPtr = ios0->s.nPtr;
        }
        else
            return -1; /* no memory */
    }
    ios->f = ios0->f;
    return 0;
}
Esempio n. 14
0
/****************************************************************************************
 *
 * In this neighbor list the (vertex number) = (canonical number) - 1
 * Since LinearCT is sorted so that parents are in ascending order
 * and all neighbors of a parent are smaller than the parent and are
 * in ascending order, the neighbors in the NEIGH_LIST are automatically
 * sorted in ascending order
 */
NEIGH_LIST *CreateNeighListFromLinearCT( AT_NUMB *LinearCT, int nLenCT, int num_atoms )
{
    /* atom numbers in LinearCT are canonical numbers
     * order: parent[i] > neigh[i][0] < neigh[i][1]...<neigh[i][n] < parent[i+1] > neigh[i+1][0] < ...
     *        parent[i] < parent[i+1]
     */
    int i, j;
    S_CHAR     *valence  = NULL;
    NEIGH_LIST *pp = NULL;
    AT_NUMB    *pAtList = NULL;
    AT_RANK     n_vertex, n_neigh;
    int err = 1, num_bonds;
    int length, start;
    if ( (int)LinearCT[0] > num_atoms ) {
        goto exit_function;
    }
    if ( !(valence = (S_CHAR*)inchi_calloc( num_atoms+1, sizeof(valence[0]) ) ) ) {
        goto exit_function;
    }
    for ( i = 1, num_bonds = 0, n_vertex = LinearCT[0]; i < nLenCT; i ++ ) {
        if ( (n_neigh = LinearCT[i]) < n_vertex ) {
            valence[n_neigh] ++;
            valence[n_vertex] ++;
            num_bonds += 2;
        } else
        if ( (int)(n_vertex = n_neigh) > num_atoms ) {
            goto exit_function;
        }
    }
    if ( (int)n_vertex != num_atoms ) {
        goto exit_function;
    }
    length = num_bonds + num_atoms + 1;
    if ( pp = (NEIGH_LIST *) inchi_calloc((num_atoms+1), sizeof(NEIGH_LIST)) ) {
        if ( pAtList = (AT_NUMB *) inchi_malloc( length*sizeof(*pAtList) ) ) {
            /*  create empty connection table */
            for ( i = 1, length = 0; i <= num_atoms; i ++ ) {
                start = length;
                length += (valence[i]+1);
                pp[i-1] = pAtList + start;
                pp[i-1][0] = 0;
            }
            /*  fill out the CT */
            for ( i = 1, n_vertex = LinearCT[0]-1; i < nLenCT; i ++ ) {
                if ( (n_neigh = LinearCT[i]-1) < n_vertex ) {
                    /*  vertex - neighbor connection */
                    j = (int)(++pp[(int)n_vertex][0]);
                    pp[(int)n_vertex][j] = n_neigh;
                    /*  neighbor - vertex connection */
                    j = (int)(++pp[(int)n_neigh][0]);
                    pp[(int)n_neigh][j] = n_vertex;

                } else
                if ( (int)(n_vertex = n_neigh) >= num_atoms ) {
                    goto exit_function;
                }
            }
            err = 0;
        }
    }
exit_function:
    if ( valence ) {
        inchi_free( valence );
    }
    if ( err ) {
        if ( pAtList )
            inchi_free( pAtList );
        if ( pp ) {
            inchi_free( pp );
            pp = NULL;
        }
    }
    return pp;
}
Esempio n. 15
0
EXPIMP_TEMPLATE INCHI_API int INCHI_DECL GetINCHIKeyFromINCHI(const char* szINCHISource, 
                                                              const int xtra1,
                                                              const int xtra2,
                                                              char* szINCHIKey,
                                                              char* szXtra1,
                                                              char* szXtra2)
{
int ret = INCHIKEY_OK;
int ret1 = INCHIKEY_OK;
int cn;
size_t slen, i, j, jproto=0, ncp, pos_slash1=0;
char *str = NULL, *smajor = NULL, *sminor = NULL, 
     *sproto=NULL,
     *stmp = NULL, tmp[MINOUTLENGTH]; 
unsigned char 
    digest_major[32], digest_minor[32];     

char flagstd = 'S', /* standard key */
     flagnonstd = 'N', /* non-standard key */
     flagver = 'A', /* InChI v. 1 */
     flagproto = 'N'; /* no [de]protonization , by default */
int  nprotons;
/*
Protonization encoding:
N 0
O +1 P +2 Q +3 R +4 S +5 T +6 U +7 V +8 W +9 X +10 Y +11 Z +12
M -1 L-2 K -3 J -4 I -5 H -6 G -7 F -8 E -9 D -10 C -11 B -12 
A < -12 or > +12
*/
static const char *pplus = "OPQRSTUVWXYZ";
static const char *pminus = "MLKJIHGFEDCB";

int bStdFormat = 0;
size_t bytelen = 32;


    /* Check if input is a valid InChI string */

    /* .. non-empty */
    if (szINCHISource==NULL)
        return INCHIKEY_EMPTY_INPUT;
    
    slen = strlen(szINCHISource);
    
    /* .. has valid prefix */
    if (slen<LEN_INCHI_STRING_PREFIX+3)                         
        return INCHIKEY_INVALID_INCHI_PREFIX;    
    if (memcmp(szINCHISource,INCHI_STRING_PREFIX,LEN_INCHI_STRING_PREFIX))    
        return INCHIKEY_INVALID_INCHI_PREFIX;

    /* .. has InChI version 1 */
    /* if (!isdigit(szINCHISource[LEN_INCHI_STRING_PREFIX]) )  */
    if ( szINCHISource[LEN_INCHI_STRING_PREFIX] != '1' )  
        return INCHIKEY_INVALID_INCHI_PREFIX;

    /* .. optionally has a 'standard' flag character */
    pos_slash1 = LEN_INCHI_STRING_PREFIX+1;
    if (szINCHISource[pos_slash1]=='S')            
    {
        /* Standard InChI ==> standard InChIKey */
        bStdFormat = 1;
        pos_slash1++;
    }

    /* .. has trailing slash in the right place */
    if (szINCHISource[pos_slash1]!='/')            
        return INCHIKEY_INVALID_INCHI_PREFIX;

    /* .. the rest of source string contains at least one a..Z0.9 or slash */
    /* TODO: improve/add full string check */
    if (!isalnum(szINCHISource[pos_slash1+1] ) &&
       ( szINCHISource[pos_slash1+1]!='/' )     ) 
        return INCHIKEY_INVALID_INCHI;    


    /*^^^ Ok. Will use a local copy of the source. */
    
    extract_inchi_substring(&str, szINCHISource, slen);
    if (NULL==str)
    { 
        ret = INCHIKEY_NOT_ENOUGH_MEMORY; 
        goto fin; 
    }
    slen = strlen(str);


    /*^^^ Make buffers. */
    smajor = (char*) inchi_calloc( slen+1, sizeof(char)); 
    if (NULL==smajor)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }
    sminor = (char*) inchi_calloc( 2*slen + 2, sizeof(char)); /* we may double the length ... */ 
    if (NULL==sminor)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }
    stmp = (char*) inchi_calloc( slen+1, sizeof(char)); 
    if (NULL==stmp)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }
    sproto = (char*) inchi_calloc( slen+1, sizeof(char)); 
    if (NULL==sproto)
        { ret = INCHIKEY_NOT_ENOUGH_MEMORY; goto fin; }


    szINCHIKey[0] = '\0';

    
    
    /*^^^ Extract the major block. */
    
    smajor[0]  = '\0';
    for (j = pos_slash1 + 1; j < slen-1; j++)
    {
        if (str[j]=='/')    
        {
            cn = str[j+1];
            switch (cn) 
            { 
                /* anything allowed from a major part */
                case 'c': case 'h': case 'q':   continue; 
                
                /* "/p"; protons now go to to special string, not to minor hash */
                case 'p':						jproto = j;
                                                continue;
                
                /* "/f",  "/r" : may not occur in stdInChI */
                case 'f': case 'r':		        if ( bStdFormat )
                                                {
                                                    ret = INCHIKEY_INVALID_STD_INCHI; 
                                                    goto fin;
                                                }
                                                break;
                
                /* anything allowed from a minor part */
                default:                        break; 
            }
            break;
        }
    }       
    j++;
    if (j==slen) 
        j++;
    else 
        j--;

    ncp=0;

    if (jproto)
        ncp = jproto - pos_slash1 - 1; 
    else
        ncp = j - pos_slash1 - 1; 
    

    /*^^^ Trim 'InChI=1[S]/' */
    memcpy(smajor,str+pos_slash1+1, ncp*sizeof(str[0]));
    smajor[ncp]='\0';


    /* Treat protonization */
    if (jproto)
    {
        /* 2009-01-07 fix bug/typo: assigned incorrect length to the protonation segment of 
        /* source string ( was sproto[ncp]='\0'; should be sproto[lenproto]='\0'; )  */
        int lenproto = j - jproto;
        if (lenproto<3)
        {	
            /* empty "/p", should not occur */
            ret = INCHIKEY_INVALID_INCHI; 
            goto fin;
        }
        
        memcpy(sproto,str+pos_slash1+ncp+1, lenproto*sizeof(str[0]));
        sproto[lenproto]='\0';
       
        nprotons = strtol( sproto+2, NULL, 10 );        
        
        if (nprotons > 0)
        {
            if (nprotons > 12) flagproto = 'A';
            else			   flagproto = pplus[nprotons-1];
        }
        else if (nprotons < 0)
        {
            if (nprotons < -12) flagproto = 'A';
            else				flagproto = pminus[-nprotons-1];
        }
        else
        {
            /* should never occur */
            ret = INCHIKEY_INVALID_STD_INCHI; 
            goto fin;
        }
    }



    /*^^^ Extract the minor block. */

    if (j != slen+1)    /*^^^ check that something exists at right.*/
    {
        ncp = slen-j; 
        memcpy(sminor,str+j, (ncp)*sizeof(str[0]));
        sminor[ncp]='\0';
    }
    else 
        sminor[0]='\0'; 
        

#if INCHIKEY_DEBUG 
    fprintf(stdout,"Source:  {%-s}\n",str);
    fprintf(stdout,"SMajor:  {%-s}\n",smajor);
    fprintf(stdout,"SMinor:  {%-s}\n",sminor);
    fprintf(stdout,"SProto:  {%-s}\n",sproto);
#endif      



    /*^^^ Compute and compose the InChIKey string. */


    /*^^^ Major hash sub-string. */    
    for( i = 0; i < 32; i++ ) 
        digest_major[i] = 0;            
    sha2_csum( (unsigned char *) smajor, (int) strlen(smajor), digest_major );    

    /* !!! */
    strcpy(tmp, base26_triplet_1(digest_major));
    strcpy(tmp, base26_triplet_2(digest_major));
    strcpy(tmp, base26_triplet_3(digest_major) );
    strcpy(tmp, base26_triplet_4(digest_major) );
    strcpy(tmp, base26_dublet_for_bits_56_to_64(digest_major));

    sprintf(tmp,"%-.3s%-.3s%-.3s%-.3s%-.2s", 
                base26_triplet_1(digest_major), base26_triplet_2(digest_major),
                base26_triplet_3(digest_major), base26_triplet_4(digest_major),
                base26_dublet_for_bits_56_to_64(digest_major));
    strcat(szINCHIKey, tmp);    
#if (INCHIKEY_DEBUG>1)
        fprint_digest(stderr, "Major hash, full SHA-256",digest_major);         
#endif  



    /*^^^ Minor hash sub-string. */
    for( i = 0; i < 32; i++ ) 
        digest_minor[i] = 0; 
    slen = strlen(sminor); 
    if ((slen>0)&&(slen<255)) 
    { 
        strcpy(stmp, sminor); 
        strcpy(sminor+slen,stmp); 
    }
    sha2_csum( (unsigned char *) sminor, (int) strlen(sminor), digest_minor );
#if (INCHIKEY_DEBUG>1)  
        fprint_digest(stderr, "Minor hash, full SHA-256",digest_minor);
#endif

    strcat(szINCHIKey, "-");
    sprintf(tmp,"%-.3s%-.3s%-.2s", 
        base26_triplet_1(digest_minor), 
        base26_triplet_2(digest_minor), 
        base26_dublet_for_bits_28_to_36(digest_minor));  
    strcat(szINCHIKey, tmp); 


    /* Append a standard/non-standard flag */
    slen = strlen(szINCHIKey);
    if ( bStdFormat )
        szINCHIKey[slen] = flagstd; 
    else
        szINCHIKey[slen] = flagnonstd; 

    /*^^^ Append InChI v.1 flag */
    szINCHIKey[slen+1] = flagver; 
    
    /*^^^ Append dash  */
    szINCHIKey[slen+2] = '-'; 
    
    /*^^^ Append protonization flag */
    szINCHIKey[slen+3] = flagproto; 
    szINCHIKey[slen+4] = '\0';


#if INCHIKEY_DEBUG 
    fprintf(stdout,"szINCHIKey:  {%-s}\n",szINCHIKey);
#endif

    /* Hash extensions */
    if ( xtra1 && szXtra1 )
    {
        get_xtra_hash_major_hex(digest_major, szXtra1);
#if INCHIKEY_DEBUG 
        fprintf(stderr,"XHash1=%-s\n",szXtra1);
        fprintf(stderr,"j=%-d\n",j);
#endif
    }
    if ( xtra2 && szXtra2 )
    {
        get_xtra_hash_minor_hex(digest_minor, szXtra2);
#if INCHIKEY_DEBUG 
        fprintf(stderr,"XHash2=%-s\n",szXtra2);
        fprintf(stderr,"j=%-d\n",j);
#endif
    }
        

fin:if (NULL!=str)      inchi_free(str);
    if (NULL!=smajor)   inchi_free(smajor);
    if (NULL!=sminor)   inchi_free(sminor);
    if (NULL!=stmp)     inchi_free(stmp);
    if (NULL!=sproto)   inchi_free(sproto);

    if ( (ret==INCHIKEY_OK) && (ret1!=INCHIKEY_OK) )
        ret = ret1;
    return ret;

}
Esempio n. 16
0
/* Print to string buffer or to file+stderr */
int inchi_ios_eprint( INCHI_IOSTREAM * ios, const char* lpszFormat, ... )
{
int ret=0, ret2=0;
va_list argList;

    if (!ios) 
        return -1;

    if (ios->type == INCHI_IOSTREAM_STRING) /* was #if ( defined(TARGET_API_LIB) || defined(BUILD_CINCHI_WITH_INCHIKEY) ) */
    {
        /* output to string buffer */
        int max_len, nAddLength = 0;
        char *new_str = NULL;

        my_va_start( argList, lpszFormat );
        max_len = GetMaxPrintfLength( lpszFormat, argList);
        va_end( argList );

        if ( max_len >= 0 ) 
        {
            if ( ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len ) 
            {
                /* enlarge output string */
                nAddLength = inchi_max( INCHI_ADD_STR_LEN, max_len );
                new_str = (char *)inchi_calloc( ios->s.nAllocatedLength + nAddLength, sizeof(new_str[0]) );
                if ( new_str ) 
                {
                    if ( ios->s.pStr ) 
                    {
                        if ( ios->s.nUsedLength > 0 ) 
                        {
                            memcpy( new_str, ios->s.pStr, sizeof(new_str[0])* ios->s.nUsedLength );
                        }
                        inchi_free( ios->s.pStr );
                    }
                    ios->s.pStr              = new_str;
                    ios->s.nAllocatedLength += nAddLength;
                } 
                else 
                {
                    return -1; /* failed */
                }
            }
         
            /* output */
            my_va_start( argList, lpszFormat );
            ret = vsprintf( ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList );
            va_end(argList);
            if ( ret >= 0 ) 
            {
                ios->s.nUsedLength += ret;
            }
            return ret;
        }
        return -1;
    }

    else if (ios->type == INCHI_IOSTREAM_FILE)
    {
        if ( ios->f) 
        {
            /* output to plain file */
            my_va_start( argList, lpszFormat );
            ret = inchi_vfprintf( ios->f, lpszFormat, argList ); 
            va_end( argList );
#if ( !defined(TARGET_API_LIB) && !defined(BUILD_LIB_FOR_WINCHI) )
            /*^^^  No output to stderr from within dll or GUI program */
            if ( ios->f != stderr ) 
            { 
                my_va_start( argList, lpszFormat );
                ret2 = vfprintf( stderr, lpszFormat, argList );
                va_end( argList );
            }
#endif
            return ret? ret : ret2;
        }
    } 

    /* no output */
    return 0;
}
Esempio n. 17
0
int INChIToOrigAtom( INCHI_IOSTREAM *inp_molfile, ORIG_ATOM_DATA *orig_at_data, int bMergeAllInputStructures,
                       int bGetOrigCoord, int bDoNotAddH, int vABParityUnknown, INPUT_TYPE nInputType,
                       char *pSdfLabel, char *pSdfValue, long *lSdfId,
                       INCHI_MODE *pInpAtomFlags, int *err, char *pStrErr )
{
    /* inp_ATOM       *at = NULL; */
    int            num_dimensions_new;
    int            num_inp_bonds_new;
    int            num_inp_atoms_new;
    inp_ATOM      *at_new     = NULL;
    inp_ATOM      *at_old     = NULL;
    int            nNumAtoms  = 0;
    MOL_COORD     *szCoordNew = NULL;
    MOL_COORD     *szCoordOld = NULL;
    int            i, j;

    if ( pStrErr ) {
        pStrErr[0] = '\0';
    }

    /*FreeOrigAtData( orig_at_data );*/
    if ( lSdfId )
        *lSdfId = 0;
    do {
        
        at_old     = orig_at_data? orig_at_data->at      : NULL; /*  save pointer to the previous allocation */
        szCoordOld = orig_at_data? orig_at_data->szCoord : NULL;
        num_inp_atoms_new =
            INChIToInpAtom( inp_molfile, (bGetOrigCoord && orig_at_data)? &szCoordNew : NULL,
                          bDoNotAddH, vABParityUnknown,  nInputType, orig_at_data? &at_new:NULL,
                          MAX_ATOMS,
                          &num_dimensions_new, &num_inp_bonds_new,
                          pSdfLabel, pSdfValue, lSdfId, pInpAtomFlags, err, pStrErr );
        if ( num_inp_atoms_new <= 0 && !*err ) {
            MOLFILE_ERR_SET (*err, 0, "Empty structure");
            *err = 98;
        } else
        if ( orig_at_data && !num_inp_atoms_new && 10 < *err && *err < 20 && orig_at_data->num_inp_atoms > 0 && bMergeAllInputStructures ) {
            *err = 0; /* end of file */
            break;
        } else
        if ( num_inp_atoms_new > 0 && orig_at_data ) {
            /*  merge pOrigDataTmp + orig_at_data => pOrigDataTmp; */
            nNumAtoms = num_inp_atoms_new + orig_at_data->num_inp_atoms;
            if ( nNumAtoms >= MAX_ATOMS ) {
                MOLFILE_ERR_SET (*err, 0, "Too many atoms");
                *err = 70;
                orig_at_data->num_inp_atoms = -1;
            } else
            if ( !at_old ) {
                /* the first structure */
                orig_at_data->at      = at_new;
                orig_at_data->szCoord = szCoordNew; 
                at_new = NULL;
                szCoordNew = NULL;
                orig_at_data->num_inp_atoms  = num_inp_atoms_new;
                orig_at_data->num_inp_bonds  = num_inp_bonds_new;
                orig_at_data->num_dimensions = num_dimensions_new;
            } else
            if ( (orig_at_data->at = ( inp_ATOM* ) inchi_calloc( nNumAtoms, sizeof(inp_ATOM) )) &&
                  (!szCoordNew || (orig_at_data->szCoord = (MOL_COORD *) inchi_calloc( nNumAtoms, sizeof(MOL_COORD) ))) ) {
                /*  switch at_new <--> orig_at_data->at; */
                if ( orig_at_data->num_inp_atoms ) {
                    memcpy( orig_at_data->at, at_old, orig_at_data->num_inp_atoms * sizeof(orig_at_data->at[0]) );
                    /*  adjust numbering in the newly read structure */
                    for ( i = 0; i < num_inp_atoms_new; i ++ ) {
                        for ( j = 0; j < at_new[i].valence; j ++ ) {
                            at_new[i].neighbor[j] += orig_at_data->num_inp_atoms;
                        }
                        at_new[i].orig_at_number += orig_at_data->num_inp_atoms; /* 12-19-2003 */
                    }
                    if ( orig_at_data->szCoord && szCoordOld ) {
                        memcpy( orig_at_data->szCoord, szCoordOld, orig_at_data->num_inp_atoms * sizeof(MOL_COORD) );
                    }
                }
                if ( at_old ) {
                    inchi_free( at_old );
                    at_old = NULL;
                }
                if ( szCoordOld ) {
                    inchi_free( szCoordOld );
                    szCoordOld = NULL;
                }
                /*  copy newly read structure */
                memcpy( orig_at_data->at + orig_at_data->num_inp_atoms,
                        at_new,
                        num_inp_atoms_new * sizeof(orig_at_data->at[0]) );
                if ( orig_at_data->szCoord && szCoordNew ) {
                    memcpy( orig_at_data->szCoord + orig_at_data->num_inp_atoms,
                            szCoordNew,
                            num_inp_atoms_new * sizeof(MOL_COORD) );
                }
                /*  add other things */
                orig_at_data->num_inp_atoms += num_inp_atoms_new;
                orig_at_data->num_inp_bonds += num_inp_bonds_new;
                orig_at_data->num_dimensions = inchi_max(num_dimensions_new, orig_at_data->num_dimensions);
            } else {
                MOLFILE_ERR_SET (*err, 0, "Out of RAM");
                *err = -1;
            }
        } else
        if ( num_inp_atoms_new > 0 ) {
            nNumAtoms += num_inp_atoms_new;
        }
        if ( at_new ) {
            inchi_free( at_new );
            at_new = NULL;
        }

    } while ( !*err && bMergeAllInputStructures );
    /*
    if ( !*err ) {
        orig_at_data->num_components =
            MarkDisconnectedComponents( orig_at_data );
        if ( orig_at_data->num_components == 0 ) {
            MOLFILE_ERR_SET (*err, 0, "No components found");
            *err = 99;
        }
        if ( orig_at_data->num_components < 0 ) {
            MOLFILE_ERR_SET (*err, 0, "Too many components");
            *err = 99;
        }
    }
    */
    if ( szCoordNew ) {
        inchi_free( szCoordNew );
    }
    if ( at_new ) {
        inchi_free( at_new );
    }
    if ( !*err && orig_at_data ) { /* added testing (orig_at_data != NULL) */
        if ( ReconcileAllCmlBondParities( orig_at_data->at, orig_at_data->num_inp_atoms, 0 ) ) {
            MOLFILE_ERR_SET (*err, 0, "Cannot reconcile stereobond parities");  /*   <BRKPT> */
            if (!orig_at_data->num_dimensions) {
                *err = 1;
            }
        }
    }
    if ( *err ) {
        FreeOrigAtData( orig_at_data );
    }
    if ( *err && !(10 < *err && *err < 20) && pStrErr && !pStrErr[0] ) {
        MOLFILE_ERR_SET (*err, 0, "Unknown error");  /*   <BRKPT> */
    }
    return orig_at_data? orig_at_data->num_inp_atoms : nNumAtoms;
}
Esempio n. 18
0
/***********************************************************************************
 * NEIGH_LIST pp[] is an array of pointers to the lists of neighboring atoms numbers
 *  The first number in each list is a number of neighbors.
 *  In case of bDoubleBondSquare != 0 neighbors connected by the double bond appear 2 times
 * The first element pp[0] is a pointer to be deallocated to free all the lists.
 */
NEIGH_LIST *CreateNeighList( int num_atoms, int num_at_tg, sp_ATOM* at,
                             int bDoubleBondSquare, T_GROUP_INFO *t_group_info )
{
    /*  +1 to add NULL termination */
    NEIGH_LIST *pp = (NEIGH_LIST *) inchi_calloc((num_at_tg+1), sizeof(NEIGH_LIST));
    T_GROUP   *t_group             = NULL;
    AT_NUMB   *nEndpointAtomNumber = NULL;
    int        num_t_groups        = 0;
    int        nFirstEndpointAtNoPos;

    AT_NUMB   *pAtList = NULL;
    int        length, start, val, i, j;
    if ( pp ) {
        if ( num_at_tg > num_atoms ) {
            t_group             = t_group_info->t_group;
            num_t_groups        = t_group_info->num_t_groups;
            nEndpointAtomNumber = t_group_info->nEndpointAtomNumber;
        }

        if ( !bDoubleBondSquare ) {
            for ( i = 0, length = 0; i < num_atoms; i ++ ) {
                length += (int)at[i].valence + (num_t_groups && at[i].endpoint);
            }
            length += num_atoms;
            for ( i = 0; i < num_t_groups; i ++ ) {
                length += (int)t_group[i].nNumEndpoints;
            }
            length += num_t_groups;

        } else {
            for ( i = 0, length = 0; i < num_atoms; i ++ ) {
                val = (int)at[i].valence;
                for ( j = 0; j < val; j ++ ) {
                    length += 1 + (bDoubleBondSquare && BOND_DOUBLE == at[i].bond_type[j]);
                }
                length += (num_t_groups && at[i].endpoint);
            }
            length += num_atoms;
            for ( i = 0; i < num_t_groups; i ++ ) {
                length += (int)t_group[i].nNumEndpoints;
            }
            length += num_t_groups;
        }
        length ++; /*  +1 to save number of neighbors */
        if ( pAtList = (AT_NUMB *) inchi_malloc( length*sizeof(*pAtList) ) ) {
            if ( !bDoubleBondSquare ) {
                for ( i = 0, length = 0; i < num_atoms; i ++ ) {
                    val = at[i].valence;
                    start = length ++;
                    for ( j = 0; j < val; j ++ ) {
                        pAtList[length ++] = at[i].neighbor[j];
                    }
                    /*  add endpoint */
                    if (num_t_groups && at[i].endpoint) {
                        pAtList[length ++] = num_atoms + (int)at[i].endpoint - 1;
                    }
                    pAtList[start] = length - start - 1;  /*  number of neighbors before the list of neighbors */
                    pp[i] = pAtList + start;              /*  pointer to the <num.neigh.><list of neigh> */
                }

            } else {
                for ( i = 0, length = 0; i < num_atoms; i ++ ) {
                    val = at[i].valence;
                    start = length ++;
                    for ( j = 0; j < val; j ++ ) {
                        pAtList[length ++] = at[i].neighbor[j];
                        if ( bDoubleBondSquare && BOND_DOUBLE == at[i].bond_type[j] ) {
                            pAtList[length ++] = at[i].neighbor[j]; /*  a list of neighbor orig. numbers */
                        }
                    }
                    /*  add endpoint */
                    if (num_t_groups && at[i].endpoint) {
                        pAtList[length ++] = num_atoms + (int)at[i].endpoint - 1;
                    }
                    pAtList[start] = length - start - 1;  /*  number of neighbors before the list of neighbors */
                    pp[i] = pAtList + start;              /*  pointer to the <num.neigh.><list of neigh> */
                }
            }

            /*  add t-groups */
            for ( i = 0; i < num_t_groups; i ++ ) {
                val = (int)t_group[i].nNumEndpoints;
                start = length ++;
                nFirstEndpointAtNoPos = (int)t_group[i].nFirstEndpointAtNoPos;
                for ( j = 0; j < val; j ++ ) {
                    pAtList[length ++] = nEndpointAtomNumber[nFirstEndpointAtNoPos+j];
                }
                pAtList[start] = length - start - 1;  /*  number of neighbors before the list of neighbors */
                pp[num_atoms+i] = pAtList + start;    /*  pointer to the <num.neigh.><list of neigh> */
            }
        } else {
            inchi_free ( pp );
            return NULL;
        }
    }
    return pp;
}
Esempio n. 19
0
int inchi_ios_print_nodisplay( INCHI_IOSTREAM * ios, const char* lpszFormat, ... )
{
    if (!ios) return -1;
    
    if (ios->type == INCHI_IOSTREAM_STRING) 
    {
        /* output to string buffer */
        int ret=0, max_len;
        va_list argList;
        my_va_start( argList, lpszFormat );
        max_len = GetMaxPrintfLength( lpszFormat, argList);
        va_end( argList );

        if ( max_len >= 0 ) 
        {
            if ( ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len ) 
            {
                /* enlarge output string */
                int  nAddLength = inchi_max( INCHI_ADD_STR_LEN, max_len );
                char *new_str = (char *)inchi_calloc( ios->s.nAllocatedLength + nAddLength, sizeof(new_str[0]) );
                if ( new_str ) 
                {
                    if ( ios->s.pStr ) 
                    {
                        if ( ios->s.nUsedLength > 0 ) 
                        {
                            memcpy( new_str, ios->s.pStr, sizeof(new_str[0])*ios->s.nUsedLength );
                        }
                        inchi_free( ios->s.pStr );
                    }
                    ios->s.pStr              = new_str;
                    ios->s.nAllocatedLength += nAddLength;
                } else 
                {
                    return -1; /* failed */
                }
            }
            /* output */
            my_va_start( argList, lpszFormat );
            ret = vsprintf( ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList );
            va_end(argList);
            if ( ret >= 0 ) 
            {
                ios->s.nUsedLength += ret;
            }
            return ret;
        }
        return -1;
    }

    else if (ios->type == INCHI_IOSTREAM_FILE)
    {
        /* output to file */
        int ret=0, ret2=0;
        va_list argList;
        if (ios->f) 
        {
            my_va_start( argList, lpszFormat );
            ret = vfprintf( ios->f, lpszFormat, argList );
            va_end( argList );
        } 
        else 
        {
            my_va_start( argList, lpszFormat );
            ret2 = vfprintf( stdout, lpszFormat, argList );
            va_end( argList );
        }
        return ret? ret : ret2;
    }

    /* no output */
    return 0;
}
Esempio n. 20
0
int process_single_input( int argc, char *argv[ ] )
/**************************************************/
{

/**************************************/
#endif /* #if ( BUILD_WITH_AMI == 1 ) */
/**************************************/
                                /* if not in AMI mode, main() starts here */
                                
    
    int bReleaseVersion = bRELEASE_VERSION;
    const int nStrLen = INCHI_SEGM_BUFLEN;
    int   nRet = 0, nRet1;
    int	i, k;
    long num_err, num_output, num_inp;
    /* long rcPict[4] = {0,0,0,0}; */
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
    unsigned long  ulTotalProcessingTime = 0;

    char szTitle[MAX_SDF_HEADER+MAX_SDF_VALUE+256];
    char szSdfDataValue[MAX_SDF_VALUE+1];
    char *pStr = NULL;

    INPUT_PARMS inp_parms;
    INPUT_PARMS *ip = &inp_parms;

    STRUCT_DATA struct_data;
    STRUCT_DATA *sd = &struct_data;

    ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */
    ORIG_ATOM_DATA *orig_inp_data = &OrigAtData;
    ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */
    ORIG_ATOM_DATA *prep_inp_data = PrepAtData;

    PINChI2     *pINChI[INCHI_NUM];
    PINChI_Aux2 *pINChI_Aux[INCHI_NUM];

    INCHI_IOSTREAM outputstr, logstr, prbstr, instr;
    INCHI_IOSTREAM *pout=&outputstr, *plog = &logstr, *pprb = &prbstr, *inp_file = &instr;
#ifdef TARGET_EXE_STANDALONE
    char ik_string[256];    /*^^^ Resulting InChIKey string */
    int ik_ret=0;           /*^^^ InChIKey-calc result code */
    int xhash1, xhash2;
    char szXtra1[65], szXtra2[65];
    int inchi_ios_type = INCHI_IOSTREAM_STRING;
#else
    int inchi_ios_type = INCHI_IOSTREAM_FILE;
#endif



/* internal tests --- */
#ifndef TEST_FPTRS
    STRUCT_FPTRS *pStructPtrs = NULL;
#else
    STRUCT_FPTRS struct_fptrs, *pStructPtrs =&struct_fptrs; /* INCHI_LIB debug only */
#endif
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
    int  num_repeat = REPEAT_ALL;
#endif

#if ( TRACE_MEMORY_LEAKS == 1 )
    _CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
/* for execution outside the VC++ debugger uncomment one of the following two */
/*#define MY_REPORT_FILE  _CRTDBG_FILE_STDERR */
/*#define MY_REPORT_FILE  _CRTDBG_FILE_STDOUT */
#ifdef MY_REPORT_FILE 
   _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
   _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
   _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
   _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
   _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
   _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
#else
    _CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG);
#endif
   /* turn on floating point exceptions */
    {
        /* Get the default control word. */
        int cw = _controlfp( 0,0 );

        /* Set the exception masks OFF, turn exceptions on. */
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
        cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_ZERODIVIDE|EM_DENORMAL);

        /* Set the control word. */
        _controlfp( cw, MCW_EM );
 
    }
#endif 

#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
repeat:
    inchi_ios_close(inp_file);
    inchi_ios_close(pout);
    inchi_ios_close(plog);
    inchi_ios_close(pprb);
    pStr = NULL;
#endif
/* --- internal tests */



    sd->bUserQuit  = 0;
#if ( defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) )
    if ( SetConsoleCtrlHandler( MyHandlerRoutine, 1 ) ) 
        ConsoleQuit = WasInterrupted;
#endif
    
    num_inp    = 0;
    num_err    = 0;
    num_output = 0;
    
    inchi_ios_init(inp_file, INCHI_IOSTREAM_FILE, NULL);
    inchi_ios_init(pout, inchi_ios_type, NULL);
    inchi_ios_init(plog, inchi_ios_type, stdout);
    inchi_ios_init(pprb, inchi_ios_type, NULL);

    
    if ( argc == 1 || argc==2 && ( argv[1][0]==INCHI_OPTION_PREFX ) &&
        (!strcmp(argv[1]+1, "?") || !stricmp(argv[1]+1, "help") ) ) 
    {
        HelpCommandLineParms(plog); 
        inchi_ios_flush(plog);
        return 0;
    }

    
    /*  original input structure */
    memset( orig_inp_data     , 0,   sizeof( *orig_inp_data  ) );
    memset( prep_inp_data     , 0, 2*sizeof( *prep_inp_data  ) );
    memset( pINChI,     0, sizeof(pINChI    ) );
    memset( pINChI_Aux, 0, sizeof(pINChI_Aux) );
    memset( szSdfDataValue    , 0, sizeof( szSdfDataValue    ) );
    

    plog->f = stderr;
    if ( 0 > ReadCommandLineParms( argc, (const char **)argv, ip, szSdfDataValue, &ulDisplTime, bReleaseVersion, plog) ) 
                                         /* explicitly cast to (const char **) to avoid a warning about "incompatible pointer type":*/    
    {
        goto exit_function;
    }


    if ( !OpenFiles( &(inp_file->f), &(pout->f), &(plog->f), &(pprb->f), ip ) ) 
    {
        goto exit_function;
    }


    if ( ip->bNoStructLabels ) 
    {
        ip->pSdfLabel = NULL;
        ip->pSdfValue = NULL;
    } 
    else if ( ip->nInputType == INPUT_INCHI_XML || ip->nInputType == INPUT_INCHI_PLAIN  ||
         ip->nInputType == INPUT_CMLFILE   || ip->nInputType == INPUT_INCHI  ) 
    {
        /* the input may contain both the header and the label of the structure */
        if ( !ip->pSdfLabel ) 
            ip->pSdfLabel  = ip->szSdfDataHeader;
        if ( !ip->pSdfValue )
            ip->pSdfValue  = szSdfDataValue;
    }


    inchi_ios_eprint( plog, "The command line used:\n\"");
    for(k=0; k<argc-1; k++)
        inchi_ios_eprint( plog, "%-s ",argv[k]);
    inchi_ios_eprint( plog, "%-s\"\n", argv[argc-1]);


    PrintInputParms(plog,ip);
    inchi_ios_flush2(plog, stderr);


    if ( !( pStr = (char*) inchi_malloc(nStrLen) ) ) 
    {
        inchi_ios_eprint( plog, "Cannot allocate output buffer. Terminating\n"); 
        inchi_ios_flush2(plog, stderr);
        goto exit_function;
    }
    pStr[0] = '\0';


#if ( READ_INCHI_STRING == 1 )
    if ( ip->nInputType == INPUT_INCHI ) {
        memset( sd, 0, sizeof(*sd) );
        ReadWriteInChI( inp_file, pout, plog, ip,  sd, NULL, NULL, NULL, 0, NULL);
        inchi_ios_flush2(plog, stderr);
        ulTotalProcessingTime = sd->ulStructTime;
        num_inp               = sd->fPtrStart;
        num_err               = sd->fPtrEnd;
        goto exit_function;
    }
#endif


    ulTotalProcessingTime = 0;
    if ( pStructPtrs ) 
    {
        memset ( pStructPtrs, 0, sizeof(pStructPtrs[0]) );
        /* debug: set CML reading sequence
        pStructPtrs->fptr = (INCHI_FPTR *)inchi_calloc(16, sizeof(INCHI_FPTR));
        for ( i = 0; i < 15; i ++ )
            pStructPtrs->fptr[i] = 15-i;
        pStructPtrs->cur_fptr = 7;
        pStructPtrs->len_fptr = 16;
        pStructPtrs->max_fptr = 14;
        */
    }


    /**********************************************************************************************/
    /*  Main cycle : read input structures and create their INChI								  */
    /**********************************************************************************************/
    while ( !sd->bUserQuit && !bInterrupted ) 
    {
    
        if ( ip->last_struct_number && num_inp >= ip->last_struct_number ) 
        {
            nRet = _IS_EOF; /*  simulate end of file */
            goto exit_function;
        }

        /*  read one structure from input and display optionally it */

        nRet = GetOneStructure( sd, ip, szTitle, inp_file, plog, pout, pprb,
                                orig_inp_data, &num_inp, pStr, nStrLen, pStructPtrs );
        inchi_ios_flush2(plog, stderr);


        if ( pStructPtrs ) 
            pStructPtrs->cur_fptr ++;

        if ( sd->bUserQuit ) 
            break;

        switch ( nRet ) 
        {
            case _IS_FATAL:
                num_err ++;
            case _IS_EOF:
                goto exit_function;
            case _IS_ERROR:
                num_err ++;
            case _IS_SKIP:
                continue;
        }

        /* create INChI for each connected component of the structure and optionally display them */
        /* output INChI for the whole structure */
        
        nRet1 = ProcessOneStructure( sd, ip, szTitle, pINChI, pINChI_Aux,
                                     inp_file, plog, pout, pprb,
                                     orig_inp_data, prep_inp_data,
                                     num_inp, pStr, nStrLen,
                                     0 /* save_opt_bits */);        
        inchi_ios_flush2(plog, stderr);


#ifdef TARGET_EXE_STANDALONE
        /* correctly treat tabbed output with InChIKey */
        if ( ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT ) 
            if ( ip->bCalcInChIHash != INCHIHASH_NONE )
                if (pout->s.pStr)
                    if (pout->s.nUsedLength>0)
                        if (pout->s.pStr[pout->s.nUsedLength-1]=='\n')
                            /* replace LF with TAB */
                            pout->s.pStr[pout->s.nUsedLength-1] = '\t';
#endif

        /*  free INChI memory */
        FreeAllINChIArrays( pINChI, pINChI_Aux, sd->num_components );
        /* free structure data */
        FreeOrigAtData( orig_inp_data );
        FreeOrigAtData( prep_inp_data );
        FreeOrigAtData( prep_inp_data+1 );

        ulTotalProcessingTime += sd->ulStructTime;

        nRet = inchi_max(nRet, nRet1);
        switch ( nRet ) 
        {
            case _IS_FATAL:
                num_err ++;
                goto exit_function;
            case _IS_ERROR:
                num_err ++;
                continue;
        }


#ifdef TARGET_EXE_STANDALONE
        if ( ip->bCalcInChIHash != INCHIHASH_NONE )
        {
            char *buf = NULL;
            size_t slen = pout->s.nUsedLength;

            extract_inchi_substring(&buf, pout->s.pStr, slen);            

            if (NULL==buf)
            {
                ik_ret = INCHIKEY_NOT_ENOUGH_MEMORY;                     
            }
            else
            {
                xhash1 = xhash2 = 0;
                if ( ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1 ) ||
                     ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2 ) )
                     xhash1 = 1;
                if ( ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2 ) ||
                     ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2 ) )
                     xhash2 = 1;
                ik_ret = GetINCHIKeyFromINCHI(buf, xhash1, xhash2, 
                                              ik_string, szXtra1, szXtra2); 
                inchi_free(buf);
            }
            
                
        
            if (ik_ret==INCHIKEY_OK)   
            {
                /* NB: correctly treat tabbed output with InChIKey & hash extensions */                
                char csep = '\n';
#ifdef TARGET_EXE_STANDALONE
                if ( ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT ) 
                    csep = '\t';
#endif                
                inchi_ios_print(pout, "InChIKey=%-s",ik_string);
                if ( xhash1 )
                    inchi_ios_print(pout, "%cXHash1=%-s",csep,szXtra1);
                if ( xhash2 )
                    inchi_ios_print(pout, "%cXHash2=%-s",csep,szXtra2);
                inchi_ios_print(pout, "\n");
            }
            else    
            {
                inchi_ios_print(plog, "Warning (Could not compute InChIKey: ", num_inp);
                switch(ik_ret)
                {
                    case INCHIKEY_UNKNOWN_ERROR:
                        inchi_ios_print(plog, "unresolved error)");
                        break;
                    case INCHIKEY_EMPTY_INPUT:
                        inchi_ios_print(plog,  "got an empty string)");
                        break;
                    case INCHIKEY_INVALID_INCHI_PREFIX:
                    case INCHIKEY_INVALID_INCHI:
                    case INCHIKEY_INVALID_STD_INCHI:
                        inchi_ios_print(plog, "got non-InChI string)");
                        break;
                    case INCHIKEY_NOT_ENOUGH_MEMORY:
                        inchi_ios_print(plog, "not enough memory to treat the string)");
                        break;
                    default:inchi_ios_print(plog, "internal program error)");
                        break;
                }
                inchi_ios_print(plog, " structure #%-lu.\n", num_inp);
                if ( ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT )
                    inchi_ios_print(pout, "\n");
            }
            inchi_ios_flush(pout);
            inchi_ios_flush2(plog, stderr);
        }

        else
            inchi_ios_flush(pout);


#endif

   /*   --- debug only ---
        if ( pStructPtrs->cur_fptr > 5 ) {
            pStructPtrs->cur_fptr = 5;
        }
   */


            
    } /* end of main cycle - while ( !sd->bUserQuit && !bInterrupted ) */



exit_function:
    if ( (ip->bINChIOutputOptions & INCHI_OUT_XML) && sd->bXmlStructStarted > 0 ) 
    {
            if ( !OutputINChIXmlStructEndTag( pout,  pStr, nStrLen, 1 ) ) 
            {
                inchi_ios_eprint( plog, "Cannot create end xml tag for structure #%ld.%s%s%s%s Terminating.\n", num_inp, SDF_LBL_VAL(ip->pSdfLabel,ip->pSdfValue) );
                inchi_ios_flush2(plog, stderr);
                sd->bXmlStructStarted = -1; /*  do not repeat same message */
        }
    }
    if ( (ip->bINChIOutputOptions & INCHI_OUT_XML) && ip->bXmlStarted ) 
    {
        OutputINChIXmlRootEndTag( pout ); 
        inchi_ios_flush(pout);
        ip->bXmlStarted = 0;
    }

    /* avoid memory leaks in case of fatal error */
    if ( pStructPtrs && pStructPtrs->fptr ) {
        inchi_free( pStructPtrs->fptr );
    }

    /*  free INChI memory */
    FreeAllINChIArrays( pINChI, pINChI_Aux, sd->num_components );
    /* free structure data */
    FreeOrigAtData( orig_inp_data );
    FreeOrigAtData( prep_inp_data );
    FreeOrigAtData( prep_inp_data+1 );
#if ( ADD_CMLPP == 1 )
    /* BILLY 8/6/04 */
    /* free CML memory */
   FreeCml ();
   FreeCmlDoc( 1 );
#endif

    /* close output(s) */
    inchi_ios_close(inp_file);    
    inchi_ios_close(pout);    
    inchi_ios_close(pprb);
    {
        int hours, minutes, seconds, mseconds;
        SplitTime( ulTotalProcessingTime, &hours, &minutes, &seconds, &mseconds );
        inchi_ios_eprint( plog, "Finished processing %ld structure%s: %ld error%s, processing time %d:%02d:%02d.%02d\n",
                                num_inp, num_inp==1?"":"s",
                                num_err, num_err==1?"":"s",
                                hours, minutes, seconds,mseconds/10);
        inchi_ios_flush2(plog, stderr);
    }
    inchi_ios_close(plog);
    if ( pStr )                             
        inchi_free( pStr );


    /* frees */
    for ( i = 0; i < MAX_NUM_PATHS; i ++ ) 
    {
        if ( ip->path[i] ) 
        {
            free( (void*) ip->path[i] ); /*  cast deliberately discards 'const' qualifier */
            ip->path[i] = NULL;
        }
    }
    SetBitFree( );

/* internal tests --- */
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
    if ( num_repeat-- > 0 ) 
        goto repeat;
#endif
/* --- internal tests */

#if ( bRELEASE_VERSION != 1 && defined(_DEBUG) )
    if ( inp_file->f && inp_file->f != stdin ) 
    {
        user_quit("Press Enter to exit ?", ulDisplTime);
    }
#endif

#if ( ( BUILD_WITH_AMI==1 ) && defined( _WIN32 ) && defined( _CONSOLE ) && !defined( COMPILE_ANSI_ONLY ) )
    if ( bInterrupted ) 
        return CTRL_STOP_EVENT;
#endif
	return 0;
}