LCOV - code coverage report
Current view: top level - src - util.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 45.0 % 587 264
Test Date: 2026-05-04 07:05:02 Functions: 60.0 % 45 27
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 40.1 % 591 237

             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                 :             : #include <string.h>
      42                 :             : #include <stdlib.h>
      43                 :             : #include <ctype.h>
      44                 :             : 
      45                 :             : #include "mode.h"
      46                 :             : 
      47                 :             : #if defined(COMPILE_ANSI_ONLY) && defined(__APPLE__)
      48                 :             : /*    For build under OSX, advice from Burt Leland */
      49                 :             : #include "ichicomp.h"    /* Needed for __isascii define */
      50                 :             : #endif
      51                 :             : 
      52                 :             : /* djb-rwth: defining __isascii */
      53                 :             : #if defined(__isascii)
      54                 :             : #define is_ascii __isascii
      55                 :             : #elif defined(isascii)
      56                 :             : #define is_ascii isascii
      57                 :             : #else
      58                 :             : #define is_ascii(c)   ((unsigned)(c) < 0x80)
      59                 :             : #endif
      60                 :             : 
      61                 :             : #include "util.h"
      62                 :             : #include "extr_ct.h"
      63                 :             : 
      64                 :             : #include "bcf_s.h"
      65                 :             : 
      66                 :             : 
      67                 :             : /*    CHEMICAL ELEMENTS & ATOMIC VALENCE MODEL
      68                 :             :       FOR VARIOUS OXIDATION STATES
      69                 :             : */
      70                 :             : const ELDATA ElData[] =
      71                 :             : {
      72                 :             :     /*       avg  norm                      El    No  -------- Valence(s) of an ion or neutral atom -------------*/
      73                 :             :     /*        mw  mass  exact mw     type   neg   H   -2          -1          0           +1         +2          */
      74                 :             :     { "H",    1,   1,   1.007825035,     0 , 21,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
      75                 :             :     { "D",    2,   2,   2.014101778,     0 , 21,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
      76                 :             :     { "T",    3,   3,   3.016049268,     0 , 21,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
      77                 :             :     { "He",   4,   4,   4.002600000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
      78                 :             :     { "Li",   7,   7,   7.016000000, METAL , 10,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
      79                 :             :     { "Be",   9,   9,   9.012180000, METAL , 15,  0, {{0,},       {0,},       {2,},       {1,},       {0,}       }},
      80                 :             :     { "B",   11,  11,  11.009300000,     0 , 20,  0, {{3,},       {4,},       {3,},       {2,},       {1,}       }},
      81                 :             :     { "C",   12,  12,  12.000000000,     0 , 25,  0, {{2,},       {3,},       {4,},       {3,},       {2,}       }},
      82                 :             :     { "N",   14,  14,  14.003074000,     0 , 30,  0, {{1,},       {2,},       {3,5},      {4,},       {3,}       }},
      83                 :             :     { "O",   16,  16,  15.994914630,     0 , 35,  0, {{0,},       {1,},       {2,},       {3,5,},     {4,}       }},
      84                 :             :     { "F",   19,  19,  18.998403220,     0 , 40,  0, {{0,},       {0,},       {1,},       {2,},       {3,5}      }},
      85                 :             :     { "Ne",  20,  20,  19.992440000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
      86                 :             :     { "Na",  23,  23,  22.989770000, METAL ,  9,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
      87                 :             :     { "Mg",  24,  24,  23.985000000, METAL , 12,  0, {{0,},       {0,},       {2,},       {1,},       {0,}       }},
      88                 :             :     { "Al",  27,  27,  26.981540000, METAL , 15,  0, {{3,5,},     {4,},       {3,},       {2,},       {1,}       }},
      89                 :             :     { "Si",  28,  28,  27.976927100,     0 , 18,  0, {{2,},       {3,5},      {4,},       {3,},       {2,}       }},
      90                 :             :     { "P",   31,  31,  30.973762000,     0 , 21,  0, {{1,3,5,7,}, {2,4,6,},   {3,5,},     {4,},       {3,}       }},
      91                 :             :     { "S",   32,  32,  31.972070700,     0 , 25,  0, {{0,},       {1,3,5,7,}, {2,4,6},    {3,5,},     {4,}       }},
      92                 :             :     { "Cl",  35,  35,  34.968852730,     0 , 30,  0, {{0,},       {0,},       {1,3,5,7},  {2,4,6},    {3,5,}     }},
      93                 :             :     { "Ar",  40,  40,  39.962400000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
      94                 :             :     { "K",   39,  39,  38.963700000, METAL ,  8,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
      95                 :             :     { "Ca",  40,  40,  39.962600000, METAL , 10,  0, {{0,},       {0,},       {2,},       {1,},       {0,}       }},
      96                 :             :     { "Sc",  45,  45,  44.955910000, METAL , 13,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
      97                 :             :     { "Ti",  48,  48,  47.947950000, METAL , 15,  1, {{0,},       {0,},       {3,4},      {0,},       {0,}       }},
      98                 :             :     { "V",   51,  51,  50.943960000, METAL , 16,  1, {{0,},       {0,},       {2,3,4,5,}, {0,},       {0,}       }},
      99                 :             :     { "Cr",  52,  52,  51.940500000, METAL , 16,  1, {{0,},       {0,},       {2,3,6,},   {0,},       {0,}       }},
     100                 :             :     { "Mn",  55,  55,  54.938050000, METAL2, 15,  1, {{0,},       {0,},       {2,3,4,6,}, {0,},       {0,}       }},
     101                 :             :     { "Fe",  56,  56,  55.934900000, METAL2, 18,  1, {{0,},       {0,},       {2,3,4,6,}, {0,},       {0,}       }},
     102                 :             :     { "Co",  59,  59,  58.933200000, METAL2, 18,  1, {{0,},       {0,},       {2,3,},     {0,},       {0,}       }},
     103                 :             :     { "Ni",  59,  58,  57.935300000, METAL2, 18,  1, {{0,},       {0,},       {2,3,},     {0,},       {0,}       }},
     104                 :             :     { "Cu",  64,  63,  62.929600000, METAL , 19,  1, {{0,},       {0,},       {1,2,},     {0,},       {0,}       }},
     105                 :             :     { "Zn",  65,  64,  63.929147000, METAL , 16,  1, {{0,},       {0,},       {2,},       {0,},       {0,}       }},
     106                 :             :     { "Ga",  70,  69,  68.925600000, METAL , 18,  0, {{3,5,},     {4,},       {3,},       {0,},       {1,}       }},
     107                 :             :     { "Ge",  73,  74,  73.921177400,     0 , 18,  0, {{2,4,6,},   {3,5,},     {4,},       {3,},       {0,}       }},
     108                 :             :     { "As",  75,  75,  74.921594200,     0 , 20,  0, {{1,3,5,7,}, {2,4,6,},   {3,5,},     {4,},       {3,}       }},
     109                 :             :     { "Se",  79,  80,  79.916519600,     0 , 24,  0, {{0,},       {1,3,5,7,}, {2,4,6,},   {3,5,},     {4,}       }},
     110                 :             :     { "Br",  80,  79,  78.918336100,     0 , 28,  0, {{0,},       {0,},       {1,3,5,7,}, {2,4,6,},   {3,5,}     }},
     111                 :             :     { "Kr",  84,  84,  83.911500000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
     112                 :             :     { "Rb",  85,  85,  84.911800000, METAL ,  8,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     113                 :             :     { "Sr",  88,  88,  87.905600000, METAL , 10,  0, {{0,},       {0,},       {2,},       {1,},       {0,}       }},
     114                 :             :     { "Y",   89,  89,  88.905860000, METAL , 12,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     115                 :             :     { "Zr",  91,  90,  89.904700000, METAL , 14,  1, {{0,},       {0,},       {4,},       {0,},       {0,}       }},
     116                 :             :     { "Nb",  93,  93,  92.906400000, METAL , 16,  1, {{0,},       {0,},       {3,5,},     {0,},       {0,}       }},
     117                 :             :     { "Mo",  96,  98,  97.905400000, METAL , 18,  1, {{0,},       {0,},       {3,4,5,6,}, {0,},       {0,}       }},
     118                 :             :     { "Tc",  98,  98,  97.907200000, METAL , 19,  1, {{0,},       {0,},       {7,},       {0,},       {0,}       }},
     119                 :             :     { "Ru", 101, 102, 101.904300000, METAL , 22,  1, {{0,},       {0,},       {2,3,4,6,}, {0,},       {0,}       }},
     120                 :             :     { "Rh", 103, 103, 102.905500000, METAL , 22,  1, {{0,},       {0,},       {2,3,4,},   {0,},       {0,}       }},
     121                 :             :     { "Pd", 106, 106, 105.903500000, METAL , 22,  1, {{0,},       {0,},       {2,4,},     {0,},       {0,}       }},
     122                 :             :     { "Ag", 108, 107, 106.905100000, METAL , 19,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     123                 :             :     { "Cd", 112, 114, 113.903400000, METAL , 17,  1, {{0,},       {0,},       {2,},       {0,},       {0,}       }},
     124                 :             :     { "In", 115, 115, 114.903900000, METAL , 17,  0, {{3,5,},     {2,4,},     {3,},       {0,},       {1,}       }},
     125                 :             :     { "Sn", 119, 120, 119.902200000, METAL2, 18,  0, {{2,4,6,},   {3,5},      {2,4,},     {3,},       {0,}       }},
     126                 :             :     { "Sb", 122, 121, 120.903800000, METAL,  19,  0, {{1,3,5,7,}, {2,4,6,},   {3,5,},     {2,4,},     {3,}       }},
     127                 :             :     { "Te", 128, 130, 129.906200000,     0 , 21,  0, {{0,},       {1,3,5,7,}, {2,4,6,},   {3,5,},     {2,4,}     }},
     128                 :             :     { "I",  127, 127, 126.904500000,     0 , 25,  0, {{0,},       {0,},       {1,3,5,7,}, {2,4,6},    {3,5,}     }},
     129                 :             :     { "Xe", 131, 132, 131.904100000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
     130                 :             :     { "Cs", 133, 133, 132.905430000, METAL ,  7,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     131                 :             :     { "Ba", 137, 138, 137.905200000, METAL ,  9,  0, {{0,},       {0,},       {2,},       {1,},       {0,}       }},
     132                 :             :     { "La", 139, 139, 138.906360000, METAL , 11,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     133                 :             :     { "Ce", 140, 140, 139.905400000, METAL2,  0,  1, {{0,},       {0,},       {3,4,},     {0,},       {0,}       }},
     134                 :             :     { "Pr", 141, 141, 140.907660000, METAL2,  0,  1, {{0,},       {0,},       {3,4,},     {0,},       {0,}       }},
     135                 :             :     { "Nd", 144, 142, 141.907719000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     136                 :             :     { "Pm", 145, 145, 144.912800000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     137                 :             :     { "Sm", 150, 152, 151.919700000, METAL2,  0,  1, {{0,},       {0,},       {2,3,},     {0,},       {0,}       }},
     138                 :             :     { "Eu", 152, 153, 152.921200000, METAL2,  0,  1, {{0,},       {0,},       {2,3,},     {0,},       {0,}       }},
     139                 :             :     { "Gd", 157, 158, 157.924099000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     140                 :             :     { "Tb", 159, 159, 158.925350000, METAL2,  0,  1, {{0,},       {0,},       {3,4,},     {0,},       {0,}       }},
     141                 :             :     { "Dy", 163, 164, 163.929200000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }}, /*  mw rounding uncertain */
     142                 :             :     { "Ho", 165, 165, 164.930300000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     143                 :             :     { "Er", 167, 166, 165.930300000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     144                 :             :     { "Tm", 169, 169, 168.934230000, METAL2,  0,  1, {{0,},       {0,},       {2,3,},     {0,},       {0,}       }},
     145                 :             :     { "Yb", 173, 174, 173.938900000, METAL2,  0,  1, {{0,},       {0,},       {2,3,},     {0,},       {0,}       }},
     146                 :             :     { "Lu", 175, 175, 174.940800000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     147                 :             :     { "Hf", 178, 180, 179.946600000, METAL , 13,  1, {{0,},       {0,},       {4,},       {0,},       {0,}       }},
     148                 :             :     { "Ta", 181, 181, 180.948010000, METAL , 15,  1, {{0,},       {0,},       {5,},       {0,},       {0,}       }},
     149                 :             :     { "W",  184, 184, 183.951000000, METAL2, 17,  1, {{0,},       {0,},       {3,4,5,6,}, {0,},       {0,}       }},
     150                 :             :     { "Re", 186, 187, 186.955800000, METAL2, 19,  1, {{0,},       {0,},       {2,4,6,7,}, {0,},       {0,}       }},
     151                 :             :     { "Os", 190, 192, 191.961500000, METAL2, 22,  1, {{0,},       {0,},       {2,3,4,6,}, {0,},       {0,}       }},
     152                 :             :     { "Ir", 192, 193, 192.962900000, METAL2, 22,  1, {{0,},       {0,},       {2,3,4,6,}, {0,},       {0,}       }},
     153                 :             :     { "Pt", 195, 195, 194.964800000, METAL2, 22,  1, {{0,},       {0,},       {2,4,},     {0,},       {0,}       }},
     154                 :             :     { "Au", 197, 197, 196.966560000, METAL , 24,  1, {{0,},       {0,},       {1,3,},     {0,},       {0,}       }},
     155                 :             :     { "Hg", 201, 202, 201.970617000, METAL2, 19,  1, {{0,},       {0,},       {1,2,},     {0,},       {0,}       }},
     156                 :             :     { "Tl", 204, 205, 204.974400000, METAL2, 18,  0, {{3,5,},     {2,4,},     {1,3,},     {0,},       {0,}       }},
     157                 :             :     { "Pb", 207, 208, 207.976627000, METAL2, 18,  0, {{2,4,6,},   {3,5},      {2,4,},     {3,},       {0,}       }},
     158                 :             :     { "Bi", 209, 209, 208.980390000, METAL , 19,  0, {{1,3,5,7,}, {2,4,6,},   {3,5,},     {2,4,},     {3,}       }},
     159                 :             :     { "Po", 209, 209, 208.982400000, METAL2, 20,  0, {{0,},       {1,3,5,7,}, {2,4,6,},   {3,5,},     {2,4,}     }},
     160                 :             :     { "At", 210, 210, 209.987100000,     0 , 22,  0, {{0,},       {0,},       {1,3,5,7,}, {2,4,6},    {3,5,}     }},
     161                 :             :     { "Rn", 222, 222, 222.017500000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
     162                 :             :     { "Fr", 223, 223, 223.019700000, METAL ,  0,  0, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     163                 :             :     { "Ra", 226, 226, 226.025410000, METAL ,  0,  0, {{0,},       {0,},       {2,},       {1,},       {0,}       }},
     164                 :             :     { "Ac", 227, 227, 227.027750000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     165                 :             :     { "Th", 232, 232, 232.038050000, METAL2,  0,  1, {{0,},       {0,},       {3,4,},     {0,},       {0,}       }},
     166                 :             :     { "Pa", 231, 231, 231.035880000, METAL2,  0,  1, {{0,},       {0,},       {3,4,5,},   {0,},       {0,}       }},
     167                 :             :     { "U",  238, 238, 238.050790000, METAL2,  0,  1, {{0,},       {0,},       {3,4,5,6,}, {0,},       {0,}       }},
     168                 :             :     { "Np", 237, 237, 237.048170000, METAL2,  0,  1, {{0,},       {0,},       {3,4,5,6,}, {0,},       {0,}       }},
     169                 :             :     { "Pu", 244, 244, 244.064200000, METAL2,  0,  1, {{0,},       {0,},       {3,4,5,6,}, {0,},       {0,}       }},
     170                 :             :     { "Am", 243, 243, 243.061370000, METAL2,  0,  1, {{0,},       {0,},       {3,4,5,6,}, {0,},       {0,}       }},
     171                 :             :     { "Cm", 247, 247, 247.070300000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     172                 :             :     { "Bk", 247, 247, 247.070300000, METAL ,  0,  1, {{0,},       {0,},       {3,4,},     {0,},       {0,}       }},
     173                 :             :     { "Cf", 251, 251, 251.079600000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     174                 :             :     { "Es", 252, 252, 252.082800000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     175                 :             :     { "Fm", 257, 257, 257.095100000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     176                 :             :     { "Md", 258, 258, 258.098600000, METAL ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     177                 :             :     { "No", 259, 259, 259.100900000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     178                 :             :     { "Lr", 260, 260, 260.105400000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     179                 :             :     { "Rf", 261, 261, 261.108700000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     180                 :             : 
     181                 :             :     /*
     182                 :             :         The elements below were added after v. 1.03.
     183                 :             :         When available, the mass is given for isotope with the longest half-life.
     184                 :             :         Standard valences given here are just placeholders.
     185                 :             :         v. 1.04: added elements 105-112.
     186                 :             :                     Ref.: M. E. WIESER AND T. B. COPLEN.
     187                 :             :                     Atomic weights of the elements 2009 (IUPAC Technical Report).
     188                 :             :                     Pure Appl. Chem., Vol. 83, No. 2, pp. 359-396, 2011.
     189                 :             :         v. 1.05: added elements 114 and 116;
     190                 :             :                     updated data for elements 105-112.
     191                 :             :                     Ref.: J. Meija, T.B. Coplen, M.Berglund et al.
     192                 :             :                     Atomic weights of the elements 2013 (IUPAC Technical Report).
     193                 :             :                     Pure Appl. Chem., Vol. 88, No. 3, pp. 265-291, 2016.
     194                 :             :                 added elements 113, 115, 117, and 118, according to IUPAC provisional recommendations:
     195                 :             :                     Ref.: L. Ohrstrom, J. Reedijk.
     196                 :             :                     Names and Symbols of the Elements with Atomic Numbers 113, 115, 117 and 118.
     197                 :             :                     Pure Appl. Chem., May 1, 2016, Manuscript ID PAC-REC-16-05-01
     198                 :             :                     http://iupac.org/cms/wp-content/uploads/2016/06/names-and-symbols-of-elements.pdf
     199                 :             :     */
     200                 :             : 
     201                 :             :     /* 105 dubnium Db                ? Like: Ta */
     202                 :             :     { "Db", 270, 270, 270.131000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     203                 :             :     /* 106 seaborgium Sg            ? Like: W */
     204                 :             :     { "Sg", 269, 269, 269.129000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     205                 :             :     /* 107 bohrium Bh                ? Like: Re */
     206                 :             :     { "Bh", 270, 270, 270.133000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     207                 :             :     /* 108 hassium Hs                ? Like: Os */
     208                 :             :     { "Hs", 270, 270, 270.134000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     209                 :             :     /* 109 meitnerium Mt            ? Like: Ir */
     210                 :             :     { "Mt", 278, 278, 278.156000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     211                 :             :     /* 110 darmstadtium Ds            ? Like: Pt */
     212                 :             :     { "Ds", 281, 281, 281.165000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     213                 :             :     /* 111 roentgenium Rg            ? Like: Au */
     214                 :             :     { "Rg", 281, 281, 281.166000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     215                 :             :     /* 112 copernicium Cn            ? Like: Hg */
     216                 :             :     { "Cn", 285, 285, 285.177000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     217                 :             :     /* 113 nihonium Nh                ? Like: ? */
     218                 :             :     { "Nh", 278, 278, 278.000000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     219                 :             :     /* 114 flerovium Fl                ? Like: Pb */
     220                 :             :     { "Fl", 289, 289, 289.190000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     221                 :             :     /* 115 moscovium Mc                ? Like: ? */
     222                 :             :     { "Mc", 289, 289, 289.000000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     223                 :             :     /* 116 livermorium Lv            ? Like: Po */
     224                 :             :     { "Lv", 293, 293, 293.204000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     225                 :             :     /* 117 tennessine Ts            ? Like: ? */
     226                 :             :     { "Ts", 297, 297, 297.000000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     227                 :             :     /* 118 oganesson Og            ? Like: ? */
     228                 :             :     { "Og", 294, 294, 294.000000000, METAL ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     229                 :             :     /* End of added in v. 1.04 - 1.05 */
     230                 :             :     { "Zy",   0,   0,   0.000000000,     0 ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     231                 :             :     { "Zz",   0,   0,   0.000000000,     0 ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     232                 :             :     #ifdef INCHI_ZFRAG
     233                 :             :     { "Zu",   0,   0,   0.000000000,     0 ,  0,  1, {{0,},       {0,},       {1,},       {0,},       {0,}       }},
     234                 :             :     { "Zv",   0,   0,   0.000000000,     0 ,  0,  1, {{0,},       {0,},       {2,},       {0,},       {0,}       }},
     235                 :             :     { "Zw",   0,   0,   0.000000000,     0 ,  0,  1, {{0,},       {0,},       {3,},       {0,},       {0,}       }},
     236                 :             :     { "Zx",   0,   0,   0.000000000,     0 ,  0,  1, {{0,},       {0,},       {1,2,},     {0,},       {0,}       }},
     237                 :             :     #endif
     238                 :             : 
     239                 :             :     { "",     0,   0,   0.000000000,     0 ,  0,  0, {{0,},       {0,},       {0,},       {0,},       {0,}       }},
     240                 :             : };
     241                 :             : 
     242                 :             : 
     243                 :             : const int ERR_ELEM = 255;
     244                 :             : const int nElDataLen = sizeof( ElData ) / sizeof( ElData[0] ) - 1;
     245                 :             : 
     246                 :             : 
     247                 :             : 
     248                 :             : /*
     249                 :             :     MISC. CHEMICAL-STRUCTURE RELATED UTILITIES AND HELPERS
     250                 :             : */
     251                 :             : 
     252                 :             : 
     253                 :             : /****************************************************************************
     254                 :             :   Finds chemical symbol for element of given number.
     255                 :             :   Returns 0 if OK and -1 if element was not found.
     256                 :             : ****************************************************************************/
     257                 :        1182 : int get_element_chemical_symbol( int nAtNum, char *szElement )
     258                 :             : {
     259                 :        1182 :     nAtNum -= 1;
     260                 :             : 
     261         [ +  - ]:        1182 :     if ( 0 < nAtNum )
     262                 :             :     {
     263                 :        1182 :         nAtNum += 2; /*  bypass D, T */
     264                 :             :     }
     265                 :             : 
     266   [ +  -  +  - ]:        1182 :     if ( 0 <= nAtNum && nAtNum < nElDataLen )
     267                 :             :     {
     268                 :             :         /* valid element symbol found */
     269                 :        1182 :         strcpy(szElement, ElData[nAtNum].szElName);
     270                 :        1182 :         return 0;
     271                 :             :     }
     272                 :             : 
     273                 :             :     /* not found */
     274                 :           0 :     strcpy(szElement, "??");
     275                 :           0 :     return -1;
     276                 :             : }
     277                 :             : 
     278                 :             : 
     279                 :             : /****************************************************************************
     280                 :             : Finds symbol for element of given number.
     281                 :             : Accounts for (translates)pseudoelements.
     282                 :             : Returns 0 if OK and -1 if element was not found.
     283                 :             : ****************************************************************************/
     284                 :         264 : int get_element_or_pseudoelement_symbol( int nAtNum,
     285                 :             :                                          char *szElement )
     286                 :             : {
     287                 :         264 :     nAtNum -= 1;
     288                 :             : 
     289         [ +  + ]:         264 :     if ( 0 < nAtNum )
     290                 :             :     {
     291                 :         263 :         nAtNum += 2; /*  bypass D, T */
     292                 :             :     }
     293                 :             : 
     294   [ +  -  +  - ]:         264 :     if ( 0 <= nAtNum && nAtNum < nElDataLen )
     295                 :             :     {
     296                 :             :         /* valid element symbol found */
     297                 :         264 :         strcpy(szElement, ElData[nAtNum].szElName);
     298                 :             : 
     299         [ -  + ]:         264 :         if (!strcmp( szElement, "Zy" ))
     300                 :             :         {
     301                 :           0 :             strcpy(szElement, "Zz");
     302                 :             :         }
     303                 :             : 
     304                 :         264 :         return 0;
     305                 :             :     }
     306                 :             : 
     307                 :             :     /* not found */
     308                 :           0 :     strcpy(szElement, "??");
     309                 :             : 
     310                 :           0 :     return -1;
     311                 :             : }
     312                 :             : 
     313                 :             : 
     314                 :             : /****************************************************************************/
     315                 :        2027 : int el_number_in_internal_ref_table( const char* elname )
     316                 :             : {
     317                 :             :     int i;
     318                 :             :     const char* p;
     319                 :             : 
     320   [ +  -  +  + ]:       24532 :     for (i = 0; ( p = ElData[i].szElName )[0] && strcmp( p, elname ); i++)
     321                 :             :     {
     322                 :             :         ;
     323                 :             :     }
     324                 :             : 
     325         [ +  - ]:        2027 :     return p[0] ? i : ERR_ELEM;
     326                 :             : }
     327                 :             : 
     328                 :             : 
     329                 :             : /****************************************************************************
     330                 :             :   Get element number by symbol
     331                 :             : ****************************************************************************/
     332                 :        1238 : int get_periodic_table_number( const char* elname )
     333                 :             : {
     334                 :             :     int num;
     335                 :             : 
     336         [ -  + ]:        1238 :     if (elname == NULL)
     337                 :             :     {
     338                 :           0 :         return ERR_ELEM;
     339                 :             :     }
     340                 :             : 
     341         [ -  + ]:        1238 :     if (strlen(elname) == 0)
     342                 :             :     {
     343                 :           0 :         return ERR_ELEM;
     344                 :             :     }
     345                 :             : 
     346                 :             :     /* the single letter (common) elements */
     347         [ +  + ]:        1238 :     if (!elname[1])
     348                 :             :     {
     349   [ +  -  +  +  :        1014 :         switch (elname[0])
          +  -  -  +  -  
                      + ]
     350                 :             :         {
     351                 :           2 :             case 'H':
     352                 :           2 :                 return EL_NUMBER_H;
     353                 :             :                 break;
     354                 :           0 :             case 'B':
     355                 :           0 :                 return EL_NUMBER_B;
     356                 :             :                 break;
     357                 :         832 :             case 'C':
     358                 :         832 :                 return EL_NUMBER_C;
     359                 :             :                 break;
     360                 :          34 :             case 'N':
     361                 :          34 :                 return EL_NUMBER_N;
     362                 :             :                 break;
     363                 :         124 :             case 'O':
     364                 :         124 :                 return EL_NUMBER_O;
     365                 :             :                 break;
     366                 :           0 :             case 'P':
     367                 :           0 :                 return EL_NUMBER_P;
     368                 :             :                 break;
     369                 :           0 :             case 'S':
     370                 :           0 :                 return EL_NUMBER_S;
     371                 :             :                 break;
     372                 :          20 :             case 'F':
     373                 :          20 :                 return EL_NUMBER_F;
     374                 :             :                 break;
     375                 :           0 :             case 'I':
     376                 :           0 :                 return EL_NUMBER_I;
     377                 :             :                 break;
     378                 :             :         }
     379                 :             :     }
     380                 :             : 
     381                 :         226 :     num = el_number_in_internal_ref_table( elname );
     382                 :             : 
     383         [ +  - ]:         226 :     if ( num < ERR_ELEM )
     384                 :             :     {
     385                 :             :         /* account for D,T in internal table (but not Mendeleev's table) */
     386                 :         226 :         num = inchi_max( 1, num - 1 );
     387                 :             :     }
     388                 :             : 
     389                 :         226 :     return num;
     390                 :             : }
     391                 :             : 
     392                 :             : 
     393                 :             : /****************************************************************************
     394                 :             :   Check if no H addition allowed
     395                 :             : ****************************************************************************/
     396                 :        1182 : int if_skip_add_H( int nPeriodicNum )
     397                 :             : /* was called if_skip_add_H(, renamed to avoid confusion with other procedures   */
     398                 :             : {
     399                 :             :     return
     400         [ +  - ]:        1182 :         ElData[nPeriodicNum > 1 ? nPeriodicNum + 1 : 0].bSkipAddingH;
     401                 :             : }
     402                 :             : 
     403                 :             : 
     404                 :             : /****************************************************************************
     405                 :             :   Get reference value of atom valence at given charge
     406                 :             : ****************************************************************************/
     407                 :       14415 : int get_el_valence( int nPeriodicNum, int charge, int val_num )
     408                 :             : {
     409   [ +  -  +  -  :       14415 :     if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE || val_num >= MAX_NUM_VALENCES )
                   -  + ]
     410                 :             :     {
     411                 :           0 :         return 0;
     412                 :             :     }
     413                 :             : 
     414                 :             :     return
     415         [ +  + ]:       14415 :         ElData[nPeriodicNum > 1 ? nPeriodicNum + 1 : 0].cValence[NEUTRAL_STATE + charge][val_num];
     416                 :             : }
     417                 :             : 
     418                 :             : 
     419                 :             : /****************************************************************************
     420                 :             :     Output valence needed to unambiguosly reconstruct bonds
     421                 :             : ****************************************************************************/
     422                 :         617 : int get_unusual_el_valence( int nPeriodicNum,
     423                 :             :                             int charge,
     424                 :             :                             int radical,
     425                 :             :                             int bonds_valence,
     426                 :             :                             int num_H,
     427                 :             :                             int num_bonds )
     428                 :             : {
     429                 :             :     int i, num_found, chem_valence, rad_adj, known_chem_valence, exact_found;
     430                 :             : 
     431   [ +  +  -  + ]:         617 :     if ( !num_bonds && !num_H )
     432                 :             :     {
     433                 :           0 :         return 0;
     434                 :             :     }
     435                 :             : 
     436   [ +  -  -  + ]:         617 :     if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE )
     437                 :             :     {
     438         [ #  # ]:           0 :         if ( bonds_valence == num_bonds )
     439                 :             :         {
     440                 :           0 :             return 0; /* all single bonds */
     441                 :             :         }
     442                 :           0 :         return bonds_valence;
     443                 :             :     }
     444                 :             : 
     445   [ +  +  +  - ]:         617 :     if (!get_el_valence( nPeriodicNum, charge, 0 ) && bonds_valence == num_bonds)
     446                 :             :     {
     447                 :           1 :         return 0;
     448                 :             :     }
     449                 :             : 
     450                 :         616 :     chem_valence = bonds_valence + num_H;
     451                 :         616 :     rad_adj = 0;
     452                 :         616 :     num_found = 0;
     453                 :         616 :     exact_found = 0;
     454                 :             : 
     455                 :             :     /* Take into account a radical */
     456         [ -  + ]:         616 :     if ( radical == RADICAL_DOUBLET )
     457                 :             :     {
     458                 :           0 :         rad_adj = 1;
     459                 :             :     }
     460         [ -  + ]:         616 :     else if ( radical == RADICAL_TRIPLET )
     461                 :             :     {
     462                 :           0 :         rad_adj = 2;
     463                 :             :     }
     464                 :             : 
     465         [ +  + ]:         633 :     for ( i = 0; i < MAX_NUM_VALENCES; i++ )
     466                 :             :     {
     467   [ +  +  +  + ]:         631 :         if (0 < ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) - rad_adj ) &&
     468         [ +  - ]:         617 :              num_bonds <= known_chem_valence && known_chem_valence <= chem_valence)
     469                 :             :         {
     470                 :         617 :             num_found++;
     471         [ +  + ]:         617 :             if ( known_chem_valence == chem_valence )
     472                 :             :             {
     473                 :         614 :                 exact_found = 1;
     474                 :         614 :                 break;
     475                 :             :             }
     476                 :             :         }
     477                 :             :     }
     478                 :             : 
     479   [ +  +  +  + ]:         616 :     return ( exact_found && 1 == num_found ) ? 0 : chem_valence;
     480                 :             : }
     481                 :             : 
     482                 :             : 
     483                 :             : /****************************************************************************
     484                 :             :     Output valence needed to unambiguosly reconstruct number of H
     485                 :             : ****************************************************************************/
     486                 :        1182 : int needed_unusual_el_valence( int nPeriodicNum,
     487                 :             :                                int charge,
     488                 :             :                                int radical,
     489                 :             :                                int bonds_valence,
     490                 :             :                                int actual_bonds_valence,
     491                 :             :                                int num_H, int
     492                 :             :                                num_bonds )
     493                 :             : {
     494                 :             :     int chem_valence, num_H_expected; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     495                 :             :     char szElement[4];
     496                 :             : 
     497                 :             :     /*
     498                 :             :     if ( !num_bonds && !num_H )
     499                 :             :         return 0;
     500                 :             :     */
     501                 :             : 
     502   [ +  -  +  - ]:        1182 :     if (num_bonds && get_element_chemical_symbol( nPeriodicNum, szElement ) != -1)
     503                 :             :     {
     504                 :        1182 :         num_H_expected = get_num_H( szElement, 0, NULL, charge, radical, actual_bonds_valence, 0, 0, 0, 0 );
     505                 :             :     }
     506                 :             :     else
     507                 :             :     {
     508                 :           0 :         num_H_expected = num_H;
     509                 :             :     }
     510                 :             : 
     511                 :        1182 :     chem_valence = bonds_valence + num_H;
     512                 :             : 
     513                 :             : #if ( (BUILD_WITH_ENG_OPTIONS==1) && (SDF_OUTPUT_HETERO_VALENCE==1) )
     514                 :             :     if ((nPeriodicNum == 1 && chem_valence != 1) /* H */ || (nPeriodicNum == 6 && chem_valence != 4) /* C */ ||
     515                 :             :         (nPeriodicNum != 1 && nPeriodicNum != 6) || charge || radical) /* djb-rwth: addressing LLVM warning */
     516                 :             :     {
     517                 :             :         return chem_valence ? chem_valence : -1;
     518                 :             :     }
     519                 :             :     else
     520                 :             :     {
     521                 :             :         return 0;
     522                 :             :     }
     523                 :             : #else
     524                 :             :     {
     525                 :             :         int i, num_found, num_found_known, rad_adj, known_chem_valence, exact_found;
     526                 :             : 
     527   [ +  -  +  -  :        2364 :         if (charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE ||
                   +  - ]
     528         [ +  + ]:        2364 :              !get_el_valence( nPeriodicNum, charge, 0 ) ||
     529   [ +  +  -  + ]:        2362 :              if_skip_add_H( nPeriodicNum ) || bonds_valence != actual_bonds_valence ||
     530                 :             :              num_H_expected != num_H)
     531                 :             :         {
     532   [ +  +  +  -  :          22 :             if ( !num_H && !num_H_expected && bonds_valence == actual_bonds_valence )
                   -  + ]
     533                 :             :             {
     534                 :           0 :                 return 0; /* no H */
     535                 :             :             }
     536                 :          22 :             return chem_valence; /* needs to add H-atoms */
     537                 :             :         }
     538                 :             : 
     539                 :             :         /* take into account radical */
     540         [ -  + ]:        1160 :         if ( radical == RADICAL_DOUBLET )
     541                 :             :         {
     542                 :           0 :             rad_adj = 1;
     543                 :             :         }
     544         [ -  + ]:        1160 :         else if ( radical == RADICAL_TRIPLET )
     545                 :             :         {
     546                 :           0 :             rad_adj = 2;
     547                 :             :         }
     548                 :             :         else
     549                 :             :         {
     550                 :        1160 :             rad_adj = 0;
     551                 :             :         }
     552                 :             : 
     553                 :        1160 :         num_found_known = 0;
     554                 :        1160 :         num_found = 0;
     555                 :        1160 :         exact_found = 0;
     556                 :             : 
     557         [ +  - ]:        1160 :         for ( i = 0; i < MAX_NUM_VALENCES; i++ )
     558                 :             :         {
     559         [ +  - ]:        1160 :             if (0 < ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) ) &&
     560         [ +  - ]:        1160 :                  bonds_valence <= ( known_chem_valence -= rad_adj ))
     561                 :             :             {
     562                 :             :                 /* found known valence that fits without H */
     563                 :        1160 :                 num_found_known++;
     564         [ +  - ]:        1160 :                 if ( known_chem_valence <= chem_valence )
     565                 :             :                 {
     566                 :             :                     /* known valence is large enough to accommodate (implicit) H */
     567                 :        1160 :                     num_found++;
     568                 :             :                 }
     569         [ +  - ]:        1160 :                 if ( known_chem_valence == chem_valence )
     570                 :             :                 {
     571                 :        1160 :                     exact_found = 1;
     572                 :        1160 :                     break;
     573                 :             :                 }
     574                 :             :             }
     575                 :             :         }
     576                 :             : 
     577   [ +  -  -  + ]:        1160 :         return ( exact_found && 1 == num_found && 1 == num_found_known )
     578                 :             :             ? 0
     579   [ +  -  -  - ]:        2320 :             : chem_valence ? chem_valence : -1;    /* needs zero */
     580                 :             :     }
     581                 :             : #endif
     582                 :             : }
     583                 :             : 
     584                 :             : 
     585                 :             : /****************************************************************************
     586                 :             :     Output valence that does not fit any known valences
     587                 :             : ****************************************************************************/
     588                 :        3931 : int detect_unusual_el_valence( int nPeriodicNum,
     589                 :             :                                int charge,
     590                 :             :                                int radical,
     591                 :             :                                int bonds_valence,
     592                 :             :                                int num_H,
     593                 :             :                                int num_bonds )
     594                 :             : {
     595                 :             :     int i, chem_valence, rad_adj, known_chem_valence;
     596                 :             : 
     597   [ +  +  +  - ]:        3931 :     if ( !num_bonds && !num_H )
     598                 :             :     {
     599                 :           4 :         return 0;
     600                 :             :     }
     601                 :             : 
     602   [ +  -  -  + ]:        3927 :     if ( charge < MIN_ATOM_CHARGE || charge > MAX_ATOM_CHARGE )
     603                 :             :     {
     604         [ #  # ]:           0 :         if ( bonds_valence == num_bonds )
     605                 :             :         {
     606                 :           0 :             return 0; /* all single bonds */
     607                 :             :         }
     608                 :           0 :         return bonds_valence;
     609                 :             :     }
     610                 :             : 
     611   [ +  +  +  - ]:        3927 :     if (!get_el_valence( nPeriodicNum, charge, 0 ) && bonds_valence == num_bonds)
     612                 :             :     {
     613                 :           4 :         return 0;
     614                 :             :     }
     615                 :             : 
     616                 :        3923 :     chem_valence = bonds_valence + num_H;
     617                 :        3923 :     rad_adj = 0;
     618                 :             : 
     619                 :             :     /* take into account radical */
     620         [ -  + ]:        3923 :     if ( radical == RADICAL_DOUBLET )
     621                 :             :     {
     622                 :           0 :         rad_adj = 1;
     623                 :             :     }
     624   [ +  -  -  + ]:        3923 :     else if ( radical == RADICAL_TRIPLET || radical == RADICAL_SINGLET )
     625                 :             :     {
     626                 :           0 :         rad_adj = 2;
     627                 :             :     }
     628                 :             : 
     629         [ +  + ]:        4043 :     for ( i = 0; i < MAX_NUM_VALENCES; i++ )
     630                 :             :     {
     631         [ +  + ]:        4026 :         if (0 < ( known_chem_valence = get_el_valence( nPeriodicNum, charge, i ) - rad_adj ))
     632                 :             :         {
     633         [ +  + ]:        3961 :             if ( known_chem_valence == chem_valence )
     634                 :             :             {
     635                 :        3906 :                 return 0;
     636                 :             :             }
     637                 :             :         }
     638                 :             :     }
     639                 :             : 
     640                 :          17 :     return chem_valence;
     641                 :             : }
     642                 :             : 
     643                 :             : 
     644                 :             : /****************************************************************************
     645                 :             :  Return element type
     646                 :             : ****************************************************************************/
     647                 :        1790 : int get_el_type( int nPeriodicNum )
     648                 :             : {
     649                 :        1790 :     return ElData[nPeriodicNum + 1].nType;
     650                 :             : }
     651                 :             : 
     652                 :             : 
     653                 :             : /****************************************************************************
     654                 :             :  Check if element is metal
     655                 :             : ****************************************************************************/
     656                 :        6214 : int is_el_a_metal( int nPeriodicNum )
     657                 :             : {
     658                 :        6214 :     return 0 != ( ElData[nPeriodicNum + 1].nType & IS_METAL );
     659                 :             : }
     660                 :             : 
     661                 :             : 
     662                 :             : /*#ifndef TARGET_API_LIB*/
     663                 :             : 
     664                 :             : 
     665                 :             : /****************************************************************************
     666                 :             :  Extract radicals and charges
     667                 :             : ****************************************************************************/
     668                 :           0 : int extract_charges_and_radicals( char *elname, int *pnRadical, int *pnCharge )
     669                 :             : {
     670                 :             :     char *q, *r, *p;
     671                 :           0 :     int  nCharge = 0, nRad = 0, charge_len = 0, k, nVal, nSign, nLastSign = 1; /* djb-rwth: removing redundant variables */
     672                 :             : 
     673                 :           0 :     p = elname;
     674                 :             : 
     675                 :             :     /*  extract radicals & charges */
     676         [ #  # ]:           0 :     while ( (q = strpbrk(p, "+-^")) ) /* djb-rwth: addressing LLVM warning */
     677                 :             :     {
     678      [ #  #  # ]:           0 :         switch ( *q )
     679                 :             :         {
     680                 :           0 :             case '+':
     681                 :             :             case '-':
     682   [ #  #  #  # ]:           0 :                 for (k = 0, nVal = 0; ( nSign = ( '+' == q[k] ) ) || ( nSign = -( '-' == q[k] ) ); k++)
     683                 :             :                 {
     684                 :           0 :                     nVal += ( nLastSign = nSign );
     685                 :           0 :                     charge_len++;
     686                 :             :                 }
     687         [ #  # ]:           0 :                 if ((nSign = (int)strtol(q + k, &r, 10))) /* djb-rwth: addressing LLVM warning */
     688                 :             :                 {
     689                 :             :                     /*  fixed 12-5-2001 */
     690                 :           0 :                     nVal += nLastSign * ( nSign - 1 );
     691                 :             :                 }
     692                 :           0 :                 charge_len = (int) ( r - q );
     693                 :           0 :                 nCharge += nVal;
     694                 :           0 :                 break;
     695                 :             :             /* case '.': */ /*  singlet '.' may be confused with '.' in formulas like CaO.H2O */
     696                 :           0 :             case '^':
     697                 :           0 :                 nRad = 1; /* doublet here is 1. See below */
     698                 :           0 :                 charge_len = 1;
     699         [ #  # ]:           0 :                 for (k = 1; q[0] == q[k]; k++)
     700                 :             :                 {
     701                 :           0 :                     nRad++;
     702                 :           0 :                     charge_len++;
     703                 :             :                 }
     704                 :           0 :                 break;
     705                 :             :         }
     706                 :           0 :         memmove(q, q + charge_len, strlen(q + charge_len) + 1);
     707                 :             :     }
     708                 :             : 
     709                 :             :     /* djb-rwth: removing redundant code */
     710                 :             : 
     711                 :             :     /*  radical */
     712   [ #  #  #  # ]:           0 :     if (( q = strrchr( p, ':' ) ) && !q[1])
     713                 :             :     {
     714                 :           0 :         nRad = RADICAL_SINGLET;
     715                 :           0 :         q[0] = '\0';
     716                 :             :         /* djb-rwth: removing redundant code */
     717                 :             :     }
     718                 :             :     else
     719                 :             :     {
     720   [ #  #  #  # ]:           0 :         while (( q = strrchr( p, '.' ) ) && !q[1])
     721                 :             :         {
     722                 :           0 :             nRad++;
     723                 :           0 :             q[0] = '\0';
     724                 :             :             /* djb-rwth: removing redundant code */
     725                 :             :         }
     726                 :             : 
     727         [ #  # ]:           0 :         nRad = nRad == 1 ? RADICAL_DOUBLET :
     728         [ #  # ]:           0 :             nRad == 2 ? RADICAL_TRIPLET : 0;
     729                 :             :     }
     730                 :             : 
     731                 :           0 :     *pnRadical = nRad;
     732                 :           0 :     *pnCharge = nCharge;
     733                 :             : 
     734   [ #  #  #  # ]:           0 :     return ( nRad || nCharge );
     735                 :             : }
     736                 :             : 
     737                 :             : 
     738                 :             : /*#endif*/
     739                 :             : 
     740                 :             : 
     741                 :             : /****************************************************************************/
     742                 :           0 : int extract_H_atoms( char *elname, S_CHAR num_iso_H[] )
     743                 :             : {
     744                 :             :     int i, len, c, k, num_H, val;
     745                 :             :     char* q;
     746                 :           0 :     char elname1 = '\0';
     747                 :             : 
     748                 :           0 :     i = 0;
     749                 :           0 :     num_H = 0;
     750                 :           0 :     len = (int) strlen( elname );
     751                 :           0 :     c = UCINT elname[0];
     752                 :             : 
     753         [ #  # ]:           0 :     if ( len > 1 )
     754                 :             :     {
     755                 :           0 :         elname1 = elname[1];
     756                 :             :     }
     757                 :             : 
     758         [ #  # ]:           0 :     while ( i < len )
     759                 :             :     {
     760   [ #  #  #  # ]:           0 :         switch ( c )
     761                 :             :         {
     762                 :           0 :             case 'H':
     763                 :           0 :                 k = 0;
     764                 :           0 :                 break;
     765                 :           0 :             case 'D':
     766                 :           0 :                 k = 1;
     767                 :           0 :                 break;
     768                 :           0 :             case 'T':
     769                 :           0 :                 k = 2;
     770                 :           0 :                 break;
     771                 :           0 :             default:
     772                 :           0 :                 k = -1;
     773                 :           0 :                 break;
     774                 :             :         }
     775                 :             : 
     776                 :           0 :         q = elname + i + 1; /*  pointer to the next to elname[i] character */
     777                 :           0 :         c = UCINT q[0];
     778                 :             : 
     779   [ #  #  #  # ]:           0 :         if (k >= 0 && !islower( c ))
     780                 :             :         {
     781                 :             :             /*  found a hydrogen */
     782         [ #  # ]:           0 :             if (isdigit( c ))
     783                 :             :             {
     784                 :           0 :                 val = (int) strtol( q, &q, 10 );
     785                 :             :                 /*  q = pointer to the next to number of hydrogen atom(s) character */
     786                 :             :             }
     787                 :             :             else
     788                 :             :             {
     789                 :           0 :                 val = 1;
     790                 :             :             }
     791         [ #  # ]:           0 :             if ( k )
     792                 :             :             {
     793                 :           0 :                 num_iso_H[k] += val;
     794                 :             :             }
     795                 :             :             else
     796                 :             :             {
     797                 :           0 :                 num_H += val;
     798                 :             :             }
     799                 :             : 
     800                 :             :             /*  remove the hydrogen atom from the string */
     801                 :           0 :             len -= (int) ( q - elname ) - i;
     802                 :           0 :             memmove(elname + i, q, (long long)len + 1); /* djb-rwth: cast operator added */
     803                 :             :             /*  c =  UCINT elname[i]; */
     804                 :             :         }
     805                 :             :         else
     806                 :             :         {
     807                 :           0 :             i++;
     808                 :             :         }
     809                 :             : 
     810                 :           0 :         c = UCINT elname[i]; /*  moved here 11-04-2002 */
     811                 :             :     }
     812                 :             : 
     813                 :           0 :     len = (int) strlen( elname );
     814         [ #  # ]:           0 :     if (len == 2)
     815                 :             :     {
     816         [ #  # ]:           0 :         if ( elname[1] != elname1 )
     817                 :             :             /* Error, incorrect 2nd char of elname appears after 'subtracting' {H,D,T}  */
     818                 :             :             /* See a bug reported to inchi-discuss by A. Dalke for alias atom "pH4d"    */
     819                 :             :             /*^^^ 2017-01-06                                                            */
     820                 :           0 :             elname[1] = '?';
     821                 :             :     }
     822                 :             : 
     823                 :           0 :     return num_H;
     824                 :             : }
     825                 :             : 
     826                 :             : 
     827                 :             : /****************************************************************************
     828                 :             :  Return number of attached hydrogens
     829                 :             : ****************************************************************************/
     830                 :        1801 : int get_num_H( const char* elname,
     831                 :             :                 int inp_num_H,
     832                 :             :                 S_CHAR inp_num_iso_H[],
     833                 :             :                 int charge,
     834                 :             :                 int radical,
     835                 :             :                 int chem_bonds_valence,
     836                 :             :                 int atom_input_valence,
     837                 :             :                 int bAliased,
     838                 :             :                 int bDoNotAddH,
     839                 :             :                 int bHasMetalNeighbor )
     840                 :             : {
     841                 :        1801 :     int val, i, el_number, num_H = 0, num_iso_H;
     842                 :             :     static int intl_el_number_N = 0, intl_el_number_S=0, intl_el_number_O=0, intl_el_number_C=0;
     843                 :             : 
     844         [ +  + ]:        1801 :     if ( !intl_el_number_N )
     845                 :             :     {
     846                 :           3 :         intl_el_number_N = el_number_in_internal_ref_table( "N" );
     847                 :             :     }
     848         [ +  + ]:        1801 :     if ( !intl_el_number_S )
     849                 :             :     {
     850                 :           3 :         intl_el_number_S = el_number_in_internal_ref_table( "S" );
     851                 :             :     }
     852         [ +  + ]:        1801 :     if ( !intl_el_number_O )
     853                 :             :     {
     854                 :           3 :         intl_el_number_O = el_number_in_internal_ref_table( "O" );
     855                 :             :     }
     856         [ +  + ]:        1801 :     if ( !intl_el_number_C )
     857                 :             :     {
     858                 :           3 :         intl_el_number_C = el_number_in_internal_ref_table( "C" );
     859                 :             :     }
     860                 :             : 
     861                 :             : 
     862                 :             :     /*  atom_input_valence (cValence) cannot be specified in case of */
     863                 :             :     /*  aliased MOLFile atom with known inp_num_H or inp_num_iso_H[] */
     864                 :             : 
     865         [ -  + ]:        1801 :     if ( bAliased )
     866                 :             :     {
     867                 :           0 :         num_H = inp_num_H;
     868                 :             :     }
     869   [ +  +  -  +  :        1801 :     else if (atom_input_valence && ( atom_input_valence != 15 || chem_bonds_valence ))
                   -  - ]
     870                 :             :     {
     871                 :          12 :         num_H = inchi_max( 0, atom_input_valence - chem_bonds_valence );
     872                 :             :     }
     873   [ -  +  -  - ]:        1789 :     else if ( atom_input_valence == 15 && !chem_bonds_valence )
     874                 :             :     {
     875                 :           0 :         num_H = 0;
     876                 :             :     }
     877   [ +  -  +  - ]:        1789 :     else if (MIN_ATOM_CHARGE <= charge &&
     878                 :        1789 :               MAX_ATOM_CHARGE >= charge &&
     879         [ +  - ]:        1789 :               ERR_ELEM != ( el_number = el_number_in_internal_ref_table( elname ) ) &&
     880   [ +  +  +  - ]:        1789 :               !ElData[el_number].bSkipAddingH && !bDoNotAddH)
     881                 :             :     {
     882                 :             :         /* add hydrogen atoms according to standard element valence */
     883   [ -  +  -  - ]:        1780 :         if ( radical && radical != RADICAL_SINGLET )
     884                 :             :         {
     885         [ #  # ]:           0 :             if ( (val = ElData[el_number].cValence[NEUTRAL_STATE + charge][0]) ) /* djb-rwth: addressing LLVM warning */
     886                 :             :             {
     887                 :           0 :                 val -= ( radical == RADICAL_DOUBLET ) ? 1
     888   [ #  #  #  #  :           0 :                     : ( radical == RADICAL_SINGLET || radical == RADICAL_TRIPLET ) ? 2 : val;
                   #  # ]
     889                 :             :                 /* if unknown radical then do not add H */
     890                 :           0 :                 num_H = inchi_max( 0, val - chem_bonds_valence );
     891                 :             :             }
     892                 :             :         }
     893                 :             :         else
     894                 :             :         {
     895                 :             :             /* find the smallest valence that is greater than the sum of the chemical bond valences */
     896                 :        1780 :             for (i = 0;
     897   [ +  -  -  + ]:        1780 :                  ( val = ElData[el_number].cValence[NEUTRAL_STATE + charge][i] ) &&
     898                 :             :                  val < chem_bonds_valence;
     899                 :           0 :                  i++)
     900                 :             :             {
     901                 :             :                 ;
     902                 :             :             }
     903                 :             : 
     904                 :             :             /* special case: do not add H to N(IV), S(III), S+(II), S-(II) */ /* S ions added 2004-05-10 */
     905   [ +  +  +  -  :        1780 :             if ( el_number == intl_el_number_N && !charge && !radical && val == 5 )
             +  -  -  + ]
     906                 :             :             {
     907                 :           0 :                 val = 3;
     908                 :             :             }
     909                 :             :             /*else if ( el_number == el_number_N && !charge && !radical && val == 3 &&
     910                 :             :                  chem_bonds_valence == 2 && bHasMetalNeighbor )
     911                 :             :               {
     912                 :             :               val = 2;
     913                 :             :               }
     914                 :             :             */
     915   [ -  +  -  -  :        1780 :             else if ( el_number == intl_el_number_S && !charge && !radical && val == 4 && chem_bonds_valence == 3 )
          -  -  -  -  -  
                      - ]
     916                 :             :             {
     917                 :           0 :                 val = 3;
     918                 :             :             }
     919   [ -  +  -  -  :        1780 :             else if ( bHasMetalNeighbor && el_number != intl_el_number_C && val > 0 )
                   -  - ]
     920                 :             :             {
     921                 :           0 :                 val--;
     922                 :             :             }
     923                 :             :             /*
     924                 :             :             if ( (el_number == el_number_S || el_number == el_number_O) &&
     925                 :             :                  abs(charge)==1 && !radical && val == 3 && chem_bonds_valence == 2 && bHasMetalNeighbor )
     926                 :             :               {
     927                 :             :               val = 2;
     928                 :             :               }
     929                 :             :             else
     930                 :             :             */
     931                 :             : 
     932                 :        1780 :             num_H = inchi_max( 0, val - chem_bonds_valence );
     933                 :             :         }
     934                 :             : 
     935                 :        1780 :         num_iso_H = 0;
     936         [ +  + ]:        1780 :         if ( inp_num_iso_H )
     937                 :             :         {
     938         [ +  + ]:        2400 :             for ( i = 0; i < NUM_H_ISOTOPES; i++ )
     939                 :             :             {
     940                 :        1800 :                 num_iso_H += inp_num_iso_H[i];
     941                 :             :             }
     942                 :             :         }
     943                 :             : 
     944                 :             :         /*  should not happen because atom here is not aliased */
     945         [ -  + ]:        1780 :         if ( num_iso_H )
     946                 :             :         {
     947         [ #  # ]:           0 :             if ( num_H >= num_iso_H )
     948                 :             :             {
     949                 :           0 :                 num_H -= num_iso_H;
     950                 :             :             }
     951                 :             :             else
     952                 :             :             {
     953                 :           0 :                 num_H = inp_num_H; /*  as requested in the alias */
     954                 :             :                 /* num_H = (num_iso_H - num_H) % 2; */ /*  keep unchanged parity of the total number of H atoms */
     955                 :             :             }
     956                 :             :         }
     957                 :             : 
     958                 :             :         /*  should not happen because atom here is not aliased */
     959         [ -  + ]:        1780 :         if ( inp_num_H > num_H )
     960                 :             :         {
     961                 :           0 :             num_H = inp_num_H;  /*  as requested in the alias */
     962                 :             :             /* num_H = inp_num_H + (inp_num_H - num_H)%2; */ /*  keep unchanged parity of the number of non-isotopic H atoms */
     963                 :             :         }
     964                 :             :     }
     965                 :             :     else
     966                 :             :     {
     967                 :           9 :         num_H = inp_num_H;
     968                 :             :     }
     969                 :             : 
     970                 :        1801 :     return num_H;
     971                 :             : }
     972                 :             : 
     973                 :             : 
     974                 :             : /****************************************************************************/
     975                 :           0 : int get_atomic_mass_from_elnum( int nAtNum )
     976                 :             : {
     977                 :           0 :     nAtNum -= 1;
     978                 :             : 
     979         [ #  # ]:           0 :     if ( 0 < nAtNum )
     980                 :             :     {
     981                 :           0 :         nAtNum += 2; /*  bypass D, T */
     982                 :             :     }
     983                 :             : 
     984   [ #  #  #  # ]:           0 :     if ( 0 <= nAtNum && nAtNum < nElDataLen )
     985                 :             :     {
     986                 :           0 :         return (int) ElData[nAtNum].nAtMass;
     987                 :             :     }
     988                 :             : 
     989                 :           0 :     return 0;
     990                 :             : }
     991                 :             : 
     992                 :             : 
     993                 :             : /****************************************************************************
     994                 :             : int get_mw(char elname[])
     995                 :             : {
     996                 :             :     int i;
     997                 :             : 
     998                 :             :     for (i=0; i<NUMEL; i++)
     999                 :             :         if (strcmp(elname,elements[i])==0)
    1000                 :             :             return(atomic_wt[i]);
    1001                 :             :     return(0);
    1002                 :             : }
    1003                 :             : ****************************************************************************/
    1004                 :             : 
    1005                 :             : 
    1006                 :             : 
    1007                 :             : /****************************************************************************/
    1008                 :           0 : int get_atomic_mass( const char *elname )
    1009                 :             : {
    1010                 :             :     int el_number, atw;
    1011         [ #  # ]:           0 :     if (ERR_ELEM != ( el_number = el_number_in_internal_ref_table( elname ) ))
    1012                 :             :     {
    1013                 :           0 :         atw = ElData[el_number].nAtMass;
    1014                 :             :     }
    1015                 :             :     else
    1016                 :             :     {
    1017                 :           0 :         atw = 0;
    1018                 :             :     }
    1019                 :             : 
    1020                 :           0 :     return atw;
    1021                 :             : }
    1022                 :             : 
    1023                 :             : 
    1024                 :             : /****************************************************************************
    1025                 :             :   Check if atom is in the list
    1026                 :             : ****************************************************************************/
    1027                 :        2274 : AT_NUMB *is_in_the_list( AT_NUMB *pathAtom, AT_NUMB nNextAtom, int nPathLen )
    1028                 :             : {
    1029   [ +  +  +  + ]:        4533 :     for ( ; nPathLen && *pathAtom != nNextAtom; nPathLen--, pathAtom++ )
    1030                 :             :     {
    1031                 :             :         ;
    1032                 :             :     }
    1033         [ +  + ]:        2274 :     return nPathLen ? pathAtom : NULL;
    1034                 :             : }
    1035                 :             : 
    1036                 :             : /****************************************************************************
    1037                 :             :   Check if integer is in the list
    1038                 :             : ****************************************************************************/
    1039                 :           0 : int *is_in_the_ilist( int *pathAtom, int nNextAtom, int nPathLen )
    1040                 :             : {
    1041   [ #  #  #  # ]:           0 :     for ( ; nPathLen && *pathAtom != nNextAtom; nPathLen--, pathAtom++ )
    1042                 :             :     {
    1043                 :             :         ;
    1044                 :             :     }
    1045         [ #  # ]:           0 :     return nPathLen ? pathAtom : NULL;
    1046                 :             : }
    1047                 :             : 
    1048                 :             : 
    1049                 :             : /****************************************************************************
    1050                 :             :   Check if list (of integers) is within the embedding list2
    1051                 :             : ****************************************************************************/
    1052                 :           0 : int is_ilist_inside( int *ilist, int nlist, int *ilist2, int nlist2 )
    1053                 :             : {
    1054                 :             :     int k;
    1055         [ #  # ]:           0 :     for ( k = 0; k < nlist; k++ )
    1056                 :             :     {
    1057         [ #  # ]:           0 :         if (!is_in_the_ilist( ilist2, ilist[k], nlist2 ))
    1058                 :             :         {
    1059                 :           0 :             return 0;
    1060                 :             :         }
    1061                 :             :     }
    1062                 :           0 :     return 1;
    1063                 :             : }
    1064                 :             : 
    1065                 :             : 
    1066                 :             : /****************************************************************************/
    1067                 :           0 : int nBondsValToMetal( inp_ATOM* at, int iat )
    1068                 :             : {
    1069                 :           0 :     int i, bond_type, nVal2Metal = 0; /* djb-rwth: removing redundant variables */
    1070                 :           0 :     inp_ATOM* a = at + iat;
    1071                 :             : 
    1072         [ #  # ]:           0 :     for ( i = 0; i < a->valence; i++ )
    1073                 :             :     {
    1074                 :             :         /* djb-rwth: removing redundant code */
    1075                 :             : 
    1076         [ #  # ]:           0 :         if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
    1077                 :             :         {
    1078                 :           0 :             bond_type = a->bond_type[i];
    1079                 :             : 
    1080         [ #  # ]:           0 :             if ( bond_type <= BOND_TYPE_TRIPLE )
    1081                 :             :             {
    1082                 :           0 :                 nVal2Metal += bond_type;
    1083                 :             :             }
    1084                 :             :             else
    1085                 :             :             {
    1086                 :           0 :                 return -1;  /* bond to metal order is not well defined */
    1087                 :             :             }
    1088                 :             :         }
    1089                 :             :     }
    1090                 :             : 
    1091                 :           0 :     return nVal2Metal;
    1092                 :             : }
    1093                 :             : 
    1094                 :             : 
    1095                 :             : /****************************************************************************/
    1096                 :           4 : int num_of_H( inp_ATOM *at, int iat )
    1097                 :             : {
    1098                 :             :     static int el_number_H = (int)EL_NUMBER_H;
    1099                 :           4 :     int    i, n, num_explicit_H = 0;
    1100                 :           4 :     inp_ATOM *a = at + iat;
    1101                 :             : 
    1102         [ +  + ]:          20 :     for (i = 0; i < a->valence; i++)
    1103                 :             :     {
    1104                 :          16 :         n = a->neighbor[i];
    1105   [ +  -  -  + ]:          16 :         num_explicit_H += ( 1 == at[n].valence && el_number_H == at[n].el_number );
    1106                 :             :     }
    1107                 :             : 
    1108                 :           4 :     return num_explicit_H + NUMH( at, iat );
    1109                 :             : }
    1110                 :             : 
    1111                 :             : /****************************************************************************/
    1112                 :             : /* Get the element group of an element. The base element rather than the    */
    1113                 :             : /* periodic group is used to aid readability.                               */
    1114                 :             : /* - NitrogenGroup = 7 (EL_NUMBER_N)                                        */
    1115                 :             : /* - OxygenGroup   = 8 (EL_NUMBER_O)                                        */
    1116                 :             : /* - Cargbon       = 6 (EL_NUMBER_C)                                        */
    1117                 :             : /****************************************************************************/
    1118                 :          10 : U_CHAR ion_el_group( int el )
    1119                 :             : {
    1120   [ +  -  -  + ]:          10 :     switch ( el )
    1121                 :             :     {
    1122                 :           4 :         case EL_NUMBER_C: /* fallthrough */
    1123                 :             : #if ( FIX_REM_ION_PAIRS_Si_BUG == 1 )
    1124                 :             :         case EL_NUMBER_SI:
    1125                 :             : #endif
    1126                 :           4 :             return EL_NUMBER_C;
    1127                 :           0 :         case EL_NUMBER_N: /* fallthrough */
    1128                 :             :         case EL_NUMBER_P:
    1129                 :             :         case EL_NUMBER_AS:
    1130                 :             :         case EL_NUMBER_SB:
    1131                 :           0 :             return EL_NUMBER_N;
    1132                 :           0 :         case EL_NUMBER_O: /* fallthrough */
    1133                 :             :         case EL_NUMBER_S:
    1134                 :             :         case EL_NUMBER_SE:
    1135                 :             :         case EL_NUMBER_TE:
    1136                 :           0 :             return EL_NUMBER_O;
    1137                 :           6 :         default:
    1138                 :           6 :             return 0;
    1139                 :             :     }
    1140                 :             : }
    1141                 :             : 
    1142                 :           0 : int has_other_ion_neigh( inp_ATOM *at,
    1143                 :             :                          int iat,
    1144                 :             :                          int iat_ion_neigh)
    1145                 :             : {
    1146                 :           0 :     int charge = at[iat_ion_neigh].charge;
    1147                 :             :     int i, neigh;
    1148                 :             : 
    1149         [ #  # ]:           0 :     for ( i = 0; i < at[iat].valence; i++ )
    1150                 :             :     {
    1151                 :           0 :         neigh = at[iat].neighbor[i];
    1152                 :             : 
    1153   [ #  #  #  #  :           0 :         if (neigh != iat_ion_neigh && at[neigh].charge == charge &&
                   #  # ]
    1154                 :           0 :             ion_el_group( at[neigh].el_number ))
    1155                 :             :         {
    1156                 :           0 :             return 1;
    1157                 :             :         }
    1158                 :             :     }
    1159                 :             : 
    1160                 :           0 :     return 0;
    1161                 :             : }
    1162                 :             : 
    1163                 :             : 
    1164                 :             : /****************************************************************************
    1165                 :             :   Check if has_other_ion_in_sphere_2
    1166                 :             :     BFS r=2
    1167                 :             : ****************************************************************************/
    1168                 :           0 : int has_other_ion_in_sphere_2( inp_ATOM *at, int iat,
    1169                 :             :                                int iat_ion_neigh )
    1170                 :             : {
    1171                 :             : #define MAXQ 16
    1172                 :             :     AT_NUMB q[MAXQ];
    1173                 :           0 :     int lenq = 0, lenq2, dist = 0, i = 0, iq, neigh, j, nRet = 0;
    1174                 :           0 :     q[lenq++] = iat;
    1175                 :           0 :     at[iat].cFlags = 1;
    1176                 :             : 
    1177                 :           0 :     iq = 0;
    1178                 :           0 :     dist = 1;
    1179                 :             :     /* use at->cFlags as an indicator */
    1180                 :             : 
    1181         [ #  # ]:           0 :     while ( dist <= 2 )
    1182                 :             :     {
    1183         [ #  # ]:           0 :         for ( lenq2 = lenq; iq < lenq2; iq++ )
    1184                 :             :         {
    1185                 :           0 :             i = q[iq];
    1186                 :             : 
    1187         [ #  # ]:           0 :             for ( j = 0; j < at[i].valence; j++ )
    1188                 :             :             {
    1189                 :           0 :                 neigh = at[i].neighbor[j];
    1190                 :             : 
    1191         [ #  # ]:           0 :                 if (!at[neigh].cFlags &&
    1192   [ #  #  #  # ]:           0 :                      at[neigh].valence <= 3 &&
    1193                 :           0 :                      ion_el_group( at[neigh].el_number ))
    1194                 :             :                 {
    1195                 :           0 :                     q[lenq++] = neigh;
    1196                 :           0 :                     at[neigh].cFlags = 1;
    1197         [ #  # ]:           0 :                     if (neigh != iat_ion_neigh &&
    1198         [ #  # ]:           0 :                          at[iat_ion_neigh].charge == at[neigh].charge)
    1199                 :             :                     {
    1200                 :           0 :                         nRet++;
    1201                 :             :                     }
    1202                 :             :                 }
    1203                 :             :             }
    1204                 :             :         }
    1205                 :             : 
    1206                 :           0 :         dist++;
    1207                 :             :     }
    1208                 :             : 
    1209         [ #  # ]:           0 :     for ( iq = 0; iq < lenq; iq++ )
    1210                 :             :     {
    1211                 :           0 :         i = q[iq];
    1212                 :           0 :         at[i].cFlags = 0;
    1213                 :             :     }
    1214                 :             : 
    1215                 :           0 :     return nRet;
    1216                 :             : }
    1217                 :             : 
    1218                 :             : 
    1219                 :             : /****************************************************************************/
    1220                 :         144 : int nNoMetalNumBonds( inp_ATOM *at, int at_no )
    1221                 :             : {
    1222                 :             :     int i;
    1223                 :             : 
    1224                 :         144 :     inp_ATOM *a = at + at_no;
    1225                 :         144 :     int num_H = NUMH( a, 0 );
    1226                 :         144 :     int std_chem_bonds_valence = get_el_valence( a->el_number, a->charge, 0 );
    1227                 :             : 
    1228         [ +  + ]:         144 :     if ( a->chem_bonds_valence + num_H > std_chem_bonds_valence )
    1229                 :             :     {
    1230                 :          72 :         int valence_to_metal = 0;
    1231                 :          72 :         int num_bonds_to_metal = 0;
    1232                 :             : 
    1233         [ +  + ]:         280 :         for ( i = 0; i < a->valence; i++ )
    1234                 :             :         {
    1235         [ +  + ]:         272 :             if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
    1236                 :             :             {
    1237         [ +  - ]:          64 :                 if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
    1238                 :             :                 {
    1239                 :          64 :                     return a->valence; /* fall back */
    1240                 :             :                 }
    1241                 :           0 :                 num_bonds_to_metal++;
    1242                 :           0 :                 valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
    1243                 :             :             }
    1244                 :             :         }
    1245                 :             : 
    1246         [ -  + ]:           8 :         if ( a->chem_bonds_valence + num_H - valence_to_metal == std_chem_bonds_valence )
    1247                 :             :         {
    1248                 :             :             /* removing bonds to metal produces standard valence */
    1249                 :           0 :             return a->valence - num_bonds_to_metal;
    1250                 :             :         }
    1251                 :             :     }
    1252                 :             : 
    1253                 :             : #if ( S_VI_O_PLUS_METAL_FIX_BOND == 1 )
    1254                 :             :     else
    1255                 :             :     {
    1256   [ -  +  -  - ]:          72 :         if (1 == a->charge && 2 == get_endpoint_valence( a->el_number ) &&
    1257         [ #  # ]:           0 :                 a->chem_bonds_valence + num_H == std_chem_bonds_valence)
    1258                 :             :         {
    1259                 :           0 :             int valence_to_metal = 0;
    1260                 :           0 :             int num_bonds_to_metal = 0;
    1261         [ #  # ]:           0 :             for ( i = 0; i < a->valence; i++ )
    1262                 :             :             {
    1263         [ #  # ]:           0 :                 if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
    1264                 :             :                 {
    1265         [ #  # ]:           0 :                     if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
    1266                 :             :                     {
    1267                 :           0 :                         return a->valence; /* fall back */
    1268                 :             :                     }
    1269                 :           0 :                     num_bonds_to_metal++;
    1270                 :           0 :                     valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
    1271                 :             :                 }
    1272                 :             :             }
    1273         [ #  # ]:           0 :             if ( 1 == valence_to_metal )
    1274                 :             :             {
    1275                 :             :                 /* removing bonds to metal produces standard valence */
    1276                 :           0 :                 return a->valence - num_bonds_to_metal;
    1277                 :             :             }
    1278                 :             :         }
    1279                 :             :     }
    1280                 :             : #endif
    1281                 :             : 
    1282                 :          80 :     return a->valence;
    1283                 :             : }
    1284                 :             : 
    1285                 :             : 
    1286                 :             : /****************************************************************************/
    1287                 :           4 : int nNoMetalBondsValence( inp_ATOM *at, int at_no )
    1288                 :             : {
    1289                 :             :     int i;
    1290                 :             : 
    1291                 :           4 :     inp_ATOM *a = at + at_no;
    1292                 :           4 :     int num_H = NUMH( a, 0 );
    1293                 :           4 :     int std_chem_bonds_valence = get_el_valence( a->el_number, a->charge, 0 );
    1294                 :             : 
    1295         [ +  - ]:           4 :     if ( a->chem_bonds_valence + num_H > std_chem_bonds_valence )
    1296                 :             :     {
    1297                 :           4 :         int valence_to_metal = 0;
    1298                 :             :         /*int num_bonds_to_metal = 0;*/
    1299                 :             : 
    1300         [ +  + ]:          20 :         for ( i = 0; i < a->valence; i++ )
    1301                 :             :         {
    1302         [ -  + ]:          16 :             if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
    1303                 :             :             {
    1304         [ #  # ]:           0 :                 if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
    1305                 :             :                 {
    1306                 :           0 :                     return a->valence; /* fall back */
    1307                 :             :                 }
    1308                 :             :                 /* num_bonds_to_metal ++;*/
    1309                 :           0 :                 valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
    1310                 :             :             }
    1311                 :             :         }
    1312                 :             : 
    1313         [ -  + ]:           4 :         if ( a->chem_bonds_valence + num_H - valence_to_metal == std_chem_bonds_valence )
    1314                 :             :         {
    1315                 :             :             /* removing bonds to metal produces standard valence */
    1316                 :           0 :             return a->chem_bonds_valence - valence_to_metal;
    1317                 :             :         }
    1318                 :             :     }
    1319                 :             : 
    1320                 :             : #if ( S_VI_O_PLUS_METAL_FIX_BOND == 1 )
    1321   [ #  #  #  # ]:           0 :     else if (1 == a->charge && 2 == get_endpoint_valence( a->el_number ) &&
    1322         [ #  # ]:           0 :          a->chem_bonds_valence + num_H == std_chem_bonds_valence)
    1323                 :             :     {
    1324                 :             : 
    1325                 :           0 :         int valence_to_metal = 0;
    1326                 :             :         /* int num_bonds_to_metal = 0;*/
    1327                 :             : 
    1328         [ #  # ]:           0 :         for ( i = 0; i < a->valence; i++ )
    1329                 :             :         {
    1330         [ #  # ]:           0 :             if (is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
    1331                 :             :             {
    1332         [ #  # ]:           0 :                 if (( a->bond_type[i] & BOND_TYPE_MASK ) >= BOND_TYPE_ALTERN)
    1333                 :             :                 {
    1334                 :           0 :                     return a->valence; /* fall back */
    1335                 :             :                 }
    1336                 :             :                 /* num_bonds_to_metal ++;*/
    1337                 :           0 :                 valence_to_metal += ( a->bond_type[i] & BOND_TYPE_MASK );
    1338                 :             :             }
    1339                 :             :         }
    1340                 :             : 
    1341         [ #  # ]:           0 :         if (1 == valence_to_metal)
    1342                 :             :         {/* removing bonds to metal produces standard valence */
    1343                 :           0 :             return a->chem_bonds_valence - valence_to_metal;
    1344                 :             :         }
    1345                 :             :     }
    1346                 :             : #endif
    1347                 :             : 
    1348                 :           4 :     return a->chem_bonds_valence;
    1349                 :             : }
    1350                 :             : 
    1351                 :             : 
    1352                 :             : /****************************************************************************/
    1353                 :           0 : int nNoMetalNeighIndex( inp_ATOM *at, int at_no )
    1354                 :             : {
    1355                 :             :     int i;
    1356                 :             : 
    1357                 :           0 :     inp_ATOM* a = at + at_no;
    1358                 :             : 
    1359         [ #  # ]:           0 :     for ( i = 0; i < a->valence; i++ )
    1360                 :             :     {
    1361         [ #  # ]:           0 :         if (!is_el_a_metal( at[(int) a->neighbor[i]].el_number ))
    1362                 :             :         {
    1363                 :           0 :             return i;
    1364                 :             :         }
    1365                 :             :     }
    1366                 :             : 
    1367                 :           0 :     return -1;
    1368                 :             : }
    1369                 :             : 
    1370                 :             : 
    1371                 :             : /****************************************************************************/
    1372                 :           0 : int nNoMetalOtherNeighIndex( inp_ATOM *at, int at_no, int cur_neigh )
    1373                 :             : {
    1374                 :             :     int i, neigh;
    1375                 :             : 
    1376                 :           0 :     inp_ATOM* a = at + at_no;
    1377                 :             : 
    1378         [ #  # ]:           0 :     for ( i = 0; i < a->valence; i++ )
    1379                 :             :     {
    1380                 :           0 :         neigh = (int) a->neighbor[i];
    1381                 :             : 
    1382   [ #  #  #  # ]:           0 :         if (neigh != cur_neigh && !is_el_a_metal( at[neigh].el_number ))
    1383                 :             :         {
    1384                 :           0 :             return i;
    1385                 :             :         }
    1386                 :             :     }
    1387                 :             : 
    1388                 :           0 :     return -1;
    1389                 :             : }
    1390                 :             : 
    1391                 :             : 
    1392                 :             : /****************************************************************************/
    1393                 :           0 : int nNoMetalOtherNeighIndex2( inp_ATOM *at,
    1394                 :             :                               int at_no,
    1395                 :             :                               int cur_neigh,
    1396                 :             :                               int cur_neigh2 )
    1397                 :             : {
    1398                 :             :     int i, neigh;
    1399                 :             : 
    1400                 :           0 :     inp_ATOM* a = at + at_no;
    1401                 :             : 
    1402         [ #  # ]:           0 :     for ( i = 0; i < a->valence; i++ )
    1403                 :             :     {
    1404                 :           0 :         neigh = (int) a->neighbor[i];
    1405                 :             : 
    1406   [ #  #  #  #  :           0 :         if (neigh != cur_neigh && neigh != cur_neigh2 && !is_el_a_metal( at[neigh].el_number ))
                   #  # ]
    1407                 :             :         {
    1408                 :           0 :             return i;
    1409                 :             :         }
    1410                 :             :     }
    1411                 :             : 
    1412                 :           0 :     return -1;
    1413                 :             : }
    1414                 :             : 
    1415                 :             : 
    1416                 :             : 
    1417                 :             : #ifndef COMPILE_ANSI_ONLY
    1418                 :             : 
    1419                 :             : 
    1420                 :             : /****************************************************************************/
    1421                 :             : int MakeRemovedProtonsString( int nNumRemovedProtons,
    1422                 :             :                               NUM_H *nNumExchgIsotopicH,
    1423                 :             :                               NUM_H *nNumRemovedProtonsIsotopic,
    1424                 :             :                               int bIsotopic,
    1425                 :             :                               char *szRemovedProtons,
    1426                 :             :                               int *num_removed_iso_H )
    1427                 :             : {
    1428                 :             :     int i, j, len, num;
    1429                 :             : 
    1430                 :             :     len = 0;
    1431                 :             : 
    1432                 :             :     if ( nNumRemovedProtons )
    1433                 :             :     {
    1434                 :             :         len = sprintf(szRemovedProtons, "Proton balance: %c %d H+",
    1435                 :             :             nNumRemovedProtons >= 0 ? '+' : '-', abs(nNumRemovedProtons));
    1436                 :             :     }
    1437                 :             : 
    1438                 :             :     if (bIsotopic && ( nNumRemovedProtonsIsotopic || nNumExchgIsotopicH ))
    1439                 :             :     {
    1440                 :             : 
    1441                 :             :         for ( i = 0, j = 0; i < NUM_H_ISOTOPES; i++ )
    1442                 :             :         {
    1443                 :             : 
    1444                 :             :             num = ( nNumExchgIsotopicH ? nNumExchgIsotopicH[i] : 0 ) +
    1445                 :             :                 ( nNumRemovedProtonsIsotopic ? nNumRemovedProtonsIsotopic[i] : 0 );
    1446                 :             : 
    1447                 :             :             if ( num )
    1448                 :             :             {
    1449                 :             :                 len += sprintf(szRemovedProtons + len, "%s %d^%dH",
    1450                 :             :                     j ? ", " : "  [ removed ", num, i + 1);
    1451                 :             :                 j++;
    1452                 :             :             }
    1453                 :             :         }
    1454                 :             : 
    1455                 :             :         if ( j )
    1456                 :             :         {
    1457                 :             :             len += sprintf(szRemovedProtons + len, " ]");
    1458                 :             :             if ( num_removed_iso_H )
    1459                 :             :             {
    1460                 :             :                 *num_removed_iso_H = j;
    1461                 :             :             }
    1462                 :             :         }
    1463                 :             :     }
    1464                 :             : 
    1465                 :             :     if ( !len )
    1466                 :             :     {
    1467                 :             :         szRemovedProtons[0] = '\0';
    1468                 :             :     }
    1469                 :             : 
    1470                 :             :     return len;
    1471                 :             : }
    1472                 :             : #endif
    1473                 :             : 
    1474                 :             : 
    1475                 :             : /****************************************************************************/
    1476                 :        3475 : int get_endpoint_valence( U_CHAR el_number )
    1477                 :             : {
    1478      [ +  +  + ]:        3475 :     switch (el_number)
    1479                 :             :     {
    1480                 :         434 :         case EL_NUMBER_O:  /* fallthrough */
    1481                 :             :         case EL_NUMBER_S:
    1482                 :             :         case EL_NUMBER_SE:
    1483                 :             :         case EL_NUMBER_TE:
    1484                 :         434 :             return 2;
    1485                 :         102 :         case EL_NUMBER_N:
    1486                 :         102 :             return 3;
    1487                 :        2939 :         default:
    1488                 :        2939 :             return 0;
    1489                 :             :     }
    1490                 :             : }
    1491                 :             : 
    1492                 :             : 
    1493                 :             : #if ( KETO_ENOL_TAUT == 1 )  /* post v.1 feature */
    1494                 :             : 
    1495                 :             : 
    1496                 :             : /****************************************************************************/
    1497                 :           0 : int get_endpoint_valence_KET( U_CHAR el_number )
    1498                 :             : {
    1499      [ #  #  # ]:           0 :     switch (el_number)
    1500                 :             :     {
    1501                 :           0 :         case EL_NUMBER_C:
    1502                 :           0 :             return 4;
    1503                 :           0 :         case EL_NUMBER_O:
    1504                 :           0 :             return 2;
    1505                 :           0 :         default:
    1506                 :           0 :             return 0;
    1507                 :             :     }
    1508                 :             : }
    1509                 :             : #endif
    1510                 :             : 
    1511                 :             : 
    1512                 :             : /*
    1513                 :             :     MEMORY MANAGEMENT
    1514                 :             : */
    1515                 :             : 
    1516                 :             : 
    1517                 :             : #ifndef inchi_malloc
    1518                 :             : /****************************************************************************/
    1519                 :             : void *inchi_malloc( size_t c )
    1520                 :             : {
    1521                 :             :     return  malloc( c );
    1522                 :             : }
    1523                 :             : #endif
    1524                 :             : 
    1525                 :             : 
    1526                 :             : #ifndef inchi_calloc
    1527                 :             : /****************************************************************************/
    1528                 :             : void *inchi_calloc( size_t c, size_t n )
    1529                 :             : {
    1530                 :             :     return calloc( c, n );
    1531                 :             : }
    1532                 :             : #endif
    1533                 :             : 
    1534                 :             : 
    1535                 :             : #ifndef inchi_free
    1536                 :             : /****************************************************************************/
    1537                 :             : void inchi_free( void *p )
    1538                 :             : {
    1539                 :             :     if ( p )
    1540                 :             :     {
    1541                 :             :         inchi_free( p ); /*added check if zero*/
    1542                 :             :     }
    1543                 :             : }
    1544                 :             : #endif
    1545                 :             : 
    1546                 :             : 
    1547                 :             : /*
    1548                 :             :     STRINGS AND TEXT HANDLING
    1549                 :             : */
    1550                 :             : 
    1551                 :             : 
    1552                 :             : /****************************************************************************
    1553                 :             :   Remove leading & trailing spaces, replace consecutive
    1554                 :             :   spaces with a single space.
    1555                 :             : ****************************************************************************/
    1556                 :           0 : int normalize_string( char* name )
    1557                 :             : {
    1558                 :             :     int i, len, n;
    1559                 :             : 
    1560                 :           0 :     len = (int) strlen( name );
    1561                 :             : 
    1562         [ #  # ]:           0 :     for ( i = 0, n = 0; i < len; i++ )
    1563                 :             :     {
    1564         [ #  # ]:           0 :         if (isspace( UCINT name[i] ) /*|| !isprint( UCINT name[i] )*/)
    1565                 :             :         {
    1566                 :           0 :             name[i] = ' '; /* exterminate tabs !!! */
    1567                 :           0 :             n++;
    1568                 :             :         }
    1569                 :             :         else
    1570                 :             :         {
    1571         [ #  # ]:           0 :             if ( n > 0 )
    1572                 :             :             {
    1573                 :           0 :                 memmove((void*)&name[i - n], (void*)&name[i], (long long)len - (long long)i + 1); /* djb-rwth: cast operators added */
    1574                 :           0 :                 i -= n;
    1575                 :           0 :                 len -= n;
    1576                 :             :             }
    1577                 :           0 :             n = -1;
    1578                 :             :         }
    1579                 :             :     }
    1580         [ #  # ]:           0 :     if ( n == len ) /* empty line */
    1581                 :             :     {
    1582                 :           0 :         name[len = 0] = '\0';
    1583                 :             :     }
    1584   [ #  #  #  # ]:           0 :     else if ( ++n && n <= len )
    1585                 :             :     {
    1586                 :           0 :         len -= n;
    1587                 :           0 :         name[len] = '\0';
    1588                 :             :     }
    1589                 :             : 
    1590                 :           0 :     return len;
    1591                 :             : }
    1592                 :             : 
    1593                 :             : 
    1594                 :             : /****************************************************************************
    1595                 :             :  Replace non-ASCII characters with '.', return number of replacements
    1596                 :             : ****************************************************************************/
    1597                 :           0 : int dotify_non_printable_chars( char *line )
    1598                 :             : {
    1599                 :           0 :     int i, c, num = 0;
    1600                 :             : 
    1601         [ #  # ]:           0 :     if ( line )
    1602                 :             :     {
    1603         [ #  # ]:           0 :         for ( i = 0; (c = UCINT line[i]); i++ ) /* djb-rwth: addressing LLVM warning */
    1604                 :             :         {
    1605                 :             :             /* assuming ASCII charset */
    1606   [ #  #  #  # ]:           0 :             if ( c < ' ' || c >= 0x7F )
    1607                 :             :             {
    1608                 :           0 :                 line[i] = '.';
    1609                 :           0 :                 num++;
    1610                 :             :             }
    1611                 :             :         }
    1612                 :             :     }
    1613                 :             : 
    1614                 :           0 :     return num;
    1615                 :             : }
    1616                 :             : 
    1617                 :             : 
    1618                 :             : /****************************************************************************
    1619                 :             :     Reads char sequence pointed to by *pstring ( char *p = *ppstring) for
    1620                 :             :     not more than maxlen bytes) to 'field' up to first occurrence of any of
    1621                 :             :     delimiters in 'delims' or end of line, whichever occurs first.
    1622                 :             :     Sets *pstring to point to character which matches delimiter.
    1623                 :             :     Returns number of bytes copied, -1 on error.
    1624                 :             : ****************************************************************************/
    1625                 :        7340 : int read_upto_delim( char **pstring, char *field, int maxlen, char* delims )
    1626                 :             : {
    1627                 :             :     int i, n;
    1628                 :        7340 :     char* p = *pstring;
    1629                 :             : 
    1630         [ +  + ]:        7340 :     if ( !p )
    1631                 :             :     {
    1632                 :           1 :         return -1;
    1633                 :             :     }
    1634                 :             : 
    1635                 :             :     /* skip leading spaces */
    1636   [ +  -  +  + ]:       12722 :     for (i = 0; p[i] && isspace( UCINT p[i] ); i++)
    1637                 :             :     {
    1638                 :             :         ;
    1639                 :             :     }
    1640                 :        7339 :     p += i;
    1641                 :             : 
    1642                 :             :     /* read up to next delim or eol */
    1643                 :        7339 :     n = 0;
    1644   [ +  +  +  + ]:       28373 :     while (p[n] && !is_matching_any_delim( p[n], delims ))
    1645                 :             :     {
    1646                 :       21034 :         n++;
    1647                 :             :     }
    1648                 :             : 
    1649         [ -  + ]:        7339 :     if ( n + 1 > maxlen )
    1650                 :             :     {
    1651                 :           0 :         return -1;
    1652                 :             :     }
    1653                 :             : 
    1654                 :        7339 :     mystrncpy( field, p, n + 1 );
    1655                 :        7339 :     field[n + 1] = '\0';
    1656                 :             : 
    1657         [ +  + ]:        7339 :     if ( !p[n] )
    1658                 :             :     {
    1659                 :             :         /* reached EOL */
    1660                 :        1278 :         *pstring = NULL;
    1661                 :             :     }
    1662                 :             :     else
    1663                 :             :     {
    1664                 :             :         /* advance reading pos */
    1665                 :        6061 :         *pstring = *pstring + i + n;
    1666                 :             :     }
    1667                 :             : 
    1668                 :        7339 :     return n;
    1669                 :             : }
    1670                 :             : 
    1671                 :             : 
    1672                 :             : /****************************************************************************
    1673                 :             :     Check if a character is in the list of possible delimiters
    1674                 :             :     NB: same as isspace if delims is " \t\n\v\f\r"
    1675                 :             :     (0x20 and 0x09-0x0D)
    1676                 :             : ****************************************************************************/
    1677                 :       27095 : int is_matching_any_delim( char c, char* delims )
    1678                 :             : {
    1679                 :       27095 :     int ic = UCINT c;
    1680         [ +  + ]:      160149 :     while ( *delims )
    1681                 :             :     {
    1682         [ +  + ]:      139115 :         if ( ic == *delims )
    1683                 :             :         {
    1684                 :        6061 :             return 1;
    1685                 :             :         }
    1686                 :      133054 :         delims++;
    1687                 :             :     }
    1688                 :       21034 :     return 0;
    1689                 :             : }
    1690                 :             : 
    1691                 :             : 
    1692                 :             : /****************************************************************************
    1693                 :             :   Remove trailing spaces
    1694                 :             : ****************************************************************************/
    1695                 :        1640 : void remove_trailing_spaces( char* p )
    1696                 :             : {
    1697                 :             :     int   len;
    1698   [ +  -  +  + ]:       22252 :     for (len = (int) strlen( p ) - 1; len >= 0 && isspace( UCINT p[len] ); len--)
    1699                 :             :     {
    1700                 :             :         ;
    1701                 :             :     }
    1702                 :        1640 :     p[++len] = '\0';
    1703                 :        1640 : }
    1704                 :             : 
    1705                 :             : 
    1706                 :             : /****************************************************************************/
    1707                 :        2022 : void remove_one_lf( char* p )
    1708                 :             : {
    1709                 :             :     size_t len;
    1710   [ +  -  +  -  :        2022 :     if (p && 0 < ( len = strlen( p ) ) && p[len - 1] == '\n')
                   +  + ]
    1711                 :             :     {
    1712                 :         333 :         p[len - 1] = '\0';
    1713   [ +  +  -  + ]:         333 :         if ( len >= 2 && p[len - 2] == '\r' )
    1714                 :             :         {
    1715                 :           0 :             p[len - 2] = '\0';
    1716                 :             :         }
    1717                 :             :     }
    1718                 :        2022 : }
    1719                 :             : 
    1720                 :             : 
    1721                 :             : /****************************************************************************
    1722                 :             :     Copies up to maxlen characters INCLUDING end null from source to target
    1723                 :             :     Fills out the rest of the target with null bytes
    1724                 :             : 
    1725                 :             :     protected from non-zero-terminated source and overlapped target/source.
    1726                 :             : ****************************************************************************/
    1727                 :        9608 : int mystrncpy( char *target, const char *source, unsigned maxlen )
    1728                 :             : {
    1729                 :             :     const char *p;
    1730                 :             :     unsigned len, source_len;
    1731                 :             : 
    1732   [ +  -  +  -  :        9608 :     if ( target == NULL || maxlen == 0 || source == NULL )
                   -  + ]
    1733                 :             :     {
    1734                 :           0 :         return 0;
    1735                 :             :     }
    1736                 :             : 
    1737                 :             :     /* giallu: PR #163 */
    1738                 :             :     /* Find actual source length first to limit memchr search */
    1739                 :        9608 :     source_len = (unsigned)strlen(source);
    1740                 :             : 
    1741         [ +  + ]:        9608 :     if (source_len < maxlen)
    1742                 :             :     {
    1743                 :             :         /* Source is shorter than maxlen, use actual source length */
    1744                 :        3512 :         len = source_len;
    1745                 :             :     }
    1746         [ -  + ]:        6096 :     else if ((p = (const char*)memchr(source, 0, maxlen))) /* djb-rwth: addressing LLVM warning */
    1747                 :             :     {
    1748                 :             :         /* maxlen does not include the found zero termination */
    1749                 :           0 :         len = (int) ( p - source );
    1750                 :             :     }
    1751                 :             :     else
    1752                 :             :     {
    1753                 :             :         /*  reduced length does not include one more byte for zero termination */
    1754                 :        6096 :         len = maxlen - 1;
    1755                 :             :     }
    1756                 :             : 
    1757         [ +  - ]:        9608 :     if ( len )
    1758                 :             :     {
    1759                 :        9608 :         memmove(target, source, len);
    1760                 :             :     }
    1761                 :             : 
    1762                 :        9608 :     memset(target + len, 0, maxlen - len); /*  zero termination */ /* djb-rwth: memset_s C11/Annex K variant? */
    1763                 :             : 
    1764                 :        9608 :     return 1;
    1765                 :             : }
    1766                 :             : 
    1767                 :             : 
    1768                 :             : /****************************************************************************
    1769                 :             :  Remove leading and trailing white spaces
    1770                 :             : ****************************************************************************/
    1771                 :        3570 : char* lrtrim( char *p, int* nLen )
    1772                 :             : {
    1773                 :        3570 :     int i, len = 0;
    1774                 :             : 
    1775   [ +  -  +  - ]:        3570 :     if (p && ( len = (int) strlen( p ) ))
    1776                 :             :     {
    1777   [ +  -  +  -  :       20202 :         for (i = 0; i < len && is_ascii( p[i] ) && isspace( p[i] ); i++)
                   +  + ]
    1778                 :             :         {
    1779                 :             :             ;
    1780                 :             :         }
    1781         [ +  - ]:        3570 :         if ( i )
    1782                 :             :         {
    1783                 :        3570 :             len -= i; /* djb-rwth: variable has to be decreased before memmove */
    1784                 :        3570 :             (memmove)(p, p + i, ((long long)len + 1)); /* djb-rwth: now cast operator can be added */
    1785                 :             :         }
    1786                 :             : 
    1787   [ +  -  +  -  :        3570 :         for (; 0 < len && is_ascii( p[len - 1] ) && isspace( p[len - 1] ); len--)
                   -  + ]
    1788                 :             :         {
    1789                 :             :             ;
    1790                 :             :         }
    1791                 :        3570 :         p[len] = '\0';
    1792                 :             :     }
    1793                 :             : 
    1794         [ +  - ]:        3570 :     if ( nLen )
    1795                 :             :     {
    1796                 :        3570 :         *nLen = len;
    1797                 :             :     }
    1798                 :             : 
    1799                 :        3570 :     return p;
    1800                 :             : }
    1801                 :             : 
    1802                 :             : 
    1803                 :             :  /****************************************************************************
    1804                 :             :    Extract InChI substring embedded into a longer string.
    1805                 :             : 
    1806                 :             :     InChI should start from "InChI=".
    1807                 :             : 
    1808                 :             :     As for the end of InChI,
    1809                 :             :     consider that according to
    1810                 :             :         http://info-uri.info/registry/OAIHandler?verb=GetRecord&metadataPrefix=reg&identifier=info:inchi/
    1811                 :             :     an InChI identifier may contain the following characters:
    1812                 :             :         A-Z
    1813                 :             :         a-z
    1814                 :             :         0-9
    1815                 :             :         ()*+,-./;=?@
    1816                 :             : 
    1817                 :             :     Here we treat any character not conforming this specification as a whitespace
    1818                 :             :     which marks the end of the InChI string.
    1819                 :             :     For example:
    1820                 :             :         "InChI=1/Ar%"
    1821                 :             :         "InChI=1/Ar\n"
    1822                 :             :         "InChI=1/Ar\r\t"
    1823                 :             :     all will be trimmed to
    1824                 :             :         "InChI=1/Ar"
    1825                 :             : 
    1826                 :             : ****************************************************************************/
    1827                 :           0 : void extract_inchi_substring( char ** buf, const char *str, size_t slen )
    1828                 :             : {
    1829                 :             :     size_t i;
    1830                 :             :     const char *p;
    1831                 :             :     char* bufp;
    1832                 :             :     char pp;
    1833                 :             : 
    1834                 :           0 :     bufp = *buf;
    1835                 :           0 :     *buf = NULL;
    1836                 :             : 
    1837         [ #  # ]:           0 :     if ( str == NULL )
    1838                 :             :     {
    1839                 :           0 :         return;
    1840                 :             :     }
    1841         [ #  # ]:           0 :     if (strlen( str ) < 1)
    1842                 :             :     {
    1843                 :           0 :         return;
    1844                 :             :     }
    1845                 :             : 
    1846                 :           0 :     p = strstr( str, "InChI=" );
    1847         [ #  # ]:           0 :     if (NULL == p)
    1848                 :           0 :         return;
    1849                 :             : 
    1850         [ #  # ]:           0 :     for ( i = 0; i < slen; i++ )
    1851                 :             :     {
    1852                 :           0 :         pp = p[i];
    1853                 :             : 
    1854   [ #  #  #  # ]:           0 :         if (pp >= 'A' && pp <= 'Z')   continue;
    1855   [ #  #  #  # ]:           0 :         if (pp >= 'a' && pp <= 'z')   continue;
    1856   [ #  #  #  # ]:           0 :         if (pp >= '0' && pp <= '9')   continue;
    1857         [ #  # ]:           0 :         switch (pp)
    1858                 :             :         {
    1859                 :           0 :             case '(':
    1860                 :             :             case ')':
    1861                 :             :             case '*':
    1862                 :             :             case '+':
    1863                 :             :             case ',':
    1864                 :             :             case '-':
    1865                 :             :             case '.':
    1866                 :             :             case '/':
    1867                 :             :             case ';':
    1868                 :             :             case '=':
    1869                 :             :             case '?':
    1870                 :           0 :             case '@':    continue;
    1871                 :             : 
    1872                 :           0 :             default:    break;
    1873                 :             :         }
    1874                 :             : 
    1875                 :           0 :         break;
    1876                 :             :     }
    1877                 :             : 
    1878                 :           0 :     *buf = (char*) inchi_calloc( i + 1, sizeof( char ) );
    1879                 :           0 :     memcpy(*buf, p, i);
    1880         [ #  # ]:           0 :     if ( *buf )
    1881                 :           0 :         (*buf)[i] = '\0';
    1882                 :             : 
    1883                 :           0 :     return;
    1884                 :             : }
    1885                 :             : 
    1886                 :             : 
    1887                 :             : /****************************************************************************/
    1888                 :           0 : void extract_auxinfo_substring( char ** buf, const char *str, size_t slen )
    1889                 :             : {
    1890                 :             :     size_t i;
    1891                 :             :     const char *p;
    1892                 :             :     char* bufp;
    1893                 :             :     char pp;
    1894                 :             : 
    1895                 :           0 :     bufp = *buf;
    1896                 :           0 :     *buf = NULL;
    1897                 :             : 
    1898         [ #  # ]:           0 :     if ( str == NULL )
    1899                 :             :     {
    1900                 :           0 :         return;
    1901                 :             :     }
    1902         [ #  # ]:           0 :     if (strlen( str ) < 1)
    1903                 :             :     {
    1904                 :           0 :         return;
    1905                 :             :     }
    1906                 :             : 
    1907                 :           0 :     p = strstr( str, "AuxInfo=" );
    1908         [ #  # ]:           0 :     if (NULL == p)
    1909                 :             :     {
    1910                 :           0 :         return;
    1911                 :             :     }
    1912                 :             : 
    1913         [ #  # ]:           0 :     for ( i = 0; i < slen; i++ )
    1914                 :             :     {
    1915                 :           0 :         pp = p[i];
    1916         [ #  # ]:           0 :         if (isspace( UCINT pp ))    break;
    1917                 :             :     }
    1918                 :             : 
    1919                 :           0 :     *buf = (char*) inchi_calloc( i + 1, sizeof( char ) );
    1920                 :           0 :     memcpy(*buf, p, i);
    1921         [ #  # ]:           0 :     if ( *buf )
    1922                 :           0 :         (*buf)[i] = '\0';
    1923                 :             : 
    1924                 :           0 :     return;
    1925                 :             : }
    1926                 :             : 
    1927                 :             : 
    1928                 :             : /****************************************************************************
    1929                 :             :     For compatibility: local implementation of non-ANSI
    1930                 :             :     (MS-specific) functions, prefixed with "inchi_"
    1931                 :             : ****************************************************************************/
    1932                 :             : 
    1933                 :             : 
    1934                 :             : #define __MYTOLOWER(c) ( ((c) >= 'A') && ((c) <= 'Z') ? ((c) - 'A' + 'a') : (c) )
    1935                 :             : 
    1936                 :             : 
    1937                 :             : /****************************************************************************/
    1938                 :         213 : int inchi_memicmp( const void * p1, const void * p2, size_t length )
    1939                 :             : {
    1940                 :         213 :     const U_CHAR *s1 = (const U_CHAR*) p1;
    1941                 :         213 :     const U_CHAR *s2 = (const U_CHAR*) p2;
    1942         [ +  - ]:         637 :     while (length--)
    1943                 :             :     {
    1944   [ +  +  +  + ]:         897 :         if (*s1 == *s2 ||
    1945   [ +  +  +  +  :         260 :               __MYTOLOWER( (int) *s1 ) == __MYTOLOWER( (int) *s2 ))
             +  +  +  - ]
    1946                 :             :         {
    1947                 :         424 :             s1++;
    1948                 :         424 :             s2++;
    1949                 :             :         }
    1950                 :             :         else
    1951                 :             :         {
    1952                 :             :             return
    1953   [ +  +  +  +  :         213 :                 __MYTOLOWER( (int) *s1 ) - __MYTOLOWER( (int) *s2 );
             +  +  +  - ]
    1954                 :             :         }
    1955                 :             :     }
    1956                 :             : 
    1957                 :           0 :     return 0;
    1958                 :             : }
    1959                 :             : 
    1960                 :             : 
    1961                 :             : /****************************************************************************/
    1962                 :         784 : int inchi_stricmp( const char *s1, const char *s2 )
    1963                 :             : {
    1964         [ +  + ]:        1985 :     while ( *s1 )
    1965                 :             :     {
    1966   [ +  +  -  + ]:        2663 :         if (*s1 == *s2 ||
    1967   [ +  -  +  +  :         731 :               __MYTOLOWER( (int) *s1 ) == __MYTOLOWER( (int) *s2 ))
             +  -  +  - ]
    1968                 :             :         {
    1969                 :        1201 :             s1++;
    1970                 :        1201 :             s2++;
    1971                 :             :         }
    1972                 :             :         else
    1973                 :             :         {
    1974                 :             :             return
    1975   [ +  -  +  +  :         731 :                 __MYTOLOWER( (int) *s1 ) - __MYTOLOWER( (int) *s2 );
             +  -  +  - ]
    1976                 :             :         }
    1977                 :             :     }
    1978                 :             : 
    1979         [ -  + ]:          53 :     if ( *s2 )
    1980                 :             :     {
    1981                 :           0 :         return -1;
    1982                 :             :     }
    1983                 :             : 
    1984                 :          53 :     return 0;
    1985                 :             : }
    1986                 :             : 
    1987                 :             : 
    1988                 :             : /****************************************************************************/
    1989                 :           0 : char *inchi__strnset( char *s, int val, size_t length )
    1990                 :             : {
    1991                 :           0 :     char* ps = s;
    1992   [ #  #  #  # ]:           0 :     while ( length-- && *ps )
    1993                 :             :     {
    1994                 :           0 :         *ps++ = (char) val;
    1995                 :             :     }
    1996                 :             : 
    1997                 :           0 :     return s;
    1998                 :             : }
    1999                 :             : 
    2000                 :             : 
    2001                 :             : /****************************************************************************/
    2002                 :          54 : char *inchi__strdup( const char *string )
    2003                 :             : {
    2004                 :          54 :     char* p = NULL;
    2005         [ -  + ]:          54 :     if ( string )
    2006                 :             :     {
    2007                 :           0 :         size_t length = strlen( string );
    2008                 :           0 :         p = (char *) inchi_malloc( length + 1 );
    2009         [ #  # ]:           0 :         if (p)
    2010                 :             :         {
    2011                 :           0 :             strcpy(p, string);
    2012                 :             :         }
    2013                 :             :     }
    2014                 :             : 
    2015                 :          54 :     return p;
    2016                 :             : }
    2017                 :             : 
    2018                 :             : 
    2019                 :             : #undef __MYTOLOWER
        

Generated by: LCOV version 2.0-1