Subversion Repositories wimsdev

Rev

Rev 17891 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6785 bpr 1
/*
2
   Modified to run w/o p2c libraries
3
   2007 Ernst-Georg Schmid
4
   Modified to run as shared library
5
   2007 Ernst-Georg Schmid
6
   pgchem@tuschehund.de
14179 bpr 7
 
6785 bpr 8
   compile with gcc without optimizations (except -march= -mcpu=) or it gets SLOWER!
14179 bpr 9
 
6785 bpr 10
   THIS VERSION HAS extended_molstat SWITCHED ON BY DEFAULT!
14179 bpr 11
 
6785 bpr 12
   This file is part of the xchem::tigress project.
13
 
14
   --- DUAL LICENSING ---
14179 bpr 15
 
6785 bpr 16
   If checkmol.c aka. pgchem::barsoi is compiled as a library, it is released under the terms of the
17
   lesser GNU General Public License. For the executable, the original GPL
18
   licensing applies!
14179 bpr 19
 
6785 bpr 20
   This program is free software; you can redistribute it and/or modify
21
   it under the terms of the lesser GNU General Public License as published by
22
   the Free Software Foundation version 2.1 of the License.
14179 bpr 23
 
6785 bpr 24
   This program is distributed in the hope that it will be useful,
25
   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
   lesser GNU General Public License for more details.
14179 bpr 28
 
6785 bpr 29
   --- DUAL LICENSING ---
30
 
31
   ORIGINAL HEADER:
14179 bpr 32
 
6785 bpr 33
checkmol/matchmol
34
Norbert Haider, University of Vienna, 2003-2007
35
norbert.haider@univie.ac.at
36
 
37
This software is published under the terms of the GNU General Public
38
License (GPL, see below). For a detailed description of this license,
39
see http://www.gnu.org/copyleft/gpl.html
40
 
41
If invoked as "checkmol", this program reads 2D and 3D molecular structure
42
files in various formats (Tripos Alchemy "mol", Tripos SYBYL "mol2", MDL "mol")
43
and describes the molecule either by its functional groups or by a set of
44
descriptors useful for database pre-screening (number of rings, sp2-hybridized
45
carbons, aromatic bonds, etc.; see definition of molstat_rec).
46
 
47
If invoked as "matchmol", the program reads two individual 2D or 3D molecular
48
structure files in various formats (see above) and checks if the first molecule
49
(the "needle") is a substructure of the second one (the "haystack").
50
"Haystack" can also be a MDL SD-file (containing multiple MOL files);
51
if invoked with "-" as file argument, both "needle" and "haystack" are
52
read as an SD-file from standard input, assuming the first entry in
53
the SDF to be the "needle"; output: entry number + ":F" (false) or ":T" (true)
54
 
55
Compile with fpc (Free Pascal, see http://www.freepascal.org), using
56
the -Sd or -S2 option (Delphi mode; IMPORTANT!)
57
 
58
example for compilation (with optimization) and installation:
59
 
60
fpc checkmol.pas -S2 -Xs -OG -Or -O2u -Op1
61
 
62
as "root", do the following:
63
 
64
cp checkmol /usr/local/bin
65
cd /usr/local/bin
66
ln checkmol matchmol
67
 
68
Version history
69
 
70
v0.1   extends "chkmol" utility (N. Haider, 2002), adds matching functionality;
71
 
72
v0.1a  minor bugfixes:
73
       stop ring search when max_rings is reached (function is_ringpath);
74
       fixed upper/lowercase of element symbol in MDL molfile output;
75
       added debug output for checkmol (-D option)
76
 
77
v0.2   added functionality to switch ring search from SAR (set of all rings) to
78
       SSR (set of small rings; see below) if number of rings exceeds max_rings
79
       (1024), e.g. with Buckminster-fullerenes (thanks to E.-G. Schmid for a hint);
80
       added -r command-line option to force ring search into SSR mode;
81
       as SSR, we regard the set of all rings with max. 10 ring members, and in
82
       which no ring is completely contained in another one
83
 
84
v0.2a  fixed a bug in function is_ringpath which could cause SAR ring search to
85
       overlook a few rings (e.g., the six 8-membered rings in cubane)
86
 
87
v0.2b  fixed unequal treatment of needle and haystack structures with respect
88
       to aromaticity check (trusting input file vs. full check)
89
 
90
v0.2c  modified the changes of v0.2b so that they affect only "matchmol" mode;
91
       added quick_match function
92
 
93
v0.2d  refined function bondtypes_OK so that it does not accept C=O fragments
94
       (and C=S, C=Se, C=Te) as equivalent to aromatic C-O (C-S, C-Se, C-Te);
95
       fixed function find_ndl_ref_atom to use only heavy atoms as "needle"
96
       reference atoms for atom-to-atom match; update function quick_match to
97
       handle queries with only one heavy atom (thanks to A. Barozza for a hint)
98
 
99
v0.2e  modified procedure get_molstat: adds 1 formal double bond for each aromatic
100
       ring to the "fingerprint" in order to allow an isolated double bond in the
101
       needle to be matched as a fragment of an aromatic ring
102
       ATTENTION: "fingerprints" (molecular statistics) generated with a previous
103
       version of checkmol(-x and -X option) must be updated for structure/
104
       substructure database searching with matchmaol.
105
 
106
v0.2f  modified procedures chk_ccx, chk_xccx, write_fg_text, write_fg_text_de,
107
       write_fg_code in order to report halogen derivatives other than alkyl halides,
108
       aryl halides and acyl halides (e.g., vinyl halides) and C=C compounds other
109
       than "true" alkenes, enols, enediols, enamines, etc. (e.g. vinyl halides);
110
       added "strict mode" (option -s) for matching: this uses a more thorough
111
       comparison of atom types and bond types (new functions atomtypes_OK_strict,
112
       bondtypes_OK_strict, several minor modifications in other subroutines).
113
 
114
v0.2g  changed procedure readinputfile (+ minor changes in main routine) in
115
       order to read very large SD input files without "not enough memory" error
116
       (the previous version attempted to read the entire SD file into a buffer,
117
       the new version reads only one molecule at once);
118
       fixed a minor bug in read_mol2file which led to undefined bond types;
119
       added definition of "debug" option as a compiler flag.
120
 
121
v0.2h  fixed a small bug which caused program hangs with (e.g.) some metal
122
       complexes: this was solved just by increasing the number of possible
123
       neighbor atoms from 8 to 16 (now defined in the constant max_neighbors).
124
 
125
v0.2i  introduced some more plausibility checking (number of directly connected
126
       atoms), result stored in variable mol_OK (set in count_neighbors);
127
       completely rewrote function matrix_OK which now can handle up to
128
       max_neighbors substituents per atom (previous versions were limited to
129
       4 substituents; larger numbers are required e.g. for ferrocenes and
130
       similar compounds).
131
 
132
v0.2j  new function raw_hetbond_count: ignores bond order (in contrast to function
133
       hetbond_count), this is better suitable for molecular statistics.
134
       ATTENTION: previously generated "fingerprints" in databases must be updated!
135
       improved recognition of non-conformant SD files (with missing "M  END" line)
136
 
137
v0.2k  changed quick_match routine to compare atom types only by element in
138
       order to avoid (rare) cases of non-matching identical input files;
139
       slightly changed error message for non-existant input files
140
 
141
v0.3   changed function update_Htotal in order to distinguish between 3-valent
142
       and 5-valent phosphorus (thanks to H. Feldman for this suggestion);
143
       added a table (array ringprop) to store ring sizes and aromaticity for
144
       faster lookup; changed aromaticity detection (chk_arom) to be fully
145
       independent of Kekule structures in condensed ring systems; changed add_ring
146
       to store new rings in ascending order (with respect to ring size): this
147
       will cause the aromaticity detection to start with smaller rings;
148
       added additional calls to chk_arom when in SSR ring search mode (to ensure
149
       that all aromatic rings are found); speeded up function is_newring;
150
       added option "-M": this restores the behavior of previous versions,
151
       i.e. metal atoms will be accepted as ring members (which costs a lot
152
       of performance for coordinate compounds like ferrocenes but gives
153
       only little useful information); when used in databases: use the _same_
154
       mode ("-M" or not) _both_ for checkmol (creation of fingerprints) and matchmol;
155
       fixed ugly linebreaks in show_usage;
156
 
157
v0.3a  fixed a bug in read_charges (which was introduced in the v0.3 code cleanup)
158
 
159
v0.3b  fixed recognition of ketenes, CO2, CS2, CSO, phosphines, boronic esters
160
 
161
v0.3c  fixed recognition of hydrazines, hydroxylamines, thiocarboxylic acids,
162
       orthocarboxylic acids; slightly changed textual output for a few functional
163
       groups
164
 
165
v0.3d  added bond topology feature ("any", "ring", "chain", as defined by MDL specs,
166
       plus "always_any", "excess-ringcount", "exact-ringcount") to bond properties
167
       and implemented its use for substructure searches, either as specified in the
168
       query MDL molfile or by using "strict" mode; added ring_count property to
169
       "bonds" section of Checkmol-tweaked molfiles (using an unused field in the MDL
170
       molfile specs);
171
       added option for E/Z isomer search, either globally (-g option) or per
172
       double bond: bstereo_xyz property, encoded either by a leading "0" in the
173
       bond block of a checkmol-tweaked molfile or by using the "stereo care" flag
174
       as defined in the MDL file specs (both atoms of a double bond must carry
175
       this flag)
176
 
177
v0.3e  fixed wrong position of "stereo care" flag expected in input molfile;
178
 
179
v0.3f  added option for enantiospecific search (R/S isomer search); this can be
180
       turned on either globally (-G option or using the "chiral" flag in the
181
       "counts line" of the query MDL molfile) or per atom (using - or abusing -
182
       the "stereo care" flag); enantiomers are compared using the 3D coordinates
183
       of the substituents at a chiral center, so we do not have to rely on the
184
       presence of correct "up" and "down" bond types in the candidate structures;
185
       nevertheless, "pseudo-3D" structures (i.e. flat 2D structures with "up"
186
       and "down" bond notation) can be also used, even in mixed mode both as
187
       query structure and candidate structure; added support for "up" and "down"
188
       bond notation in MDL molfile output (if -m option is used and these bond
189
       types were present in the input file); refined function find_ndl_ref_atom;
190
       fixed Alchemy atom type misinterpretation (upper/lower case mismatch);
191
 
192
v0.3g  minor fixes: recognition of sp2 nitrogen in N=N structures (function
193
       update_atypes); extended E/Z geometry check to C=N and N=N bonds; accelerated
194
       exact search by initial comparison of C,O,N counts; added meaningful error
195
       message for input structures with 0 (zero) atoms;
196
 
197
v0.3h  added a match matrix clean-up step to function is_matching in order to
198
       remove "impossible" multiple matches prior to chirality check; added
199
       function ndl_maybe_chiral as a plausibility check; added support for other
200
       atoms than carbon as chiral centers; changed function is_cis from a
201
       distance-based cis/trans check into a torsion-based check;
202
 
203
v0.3i  minor fixes in functions max_neighbors and chk_ammon;
204
       revert ringsearch_mode to its original value for each new molecule
205
       (main routine)
206
 
207
v0.3j  various improvements in checkmol: added alkenyl (vinyl) and alkynyl
208
       residues as possible substituents for amides, esters, ethers, etc.;
209
       extended recognition of orthocarboxylic acid derivatives; refined
210
       recognition of oxohetarenes and iminohetareenes, ureas, nitroso
211
       compounds; fixed reading of "old-style" charges from MDL files;
212
       refined aromaticity check; fixed a bug in procedure chk_arom and
213
       renamed function is_exocyclic_methylene_C into
214
       find_exocyclic_methylene_C; added assignment of pointers to "nil"
215
       after calling "freemem" in procedure zap_molecule and zap_needle;
216
       matchmol: refined selection of needle reference atom; added "strict
217
       chirality check" mode (if -x -s and -G options are used): returns
218
       "false" if a chiral or pseudochiral atom is matched against its
219
       counterpart with undefined or "flat" geometry; added an alternative
220
       selection mechanism for the needle reference atom, based on the
221
       Morgan algorithm;
222
 
223
v0.3k  improved matching of nitro compounds (ionic vs. non-ionic
224
       representation); some finetuning in recognition of N-oxides,
225
       hydroxylamines, etc.; modified get_molstat in order to ignore
226
       charges in nitro groups, N-oxides, sulfoxides, azides, etc. in
227
       ionic representation; added function normalize_ionic_bonds;
228
       fixed a bug in is_alkenyl; fixed a bug (introduced in v0.3j) in
229
       the treatment of "old-style" MDL charges;
230
 
231
v0.3l  minor adjustments in quick_match (for unknown atom types,
232
       opposite charges); some performance improvements, e.g. in function
233
       path_pos, reduced extensive calls to is_heavyatom and is_metal
234
       by extending atom_rec with boolean fields 'heavy' and 'metal'
235
       (thanks to E.-G.Schmid); added molstat field n_rBz (number of
236
       benzene rings; deactivated by default); added -l command-line
237
       option to checkmol (lists all molstat codes with a short
238
       explanation); added graceful handling of NoStruct (i.e.,
239
       zero-atom) molecules
240
 
241
v0.3m  minor bug fixes (chk_imine), let normalize_ionic_bonds return "true"
242
       if some bond-order change was made; fixed incorrect implementation
243
       of the Morgan algorithm (thanks to H.Feldman), fixed is_matching in
244
       order to prevent wrong matches of larger rings on smaller ones; count
245
       halogens also as type "X" in molstat (as before v0.3l); added some more
246
       molstat descriptors for most elements (deactivated by default; for
247
       activation, uncomment the definition of "extended_molstat", see below);
248
       added support for the generation of binary fingerprints with output
249
       either as boolean values (-f option) or as decimal values (-F option),
250
       fingerprint patterns are supplied by the user (in SDF format, max. 62
251
       structures per file); added a version check ("tweaklevel",
252
       ringsearch_mode, opt_metalrings) for "tweaked" MDL molfiles
253
 
254
v0.3n  increased max_vringsize in SSR mode from 10 to 12 (now defined in
255
       ssr_vringsize); optionally changed ring statistics to ignore envelope
256
       rings (which completely contain another ring, "reduced SAR") in order to
257
       make molstat in SAR and SSR mode more compatible) - disabled by default;
258
       introduced a new molstat descriptor: n_br2p (number of bonds which
259
       belong to two or more rings); changed n_b1 counter to ignore bonds to
260
       explicit hydrogens; added procedure fix_ssr_ringcounts
261
       (see comment in the code); added bond property mdl_stereo for preservation
262
       of original value; slightly changed "get_molstat" and "update_atypes" in
263
       order to consolidate atom type for various N atoms; remember "chiral" flag
264
       status in molfile output (-m); modified chk_arom in order to accept rings
265
       as aromatic if all bonds are of type 'A'; several minor bug fixes
266
 
267
v0.3o  minor changes in update_atypes (nitrogen); changed the matching
268
       algorithm in order to take care of disconnected molecular graphs
269
       (e.g., salts); refined matching of atoms with formal charges
270
 
271
Credits:
272
 
273
Rami Jbara (rami_jbara@hotmail.com) designed the 8-character functional
274
group codes.
275
 
276
I am also very grateful to Ernst-Georg Schmid (Bayer Business Services,
277
Leverkusen/Germany) and to Howard Feldman (The Blueprint Initiative,
278
Toronto/Canada) for numerous bug reports and suggestions for improvements.
279
 
280
===============================================================================
281
DISCLAIMER
282
This program is free software; you can redistribute it and/or
283
modify it under the terms of the GNU General Public License
284
as published by the Free Software Foundation; either version 2
285
of the License, or (at your option) any later version.
286
 
287
This program is distributed in the hope that it will be useful,
288
but WITHOUT ANY WARRANTY; without even the implied warranty of
289
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
290
GNU General Public License for more details.
291
 
292
You should have received a copy of the GNU General Public License
293
along with this program; if not, write to the Free Software Foundation,
294
Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
295
===============================================================================
296
*/
297
 
298
/* $DEFINE debug                    uncomment if desired */
299
/* $DEFINE extended_molstat         uncomment if desired */
300
/* $DEFINE reduced_SAR              uncomment if desired */
301
 
302
/* uses
303
  SYSUTILS, MATH; */
304
 
305
#include <stdlib.h>
306
#include <stdio.h>
307
#include <math.h>
308
#include <string.h>
309
#include <ctype.h>
310
#include <sys/types.h>
311
#include <sys/stat.h>
312
#include "safemem.h"
313
#ifdef MAKE_SHARED_LIBRARY
314
#include "barsoi.h"
315
#endif
316
 
317
#ifdef MAKE_SHARED_LIBRARY
318
#define version         "0.3p C (pgchem::barsoi)"
319
#else
320
#define version         "0.3p C"
321
#endif
322
 
323
#undef REDUCED_SAR
324
 
325
/* How many recursions before aborting is_ringpath and reverting to SSR */
326
#define max_ringpath_recursion_depth   500000
327
 
328
/* How many recursions before aborting is_match and reverting to non-exhaustive match */
329
#define max_match_recursion_depth   500000
330
 
331
#define tweaklevel      2
332
    /* v0.3m; accept tweaks in MDL molfiles only if same level */
333
#define max_atoms       1024
334
#define max_bonds       1024
335
#define slack           8192
336
#define max_ringsize    128
337
#define max_rings       1024
338
#define max_fg          256
339
#define max_neighbors   16      /* new in v0.2h */
340
 
341
#define TAB             '\t'
342
 
343
#define max_matchpath_length  256
344
#define pmCheckMol      1001
345
#define pmMatchMol      1002
346
 
347
#define rs_sar          2001    /* ring search mode: SAR = set of all rings */
348
#define rs_ssr          2002
349
    /*                   SSR = set of small rings */
350
 
351
#define btopo_any       0       /* bond topology, new in v0.3d */
352
#define btopo_ring      1
353
#define btopo_chain     2
354
#define btopo_always_any  3     /* even in "strict mode" */
355
#define btopo_excess_rc  4
356
/* bond in candidate must be included in _more_ rings than
357
                        the matching bond in the query ==> specific search for
358
                        annulated systems */
359
#define btopo_exact_rc  5
360
    /* bond in query and candidate must have same ring count */
361
 
362
#define bstereo_any     0
363
    /* new in v0.3d, any E/Z isomer matches (for double bonds) */
364
#define bstereo_xyz     1
365
    /* E/Z match is checked by using XYZ coordinates of the atoms */
366
#define bstereo_up      11      /* new in v0.3f, flags for single bonds */
367
#define bstereo_down    16
368
#define bstereo_either    14    /* 0.3x */
369
#define bstereo_double_either    13     /* 0.3x */
370
 
371
#define fpf_boolean     3001
372
    /* v0.3m; format for fingerprint output (n:T, n:F) */
373
#define fpf_decimal     3002
374
    /* v0.3m; format for fingerprint output as decimal value of bitstring */
375
#define fp_blocksize    62
376
    /* v0.3m; 1 bit may be used for sign (e.g. by PHP), 1 bit for "exact hit" */
377
#define ssr_vringsize   12      /* v0.3n; max. ring size in SSR mode */
378
 
379
/* Definitions for functional groups: */
380
#define fg_cation       1
381
#define fg_anion        2
382
#define fg_carbonyl     3
383
#define fg_aldehyde     4
384
#define fg_ketone       5
385
#define fg_thiocarbonyl  6
386
#define fg_thioaldehyde  7
387
#define fg_thioketone   8
388
#define fg_imine        9
389
#define fg_hydrazone    10
390
#define fg_semicarbazone  11
391
#define fg_thiosemicarbazone  12
392
#define fg_oxime        13
393
#define fg_oxime_ether  14
394
#define fg_ketene       15
395
#define fg_ketene_acetal_deriv  16
396
#define fg_carbonyl_hydrate  17
397
#define fg_hemiacetal   18
398
#define fg_acetal       19
399
#define fg_hemiaminal   20
400
#define fg_aminal       21
401
#define fg_thiohemiaminal  22
402
#define fg_thioacetal   23
403
#define fg_enamine      24
404
#define fg_enol         25
405
#define fg_enolether    26
406
#define fg_hydroxy      27
407
#define fg_alcohol      28
408
#define fg_prim_alcohol  29
409
#define fg_sec_alcohol  30
410
#define fg_tert_alcohol  31
411
#define fg_1_2_diol     32
412
#define fg_1_2_aminoalcohol  33
413
#define fg_phenol       34
414
#define fg_1_2_diphenol  35
415
#define fg_enediol      36
416
#define fg_ether        37
417
#define fg_dialkylether  38
418
#define fg_alkylarylether  39
419
#define fg_diarylether  40
420
#define fg_thioether    41
421
#define fg_disulfide    42
422
#define fg_peroxide     43
423
#define fg_hydroperoxide  44
424
#define fg_hydrazine    45
425
#define fg_hydroxylamine  46
426
#define fg_amine        47
427
#define fg_prim_amine   48
428
#define fg_prim_aliph_amine  49
429
#define fg_prim_arom_amine  50
430
#define fg_sec_amine    51
431
#define fg_sec_aliph_amine  52
432
#define fg_sec_mixed_amine  53
433
#define fg_sec_arom_amine  54
434
#define fg_tert_amine   55
435
#define fg_tert_aliph_amine  56
436
#define fg_tert_mixed_amine  57
437
#define fg_tert_arom_amine  58
438
#define fg_quart_ammonium  59
439
#define fg_n_oxide      60
440
#define fg_halogen_deriv  61
441
#define fg_alkyl_halide  62
442
#define fg_alkyl_fluoride  63
443
#define fg_alkyl_chloride  64
444
#define fg_alkyl_bromide  65
445
#define fg_alkyl_iodide  66
446
#define fg_aryl_halide  67
447
#define fg_aryl_fluoride  68
448
#define fg_aryl_chloride  69
449
#define fg_aryl_bromide  70
450
#define fg_aryl_iodide  71
451
#define fg_organometallic  72
452
#define fg_organolithium  73
453
#define fg_organomagnesium  74
454
#define fg_carboxylic_acid_deriv  75
455
#define fg_carboxylic_acid  76
456
#define fg_carboxylic_acid_salt  77
457
#define fg_carboxylic_acid_ester  78
458
#define fg_lactone      79
459
#define fg_carboxylic_acid_amide  80
460
#define fg_carboxylic_acid_prim_amide  81
461
#define fg_carboxylic_acid_sec_amide  82
462
#define fg_carboxylic_acid_tert_amide  83
463
#define fg_lactam       84
464
#define fg_carboxylic_acid_hydrazide  85
465
#define fg_carboxylic_acid_azide  86
466
#define fg_hydroxamic_acid  87
467
#define fg_carboxylic_acid_amidine  88
468
#define fg_carboxylic_acid_amidrazone  89
469
#define fg_nitrile      90
470
#define fg_acyl_halide  91
471
#define fg_acyl_fluoride  92
472
#define fg_acyl_chloride  93
473
#define fg_acyl_bromide  94
474
#define fg_acyl_iodide  95
475
#define fg_acyl_cyanide  96
476
#define fg_imido_ester  97
477
#define fg_imidoyl_halide  98
478
#define fg_thiocarboxylic_acid_deriv  99
479
#define fg_thiocarboxylic_acid  100
480
#define fg_thiocarboxylic_acid_ester  101
481
#define fg_thiolactone  102
482
#define fg_thiocarboxylic_acid_amide  103
483
#define fg_thiolactam   104
484
#define fg_imido_thioester  105
485
#define fg_oxohetarene  106
486
#define fg_thioxohetarene  107
487
#define fg_iminohetarene  108
488
#define fg_orthocarboxylic_acid_deriv  109
489
#define fg_carboxylic_acid_orthoester  110
490
#define fg_carboxylic_acid_amide_acetal  111
491
#define fg_carboxylic_acid_anhydride  112
492
#define fg_carboxylic_acid_imide  113
493
#define fg_carboxylic_acid_unsubst_imide  114
494
#define fg_carboxylic_acid_subst_imide  115
495
#define fg_co2_deriv    116
496
#define fg_carbonic_acid_deriv  117
497
#define fg_carbonic_acid_monoester  118
498
#define fg_carbonic_acid_diester  119
499
#define fg_carbonic_acid_ester_halide  120
500
#define fg_thiocarbonic_acid_deriv  121
501
#define fg_thiocarbonic_acid_monoester  122
502
#define fg_thiocarbonic_acid_diester  123
503
#define fg_thiocarbonic_acid_ester_halide  124
504
#define fg_carbamic_acid_deriv  125
505
#define fg_carbamic_acid  126
506
#define fg_carbamic_acid_ester  127
507
#define fg_carbamic_acid_halide  128
508
#define fg_thiocarbamic_acid_deriv  129
509
#define fg_thiocarbamic_acid  130
510
#define fg_thiocarbamic_acid_ester  131
511
#define fg_thiocarbamic_acid_halide  132
512
#define fg_urea         133
513
#define fg_isourea      134
514
#define fg_thiourea     135
515
#define fg_isothiourea  136
516
#define fg_guanidine    137
517
#define fg_semicarbazide  138
518
#define fg_thiosemicarbazide  139
519
#define fg_azide        140
520
#define fg_azo_compound  141
521
#define fg_diazonium_salt  142
522
#define fg_isonitrile   143
523
#define fg_cyanate      144
524
#define fg_isocyanate   145
525
#define fg_thiocyanate  146
526
#define fg_isothiocyanate  147
527
#define fg_carbodiimide  148
528
#define fg_nitroso_compound  149
529
#define fg_nitro_compound  150
530
#define fg_nitrite      151
531
#define fg_nitrate      152
532
#define fg_sulfuric_acid_deriv  153
533
#define fg_sulfuric_acid  154
534
#define fg_sulfuric_acid_monoester  155
535
#define fg_sulfuric_acid_diester  156
536
#define fg_sulfuric_acid_amide_ester  157
537
#define fg_sulfuric_acid_amide  158
538
#define fg_sulfuric_acid_diamide  159
539
#define fg_sulfuryl_halide  160
540
#define fg_sulfonic_acid_deriv  161
541
#define fg_sulfonic_acid  162
542
#define fg_sulfonic_acid_ester  163
543
#define fg_sulfonamide  164
544
#define fg_sulfonyl_halide  165
545
#define fg_sulfone      166
546
#define fg_sulfoxide    167
547
#define fg_sulfinic_acid_deriv  168
548
#define fg_sulfinic_acid  169
549
#define fg_sulfinic_acid_ester  170
550
#define fg_sulfinic_acid_halide  171
551
#define fg_sulfinic_acid_amide  172
552
#define fg_sulfenic_acid_deriv  173
553
#define fg_sulfenic_acid  174
554
#define fg_sulfenic_acid_ester  175
555
#define fg_sulfenic_acid_halide  176
556
#define fg_sulfenic_acid_amide  177
557
#define fg_thiol        178
558
#define fg_alkylthiol   179
559
#define fg_arylthiol    180
560
#define fg_phosphoric_acid_deriv  181
561
#define fg_phosphoric_acid  182
562
#define fg_phosphoric_acid_ester  183
563
#define fg_phosphoric_acid_halide  184
564
#define fg_phosphoric_acid_amide  185
565
#define fg_thiophosphoric_acid_deriv  186
566
#define fg_thiophosphoric_acid  187
567
#define fg_thiophosphoric_acid_ester  188
568
#define fg_thiophosphoric_acid_halide  189
569
#define fg_thiophosphoric_acid_amide  190
570
#define fg_phosphonic_acid_deriv  191
571
#define fg_phosphonic_acid  192
572
#define fg_phosphonic_acid_ester  193
573
#define fg_phosphine    194
574
#define fg_phosphinoxide  195
575
#define fg_boronic_acid_deriv  196
576
#define fg_boronic_acid  197
577
#define fg_boronic_acid_ester  198
578
#define fg_alkene       199
579
#define fg_alkyne       200
580
#define fg_aromatic     201
581
#define fg_heterocycle  202
582
#define fg_alpha_aminoacid  203
583
#define fg_alpha_hydroxyacid  204
584
 
585
typedef enum
18544 georgesk 586
  { isfalse = 0, istrue } boolean;
6785 bpr 587
 
588
typedef char str2[3];
589
 
590
typedef char str3[4];
591
 
592
typedef char str4[5];
593
 
594
typedef char str5[6];
595
 
596
typedef char str8[9];
597
 
598
typedef struct atom_rec
599
{
600
  str2 element;
601
  str3 atype;
602
  float x, y, z;
603
  int formal_charge;
604
  float real_charge;
14179 bpr 605
  int Hexp;      /* explicit H count */
606
  int Htot;      /* total H count */
6785 bpr 607
  int neighbor_count, ring_count;
14179 bpr 608
  boolean arom, stereo_care;  /* new in v0.3d */
609
  boolean q_arom;    // v0.3p potentially aromatic in a query structure
610
  boolean heavy;    /* new in v0.3l */
611
  boolean metal;    /* new in v0.3l */
612
  int nvalences;    /* new in v0.3m */
613
  boolean tag;      /* new in v0.3o */
614
  int nucleon_number;   /* 0.3.x */
6785 bpr 615
  int radical_type;             /* 0.3.x */
616
} atom_rec;
617
 
618
typedef struct bond_rec
619
{
620
  int a1, a2;
621
  char btype;
622
  int ring_count;
623
  boolean arom;
14179 bpr 624
  boolean q_arom;    // v0.3p potentially aromatic in a query structure
625
  int topo;      /* new in v0.3d, see MDL file description */
626
  int stereo;    /* new in v0.3d */
627
  int mdl_stereo;/* new in v0.3n */
6785 bpr 628
} bond_rec;
629
 
630
typedef int ringpath_type[max_ringsize];
631
typedef int matchpath_type[max_matchpath_length];
632
 
633
typedef atom_rec atomlist[max_atoms];
634
typedef bond_rec bondlist[max_bonds];
635
typedef ringpath_type ringlist[max_rings];
14179 bpr 636
typedef int neighbor_rec[max_neighbors];  /* new in v0.2h */
6785 bpr 637
typedef boolean fglist[max_fg];
638
 
639
typedef char molbuftype[max_atoms + max_bonds + slack][256];
640
 
641
typedef boolean matchmatrix[max_neighbors][max_neighbors];
642
    /* new in v0.2i */
643
 
644
typedef struct molstat_rec
645
{
14179 bpr 646
  int n_QA, n_QB, n_chg;  /* number of query atoms, query bonds, charges */
6785 bpr 647
  int n_C1, n_C2, n_C;
648
  /* number of sp, sp2 hybridized, and total no. of carbons */
649
  int n_CHB1p, n_CHB2p, n_CHB3p, n_CHB4;
650
  /* number of C atoms with at least 1, 2, 3 hetero bonds */
14179 bpr 651
  int n_O2, n_O3;    /* number of sp2 and sp3 oxygens */
652
  int n_N1, n_N2, n_N3;    /* number of sp, sp2, and sp3 nitrogens */
6785 bpr 653
  int n_S, n_SeTe;
654
  /* number of sulfur atoms and selenium or tellurium atoms */
655
  int n_F, n_Cl, n_Br, n_I;
656
  /* number of fluorine, chlorine, bromine, iodine atoms */
14179 bpr 657
  int n_P, n_B;      /* number of phosphorus and boron atoms */
6785 bpr 658
  int n_Met, n_X;
659
  /* number of metal and "other" atoms (not listed elsewhere); v0.3l */
660
  int n_b1, n_b2, n_b3, n_bar;
661
  /* number single, double, triple, and aromatic bonds */
662
  int n_C1O, n_C2O, n_CN, n_XY;
663
  /* number of C-O single bonds, C=O double bonds, CN bonds (any type), hetero/hetero bonds */
664
  int n_r3, n_r4, n_r5, n_r6, n_r7, n_r8;
665
  /* number of 3-, 4-, 5-, 6-, 7-, and 8-membered rings */
666
  int n_r9, n_r10, n_r11, n_r12, n_r13p;
667
  /* number of 9-, 10-, 11-, 12-, and 13plus-membered rings */
668
  int n_rN, n_rN1, n_rN2, n_rN3p;
669
  /* number of rings containing N (any number), 1 N, 2 N, and 3 N or more */
670
  int n_rO, n_rO1, n_rO2p;
671
  /* number of rings containing O (any number), 1 O, and 2 O or more */
672
  int n_rS, n_rX, n_rAr, n_rBz;
673
  /* number of rings containing S (any number), any heteroatom (any number),  */
674
  /* number of aromatic rings, number of benzene rings */
14179 bpr 675
  int n_br2p;      /* number of bonds belonging to more than one ring (v0.3n) */
676
  /* p2c: checkmol.pas, line 590:
677
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 678
  /*$IFDEF extended_molstat */
679
  int n_psg01, n_psg02, n_psg13, n_psg14;
680
  /* number of atoms belonging to elements of group 1, 2, etc.  */
681
  int n_psg15, n_psg16, n_psg17, n_psg18;
682
  /* number of atoms belonging to elements of group 15, 16, etc.  */
683
  int n_pstm, n_psla;
684
  /* number of transition metals, lanthanides/actinides */
685
  int n_iso, n_rad;
686
  /* number of isotopes, radicals */
687
  /*$ENDIF */
688
} molstat_rec;
689
 
690
typedef struct ringprop_rec
691
{
692
  /* new in v0.3 */
693
  int size;
694
  boolean arom, envelope;
695
} ringprop_rec;
696
 
697
typedef ringprop_rec ringprop_type[max_rings];
698
 
699
typedef struct p_3d
700
{
701
  /* new in v0.3d */
702
  double x, y, z;
703
} p_3d;
704
 
14179 bpr 705
typedef int chirpath_type[4];  /* new in v0.3f */
6785 bpr 706
 
707
#ifdef MAKE_SHARED_LIBRARY
18544 georgesk 708
static boolean yet_initialized = isfalse;
6785 bpr 709
#endif
710
 
711
typedef struct connval_rec
712
{
713
  /* new in v0.3j */
14179 bpr 714
  int def;      /* better as longint for large molecules? */
6785 bpr 715
  int tmp;
716
} connval_rec;
717
 
14179 bpr 718
typedef connval_rec connval_type[max_atoms];  /* new in v0.3j  */
6785 bpr 719
 
720
static int progmode;
721
static char progname[256];
722
 
723
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 724
static int i;      /* general purpose index */
6785 bpr 725
#endif
726
 
727
static int li;
728
static boolean opt_none, opt_verbose, opt_text, opt_text_de, opt_code,
729
  opt_bin, opt_bitstring, opt_stdin, opt_exact, opt_debug,
730
  opt_molout, opt_molstat, opt_molstat_X, opt_xmdlout, opt_strict;
731
    /* new in v0.2f */
14179 bpr 732
static boolean opt_metalrings;  /* new in v0.3 */
733
static boolean opt_geom;  /* new in v0.3d */
734
static boolean opt_chiral;  /* new in v0.3f */
735
static boolean opt_iso;    /* new in v0.3x */
736
static boolean opt_chg;    /* new in v0.3x */
737
static boolean opt_rad;    /* new in v0.3x */
738
static int opt_rs;    /* new in v0.3i */
6785 bpr 739
 
740
#ifdef MAKE_SHARED_LIBRARY
741
static int opt_rs_dll = RPA_DEFAULT;
742
#endif
743
 
14179 bpr 744
static boolean opt_fp;    /* new in v0.3m */
745
static int fpformat;    /* new in v0.3m */
6785 bpr 746
static char filetype[256];
747
/*molfile : text; */
748
static char molfilename[256];
749
static char ndl_molfilename[256];
750
static char molname[256];
751
static char ndl_molname[256];
14179 bpr 752
static char tmp_molname[256];  /* v0.3m */
6785 bpr 753
static char molcomment[256];
754
static int n_atoms, n_bonds, n_rings;
755
    /* the number of rings we determined ourselves */
756
static int n_countablerings;
757
    /* v0.3n; number of rings which are not envelope rings */
758
static int n_cmrings;
759
    /* the number of rings we read from a (CheckMol-tweaked) MDL molfile */
760
//static int n_charges;         /* number of charges */
761
static int n_heavyatoms, n_heavybonds, ndl_n_atoms, ndl_n_bonds, ndl_n_rings,
762
  ndl_n_heavyatoms, ndl_n_heavybonds;
763
/*cm_mdlmolfile  : boolean; */
764
static boolean found_arominfo, found_querymol, ndl_querymol;
14179 bpr 765
static int tmp_n_atoms;    /* v0.3m */
766
static int tmp_n_bonds;    /* v0.3m */
767
static int tmp_n_rings;    /* v0.3m */
768
static int tmp_n_heavyatoms;  /* v0.3m */
769
static int tmp_n_heavybonds;  /* v0.3m */
6785 bpr 770
 
771
static atom_rec *atom;
772
static bond_rec *bond;
773
static ringpath_type *ring;
14179 bpr 774
static ringprop_rec *ringprop;  /* new in v0.3 */
6785 bpr 775
 
776
static atom_rec *ndl_atom;
777
static bond_rec *ndl_bond;
778
static ringpath_type *ndl_ring;
14179 bpr 779
static ringprop_rec *ndl_ringprop;  /* new in v0.3 */
780
static int ndl_ref_atom;  /* since v0.3j as a global variable */
781
static atom_rec *tmp_atom;  /* v0.3m */
782
static bond_rec *tmp_bond;  /* v0.3m */
783
static ringpath_type *tmp_ring;  /* v0.3m */
784
static ringprop_rec *tmp_ringprop;  /* v0.3m */
6785 bpr 785
 
14179 bpr 786
static boolean matchresult, matchsummary;  /* v0.3o */
6785 bpr 787
static matchpath_type ndl_matchpath, hst_matchpath;
788
 
789
static fglist fg;
790
static str4 atomtype;
791
static str3 newatomtype;
792
 
793
static char (*molbuf)[256];
794
static int molbufindex;
795
 
796
static boolean mol_in_queue;
797
static int mol_count;
798
 
14179 bpr 799
static molstat_rec molstat, ndl_molstat, tmp_molstat;  /* v0.3m */
6785 bpr 800
 
14179 bpr 801
static int ringsearch_mode, max_vringsize;  /* for SSR ring search */
6785 bpr 802
 
803
static FILE *rfile;
14179 bpr 804
static boolean rfile_is_open, mol_OK;  /* new in v0.2i */
6785 bpr 805
 
14179 bpr 806
static int n_ar;    /* new in v0.3 */
807
static int prev_n_ar;    /* new in v0.3 */
808
static boolean ez_search;  /* new in v0.3d */
809
static boolean rs_search;  /* new in v0.3f */
810
static boolean ez_flag;    /* new in v0.3f */
811
static boolean chir_flag;  /* new in v0.3f */
812
static boolean rs_strict;  /* new in v0.3j */
6785 bpr 813
 
14179 bpr 814
static int n_Ctot, n_Otot, n_Ntot;  /* new in v0.3g */
815
static int ndl_n_Ctot, ndl_n_Otot, ndl_n_Ntot;  /* new in v0.3g */
816
static int tmp_n_Ctot, tmp_n_Otot, tmp_n_Ntot;  /* new in v0.3m */
817
static boolean ether_generic;  /* v0.3j */
818
static boolean amine_generic;  /* v0.3j   */
819
static boolean hydroxy_generic;  /* v0.3j */
820
static connval_rec *cv;    /* new in v0.3j */
821
static long long fpdecimal;  /* v0.3m */
6785 bpr 822
static long long fpincrement;
823
static int fpindex;
824
static boolean fp_exacthit, fp_exactblock;
825
static int tmfcode;
826
    /* v0.3m; version number for tweaked MDL molfiles (tweaklevel) */
827
static boolean tmfmismatch;
828
    /* v0.3m; rely on tweaked MDL molfiles only if same level */
829
static boolean auto_ssr;
830
    /* v0.3n; indicates that SAR -> SSR fallback has happened */
831
static int recursion_depth;
832
    /* ====================emulated pascal functions============================ */
833
 
834
static boolean
835
file_exists (const char *fileName)
836
{
837
  struct stat filestat;
838
 
18544 georgesk 839
  return stat (fileName, &filestat) == 0 ? istrue : isfalse;
6785 bpr 840
}
841
 
14179 bpr 842
static void lblank (int cols, char *nstr)
6785 bpr 843
{
844
  /* inserts leading blanks up to a given number of total characters */
845
  char STR1[256];
846
 
847
  if (strlen (nstr) >= cols)
848
    return;
849
  while (strlen (nstr) < cols)
850
    sprintf (nstr, " %s", strcpy (STR1, nstr));
851
}
852
 
14179 bpr 853
static inline double radtodeg (double rads)
6785 bpr 854
{
855
  return (180.0 / M_PI) * rads;
856
}
857
 
14179 bpr 858
static void strdelete (char *s, int pos, int len)
6785 bpr 859
{
860
  int slen;
861
 
862
  if (--pos < 0)
863
    return;
864
  slen = strlen (s) - pos;
865
  if (slen <= 0)
866
    return;
867
  s += pos;
14179 bpr 868
  if (slen <= len) {
869
    *s = 0;
870
    return;
871
  }
6785 bpr 872
  while ((*s = s[len]))
873
    s++;
874
}
875
 
14179 bpr 876
static int strpos2 (char *s, char *pat, int pos)
6785 bpr 877
{
878
  char *cp, ch;
879
  int slen;
880
 
881
  if (--pos < 0)
882
    return 0;
883
  slen = strlen (s) - pos;
884
  cp = s + pos;
885
  if (!(ch = *pat++))
886
    return 0;
887
  pos = strlen (pat);
888
  slen -= pos;
14179 bpr 889
  while (--slen >= 0) {
890
    if (*cp++ == ch && !strncmp (cp, pat, pos))
891
      return cp - s;
892
  }
6785 bpr 893
  return 0;
894
}
895
 
14179 bpr 896
static char * strsub (char *ret, char *s, int pos, int len)
6785 bpr 897
{
898
  char *s2;
899
 
14179 bpr 900
  if (--pos < 0 || len <= 0){
901
    *ret = 0;
902
    return ret;
903
  }
904
  while (pos > 0){
905
    if (!*s++){
6785 bpr 906
      *ret = 0;
907
      return ret;
908
    }
14179 bpr 909
    pos--;
910
  }
6785 bpr 911
  s2 = ret;
14179 bpr 912
  while (--len >= 0){
913
    if (!(*s2++ = *s++))
914
      return ret;
915
  }
6785 bpr 916
  *s2 = 0;
917
  return ret;
918
}
919
 
920
/*============================= auxiliary functions & procedures */
921
 
14179 bpr 922
inline static void all_lowercase (char *astring)
6785 bpr 923
{
924
  int i;
925
  int l = strlen (astring);
926
 
14179 bpr 927
  for (i = 0; i < l; i++){
928
    astring[i] = tolower (astring[i]);
929
  }
6785 bpr 930
}
931
 
14179 bpr 932
static void init_globals ()
6785 bpr 933
{
934
  /*int i;*/
935
 
18544 georgesk 936
  opt_verbose = isfalse;
937
  opt_debug = isfalse;
938
  opt_exact = isfalse;
939
  opt_stdin = isfalse;
940
  opt_text = isfalse;
941
  opt_code = isfalse;
942
  opt_bin = isfalse;
943
  opt_bitstring = isfalse;
944
  opt_molout = isfalse;
945
  opt_molstat = isfalse;
946
  opt_molstat_X = isfalse;
947
  opt_xmdlout = isfalse;
948
  opt_strict = isfalse; /* new in v0.2f */
949
  opt_metalrings = isfalse;  /* new in v0.3 */
950
  opt_geom = isfalse;   /* new in v0.3d */
951
  opt_chiral = isfalse; /* new in v0.3f */
952
  opt_fp = isfalse;     /* new in v0.3m */
953
  opt_iso = isfalse;    /* new in v0.3x */
954
  opt_chg = isfalse;    /* new in v0.3x */
955
  opt_rad = isfalse;    /* new in v0.3x */
956
  /*cm_mdlmolfile   := isfalse; */
957
  found_arominfo = isfalse;
958
  found_querymol = isfalse;
959
  ndl_querymol = isfalse;
14179 bpr 960
  opt_rs = rs_sar;    /* v0.3i */
6785 bpr 961
  /*ringsearch_mode := rs_sar; */
18544 georgesk 962
  rfile_is_open = isfalse;/* new in v0.2g */
963
  ez_search = isfalse;    /* new in v0.3d */
964
  rs_search = isfalse;    /* new in v0.3f */
965
  ez_flag = isfalse;      /* new in v0.3f */
966
  chir_flag = isfalse;    /* new in v0.3f */
967
  rs_strict = isfalse;    /* new in v0.3j */
6785 bpr 968
  n_Ctot = 0;
969
  n_Otot = 0;
14179 bpr 970
  n_Ntot = 0;      /* new in v0.3g */
6785 bpr 971
  ndl_n_Ctot = 0;
972
  ndl_n_Otot = 0;
14179 bpr 973
  ndl_n_Ntot = 0;   /* new in v0.3g */
6785 bpr 974
  //for (i = 0; i < max_fg; i++)
18544 georgesk 975
  //  fg[i] = isfalse;
6785 bpr 976
  memset (fg, 0, sizeof (fglist));
977
  /*try */
978
  molbuf = safe_malloc (sizeof (molbuftype));
979
  /*except
980
     on e:Eoutofmemory do
981
     begin
982
     writeln('Not enough memory');
983
     halt(4);
984
     end;
985
     end; */
18544 georgesk 986
  ether_generic = isfalse;  /* v0.3j */
987
  amine_generic = isfalse;  /* v0.3j */
988
  hydroxy_generic = isfalse;/* v0.3j */
14179 bpr 989
  fpformat = fpf_decimal; /* v0.3m */
990
  fpindex = 0;            /* v0.3m */
18544 georgesk 991
  fp_exacthit = isfalse;    /* v0.3m */
992
  fp_exactblock = isfalse;  /* v0.3m */
14179 bpr 993
  tmfcode = 0;            /* v0.3m */
18544 georgesk 994
  tmfmismatch = isfalse;    /* v0.3m */
995
  auto_ssr = isfalse;       /* v0.3n */
6785 bpr 996
  recursion_depth = 0;
997
}
998
 
17891 bpr 999
static inline void init_molstat (molstat_rec *mstat)
6785 bpr 1000
{
1001
  /*
1002
     with mstat do
1003
     begin
1004
     n_QA := 0; n_QB := 0; n_chg := 0;
1005
     n_C1 := 0; n_C2 := 0; n_C  := 0;
1006
     n_CHB1p := 0; n_CHB2p := 0; n_CHB3p := 0; n_CHB4 := 0;
1007
     n_O2 := 0; n_O3  := 0;
1008
     n_N1 := 0; n_N2 := 0; n_N3 := 0;
1009
     n_S := 0; n_SeTe := 0;
1010
     n_F := 0; n_Cl := 0; n_Br := 0; n_I := 0;
1011
     n_P := 0; n_B := 0;
1012
     n_Met := 0; n_X := 0;
1013
     n_b1 := 0; n_b2 := 0; n_b3 := 0; n_bar := 0;
1014
     n_C1O := 0; n_C2O := 0; n_CN := 0; n_XY := 0;
1015
     n_r3 := 0; n_r4 := 0; n_r5 := 0; n_r6 := 0; n_r7 := 0;
1016
     n_r8 := 0; n_r9 := 0; n_r10 := 0; n_r11 := 0; n_r12 := 0; n_r13p := 0;
1017
     n_rN := 0; n_rN1 := 0; n_rN2 := 0; n_rN3p := 0;
1018
     n_rO := 0; n_rO1 := 0; n_rO2p := 0;
1019
     n_rS := 0; n_rX := 0;
1020
     n_rAr := 0; n_rBz := 0; n_br2p := 0;
1021
     end;
1022
   */
14179 bpr 1023
  memset (mstat, 0, sizeof (molstat_rec));  /* v0.3k */
6785 bpr 1024
}
1025
 
1026
#if 0
14179 bpr 1027
static void debugoutput (dstr)
1028
  char *dstr;
6785 bpr 1029
{
1030
  if (opt_debug)
1031
    printf ("%s\n", dstr);
1032
}
1033
#endif
1034
 
17891 bpr 1035
static void left_trim (char *trimstr)
6785 bpr 1036
{
1037
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1038
    strdelete (trimstr, 1, 1);
1039
}
14626 bpr 1040
/* left_int fixed by D. Bernardi (2020-02-01) */
1041
static int left_int (char *trimstr)
6785 bpr 1042
{
14626 bpr 1043
  char *s = trimstr;
1044
  int r = 0;
1045
  int sg = 1;
6785 bpr 1046
 
14626 bpr 1047
  while (*s == ' ' || *s == '\t' || *s == '+' || *s == '-')
1048
    {if (*s == '-') sg = -sg; s++;}
1049
  while (*s >= '0' && *s <= '9')
1050
    r = 10*r + *s++ - '0';
1051
  while ((*trimstr++ = *s++)); /* gag! */
1052
  return sg * r;
6785 bpr 1053
}
1054
 
14179 bpr 1055
static int path_pos (int id, int *a_path)
6785 bpr 1056
{
1057
  int i = 0;
1058
 
14179 bpr 1059
  for (i = 0; i < max_ringsize; i++){
1060
    if (*(a_path++) == id) {
1061
      return ++i;
6785 bpr 1062
    }
14179 bpr 1063
  }
6785 bpr 1064
  return 0;
1065
}
1066
 
14179 bpr 1067
static int path_length (int *a_path)
6785 bpr 1068
{
1069
  if ((a_path[max_ringsize - 1] != 0) && (path_pos (0, a_path) == 0))
1070
    return max_ringsize;
1071
  else
1072
    return (path_pos (0, a_path) - 1);
1073
}
1074
 
14179 bpr 1075
static int get_bond (int ba1, int ba2)
6785 bpr 1076
{
1077
  int i;
1078
  int b_id = 0;
1079
  int FORLIM;
1080
 
1081
  if (n_bonds <= 0)
1082
    return b_id;
1083
  FORLIM = n_bonds;
14179 bpr 1084
  for (i = 1; i <= FORLIM; i++) {
1085
    if ((bond[i - 1].a1 == ba1 && bond[i - 1].a2 == ba2) ||
1086
      (bond[i - 1].a1 == ba2 && bond[i - 1].a2 == ba1))
1087
      b_id = i;
1088
  }
6785 bpr 1089
  return b_id;
1090
}
1091
 
14179 bpr 1092
static void clear_atom_tags ()
6785 bpr 1093
{
1094
  int i, FORLIM;
1095
 
14179 bpr 1096
  if (n_atoms > 0) {
1097
    FORLIM = n_atoms;
1098
    for (i = 0; i < FORLIM; i++)
18544 georgesk 1099
      atom[i].tag = isfalse;
14179 bpr 1100
  }
6785 bpr 1101
}
1102
 
1103
#if 0
14179 bpr 1104
static void set_atom_tags ()
6785 bpr 1105
{
1106
  int i, FORLIM;
1107
 
14179 bpr 1108
  if (n_atoms > 0){
1109
    FORLIM = n_atoms;
1110
    for (i = 0; i < FORLIM; i++)
18544 georgesk 1111
      atom[i].tag = istrue;
14179 bpr 1112
  }
6785 bpr 1113
}
1114
#endif
14179 bpr 1115
static void order_ringpath (int *r_path)
6785 bpr 1116
{
1117
  /* order should be: array starts with atom of lowest number, followed by neighbor atom with lower number */
1118
  int i, pl, a_ref, a_left, a_right, a_tmp;
1119
 
1120
  pl = path_length (r_path);
1121
  if (pl < 3)
1122
    return;
1123
  a_ref = n_atoms;
1124
  /* start with highest possible value for an atom number */
14179 bpr 1125
  for (i = 0; i < pl; i++){
1126
    if (r_path[i] < a_ref)  /* find the minimum value ==> reference atom */
1127
     a_ref = r_path[i];
1128
  }
1129
  if (a_ref < 1)   /* just to be sure */
6785 bpr 1130
    return;
1131
  if (path_pos (a_ref, r_path) < pl)
1132
    a_right = r_path[path_pos (a_ref, r_path)];
1133
  else
1134
    a_right = r_path[0];
1135
  if (path_pos (a_ref, r_path) > 1)
1136
    a_left = r_path[path_pos (a_ref, r_path) - 2];
1137
  else
1138
    a_left = r_path[pl - 1];
14179 bpr 1139
  if (a_right == a_left)  /* should never happen */
6785 bpr 1140
    return;
14179 bpr 1141
  if (a_right < a_left) {
6785 bpr 1142
      /* correct ring numbering direction, only shift of the reference atom to the left end required */
14179 bpr 1143
    while (path_pos (a_ref, r_path) > 1){
1144
      a_tmp = r_path[0];
1145
      for (i = 1; i < pl; i++)
1146
        r_path[i - 1] = r_path[i];
1147
      r_path[pl - 1] = a_tmp;
6785 bpr 1148
    }
14179 bpr 1149
    return;
1150
  }
1151
  while (path_pos (a_ref, r_path) < pl) {
6785 bpr 1152
      /* step one: create "mirrored" ring path with reference atom at right end */
14179 bpr 1153
    a_tmp = r_path[pl - 1];
1154
    for (i = pl; i >= 2; i--)
1155
      r_path[i - 1] = r_path[i - 2];
1156
    r_path[0] = a_tmp;
1157
  }
1158
  for (i = 1; i <= pl / 2; i++){        /* one more mirroring */
1159
    a_tmp = r_path[i - 1];
1160
    r_path[i - 1] = r_path[pl - i];
1161
    r_path[pl - i] = a_tmp;
1162
    /* wrong ring numbering direction, two steps required */
1163
  }
6785 bpr 1164
}
1165
 
14179 bpr 1166
static void clear_ndl_atom_tags ()
6785 bpr 1167
{
1168
  int i;
1169
 
14179 bpr 1170
  if (ndl_n_atoms > 0){
1171
    for (i = 0; i < ndl_n_atoms; i++)
18544 georgesk 1172
      ndl_atom[i].tag = isfalse;
14179 bpr 1173
  }
6785 bpr 1174
}
1175
 
14179 bpr 1176
static void set_ndl_atom_tags ()
6785 bpr 1177
{
1178
  int i;
1179
 
14179 bpr 1180
  if (ndl_n_atoms > 0){
1181
    for (i = 0; i < ndl_n_atoms; i++)
18544 georgesk 1182
     ndl_atom[i].tag = istrue;
14179 bpr 1183
  }
6785 bpr 1184
}
1185
 
14179 bpr 1186
static int count_tagged_ndl_heavyatoms ()
6785 bpr 1187
{
1188
  int i;
1189
  int n = 0;
1190
 
1191
  if (ndl_n_atoms < 1)
1192
    return n;
1193
 
14179 bpr 1194
  for (i = 0; i < ndl_n_atoms; i++){
1195
    if (ndl_atom[i].heavy && ndl_atom[i].tag)
1196
    n++;
1197
  }
6785 bpr 1198
  return n;
1199
}
1200
 
1201
/*============================= geometry functions ========================== */
1202
 
17891 bpr 1203
static double dist3d (p_3d p1, p_3d p2)
6785 bpr 1204
{
1205
  double res, TEMP, TEMP1, TEMP2;
1206
 
1207
  TEMP = p1.x - p2.x;
1208
  TEMP1 = p1.y - p2.y;
1209
  TEMP2 = p1.z - p2.z;
1210
  res = sqrt (TEMP * TEMP + TEMP1 * TEMP1 + TEMP2 * TEMP2);
1211
  return res;
1212
}
1213
 
1214
/*
1215
function is_cis(p1,p2,p3,p4:p_3d):boolean;  (* new in v0.3d
1216
var                         (* just a simple, distance-based estimation
1217
  total_dist  : double;     (* instead of calculating the dihedral angle
1218
  direct_dist : double;
1219
  res         : boolean;
1220
begin
18544 georgesk 1221
  res := isfalse;
6785 bpr 1222
  total_dist  := dist3d(p1,p2) + dist3d(p2,p3) + dist3d(p3,p4);
1223
  direct_dist := dist3d(p1,p4);
18544 georgesk 1224
  if (direct_dist < 0.78 * total_dist) then res := istrue;  (* cutoff value of 0.78 was
6785 bpr 1225
  is_cis := res;                                          (* experimentally determined
1226
end;
1227
*/
1228
/* function is_cis was replaced by a new one in v0.3h */
1229
 
17891 bpr 1230
static p_3d subtract_3d (p_3d p1, p_3d p2)
6785 bpr 1231
{
1232
  p_3d p;
1233
 
1234
  p.x = p1.x - p2.x;
1235
  p.y = p1.y - p2.y;
1236
  p.z = p1.z - p2.z;
1237
  return p;
1238
}
1239
 
17891 bpr 1240
static p_3d add_3d (p_3d p1, p_3d p2)
6785 bpr 1241
{
1242
  p_3d p;
1243
 
1244
  p.x = p1.x + p2.x;
1245
  p.y = p1.y + p2.y;
1246
  p.z = p1.z + p2.z;
1247
  return p;
1248
}
1249
 
1250
#if 0
14179 bpr 1251
static void vec2origin (p1, p2)
6785 bpr 1252
     p_3d *p1, *p2;
1253
{
1254
  p_3d p;
1255
 
1256
  p = subtract_3d (*p2, *p1);
1257
  *p2 = p;
1258
  p1->x = 0.0;
1259
  p1->y = 0.0;
1260
  p1->z = 0.0;
1261
}
1262
#endif
1263
 
17891 bpr 1264
static double scalar_prod (p_3d p1, p_3d p2, p_3d p3)
6785 bpr 1265
{
1266
  p_3d p;
1267
  double res;
1268
 
1269
  p = subtract_3d (p2, p1);
1270
  p2 = p;
1271
  p = subtract_3d (p3, p1);
1272
  p3 = p;
1273
  p1.x = 0.0;
1274
  p1.y = 0.0;
1275
  p1.z = 0.0;
1276
  res = p2.x * p3.x + p2.y * p3.y + p2.z * p3.z;
1277
  return res;
1278
}
1279
 
17891 bpr 1280
static p_3d cross_prod (p_3d p1, p_3d p2, p_3d p3)
6785 bpr 1281
{
1282
  p_3d p, orig_p1;
1283
 
1284
  orig_p1 = p1;
1285
  p = subtract_3d (p2, p1);
1286
  p2 = p;
1287
  p = subtract_3d (p3, p1);
1288
  p3 = p;
1289
  p.x = p2.y * p3.z - p2.z * p3.y;
1290
  p.y = p2.z * p3.x - p2.x * p3.z;
1291
  p.z = p2.x * p3.y - p2.y * p3.x;
1292
  return (add_3d (orig_p1, p));
1293
}
1294
 
17891 bpr 1295
static double angle_3d (p_3d p1, p_3d p2, p_3d p3)
6785 bpr 1296
{
1297
  p_3d lp1, lp2, lp3, p;
1298
  double res = 0.0;
1299
  double magn_1, magn_2, cos_phi;
1300
 
1301
  lp1 = p1;
1302
  lp2 = p2;
1303
  lp3 = p3;
1304
  p = subtract_3d (lp2, lp1);
1305
  lp2 = p;
1306
  p = subtract_3d (lp3, lp1);
1307
  lp3 = p;
1308
  lp1.x = 0.0;
1309
  lp1.y = 0.0;
1310
  lp1.z = 0.0;
1311
  magn_1 = dist3d (lp1, lp2);
1312
  magn_2 = dist3d (lp1, lp3);
14179 bpr 1313
  if (magn_1 * magn_2 == 0)  /* emergency exit */
6785 bpr 1314
    return M_PI;
1315
  cos_phi = scalar_prod (lp1, lp2, lp3) / (magn_1 * magn_2);
1316
  if (cos_phi < -1)
1317
    cos_phi = -1.0;
1318
  if (cos_phi > 1)
1319
    cos_phi = 1.0;
1320
  res = acos (cos_phi);
1321
  return res;
1322
}
1323
 
17891 bpr 1324
static double torsion (p_3d p1, p_3d p2, p_3d p3, p_3d p4)
6785 bpr 1325
{
1326
  p_3d lp1, lp2, lp3, lp4, d1, c1, c2;
1327
  double res;
1328
  p_3d c1xc2, c2xc1;
1329
  double dist1, dist2, sign;
1330
 
1331
  /* copy everything into local variables */
1332
  lp1 = p1;
1333
  lp2 = p2;
1334
  lp3 = p3;
1335
  lp4 = p4;
1336
  /* get the vector between the two central atoms */
1337
  d1 = subtract_3d (p3, p2);
1338
  /* shift the first atom parallel to be attached to p3 instead of p2 */
1339
  lp1 = add_3d (p1, d1);
1340
  /* now get the cross product vectors */
1341
  c1 = cross_prod (lp3, lp2, lp1);
1342
  c2 = cross_prod (lp3, lp2, lp4);
1343
  res = angle_3d (p3, c1, c2);
1344
  /*now check if it is clockwise or anticlockwise: */
1345
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1346
  c1xc2 = cross_prod (lp3, c1, c2);
1347
  c2xc1 = cross_prod (lp3, c2, c1);
1348
  /*next, get the distances from these points to our refernce point lp2 */
1349
  dist1 = dist3d (lp2, c1xc2);
1350
  dist2 = dist3d (lp2, c2xc1);
1351
  if (dist1 <= dist2)
1352
    sign = 1.0;
1353
  else
1354
    sign = -1.0;
1355
  return (sign * res);
1356
}
1357
 
17891 bpr 1358
static double ctorsion (p_3d p1, p_3d p2, p_3d p3, p_3d p4)
6785 bpr 1359
{
1360
  /* calculates "pseudo-torsion" defined by atoms 3 and 4, being both */
1361
  /* attached to atom 2, with respect to axis of atoms 1 and 2 */
1362
  p_3d lp1, lp2, lp3, lp4;
1363
  /*d1 : p_3d; */
1364
  p_3d c1, c2;
1365
  double res;
1366
  p_3d c1xc2, c2xc1;
1367
  double dist1, dist2, sign;
1368
 
1369
  /* copy everything into local variables */
1370
  lp1 = p1;
1371
  lp2 = p2;
1372
  lp3 = p3;
1373
  lp4 = p4;
1374
  /* get the cross product vectors */
1375
  c1 = cross_prod (lp2, lp1, lp3);
1376
  c2 = cross_prod (lp2, lp1, lp4);
1377
  res = angle_3d (p2, c1, c2);
1378
  /*now check if it is clockwise or anticlockwise: */
1379
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1380
  c1xc2 = cross_prod (lp2, c1, c2);
1381
  c2xc1 = cross_prod (lp2, c2, c1);
1382
  /*next, get the distances from these points to our refernce point lp1 */
1383
  dist1 = dist3d (lp1, c1xc2);
1384
  dist2 = dist3d (lp1, c2xc1);
1385
  if (dist1 <= dist2)
1386
    sign = 1.0;
1387
  else
1388
    sign = -1.0;
1389
  return (sign * res);
1390
}
1391
 
17891 bpr 1392
static boolean is_cis (p_3d p1, p_3d p2, p_3d p3, p_3d p4)
6785 bpr 1393
{
1394
  /* new in v0.3h, uses the dihedral angle */
1395
  double phi;
18544 georgesk 1396
  boolean res = isfalse;
6785 bpr 1397
 
1398
  phi = torsion (p1, p2, p3, p4);
1399
  if (fabs (phi) < M_PI / 2)
18544 georgesk 1400
    res = istrue;
6785 bpr 1401
  return res;
1402
}
1403
 
1404
/*====================== end of geometry functions ========================== */
1405
 
14179 bpr 1406
static void show_usage () {
1407
  if (progmode == pmMatchMol) {
1408
    printf ("matchmol version %s  N. Haider, University of Vienna, 2003-2007\n", version);
1409
    printf ("Usage: matchmol [options] <needle> <haystack>\n");
1410
    printf (" where <needle> and <haystack> are the two molecules to compare\n");
1411
    printf (" (supported formats: MDL *.mol or *.sdf, Alchemy *.mol, Sybyl *.mol2)\n");
1412
    printf (" options can be:\n");
1413
    printf ("    -v  verbose output\n");
1414
    printf ("    -x  exact match\n");
1415
    printf ("    -s  strict comparison of atom and bond types (including ring check)\n");
6785 bpr 1416
      /* new in v0.2f, v0.3d */
14179 bpr 1417
    printf ("    -r  force SSR (set of small rings) ring search mode\n");
1418
    printf ("    -m  write matching molecule as MDL molfile to standard output\n");
1419
    printf ("        (default output: record number + \":T\" for hit  or \":F\" for miss\n");
1420
    printf ("    -M  accept metal atoms as ring members\n");
1421
    printf ("    -g  check geometry of double bonds (E/Z)\n");
1422
    printf ("    -G  check geometry of chiral centers (R/S)\n");
1423
    printf ("    -a  check charges strict\n");   /* 0.3x */
1424
    printf ("    -i  check isotopes strict\n");  /* 0.3x */
1425
    printf ("    -d  check radicals strict\n");  /* 0.3x */
1426
    printf ("    -f  fingerprint mode (1 haystack, multiple needles) with boolean output\n");
1427
    printf ("    -F  fingerprint mode (1 haystack, multiple needles) with decimal output\n");
1428
    return;
1429
  }
1430
  printf ("checkmol version %s  N. Haider, University of Vienna, 2003-2007\n", version);
6785 bpr 1431
  printf ("Usage: checkmol [options] <filename>\n");
1432
  printf (" where options can be:\n");
14179 bpr 1433
  printf ("    -l  print a list of fingerprint codes + explanation and exit\n");
6785 bpr 1434
  printf ("    -v  verbose output\n");
1435
  printf ("    -r  force SSR (set of small rings) ring search mode\n");
1436
  printf ("    -M  accept metal atoms as ring members\n");
1437
  printf ("  and one of the following:\n");
14179 bpr 1438
  printf ("    -e  english text (common name of functional group; default)\n");
6785 bpr 1439
  printf ("    -d  german text (common name of functional group)\n");
1440
  printf ("    -c  code (acronym-like code for functional group)\n");
14179 bpr 1441
  printf ("    -b  binary (a bitstring representing absence or presence of each group)\n");
1442
  printf ("    -s  the ASCII representation of the above bitstring, i.e. 0s and 1s)\n");
1443
  printf ("    -x  print molecular statistics (number of various atom types, bond types,\n");
6785 bpr 1444
  printf ("        ring sizes, etc.\n");
14179 bpr 1445
  printf ("    -X  same as above, listing all records (even if 0) as comma-separated list\n");
1446
  printf ("    -a  count charges in fingerprint\n");  /* 0.3x */
1447
  printf ("    -m  write MDL molfile (with special encoding for aromatic atoms/bonds)\n");
6785 bpr 1448
  printf (" options can be combined like -vc\n");
1449
  printf (" <filename> specifies any file in the formats supported\n");
14179 bpr 1450
  printf (" (MDL *.mol, Alchemy *.mol, Sybyl *.mol2), the filename \"-\" (without quotes)\n");
6785 bpr 1451
  printf (" specifies standard input\n");
1452
  /* the "debug" option (-D) remains undocumented */
1453
}
1454
 
14179 bpr 1455
static void list_molstat_codes ()
6785 bpr 1456
{
1457
  printf ("n_atoms:     number of heavy atoms\n");
1458
  printf ("n_bonds:     number of bonds between non-H atoms\n");
1459
  printf ("n_rings:     number of rings\n");
1460
  printf ("n_QA:        number of query atoms\n");
1461
  printf ("n_QB:        number of query bonds\n");
1462
  printf ("n_chg:       number of charges\n");
1463
  printf ("n_C1:        number of sp-hybridized carbon atoms\n");
1464
  printf ("n_C2:        number of sp2-hybridized carbon atoms\n");
1465
  printf ("n_C:         total number of carbon atoms\n");
1466
  printf
1467
    ("n_CHB1p:     number of carbon atoms with at least 1 bond to a hetero atom\n");
1468
  printf
1469
    ("n_CHB2p:     number of carbon atoms with at least 2 bonds to a hetero atom\n");
1470
  printf
1471
    ("n_CHB3p:     number of carbon atoms with at least 3 bonds to a hetero atom\n");
1472
  printf
1473
    ("n_CHB4:      number of carbon atoms with 4 bonds to a hetero atom\n");
1474
  printf ("n_O2:        number of sp2-hybridized oxygen atoms\n");
1475
  printf ("n_O3:        number of sp3-hybridized oxygen atoms\n");
1476
  printf ("n_N1:        number of sp-hybridized nitrogen atoms\n");
1477
  printf ("n_N2:        number of sp2-hybridized nitrogen atoms\n");
1478
  printf ("n_N3:        number of sp3-hybridized nitrogen atoms\n");
1479
  printf ("n_S:         number of sulfur atoms\n");
1480
  printf ("n_SeTe:      total number of selenium and tellurium atoms\n");
1481
  printf ("n_F:         number of fluorine atoms\n");
1482
  printf ("n_Cl:        number of chlorine atoms\n");
1483
  printf ("n_Br:        number of bromine atoms\n");
1484
  printf ("n_I:         number of iodine atoms\n");
1485
  printf ("n_P:         number of phosphorus atoms\n");
1486
  printf ("n_B:         number of boron atoms\n");
1487
  printf ("n_Met:       total number of metal atoms\n");
1488
  printf
1489
    ("n_X:         total number of \"other\" atoms (not listed above) and halogens\n");
1490
  printf ("n_b1:        number of single bonds\n");
1491
  printf ("n_b2:        number of double bonds\n");
1492
  printf ("n_b3:        number of triple bonds\n");
1493
  printf ("n_bar:       number of aromatic bonds\n");
1494
  printf ("n_C1O:       number of C-O single bonds\n");
1495
  printf ("n_C2O:       number of C=O double bonds\n");
1496
  printf ("n_CN:        number of C/N bonds (any type)\n");
1497
  printf ("n_XY:        number of heteroatom/heteroatom bonds (any type)\n");
1498
  printf ("n_r3:        number of 3-membered rings\n");
1499
  printf ("n_r4:        number of 4-membered rings\n");
1500
  printf ("n_r5:        number of 5-membered rings\n");
1501
  printf ("n_r6:        number of 6-membered rings\n");
1502
  printf ("n_r7:        number of 7-membered rings\n");
1503
  printf ("n_r8:        number of 8-membered rings\n");
1504
  printf ("n_r9:        number of 9-membered rings\n");
1505
  printf ("n_r10:       number of 10-membered rings\n");
1506
  printf ("n_r11:       number of 11-membered rings\n");
1507
  printf ("n_r12:       number of 12-membered rings\n");
1508
  printf ("n_r13p:      number of 13-membered or larger rings\n");
1509
  printf ("n_rN:        number of rings containing nitrogen (any number)\n");
1510
  printf ("n_rN1:       number of rings containing 1 nitrogen atom\n");
1511
  printf ("n_rN2:       number of rings containing 2 nitrogen atoms\n");
1512
  printf
1513
    ("n_rN3p:      number of rings containing 3 or more nitrogen atoms\n");
1514
  printf ("n_rO:        number of rings containing oxygen (any number)\n");
1515
  printf ("n_rO1:       number of rings containing 1 oxygen atom\n");
1516
  printf ("n_rO2p:      number of rings containing 2 or more oxygen atoms\n");
1517
  printf ("n_rS:        number of rings containing sulfur (any number)\n");
1518
  printf ("n_rX:        number of heterocycles (any type)\n");
1519
  printf ("n_rar:       number of aromatic rings (any type)\n");
14179 bpr 1520
  /* p2c: checkmol.pas, line 1207:
1521
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 1522
  /*$IFDEF extended_molstat */
1523
  printf ("n_rbz:       number of benzene rings\n");
1524
  printf ("n_br2p:      number of bonds belonging to two or more rings\n");
14179 bpr 1525
  printf ("n_psg01:     number of atoms belonging to group 1 of the periodic system\n");
1526
  printf ("n_psg02:     number of atoms belonging to group 2 of the periodic system\n");
1527
  printf ("n_psg13:     number of atoms belonging to group 13 of the periodic system\n");
1528
  printf ("n_psg14:     number of atoms belonging to group 14 of the periodic system\n");
1529
  printf ("n_psg15:     number of atoms belonging to group 15 of the periodic system\n");
1530
  printf ("n_psg16:     number of atoms belonging to group 16 of the periodic system\n");
1531
  printf ("n_psg17:     number of atoms belonging to group 17 of the periodic system\n");
1532
  printf ("n_psg18:     number of atoms belonging to group 18 of the periodic system\n");
1533
  printf ("n_pstm:      number of atoms belonging to the transition metals\n");
1534
  printf ("n_psla:      number of atoms belonging to the lanthanides or actinides\n");
6785 bpr 1535
  printf ("n_iso:      number of isotopes\n");
1536
  printf ("n_rad:      number of radicals\n");
1537
  /*$ENDIF */
1538
}
1539
 
1540
#if 0
14179 bpr 1541
static void parse_args() {
6785 bpr 1542
  int p;
1543
  char parstr[256];
1544
  char tmpstr[256];
1545
  int l;
1546
 
1547
  *tmpstr = '\0';
18544 georgesk 1548
  opt_none = istrue;
6785 bpr 1549
  if (progmode == pmCheckMol) {
1550
    for (p = 1; p < P_argc; p++) {
1551
      strcpy(parstr, P_argv[p]);
1552
      if (!strcmp(parstr, "-l")) {   /* new in v0.3l */
14179 bpr 1553
        list_molstat_codes();
1554
        _Escape(0);
6785 bpr 1555
      }
1556
      if (p < P_argc - 1) {
14179 bpr 1557
        if (strpos2(parstr, "-", 1) == 1 && p < P_argc - 1) {
1558
          strcpy(tmpstr, P_argv[p]);
1559
          left_trim(tmpstr);
1560
          l = 0;
1561
          if (strpos2(tmpstr, "v", 1) > 0)
1562
            l++;
1563
          if (strpos2(tmpstr, "D", 1) > 0)
1564
            l++;
1565
          if (strpos2(tmpstr, "r", 1) > 0)
1566
            l++;
1567
          if (strpos2(tmpstr, "M", 1) > 0)   /* new in v0.3 */
1568
            l++;
1569
          if (strlen(tmpstr) > l + 2) {
1570
            show_usage();
1571
            _Escape(1);
1572
          }
18544 georgesk 1573
          opt_none = isfalse;
14179 bpr 1574
          if (strpos2(tmpstr, "M", 1) > 0)
18544 georgesk 1575
            opt_metalrings = istrue;
14179 bpr 1576
          if (strpos2(tmpstr, "v", 1) > 0)
18544 georgesk 1577
            opt_verbose = istrue;
14179 bpr 1578
            /* p2c: checkmol.pas, line 1261:
1579
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1580
            /*$IFDEF debug
1581
            if (strpos2(tmpstr, "D", 1) > 0)
18544 georgesk 1582
              opt_debug = istrue;
14179 bpr 1583
            $ENDIF*/
1584
          if (strpos2(tmpstr, "e", 1) > 0)
18544 georgesk 1585
            opt_text = istrue;
14179 bpr 1586
          else {
1587
            if (strpos2(tmpstr, "d", 1) > 0)
18544 georgesk 1588
              opt_text_de = istrue;
14179 bpr 1589
            else {
1590
              if (strpos2(tmpstr, "c", 1) > 0)
18544 georgesk 1591
                opt_code = istrue;
14179 bpr 1592
              else {
1593
                if (strpos2(tmpstr, "b", 1) > 0)
18544 georgesk 1594
                  opt_bin = istrue;
14179 bpr 1595
                else {
1596
                  if (strpos2(tmpstr, "s", 1) > 0)
18544 georgesk 1597
                    opt_bitstring = istrue;
14179 bpr 1598
                }
1599
              }
1600
            }
1601
            if (strpos2(tmpstr, "x", 1) > 0)
18544 georgesk 1602
              opt_molstat = istrue;
14179 bpr 1603
            if (strpos2(tmpstr, "r", 1) > 0)
1604
              opt_rs = rs_ssr;
1605
            if (strpos2(tmpstr, "X", 1) > 0) {
18544 georgesk 1606
              opt_molstat = istrue;
1607
              opt_molstat_X = istrue;
14179 bpr 1608
            }
1609
            if (strpos2(tmpstr, "m", 1) > 0) {
18544 georgesk 1610
              opt_text = isfalse;
1611
              opt_text_de = isfalse;
1612
              opt_bin = isfalse;
1613
              opt_bitstring = isfalse;
1614
              opt_code = isfalse;
1615
              opt_molstat = isfalse;
1616
              opt_xmdlout = istrue;
14179 bpr 1617
                  }
1618
          }
1619
        strcpy(molfilename, tmpstr);
1620
      }
1621
    } else {
1622
      if (strpos2(parstr, "-", 1) == 1) {
1623
        if (strlen(parstr) > 1) {
1624
          show_usage();
1625
          _Escape(1);
1626
        }
18544 georgesk 1627
        opt_stdin = istrue;
6785 bpr 1628
      } else {
18544 georgesk 1629
      opt_stdin = isfalse;
14179 bpr 1630
      strcpy(molfilename, parstr);
6785 bpr 1631
      }
14179 bpr 1632
        }
6785 bpr 1633
    }
18544 georgesk 1634
    if (opt_text == isfalse && opt_text_de == isfalse && opt_code == isfalse &&
1635
        opt_bin == isfalse && opt_bitstring == isfalse && opt_molstat == isfalse &&
1636
        opt_molstat_X == isfalse && opt_xmdlout == isfalse)
1637
      opt_none = istrue;
6785 bpr 1638
  }
1639
  if (progmode == pmMatchMol) {
1640
    *ndl_molfilename = '\0';
1641
    *molfilename = '\0';
1642
    for (p = 1; p < P_argc; p++) {
14179 bpr 1643
        strcpy(parstr, P_argv[p]);
6785 bpr 1644
      if (p == 1) {
14179 bpr 1645
        if (strpos2(parstr, "-", 1) == 1) {
1646
          if (strpos2(parstr, "v", 1) > 1)
18544 georgesk 1647
            opt_verbose = istrue;
14179 bpr 1648
            /* p2c: checkmol.pas, line 1329:
1649
             * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1650
            /*$IFDEF debug
1651
                if (strpos2(parstr, "D", 1) > 1)
18544 georgesk 1652
                  opt_debug = istrue;
14179 bpr 1653
               $ENDIF*/
1654
          if (strpos2(parstr, "x", 1) > 1)
18544 georgesk 1655
            opt_exact = istrue;
14179 bpr 1656
          if (strpos2(parstr, "s", 1) > 1)   /* new in v0.2f */
18544 georgesk 1657
            opt_strict = istrue;
14179 bpr 1658
          if (strpos2(parstr, "m", 1) > 1)
18544 georgesk 1659
           opt_molout = istrue;
14179 bpr 1660
          if (strpos2(parstr, "r", 1) > 1)
1661
            opt_rs = rs_ssr;
1662
          if (strpos2(parstr, "M", 1) > 0)   /* new in v0.3 */
18544 georgesk 1663
            opt_metalrings = istrue;
14179 bpr 1664
          if (strpos2(parstr, "g", 1) > 0)   /* new in v0.3d */
18544 georgesk 1665
            opt_geom = istrue;
14179 bpr 1666
          if (strpos2(parstr, "G", 1) > 0)   /* new in v0.3f */
18544 georgesk 1667
            opt_chiral = istrue;
14179 bpr 1668
          if (strpos2(parstr, "f", 1) > 0) {   /* new in v0.3m */
18544 georgesk 1669
            opt_fp = istrue;
14179 bpr 1670
          fpformat = fpf_boolean;
1671
        }
1672
        if (strpos2(parstr, "F", 1) > 0) {   /* new in v0.3m */
18544 georgesk 1673
          opt_fp = istrue;
14179 bpr 1674
          fpformat = fpf_decimal;
1675
        }
1676
        if (strpos2(parstr, "h", 1) > 1) {
1677
          show_usage();
1678
          _Escape(0);
1679
        }
1680
            } else
1681
        strcpy(ndl_molfilename, parstr);
1682
    }
1683
    if (p == P_argc - 2) {
1684
      if (strpos2(parstr, "-", 1) != 1)
1685
      strcpy(ndl_molfilename, parstr);
1686
    }
1687
    if (p == P_argc - 1) {
1688
      if (strcmp(parstr, "-"))
1689
        strcpy(molfilename, parstr);
1690
      else
18544 georgesk 1691
        opt_stdin = istrue;
14179 bpr 1692
      }
1693
    }
1694
    if (opt_geom)   /* v0.3d */
18544 georgesk 1695
      ez_search = istrue;
14179 bpr 1696
    if (opt_chiral)   /* v0.3f */
18544 georgesk 1697
      rs_search = istrue;
14179 bpr 1698
    if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1699
        /* new in v0.3j, v0.3m */
18544 georgesk 1700
      rs_strict = istrue;
14179 bpr 1701
    if (opt_fp) {   /* v0.3m */
18544 georgesk 1702
        opt_molout = isfalse;
1703
        opt_exact = isfalse;
14179 bpr 1704
    }
1705
  }  /* progmode = pmMatchMol */
1706
  ringsearch_mode = opt_rs;   /* v0.3i */
1707
}
6785 bpr 1708
#endif
1709
 
14179 bpr 1710
static void parse_args (int argc, char *argv[])
6785 bpr 1711
{
1712
  short p;
1713
  char parstr[256];
1714
  char tmpstr[256];
1715
  short l;
1716
 
1717
  *tmpstr = '\0';
18544 georgesk 1718
  opt_none = istrue;
6785 bpr 1719
  *molfilename = '\0';
1720
  *ndl_molfilename = '\0';
14179 bpr 1721
  if (progmode == pmCheckMol) {
1722
    for (p = 1; p <= argc - 1; p++) {
1723
            strcpy (parstr, argv[p]);
1724
            if (!strcmp (parstr, "-l")) {                       /* new in v0.3l */
6785 bpr 1725
              list_molstat_codes ();
1726
              exit (0);
1727
            }
14179 bpr 1728
            if (p < argc - 1) {
1729
              if (strpos2 (parstr, "-", 1) == 1 && p < argc - 1) {
1730
                      strcpy (tmpstr, argv[p]);
1731
                      left_trim (tmpstr);
1732
                      l = 0;
1733
                      if (strpos2 (tmpstr, "v", 1) > 0)
1734
                        l++;
1735
                      if (strpos2 (tmpstr, "D", 1) > 0)
1736
                        l++;
6785 bpr 1737
                      if (strpos2 (tmpstr, "r", 1) > 0)
14179 bpr 1738
                        l++;
1739
                      /*if (strpos2 (tmpstr, "a", 1) > 0)   // 0.3x
1740
                         l++; */
1741
                      if (strpos2 (tmpstr, "M", 1) > 0) /* new in v0.3 */
1742
                        l++;
1743
                      if (strlen (tmpstr) > l + 2) {
1744
                        show_usage ();
1745
                        exit (1);
1746
                      }
18544 georgesk 1747
                      opt_none = isfalse;
14179 bpr 1748
                      if (strpos2 (tmpstr, "M", 1) > 0)
18544 georgesk 1749
                        opt_metalrings = istrue;
14179 bpr 1750
                      if (strpos2 (tmpstr, "v", 1) > 0)
18544 georgesk 1751
                        opt_verbose = istrue;
14179 bpr 1752
                      /*{$IFDEF debug
18544 georgesk 1753
                         if pos('D',tmpstr)>0 then opt_debug       := istrue;
14179 bpr 1754
                         {$ENDIF */
1755
                      if (strpos2 (tmpstr, "e", 1) > 0)
18544 georgesk 1756
                        opt_text = istrue;
14179 bpr 1757
                      else {
1758
                        if (strpos2 (tmpstr, "d", 1) > 0)
18544 georgesk 1759
                                 opt_text_de = istrue;
14179 bpr 1760
                        else {
1761
                                if (strpos2 (tmpstr, "c", 1) > 0)
18544 georgesk 1762
                                  opt_code = istrue;
14179 bpr 1763
                                else {
1764
                                  if (strpos2 (tmpstr, "b", 1) > 0)
18544 georgesk 1765
                                    opt_bin = istrue;
14179 bpr 1766
                                  else {
1767
                                    if (strpos2 (tmpstr, "s", 1) > 0)
18544 georgesk 1768
                                      opt_bitstring = istrue;
14179 bpr 1769
                                  }
1770
                                }
1771
                              }
1772
                        if (strpos2 (tmpstr, "x", 1) > 0)
18544 georgesk 1773
                                opt_molstat = istrue;
14179 bpr 1774
                        if (strpos2 (tmpstr, "r", 1) > 0)
1775
                                opt_rs = rs_ssr;
1776
                          /* if (strpos2 (tmpstr, "a", 1) > 0)
18544 georgesk 1777
                            opt_chg = istrue; */ /* 0.3x  */
14179 bpr 1778
                        if (strpos2 (tmpstr, "X", 1) > 0) {
18544 georgesk 1779
                                opt_molstat = istrue;
1780
                                opt_molstat_X = istrue;
14179 bpr 1781
                              }
1782
                        if (strpos2 (tmpstr, "m", 1) > 0) {
18544 georgesk 1783
                                opt_text = isfalse;
1784
                                opt_text_de = isfalse;
1785
                                opt_bin = isfalse;
1786
                                opt_bitstring = isfalse;
1787
                                opt_code = isfalse;
1788
                                opt_molstat = isfalse;
1789
                                opt_xmdlout = istrue;
14179 bpr 1790
                              }
1791
                      }
1792
                      strcpy (molfilename, tmpstr);
1793
              }
6785 bpr 1794
            }
14179 bpr 1795
            else {
1796
              if (strpos2 (parstr, "-", 1) == 1) {
1797
                if (strlen (parstr) > 1) {
1798
                  show_usage ();
1799
                  exit (1);
1800
                }
18544 georgesk 1801
                opt_stdin = istrue;
14179 bpr 1802
              } else {
18544 georgesk 1803
                      opt_stdin = isfalse;
14179 bpr 1804
                      strcpy (molfilename, parstr);
6785 bpr 1805
                    }
1806
            }
14179 bpr 1807
          }
18544 georgesk 1808
    if (opt_text == isfalse && opt_text_de == isfalse && opt_code == isfalse &&
1809
                opt_bin == isfalse && opt_bitstring == isfalse && opt_molstat == isfalse
1810
                && opt_molstat_X == isfalse && opt_xmdlout == isfalse
1811
                && opt_chg == isfalse)
1812
              opt_none = istrue;        /* 0.3x */
14179 bpr 1813
  }
1814
  if (progmode == pmMatchMol) {
1815
    for (p = 1; p <= argc - 1; p++) {
1816
      strcpy (parstr, argv[p]);
1817
      if (p == 1) {
1818
        if (strpos2 (parstr, "-", 1) == 1) {
1819
          if (strpos2 (parstr, "v", 1) > 1)
18544 georgesk 1820
            opt_verbose = istrue;
14179 bpr 1821
            /*{$IFDEF debug
18544 georgesk 1822
               if pos('D',parstr)>1 then opt_debug       := istrue;
14179 bpr 1823
               {$ENDIF */
1824
          if (strpos2 (parstr, "x", 1) > 1)
18544 georgesk 1825
            opt_exact = istrue;
14179 bpr 1826
          if (strpos2 (parstr, "s", 1) > 1)     /* new in v0.2f */
18544 georgesk 1827
            opt_strict = istrue;
14179 bpr 1828
          if (strpos2 (parstr, "m", 1) > 1)
18544 georgesk 1829
            opt_molout = istrue;
14179 bpr 1830
          if (strpos2 (parstr, "r", 1) > 1)
1831
            opt_rs = rs_ssr;
1832
          if (strpos2 (parstr, "a", 1) > 0)
18544 georgesk 1833
                    opt_chg = istrue;   /* 0.3x */
14179 bpr 1834
          if (strpos2 (parstr, "i", 1) > 0)
18544 georgesk 1835
            opt_iso = istrue;   /* 0.3x */
14179 bpr 1836
          if (strpos2 (parstr, "d", 1) > 0)
18544 georgesk 1837
            opt_rad = istrue;   /* 0.3x */
14179 bpr 1838
          if (strpos2 (parstr, "M", 1) > 0)     /* new in v0.3 */
18544 georgesk 1839
            opt_metalrings = istrue;
14179 bpr 1840
          if (strpos2 (parstr, "g", 1) > 0)     /* new in v0.3d */
18544 georgesk 1841
            opt_geom = istrue;
14179 bpr 1842
          if (strpos2 (parstr, "G", 1) > 0)     /* new in v0.3f */
18544 georgesk 1843
            opt_chiral = istrue;
14179 bpr 1844
          if (strpos2 (parstr, "f", 1) > 0) {           /* new in v0.3m */
18544 georgesk 1845
            opt_fp = istrue;
14179 bpr 1846
            fpformat = fpf_boolean;
1847
          }
1848
          if (strpos2 (parstr, "F", 1) > 0) {           /* new in v0.3m */
18544 georgesk 1849
            opt_fp = istrue;
14179 bpr 1850
            fpformat = fpf_decimal;
1851
          }
1852
          if (strpos2 (parstr, "h", 1) > 1) {
1853
            show_usage ();
1854
            exit (0);
1855
          }
1856
              } else
1857
                strcpy (ndl_molfilename, parstr);
6785 bpr 1858
            }
14179 bpr 1859
            if (p == argc - 2) {
6785 bpr 1860
              if (strpos2 (parstr, "-", 1) != 1)
14179 bpr 1861
                strcpy (ndl_molfilename, parstr);
1862
              }
1863
            if (p == argc - 1) {
6785 bpr 1864
              if (strcmp (parstr, "-"))
14179 bpr 1865
                strcpy (molfilename, parstr);
6785 bpr 1866
              else
18544 georgesk 1867
                opt_stdin = istrue;
6785 bpr 1868
            }
14179 bpr 1869
          }
1870
    if (opt_geom)               /* v0.3d */
18544 georgesk 1871
            ez_search = istrue;
14179 bpr 1872
    if (opt_chiral)             /* v0.3f */
18544 georgesk 1873
            rs_search = istrue;
14179 bpr 1874
    if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1875
            /* new in v0.3j, v0.3m  */
18544 georgesk 1876
            rs_strict = istrue;
14179 bpr 1877
    if (opt_fp) {                       /* v0.3m */
18544 georgesk 1878
            opt_molout = isfalse;
1879
            opt_exact = isfalse;
14179 bpr 1880
          }
1881
  }                             /* progmode = pmMatchMol */
6785 bpr 1882
  ringsearch_mode = opt_rs;     /* v0.3i */
1883
}
1884
 
1885
/*============== input-related functions & procedures ===================== */
1886
 
17891 bpr 1887
static char *get_filetype (char *Result, char *f)
6785 bpr 1888
{
1889
  char rline[256];
1890
  char auxstr[256];
1891
  int i;
18544 georgesk 1892
  boolean mdl1 = isfalse;
6785 bpr 1893
  int ri;
1894
  int sepcount = 0;
1895
  char STR1[256], STR6[256], STR7[256];
1896
 
1897
  strcpy (auxstr, "unknown");
1898
  i = li;
1899
  ri = li - 1;
14179 bpr 1900
  while (ri < molbufindex && sepcount < 1) {
1901
    ri++;
1902
    strcpy (rline, molbuf[ri - 1]);
1903
    if (strpos2 (rline, "$$$$", 1) > 0)
1904
            sepcount++;
1905
    if ((i == li) && (strcmp (strsub (STR1, rline, 7, 5), "ATOMS") == 0) &&
1906
              (strcmp (strsub (STR6, rline, 20, 5), "BONDS") == 0) &&
1907
              (strcmp (strsub (STR7, rline, 33, 7), "CHARGES") == 0))
1908
            strcpy (auxstr, "alchemy");
1909
    if ((i == li + 3) && (strcmp (strsub (STR1, rline, 35, 5), "V2000") == 0))
1910
            /* and (copy(rline,31,3)='999') */
18544 georgesk 1911
            mdl1 = istrue;
14179 bpr 1912
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 6), "-ISIS-") == 0))
18544 georgesk 1913
            mdl1 = istrue;
14179 bpr 1914
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "WLViewer") == 0))
18544 georgesk 1915
            mdl1 = istrue;
14179 bpr 1916
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CheckMol") == 0))
18544 georgesk 1917
            mdl1 = istrue;
14179 bpr 1918
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CATALYST") == 0)) {
18544 georgesk 1919
            mdl1 = istrue;
14179 bpr 1920
            strcpy (auxstr, "mdl");
1921
          }
1922
    if (strpos2 (rline, "M  END", 1) == 1 || mdl1)
1923
            strcpy (auxstr, "mdl");
1924
    if (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) > 0)
1925
            strcpy (auxstr, "sybyl");
1926
    i++;
1927
  }
6785 bpr 1928
  /* new in v0.2j: try to identify non-conformant SD-files */
1929
  if (!strcmp (auxstr, "unknown") && sepcount > 0)
1930
    strcpy (auxstr, "mdl");
1931
  return strcpy (Result, auxstr);
1932
}
1933
 
14179 bpr 1934
static void zap_molecule ()
6785 bpr 1935
{
1936
  /* try */
14179 bpr 1937
  if (atom != NULL) {
1938
    free (atom);
1939
    atom = NULL;                /* added in v0.3j */
1940
  }
1941
  if (bond != NULL) {
1942
    free (bond);
1943
    bond = NULL;                /* added in v0.3j */
1944
  }
1945
  if (ring != NULL) {
1946
    free (ring);
1947
    ring = NULL;                /* added in v0.3j */
1948
  }
1949
  if (ringprop != NULL) {
1950
    free (ringprop);
1951
    ringprop = NULL;            /* added in v0.3j */
1952
  }
6785 bpr 1953
  /* except
14179 bpr 1954
    on e:Einvalidpointer do begin end;
1955
    end; */
6785 bpr 1956
  n_atoms = 0;
1957
  n_bonds = 0;
1958
  n_rings = 0;
1959
}
1960
 
14179 bpr 1961
static void zap_needle ()
6785 bpr 1962
{
1963
  /* try */
14179 bpr 1964
  if (ndl_atom != NULL) {
1965
    free (ndl_atom);
1966
    ndl_atom = NULL;            /* added in v0.3j */
1967
  }
1968
  if (ndl_bond != NULL) {
1969
    free (ndl_bond);
1970
    ndl_bond = NULL;            /* added in v0.3j */
1971
  }
1972
  if (ndl_ring != NULL) {
1973
    free (ndl_ring);
1974
    ndl_ring = NULL;            /* added in v0.3j */
1975
  }
1976
  if (ndl_ringprop != NULL) {
1977
    free (ndl_ringprop);        /* fixed in v0.3g */
1978
    ndl_ringprop = NULL;        /* added in v0.3j */
1979
  }
6785 bpr 1980
  /* except
1981
     on e:Einvalidpointer do begin end;
1982
     end; */
1983
  ndl_n_atoms = 0;
1984
  ndl_n_bonds = 0;
1985
  ndl_n_rings = 0;
1986
}
1987
 
1988
#if 0
14179 bpr 1989
static void zap_tmp ()
6785 bpr 1990
{
1991
  /* try */
14179 bpr 1992
  if (tmp_atom != NULL) {
6785 bpr 1993
      free (tmp_atom);
1994
      tmp_atom = NULL;          /* added in v0.3j */
1995
    }
14179 bpr 1996
  if (tmp_bond != NULL) {
6785 bpr 1997
      free (tmp_bond);
1998
      tmp_bond = NULL;          /* added in v0.3j */
1999
    }
14179 bpr 2000
  if (tmp_ring != NULL) {
6785 bpr 2001
      free (tmp_ring);
2002
      tmp_ring = NULL;          /* added in v0.3j */
2003
    }
14179 bpr 2004
  if (tmp_ringprop != NULL) {
6785 bpr 2005
      free (tmp_ringprop);      /* fixed in v0.3g */
2006
      tmp_ringprop = NULL;      /* added in v0.3j */
2007
    }
2008
  /* except
2009
     on e:Einvalidpointer do begin end;
2010
     end; */
2011
  tmp_n_atoms = 0;
2012
  tmp_n_bonds = 0;
2013
  tmp_n_rings = 0;
2014
}
2015
#endif
2016
 
17891 bpr 2017
static boolean is_heavyatom (int id)
6785 bpr 2018
{
2019
  str2 el;
2020
 
2021
  strcpy (el, atom[id - 1].element);
14179 bpr 2022
 
6785 bpr 2023
  if (!strcmp (el, "DU") || !strcmp (el, "LP"))
18544 georgesk 2024
    return isfalse;
6785 bpr 2025
  /*if (progmode == pmCheckMol && !strcmp (el, "H ")
2026
     && atom[id - 1].nucleon_number < 2)
18544 georgesk 2027
     return isfalse;               0.3x  */
14179 bpr 2028
  if (!strcmp (el, "H "))       /* 0.3 p */ {
2029
    if (progmode == pmMatchMol && !opt_iso) {
18544 georgesk 2030
            return isfalse;
14179 bpr 2031
          }
2032
    else {
6785 bpr 2033
          if (atom[id - 1].nucleon_number < 2)
18544 georgesk 2034
            return isfalse;
14179 bpr 2035
          }
2036
  }
18544 georgesk 2037
  return istrue;
6785 bpr 2038
}
2039
 
17891 bpr 2040
static boolean ndl_alkene_C (int ba)
6785 bpr 2041
{
2042
  /* new in v0.3f */
18544 georgesk 2043
  boolean res = isfalse;
6785 bpr 2044
  int i, ba2, FORLIM;
2045
 
2046
  if (ndl_n_atoms <= 0 || ndl_n_bonds <= 0)
18544 georgesk 2047
    return isfalse;
6785 bpr 2048
  FORLIM = ndl_n_bonds;
14179 bpr 2049
  for (i = 0; i < FORLIM; i++) {
2050
    if (ndl_bond[i].a1 == ba || ndl_bond[i].a2 == ba) {
2051
            if (ndl_bond[i].a1 == ba)
2052
              ba2 = ndl_bond[i].a2;
2053
            else
2054
              ba2 = ndl_bond[i].a1;
6785 bpr 2055
          if (!strcmp (ndl_atom[ba - 1].atype, "C2 ") &&
2056
              !strcmp (ndl_atom[ba2 - 1].atype, "C2 ")
18544 georgesk 2057
              && ndl_bond[i].btype == 'D' && ndl_bond[i].arom == isfalse)
2058
            res = istrue;
14179 bpr 2059
          }
2060
  }
6785 bpr 2061
  return res;
2062
}
2063
 
17891 bpr 2064
static boolean is_metal (int id)
6785 bpr 2065
{
18544 georgesk 2066
  boolean r = isfalse;
6785 bpr 2067
  str2 el;
2068
 
2069
  strcpy (el, atom[id - 1].element);
2070
  if (!strcmp (el, "LI") || !strcmp (el, "NA") || !strcmp (el, "K ") ||
2071
      !strcmp (el, "RB") || !strcmp (el, "CS") || !strcmp (el, "BE") ||
2072
      !strcmp (el, "MG") || !strcmp (el, "CA") || !strcmp (el, "SR") ||
2073
      !strcmp (el, "BA") || !strcmp (el, "TI") || !strcmp (el, "ZR") ||
2074
      !strcmp (el, "CR") || !strcmp (el, "MO") || !strcmp (el, "MN") ||
2075
      !strcmp (el, "FE") || !strcmp (el, "CO") || !strcmp (el, "NI") ||
2076
      !strcmp (el, "PD") || !strcmp (el, "PT") || !strcmp (el, "SN") ||
2077
      !strcmp (el, "CU") || !strcmp (el, "AG") || !strcmp (el, "AU") ||
2078
      !strcmp (el, "ZN") || !strcmp (el, "CD") || !strcmp (el, "HG") ||
2079
      !strcmp (el, "AL") || !strcmp (el, "SN") || !strcmp (el, "PB") ||
2080
      !strcmp (el, "SB") || !strcmp (el, "BI"))
14179 bpr 2081
  /* p2c: checkmol.pas, line 1577:
2082
  * Note: Line breaker spent 0.0 seconds, 5000 tries on line 1686 [251] */
6785 bpr 2083
    /* etc. etc. */
18544 georgesk 2084
    r = istrue;
6785 bpr 2085
  return r;
2086
}
2087
 
17891 bpr 2088
static int get_nvalences (char *a_el)
6785 bpr 2089
{
2090
  /* changed name and position in v0.3m */
2091
  /* preliminary version; should be extended to element/atomtype */
2092
  int res = 1;
2093
 
2094
  if (!strcmp (a_el, "H "))
2095
    res = 1;
14179 bpr 2096
  /*if (!strcmp (a_el, "D "))   // v0.3n
6785 bpr 2097
     res = 1; */
2098
  if (!strcmp (a_el, "C "))
2099
    res = 4;
2100
  if (!strcmp (a_el, "N "))
2101
    res = 3;
2102
  if (!strcmp (a_el, "O "))
2103
    res = 2;
2104
  if (!strcmp (a_el, "S "))
2105
    res = 2;
2106
  if (!strcmp (a_el, "SE"))
2107
    res = 2;
2108
  if (!strcmp (a_el, "TE"))
2109
    res = 2;
2110
  if (!strcmp (a_el, "P "))
2111
    res = 3;
2112
  if (!strcmp (a_el, "F "))
2113
    res = 1;
2114
  if (!strcmp (a_el, "CL"))
2115
    res = 1;
2116
  if (!strcmp (a_el, "BR"))
2117
    res = 1;
2118
  if (!strcmp (a_el, "I "))
2119
    res = 1;
2120
  if (!strcmp (a_el, "AT"))
2121
    res = 1;
2122
  if (!strcmp (a_el, "B "))
2123
    res = 3;
2124
  if (!strcmp (a_el, "LI"))
2125
    res = 1;
2126
  if (!strcmp (a_el, "NA"))
2127
    res = 1;
2128
  if (!strcmp (a_el, "K "))
2129
    res = 1;
2130
  if (!strcmp (a_el, "CA"))
2131
    res = 2;
2132
  if (!strcmp (a_el, "SR"))
2133
    res = 2;
2134
  if (!strcmp (a_el, "MG"))
2135
    res = 2;
2136
  if (!strcmp (a_el, "FE"))
2137
    res = 3;
2138
  if (!strcmp (a_el, "MN"))
2139
    res = 2;
2140
  if (!strcmp (a_el, "HG"))
2141
    res = 2;
2142
  if (!strcmp (a_el, "SI"))
2143
    res = 4;
2144
  if (!strcmp (a_el, "SN"))
2145
    res = 4;
2146
  if (!strcmp (a_el, "ZN"))
2147
    res = 2;
2148
  if (!strcmp (a_el, "CU"))
2149
    res = 2;
2150
  if (!strcmp (a_el, "A "))
2151
    res = 4;
2152
  if (!strcmp (a_el, "Q "))
2153
    res = 4;
2154
  return res;
2155
}
2156
 
17891 bpr 2157
static char * convert_type (char *Result, char *oldtype)
6785 bpr 2158
{
2159
  int i;
2160
  str3 newtype;
2161
 
2162
  sprintf (newtype, "%.3s", oldtype);
2163
  for (i = 0; i <= 2; i++)
2164
    newtype[i] = toupper (newtype[i]);
2165
  if (newtype[0] == '~')
2166
    strcpy (newtype, "VAL");
2167
  if (newtype[0] == '*')
2168
    strcpy (newtype, "STR");
2169
  return strcpy (Result, newtype);
2170
}
2171
 
17891 bpr 2172
static char * convert_sybtype (char *Result, char *oldtype)
6785 bpr 2173
{
2174
  str3 newtype;
2175
 
2176
  /*  NewType := Copy(OldType,1,3); */
2177
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2178
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2179
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2180
  strcpy (newtype, "DU ");
2181
  if (!strcmp (oldtype, "H    "))
2182
    strcpy (newtype, "H  ");
2183
  if (!strcmp (oldtype, "C.ar "))
2184
    strcpy (newtype, "CAR");
2185
  if (!strcmp (oldtype, "C.2  "))
2186
    strcpy (newtype, "C2 ");
2187
  if (!strcmp (oldtype, "C.3  "))
2188
    strcpy (newtype, "C3 ");
2189
  if (!strcmp (oldtype, "C.1  "))
2190
    strcpy (newtype, "C1 ");
2191
  if (!strcmp (oldtype, "O.2  "))
2192
    strcpy (newtype, "O2 ");
2193
  if (!strcmp (oldtype, "O.3  "))
2194
    strcpy (newtype, "O3 ");
2195
  if (!strcmp (oldtype, "O.co2"))
2196
    strcpy (newtype, "O2 ");
2197
  if (!strcmp (oldtype, "O.spc"))
2198
    strcpy (newtype, "O3 ");
2199
  if (!strcmp (oldtype, "O.t3p"))
2200
    strcpy (newtype, "O3 ");
2201
  if (!strcmp (oldtype, "N.1  "))
2202
    strcpy (newtype, "N1 ");
2203
  if (!strcmp (oldtype, "N.2  "))
2204
    strcpy (newtype, "N2 ");
2205
  if (!strcmp (oldtype, "N.3  "))
2206
    strcpy (newtype, "N3 ");
2207
  if (!strcmp (oldtype, "N.pl3"))
2208
    strcpy (newtype, "NPL");
2209
  if (!strcmp (oldtype, "N.4  "))
2210
    strcpy (newtype, "N3+");
2211
  if (!strcmp (oldtype, "N.am "))
2212
    strcpy (newtype, "NAM");
2213
  if (!strcmp (oldtype, "N.ar "))
2214
    strcpy (newtype, "NAR");
2215
  if (!strcmp (oldtype, "F    "))
2216
    strcpy (newtype, "F  ");
2217
  if (!strcmp (oldtype, "Cl   "))
2218
    strcpy (newtype, "CL ");
2219
  if (!strcmp (oldtype, "Br   "))
2220
    strcpy (newtype, "BR ");
2221
  if (!strcmp (oldtype, "I    "))
2222
    strcpy (newtype, "I  ");
2223
  if (!strcmp (oldtype, "Al   "))
2224
    strcpy (newtype, "AL ");
2225
  if (!strcmp (oldtype, "ANY  "))
2226
    strcpy (newtype, "A  ");
2227
  if (!strcmp (oldtype, "Ca   "))
2228
    strcpy (newtype, "CA ");
2229
  if (!strcmp (oldtype, "Du   "))
2230
    strcpy (newtype, "DU ");
2231
  if (!strcmp (oldtype, "Du.C "))
2232
    strcpy (newtype, "DU ");
2233
  if (!strcmp (oldtype, "H.spc"))
2234
    strcpy (newtype, "H  ");
2235
  if (!strcmp (oldtype, "H.t3p"))
2236
    strcpy (newtype, "H  ");
2237
  if (!strcmp (oldtype, "HAL  "))
2238
    strcpy (newtype, "Cl ");
2239
  if (!strcmp (oldtype, "HET  "))
2240
    strcpy (newtype, "Q  ");
2241
  if (!strcmp (oldtype, "HEV  "))
2242
    strcpy (newtype, "DU ");
2243
  if (!strcmp (oldtype, "K    "))
2244
    strcpy (newtype, "K  ");
2245
  if (!strcmp (oldtype, "Li   "))
2246
    strcpy (newtype, "LI ");
2247
  if (!strcmp (oldtype, "LP   "))
2248
    strcpy (newtype, "LP ");
2249
  if (!strcmp (oldtype, "Na   "))
2250
    strcpy (newtype, "NA ");
2251
  if (!strcmp (oldtype, "P.3  "))
2252
    strcpy (newtype, "P3 ");
2253
  if (!strcmp (oldtype, "S.2  "))
2254
    strcpy (newtype, "S2 ");
2255
  if (!strcmp (oldtype, "S.3  "))
2256
    strcpy (newtype, "S3 ");
2257
  if (!strcmp (oldtype, "S.o  "))
2258
    strcpy (newtype, "SO ");
2259
  if (!strcmp (oldtype, "S.o2 "))
2260
    strcpy (newtype, "SO2");
2261
  if (!strcmp (oldtype, "Si   "))
2262
    strcpy (newtype, "SI ");
2263
  if (!strcmp (oldtype, "P.4  "))
2264
    strcpy (newtype, "P4 ");
2265
  return strcpy (Result, newtype);
2266
}
2267
 
17891 bpr 2268
static char * convert_MDLtype (char *Result, char *oldtype)
6785 bpr 2269
{
2270
  str3 newtype;
2271
 
2272
  /*  NewType := Copy(OldType,1,3); */
2273
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2274
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2275
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2276
  strcpy (newtype, "DU ");
2277
  if (!strcmp (oldtype, "H  "))
2278
    strcpy (newtype, "H  ");
2279
  if (!strcmp (oldtype, "C  "))
2280
    strcpy (newtype, "C3 ");
2281
  if (!strcmp (oldtype, "O  "))
2282
    strcpy (newtype, "O2 ");
2283
  if (!strcmp (oldtype, "N  "))
2284
    strcpy (newtype, "N3 ");
2285
  if (!strcmp (oldtype, "F  "))
2286
    strcpy (newtype, "F  ");
2287
  if (!strcmp (oldtype, "Cl "))
2288
    strcpy (newtype, "CL ");
2289
  if (!strcmp (oldtype, "Br "))
2290
    strcpy (newtype, "BR ");
2291
  if (!strcmp (oldtype, "I  "))
2292
    strcpy (newtype, "I  ");
2293
  if (!strcmp (oldtype, "Al "))
2294
    strcpy (newtype, "AL ");
2295
  if (!strcmp (oldtype, "ANY"))
2296
    strcpy (newtype, "A  ");
2297
  if (!strcmp (oldtype, "Ca "))
2298
    strcpy (newtype, "CA ");
2299
  if (!strcmp (oldtype, "Du "))
2300
    strcpy (newtype, "DU ");
2301
  if (!strcmp (oldtype, "K  "))
2302
    strcpy (newtype, "K  ");
2303
  if (!strcmp (oldtype, "Li "))
2304
    strcpy (newtype, "LI ");
2305
  if (!strcmp (oldtype, "LP "))
2306
    strcpy (newtype, "LP ");
2307
  if (!strcmp (oldtype, "Na "))
2308
    strcpy (newtype, "NA ");
2309
  if (!strcmp (oldtype, "P  "))
2310
    strcpy (newtype, "P3 ");
2311
  if (!strcmp (oldtype, "S  "))
2312
    strcpy (newtype, "S3 ");
2313
  if (!strcmp (oldtype, "Si "))
2314
    strcpy (newtype, "SI ");
2315
  if (!strcmp (oldtype, "P  "))
2316
    strcpy (newtype, "P4 ");
2317
  if (!strcmp (oldtype, "A  "))
2318
    strcpy (newtype, "A  ");
2319
  if (!strcmp (oldtype, "Q  "))
2320
    strcpy (newtype, "Q  ");
2321
  return strcpy (Result, newtype);
2322
}
2323
 
17891 bpr 2324
static char * get_element (char *Result, char *oldtype)
6785 bpr 2325
{
2326
  char elemstr[256];
2327
 
2328
  if (!strcmp (oldtype, "H   "))
2329
    strcpy (elemstr, "H ");
14179 bpr 2330
  /* if (!strcmp (oldtype, "D   "))  // v0.3n
6785 bpr 2331
     strcpy (elemstr, "D "); */
2332
  if (!strcmp (oldtype, "CAR "))
2333
    strcpy (elemstr, "C ");
2334
  if (!strcmp (oldtype, "C2  "))
2335
    strcpy (elemstr, "C ");
2336
  if (!strcmp (oldtype, "C3  "))
2337
    strcpy (elemstr, "C ");
2338
  if (!strcmp (oldtype, "C1  "))
2339
    strcpy (elemstr, "C ");
2340
  if (!strcmp (oldtype, "O2  "))
2341
    strcpy (elemstr, "O ");
2342
  if (!strcmp (oldtype, "O3  "))
2343
    strcpy (elemstr, "O ");
2344
  if (!strcmp (oldtype, "O2  "))
2345
    strcpy (elemstr, "O ");
2346
  if (!strcmp (oldtype, "O3  "))
2347
    strcpy (elemstr, "O ");
2348
  if (!strcmp (oldtype, "O3  "))
2349
    strcpy (elemstr, "O ");
2350
  if (!strcmp (oldtype, "N1  "))
2351
    strcpy (elemstr, "N ");
2352
  if (!strcmp (oldtype, "N2  "))
2353
    strcpy (elemstr, "N ");
2354
  if (!strcmp (oldtype, "N3  "))
2355
    strcpy (elemstr, "N ");
2356
  if (!strcmp (oldtype, "NPL "))
2357
    strcpy (elemstr, "N ");
2358
  if (!strcmp (oldtype, "N3+ "))
2359
    strcpy (elemstr, "N ");
2360
  if (!strcmp (oldtype, "NAM "))
2361
    strcpy (elemstr, "N ");
2362
  if (!strcmp (oldtype, "NAR "))
2363
    strcpy (elemstr, "N ");
2364
  if (!strcmp (oldtype, "F   "))
2365
    strcpy (elemstr, "F ");
2366
  if (!strcmp (oldtype, "CL  "))
2367
    strcpy (elemstr, "CL");
2368
  if (!strcmp (oldtype, "BR  "))
2369
    strcpy (elemstr, "BR");
2370
  if (!strcmp (oldtype, "I   "))
2371
    strcpy (elemstr, "I ");
2372
  if (!strcmp (oldtype, "AT  "))
2373
    strcpy (elemstr, "AT");
2374
  if (!strcmp (oldtype, "AL  "))
2375
    strcpy (elemstr, "AL");
2376
  if (!strcmp (oldtype, "DU  "))
2377
    strcpy (elemstr, "DU");
2378
  if (!strcmp (oldtype, "CA  "))
2379
    strcpy (elemstr, "CA");
2380
  if (!strcmp (oldtype, "DU  "))
2381
    strcpy (elemstr, "DU");
2382
  if (!strcmp (oldtype, "Cl  "))
2383
    strcpy (elemstr, "CL");
2384
  if (!strcmp (oldtype, "K   "))
2385
    strcpy (elemstr, "K ");
2386
  if (!strcmp (oldtype, "LI  "))
2387
    strcpy (elemstr, "LI");
2388
  if (!strcmp (oldtype, "LP  "))
2389
    strcpy (elemstr, "LP");
2390
  if (!strcmp (oldtype, "NA  "))
2391
    strcpy (elemstr, "NA");
2392
  if (!strcmp (oldtype, "P3  "))
2393
    strcpy (elemstr, "P ");
2394
  if (!strcmp (oldtype, "S2  "))
2395
    strcpy (elemstr, "S ");
2396
  if (!strcmp (oldtype, "S3  "))
2397
    strcpy (elemstr, "S ");
2398
  if (!strcmp (oldtype, "SO  "))
2399
    strcpy (elemstr, "S ");
2400
  if (!strcmp (oldtype, "SO2 "))
2401
    strcpy (elemstr, "S ");
2402
  if (!strcmp (oldtype, "SI  "))
2403
    strcpy (elemstr, "SI");
2404
  if (!strcmp (oldtype, "P4  "))
2405
    strcpy (elemstr, "P ");
2406
  if (!strcmp (oldtype, "A   "))
2407
    strcpy (elemstr, "A ");
2408
  if (!strcmp (oldtype, "Q   "))
2409
    strcpy (elemstr, "Q ");
2410
  return strcpy (Result, elemstr);
2411
}
2412
 
17891 bpr 2413
static char * get_sybelement (char *Result,char *oldtype)
6785 bpr 2414
{
2415
  int i;
2416
  str2 elemstr;
2417
 
2418
  if (strpos2 (oldtype, ".", 1) < 2)
2419
    sprintf (elemstr, "%.2s", oldtype);
14179 bpr 2420
  else {
2421
    sprintf (elemstr, "%.*s", strpos2 (oldtype, ".", 1) - 1, oldtype);
2422
    if (strlen (elemstr) < 2)
2423
            strcat (elemstr, " ");
2424
  }
6785 bpr 2425
  for (i = 0; i <= 1; i++)
2426
    elemstr[i] = toupper (elemstr[i]);
2427
  return strcpy (Result, elemstr);
2428
}
2429
 
17891 bpr 2430
static char * get_MDLelement (char *Result,char *oldtype)
6785 bpr 2431
{
2432
  int i;
2433
  str2 elemstr;
2434
 
2435
  sprintf (elemstr, "%.2s", oldtype);
2436
  for (i = 0; i <= 1; i++)
2437
    elemstr[i] = toupper (elemstr[i]);
2438
  if (elemstr[0] == '~')
2439
    strcpy (elemstr, "??");
2440
  if (elemstr[0] == '*')
2441
    strcpy (elemstr, "??");
2442
  return strcpy (Result, elemstr);
2443
}
2444
 
17891 bpr 2445
static void read_molfile (char *mfilename)
6785 bpr 2446
{
2447
  /* reads ALCHEMY mol files */
6787 kbelabas 2448
  int n;
6785 bpr 2449
  char rline[256], tmpstr[256];
2450
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2451
  float xval, yval, zval, chgval;
2452
  char a1str[256], a2str[256], elemstr[256];
2453
  int a1val, a2val, ri;
2454
  char STR1[256];
2455
  int FORLIM;
2456
  atom_rec *WITH;
2457
  bond_rec *WITH1;
2458
 
2459
  if (n_atoms > 0)
2460
    zap_molecule ();
2461
  ri = li;
2462
  strcpy (rline, molbuf[ri - 1]);
2463
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2464
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2465
  strsub (tmpstr, rline, 14, 5);
6787 kbelabas 2466
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2467
  strsub (molname, rline, 42, (int) (strlen (rline) - 42L));
2468
  /* try */
2469
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2470
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2471
  ring = safe_calloc (1, sizeof (ringlist));
2472
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2473
  /* except
2474
     on e:Eoutofmemory do
2475
     begin
2476
     writeln('Not enough memory');
2477
     halt(4);
2478
     end;
2479
     end; */
2480
  n_heavyatoms = 0;
2481
  n_heavybonds = 0;
2482
  n_Ctot = 0;                   /* v0.3g */
2483
  n_Otot = 0;                   /* v0.3g */
2484
  n_Ntot = 0;                   /* v0.3g */
2485
  FORLIM = n_atoms;
14179 bpr 2486
  for (n = 1; n <= FORLIM; n++) {
2487
    ri++;
2488
    strcpy (rline, molbuf[ri - 1]);
2489
    strsub (atomtype, rline, 7, 4);
2490
    sprintf (STR1, "%c", toupper (*atomtype));
2491
    strcpy (atomtype, STR1);    /* fixed in v0.3f */
2492
    get_element (elemstr, atomtype);
2493
    if (!strcmp (elemstr, "C "))
2494
            n_Ctot++;
2495
    if (!strcmp (elemstr, "O "))
2496
            n_Otot++;
2497
    if (!strcmp (elemstr, "N "))
2498
            n_Ntot++;
2499
    convert_type (newatomtype, atomtype);
2500
    strsub (xstr, rline, 14, 7);
2501
    strsub (ystr, rline, 23, 7);
2502
    strsub (zstr, rline, 32, 7);
2503
    strsub (chgstr, rline, 43, 7);
2504
    (void)sscanf (xstr, "%g", &xval);
2505
    (void)sscanf (ystr, "%g", &yval);
2506
    (void)sscanf (zstr, "%g", &zval);
2507
    (void)sscanf (chgstr, "%g", &chgval);
2508
    WITH = &atom[n - 1];
2509
    strcpy (WITH->element, elemstr);
2510
    strcpy (WITH->atype, newatomtype);
2511
    WITH->x = xval;
2512
    WITH->y = yval;
2513
    WITH->z = zval;
2514
    WITH->real_charge = chgval;
2515
    if (is_heavyatom (n)) {
2516
            n_heavyatoms++;
18544 georgesk 2517
            WITH->heavy = istrue;
14179 bpr 2518
            if (is_metal (n))
18544 georgesk 2519
              WITH->metal = istrue;
14179 bpr 2520
          }
2521
    WITH->nvalences = get_nvalences (WITH->element);    /* v0.3m   */
2522
  }
6785 bpr 2523
  /*
2524
     with atom^[n] do
2525
     begin
2526
     x := 0; y := 0; z := 0;  (* v0.3g
2527
     formal_charge  := 0;
2528
     real_charge    := 0;
2529
     Hexp           := 0;
2530
     Htot           := 0;
2531
     neighbor_count := 0;
2532
     ring_count     := 0;
18544 georgesk 2533
     arom           := isfalse;
2534
     stereo_care    := isfalse;
2535
     heavy          := isfalse;
2536
     metal          := isfalse;
2537
     tag            := isfalse;
6785 bpr 2538
     end;
2539
   */
2540
  FORLIM = n_bonds;
14179 bpr 2541
  for (n = 0; n < FORLIM; n++) {
2542
    ri++;
2543
    strcpy (rline, molbuf[ri - 1]);
2544
    strsub (a1str, rline, 9, 3);
2545
    strsub (a2str, rline, 15, 3);
2546
    (void)sscanf(a1str, "%d", &a1val);
2547
    (void)sscanf(a2str, "%d", &a2val);
2548
    WITH1 = &bond[n];
2549
    WITH1->a1 = a1val;
2550
    WITH1->a2 = a2val;
2551
    WITH1->btype = rline[19];
2552
    WITH1->ring_count = 0;
18544 georgesk 2553
    WITH1->arom = isfalse;
14179 bpr 2554
    WITH1->topo = btopo_any;
2555
    WITH1->stereo = bstereo_any;
2556
    WITH1->mdl_stereo = 0;      /* v0.3n */
2557
    if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2558
            n_heavybonds++;
2559
  }
6785 bpr 2560
  memset (ring, 0, sizeof (ringlist));
14179 bpr 2561
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
2562
    ringprop[n].size = 0;
18544 georgesk 2563
    ringprop[n].arom = isfalse;
2564
    ringprop[n].envelope = isfalse;
14179 bpr 2565
  }
6785 bpr 2566
  li = ri + 1;
2567
}
2568
 
17891 bpr 2569
static void read_mol2file (char *mfilename)
6785 bpr 2570
{
2571
  /* reads SYBYL mol2 files */
2572
  int n, code;
2573
  char sybatomtype[6];
2574
  char tmpstr[256], rline[256];
2575
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2576
  float xval, yval, zval, chgval;
2577
  char a1str[256], a2str[256], elemstr[256];
2578
  int a1val, a2val, ri, FORLIM;
2579
  atom_rec *WITH;
2580
  bond_rec *WITH1;
2581
 
2582
  if (n_atoms > 0)
2583
    zap_molecule ();
2584
  *rline = '\0';
2585
  ri = li - 1;
14179 bpr 2586
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) == 0)) {
2587
    ri++;
2588
    strcpy (rline, molbuf[ri - 1]);
2589
  }
2590
  if (ri < molbufindex) {
2591
    ri++;
2592
    strcpy (molname, molbuf[ri - 1]);
2593
  }
2594
  if (ri < molbufindex) {
2595
    ri++;
2596
    strcpy (rline, molbuf[ri - 1]);
2597
  }
6785 bpr 2598
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2599
  (void)sscanf (tmpstr, "%d", &n_atoms);
14179 bpr 2600
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 2601
  strsub (tmpstr, rline, 7, 5);
6787 kbelabas 2602
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2603
  /* try */
14179 bpr 2604
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 2605
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2606
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2607
  ring = safe_calloc (1, sizeof (ringlist));
2608
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2609
  /* except
2610
     on e:Eoutofmemory do
2611
     begin
2612
     writeln('Not enough memory');
2613
     halt(4);
2614
     end;
2615
     end; */
2616
  n_heavyatoms = 0;
2617
  n_heavybonds = 0;
2618
  n_Ctot = 0;                   /* v0.3g */
2619
  n_Otot = 0;                   /* v0.3g */
2620
  n_Ntot = 0;                   /* v0.3g */
14179 bpr 2621
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>ATOM", 1) == 0)) {
2622
    ri++;
2623
    strcpy (rline, molbuf[ri - 1]);
2624
  }
6785 bpr 2625
  FORLIM = n_atoms;
14179 bpr 2626
  for (n = 1; n <= FORLIM; n++) {
2627
    /*
2628
      with atom^[n] do
2629
      begin
2630
      x := 0; y := 0; z := 0;  (* v0.3g
2631
      formal_charge  := 0;
2632
      real_charge    := 0;
2633
      Hexp           := 0;
2634
      Htot           := 0;
2635
      neighbor_count := 0;
2636
      ring_count     := 0;
18544 georgesk 2637
      arom           := isfalse;
2638
      stereo_care    := isfalse;
2639
      heavy          := isfalse;
2640
      metal          := isfalse;
2641
      tag            := isfalse;
14179 bpr 2642
      end;
2643
    */
2644
    if (ri < molbufindex) {
2645
            ri++;
2646
            strcpy (rline, molbuf[ri - 1]);
2647
          }
2648
    strsub (sybatomtype, rline, 48, 5);
2649
    get_sybelement (elemstr, sybatomtype);
2650
    if (!strcmp (elemstr, "C "))
2651
            n_Ctot++;
2652
    if (!strcmp (elemstr, "O "))
2653
            n_Otot++;
2654
    if (!strcmp (elemstr, "N "))
2655
            n_Ntot++;
2656
    convert_sybtype (newatomtype, sybatomtype);
2657
    strsub (xstr, rline, 18, 9);
2658
    strsub (ystr, rline, 28, 9);
2659
    strsub (zstr, rline, 38, 9);
2660
    strsub (chgstr, rline, 70, 9);
2661
    (void)sscanf (xstr, "%g", &xval);
2662
    (void)sscanf (ystr, "%g", &yval);
2663
    (void)sscanf (zstr, "%g", &zval);
2664
    (void)sscanf (chgstr, "%g", &chgval);
2665
    WITH = &atom[n - 1];
2666
    strcpy (WITH->element, elemstr);
2667
    strcpy (WITH->atype, newatomtype);
2668
    WITH->x = xval;
2669
    WITH->y = yval;
2670
    WITH->z = zval;
2671
    WITH->real_charge = chgval;
2672
    if (is_heavyatom (n)) {
2673
            n_heavyatoms++;
18544 georgesk 2674
            WITH->heavy = istrue;
14179 bpr 2675
            if (is_metal (n))
18544 georgesk 2676
              WITH->metal = istrue;
14179 bpr 2677
          }
2678
    WITH->nvalences = get_nvalences (WITH->element);    /* v0.3m   */
2679
  }
2680
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>BOND", 1) == 0)) {
2681
    ri++;
2682
    strcpy (rline, molbuf[ri - 1]);
2683
  }
6785 bpr 2684
  FORLIM = n_bonds;
14179 bpr 2685
  for (n = 0; n < FORLIM; n++) {
2686
    if (ri < molbufindex) {
2687
            ri++;
2688
            strcpy (rline, molbuf[ri - 1]);
2689
          }
2690
    strsub (a1str, rline, 9, 3);
2691
    strsub (a2str, rline, 14, 3);
2692
    code = (sscanf (a1str, "%d", &a1val) == 0);
2693
    if (code != 0)
2694
            printf ("%s\007\n", rline);
2695
    code = (sscanf (a2str, "%d", &a2val) == 0);
2696
    if (code != 0)
2697
            printf ("%s\007\n", rline);
2698
    WITH1 = &bond[n];
2699
    WITH1->a1 = a1val;
2700
    WITH1->a2 = a2val;
2701
    if (rline[17] == '1')
2702
            WITH1->btype = 'S';
2703
    if (rline[17] == '2')
2704
            WITH1->btype = 'D';
2705
    if (rline[17] == '3')
2706
            WITH1->btype = 'T';
2707
    if (rline[17] == 'a')
2708
            WITH1->btype = 'A';
2709
    WITH1->ring_count = 0;
18544 georgesk 2710
    WITH1->arom = isfalse;
14179 bpr 2711
    WITH1->topo = btopo_any;
2712
    WITH1->stereo = bstereo_any;
2713
    WITH1->mdl_stereo = 0;      /* v0.3n */
2714
    if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2715
            n_heavybonds++;
2716
  }
6785 bpr 2717
  memset (ring, 0, sizeof (ringlist));
14179 bpr 2718
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
2719
    ringprop[n].size = 0;
18544 georgesk 2720
    ringprop[n].arom = isfalse;
2721
    ringprop[n].envelope = isfalse;
14179 bpr 2722
  }
6785 bpr 2723
  li = ri + 1;
2724
}
2725
 
17891 bpr 2726
static void read_charges (char *chgstring_)
6785 bpr 2727
{
2728
  char chgstring[256];
2729
  int a_id, a_chg;
2730
  /* int n_chrg;*/
2731
 
2732
  /* typical example: a molecule with 2 cations + 1 anion */
2733
  /* M  CHG  3   8   1  10   1  11  -1 */
2734
  strcpy (chgstring, chgstring_);
2735
  if (strpos2 (chgstring, "M  CHG", 1) <= 0)
2736
    return;
2737
  strdelete (chgstring, 1, 6);
2738
  left_trim (chgstring);
14179 bpr 2739
  /* n_chrg = left_int (chgstring);*/
6785 bpr 2740
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2741
  /* p2c: checkmol.pas, line 2077:
2742
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2743
  /*$IFDEF debug */
2744
  /*if (n_chrg == 0)
2745
     debugoutput ("strange... M  CHG present, but no charges found"); */
2746
  /*$ENDIF */
14626 bpr 2747
  left_int (chgstring); /* delete the first one, that is the number of atoms */
14179 bpr 2748
  while (*chgstring != '\0') {
2749
    a_id = left_int (chgstring);
2750
    a_chg = left_int (chgstring);
2751
    if (a_id != 0 && a_chg != 0)
14626 bpr 2752
            atom[a_id - 1].formal_charge = a_chg;
2753
          //printf ("CHG %i %i\n", a_id, a_chg);
14179 bpr 2754
  }
6785 bpr 2755
}
2756
 
14179 bpr 2757
static void read_isotopes (char *isotopestring_)
6785 bpr 2758
{
2759
  char isotopestring[256];
2760
  int a_id, a_nucleon_number;
2761
  /* int n_isotopes;*/
2762
 
2763
  /* typical example: a molecule with 2 cations + 1 anion */
2764
  /* M  CHG  3   8   1  10   1  11  -1 */
2765
  strcpy (isotopestring, isotopestring_);
2766
  if (strpos2 (isotopestring, "M  ISO", 1) <= 0)
2767
    return;
2768
  strdelete (isotopestring, 1, 6);
2769
  left_trim (isotopestring);
14626 bpr 2770
  left_int (isotopestring);
14179 bpr 2771
  while (*isotopestring != '\0') {
2772
    a_id = left_int (isotopestring);
2773
    a_nucleon_number = left_int (isotopestring);
2774
    if (a_id != 0 && a_nucleon_number != 0) {
2775
            atom[a_id - 1].nucleon_number = a_nucleon_number;
2776
            if (!strcmp (atom[a_id - 1].element, "H ")) {
18544 georgesk 2777
              atom[a_id - 1].heavy = istrue;
6785 bpr 2778
              n_heavyatoms++;
2779
              strcpy (atom[a_id - 1].atype, "DU ");
2780
            }
14179 bpr 2781
          }
14626 bpr 2782
    //printf ("ISO %i, %i\n", a_id, a_nucleon_number);
14179 bpr 2783
  }
6785 bpr 2784
}
2785
 
17891 bpr 2786
static void read_radicals (char *radstring_)
6785 bpr 2787
{
2788
  char radstring[256];
6788 kbelabas 2789
  int a_id, a_rad;
6785 bpr 2790
 
2791
  /* typical example: a molecule with 2 cations + 1 anion */
2792
  /* M  CHG  3   8   1  10   1  11  -1 */
2793
  strcpy (radstring, radstring_);
2794
  if (strpos2 (radstring, "M  RAD", 1) <= 0)
2795
    return;
2796
  strdelete (radstring, 1, 6);
2797
  left_trim (radstring);
14626 bpr 2798
  left_int (radstring);
6785 bpr 2799
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2800
  /* p2c: checkmol.pas, line 2077:
2801
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2802
  /*$IFDEF debug */
2803
  /*if (n_chrg == 0)
2804
     debugoutput ("strange... M  CHG present, but no charges found"); */
2805
  /*$ENDIF */
14179 bpr 2806
  while (*radstring != '\0') {
2807
    a_id = left_int (radstring);
2808
    a_rad = left_int (radstring);
2809
    if (a_id != 0 && a_rad != 0)
2810
            atom[a_id - 1].radical_type = a_rad;
2811
    //printf ("RAD %i %i\n", a_id, a_rad);
2812
  }
6785 bpr 2813
}
2814
 
14179 bpr 2815
static void read_MDLmolfile (char *mfilename)
6785 bpr 2816
{
2817
  /* reads MDL mol files */
2818
  int n, v, tmp_n_atoms, tmp_n_bonds, code;     /* v0.3l */
2819
  char rline[256], tmpstr[256];
2820
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2821
  float xval, yval, zval, chgval;
2822
  char a1str[256], a2str[256], elemstr[256];
2823
  int a1val, a2val, ri, rc, bt, bs;
2824
  int sepcount = 0;
2825
  int i;                        /* v0.3j */
18544 georgesk 2826
  boolean clearcharges = istrue;        /* v0.3j */
6785 bpr 2827
  char STR1[256];
14179 bpr 2828
  /*  int FORLIM;*/
6785 bpr 2829
  atom_rec *WITH;
2830
  bond_rec *WITH1;
2831
 
2832
  /* v0.3j */
2833
  if (n_atoms > 0)
2834
    zap_molecule ();
18544 georgesk 2835
  /*cm_mdlmolfile := isfalse; */
6785 bpr 2836
  *rline = '\0';
2837
  ri = li;
2838
  strcpy (molname, molbuf[ri - 1]);     /* line 1 */
2839
  if (ri < molbufindex)         /* line 2 */
2840
    ri++;
2841
  strcpy (rline, molbuf[ri - 1]);
14179 bpr 2842
  if (strpos2 (rline, "CheckMol", 1) == 3) {
18544 georgesk 2843
    /*cm_mdlmolfile := istrue; */
2844
    found_arominfo = istrue;
14179 bpr 2845
    tmfcode = 1;                /* v0.3m (begin) */
2846
    code = 0;
2847
    if ((strlen (rline) >= 39) && (strpos2 (rline, "TMF", 1) == 35)) {
2848
      /* v0.3m; encoding of tweaklevel */
2849
            strsub (tmpstr, rline, 38, 2);
2850
            code = (sscanf (tmpstr, "%d", &tmfcode) == 0);
2851
          }
2852
    if (code != 0 || tmfcode != tweaklevel)
18544 georgesk 2853
            tmfmismatch = istrue;
14179 bpr 2854
    else
18544 georgesk 2855
            tmfmismatch = isfalse;
17890 bpr 2856
      if ((strpos2 (rline, ":r0", 1) >= 40 && ringsearch_mode != rs_sar) ||
14179 bpr 2857
                (strpos2 (rline, ":r1", 1) >= 40 && ringsearch_mode != rs_ssr))
18544 georgesk 2858
              tmfmismatch = istrue;
2859
      if ((strpos2 (rline, ":m0", 1) >= 40 && opt_metalrings == istrue) ||
2860
                (strpos2 (rline, ":m1", 1) >= 40 && opt_metalrings == isfalse))
2861
              tmfmismatch = istrue;
14179 bpr 2862
      /* p2c: checkmol.pas, line 2128:
2863
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
2864
            /*$IFDEF debug */
2865
            //if (tmfmismatch)
2866
            //printf ("\"tweaked\" molfile: version mismatch!\n");
2867
            // else
2868
            //printf ("\"tweaked\" molfile: version OK");
2869
          }
2870
      /*$ENDIF */
2871
      /* v0.3m (end) */
2872
      if (ri < molbufindex)             /* line 3 */
2873
        ri++;
2874
      strcpy (rline, molbuf[ri - 1]);
2875
      strcpy (molcomment, rline);
2876
      if (ri < molbufindex)             /* line 4 */
2877
        ri++;
2878
      strcpy (rline, molbuf[ri - 1]);
2879
      sprintf (tmpstr, "%.3s", rline);
2880
      (void)sscanf (tmpstr, "%d", &n_atoms);
2881
      strsub (tmpstr, rline, 4, 3);
2882
      (void)sscanf (tmpstr, "%d", &n_bonds);
2883
      strsub (tmpstr, rline, 10, 3);
2884
      /* if it is a CheckMol-tweaked molfile, this is the number of rings */
2885
      n_cmrings = 0;
2886
      code = (sscanf (tmpstr, "%d", &n_cmrings) == 0);
2887
      if (code != 0)
2888
        n_cmrings = 0;
2889
      /* do some range checking for n_atoms, n_bonds; new in v0.3l */
2890
      tmp_n_atoms = n_atoms;
2891
      if (n_atoms > max_atoms)
2892
        n_atoms = max_atoms;
2893
      if (n_atoms < 0)
2894
        n_atoms = 0;
2895
      tmp_n_bonds = n_bonds;
2896
      if (n_bonds > max_bonds)
2897
        n_bonds = max_bonds;
2898
      if (n_bonds < 0)
2899
        n_bonds = 0;
2900
      if (n_atoms == 0
6785 bpr 2901
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 2902
        && opt_verbose
6785 bpr 2903
#endif
14179 bpr 2904
    ) {                                 /* v0.3l */
2905
        printf ("WARNING: Possible NoStruct read!\n");
2906
        printf ("NoStructs are proprietary, obsolete and dangerous.\n");
2907
      }
2908
      /* try */
2909
      atom = safe_calloc (n_atoms, sizeof (atom_rec));
2910
      bond = safe_calloc (n_bonds, sizeof (bond_rec));
2911
      /* this would be only one safe_calloc() in C;  v0.3l */
2912
      ring = safe_calloc (1, sizeof (ringlist));
2913
      ringprop = safe_calloc (1, sizeof (ringprop_type));
2914
      /* except
2915
      on e:Eoutofmemory do
2916
      begin
2917
      writeln('Not enough memory');
2918
      (* close(molfile);
2919
      halt(4);
2920
      exit;
2921
      end;
2922
      end; */
2923
      /* check for the chirality flag */
2924
      if (strlen (rline) > 14 && rline[14] == '1')      /* new in v0.3f */
18544 georgesk 2925
        chir_flag = istrue;
14179 bpr 2926
      n_heavyatoms = 0;
2927
      n_heavybonds = 0;
2928
      n_Ctot = 0;                       /* v0.3g */
2929
      n_Otot = 0;                       /* v0.3g */
2930
      n_Ntot = 0;                       /* v0.3g */
2931
      if (n_atoms > 0) {                                /* v0.3l */
2932
        for (n = 1; n <= tmp_n_atoms; n++) {
2933
                if (n <= max_atoms)
2934
                  v = n;
2935
                else
2936
                  v = max_atoms;
2937
                /* just for safety; v0.3l */
2938
                /*
2939
                with atom^[v] do
2940
                begin
2941
                x := 0; y := 0; z := 0;  (* v0.3g
2942
                formal_charge  := 0;
2943
                real_charge    := 0;
2944
                Hexp           := 0;
2945
                Htot           := 0;
2946
                neighbor_count := 0;
2947
                ring_count     := 0;
18544 georgesk 2948
                arom           := isfalse;
2949
                stereo_care    := isfalse;
2950
                metal          := isfalse;
2951
                heavy          := isfalse;
2952
                tag            := isfalse;
14179 bpr 2953
                end;
2954
                */
2955
                /* replaced by fillchar() after getmem() (see above); v0.3l */
2956
                ri++;
2957
                strcpy (rline, molbuf[ri - 1]);
2958
                strsub (atomtype, rline, 32, 3);
2959
                get_MDLelement (elemstr, atomtype);
2960
                if (!strcmp (elemstr, "C "))
2961
                  n_Ctot++;
2962
                if (!strcmp (elemstr, "O "))
2963
                  n_Otot++;
2964
                if (!strcmp (elemstr, "N "))
2965
                  n_Ntot++;
6785 bpr 2966
 
14179 bpr 2967
                convert_MDLtype (newatomtype, atomtype);
2968
                strsub (xstr, rline, 1, 10);    /* fixed in v0.3k (was: 2,9 etc.) */
2969
                strsub (ystr, rline, 11, 10);
2970
                strsub (zstr, rline, 21, 10);
2971
                /*chgstr := '0'; */
2972
                strsub (chgstr, rline, 37, 3);  /* new in v0.3j */
2973
                (void)sscanf (chgstr, "%f", &chgval);
2974
                if (chgval != 0) {
2975
                  if (chgval >= 1 && chgval <= 7)
2976
                          chgval = 4.0 - chgval;
2977
                  else {
2978
                          chgval = 0.0;
2979
                        }
2980
                }                       /* end (v0.3j) */
2981
                (void)sscanf (xstr, "%f", &xval);
2982
                (void)sscanf (ystr, "%f", &yval);
2983
                (void)sscanf (zstr, "%f", &zval);
2984
                /* v0.3k: removed superfluous val(chgstr,chgval,code) */
2985
                WITH = &atom[v - 1];
2986
                strcpy (WITH->element, elemstr);
2987
                if (!strcmp (elemstr, "A ") || !strcmp (elemstr, "Q ") ||
2988
                    !strcmp (elemstr, "X "))
2989
                  /* 'X ' added in v0.3n */
18544 georgesk 2990
                  found_querymol = istrue;
6785 bpr 2991
 
14179 bpr 2992
                strcpy (WITH->atype, newatomtype);
6785 bpr 2993
 
14179 bpr 2994
                if (!strcmp (elemstr, "D ")) {
2995
                  strcpy (WITH->element, "H ");
2996
                  WITH->nucleon_number = 2;
2997
                }                       /* 0.3x */
2998
                if (!strcmp (elemstr, "T ")) {
2999
                  strcpy (WITH->element, "H ");
3000
                  WITH->nucleon_number = 3;
3001
                }                       /* 0.3x */
6785 bpr 3002
 
14179 bpr 3003
                WITH->x = xval;
3004
                WITH->y = yval;
3005
                WITH->z = zval;
3006
                WITH->formal_charge = (long) floor (chgval + 0.5);
3007
                WITH->real_charge = 0.0;        /* v0.3j */
3008
                /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3009
                if (strlen (rline) > 37 && rline[37] == '0') {
18544 georgesk 3010
                  WITH->arom = istrue;
3011
                  found_arominfo = istrue;
14179 bpr 3012
                }
3013
                /* new in v0.3d: read stereo care flag */
3014
                if (strlen (rline) > 47 && rline[47] == '1')
18544 georgesk 3015
                  WITH->stereo_care = istrue;
14179 bpr 3016
                if (is_heavyatom (n)) {
3017
                  n_heavyatoms++;
18544 georgesk 3018
                  WITH->heavy = istrue;
14179 bpr 3019
                  if (is_metal (n))
18544 georgesk 3020
                          WITH->metal = istrue;
14179 bpr 3021
                }
3022
                WITH->nvalences = get_nvalences (WITH->element);
3023
                /* v0.3m                 */
3024
              }
3025
      }                         /* if (n_atoms > 0)... */
3026
      if (n_bonds > 0) {                                /* v0.3l */
3027
        for (n = 1; n <= tmp_n_bonds; n++) {
3028
                if (n <= max_bonds)
3029
                  v = n;
3030
                else
3031
                  v = max_bonds;
3032
                /* just for safety; v0.3l */
3033
                ri++;
3034
                strcpy (rline, molbuf[ri - 1]);
3035
                sprintf (a1str, "%.3s", rline);
3036
                strsub (a2str, rline, 4, 3);
3037
                code = (sscanf (a1str, "%d", &a1val) == 0);
3038
                if (code != 0)  /* v0.3l */
3039
                  a1val = 1;
3040
                code = (sscanf (a2str, "%d", &a2val) == 0);
3041
                if (code != 0)  /* v0.3l */
3042
                  a2val = 1;
3043
                WITH1 = &bond[v - 1];
3044
                WITH1->a1 = a1val;
3045
                WITH1->a2 = a2val;
3046
                if (rline[8] == '1')    /* single */
3047
                  WITH1->btype = 'S';
3048
                if (rline[8] == '2')    /* double */
3049
                  WITH1->btype = 'D';
3050
                if (rline[8] == '3')    /* triple */
3051
                  WITH1->btype = 'T';
3052
                if (rline[8] == '4')    /* aromatic */
3053
                  WITH1->btype = 'A';
3054
                if (rline[8] == '5')    /* single or double */
3055
                  WITH1->btype = 'l';
3056
                if (rline[8] == '6')    /* single or aromatic */
3057
                  WITH1->btype = 's';
3058
                if (rline[8] == '7')    /* double or aromatic */
3059
                  WITH1->btype = 'd';
3060
                if (rline[8] == '8')    /* any */
3061
                  WITH1->btype = 'a';
3062
                sprintf (STR1, "%c", WITH1->btype);
3063
                if (strpos2 ("lsda", STR1, 1) > 0)
18544 georgesk 3064
                  found_querymol = istrue;
3065
                WITH1->arom = isfalse;
3066
                WITH1->q_arom = isfalse;        /* 0.3p */
14179 bpr 3067
                /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3068
                if (WITH1->btype == 'A' || rline[7] == '0') {
18544 georgesk 3069
                  WITH1->arom = istrue;
14179 bpr 3070
                  if (rline[7] == '0')
18544 georgesk 3071
                          found_arominfo = istrue;
14179 bpr 3072
                }
3073
                strsub (tmpstr, rline, 13, 3);
3074
                /* new in v0.3d: read ring_count from tweaked molfile */
3075
                code = (sscanf (tmpstr, "%d", &rc) == 0);
3076
                if (code != 0 || rc < 0 || progmode == pmCheckMol || tmfmismatch)
3077
                  WITH1->ring_count = 0;
3078
                else
3079
                 WITH1->ring_count = rc;
3080
                /* v0.3n: added tmfmismatch check */
3081
                strsub (tmpstr, rline, 16, 3);  /* new in v0.3d: read bond topology; */
3082
                code = (sscanf (tmpstr, "%d", &bt) == 0);
3083
                /* extended features are encoded by leading zero */
3084
                if (code != 0 || (unsigned long) bt > 2)
3085
                  WITH1->topo = btopo_any;
3086
                else {
3087
                  if (tmpstr[1] == '0')
3088
                          WITH1->topo = bt + 3;
3089
                  else
3090
                          WITH1->topo = bt;
3091
                }
3092
          /* v0.3n changed >5 into >2 */
3093
          /* new in v0.3d: add stereo property from MDL "stereo care" flag in atom block */
3094
          WITH1->stereo = bstereo_any;
3095
          if (WITH1->btype == 'D') {
3096
            if (atom[WITH1->a1 - 1].stereo_care
3097
                && atom[WITH1->a2 - 1].stereo_care) {           /* this is the MDL-conformant encoding, */
3098
              WITH1->stereo = bstereo_xyz;      /* for an alternative see below */
18544 georgesk 3099
              ez_flag = istrue; /* v0.3f */
14179 bpr 3100
            }
3101
                  else {                /* this extended feature is encoded by a leading zero */
3102
                          strsub (tmpstr, rline, 10, 3);
3103
                          /* new in v0.3d: read bond stereo specification; */
3104
                          code = (sscanf (tmpstr, "%d", &bs) == 0);
3105
                          WITH1->mdl_stereo = bs;       /* v0.3n */
3106
                          if (code != 0 || bs <= 0 || bs > 2)
3107
                            WITH1->stereo = bstereo_any;
3108
                          else
3109
                            WITH1->stereo = bstereo_xyz;
3110
                          if (tmpstr[1] == '0')
3111
                            WITH1->stereo = bstereo_xyz;
3112
                        }
3113
                }
18544 georgesk 3114
                /*if stereo <> bstereo_any then ez_search := istrue; */
14179 bpr 3115
                if (WITH1->stereo != bstereo_any)       /* changed in v0.3f */
18544 georgesk 3116
                  ez_flag = istrue;
14179 bpr 3117
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '1')
3118
                  WITH1->stereo = bstereo_up;
3119
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '6')
3120
                  WITH1->stereo = bstereo_down;
3121
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '4')
3122
                  WITH1->stereo = bstereo_either;       /* 0.3x */
3123
                if (WITH1->btype == 'D' && strlen (rline) > 11 && rline[11] == '3')
3124
                  WITH1->stereo = bstereo_double_either;        /* 0.3x */
3125
                strsub (tmpstr, rline, 10, 3);
3126
                /* new in v0.3n: save original bond stereo specification; */
3127
                (void)sscanf (tmpstr, "%d", &bs);
3128
                /* v0.3n */
3129
          /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3130
                WITH1->mdl_stereo = bs; /* v0.3n */
3131
                if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
3132
                  n_heavybonds++;
3133
              }
3134
      }                         /* if (n_bonds > 0)... */
3135
      while (ri < molbufindex && sepcount < 1) {
3136
        ri++;
3137
        strcpy (rline, molbuf[ri - 1]);
3138
    if (strpos2 (rline, "M  CHG", 1) > 0) {                     /* new in v0.3j */
3139
            if (clearcharges) {                 /* "M  CHG" supersedes all "old-style" charge values */
6785 bpr 3140
 
3141
              for (i = 0; i < n_atoms; i++)
14179 bpr 3142
                atom[i].formal_charge = 0;
6785 bpr 3143
            }
14179 bpr 3144
            read_charges (rline);
18544 georgesk 3145
            clearcharges = isfalse;
14179 bpr 3146
            /* subsequent "M  CHG" lines must not clear previous values */
3147
          }
6785 bpr 3148
 
14179 bpr 3149
    if (strpos2 (rline, "M  ISO", 1) > 0)
3150
            read_isotopes (rline);      /* 0.3x */
6785 bpr 3151
 
14179 bpr 3152
    if (strpos2 (rline, "M  RAD", 1) > 0)
3153
            read_radicals (rline);      /* 0.3x */
6785 bpr 3154
 
14179 bpr 3155
    if (strpos2 (rline, "$$$$", 1) > 0) {
3156
            sepcount++;
3157
            if (molbufindex > ri + 2)   /* we assume this is an SDF file */
18544 georgesk 3158
              mol_in_queue = istrue;
14179 bpr 3159
          }
3160
  }
6785 bpr 3161
  memset (ring, 0, sizeof (ringlist));
14179 bpr 3162
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
3163
    ringprop[n].size = 0;
18544 georgesk 3164
    ringprop[n].arom = isfalse;
3165
    ringprop[n].envelope = isfalse;
14179 bpr 3166
  }
6785 bpr 3167
  li = ri + 1;
3168
}
3169
 
14179 bpr 3170
static void write_MDLmolfile ()
6785 bpr 3171
{
3172
  int i;
3173
  char tmpstr[256];
3174
  char wline[256];
3175
  int a_chg;
3176
  int a_iso;
3177
  int a_rad;
3178
  char tmflabel[256];           /* v0.3m */
3179
  char STR1[256];
3180
  /*char STR7[256];*/
3181
  int FORLIM;
3182
 
3183
  sprintf (tmflabel, "%d", (int) tweaklevel);   /* v0.3m */
3184
  while (strlen (tmflabel) < 2) /* v0.3m */
3185
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
3186
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
3187
  if (strlen (molname) > 80)
3188
    sprintf (molname, "%.80s", strcpy (STR1, molname));
3189
  puts (molname);
3190
  printf ("  CheckMol                        %s", tmflabel);    /* v0.3m */
3191
  if (ringsearch_mode == rs_sar)        /* v0.3m */
3192
    printf (":r0");
3193
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
3194
    printf (":r1");
3195
  if (opt_metalrings)
3196
    printf (":m1");
3197
  else
3198
    printf (":m0");
3199
  /* v0.3m */
3200
  printf ("\n%s\n", molcomment);
3201
  *wline = '\0';
3202
  *tmpstr = '\0';
3203
  sprintf (tmpstr, "%d", n_atoms);
3204
  lblank (3L, tmpstr);
3205
  strcat (wline, tmpstr);
3206
  *tmpstr = '\0';               /* first 3 digits: number of atoms */
3207
  sprintf (tmpstr, "%d", n_bonds);
3208
  lblank (3L, tmpstr);
3209
  strcat (wline, tmpstr);
3210
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
3211
  strcpy (tmpstr, "  0");
3212
  strcat (wline, tmpstr);
3213
  *tmpstr = '\0';               /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 3214
  /* p2c: checkmol.pas, line 2388:
3215
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3216
#ifdef REDUCED_SAR
3217
  sprintf (tmpstr, "%d", n_countablerings);
3218
  /* v0.3n; changed n_rings into n_countablerings */
3219
#else
3220
  sprintf (tmpstr, "%d", n_rings);
3221
#endif
3222
  lblank (3L, tmpstr);
3223
  strcat (wline, tmpstr);
3224
  *tmpstr = '\0';
3225
  /* officially "obsolete", we use it for the number of rings */
3226
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
3227
  if (chir_flag)
3228
    strcat (wline, "1");
3229
  else
3230
    strcat (wline, "0");
3231
  /* v0.3n */
3232
  strcat (wline, "               999 V2000");
3233
  /* v0.3n (adjust string length) */
3234
  puts (wline);
3235
  FORLIM = n_atoms;
14179 bpr 3236
  for (i = 0; i < FORLIM; i++) {
3237
    *wline = '\0';
3238
    sprintf (tmpstr, "%1.4f", atom[i].x);
3239
    lblank (10L, tmpstr);
3240
    strcat (wline, tmpstr);
3241
    sprintf (tmpstr, "%1.4f", atom[i].y);
3242
    lblank (10L, tmpstr);
3243
    strcat (wline, tmpstr);
3244
    sprintf (tmpstr, "%1.4f", atom[i].z);
3245
    lblank (10L, tmpstr);
3246
    strcat (wline, tmpstr);
3247
    strcpy (tmpstr, atom[i].element);
3248
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
3249
    //tmpstr[0] = toupper (tmpstr[0]);
3250
    all_lowercase (tmpstr);
3251
    tmpstr[0] = toupper (tmpstr[0]);
3252
    /*wline := wline + ' '+atom^[i].element+' '; */
3253
    sprintf (wline + strlen (wline), " %s ", tmpstr);
3254
    strcat (wline, " 0");       /* mass difference (isotopes) */
3255
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
3256
    if (atom[i].arom)
3257
            strcpy (tmpstr, " 00");
3258
    else
3259
            strcpy (tmpstr, "  0");
6785 bpr 3260
      strcat (wline, tmpstr);
3261
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0");
3262
      puts (wline);
14179 bpr 3263
  }
6785 bpr 3264
  FORLIM = n_bonds;
14179 bpr 3265
  for (i = 0; i < FORLIM; i++) {
3266
    *wline = '\0';
3267
    sprintf (tmpstr, "%d", bond[i].a1);
3268
    lblank (3L, tmpstr);
3269
    strcat (wline, tmpstr);
3270
    sprintf (tmpstr, "%d", bond[i].a2);
3271
    lblank (3L, tmpstr);
3272
    strcat (wline, tmpstr);
3273
    if (bond[i].btype == 'S')
3274
            strcpy (tmpstr, "  1");
3275
    if (bond[i].btype == 'D')
3276
            strcpy (tmpstr, "  2");
3277
    if (bond[i].btype == 'T')
3278
            strcpy (tmpstr, "  3");
3279
    if (bond[i].btype == 'A')
3280
            strcpy (tmpstr, "  4");
3281
    if (bond[i].btype == 'l')
3282
            strcpy (tmpstr, "  5");
3283
    if (bond[i].btype == 's')
3284
            strcpy (tmpstr, "  6");
3285
    if (bond[i].btype == 'd')
3286
            strcpy (tmpstr, "  7");
3287
    if (bond[i].btype == 'a')
3288
            strcpy (tmpstr, "  8");
6785 bpr 3289
      /* now encode our own aromaticity information */
14179 bpr 3290
    if (bond[i].arom)
3291
            tmpstr[1] = '0';
3292
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
3293
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
3294
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
3295
    /*    wline := wline + '  0'; */
3296
    /* restore original value from MDL molfile (v0.3n) */
3297
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
3298
    *tmpstr = '\0';
3299
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
3300
    strcat (wline, "  ");
3301
    strcat (wline, tmpstr);
3302
    *tmpstr = '\0';
3303
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
3304
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
3305
    sprintf (tmpstr, "%i", bond[i].ring_count);
3306
    while (strlen (tmpstr) < 3)
3307
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
3308
    sprintf (wline + strlen (wline), "%s  0  0", tmpstr);
3309
    puts (wline);
3310
  }
6785 bpr 3311
  FORLIM = n_atoms;
14179 bpr 3312
  for (i = 1; i <= FORLIM; i++) {
3313
    a_chg = atom[i - 1].formal_charge;
3314
    if (a_chg != 0) {
3315
            strcpy (wline, "M  CHG  1 ");
3316
            sprintf (tmpstr, "%d", i);
3317
            lblank (3L, tmpstr);
3318
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3319
            sprintf (tmpstr, "%d", a_chg);
3320
            lblank (3L, tmpstr);
3321
            strcat (wline, tmpstr);
3322
            puts (wline);
3323
          }
3324
  }
3325
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
3326
    a_iso = atom[i - 1].nucleon_number;
3327
    if (a_iso != 0) {
3328
            strcpy (wline, "M  ISO  1 ");
3329
            sprintf (tmpstr, "%d", i);
3330
            lblank (3L, tmpstr);
3331
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3332
            sprintf (tmpstr, "%d", a_iso);
3333
            lblank (3L, tmpstr);
3334
            strcat (wline, tmpstr);
3335
            puts (wline);
3336
          }
3337
  }
3338
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
3339
    a_rad = atom[i - 1].radical_type;
3340
    if (a_rad != 0) {
3341
            strcpy (wline, "M  RAD  1 ");
3342
            sprintf (tmpstr, "%d", i);
3343
            lblank (3L, tmpstr);
3344
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3345
            sprintf (tmpstr, "%d", a_rad);
3346
            lblank (3L, tmpstr);
3347
            strcat (wline, tmpstr);
3348
            puts (wline);
3349
          }
3350
  }
6785 bpr 3351
  printf ("M  END\n");
3352
}
3353
 
3354
/*============= chemical processing functions && procedures ============ */
3355
 
17891 bpr 3356
static boolean is_electroneg (char *a_el)
6785 bpr 3357
{
3358
  /* new in v0.3j */
18544 georgesk 3359
  boolean res = isfalse;
6785 bpr 3360
 
3361
  if (!strcmp (a_el, "N "))
18544 georgesk 3362
    res = istrue;
6785 bpr 3363
  if (!strcmp (a_el, "P "))
18544 georgesk 3364
    res = istrue;
6785 bpr 3365
  if (!strcmp (a_el, "O "))
18544 georgesk 3366
    res = istrue;
6785 bpr 3367
  if (!strcmp (a_el, "S "))
18544 georgesk 3368
    res = istrue;
6785 bpr 3369
  if (!strcmp (a_el, "SE"))
18544 georgesk 3370
    res = istrue;
6785 bpr 3371
  if (!strcmp (a_el, "TE"))
18544 georgesk 3372
    res = istrue;
6785 bpr 3373
  if (!strcmp (a_el, "F "))
18544 georgesk 3374
    res = istrue;
6785 bpr 3375
  if (!strcmp (a_el, "CL"))
18544 georgesk 3376
    res = istrue;
6785 bpr 3377
  if (!strcmp (a_el, "BR"))
18544 georgesk 3378
    res = istrue;
6785 bpr 3379
  if (!strcmp (a_el, "I "))
18544 georgesk 3380
    res = istrue;
6785 bpr 3381
  if (!strcmp (a_el, "AT"))
18544 georgesk 3382
    res = istrue;
6785 bpr 3383
  return res;
3384
}
3385
 
14179 bpr 3386
static void count_neighbors ()
6785 bpr 3387
{
3388
  /* counts heavy-atom neighbors and explicit hydrogens */
3389
  int i, FORLIM;
3390
 
3391
  if (n_atoms < 1 || n_bonds < 1)
3392
    return;
3393
  FORLIM = n_bonds;
14179 bpr 3394
  for (i = 0; i < FORLIM; i++) {
3395
    if (atom[bond[i].a1 - 1].heavy)
3396
            atom[bond[i].a2 - 1].neighbor_count++;
3397
    if (atom[bond[i].a2 - 1].heavy)
3398
            atom[bond[i].a1 - 1].neighbor_count++;
3399
    if (!strcmp (atom[bond[i].a1 - 1].element, "H "))
3400
            atom[bond[i].a2 - 1].Hexp++;
3401
    if (!strcmp (atom[bond[i].a2 - 1].element, "H "))
3402
            atom[bond[i].a1 - 1].Hexp++;
3403
    /* plausibility check (new in v02.i) */
3404
    if (atom[bond[i].a1 - 1].neighbor_count > max_neighbors ||
3405
              atom[bond[i].a2 - 1].neighbor_count > max_neighbors) {
18544 georgesk 3406
            mol_OK = isfalse;
14179 bpr 3407
            /*writeln('invalid molecule!'); */
3408
          }
3409
  }
6785 bpr 3410
}
3411
 
17891 bpr 3412
static void get_neighbors (int *Result, int id)
6785 bpr 3413
{
6786 kbelabas 3414
  int i;
6785 bpr 3415
  //neighbor_rec nb_tmp;
3416
  int nb_count = 0;
3417
  //int FORLIM = n_bonds;
3418
 
3419
  //memset (Result, 0, sizeof (neighbor_rec));
3420
 
14179 bpr 3421
  for (i = 0; i < n_bonds; i++) {
3422
    if (bond[i].a1 == id && atom[bond[i].a2 - 1].heavy
3423
              && nb_count < max_neighbors) {
3424
            Result[nb_count++] = bond[i].a2;
3425
          }
3426
    if (bond[i].a2 == id && atom[bond[i].a1 - 1].heavy
3427
              && nb_count < max_neighbors) {
3428
            Result[nb_count++] = bond[i].a1;
3429
          }
3430
  }
6785 bpr 3431
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3432
}
3433
 
14179 bpr 3434
static void get_ndl_neighbors (int *Result, int id)
6785 bpr 3435
{
3436
  int i;
3437
  //neighbor_rec nb_tmp;
3438
  int nb_count = 0;
3439
  /* v0.3i: use max_neighbors instead of a fixed value of 8 */
3440
  //int FORLIM = ndl_n_bonds;
3441
 
3442
  //memset (nb_tmp, 0, sizeof (neighbor_rec));
3443
 
14179 bpr 3444
  for (i = 0; i < ndl_n_bonds; i++) {
3445
    if (ndl_bond[i].a1 == id && nb_count < max_neighbors &&
3446
              ndl_atom[ndl_bond[i].a2 - 1].heavy) {
3447
            nb_count++;
3448
            Result[nb_count - 1] = ndl_bond[i].a2;
3449
          }
3450
    if (ndl_bond[i].a2 == id && nb_count < max_neighbors &&
3451
              ndl_atom[ndl_bond[i].a1 - 1].heavy){
3452
            nb_count++;
3453
            Result[nb_count - 1] = ndl_bond[i].a1;
3454
          }
3455
  }
6785 bpr 3456
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3457
}
3458
 
14179 bpr 3459
static int * get_nextneighbors (int *Result, int id, int prev_id)
6785 bpr 3460
{
3461
  int i;
3462
  neighbor_rec nb_tmp;
3463
  int nb_count = 0;
3464
  int FORLIM;
3465
 
3466
  /* gets all neighbors except prev_id (usually the atom where we came from */
3467
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3468
  FORLIM = n_bonds;
14179 bpr 3469
  for (i = 0; i < FORLIM; i++) {
3470
    if (bond[i].a1 == id && bond[i].a2 != prev_id &&
3471
              nb_count < max_neighbors && atom[bond[i].a2 - 1].heavy) {
3472
            nb_count++;
3473
            nb_tmp[nb_count - 1] = bond[i].a2;
3474
          }
3475
    if (bond[i].a2 == id && bond[i].a1 != prev_id &&
3476
              nb_count < max_neighbors && atom[bond[i].a1 - 1].heavy) {
3477
            nb_count++;
3478
            nb_tmp[nb_count - 1] = bond[i].a1;
3479
          }
3480
  }
6785 bpr 3481
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3482
}
3483
 
14179 bpr 3484
static int * get_ndl_nextneighbors (int *Result, int id, int prev_id)
6785 bpr 3485
{
3486
  int i;
3487
  neighbor_rec nb_tmp;
3488
  int nb_count = 0;
3489
  int FORLIM;
3490
 
3491
  /* gets all neighbors except prev_id (usually the atom where we came from */
3492
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3493
  FORLIM = ndl_n_bonds;
14179 bpr 3494
  for (i = 0; i < FORLIM; i++) {
3495
    if (ndl_bond[i].a1 == id && ndl_bond[i].a2 != prev_id &&
3496
              nb_count < max_neighbors && ndl_atom[ndl_bond[i].a2 - 1].heavy) {
3497
            nb_count++;
3498
            nb_tmp[nb_count - 1] = ndl_bond[i].a2;
3499
          }
3500
    if (ndl_bond[i].a2 == id && ndl_bond[i].a1 != prev_id &&
3501
              nb_count < max_neighbors && ndl_atom[ndl_bond[i].a1 - 1].heavy) {
3502
            nb_count++;
3503
            nb_tmp[nb_count - 1] = ndl_bond[i].a1;
3504
          }
3505
  }
6785 bpr 3506
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3507
}
3508
 
3509
#if 0
3510
static int path_pos (id, a_path) int id;
14179 bpr 3511
  int *a_path;
3512
  {
3513
  /* new version in v0.3l */
3514
  int i;
3515
  int pp = 0;
6785 bpr 3516
 
14179 bpr 3517
  for (i = 1; i <= max_ringsize; i++)
3518
  {
3519
  if (a_path[i - 1] == id)
3520
  {
3521
  pp = i;
3522
  /* p2c: checkmol.pas, line 2620:
3523
  * Warning: Expected a '(', found a semicolon [227]  */
3524
  /* p2c: checkmol.pas, line 2620:
3525
  * Warning: Expected an expression, found a semicolon [227] */
3526
  fflush (0);
3527
  P_ioresult = 0;
3528
  }
3529
  }
3530
  return pp;
3531
  }
6785 bpr 3532
#endif
3533
 
14179 bpr 3534
static int matchpath_pos (int id, int *a_path)
6785 bpr 3535
{
3536
  int i;
3537
  int pp = 0;
3538
 
14179 bpr 3539
  for (i = max_matchpath_length; i >= 1; i--) {
3540
    if (a_path[i - 1] == id)
3541
            pp = i;
3542
  }
6785 bpr 3543
  return pp;
3544
}
3545
 
14179 bpr 3546
static int matchpath_length (int *a_path)
6785 bpr 3547
{
3548
  if (a_path[max_matchpath_length - 1] != 0)
3549
    return max_matchpath_length;
3550
  else
3551
    return (matchpath_pos (0L, a_path) - 1);
3552
}
3553
 
14179 bpr 3554
static int get_ndl_bond (int ba1, int ba2)
6785 bpr 3555
{
3556
  int i;
3557
  int b_id = 0;
3558
  int FORLIM;
3559
 
3560
  if (ndl_n_bonds <= 0)
3561
    return b_id;
3562
  FORLIM = ndl_n_bonds;
14179 bpr 3563
  for (i = 1; i <= FORLIM; i++) {
3564
    if ((ndl_bond[i - 1].a1 == ba1 && ndl_bond[i - 1].a2 == ba2) ||
3565
              (ndl_bond[i - 1].a1 == ba2 && ndl_bond[i - 1].a2 == ba1))
3566
          b_id = i;
3567
  }
6785 bpr 3568
  return b_id;
3569
}
3570
 
14179 bpr 3571
static int ringcompare (int *rp1, int *rp2)
6785 bpr 3572
{
3573
  int i, j;
3574
  int rc = 0;
3575
  int rs1, rs2;
3576
  int n_common = 0;
3577
  int max_cra;
3578
 
3579
  rs1 = path_length (rp1);
3580
  rs2 = path_length (rp2);
3581
  if (rs1 < rs2)
3582
    max_cra = rs1;
3583
  else
3584
    max_cra = rs2;
14179 bpr 3585
  for (i = 0; i < rs1; i++) {
3586
    for (j = 0; j < rs2; j++) {
3587
            if (rp1[i] == rp2[j])
3588
              n_common++;
3589
          }
3590
  }
3591
  if (rs1 == rs2 && n_common == max_cra) {
3592
    rc = 0;
3593
    return rc;
3594
  }
6785 bpr 3595
  if (n_common == 0)
3596
    rc += 8;
14179 bpr 3597
  if (n_common < max_cra) {
3598
    rc += 4;
3599
    return rc;
3600
  }
6785 bpr 3601
  if (rs1 < rs2)
3602
    rc++;
3603
  else
3604
    rc += 2;
3605
  return rc;
3606
}
3607
 
14179 bpr 3608
static boolean rc_identical (int rc_int)
6785 bpr 3609
{
3610
  if (rc_int == 0)
18544 georgesk 3611
    return istrue;
6785 bpr 3612
  else
18544 georgesk 3613
    return isfalse;
6785 bpr 3614
}
3615
 
14179 bpr 3616
static boolean rc_1in2 (int rc_int)
6785 bpr 3617
{
3618
  if (rc_int & 1)
18544 georgesk 3619
    return istrue;
6785 bpr 3620
  else
18544 georgesk 3621
    return isfalse;
6785 bpr 3622
}
3623
 
14179 bpr 3624
static boolean rc_2in1 (int rc_int)
6785 bpr 3625
{
3626
  rc_int /= 2;
3627
  if (rc_int & 1)
18544 georgesk 3628
    return istrue;
6785 bpr 3629
  else
18544 georgesk 3630
    return isfalse;
6785 bpr 3631
}
3632
 
3633
#if 0
14179 bpr 3634
static boolean rc_different (int rc_int)
6785 bpr 3635
{
3636
  rc_int /= 4;
3637
  if (rc_int & 1)
18544 georgesk 3638
    return istrue;
6785 bpr 3639
  else
18544 georgesk 3640
    return isfalse;
6785 bpr 3641
}
3642
#endif
3643
#if 0
14179 bpr 3644
static boolean rc_independent (int rc_int)
6785 bpr 3645
{
3646
  rc_int /= 8;
3647
  if (rc_int & 1)
18544 georgesk 3648
    return istrue;
6785 bpr 3649
  else
18544 georgesk 3650
    return isfalse;
6785 bpr 3651
}
3652
#endif
3653
 
14179 bpr 3654
static boolean is_newring (int *n_path)
6785 bpr 3655
{
3656
  int i, j;
18544 georgesk 3657
  boolean nr = istrue;
6785 bpr 3658
  boolean same_ring;
3659
  ringpath_type tmp_path;
3660
  int rc_result;
3661
  boolean found_ring;
3662
  int pl;                       /* new in v0.3 */
3663
  int FORLIM;
3664
 
3665
  pl = path_length (n_path);    /* new in v0.3 */
3666
  if (n_rings <= 0)
18544 georgesk 3667
    return istrue;
14179 bpr 3668
  switch (ringsearch_mode) {
6785 bpr 3669
    case rs_sar:
18544 georgesk 3670
      found_ring = isfalse;
6785 bpr 3671
      i = 0;
14179 bpr 3672
      while (i < n_rings && !found_ring) {
3673
              i++;
3674
              if (pl != ringprop[i - 1].size)   /* compare only rings of same size */
3675
                continue;
18544 georgesk 3676
              same_ring = istrue;
14179 bpr 3677
              for (j = 0; j < max_ringsize; j++) {
3678
                if (ring[i - 1][j] != n_path[j])
18544 georgesk 3679
                        same_ring = isfalse;
14179 bpr 3680
              }
3681
              if (same_ring) {
18544 georgesk 3682
                nr = isfalse;
3683
                found_ring = istrue;
14179 bpr 3684
              }
6785 bpr 3685
            }
3686
      break;
3687
 
3688
    case rs_ssr:
3689
      FORLIM = n_rings;
14179 bpr 3690
      for (i = 0; i < FORLIM; i++) {
3691
              for (j = 0; j < max_ringsize; j++)
3692
                tmp_path[j] = ring[i][j];
3693
              rc_result = ringcompare (n_path, tmp_path);
3694
              if (rc_identical (rc_result))
18544 georgesk 3695
                nr = isfalse;
14179 bpr 3696
              if (rc_1in2 (rc_result)) {
6785 bpr 3697
              /* exchange existing ring by smaller one */
14179 bpr 3698
                for (j = 0; j < max_ringsize; j++)
3699
                        ring[i][j] = n_path[j];
3700
                /* update ring property record (new in v0.3) */
3701
                ringprop[i].size = pl;
18544 georgesk 3702
                nr = isfalse;
14179 bpr 3703
        /* p2c: checkmol.pas, line 2841:
3704
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3705
              /*$IFDEF debug */
3706
              /* debugoutput('replacing ring '+inttostr(i)+' by smaller one (ringsize: '+inttostr(path_length(n_path))+')'); */
3707
              /*$ENDIF */
3708
        }
3709
        if (rc_2in1 (rc_result)) {
3710
                  /* new ring contains existing one, but is larger ==> discard */
18544 georgesk 3711
                nr = isfalse;
14179 bpr 3712
              }
6785 bpr 3713
            }
14179 bpr 3714
    break;
3715
  }
6785 bpr 3716
  return nr;
3717
}
3718
 
14179 bpr 3719
static void add_ring (int *n_path)
6785 bpr 3720
{
3721
  /* new in v0.3: store rings in an ordered way (with ascending ring size) */
3722
  int i;
3723
  int j = 0;
3724
  int k, s, pl;
14179 bpr 3725
  /* p2c: checkmol.pas, line 2862:
3726
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3727
  /*$IFDEF debug */
3728
  /*char dstr[256];*/
3729
  int FORLIM;
3730
 
3731
  /*$ENDIF */
3732
  pl = path_length (n_path);
3733
 
3734
  if (pl < 1)
3735
    return;
3736
 
14179 bpr 3737
  if (n_rings >= max_rings) {
3738
    /* p2c: checkmol.pas, line 2906:
3739
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3740
          /*$IFDEF debug
3741
             debugoutput ("max_rings exceeded!");
3742
             $ENDIF */
3743
    return;
3744
  }
6785 bpr 3745
  n_rings++;
3746
 
14179 bpr 3747
  /* p2c: checkmol.pas, line 2871:
3748
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3749
    /*$IFDEF debug */
3750
    /* dstr := '';
3751
       for j := 1 to pl do dstr := dstr + inttostr((n_path[j])) + ' ';
3752
       debugoutput('adding ring '+inttostr(n_rings)+':  '+dstr); */
3753
    /*$ENDIF */
3754
  if (n_rings > 1) {
3755
    FORLIM = n_rings;
3756
    for (i = 1; i < FORLIM; i++) {
3757
            s = ringprop[i - 1].size;
3758
            if (pl >= s)
3759
              j = i;
3760
          }
3761
  }
6785 bpr 3762
  j++;                          /* the next position is ours */
14179 bpr 3763
  if (j < n_rings) {                            /* push up the remaining rings by one position */
3764
    for (k = n_rings; k > j; k--) {
3765
            ringprop[k - 1].size = ringprop[k - 2].size;
3766
            /*ringprop^[k].arom := ringprop^[(k-1)].arom; */
3767
            for (i = 0; i < max_ringsize; i++)
3768
              ring[k - 1][i] = ring[k - 2][i];
3769
          }
3770
  }
6785 bpr 3771
  ringprop[j - 1].size = pl;
14179 bpr 3772
  for (i = 0; i < max_ringsize; i++) {
3773
    ring[j - 1][i] = n_path[i];
3774
    /*inc(atom^[(n_path[i])].ring_count); */
3775
  }
6785 bpr 3776
}
3777
 
3778
#if 0
14179 bpr 3779
static boolean is_ringpath (s_path) int *s_path;
3780
   {
3781
   boolean Result;
3782
   int i, j;
3783
   neighbor_rec nb;
18544 georgesk 3784
   boolean rp = isfalse;
14179 bpr 3785
   boolean new_atom;
3786
   int a_last, pl;
3787
   ringpath_type l_path;
3788
   int FORLIM;
6785 bpr 3789
 
14179 bpr 3790
   /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3791
   memset (nb, 0, sizeof (neighbor_rec));
3792
   memset (l_path, 0, sizeof (ringpath_type));
3793
   pl = path_length (s_path);
3794
   if (pl < 1) {
3795
   /* p2c: checkmol.pas, line 2928:
6785 bpr 3796
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14179 bpr 3797
     /*$IFDEF debug
6785 bpr 3798
     debugoutput ("Oops! Got zero-length s_path!");
3799
     $ENDIF */
3800
     return Result;
14179 bpr 3801
    }
3802
    for (i = 0; i < pl; i++)
3803
      l_path[i] = s_path[i];
3804
    /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
18544 georgesk 3805
    if (opt_metalrings == isfalse) {
14179 bpr 3806
      if (atom[l_path[pl - 1] - 1].metal){
3807
        /* p2c: checkmol.pas, line 2942:
3808
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3809
        /*$IFDEF debug
3810
        debugoutput ("skipping metal in ring search");
3811
         $ENDIF */
18544 georgesk 3812
        return isfalse;
14179 bpr 3813
      }
3814
    }
3815
    /* check if ring is already closed */
3816
    if (pl > 2 && l_path[pl - 1] == l_path[0]) {
3817
    l_path[pl - 1] = 0;        /* remove last entry (redundant!) */
3818
    order_ringpath (l_path);
3819
    if (is_newring (l_path)) {
3820
      if (n_rings >= max_rings) {
3821
        /* p2c: checkmol.pas, line 2958:
3822
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3823
        /*$IFDEF debug
3824
        debugoutput ("maximum number of rings exceeded!");
3825
        $ENDIF */
18544 georgesk 3826
        return isfalse;
14179 bpr 3827
      }
3828
      add_ring (l_path);
3829
    }
3830
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
18544 georgesk 3831
    return istrue;
14179 bpr 3832
  }
3833
  /* any other case: ring is not (yet) closed */
3834
  a_last = l_path[pl - 1];
3835
  get_neighbors (nb, a_last);
3836
  if (atom[a_last - 1].neighbor_count <= 1)
18544 georgesk 3837
    return isfalse;
14179 bpr 3838
  if (n_rings >= max_rings)
3839
    /* added in v0.2: check if max_rings is reached **/
3840
  {                          /* if ring is not closed, continue searching */
18544 georgesk 3841
    return isfalse;
14179 bpr 3842
  }
3843
  FORLIM = atom[a_last - 1].neighbor_count;
3844
  for (i = 0; i < FORLIM; i++) {
18544 georgesk 3845
    new_atom = istrue;
14179 bpr 3846
     for (j = 1; j < pl; j++) {
3847
      if (nb[i] == l_path[j]) {                    /* v0.3k */
18544 georgesk 3848
       new_atom = isfalse;
14179 bpr 3849
       /* p2c: checkmol.pas, line 2982:
3850
       * Warning: Expected a '(', found a semicolon [227] */
3851
       /* p2c: checkmol.pas, line 2982:
3852
       * Warning: Expected an expression, found a semicolon [227] */
3853
       fflush (0);
3854
       P_ioresult = 0;      /* v0.3k */
3855
      }
3856
    }
3857
    /* added in v0.1a: check if max_rings not yet reached */
3858
    /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
3859
    if (new_atom && pl < max_vringsize && n_rings < max_rings) {
3860
      l_path[pl] = nb[i];
3861
      if (pl < max_ringsize - 1)   /* just to be sure */
3862
      l_path[pl + 1] = 0;
3863
      if (is_ringpath (l_path))
18544 georgesk 3864
       rp = istrue;
14179 bpr 3865
    }
3866
  }
3867
  return rp;
3868
}
6785 bpr 3869
#endif
3870
 
14179 bpr 3871
static boolean is_ringpath (int *s_path)
6785 bpr 3872
{
3873
  int i, j;
3874
  neighbor_rec nb;
18544 georgesk 3875
  boolean rp = isfalse;
6785 bpr 3876
  boolean new_atom;
3877
  int a_last, pl;
3878
  ringpath_type l_path;
3879
  int FORLIM, pl_prev, pl_next, max_ringsize_dec;
3880
 
3881
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3882
  memset ((void *) nb, 0, sizeof (neighbor_rec));
3883
  memset ((void *) l_path, 0, sizeof (ringpath_type));
3884
  pl = path_length (s_path);
14179 bpr 3885
  if (pl < 1) {
3886
    /* p2c: checkmol.pas, line 2524:
3887
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3888
 
18544 georgesk 3889
      return isfalse;
6785 bpr 3890
    }
3891
 
3892
  pl_prev = pl - 1;
3893
  //memcpy (l_path, s_path, sizeof (ringpath_type));
3894
  memcpy (l_path, s_path, pl * sizeof (int));
3895
 
3896
  /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
18544 georgesk 3897
  if (opt_metalrings == isfalse) {
14179 bpr 3898
    if (atom[l_path[pl_prev] - 1].metal) {
3899
    /* p2c: checkmol.pas, line 2538:
3900
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
18544 georgesk 3901
          return isfalse;
14179 bpr 3902
          }
3903
  }
6785 bpr 3904
  /* check if ring is already closed */
14179 bpr 3905
  if (pl > 2 && l_path[pl_prev] == l_path[0]) {
3906
    l_path[pl_prev] = 0;        /* remove last entry (redundant!) */
3907
    order_ringpath (l_path);
3908
    if (is_newring (l_path)) {
3909
            if (n_rings >= max_rings) {
3910
        /* p2c: checkmol.pas, line 2554:
3911
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
18544 georgesk 3912
              return isfalse;
6785 bpr 3913
            }
14179 bpr 3914
            add_ring (l_path);
3915
          }
3916
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
18544 georgesk 3917
      return istrue;
14179 bpr 3918
  }
6785 bpr 3919
  /* any other case: ring is not (yet) closed */
3920
  a_last = l_path[pl_prev];
3921
  get_neighbors (nb, a_last);
3922
  if (atom[a_last - 1].neighbor_count <= 1)
18544 georgesk 3923
    return isfalse;
6785 bpr 3924
  if (n_rings >= max_rings)
14179 bpr 3925
    /* added in v0.2: check if max_rings is reached */ {                                /* if ring is not closed, continue searching */
18544 georgesk 3926
    return isfalse;
14179 bpr 3927
  }
6785 bpr 3928
  FORLIM = atom[a_last - 1].neighbor_count;
3929
  pl_next = pl + 1;
3930
  max_ringsize_dec = max_ringsize - 1;
14179 bpr 3931
  for (i = 0; i < FORLIM; i++) {
18544 georgesk 3932
    new_atom = istrue;
14179 bpr 3933
    for (j = 1; j < pl; j++) {
3934
            if (nb[i] == l_path[j]) {
18544 georgesk 3935
              new_atom = isfalse;
6785 bpr 3936
              break;
3937
            }
14179 bpr 3938
          }
3939
    /* added in v0.1a: check if max_rings not yet reached */
3940
    /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
3941
    if (new_atom && pl < max_vringsize && n_rings < max_rings) {
3942
            l_path[pl] = nb[i];
3943
            if (pl < max_ringsize_dec)  /* just to be sure */
3944
              l_path[pl_next] = 0;
6785 bpr 3945
 
14179 bpr 3946
            if (max_ringpath_recursion_depth != 0
3947
                && ++recursion_depth > max_ringpath_recursion_depth) {
6785 bpr 3948
#ifndef MAKE_SHARED_LIBRARY
3949
              if (opt_verbose)
3950
#endif
14179 bpr 3951
                    printf ("Warning: max. number of ringpath recursions (%i) reached\n",
3952
                    max_ringpath_recursion_depth);
6785 bpr 3953
              n_rings = max_rings;
18544 georgesk 3954
              return isfalse;
6785 bpr 3955
            }
3956
 
14179 bpr 3957
            /*printf("%i\n",recursion_depth);
3958
            fflush(stdout);*/
6785 bpr 3959
 
14179 bpr 3960
            if (is_ringpath (l_path))
18544 georgesk 3961
              rp = istrue;
3962
            /*return istrue;*/
14179 bpr 3963
          }
3964
  }
6785 bpr 3965
  return rp;
3966
}
3967
 
14179 bpr 3968
static boolean is_ringbond (int b_id)
6785 bpr 3969
{
3970
  int i, ra1, ra2;
3971
  neighbor_rec nb;
3972
  ringpath_type search_path;
18544 georgesk 3973
  boolean rb = isfalse;
6785 bpr 3974
  int FORLIM;
3975
 
3976
  recursion_depth = 0;
3977
 
3978
  ra1 = bond[b_id - 1].a1;
3979
  ra2 = bond[b_id - 1].a2;
3980
  memset (nb, 0, sizeof (neighbor_rec));
3981
  memset (search_path, 0, sizeof (ringpath_type));
3982
  get_neighbors (nb, ra2);
3983
  if (atom[ra2 - 1].neighbor_count <= 1 || atom[ra1 - 1].neighbor_count <= 1)
18544 georgesk 3984
    return isfalse;
6785 bpr 3985
  search_path[0] = ra1;
3986
  search_path[1] = ra2;
3987
  FORLIM = atom[ra2 - 1].neighbor_count;
14179 bpr 3988
  for (i = 0; i < FORLIM; i++) {
3989
    if (nb[i] != ra1 && atom[nb[i] - 1].heavy) {
3990
            search_path[2] = nb[i];
3991
            if (is_ringpath (search_path))
18544 georgesk 3992
              rb = istrue;
3993
            //return istrue;
14179 bpr 3994
          }
3995
  }
6785 bpr 3996
  return rb;
3997
}
3998
 
14179 bpr 3999
static void chk_ringbonds ()
6785 bpr 4000
{
4001
  int i, a1rc, a2rc;
4002
 
4003
  if (n_bonds < 1)
4004
    return;
4005
 
14179 bpr 4006
  for (i = 0; i < n_bonds; i++) {
4007
    a1rc = atom[bond[i].a1 - 1].ring_count;
4008
    a2rc = atom[bond[i].a2 - 1].ring_count;
4009
    if (n_rings == 0 || (a1rc < n_rings && a2rc < n_rings)) {
4010
            is_ringbond (i + 1);
6785 bpr 4011
          /*inc(bond^[i].ring_count); */
14179 bpr 4012
          }
4013
  }
6785 bpr 4014
}
4015
 
4016
/* v0.3d: moved procedure update_ringcount a bit down */
4017
 
14179 bpr 4018
static int raw_hetbond_count (int a)
6785 bpr 4019
{
4020
  /* new in v0.2j, ignores bond order */
4021
  int i;
4022
  neighbor_rec nb;
4023
  str2 nb_el;
4024
  int hbc = 0;
4025
  int FORLIM;
4026
 
4027
  if (a <= 0 || a > n_atoms)
4028
    return hbc;
4029
  memset (nb, 0, sizeof (neighbor_rec));
4030
  get_neighbors (nb, a);
4031
  if (atom[a - 1].neighbor_count <= 0)
4032
    return hbc;
4033
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4034
  for (i = 0; i < FORLIM; i++) {
4035
    strcpy (nb_el, atom[nb[i] - 1].element);
4036
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /* &&  strcmp (nb_el, "D ") */
4037
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4038
            /* added 'D ' in v0.3n */
4039
          hbc++;
4040
  }
6785 bpr 4041
  return hbc;
4042
}
4043
 
14179 bpr 4044
static int hetbond_count (int a)
6785 bpr 4045
{
4046
  int i;
4047
  neighbor_rec nb;
4048
  str2 nb_el;
4049
  float hbc = 0.0;
4050
  int FORLIM;
4051
 
4052
  if (a <= 0 || a > n_atoms)
4053
    return ((int) floor (hbc + 0.5));
4054
  memset (nb, 0, sizeof (neighbor_rec));
4055
  get_neighbors (nb, a);
4056
  if (atom[a - 1].neighbor_count <= 0)
4057
    return ((int) floor (hbc + 0.5));
4058
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4059
  for (i = 0; i < FORLIM; i++) {
4060
    strcpy (nb_el, atom[nb[i] - 1].element);
4061
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /*&& strcmp (nb_el, "D ") */
4062
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU")) {                        /* added 'D ' in v0.3n */
4063
            if (bond[get_bond (a, nb[i]) - 1].btype == 'S')
4064
              hbc += 1.0;
4065
            if (bond[get_bond (a, nb[i]) - 1].btype == 'A')
4066
              hbc += 1.5;
4067
            if (bond[get_bond (a, nb[i]) - 1].btype == 'D')
4068
              hbc += 2.0;
4069
            if (bond[get_bond (a, nb[i]) - 1].btype == 'T')
4070
              hbc += 3.0;
4071
          }
4072
  }
6785 bpr 4073
  return ((int) floor (hbc + 0.5));
4074
}
4075
 
14179 bpr 4076
static int hetatom_count (int a)
6785 bpr 4077
{
4078
  int i;
4079
  neighbor_rec nb;
4080
  str2 nb_el;
4081
  int hac = 0;
4082
  int FORLIM;
4083
 
4084
  if (a <= 0 || a > n_atoms)
4085
    return hac;
4086
  memset (nb, 0, sizeof (neighbor_rec));
4087
  get_neighbors (nb, a);
4088
  if (atom[a - 1].neighbor_count <= 0)
4089
    return hac;
4090
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4091
  for (i = 0; i < FORLIM; i++) {
4092
    strcpy (nb_el, atom[nb[i] - 1].element);
4093
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4094
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4095
              && strcmp (nb_el, "DU"))
4096
            /* added 'D ' in v0.3n */
4097
            hac++;
4098
  }
6785 bpr 4099
  return hac;
4100
}
4101
 
4102
#if 0
14179 bpr 4103
static int ndl_hetbond_count (int a)
6785 bpr 4104
{
4105
  int i;
4106
  neighbor_rec nb;
4107
  str2 nb_el;
4108
  float hbc = 0.0;
4109
  int FORLIM;
4110
 
4111
  if (a <= 0 || a > n_atoms)
4112
    return ((int) floor (hbc + 0.5));
4113
  memset (nb, 0, sizeof (neighbor_rec));
4114
  get_ndl_neighbors (nb, a);
4115
  if (ndl_atom[a - 1].neighbor_count <= 0)
4116
    return ((int) floor (hbc + 0.5));
4117
  FORLIM = ndl_atom[a - 1].neighbor_count;
14179 bpr 4118
  for (i = 0; i < FORLIM; i++) {
4119
    strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4120
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4121
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4122
              && strcmp (nb_el, "DU")) {                        /* added 'D ' in v0.3n */
4123
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'S')
4124
              hbc += 1.0;
4125
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'A')
4126
              hbc += 1.5;
4127
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'D')
4128
              hbc += 2.0;
4129
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'T')
4130
              hbc += 3.0;
4131
          }
4132
  }
6785 bpr 4133
  return ((int) floor (hbc + 0.5));
4134
}
4135
#endif
4136
 
14179 bpr 4137
static int ndl_hetatom_count (int a)
6785 bpr 4138
{
4139
  int i;
4140
  neighbor_rec nb;
4141
  str2 nb_el;
4142
  int hac = 0;
4143
  int FORLIM;
4144
 
4145
  if (a <= 0 || a > ndl_n_atoms)
4146
    return hac;
4147
  memset (nb, 0, sizeof (neighbor_rec));
4148
  get_ndl_neighbors (nb, a);
4149
  if (ndl_atom[a - 1].neighbor_count <= 0)
4150
    return hac;
4151
  FORLIM = ndl_atom[a - 1].neighbor_count;
14179 bpr 4152
  for (i = 0; i < FORLIM; i++) {                                /* note: query atoms like 'A' should be present only in the needle */
4153
    strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4154
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /*&&  strcmp (nb_el, "D ") */
4155
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4156
            /* added 'D ' in v0.3n */
4157
          hac++;
4158
  }
6785 bpr 4159
  return hac;
4160
}
4161
 
14179 bpr 4162
static boolean is_oxo_C (int id)
6785 bpr 4163
{
4164
  int i;
18544 georgesk 4165
  boolean r = isfalse;
6785 bpr 4166
  neighbor_rec nb;
4167
  int FORLIM;
4168
 
4169
  memset (nb, 0, sizeof (neighbor_rec));
4170
  if (id < 1 || id > n_atoms)
18544 georgesk 4171
    return isfalse;
6785 bpr 4172
  get_neighbors (nb, id);
4173
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 4174
    return isfalse;
6785 bpr 4175
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4176
  for (i = 0; i < FORLIM; i++) {
4177
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4178
              !strcmp (atom[nb[i] - 1].element, "O "))
4179
            /* no N, amidines are different... */
18544 georgesk 4180
            r = istrue;
6785 bpr 4181
      /* or
4182
         (atom^[(nb[i])].element = 'S ')  or
4183
         (atom^[(nb[i])].element = 'SE') */
14179 bpr 4184
  }
6785 bpr 4185
  return r;
4186
}
4187
 
14179 bpr 4188
static boolean is_thioxo_C (int id)
6785 bpr 4189
{
4190
  int i;
18544 georgesk 4191
  boolean r = isfalse;
6785 bpr 4192
  neighbor_rec nb;
4193
  int FORLIM;
4194
 
4195
  memset (nb, 0, sizeof (neighbor_rec));
4196
  if (id < 1 || id > n_atoms)
18544 georgesk 4197
    return isfalse;
6785 bpr 4198
  get_neighbors (nb, id);
4199
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 4200
    return isfalse;
6785 bpr 4201
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4202
  for (i = 0; i < FORLIM; i++) {
4203
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4204
              (!strcmp (atom[nb[i] - 1].element, "S ") ||
4205
              !strcmp (atom[nb[i] - 1].element, "SE")))
4206
            /* no N, amidines are different... */
18544 georgesk 4207
          r = istrue;
14179 bpr 4208
  }
6785 bpr 4209
  return r;
4210
}
4211
 
14179 bpr 4212
static boolean is_imino_C (int id)
6785 bpr 4213
{
4214
  int i;
18544 georgesk 4215
  boolean r = isfalse;
6785 bpr 4216
  neighbor_rec nb;
4217
  int FORLIM;
4218
 
4219
  memset (nb, 0, sizeof (neighbor_rec));
4220
  if (id < 1 || id > n_atoms)
18544 georgesk 4221
    return isfalse;
6785 bpr 4222
  get_neighbors (nb, id);
4223
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 4224
    return isfalse;
6785 bpr 4225
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4226
  for (i = 0; i < FORLIM; i++) {
4227
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4228
              !strcmp (atom[nb[i] - 1].element, "N "))
18544 georgesk 4229
            r = istrue;
14179 bpr 4230
  }
6785 bpr 4231
  return r;
4232
}
4233
 
18544 georgesk 4234
static boolean is_istrue_imino_C (int id)
6785 bpr 4235
{
4236
  int i;
18544 georgesk 4237
  boolean r = istrue;
6785 bpr 4238
  neighbor_rec nb;
4239
  str2 nb_el;
4240
  int a_n = 0;
4241
  int b;                        /* v0.3j */
4242
  int FORLIM;
4243
 
4244
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4245
  memset (nb, 0, sizeof (neighbor_rec));
4246
  if (id < 1 || id > n_atoms)
18544 georgesk 4247
    return isfalse;
6785 bpr 4248
  get_neighbors (nb, id);
4249
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 4250
    return isfalse;
6785 bpr 4251
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4252
  for (i = 0; i < FORLIM; i++) {
4253
    b = get_bond (id, nb[i]);   /* v0.3j */
18544 georgesk 4254
    if (bond[b - 1].btype == 'D' && bond[b - 1].arom == isfalse &&
14179 bpr 4255
              !strcmp (atom[nb[i] - 1].element, "N "))
6785 bpr 4256
        /* v0.3j */
14179 bpr 4257
            a_n = nb[i];
4258
  }
6785 bpr 4259
  if (a_n <= 0)
18544 georgesk 4260
    return isfalse;
6785 bpr 4261
  memset (nb, 0, sizeof (neighbor_rec));
4262
  get_neighbors (nb, a_n);
4263
  FORLIM = atom[a_n - 1].neighbor_count;
14179 bpr 4264
  for (i = 0; i < FORLIM; i++) {
4265
    strcpy (nb_el, atom[nb[i] - 1].element);
4266
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4267
            /*&&  strcmp (nb_el, "D ") */ )
4268
            /* v0.3n: D */
18544 georgesk 4269
            r = isfalse;
14179 bpr 4270
  }
6785 bpr 4271
  return r;
4272
}
4273
 
18544 georgesk 4274
static boolean is_istrue_exocyclic_imino_C (int id, int r_id)
6785 bpr 4275
{
4276
  /* v0.3j */
4277
  int i, j;
18544 georgesk 4278
  boolean r = isfalse;
6785 bpr 4279
  neighbor_rec nb;
4280
  ringpath_type testring;
4281
  int ring_size, b, FORLIM;
4282
 
4283
  memset (nb, 0, sizeof (neighbor_rec));
4284
  if (id < 1 || id > n_atoms)
18544 georgesk 4285
    return isfalse;
6785 bpr 4286
  get_neighbors (nb, id);
4287
  memset (testring, 0, sizeof (ringpath_type));
4288
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4289
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4290
    testring[j] = ring[r_id - 1][j];
4291
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 4292
    return isfalse;
6785 bpr 4293
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4294
  for (i = 0; i < FORLIM; i++) {
4295
    b = get_bond (id, nb[i]);
18544 georgesk 4296
    if (bond[b - 1].btype == 'D' && bond[b - 1].arom == isfalse &&
14179 bpr 4297
              !strcmp (atom[nb[i] - 1].element, "N ")) {
18544 georgesk 4298
            r = istrue;
14179 bpr 4299
            for (j = 0; j < ring_size; j++) {
6785 bpr 4300
              if (nb[i] == ring[r_id - 1][j])
18544 georgesk 4301
                      r = isfalse;
6785 bpr 4302
            }
14179 bpr 4303
          }
4304
  }
6785 bpr 4305
  return r;
4306
}
4307
 
14179 bpr 4308
static boolean is_exocyclic_imino_C (int id, int r_id)
6785 bpr 4309
{
4310
  int i, j;
18544 georgesk 4311
  boolean r = isfalse;
6785 bpr 4312
  neighbor_rec nb;
4313
  ringpath_type testring;
4314
  int ring_size, FORLIM;
4315
 
4316
  memset (nb, 0, sizeof (neighbor_rec));
4317
  if (id < 1 || id > n_atoms)
18544 georgesk 4318
    return isfalse;
6785 bpr 4319
  get_neighbors (nb, id);
4320
  memset (testring, 0, sizeof (ringpath_type));
4321
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4322
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4323
    testring[j] = ring[r_id - 1][j];
4324
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 4325
    return isfalse;
6785 bpr 4326
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4327
  for (i = 0; i < FORLIM; i++) {
4328
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4329
              !strcmp (atom[nb[i] - 1].element, "N ")) {
18544 georgesk 4330
            r = istrue;
14179 bpr 4331
            for (j = 0; j < ring_size; j++) {
6785 bpr 4332
              if (nb[i] == ring[r_id - 1][j])
18544 georgesk 4333
                      r = isfalse;
6785 bpr 4334
            }
14179 bpr 4335
          }
4336
  }
6785 bpr 4337
  return r;
4338
}
4339
 
14179 bpr 4340
static int find_exocyclic_methylene_C (int id, int r_id)
6785 bpr 4341
{
4342
  /* renamed and rewritten in v0.3j */
4343
  int i, j;
4344
  int r = 0;
4345
  neighbor_rec nb;
4346
  ringpath_type testring;
4347
  int ring_size, FORLIM;
4348
 
4349
  memset (nb, 0, sizeof (neighbor_rec));
4350
  if (id < 1 || id > n_atoms)
4351
    return 0;
4352
  get_neighbors (nb, id);
4353
  memset (testring, 0, sizeof (ringpath_type));
4354
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4355
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4356
    testring[j] = ring[r_id - 1][j];
4357
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4358
    return r;
4359
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4360
  for (i = 0; i < FORLIM; i++) {
4361
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4362
              !strcmp (atom[nb[i] - 1].element, "C ")) {
4363
            r = nb[i];
4364
            for (j = 0; j < ring_size; j++) {
6785 bpr 4365
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4366
                    r = 0;
6785 bpr 4367
            }
14179 bpr 4368
          }
4369
  }
6785 bpr 4370
  return r;
4371
}
4372
 
14179 bpr 4373
static boolean is_hydroxy (int a_view, int a_ref)
6785 bpr 4374
{
18544 georgesk 4375
  boolean r = isfalse;
6785 bpr 4376
 
14179 bpr 4377
  if (atom[a_view - 1]. heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4378
    if (!strcmp (atom[a_ref - 1].atype, "O3 ") &&
4379
              atom[a_ref - 1].neighbor_count == 1)
18544 georgesk 4380
            r = istrue;
14179 bpr 4381
  }
6785 bpr 4382
  return r;
4383
}
4384
 
14179 bpr 4385
static boolean is_sulfanyl (int a_view, int a_ref)
6785 bpr 4386
{
18544 georgesk 4387
  boolean r = isfalse;
6785 bpr 4388
 
4389
  if (atom[a_view - 1].
14179 bpr 4390
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4391
    if (!strcmp (atom[a_ref - 1].atype, "S3 ") &&
4392
              atom[a_ref - 1].neighbor_count == 1)
18544 georgesk 4393
            r = istrue;
14179 bpr 4394
  }
6785 bpr 4395
  return r;
4396
}
4397
 
14179 bpr 4398
static boolean is_amino (int a_view, int a_ref)
6785 bpr 4399
{
18544 georgesk 4400
  boolean r = isfalse;
6785 bpr 4401
 
4402
  if (atom[a_view - 1].
14179 bpr 4403
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4404
    if ((!strcmp (atom[a_ref - 1].atype, "N3 ") ||
4405
              !strcmp (atom[a_ref - 1].atype, "N3+")) &&
4406
              atom[a_ref - 1].neighbor_count == 1)
18544 georgesk 4407
            r = istrue;
6785 bpr 4408
    }
4409
  return r;
4410
}
4411
 
14179 bpr 4412
static boolean is_alkyl (int a_view, int a_ref)
6785 bpr 4413
{
4414
  int i;
18544 georgesk 4415
  boolean r = isfalse;
6785 bpr 4416
  neighbor_rec nb;
4417
  str2 nb_el;
4418
  int het_count = 0;
4419
  int FORLIM;
4420
 
4421
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4422
  if (! (atom[a_view - 1].
4423
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
6785 bpr 4424
      || strcmp (atom[a_ref - 1].atype, "C3 ")
18544 georgesk 4425
      || atom[a_ref - 1].arom != isfalse)
4426
    return isfalse;
6785 bpr 4427
  get_nextneighbors (nb, a_ref, a_view);
4428
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4429
  for (i = 0; i <= FORLIM; i++) {
4430
    strcpy (nb_el, atom[nb[i] - 1].element);
4431
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4432
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4433
              && strcmp (nb_el, "LP"))
4434
            /* added 'D ' in v0.3n */
4435
            het_count++;
4436
  }
6785 bpr 4437
  if (het_count <= 1)           /* we consider (e.g.) alkoxyalkyl groups as alkyl */
18544 georgesk 4438
    r = istrue;
6785 bpr 4439
  return r;
4440
}
4441
 
18544 georgesk 4442
static boolean is_istrue_alkyl (int a_view, int a_ref)
6785 bpr 4443
{
4444
  int i;
18544 georgesk 4445
  boolean r = isfalse;
6785 bpr 4446
  neighbor_rec nb;
4447
  str2 nb_el;
4448
  int het_count = 0;
4449
  int FORLIM;
4450
 
4451
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4452
  if (!(atom[a_view - 1].
6785 bpr 4453
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4454
      || strcmp (atom[a_ref - 1].atype, "C3 ")
18544 georgesk 4455
      || atom[a_ref - 1].arom != isfalse)
4456
    return isfalse;
6785 bpr 4457
  get_nextneighbors (nb, a_ref, a_view);
4458
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4459
  for (i = 0; i <= FORLIM; i++) {
4460
    strcpy (nb_el, atom[nb[i] - 1].element);
4461
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4462
             /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
4463
             /* added 'D ' in v0.3n */
4464
             het_count++;
4465
  }
6785 bpr 4466
  if (het_count == 0)           /* */
18544 georgesk 4467
    r = istrue;
6785 bpr 4468
  return r;
4469
}
4470
 
14179 bpr 4471
static boolean is_alkenyl (int a_view, int a_ref)
6785 bpr 4472
{
4473
  /* new in v0.3j */
4474
  int i;
18544 georgesk 4475
  boolean r = isfalse;
6785 bpr 4476
  neighbor_rec nb;
4477
  str2 nb_el;
4478
  str3 nb_at;
4479
  int c2_count = 0, het_count = 0;
4480
  int FORLIM;
4481
 
4482
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4483
  if (! (atom[a_view - 1].
6785 bpr 4484
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4485
      || strcmp (atom[a_ref - 1].atype, "C2 ")
18544 georgesk 4486
      || atom[a_ref - 1].arom != isfalse) {
4487
    return isfalse;
14179 bpr 4488
  }                             /* v0.3k: changed c2_count = 1 into c2_count >= 1 */
6785 bpr 4489
  get_nextneighbors (nb, a_ref, a_view);
4490
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4491
  for (i = 0; i <= FORLIM; i++) {
4492
    strcpy (nb_el, atom[nb[i] - 1].element);
4493
    strcpy (nb_at, atom[nb[i] - 1].atype);
4494
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4495
            /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4496
             && strcmp (nb_el, "LP"))
4497
            /* added 'D ' in v0.3n */
4498
            het_count++;
4499
    if (!strcmp (nb_at, "C2 "))
4500
            c2_count++;
4501
  }
6785 bpr 4502
  if (c2_count >= 1 && het_count <= 1)
4503
    /* we consider (e.g.) alkoxyalkenyl groups as alkenyl */
18544 georgesk 4504
    r = istrue;
6785 bpr 4505
  return r;
4506
}
4507
 
14179 bpr 4508
static boolean is_alkynyl (int a_view, int a_ref)
6785 bpr 4509
{
4510
  /* new in v0.3j */
4511
  int i;
18544 georgesk 4512
  boolean r = isfalse;
6785 bpr 4513
  neighbor_rec nb;
4514
  str3 nb_at;
4515
  int c1_count = 0;
4516
  int FORLIM;
4517
 
4518
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4519
  if (!(atom[a_view - 1].
6785 bpr 4520
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4521
      || strcmp (atom[a_ref - 1].atype, "C1 ")
18544 georgesk 4522
      || atom[a_ref - 1].arom != isfalse)
4523
    return isfalse;
6785 bpr 4524
  get_nextneighbors (nb, a_ref, a_view);
4525
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4526
  for (i = 0; i <= FORLIM; i++) {
4527
    strcpy (nb_at, atom[nb[i] - 1].atype);
4528
    if (!strcmp (nb_at, "C1 "))
4529
            c1_count++;
4530
  }
6785 bpr 4531
  if (c1_count == 1)
18544 georgesk 4532
    r = istrue;
6785 bpr 4533
  return r;
4534
}
4535
 
14179 bpr 4536
static boolean is_aryl (int a_view, int a_ref)
6785 bpr 4537
{
18544 georgesk 4538
  boolean r = isfalse;
6785 bpr 4539
 
4540
  if ((atom[a_view - 1].
4541
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4542
      && !strcmp (atom[a_ref - 1].element, "C ")
18544 georgesk 4543
      && atom[a_ref - 1].arom == istrue)
4544
    r = istrue;
6785 bpr 4545
  return r;
4546
}
4547
 
14179 bpr 4548
static boolean is_alkoxy (int a_view, int a_ref)
6785 bpr 4549
{
18544 georgesk 4550
  boolean r = isfalse;
6785 bpr 4551
  neighbor_rec nb;
4552
 
4553
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4554
  if (!(atom[a_view - 1].
6785 bpr 4555
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4556
    return isfalse;
6785 bpr 4557
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4558
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4559
    return isfalse;
6785 bpr 4560
  get_nextneighbors (nb, a_ref, a_view);
4561
  if (is_alkyl (a_ref, nb[0]))
18544 georgesk 4562
    r = istrue;
6785 bpr 4563
  return r;
4564
}
4565
 
14179 bpr 4566
static boolean is_siloxy (int a_view, int a_ref)
6785 bpr 4567
{
18544 georgesk 4568
  boolean r = isfalse;
6785 bpr 4569
  neighbor_rec nb;
4570
 
4571
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4572
  if (!(atom[a_view - 1].
6785 bpr 4573
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4574
    return isfalse;
6785 bpr 4575
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4576
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4577
    return isfalse;
6785 bpr 4578
  get_nextneighbors (nb, a_ref, a_view);
4579
  if (!strcmp (atom[nb[0] - 1].element, "SI"))
18544 georgesk 4580
    r = istrue;
6785 bpr 4581
  return r;
4582
}
4583
 
18544 georgesk 4584
static boolean is_istrue_alkoxy (int a_view, int a_ref)
6785 bpr 4585
{
18544 georgesk 4586
  boolean r = isfalse;
6785 bpr 4587
  neighbor_rec nb;
4588
 
4589
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4590
  if (!(atom[a_view - 1].
6785 bpr 4591
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4592
    return isfalse;
6785 bpr 4593
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4594
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4595
    return isfalse;
6785 bpr 4596
  get_nextneighbors (nb, a_ref, a_view);
18544 georgesk 4597
  if (is_istrue_alkyl (a_ref, nb[0]))
4598
    r = istrue;
6785 bpr 4599
  return r;
4600
}
4601
 
14179 bpr 4602
static boolean is_aryloxy (int a_view, int a_ref)
6785 bpr 4603
{
18544 georgesk 4604
  boolean r = isfalse;
6785 bpr 4605
  neighbor_rec nb;
4606
 
4607
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4608
  if (!(atom[a_view - 1].
6785 bpr 4609
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4610
    return isfalse;
6785 bpr 4611
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4612
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4613
    return isfalse;
6785 bpr 4614
  get_nextneighbors (nb, a_ref, a_view);
4615
  if (is_aryl (a_ref, nb[0]))
18544 georgesk 4616
    r = istrue;
6785 bpr 4617
  return r;
4618
}
4619
 
14179 bpr 4620
static boolean is_alkenyloxy (int a_view, int a_ref) {
6785 bpr 4621
  /* v0.3j */
18544 georgesk 4622
  boolean r = isfalse;
6785 bpr 4623
  neighbor_rec nb;
4624
 
4625
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4626
  if (!(atom[a_view - 1].
6785 bpr 4627
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4628
    return isfalse;
6785 bpr 4629
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4630
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4631
    return isfalse;
6785 bpr 4632
  get_nextneighbors (nb, a_ref, a_view);
4633
  if (is_alkenyl (a_ref, nb[0]))
18544 georgesk 4634
    r = istrue;
6785 bpr 4635
  return r;
4636
}
4637
 
14179 bpr 4638
static boolean is_alkynyloxy (int a_view, int a_ref)
6785 bpr 4639
{
4640
  /* v0.3j */
18544 georgesk 4641
  boolean r = isfalse;
6785 bpr 4642
  neighbor_rec nb;
4643
 
4644
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4645
  if (!(atom[a_view - 1].
6785 bpr 4646
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4647
    return isfalse;
6785 bpr 4648
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4649
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4650
    return isfalse;
6785 bpr 4651
  get_nextneighbors (nb, a_ref, a_view);
4652
  if (is_alkynyl (a_ref, nb[0]))
18544 georgesk 4653
    r = istrue;
6785 bpr 4654
  return r;
4655
}
4656
 
14179 bpr 4657
static boolean is_alkylsulfanyl (int a_view, int a_ref)
6785 bpr 4658
{
18544 georgesk 4659
  boolean r = isfalse;
6785 bpr 4660
  neighbor_rec nb;
4661
 
4662
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4663
  if (!(atom[a_view - 1].
6785 bpr 4664
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4665
    return isfalse;
6785 bpr 4666
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4667
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4668
    return isfalse;
6785 bpr 4669
  get_nextneighbors (nb, a_ref, a_view);
4670
  if (is_alkyl (a_ref, nb[0]))
18544 georgesk 4671
    r = istrue;
6785 bpr 4672
  return r;
4673
}
4674
 
18544 georgesk 4675
static boolean is_istrue_alkylsulfanyl (int a_view, int a_ref)
6785 bpr 4676
{
18544 georgesk 4677
  boolean r = isfalse;
6785 bpr 4678
  neighbor_rec nb;
4679
 
4680
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4681
  if (!(atom[a_view - 1].
6785 bpr 4682
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4683
    return isfalse;
6785 bpr 4684
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4685
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4686
    return isfalse;
6785 bpr 4687
  get_nextneighbors (nb, a_ref, a_view);
18544 georgesk 4688
  if (is_istrue_alkyl (a_ref, nb[0]))
4689
    r = istrue;
6785 bpr 4690
  return r;
4691
}
4692
 
14179 bpr 4693
static boolean is_arylsulfanyl (int a_view, int a_ref)
6785 bpr 4694
{
18544 georgesk 4695
  boolean r = isfalse;
6785 bpr 4696
  neighbor_rec nb;
4697
 
4698
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4699
  if (!(atom[a_view - 1].
6785 bpr 4700
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4701
    return isfalse;
6785 bpr 4702
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4703
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4704
    return isfalse;
6785 bpr 4705
  get_nextneighbors (nb, a_ref, a_view);
4706
  if (is_aryl (a_ref, nb[0]))
18544 georgesk 4707
    r = istrue;
6785 bpr 4708
  return r;
4709
}
4710
 
17891 bpr 4711
static boolean is_alkenylsulfanyl (int a_view, int a_ref)
6785 bpr 4712
{
4713
  /* v0.3j */
18544 georgesk 4714
  boolean r = isfalse;
6785 bpr 4715
  neighbor_rec nb;
4716
 
4717
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4718
  if (!(atom[a_view - 1].
6785 bpr 4719
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4720
    return isfalse;
6785 bpr 4721
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4722
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4723
    return isfalse;
6785 bpr 4724
  get_nextneighbors (nb, a_ref, a_view);
4725
  if (is_alkenyl (a_ref, nb[0]))
18544 georgesk 4726
    r = istrue;
6785 bpr 4727
  return r;
4728
}
4729
 
17891 bpr 4730
static boolean is_alkynylsulfanyl (int a_view, int a_ref)
6785 bpr 4731
{
4732
  /* v0.3j */
18544 georgesk 4733
  boolean r = isfalse;
6785 bpr 4734
  neighbor_rec nb;
4735
 
4736
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4737
  if (!(atom[a_view - 1].
6785 bpr 4738
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4739
    return isfalse;
6785 bpr 4740
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4741
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4742
    return isfalse;
6785 bpr 4743
  get_nextneighbors (nb, a_ref, a_view);
4744
  if (is_alkynyl (a_ref, nb[0]))
18544 georgesk 4745
    r = istrue;
6785 bpr 4746
  return r;
4747
}
4748
 
17891 bpr 4749
static boolean is_alkylamino (int a_view, int a_ref)
6785 bpr 4750
{
18544 georgesk 4751
  boolean r = isfalse;
6785 bpr 4752
  neighbor_rec nb;
4753
  int alkyl_count = 0;
4754
 
4755
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4756
  if (!(atom[a_view - 1].
6785 bpr 4757
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4758
    return isfalse;
6785 bpr 4759
  if (strcmp (atom[a_ref - 1].element, "N ")
4760
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4761
    return isfalse;
6785 bpr 4762
  get_nextneighbors (nb, a_ref, a_view);
4763
  if (is_alkyl (a_ref, nb[0]))
4764
    alkyl_count++;
4765
  if (alkyl_count == 1)
18544 georgesk 4766
    r = istrue;
6785 bpr 4767
  return r;
4768
}
4769
 
17891 bpr 4770
static boolean is_dialkylamino (int a_view, int a_ref)
6785 bpr 4771
{
4772
  int i;
18544 georgesk 4773
  boolean r = isfalse;
6785 bpr 4774
  neighbor_rec nb;
4775
  int alkyl_count = 0;
4776
 
4777
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4778
  if (!(atom[a_view - 1].
6785 bpr 4779
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4780
    return isfalse;
6785 bpr 4781
  if (strcmp (atom[a_ref - 1].element, "N ")
4782
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 4783
    return isfalse;
6785 bpr 4784
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4785
  for (i = 0; i <= 1; i++) {
4786
    if (is_alkyl (a_ref, nb[i]))
4787
            alkyl_count++;
4788
  }
6785 bpr 4789
  if (alkyl_count == 2)
18544 georgesk 4790
    r = istrue;
6785 bpr 4791
  return r;
4792
}
4793
 
17891 bpr 4794
static boolean is_arylamino (int a_view, int a_ref)
6785 bpr 4795
{
18544 georgesk 4796
  boolean r = isfalse;
6785 bpr 4797
  neighbor_rec nb;
4798
  int aryl_count = 0;
4799
 
4800
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4801
  if (!(atom[a_view - 1].
6785 bpr 4802
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4803
    return isfalse;
6785 bpr 4804
  if (strcmp (atom[a_ref - 1].element, "N ")
4805
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4806
    return isfalse;
6785 bpr 4807
  get_nextneighbors (nb, a_ref, a_view);
4808
  if (is_aryl (a_ref, nb[0]))
4809
    aryl_count++;
4810
  if (aryl_count == 1)
18544 georgesk 4811
    r = istrue;
6785 bpr 4812
  return r;
4813
}
4814
 
17891 bpr 4815
static boolean is_diarylamino (int a_view, int a_ref)
6785 bpr 4816
{
4817
  int i;
18544 georgesk 4818
  boolean r = isfalse;
6785 bpr 4819
  neighbor_rec nb;
4820
  int aryl_count = 0;
4821
 
4822
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4823
  if (!(atom[a_view - 1].
6785 bpr 4824
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4825
    return isfalse;
6785 bpr 4826
  if (strcmp (atom[a_ref - 1].element, "N ")
4827
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 4828
    return isfalse;
6785 bpr 4829
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4830
  for (i = 0; i <= 1; i++) {
4831
    if (is_aryl (a_ref, nb[i]))
4832
            aryl_count++;
4833
  }
6785 bpr 4834
  if (aryl_count == 2)
18544 georgesk 4835
    r = istrue;
6785 bpr 4836
  return r;
4837
}
4838
 
17891 bpr 4839
static boolean is_alkylarylamino (int a_view, int a_ref)
6785 bpr 4840
{
4841
  int i;
18544 georgesk 4842
  boolean r = isfalse;
6785 bpr 4843
  neighbor_rec nb;
4844
  int alkyl_count = 0, aryl_count = 0;
4845
 
4846
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4847
  if (!(atom[a_view - 1].
6785 bpr 4848
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4849
    return isfalse;
6785 bpr 4850
  if (strcmp (atom[a_ref - 1].element, "N ")
4851
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 4852
    return isfalse;
6785 bpr 4853
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4854
  for (i = 0; i <= 1; i++) {
4855
    if (is_alkyl (a_ref, nb[i]))
4856
            alkyl_count++;
4857
    if (is_aryl (a_ref, nb[i]))
4858
            aryl_count++;
4859
  }
6785 bpr 4860
  if (alkyl_count == 1 && aryl_count == 1)
18544 georgesk 4861
    r = istrue;
6785 bpr 4862
  return r;
4863
}
4864
 
17891 bpr 4865
static boolean is_C_monosubst_amino (int a_view, int a_ref)
6785 bpr 4866
{
4867
  /* new in v0.3j */
18544 georgesk 4868
  boolean r = isfalse;
6785 bpr 4869
  neighbor_rec nb;
4870
  int c_count = 0;
4871
 
4872
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4873
  if (! (atom[a_view - 1].
6785 bpr 4874
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4875
    return isfalse;
6785 bpr 4876
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4877
      && strcmp (atom[a_ref - 1].atype, "NAM"))
4878
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4879
    return isfalse;
6785 bpr 4880
  get_nextneighbors (nb, a_ref, a_view);
4881
  if (!strcmp (atom[nb[0] - 1].element, "C "))
4882
    c_count++;
4883
  if (c_count == 1)
18544 georgesk 4884
    r = istrue;
6785 bpr 4885
  return r;
4886
}
4887
 
17891 bpr 4888
static boolean is_C_disubst_amino (int a_view, int a_ref)
6785 bpr 4889
{
4890
  /* new in v0.3j */
4891
  int i;
18544 georgesk 4892
  boolean r = isfalse;
6785 bpr 4893
  neighbor_rec nb;
4894
  int b;
4895
  int c_count = 0;
4896
 
4897
  b = get_bond (a_view, a_ref);
4898
  memset (nb, 0, sizeof (neighbor_rec));
4899
  if (!(atom[a_view - 1].heavy && bond[b - 1].btype == 'S' &&
18544 georgesk 4900
            bond[b - 1].arom == isfalse))
4901
    return isfalse;
6785 bpr 4902
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4903
      && strcmp (atom[a_ref - 1].atype, "NAM"))
4904
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 4905
    return isfalse;
6785 bpr 4906
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4907
  for (i = 0; i <= 1; i++) {
4908
    if (!strcmp (atom[nb[i] - 1].element, "C "))
4909
            c_count++;
4910
  }
6785 bpr 4911
  if (c_count == 2)
18544 georgesk 4912
    r = istrue;
6785 bpr 4913
  return r;
4914
}
4915
 
17891 bpr 4916
static boolean is_subst_amino (int a_view, int a_ref)
6785 bpr 4917
{
18544 georgesk 4918
  boolean r = isfalse;
6785 bpr 4919
 
4920
  if (is_amino (a_view, a_ref) || is_alkylamino (a_view, a_ref) |
4921
      is_arylamino (a_view, a_ref) || is_dialkylamino (a_view, a_ref) |
4922
      is_alkylarylamino (a_view, a_ref) || is_diarylamino (a_view, a_ref))
18544 georgesk 4923
    r = istrue;
6785 bpr 4924
  return r;
4925
}
4926
 
18544 georgesk 4927
static boolean is_istrue_alkylamino (int a_view, int a_ref)
6785 bpr 4928
{
18544 georgesk 4929
  boolean r = isfalse;
6785 bpr 4930
  neighbor_rec nb;
4931
  int alkyl_count = 0;
4932
 
4933
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4934
  if (!(atom[a_view - 1].
6785 bpr 4935
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4936
    return isfalse;
6785 bpr 4937
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4938
      && strcmp (atom[a_ref - 1].atype, "N3+"))
4939
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 4940
    return isfalse;
6785 bpr 4941
  get_nextneighbors (nb, a_ref, a_view);
18544 georgesk 4942
  if (is_istrue_alkyl (a_ref, nb[0]))
6785 bpr 4943
    alkyl_count++;
4944
  if (alkyl_count == 1)
18544 georgesk 4945
    r = istrue;
6785 bpr 4946
  return r;
4947
}
4948
 
18544 georgesk 4949
static boolean is_istrue_dialkylamino (int a_view, int a_ref)
6785 bpr 4950
{
4951
  int i;
18544 georgesk 4952
  boolean r = isfalse;
6785 bpr 4953
  neighbor_rec nb;
4954
  int alkyl_count = 0;
4955
 
4956
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4957
  if (!(atom[a_view - 1].
6785 bpr 4958
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4959
    return isfalse;
6785 bpr 4960
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4961
      && strcmp (atom[a_ref - 1].atype, "N3+"))
4962
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 4963
    return isfalse;
6785 bpr 4964
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4965
  for (i = 0; i <= 1; i++) {
18544 georgesk 4966
    if (is_istrue_alkyl (a_ref, nb[i]))
14179 bpr 4967
            alkyl_count++;
4968
  }
6785 bpr 4969
  if (alkyl_count == 2)
18544 georgesk 4970
    r = istrue;
6785 bpr 4971
  return r;
4972
}
4973
 
4974
#if 0
18544 georgesk 4975
static boolean is_istrue_alkylarylamino (int a_view, int a_ref)
6785 bpr 4976
{
4977
  int i;
18544 georgesk 4978
  boolean r = isfalse;
6785 bpr 4979
  neighbor_rec nb;
4980
  int alkyl_count = 0, aryl_count = 0;
4981
 
4982
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4983
  if (!(atom[a_view - 1].
6785 bpr 4984
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 4985
    return isfalse;
6785 bpr 4986
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4987
      && strcmp (atom[a_ref - 1].atype, "N3+"))
4988
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 4989
    return isfalse;
6785 bpr 4990
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4991
  for (i = 0; i <= 1; i++) {
18544 georgesk 4992
    if (is_istrue_alkyl (a_ref, nb[i]))
14179 bpr 4993
            alkyl_count++;
4994
    if (is_aryl (a_ref, nb[i]))
4995
            aryl_count++;
4996
  }
6785 bpr 4997
  if (alkyl_count == 1 && aryl_count == 1)
18544 georgesk 4998
    r = istrue;
6785 bpr 4999
  return r;
5000
}
5001
#endif
5002
 
17891 bpr 5003
static boolean is_hydroxylamino (int a_view, int a_ref)
6785 bpr 5004
{
5005
  int i;
18544 georgesk 5006
  boolean r = isfalse;
6785 bpr 5007
  neighbor_rec nb;
5008
  int oh_count = 0, het_count = 0;      /* v0.3k */
5009
  str2 nb_el;                   /* v0.3k */
5010
  int FORLIM;
5011
 
5012
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5013
  if (!(atom[a_view - 1].
6785 bpr 5014
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5015
    return isfalse;
6785 bpr 5016
  if (strcmp (atom[a_ref - 1].element, "N ")
5017
      || atom[a_ref - 1].neighbor_count < 2)
5018
    /* v0.3c */
18544 georgesk 5019
    return isfalse;
6785 bpr 5020
  get_nextneighbors (nb, a_ref, a_view);
5021
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5022
  for (i = 0; i <= FORLIM; i++) {                               /* v0.3c */
5023
    if (is_hydroxy (a_ref, nb[i]))
5024
            oh_count++;
5025
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
5026
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
5027
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
5028
              && strcmp (nb_el, "LP"))
5029
              /* v0.3k */
5030
            het_count++;
6785 bpr 5031
      /* v0.3n: D */
14179 bpr 5032
  }
6785 bpr 5033
  if (oh_count == 1 && het_count == 1)
18544 georgesk 5034
    r = istrue;
6785 bpr 5035
  return r;
5036
}
5037
 
17891 bpr 5038
static boolean is_nitro (int a_view, int a_ref)
6785 bpr 5039
{
5040
  int i;
18544 georgesk 5041
  boolean r = isfalse;
6785 bpr 5042
  neighbor_rec nb;
5043
  int o_count = 0, bond_count = 0;
5044
 
5045
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5046
  if (!(atom[a_view - 1].
6785 bpr 5047
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5048
    return isfalse;
6785 bpr 5049
  if (strcmp (atom[a_ref - 1].element, "N ")
5050
      || atom[a_ref - 1].neighbor_count != 3)
18544 georgesk 5051
    return isfalse;
6785 bpr 5052
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5053
  for (i = 0; i <= 1; i++) {
5054
    if (!strcmp (atom[nb[i] - 1].element, "O "))
5055
            o_count++;
5056
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
5057
            bond_count++;
5058
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
5059
            bond_count += 2;
5060
  }
6785 bpr 5061
  if (o_count == 2 && bond_count >= 3)
18544 georgesk 5062
    r = istrue;
6785 bpr 5063
  return r;
5064
}
5065
 
17891 bpr 5066
static boolean is_azido (int a_view, int a_ref)
6785 bpr 5067
{
18544 georgesk 5068
  boolean r = isfalse;
6785 bpr 5069
  neighbor_rec nb;
5070
  int bond_count = 0, n1 = 0, n2 = 0, n3 = 0;
5071
 
14179 bpr 5072
  if (!(atom[a_view - 1].
6785 bpr 5073
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5074
    return isfalse;
6785 bpr 5075
  if (strcmp (atom[a_ref - 1].element, "N ")
5076
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 5077
    return isfalse;
6785 bpr 5078
  n1 = a_ref;
5079
  memset (nb, 0, sizeof (neighbor_rec));
5080
  get_nextneighbors (nb, n1, a_view);
14179 bpr 5081
  if (!strcmp (atom[nb[0] - 1].element, "N ")) {
5082
    n2 = nb[0];
5083
    if (bond[get_bond (n1, n2) - 1].btype == 'S')
6785 bpr 5084
            bond_count++;
14179 bpr 5085
    if (bond[get_bond (n1, n2) - 1].btype == 'D')
6785 bpr 5086
            bond_count += 2;
14179 bpr 5087
    if (bond[get_bond (n1, n2) - 1].btype == 'T')
6785 bpr 5088
            bond_count += 3;
14179 bpr 5089
  }
5090
  if (n2 > 0 && atom[n2 - 1].neighbor_count == 2) {
5091
    memset (nb, 0, sizeof (neighbor_rec));
5092
    get_nextneighbors (nb, n2, n1);
5093
    if (!strcmp (atom[nb[0] - 1].element, "N ")){
5094
            n3 = nb[0];
5095
            if (bond[get_bond (n2, n3) - 1].btype == 'S')
5096
              bond_count++;
5097
            if (bond[get_bond (n2, n3) - 1].btype == 'D')
5098
              bond_count += 2;
5099
            if (bond[get_bond (n2, n3) - 1].btype == 'T')
5100
              bond_count += 3;
5101
          }
5102
  }
6785 bpr 5103
  if (n1 > 0 && n2 > 0 && n3 > 0 && atom[n3 - 1].neighbor_count == 1 &&
5104
      bond_count > 3)
18544 georgesk 5105
    r = istrue;
6785 bpr 5106
  return r;
5107
}
5108
 
17891 bpr 5109
static boolean is_diazonium (int a_view, int a_ref)
6785 bpr 5110
{
18544 georgesk 5111
  boolean r = isfalse;
6785 bpr 5112
  neighbor_rec nb;
5113
  int bond_count = 0, chg_count = 0, n1 = 0, n2 = 0;
5114
 
14179 bpr 5115
  if (!(atom[a_view - 1].
6785 bpr 5116
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5117
    return isfalse;
6785 bpr 5118
  if (strcmp (atom[a_ref - 1].element, "N ")
5119
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 5120
    return isfalse;
6785 bpr 5121
  n1 = a_ref;
5122
  chg_count = atom[n1 - 1].formal_charge;
5123
  memset (nb, 0, sizeof (neighbor_rec));
5124
  get_nextneighbors (nb, n1, a_view);
14179 bpr 5125
  if (!strcmp (atom[nb[0] - 1].element, "N ")) {
5126
    n2 = nb[0];
5127
    chg_count += atom[n2 - 1].formal_charge;
5128
    if (bond[get_bond (n1, n2) - 1].btype == 'S')
5129
            bond_count++;
5130
    if (bond[get_bond (n1, n2) - 1].btype == 'D')
5131
            bond_count += 2;
5132
    if (bond[get_bond (n1, n2) - 1].btype == 'T')
5133
            bond_count += 3;
5134
  }
6785 bpr 5135
  if (n1 > 0 && n2 > 0 && atom[n2 - 1].neighbor_count == 1
5136
      && bond_count >= 2 && chg_count > 0)
18544 georgesk 5137
    r = istrue;
6785 bpr 5138
  return r;
5139
}
5140
 
17891 bpr 5141
static boolean is_hydroximino_C (int id)
6785 bpr 5142
{
5143
  int i;
18544 georgesk 5144
  boolean r = isfalse;
6785 bpr 5145
  neighbor_rec nb;
5146
  int a_het = 0;
5147
  int FORLIM;
5148
 
5149
  memset (nb, 0, sizeof (neighbor_rec));
5150
  if (id < 1 || id > n_atoms)
18544 georgesk 5151
    return isfalse;
6785 bpr 5152
  get_neighbors (nb, id);
5153
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 5154
    return isfalse;
6785 bpr 5155
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 5156
  for (i = 0; i < FORLIM; i++) {
5157
    if ((bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5158
              !strcmp (atom[nb[i] - 1].element, "N ")) && (hetbond_count (nb[i]) == 3))
5159
            a_het = nb[i];
5160
  }
6785 bpr 5161
  if (a_het <= 0)
18544 georgesk 5162
    return isfalse;
6785 bpr 5163
  memset (nb, 0, sizeof (neighbor_rec));
5164
  get_neighbors (nb, a_het);
5165
  if (strcmp (atom[a_het - 1].element, "N ")
5166
      || atom[a_het - 1].neighbor_count <= 0)
18544 georgesk 5167
    return isfalse;
6785 bpr 5168
  FORLIM = atom[a_het - 1].neighbor_count;
14179 bpr 5169
  for (i = 0; i < FORLIM; i++) {
5170
    if (is_hydroxy (a_het, nb[i]))
18544 georgesk 5171
          r = istrue;
14179 bpr 5172
  }
6785 bpr 5173
  return r;
5174
}
5175
 
17891 bpr 5176
static boolean is_hydrazono_C (int id)
6785 bpr 5177
{
5178
  int i;
18544 georgesk 5179
  boolean r = isfalse;
6785 bpr 5180
  neighbor_rec nb;
5181
  int a_het = 0;
5182
  int FORLIM;
5183
 
5184
  memset (nb, 0, sizeof (neighbor_rec));
5185
  if (id < 1 || id > n_atoms)
18544 georgesk 5186
    return isfalse;
6785 bpr 5187
  get_neighbors (nb, id);
5188
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
18544 georgesk 5189
    return isfalse;
6785 bpr 5190
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 5191
  for (i = 0; i < FORLIM; i++) {
5192
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5193
              !strcmp (atom[nb[i] - 1].element, "N ")) {
6785 bpr 5194
          /* and
5195
             (hetbond_count(nb[i]) = 3)  */
5196
          a_het = nb[i];
14179 bpr 5197
          }
5198
  }
6785 bpr 5199
  if (a_het <= 0)
18544 georgesk 5200
    return isfalse;
6785 bpr 5201
  memset (nb, 0, sizeof (neighbor_rec));
5202
  get_neighbors (nb, a_het);
5203
  if (strcmp (atom[a_het - 1].element, "N ")
5204
      || atom[a_het - 1].neighbor_count <= 0)
18544 georgesk 5205
    return isfalse;
6785 bpr 5206
  FORLIM = atom[a_het - 1].neighbor_count;
14179 bpr 5207
  for (i = 0; i < FORLIM; i++) {
5208
    if (is_amino (a_het, nb[i]) || is_alkylamino (a_het, nb[i]) |
5209
              is_alkylarylamino (a_het, nb[i]) || is_arylamino (a_het, nb[i]) |
5210
              is_dialkylamino (a_het, nb[i]) || is_diarylamino (a_het, nb[i]))
18544 georgesk 5211
            r = istrue;
14179 bpr 5212
  }
6785 bpr 5213
  return r;
5214
}
5215
 
17891 bpr 5216
static boolean is_alkoxycarbonyl (int a_view, int a_ref)
6785 bpr 5217
{
5218
  int i;
18544 georgesk 5219
  boolean r = isfalse;
6785 bpr 5220
  neighbor_rec nb;
5221
 
5222
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5223
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5224
    return isfalse;
6785 bpr 5225
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5226
    return isfalse;
6785 bpr 5227
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5228
  for (i = 0; i <= 1; i++) {
5229
    if (is_alkoxy (a_ref, nb[i]))
18544 georgesk 5230
            r = istrue;
14179 bpr 5231
  }
6785 bpr 5232
  return r;
5233
}
5234
 
17891 bpr 5235
static boolean is_aryloxycarbonyl (int a_view, int a_ref)
6785 bpr 5236
{
5237
  int i;
18544 georgesk 5238
  boolean r = isfalse;
6785 bpr 5239
  neighbor_rec nb;
5240
 
5241
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5242
  if (!(atom[a_view - 1].
6785 bpr 5243
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5244
    return isfalse;
6785 bpr 5245
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5246
    return isfalse;
6785 bpr 5247
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5248
  for (i = 0; i <= 1; i++) {
5249
    if (is_aryloxy (a_ref, nb[i]))
18544 georgesk 5250
            r = istrue;
14179 bpr 5251
  }
6785 bpr 5252
  return r;
5253
}
5254
 
17891 bpr 5255
static boolean is_carbamoyl (int a_view, int a_ref)
6785 bpr 5256
{
5257
  int i;
18544 georgesk 5258
  boolean r = isfalse;
6785 bpr 5259
  neighbor_rec nb;
5260
 
5261
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5262
  if (!(atom[a_view - 1].
6785 bpr 5263
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5264
    return isfalse;
6785 bpr 5265
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5266
    return isfalse;
6785 bpr 5267
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5268
  for (i = 0; i <= 1; i++) {
5269
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
18544 georgesk 5270
            r = istrue;
14179 bpr 5271
  }
6785 bpr 5272
  return r;
5273
}
5274
 
17891 bpr 5275
static boolean is_alkoxythiocarbonyl (int a_view, int a_ref)
6785 bpr 5276
{
5277
  int i;
18544 georgesk 5278
  boolean r = isfalse;
6785 bpr 5279
  neighbor_rec nb;
5280
 
5281
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5282
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5283
    return isfalse;
6785 bpr 5284
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5285
    return isfalse;
6785 bpr 5286
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5287
  for (i = 0; i <= 1; i++) {
5288
    if (is_alkoxy (a_ref, nb[i]))
18544 georgesk 5289
            r = istrue;
14179 bpr 5290
  }
6785 bpr 5291
  return r;
5292
}
5293
 
17891 bpr 5294
static boolean is_aryloxythiocarbonyl (int a_view, int a_ref)
6785 bpr 5295
{
5296
  int i;
18544 georgesk 5297
  boolean r = isfalse;
6785 bpr 5298
  neighbor_rec nb;
5299
 
5300
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5301
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5302
    return isfalse;
6785 bpr 5303
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5304
    return isfalse;
6785 bpr 5305
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5306
  for (i = 0; i <= 1; i++) {
5307
    if (is_aryloxy (a_ref, nb[i]))
18544 georgesk 5308
            r = istrue;
14179 bpr 5309
  }
6785 bpr 5310
  return r;
5311
}
5312
 
17891 bpr 5313
static boolean is_thiocarbamoyl (int a_view, int a_ref)
6785 bpr 5314
{
5315
  int i;
18544 georgesk 5316
  boolean r = isfalse;
6785 bpr 5317
  neighbor_rec nb;
5318
 
5319
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5320
  if (!(atom[a_view - 1].
6785 bpr 5321
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5322
    return isfalse;
6785 bpr 5323
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5324
    return isfalse;
6785 bpr 5325
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5326
  for (i = 0; i <= 1; i++) {
5327
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5328
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
18544 georgesk 5329
            r = istrue;
14179 bpr 5330
  }
6785 bpr 5331
  return r;
5332
}
5333
 
17891 bpr 5334
static boolean is_alkanoyl (int a_view, int a_ref)
6785 bpr 5335
{
5336
  int i;
18544 georgesk 5337
  boolean r = isfalse;
6785 bpr 5338
  neighbor_rec nb;
5339
 
5340
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5341
  if (!(atom[a_view - 1].
6785 bpr 5342
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5343
    return isfalse;
6785 bpr 5344
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5345
    return isfalse;
6785 bpr 5346
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5347
  for (i = 0; i <= 1; i++) {
5348
    if (is_alkyl (a_ref, nb[i]))
18544 georgesk 5349
            r = istrue;
14179 bpr 5350
  }
6785 bpr 5351
  return r;
5352
}
5353
 
17891 bpr 5354
static boolean is_aroyl (int a_view, int a_ref)
6785 bpr 5355
{
5356
  int i;
18544 georgesk 5357
  boolean r = isfalse;
6785 bpr 5358
  neighbor_rec nb;
5359
 
5360
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5361
  if (!(atom[a_view - 1].
6785 bpr 5362
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5363
    return isfalse;
6785 bpr 5364
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
18544 georgesk 5365
    return isfalse;
6785 bpr 5366
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5367
  for (i = 0; i <= 1; i++) {
5368
    if (is_aryl (a_ref, nb[i]))
18544 georgesk 5369
            r = istrue;
14179 bpr 5370
  }
6785 bpr 5371
  return r;
5372
}
5373
 
17891 bpr 5374
static boolean is_acyl (int a_view, int a_ref)
6785 bpr 5375
{
18544 georgesk 5376
  boolean r = isfalse;
6785 bpr 5377
 
5378
  if (is_alkanoyl (a_view, a_ref) || is_aroyl (a_view, a_ref))
18544 georgesk 5379
    r = istrue;
6785 bpr 5380
  return r;
5381
}
5382
 
17891 bpr 5383
static boolean is_acyl_gen (int a_view, int a_ref)
6785 bpr 5384
{
5385
  /* new in v0.3j */
18544 georgesk 5386
  boolean r = isfalse;
6785 bpr 5387
 
5388
  if (is_oxo_C (a_ref))
18544 georgesk 5389
    r = istrue;
6785 bpr 5390
  return r;
5391
}
5392
 
17891 bpr 5393
static boolean is_acylamino (int a_view, int a_ref)
6785 bpr 5394
{
18544 georgesk 5395
  boolean r = isfalse;
6785 bpr 5396
  neighbor_rec nb;
5397
  int acyl_count = 0;
5398
 
5399
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5400
  if (!(atom[a_view - 1].
6785 bpr 5401
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5402
    return isfalse;
6785 bpr 5403
  if (strcmp (atom[a_ref - 1].element, "N ")
5404
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 5405
    return isfalse;
6785 bpr 5406
  get_nextneighbors (nb, a_ref, a_view);
5407
  if (is_acyl (a_ref, nb[0]))
5408
    acyl_count++;
5409
  if (acyl_count == 1)
18544 georgesk 5410
    r = istrue;
6785 bpr 5411
  return r;
5412
}
5413
 
17891 bpr 5414
static boolean is_subst_acylamino (int a_view, int a_ref)
6785 bpr 5415
{
5416
  /* may be substituted _or_ unsubstituted acylamino group! */
5417
  int i;
18544 georgesk 5418
  boolean r = isfalse;
6785 bpr 5419
  neighbor_rec nb;
5420
  int acyl_count = 0;
5421
  int FORLIM;
5422
 
5423
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5424
  if (!(atom[a_view - 1].
6785 bpr 5425
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5426
    return isfalse;
6785 bpr 5427
  if (strcmp (atom[a_ref - 1].element, "N ")
5428
      || atom[a_ref - 1].neighbor_count < 2)
18544 georgesk 5429
    return isfalse;
6785 bpr 5430
  get_nextneighbors (nb, a_ref, a_view);
5431
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5432
  for (i = 0; i <= FORLIM; i++) {
5433
    if (is_acyl_gen (a_ref, nb[i]))     /* v0.3j */
5434
            acyl_count++;
5435
  }
6785 bpr 5436
  if (acyl_count > 0)
18544 georgesk 5437
    r = istrue;
6785 bpr 5438
  return r;
5439
}
5440
 
17891 bpr 5441
static boolean is_hydrazino (int a_view, int a_ref)
6785 bpr 5442
{
5443
  int i;
18544 georgesk 5444
  boolean r = isfalse;
6785 bpr 5445
  neighbor_rec nb;
5446
  int nr_count = 0;
5447
  int FORLIM;
5448
 
5449
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5450
  if (!(atom[a_view - 1].
6785 bpr 5451
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5452
    return isfalse;
6785 bpr 5453
  if (strcmp (atom[a_ref - 1].element, "N ")
5454
      || atom[a_ref - 1].neighbor_count < 2)
18544 georgesk 5455
    return isfalse;
6785 bpr 5456
  get_nextneighbors (nb, a_ref, a_view);
5457
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5458
  for (i = 0; i <= FORLIM; i++) {                               /* fixed in v0.3c */
5459
    if (is_amino (a_ref, nb[i]) || is_subst_amino (a_ref, nb[i]))
5460
            nr_count++;
5461
  }
6785 bpr 5462
  if (nr_count == 1)
18544 georgesk 5463
    r = istrue;
6785 bpr 5464
  return r;
5465
}
5466
 
17891 bpr 5467
static boolean is_nitroso (int a_view, int a_ref)
6785 bpr 5468
{
5469
  /* new in v0.3j */
18544 georgesk 5470
  boolean r = isfalse;
6785 bpr 5471
  neighbor_rec nb;
5472
  int o_count = 0;
5473
  int a2;
5474
 
5475
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5476
  if (!(atom[a_view - 1].
6785 bpr 5477
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5478
    return isfalse;
6785 bpr 5479
  if (strcmp (atom[a_ref - 1].element, "N ")
5480
      || atom[a_ref - 1].neighbor_count != 2)
18544 georgesk 5481
    return isfalse;
6785 bpr 5482
  get_nextneighbors (nb, a_ref, a_view);
5483
  a2 = nb[0];
17891 bpr 5484
  if ((strcmp (atom[a2 - 1].element, "O ") == 0) &&
6785 bpr 5485
      (bond[get_bond (a_ref, a2) - 1].btype == 'D'))
5486
    o_count++;
5487
  if (o_count == 1)
18544 georgesk 5488
    r = istrue;
6785 bpr 5489
  return r;
5490
}
5491
 
17891 bpr 5492
static boolean is_subst_hydrazino (int a_view, int a_ref)
6785 bpr 5493
{
5494
  int i;
18544 georgesk 5495
  boolean r = isfalse;
6785 bpr 5496
  neighbor_rec nb;
5497
  int nr_count = 0;
5498
  int a2, FORLIM;
5499
 
5500
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5501
  if (!(atom[a_view - 1].
6785 bpr 5502
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
18544 georgesk 5503
    return isfalse;
6785 bpr 5504
  if (strcmp (atom[a_ref - 1].element, "N ")
5505
      || atom[a_ref - 1].neighbor_count < 2)
18544 georgesk 5506
    return isfalse;
6785 bpr 5507
  get_nextneighbors (nb, a_ref, a_view);
5508
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5509
  for (i = 0; i <= FORLIM; i++) {
5510
    a2 = nb[i];
5511
    if ((strcmp (atom[a2 - 1].element, "N ") == 0) && (!is_nitroso (a_ref, a2)))
5512
            /* v0.3j */
5513
            nr_count++;
5514
  }
6785 bpr 5515
  if (nr_count == 1)
18544 georgesk 5516
    r = istrue;
6785 bpr 5517
  return r;
5518
}
5519
 
17891 bpr 5520
static boolean is_cyano (int a_view, int a_ref)
6785 bpr 5521
{
18544 georgesk 5522
  boolean r = isfalse;
6785 bpr 5523
 
17891 bpr 5524
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &&
14179 bpr 5525
      (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6785 bpr 5526
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
5527
      atom[a_ref - 1].neighbor_count == 1)
18544 georgesk 5528
    r = istrue;
6785 bpr 5529
  return r;
5530
}
5531
 
17891 bpr 5532
static boolean is_cyano_c (int a_ref)
6785 bpr 5533
{
5534
  int i;
18544 georgesk 5535
  boolean r = isfalse;
6785 bpr 5536
  neighbor_rec nb;
5537
  int FORLIM;
5538
 
5539
  memset (nb, 0, sizeof (neighbor_rec));
5540
  if (strcmp (atom[a_ref - 1].atype, "C1 ")
5541
      || atom[a_ref - 1].neighbor_count <= 0)
18544 georgesk 5542
    return isfalse;
6785 bpr 5543
  get_neighbors (nb, a_ref);
5544
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 5545
  for (i = 0; i < FORLIM; i++) {
5546
    if (is_cyano (a_ref, nb[i]))
18544 georgesk 5547
            r = istrue;
14179 bpr 5548
  }
6785 bpr 5549
  return r;
5550
}
5551
 
17891 bpr 5552
static boolean is_nitrile (int a_view, int a_ref)
6785 bpr 5553
{
18544 georgesk 5554
  boolean r = isfalse;
6785 bpr 5555
  neighbor_rec nb;
5556
  str2 nb_el;
5557
 
5558
  if (!is_cyano (a_view, a_ref))
18544 georgesk 5559
    return isfalse;
6785 bpr 5560
  if (atom[a_view - 1].neighbor_count == 1
5561
      && atom[a_view - 1].formal_charge == 0)
18544 georgesk 5562
    return istrue;
6785 bpr 5563
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
5564
  get_nextneighbors (nb, a_view, a_ref);
5565
  strcpy (nb_el, atom[nb[0] - 1].element);
5566
  if (!strcmp (nb_el, "C ")
5567
      || !strcmp (nb_el, "H ") /*|| !strcmp (nb_el, "D ") */ )
5568
    /* v0.3n: D */
18544 georgesk 5569
    r = istrue;
6785 bpr 5570
  /* HCN is also a nitrile! */
5571
  return r;
5572
}
5573
 
17891 bpr 5574
static boolean is_isonitrile (int a_view, int a_ref)
6785 bpr 5575
{
5576
  /* only recognized with CN triple bond! */
18544 georgesk 5577
  boolean r = isfalse;
6785 bpr 5578
 
17890 bpr 5579
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &&
6785 bpr 5580
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
5581
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
5582
      atom[a_ref - 1].neighbor_count == 2
5583
      && atom[a_view - 1].neighbor_count == 1)
18544 georgesk 5584
    r = istrue;
6785 bpr 5585
  return r;
5586
}
5587
 
17891 bpr 5588
static boolean is_cyanate (int a_view, int a_ref)
6785 bpr 5589
{
18544 georgesk 5590
  boolean r = isfalse;
6785 bpr 5591
  neighbor_rec nb;
5592
 
5593
  if (!is_cyano (a_view, a_ref))
18544 georgesk 5594
    return isfalse;
6785 bpr 5595
  if (atom[a_view - 1].neighbor_count != 2)
18544 georgesk 5596
    return isfalse;
6785 bpr 5597
  get_nextneighbors (nb, a_view, a_ref);
5598
  if (is_alkoxy (a_view, nb[0]) || is_aryloxy (a_view, nb[0]))
18544 georgesk 5599
    r = istrue;
6785 bpr 5600
  return r;
5601
}
5602
 
17891 bpr 5603
static boolean is_thiocyanate (int a_view, int a_ref)
6785 bpr 5604
{
18544 georgesk 5605
  boolean r = isfalse;
6785 bpr 5606
  neighbor_rec nb;
5607
 
5608
  if (!is_cyano (a_view, a_ref))
18544 georgesk 5609
    return isfalse;
6785 bpr 5610
  if (atom[a_view - 1].neighbor_count != 2)
18544 georgesk 5611
    return isfalse;
6785 bpr 5612
  get_nextneighbors (nb, a_view, a_ref);
5613
  if (is_alkylsulfanyl (a_view, nb[0]) || is_arylsulfanyl (a_view, nb[0]))
18544 georgesk 5614
    r = istrue;
6785 bpr 5615
  return r;
5616
}
5617
 
14179 bpr 5618
static void update_Htotal ()
6785 bpr 5619
{
5620
  int i, j, b_id;
5621
  neighbor_rec nb;
5622
  int single_count, double_count, triple_count, arom_count, total_bonds,
5623
    Htotal, nval;
5624
  /* new in v0.3 */
18544 georgesk 5625
  boolean diazon = isfalse;     /* new in v0.3j */
6785 bpr 5626
  neighbor_rec nb2;             /* new in v0.3j */
5627
  int a1, a2, a3;               /* new in v0.3j */
5628
  int FORLIM, FORLIM1;
5629
 
5630
  if (n_atoms < 1)
5631
    return;
5632
  memset (nb, 0, sizeof (neighbor_rec));
5633
  FORLIM = n_atoms;
14179 bpr 5634
  for (i = 1; i <= FORLIM; i++) {
5635
    single_count = 0;
5636
    double_count = 0;
5637
    triple_count = 0;
5638
    arom_count = 0;
5639
    total_bonds = 0;
5640
    Htotal = 0;
5641
    get_neighbors (nb, i);
5642
    if (atom[i - 1].neighbor_count > 0) {
5643
            /* count single, double, triple, and aromatic bonds to all neighbor atoms */
5644
            FORLIM1 = atom[i - 1].neighbor_count;
5645
            for (j = 0; j < FORLIM1; j++) {
5646
                b_id = get_bond (i, nb[j]);
5647
              if (b_id > 0) {
5648
                      if (bond[b_id - 1].btype == 'S')
5649
                        single_count++;
5650
                      if (bond[b_id - 1].btype == 'D')
5651
                        double_count++;
5652
                      if (bond[b_id - 1].btype == 'T')
5653
                        triple_count++;
5654
                      if (bond[b_id - 1].btype == 'A')
5655
                        arom_count++;
5656
                    }
6785 bpr 5657
            }
14179 bpr 5658
            /*check for diazonium salts */
5659
            a1 = i;
5660
            a2 = nb[0];
5661
            if (!strcmp (atom[a1 - 1].element, "N ") && !strcmp (atom[a2 - 1].element, "N ")) {
5662
              if (atom[a2 - 1].neighbor_count == 2) {
5663
                      get_nextneighbors (nb2, a2, a1);
5664
                      a3 = nb2[0];
5665
                      if ((strcmp (atom[a3 - 1].element, "C ") == 0) && is_diazonium (a3, a2))
18544 georgesk 5666
                        diazon = istrue;
14179 bpr 5667
                  }
6785 bpr 5668
            }
14179 bpr 5669
          }
5670
    total_bonds = single_count + double_count * 2 + triple_count * 3 + (int) (1.5 * arom_count);
6785 bpr 5671
      /* calculate number of total hydrogens per atom */
5672
      /*nval := nvalences(atom^[i].element);    (* new in v0.3 */
14179 bpr 5673
    nval = atom[i - 1].nvalences;       /* new in v0.3m */
5674
    if (!strcmp (atom[i - 1].element, "P ")) {
5675
            if (total_bonds - atom[i - 1].formal_charge > 3)    /* refined in v0.3n */
5676
              nval = 5;
5677
          }                     /*  */
5678
    if (!strcmp (atom[i - 1].element, "S ")) {                  /* v0.3h */
5679
            if (total_bonds > 2 && atom[i - 1].formal_charge < 1)
5680
              /* updated in v0.3j */
5681
              nval = 4;
5682
            if (total_bonds > 4)        /* this will need some refinement... */
5683
              nval = 6;
5684
          }                     /*  */
5685
    Htotal = nval - total_bonds + atom[i - 1].formal_charge;
5686
    if (diazon)         /* v0.3j */
5687
            Htotal = 0;
5688
    if (Htotal < 0)             /* e.g., N in nitro group */
5689
            Htotal = 0;
6785 bpr 5690
      atom[i - 1].Htot = Htotal;
14179 bpr 5691
    if (atom[i - 1].Hexp > atom[i - 1].Htot)    /* v0.3n; just to be sure... */
5692
            atom[i - 1].Htot = atom[i - 1].Hexp;
5693
  }
6785 bpr 5694
}
5695
 
14179 bpr 5696
static void update_atypes ()
6785 bpr 5697
{
5698
  int i, j, b_id;
5699
  neighbor_rec nb;
5700
  int single_count, double_count, triple_count, arom_count, acyl_count,
5701
    C_count, O_count, total_bonds, NdO_count, NdC_count, Htotal, FORLIM,
5702
    FORLIM1;
5703
 
5704
  if (n_atoms < 1)
5705
    return;
5706
  memset (nb, 0, sizeof (neighbor_rec));
5707
  FORLIM = n_atoms;
14179 bpr 5708
  for (i = 0; i < FORLIM; i++) {
5709
    single_count = 0;
5710
    double_count = 0;
5711
    triple_count = 0;
5712
    arom_count = 0;
5713
    total_bonds = 0;
5714
    acyl_count = 0;
5715
    C_count = 0;
5716
    O_count = 0;
5717
    NdO_count = 0;
5718
    NdC_count = 0;
5719
    Htotal = 0;
5720
    get_neighbors (nb, i + 1);
5721
    if (atom[i].neighbor_count > 0) {
5722
            /* count single, double, triple, and aromatic bonds to all neighbor atoms */
5723
            FORLIM1 = atom[i].neighbor_count;
5724
            for (j = 0; j < FORLIM1; j++) {
6785 bpr 5725
              if (is_oxo_C (nb[j]) || is_thioxo_C (nb[j]))
14179 bpr 5726
          acyl_count++;
6785 bpr 5727
              if (!strcmp (atom[nb[j] - 1].element, "C "))
14179 bpr 5728
                      C_count++;
6785 bpr 5729
              if (!strcmp (atom[nb[j] - 1].element, "O "))
14179 bpr 5730
                      O_count++;
6785 bpr 5731
              b_id = get_bond (i + 1, nb[j]);
14179 bpr 5732
              if (b_id > 0) {
5733
                      if (bond[b_id - 1].btype == 'S')
5734
                        single_count++;
6785 bpr 5735
                      if (bond[b_id - 1].btype == 'D')
14179 bpr 5736
                        double_count++;
5737
                      if (bond[b_id - 1].btype == 'T')
5738
                        triple_count++;
5739
                      if (bond[b_id - 1].btype == 'A'){
5740
                        /* v0.3n: special treatment for acyclic bonds */
5741
                           /* flagged as "aromatic" (in query structures) */
5742
                        if (bond[b_id - 1].ring_count > 0)
5743
                                arom_count++;
5744
                        else
5745
                                double_count++;
5746
                      }
5747
                      if ((!strcmp (atom[i].element, "N ") &&
5748
                          !strcmp (atom[nb[j] - 1].element, "O ")) ||
5749
                          (!strcmp (atom[i].element, "O ") &&
5750
                        !strcmp (atom[nb[j] - 1].element, "N "))) {
5751
                        /* check if it is an N-oxide drawn with a double bond ==> should be N3 */
5752
                        if (bond[b_id - 1].btype == 'D')
5753
                                NdO_count++;
5754
                     }
5755
                    if ((!strcmp (atom[i].element, "N ") &&
5756
                         !strcmp (atom[nb[j] - 1].element, "C ")) ||
5757
                        (!strcmp (atom[i].element, "C ") &&
5758
                         !strcmp (atom[nb[j] - 1].element, "N "))) {
6785 bpr 5759
                      if (bond[b_id - 1].btype == 'D')
14179 bpr 5760
                              NdC_count++;
6785 bpr 5761
                    }
14179 bpr 5762
                  }
5763
          }
6785 bpr 5764
          total_bonds = single_count + double_count * 2 + triple_count * 3 +
5765
            (int) (1.5 * arom_count);
5766
          /* calculate number of total hydrogens per atom */
5767
          /*Htotal := nvalences(atom^[i].element) - total_bonds + atom^[i].formal_charge; */
5768
          Htotal = atom[i].nvalences - total_bonds + atom[i].formal_charge;
5769
          if (Htotal < 0)       /* e.g., N in nitro group */
5770
            Htotal = 0;
5771
          atom[i].Htot = Htotal;
5772
          /* refine atom types, based on bond types */
14179 bpr 5773
          if (!strcmp (atom[i].element, "C ")) {
5774
            if (arom_count > 1)
5775
                    strcpy (atom[i].atype, "CAR");
5776
      if (triple_count == 1 || double_count == 2)
5777
                    strcpy (atom[i].atype, "C1 ");
5778
            if (double_count == 1)
5779
                    strcpy (atom[i].atype, "C2 ");
5780
            if (triple_count == 0 && double_count == 0 && arom_count < 2)
5781
                    strcpy (atom[i].atype, "C3 ");
5782
          }
5783
          if (!strcmp (atom[i].element, "O ")) {
5784
            if (double_count == 1)
5785
                    strcpy (atom[i].atype, "O2 ");
5786
            if (double_count == 0)
5787
                    strcpy (atom[i].atype, "O3 ");
5788
          }
5789
          if (!strcmp (atom[i].element, "N ")) {
5790
            if (total_bonds > 3) {
5791
                    if (O_count == 0) {
6785 bpr 5792
                      if (single_count > 3 ||
14179 bpr 5793
                                (single_count == 2 && double_count == 1 && C_count >= 2))
5794
                              atom[i].formal_charge = 1;
6785 bpr 5795
                    }
14179 bpr 5796
                    else {
6785 bpr 5797
                      if (O_count == 1 && atom[i].formal_charge == 0)   /* v0.3m */
14179 bpr 5798
                              strcpy (atom[i].atype, "N3 ");
5799
                      if (O_count == 2 && atom[i].formal_charge == 0) {
5800
                              if (atom[i].neighbor_count > 2)   /* nitro v0.3o */
5801
                                strcpy (atom[i].atype, "N2 ");
5802
                              if (atom[i].neighbor_count == 2)  /* NO2   v0.3o */
5803
                                strcpy (atom[i].atype, "N1 ");
5804
                            }
6785 bpr 5805
                      /* the rest is left empty, so far.... */
5806
                    }
14179 bpr 5807
                  }
5808
            /* could be an N-oxide -> should be found elsewhere  */
5809
            if (triple_count == 1 || (double_count == 2 && atom[i].neighbor_count == 2))
5810
                    /* v0.3n */
5811
                    strcpy (atom[i].atype, "N1 ");
5812
              if (double_count == 1) {
5813
                      /*if NdC_count > 0 then atom^[i].atype := 'N2 '; */
5814
                      if (NdC_count == 0 && NdO_count > 0 && C_count >= 2)
5815
                        strcpy (atom[i].atype, "N3 ");
5816
                      /* N-oxide is N3 except in hetarene etc. */
5817
                      else
5818
                        strcpy (atom[i].atype, "N2 ");
5819
                    }
6785 bpr 5820
              /* fallback, added in v0.3g  */
18544 georgesk 5821
              if (arom_count > 1 || atom[i].arom == istrue)     /* v0.3n */
14179 bpr 5822
                      strcpy (atom[i].atype, "NAR");
5823
              if (triple_count == 0 && double_count == 0) {
5824
                      if (atom[i].formal_charge == 0) {
5825
                        if (acyl_count == 0)
5826
                                strcpy (atom[i].atype, "N3 ");
5827
                        if (acyl_count > 0)
5828
                                strcpy (atom[i].atype, "NAM");
5829
                      }
5830
                      if (atom[i].formal_charge == 1)
5831
                        strcpy (atom[i].atype, "N3+");
5832
                      }
5833
              }
5834
              if (!strcmp (atom[i].element, "P ")) {
5835
                if (single_count > 4)
5836
                        strcpy (atom[i].atype, "P4 ");
5837
                if (single_count <= 4 && double_count == 0)
5838
                        strcpy (atom[i].atype, "P3 ");
5839
                if (double_count == 2)
5840
                        strcpy (atom[i].atype, "P3D");
5841
             }
5842
            if (!strcmp (atom[i].element, "S ")) {
6785 bpr 5843
              if (double_count == 1 && single_count == 0)
14179 bpr 5844
                      strcpy (atom[i].atype, "S2 ");
6785 bpr 5845
              if (double_count == 0)
14179 bpr 5846
                      strcpy (atom[i].atype, "S3 ");
6785 bpr 5847
              if (double_count == 1 && single_count > 0)
14179 bpr 5848
                      strcpy (atom[i].atype, "SO ");
6785 bpr 5849
              if (double_count == 2 && single_count > 0)
14179 bpr 5850
                      strcpy (atom[i].atype, "SO2");
6785 bpr 5851
            }
5852
          /* further atom types should go here */
14179 bpr 5853
          }
5854
  }
6785 bpr 5855
}
5856
 
14179 bpr 5857
static void chk_arom ()
6785 bpr 5858
{
5859
  int i, j, pi_count, ring_size, b, a1, a2;     /* v0.3n */
5860
  ringpath_type testring;
5861
  int a_ref, a_prev, a_next, b_bk, b_fw, b_exo;
5862
  char bt_bk, bt_fw;
5863
  boolean ar_bk, ar_fw, ar_exo; /* new in v0.3 */
5864
  boolean conj_intr, ko, aromatic, aromatic_bt; /* v0.3n */
5865
  int n_db, n_sb, n_ar;
5866
  boolean cumul;
5867
  int exo_mC;                   /* v0.3j */
5868
  int arom_pi_diff;             /* v0.3j */
5869
  int FORLIM;
5870
 
5871
  if (n_rings < 1)
5872
    return;
5873
  FORLIM = n_rings;
5874
  /* first, do a very quick check for benzene, pyridine, etc. */
14179 bpr 5875
  for (i = 0; i < FORLIM; i++) {
5876
    ring_size = ringprop[i].size;
5877
    if (ring_size == 6) {
5878
            memset (testring, 0, sizeof (ringpath_type));
5879
            for (j = 0; j < ring_size; j++)
5880
              testring[j] = ring[i][j];
18544 georgesk 5881
            cumul = isfalse;
14179 bpr 5882
            n_sb = 0;
5883
            n_db = 0;
5884
            n_ar = 0;
5885
            a_prev = testring[ring_size - 1];
5886
            for (j = 1; j <= ring_size; j++) {
6785 bpr 5887
              a_ref = testring[j - 1];
5888
              if (j < ring_size)
14179 bpr 5889
               a_next = testring[j];
6785 bpr 5890
              else
14179 bpr 5891
               a_next = testring[0];
6785 bpr 5892
              b_bk = get_bond (a_prev, a_ref);
5893
              b_fw = get_bond (a_ref, a_next);
5894
              bt_bk = bond[b_bk - 1].btype;
5895
              bt_fw = bond[b_fw - 1].btype;
5896
              if (bt_fw == 'S')
14179 bpr 5897
                n_sb++;
6785 bpr 5898
              if (bt_fw == 'D')
14179 bpr 5899
                n_db++;
6785 bpr 5900
              if (bt_fw == 'A')
14179 bpr 5901
                      n_ar++;
6785 bpr 5902
              if (bt_fw != 'A' && bt_bk == bt_fw)
18544 georgesk 5903
                      cumul = istrue;
6785 bpr 5904
              a_prev = a_ref;
5905
            }
18544 georgesk 5906
            if (n_ar == 6 || (n_sb == 3 && n_db == 3 && cumul == isfalse)) {
14179 bpr 5907
              /* this ring is aromatic */
6785 bpr 5908
              a_prev = testring[ring_size - 1];
14179 bpr 5909
              for (j = 0; j < ring_size; j++) {
5910
                      a_ref = testring[j];
5911
                      b_bk = get_bond (a_prev, a_ref);
18544 georgesk 5912
                      bond[b_bk - 1].arom = istrue;
14179 bpr 5913
                      a_prev = a_ref;
5914
                    }
18544 georgesk 5915
              ringprop[i].arom = istrue;
6785 bpr 5916
            }
14179 bpr 5917
          }
5918
  }
6785 bpr 5919
  FORLIM = n_rings;
14179 bpr 5920
  for (i = 1; i <= FORLIM; i++) {
18544 georgesk 5921
    if (ringprop[i - 1].arom == isfalse) {
14179 bpr 5922
            /* do the hard work only for those rings which are not yet flagged aromatic */
5923
            memset (testring, 0, sizeof (ringpath_type));
5924
            ring_size = ringprop[i - 1].size;   /* v0.3j */
5925
            for (j = 0; j < ring_size; j++)     /* v0.3j */
5926
              testring[j] = ring[i - 1][j];
5927
            pi_count = 0;
5928
            arom_pi_diff = 0;   /* v0.3j */
5929
      /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
18544 georgesk 5930
            ko = isfalse;
14179 bpr 5931
            a_prev = testring[ring_size - 1];
5932
            for (j = 1; j <= ring_size; j++) {
6785 bpr 5933
              a_ref = testring[j - 1];
5934
              if (j < ring_size)
14179 bpr 5935
                a_next = testring[j];
6785 bpr 5936
              else
14179 bpr 5937
                a_next = testring[0];
6785 bpr 5938
              b_bk = get_bond (a_prev, a_ref);
5939
              b_fw = get_bond (a_ref, a_next);
5940
              bt_bk = bond[b_bk - 1].btype;
5941
              bt_fw = bond[b_fw - 1].btype;
5942
              ar_bk = bond[b_bk - 1].arom;
5943
              ar_fw = bond[b_fw - 1].arom;
18544 georgesk 5944
              if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == isfalse && ar_fw == isfalse) {
14179 bpr 5945
                /* first, assume the worst case (interrupted conjugation) */
18544 georgesk 5946
                conj_intr = istrue;
14179 bpr 5947
                /* conjugation can be restored by hetero atoms */
5948
                if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
5949
                    !strcmp (atom[a_ref - 1].atype, "S3 ") ||
5950
                          !strcmp (atom[a_ref - 1].element, "N ") ||
5951
                          !strcmp (atom[a_ref - 1].element, "SE")) {
18544 georgesk 5952
                        conj_intr = isfalse;
14179 bpr 5953
                        pi_count += 2;  /* lone pair adds for 2 pi electrons */
5954
                      }
5955
                      /* conjugation can be restored by a formal charge at a methylene group */
6785 bpr 5956
                      if (!strcmp (atom[a_ref - 1].element, "C ") &&
14179 bpr 5957
                          atom[a_ref - 1].formal_charge != 0) {
18544 georgesk 5958
                          conj_intr = isfalse;
14179 bpr 5959
                          pi_count -= atom[a_ref - 1].formal_charge;
5960
                          /* neg. charge increases pi_count! */
5961
                      }
5962
                      /* conjugation can be restored by carbonyl groups etc. */
5963
                      if (is_oxo_C (a_ref) || is_thioxo_C (a_ref) |
5964
                          is_exocyclic_imino_C (a_ref, i))
18544 georgesk 5965
                        conj_intr = isfalse;
14179 bpr 5966
                      /* conjugation can be restored by exocyclic C=C double bond, */
5967
                      /* adds 2 pi electrons to 5-membered rings, not to 7-membered rings (CAUTION!) */
5968
                      /* apply only to non-aromatic exocyclic C=C bonds */
6785 bpr 5969
                      exo_mC = find_exocyclic_methylene_C (a_ref, i);   /* v0.3j */
14179 bpr 5970
                      if (exo_mC > 0 && (ring_size & 1)) {              /* v0.3j */
5971
                          b_exo = get_bond (a_ref, exo_mC);     /* v0.3j  */
5972
                          ar_exo = bond[b_exo - 1].arom;
5973
                        if (((ring_size - 1) & 3) == 0) {       /* 5-membered rings and related */
18544 georgesk 5974
                                conj_intr = isfalse;
14179 bpr 5975
                                pi_count += 2;
5976
                              }
5977
                        else {
5978
                                if (!ar_exo)
18544 georgesk 5979
                                  conj_intr = isfalse;
14179 bpr 5980
                              }
5981
                      }
5982
                      /* 7-membered rings and related */
5983
                      /* if conjugation is still interrupted ==> knock-out */
5984
                      if (conj_intr)
18544 georgesk 5985
                        ko = istrue;
6785 bpr 5986
                    }
14179 bpr 5987
              else {
18544 georgesk 5988
                      if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == istrue && ar_fw == istrue) {
14179 bpr 5989
                        if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
5990
                                  !strcmp (atom[a_ref - 1].atype, "S3 ") ||
5991
                                  !strcmp (atom[a_ref - 1].element, "N ") ||
5992
                                  !strcmp (atom[a_ref - 1].element, "SE"))
5993
                                pi_count += 2;  /* lone pair adds for 2 pi electrons */
5994
                        if (!strcmp (atom[a_ref - 1].element, "C ") &&
5995
                                  atom[a_ref - 1].formal_charge != 0)
5996
                                pi_count -= atom[a_ref - 1].formal_charge;
5997
                          /* neg. charge increases pi_count! */
5998
                        exo_mC = find_exocyclic_methylene_C (a_ref, i); /* v0.3j */
5999
                        if (exo_mC > 0 && (ring_size & 1))  {   /* v0.3j */
6000
                                b_exo = get_bond (a_ref, exo_mC);       /* v0.3j */
6001
            /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6002
                                if (((ring_size - 1) & 3) == 0)
6003
                                  /* 5-membered rings and related */
6004
                                  pi_count += 2;
6005
                              }
6006
                      }
6007
                      else {
6008
                  pi_count++;   /* v0.3j; adjustment for bridgehead N: see below */
18544 georgesk 6009
                  if (bt_bk == 'S' && bt_fw == 'S' && ((ar_bk == istrue && ar_fw == isfalse) ||
6010
                                  (ar_bk == isfalse && ar_fw == istrue))) {
14179 bpr 6011
                                /* v0.3j; if a bridgehead N were not aromatic, it could  */
6012
                                /* contribute 2 pi electrons --> try also this variant */
6013
                                /* (example: CAS 32278-54-9) */
6014
                                if (!strcmp (atom[a_ref - 1].element, "N ")) {
6015
                                  arom_pi_diff++;
6016
                                  /* any other case: increase pi count by one electron */
6017
                                }
6018
                              }
6019
                      }
6785 bpr 6020
                    }
14179 bpr 6021
        /* last command: */
6022
        a_prev = a_ref;
6785 bpr 6023
            }                   /* for j := 1 to ring_size */
14179 bpr 6024
            /* now we can draw our conclusion */
6025
            /*if not ((ko) or (odd(pi_count))) then */
6026
            if (!ko) {
6027
              /* v0.3j; odd pi_count might be compensated by arom_pi_diff */
6028
                          /* apply Hueckel's rule */
6785 bpr 6029
              if (labs (ring_size - pi_count) < 2 &&
14179 bpr 6030
                        (((pi_count - 2) & 3) == 0 || ((pi_count + arom_pi_diff - 2) & 3) == 0)) {
6031
                      /* this ring is aromatic */
18544 georgesk 6032
                      ringprop[i - 1].arom = istrue;
14179 bpr 6033
                      /* now mark _all_ bonds in the ring as aromatic */
6034
                      a_prev = testring[ring_size - 1];
6035
                      for (j = 0; j < ring_size; j++) {
6036
                        a_ref = testring[j];
18544 georgesk 6037
                        bond[get_bond (a_prev, a_ref) - 1].arom = istrue;
14179 bpr 6038
                        a_prev = a_ref;
6039
                      }
6785 bpr 6040
                    }
6041
            }
14179 bpr 6042
          }
6043
  }                             /* (for i := 1 to n_rings) */
6785 bpr 6044
  FORLIM = n_bonds;
6045
  /* finally, mark all involved atoms as aromatic */
14179 bpr 6046
  for (i = 0; i < FORLIM; i++) {
6047
    if (bond[i].arom) {
6048
            a1 = bond[i].a1;    /* v0.3n */
6049
            a2 = bond[i].a2;    /* v0.3n */
18544 georgesk 6050
            atom[a1 - 1].arom = istrue;
6051
            atom[a2 - 1].arom = istrue;
14179 bpr 6052
            /* v0.3n: update atom types if applicable (C and N) */
6053
            if (!strcmp (atom[a1 - 1].element, "C "))
6054
              strcpy (atom[a1 - 1].atype, "CAR");
6055
            if (!strcmp (atom[a2 - 1].element, "C "))
6056
              strcpy (atom[a2 - 1].atype, "CAR");
6057
            if (!strcmp (atom[a1 - 1].element, "N "))
6058
              strcpy (atom[a1 - 1].atype, "NAR");
6059
            if (!strcmp (atom[a2 - 1].element, "N "))
6060
              strcpy (atom[a2 - 1].atype, "NAR");
6061
          }
6062
  }
6785 bpr 6063
  FORLIM = n_rings;
6064
  /* update aromaticity information in ringprop */
6065
  /* new in v0.3n: accept rings as aromatic if all bonds are of type 'A' */
14179 bpr 6066
  for (i = 0; i < FORLIM; i++) {
6067
    memcpy (testring, ring[i], sizeof (ringpath_type));
6068
    /*ring_size := path_length(testring); */
6069
    ring_size = ringprop[i].size;       /* v0.3j */
18544 georgesk 6070
    aromatic = istrue;
6071
    aromatic_bt = istrue;       /* v0.3n */
14179 bpr 6072
    a_prev = testring[ring_size - 1];
6073
    for (j = 0; j < ring_size; j++) {
6074
            a_ref = testring[j];
6075
            b = get_bond (a_prev, a_ref);       /* v0.3n */
6076
            if (!bond[b - 1].arom)
18544 georgesk 6077
              aromatic = isfalse;
14179 bpr 6078
            if (bond[b - 1].btype != 'A')       /* v0.3n */
18544 georgesk 6079
              aromatic_bt = isfalse;
14179 bpr 6080
            a_prev = a_ref;
6081
          }
6082
    if (aromatic_bt && !aromatic) {                     /* v0.3n: update aromaticity flag */
6083
            a_prev = testring[ring_size - 1];
6084
            for (j = 0; j < ring_size; j++) {
6785 bpr 6085
              a_ref = testring[j];
6086
              b = get_bond (a_prev, a_ref);
18544 georgesk 6087
              bond[b - 1].arom = istrue;
6785 bpr 6088
              if (!strcmp (atom[a_ref - 1].element, "C "))
14179 bpr 6089
                      strcpy (atom[a_ref - 1].atype, "CAR");
6785 bpr 6090
              if (!strcmp (atom[a_ref - 1].element, "N "))
14179 bpr 6091
                      strcpy (atom[a_ref - 1].atype, "NAR");
6785 bpr 6092
              a_prev = a_ref;
6093
            }
18544 georgesk 6094
            aromatic = istrue;
14179 bpr 6095
          }                     /* end v0.3n block   */
6096
    if (aromatic)
18544 georgesk 6097
            ringprop[i].arom = istrue;
14179 bpr 6098
    else
18544 georgesk 6099
            ringprop[i].arom = isfalse;
14179 bpr 6100
  }
6785 bpr 6101
}
6102
 
14179 bpr 6103
static void write_mol ()
6785 bpr 6104
{
6105
  int i, j;
6106
  ringpath_type testring;
6107
  int ring_size, FORLIM;
6108
 
6109
  /*aromatic : boolean; */
6110
  /*a_prev, a_ref : integer; */
6111
  if (progmode == pmCheckMol)
6112
    printf ("Molecule name: %s\n", molname);
6113
  else
6114
    printf ("Molecule name (haystack): %s\n", molname);
6115
  printf ("atoms: %d  bonds: %d  rings: %d\n", n_atoms, n_bonds, n_rings);
6116
  if (n_atoms < 1)
6117
    return;
6118
  if (n_bonds < 1)
6119
    return;
6120
  FORLIM = n_atoms;
14179 bpr 6121
  for (i = 1; i <= FORLIM; i++) {
6122
    if (i < 10) putchar (' ');
6123
    if (i < 100) putchar (' ');
6124
    if (i < 1000) putchar (' ');
6125
    printf ("%d %s %s %f %f ",
6785 bpr 6126
              i, atom[i - 1].element, atom[i - 1].atype, atom[i - 1].x,
6127
              atom[i - 1].y);
14179 bpr 6128
    printf ("%f", atom[i - 1].z);
6129
    printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6130
            atom[i - 1].neighbor_count, atom[i - 1].Hexp, atom[i - 1].Htot);
6131
    if (atom[i - 1].formal_charge != 0)
6132
            printf ("  charge: %d", atom[i - 1].formal_charge);
6133
    putchar ('\n');
6134
  }
6785 bpr 6135
  FORLIM = n_bonds;
14179 bpr 6136
  for (i = 1; i <= FORLIM; i++) {
6137
    if (i < 10) putchar (' ');
6138
    if (i < 100) putchar (' ');
6139
    if (i < 1000) putchar (' ');
6140
    printf ("%d %d %d %c", i, bond[i - 1].a1, bond[i - 1].a2, bond[i - 1].btype);
6141
    if (bond[i - 1].ring_count > 0)
6142
            printf (", contained in %d ring(s)", bond[i - 1].ring_count);
6143
    if (bond[i - 1].arom) printf (" (aromatic) ");
6144
    putchar ('\n');
6145
  }
6785 bpr 6146
  if (n_rings <= 0)
6147
    return;
6148
  FORLIM = n_rings;
14179 bpr 6149
  for (i = 0; i < FORLIM; i++) {
6150
    printf ("ring %d: ", i + 1);
18544 georgesk 6151
    /*aromatic := istrue; */
14179 bpr 6152
    memset (testring, 0, sizeof (ringpath_type));
6153
    ring_size = ringprop[i].size;       /* v0.3j */
6154
    /*for j := 1 to max_ringsize do if ring^[i,j] > 0 then testring[j] := ring^[i,j]; */
6155
    for (j = 0; j < ring_size; j++)     /* v0.3j */
6156
            testring[j] = ring[i][j];
6157
    /*ring_size := path_length(testring); */
6158
    /*a_prev := testring[ring_size]; */
6159
    for (j = 0; j < ring_size; j++) {
6160
            printf ("%d ", testring[j]);
6161
            /*a_ref := testring[j]; */
18544 georgesk 6162
            /*if (not bond^[get_bond(a_prev,a_ref)].arom) then aromatic := isfalse; */
14179 bpr 6163
            /*a_prev := a_ref; */
6164
          }
6165
    /*if aromatic then write(' (aromatic)'); */
6166
    if (ringprop[i].arom) printf (" (aromatic)");
6167
    if (ringprop[i].envelope) printf (" (env)");
6168
    putchar ('\n');
6169
  }
6785 bpr 6170
}
6171
 
14179 bpr 6172
static void write_needle_mol ()
6785 bpr 6173
{
6174
  int i, j;
6175
  ringpath_type testring;
6176
  int ring_size;
6177
  boolean aromatic;
6178
  int a_prev, a_ref, FORLIM;
6179
 
6180
  printf ("Molecule name (needle): %s\n", ndl_molname);
6181
  printf ("atoms: %d  bonds: %d  rings: %d\n",
6182
          ndl_n_atoms, ndl_n_bonds, ndl_n_rings);
6183
  if (ndl_n_atoms < 1)
6184
    return;
6185
  if (ndl_n_bonds < 1)
6186
    return;
6187
  FORLIM = ndl_n_atoms;
14179 bpr 6188
  for (i = 1; i <= FORLIM; i++) {
6189
    if (i < 10) putchar (' ');
6190
    if (i < 100) putchar (' ');
6191
    if (i < 1000) putchar (' ');
6192
    printf ("%d %s %s %f %f ",
6785 bpr 6193
              i, ndl_atom[i - 1].element, ndl_atom[i - 1].atype,
6194
              ndl_atom[i - 1].x, atom[i - 1].y);
14179 bpr 6195
    printf ("%f", ndl_atom[i - 1].z);
6196
    printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6197
            ndl_atom[i - 1].neighbor_count, ndl_atom[i - 1].Hexp,
6198
            ndl_atom[i - 1].Htot);
6199
    if (ndl_atom[i - 1].formal_charge != 0)
6200
            printf ("  charge: %d", ndl_atom[i - 1].formal_charge);
6201
    putchar ('\n');
6202
  }
6785 bpr 6203
  FORLIM = ndl_n_bonds;
14179 bpr 6204
  for (i = 1; i <= FORLIM; i++) {
6205
    if (i < 10) putchar (' ');
6206
    if (i < 100) putchar (' ');
6207
    if (i < 1000) putchar (' ');
6208
    printf ("%d %d %d %c", i, ndl_bond[i - 1].a1, ndl_bond[i - 1].a2,
6785 bpr 6209
              ndl_bond[i - 1].btype);
14179 bpr 6210
    if (ndl_bond[i - 1].ring_count > 0)
6211
            printf (", contained in %d ring(s)", ndl_bond[i - 1].ring_count);
6212
    if (ndl_bond[i - 1].arom)
6213
            printf (" (aromatic) ");
6214
    putchar ('\n');
6215
  }
6785 bpr 6216
  if (ndl_n_rings <= 0)
6217
    return;
6218
  FORLIM = ndl_n_rings;
14179 bpr 6219
  for (i = 0; i < FORLIM; i++) {
18544 georgesk 6220
    aromatic = istrue;
14179 bpr 6221
    memset (testring, 0, sizeof (ringpath_type));
6222
    for (j = 0; j < max_ringsize; j++) {
6223
            if (ndl_ring[i][j] > 0)
6224
              testring[j] = ndl_ring[i][j];
6225
          }
6226
    ring_size = path_length (testring);
6227
    printf ("ring %d: ", i + 1);
6228
    a_prev = testring[ring_size - 1];
6229
    for (j = 0; j < ring_size; j++) {
6230
            printf ("%d ", testring[j]);
6231
            a_ref = testring[j];
6232
            if (!ndl_bond[get_ndl_bond (a_prev, a_ref) - 1].arom)       /* v0.3k */
18544 georgesk 6233
              aromatic = isfalse;
14179 bpr 6234
            a_prev = a_ref;
6235
          }
6236
    if (aromatic) printf (" (aromatic)");
6237
    putchar ('\n');
6238
  }
6785 bpr 6239
}
6240
 
17891 bpr 6241
static void chk_so2_deriv (int a_ref)
6785 bpr 6242
{
6243
  int i;
6244
  neighbor_rec nb;
6245
  str2 nb_el;
6246
  int het_count = 0, o_count = 0, or_count = 0, hal_count = 0, n_count = 0,
6247
    c_count = 0;
6248
  int FORLIM;
6249
 
6250
  memset (nb, 0, sizeof (neighbor_rec));
6251
  if (strcmp (atom[a_ref - 1].atype, "SO2"))
6252
    return;
6253
  get_neighbors (nb, a_ref);
6254
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6255
  for (i = 0; i < FORLIM; i++) {
6256
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6257
            strcpy (nb_el, atom[nb[i] - 1].element);
6258
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6259
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
6260
                && strcmp (nb_el, "LP"))
6261
              /* added 'D ' in v0.3n */
6262
              het_count++;
6263
            if (!strcmp (nb_el, "O ")) {
6785 bpr 6264
              o_count++;
6265
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
14179 bpr 6266
                      or_count++;
6785 bpr 6267
            }
14179 bpr 6268
            if (!strcmp (nb_el, "N "))
6269
              n_count++;
6270
            if (!strcmp (nb_el, "C "))
6271
              c_count++;
6272
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6273
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6274
                || !strcmp (nb_el, "AT"))
6275
              hal_count++;
6276
          }
6277
  }
6278
  if (het_count == 2) {                                 /* sulfuric acid derivative */
18544 georgesk 6279
    fg[fg_sulfuric_acid_deriv - 1] = istrue;
14179 bpr 6280
    if (o_count == 2) {
6281
            if (or_count == 0)
18544 georgesk 6282
              fg[fg_sulfuric_acid - 1] = istrue;
14179 bpr 6283
            if (or_count == 1)
18544 georgesk 6284
              fg[fg_sulfuric_acid_monoester - 1] = istrue;
14179 bpr 6285
            if (or_count == 2)
18544 georgesk 6286
              fg[fg_sulfuric_acid_diester - 1] = istrue;
14179 bpr 6287
          }
6288
    if (o_count == 1) {
6289
            if (or_count == 1 && n_count == 1)
18544 georgesk 6290
              fg[fg_sulfuric_acid_amide_ester - 1] = istrue;
14179 bpr 6291
            if (or_count == 0 && n_count == 1)
18544 georgesk 6292
              fg[fg_sulfuric_acid_amide - 1] = istrue;
14179 bpr 6293
          }
6294
    if (n_count == 2)
18544 georgesk 6295
            fg[fg_sulfuric_acid_diamide - 1] = istrue;
14179 bpr 6296
    if (hal_count > 0)
18544 georgesk 6297
            fg[fg_sulfuryl_halide - 1] = istrue;
14179 bpr 6298
  }
6299
  if (het_count == 1 && c_count == 1) {                                 /* sulfonic acid derivative */
18544 georgesk 6300
    fg[fg_sulfonic_acid_deriv - 1] = istrue;
14179 bpr 6301
    if (o_count == 1 && or_count == 0)
18544 georgesk 6302
            fg[fg_sulfonic_acid - 1] = istrue;
14179 bpr 6303
    if (o_count == 1 && or_count == 1)
18544 georgesk 6304
            fg[fg_sulfonic_acid_ester - 1] = istrue;
14179 bpr 6305
    if (n_count == 1)
18544 georgesk 6306
            fg[fg_sulfonamide - 1] = istrue;
14179 bpr 6307
    if (hal_count == 1)
18544 georgesk 6308
            fg[fg_sulfonyl_halide - 1] = istrue;
14179 bpr 6309
  }
6785 bpr 6310
  if (het_count == 0 && c_count == 2)   /* sulfone */
18544 georgesk 6311
    fg[fg_sulfone - 1] = istrue;
6785 bpr 6312
}
6313
 
17891 bpr 6314
static void chk_p_deriv (int a_ref)
6785 bpr 6315
{
6316
  int i;
6317
  neighbor_rec nb;
6318
  str2 nb_el, dbl_het;
6319
  int het_count;
6320
  int oh_count = 0, or_count = 0, hal_count = 0, n_count = 0, c_count = 0;
6321
  int FORLIM;
6322
 
6323
  if (strcmp (atom[a_ref - 1].element, "P "))
6324
    return;
6325
  memset (nb, 0, sizeof (neighbor_rec));
6326
  get_neighbors (nb, a_ref);
6327
  *dbl_het = '\0';
14179 bpr 6328
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 6329
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6330
  for (i = 0; i < FORLIM; i++) {
6331
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
6332
            strcpy (dbl_het, atom[nb[i] - 1].element);
6333
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6334
            strcpy (nb_el, atom[nb[i] - 1].element);
6335
            if (!strcmp (nb_el, "C "))
6336
              c_count++;
6337
            if (is_hydroxy (a_ref, nb[i]))
6338
              oh_count++;
6339
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6340
              or_count++;
6341
            if (!strcmp (nb_el, "N "))
6342
              n_count++;
6343
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6344
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6345
                || !strcmp (nb_el, "AT"))
6346
              hal_count++;
6347
          }
6348
  }
6785 bpr 6349
  het_count = oh_count + or_count + hal_count + n_count;
6350
  if (!strcmp (atom[a_ref - 1].atype, "P3D") ||
14179 bpr 6351
      !strcmp (atom[a_ref - 1].atype, "P4 ")) {
6352
    if (!strcmp (dbl_het, "O ")) {
6353
            if (c_count == 0) {
18544 georgesk 6354
              fg[fg_phosphoric_acid_deriv - 1] = istrue;
6785 bpr 6355
              if (oh_count == 3)
18544 georgesk 6356
                fg[fg_phosphoric_acid - 1] = istrue;
6785 bpr 6357
              if (or_count > 0)
18544 georgesk 6358
                fg[fg_phosphoric_acid_ester - 1] = istrue;
6785 bpr 6359
              if (hal_count > 0)
18544 georgesk 6360
                fg[fg_phosphoric_acid_halide - 1] = istrue;
6785 bpr 6361
              if (n_count > 0)
18544 georgesk 6362
                fg[fg_phosphoric_acid_amide - 1] = istrue;
6785 bpr 6363
            }
14179 bpr 6364
            if (c_count == 1) {
18544 georgesk 6365
              fg[fg_phosphonic_acid_deriv - 1] = istrue;
6785 bpr 6366
              if (oh_count == 2)
18544 georgesk 6367
                fg[fg_phosphonic_acid - 1] = istrue;
6785 bpr 6368
              if (or_count > 0)
18544 georgesk 6369
                fg[fg_phosphonic_acid_ester - 1] = istrue;
6370
              /*if (hal_count > 0)  then fg[fg_phosphonic_acid_halide] := istrue;             */
6371
              /*if (n_count > 0)    then fg[fg_phosphonic_acid_amide]  := istrue; */
6785 bpr 6372
            }
14179 bpr 6373
            if (c_count == 3)
18544 georgesk 6374
              fg[fg_phosphinoxide - 1] = istrue;
14179 bpr 6375
          }
6376
    if (!strcmp (dbl_het, "S ")) {
6377
      if (c_count == 0) {
18544 georgesk 6378
        fg[fg_thiophosphoric_acid_deriv - 1] = istrue;
14179 bpr 6379
        if (oh_count == 3)
18544 georgesk 6380
            fg[fg_thiophosphoric_acid - 1] = istrue;
14179 bpr 6381
        if (or_count > 0)
18544 georgesk 6382
            fg[fg_thiophosphoric_acid_ester - 1] = istrue;
14179 bpr 6383
        if (hal_count > 0)
18544 georgesk 6384
            fg[fg_thiophosphoric_acid_halide - 1] = istrue;
14179 bpr 6385
        if (n_count > 0)
18544 georgesk 6386
            fg[fg_thiophosphoric_acid_amide - 1] = istrue;
14179 bpr 6387
      }
6785 bpr 6388
    }
14179 bpr 6389
  }
18544 georgesk 6390
  /*  if (atom^[a_ref].atype = 'P4 ') then fg[fg_phosphoric_acid_deriv] := istrue; */
6785 bpr 6391
  if (strcmp (atom[a_ref - 1].atype, "P3 "))    /* changed P3D into P3 in v0.3b */
6392
    return;
6393
  if (c_count == 3 && het_count == 0)
18544 georgesk 6394
    fg[fg_phosphine - 1] = istrue;
6785 bpr 6395
  if (c_count == 3 && oh_count == 1)
18544 georgesk 6396
    fg[fg_phosphinoxide - 1] = istrue;
6785 bpr 6397
}
6398
 
17891 bpr 6399
static void chk_b_deriv (int a_ref)
6785 bpr 6400
{
6401
  int i;
6402
  neighbor_rec nb;
6403
  str2 nb_el;
6404
  int het_count = 0, oh_count = 0, or_count = 0, hal_count = 0, n_count = 0,
6405
    c_count = 0;
6406
  int FORLIM;
6407
 
6408
  if (strcmp (atom[a_ref - 1].element, "B "))
6409
    return;
6410
  memset (nb, 0, sizeof (neighbor_rec));
6411
  get_neighbors (nb, a_ref);
6412
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6413
  for (i = 0; i < FORLIM; i++) {
6414
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6415
            strcpy (nb_el, atom[nb[i] - 1].element);
6416
            if (!strcmp (nb_el, "C "))
6417
              c_count++;
6418
            else
14249 bpr 6419
              if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP"))
14179 bpr 6420
                /* v0.3n: D */
14249 bpr 6421
                het_count++;
6422
            if (is_hydroxy (a_ref, nb[i]))
6423
              oh_count++;
6424
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6425
              /* fixed in v0.3b */
6426
              or_count++;
6427
            if (!strcmp (nb_el, "N "))
6428
              n_count++;
6429
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6430
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6431
                || !strcmp (nb_el, "AT"))
6432
              hal_count++;
14179 bpr 6433
          }
6434
  }
6785 bpr 6435
  het_count = oh_count + or_count + hal_count + n_count;
6436
  /* fixed in v0.3b */
6437
  if (c_count != 1 || het_count != 2)
6438
    return;
18544 georgesk 6439
  fg[fg_boronic_acid_deriv - 1] = istrue;
6785 bpr 6440
  if (oh_count == 2)
18544 georgesk 6441
    fg[fg_boronic_acid - 1] = istrue;
6785 bpr 6442
  if (or_count > 0)
18544 georgesk 6443
    fg[fg_boronic_acid_ester - 1] = istrue;
6785 bpr 6444
}
6445
 
17891 bpr 6446
static void chk_ammon (int a_ref)
6785 bpr 6447
{
6448
  int i;
6449
  neighbor_rec nb;
6450
  str2 nb_el;
6451
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
6452
  char bt;                      /* v0.3k */
6453
  float bo_sum = 0.0;
6454
  boolean ha;
6455
  int FORLIM;
6456
 
6457
  memset (nb, 0, sizeof (neighbor_rec));
6458
  if (strcmp (atom[a_ref - 1].atype, "N3+")
6459
      && atom[a_ref - 1].formal_charge == 0)
6460
    return;
6461
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
6462
    return;
6463
  get_neighbors (nb, a_ref);
6464
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6465
  for (i = 0; i < FORLIM; i++) {
6466
    bt = bond[get_bond (a_ref, nb[i]) - 1].btype;       /* v0.3k */
6467
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
6468
    ha = atom[nb[i] - 1].heavy; /* v0.3k */
6469
    if (bt == 'S') {
6470
            if (ha)
6471
              bo_sum += 1.0;
6472
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6473
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")) {
6474
                /* added 'D ' in v0.3n */
6785 bpr 6475
              het_count++;
14179 bpr 6476
              if (!strcmp (nb_el, "O ")) {
6477
                      o_count++;
6478
                      if (atom[nb[i] - 1].neighbor_count > 1)
6479
                        or_count++;
6480
                    }
6785 bpr 6481
            }
14179 bpr 6482
            if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
6483
                is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
6484
              /* v0.3k */
6485
              r_count++;
6486
          }
6487
    if (bt == 'D') {
6488
            if (ha)
6489
              bo_sum += 2.0;
6490
            if (strcmp (nb_el, "C ")) {
6785 bpr 6491
              het_count += 2;
6492
              if (!strcmp (nb_el, "O "))
14179 bpr 6493
                      o_count += 2;
6785 bpr 6494
            }
14179 bpr 6495
            if (!strcmp (nb_el, "C "))
6496
              r_count++;
6497
          }
6498
    if (bt == 'A' && ha)
6499
            bo_sum += 1.5;
6500
  }                             /* v0.3k: corrected end of "for ..." loop */
6785 bpr 6501
  if (het_count == 0 && r_count == 4)
18544 georgesk 6502
    fg[fg_quart_ammonium - 1] = istrue;
6785 bpr 6503
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
6504
    return;
6505
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
18544 georgesk 6506
    fg[fg_n_oxide - 1] = istrue;        /* finds only aliphatic N-oxides! */
6785 bpr 6507
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
18544 georgesk 6508
      atom[a_ref - 1].arom == istrue)
6509
    fg[fg_quart_ammonium - 1] = istrue;
6785 bpr 6510
}
6511
 
17891 bpr 6512
static void swap_atoms (int *a1, int *a2)
6785 bpr 6513
{
6514
  int a_tmp;
6515
 
6516
  a_tmp = *a1;
6517
  *a1 = *a2;
6518
  *a2 = a_tmp;
6519
}
6520
 
17891 bpr 6521
static void orient_bond (int *a1, int *a2)
6785 bpr 6522
{
6523
  str2 a1_el, a2_el;
6524
 
6525
  strcpy (a1_el, atom[*a1 - 1].element);
6526
  strcpy (a2_el, atom[*a2 - 1].element);
6527
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
6528
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
6529
    /* v0.3n: D */
6530
    return;
6531
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
6532
    swap_atoms (a1, a2);
14179 bpr 6533
  if (!strcmp (a2_el, a1_el)) {
6534
    if (hetbond_count (*a1) > hetbond_count (*a2))
6785 bpr 6535
            swap_atoms (a1, a2);
14179 bpr 6536
  }
6537
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el)) {
6538
    if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O ")) {
6539
            if (!strcmp (a1_el, "O "))
6540
              swap_atoms (a1, a2);
6541
          }
6542
  }
6543
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el)) {
6785 bpr 6544
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
14179 bpr 6545
              atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
6546
          swap_atoms (a1, a2);
6547
  }
6785 bpr 6548
}
6549
 
17891 bpr 6550
static void chk_imine (int a_ref, int a_view)
6785 bpr 6551
{
6552
  /* a_ref = C, a_view = N */
6553
  int i;
6554
  neighbor_rec nb;
6555
  str2 nb_el;
6788 kbelabas 6556
  int a_het = 0, a_c;
6785 bpr 6557
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
6558
  int FORLIM;
6559
 
6560
  /* v0.3k */
14179 bpr 6561
  if (atom[a_view - 1].neighbor_count == 1) {
18544 georgesk 6562
      if (atom[a_ref - 1].arom == isfalse)
6563
        fg[fg_imine - 1] = istrue;
6785 bpr 6564
      return;
6565
    }
6566
  memset (nb, 0, sizeof (neighbor_rec));
6567
  get_neighbors (nb, a_view);
6568
  if (atom[a_view - 1].neighbor_count <= 1)
6569
    return;
6570
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6571
  for (i = 0; i < FORLIM; i++) {
6572
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')){
6573
            strcpy (nb_el, atom[nb[i] - 1].element);
6574
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6575
              a_c = nb[i];
6576
              c_count++;
6577
            }
14179 bpr 6578
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")) {
6785 bpr 6579
              a_het = nb[i];
6580
              het_count++;
6581
            }
14179 bpr 6582
            if ((!strcmp (nb_el, "O ")
6785 bpr 6583
               && atom[nb[i] - 1].neighbor_count ==
18544 georgesk 6584
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == isfalse))
14179 bpr 6585
              /* v0.3k */
6586
              o_count++;
6587
          }
6588
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')){
6589
      /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
6590
            strcpy (nb_el, atom[nb[i] - 1].element);
6591
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ") || !strcmp (nb_el, "S ")) {
6785 bpr 6592
              a_het = nb[i];    /* v0.3m */
6593
              het_count++;
6594
            }
14179 bpr 6595
            if ((!strcmp (nb_el, "O ")
6596
                && atom[nb[i] - 1].neighbor_count == 1) &&
18544 georgesk 6597
                  (bond[get_bond (a_view, nb[i]) - 1].arom == isfalse))
14179 bpr 6598
              /* v0.3k */
6599
              o_count++;
6600
          }
6601
  }
6602
  if (c_count == 1) {
6603
    if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
6604
              is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
18544 georgesk 6605
              && atom[a_ref - 1].arom == isfalse && het_count == 0)
6785 bpr 6606
            /* v0.3k */
18544 georgesk 6607
            fg[fg_imine - 1] = istrue;
14179 bpr 6608
  }
6609
  if (het_count == 1) {
6610
    strcpy (nb_el, atom[a_het - 1].element);
6611
    if (!strcmp (nb_el, "O ")) {
6612
            if (is_hydroxy (a_view, a_het))
18544 georgesk 6613
              fg[fg_oxime - 1] = istrue;
6785 bpr 6614
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
6615
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
18544 georgesk 6616
            fg[fg_oxime_ether - 1] = istrue;
14179 bpr 6617
          }
6618
    if (!strcmp (nb_el, "N ")) {
6619
            if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
6620
                is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,a_het) |
6621
                is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
18544 georgesk 6622
              fg[fg_hydrazone - 1] = istrue;
14179 bpr 6623
            else {
6785 bpr 6624
              memset (nb, 0, sizeof (neighbor_rec));
6625
              get_neighbors (nb, a_het);
14179 bpr 6626
              if (atom[a_het - 1].neighbor_count > 1) {
6627
                      FORLIM = atom[a_het - 1].neighbor_count;
6628
                      for (i = 0; i < FORLIM; i++) {
6629
                        if (nb[i] != a_view) {
6630
                                if (is_carbamoyl (a_het, nb[i]))
18544 georgesk 6631
                                  fg[fg_semicarbazone - 1] = istrue;
14179 bpr 6632
                                if (is_thiocarbamoyl (a_het, nb[i]))
18544 georgesk 6633
                                  fg[fg_thiosemicarbazone - 1] = istrue;
14179 bpr 6634
                              }
6635
                      }
6785 bpr 6636
                    }
6637
            }
14179 bpr 6638
          }
6639
  }                             /* v0.3k: nitro groups in "azi" form */
6785 bpr 6640
  /* check for semicarbazone or thiosemicarbazone */
6641
  if (het_count == 2 && o_count == 2)
18544 georgesk 6642
    fg[fg_nitro_compound - 1] = istrue;
6785 bpr 6643
}
6644
 
17891 bpr 6645
static void chk_carbonyl_deriv (int a_view, int a_ref)
6785 bpr 6646
{
6647
  /* a_view = C */
6648
  int i;
6649
  neighbor_rec nb;
6650
  str2 nb_el;
6651
  int c_count = 0, cn_count = 0;
6652
  char bt;                      /* new in v0.3b */
6653
  int n_db = 0;                 /* new in v0.3b */
6654
  int FORLIM;
6655
 
6656
  memset (nb, 0, sizeof (neighbor_rec));
6657
  get_neighbors (nb, a_view);
6658
  FORLIM = atom[a_view - 1].neighbor_count;
6659
  /* new in v0.3b */
14179 bpr 6660
  for (i = 0; i < FORLIM; i++) {
6661
    bt = bond[get_bond (a_view, nb[i]) - 1].btype;
6662
    if (bt == 'S') {
6663
            strcpy (nb_el, atom[nb[i] - 1].element);
6664
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6665
              if (is_cyano_c (nb[i]))
14179 bpr 6666
                      cn_count++;
6785 bpr 6667
              else
14179 bpr 6668
                      c_count++;
6785 bpr 6669
            }
14179 bpr 6670
          }
6671
    else {
6672
            if (bt == 'D')
6673
              n_db++;
6674
          }
6675
  }
6785 bpr 6676
  /* new in v0.3b */
14179 bpr 6677
  if (is_oxo_C (a_view)) {
18544 georgesk 6678
    fg[fg_carbonyl - 1] = istrue;
14179 bpr 6679
    if (c_count + cn_count < 2) {                       /* new in v0.3b (detection of ketenes) */
6680
            if (n_db <= 1)
18544 georgesk 6681
              fg[fg_aldehyde - 1] = istrue;
14179 bpr 6682
            else
18544 georgesk 6683
              fg[fg_ketene - 1] = istrue;
14179 bpr 6684
          }
6685
    if (c_count == 2) {
6686
            if (atom[a_view - 1].arom)
18544 georgesk 6687
              fg[fg_oxohetarene - 1] = istrue;
14179 bpr 6688
            else
18544 georgesk 6689
              fg[fg_ketone - 1] = istrue;
14179 bpr 6690
          }
6691
    if (cn_count > 0)
18544 georgesk 6692
            fg[fg_acyl_cyanide - 1] = istrue;
14179 bpr 6693
  }
6694
  if (is_thioxo_C (a_view)) {
18544 georgesk 6695
    fg[fg_thiocarbonyl - 1] = istrue;
14179 bpr 6696
    if (c_count < 2)
18544 georgesk 6697
            fg[fg_thioaldehyde - 1] = istrue;
14179 bpr 6698
    if (c_count == 2) {
6699
            if (atom[a_view - 1].arom)
18544 georgesk 6700
              fg[fg_thioxohetarene - 1] = istrue;
14179 bpr 6701
            else
18544 georgesk 6702
              fg[fg_thioketone - 1] = istrue;
14179 bpr 6703
          }
6704
  }
6785 bpr 6705
  if (is_imino_C (a_view))
6706
    chk_imine (a_view, a_ref);
6707
}
6708
 
17891 bpr 6709
static void chk_carboxyl_deriv (int a_view, int a_ref)
6785 bpr 6710
{
6711
  int i;
6712
  neighbor_rec nb;
6713
  str2 nb_el;
6714
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 6715
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 6716
 
6717
  memset (nb, 0, sizeof (neighbor_rec));
6718
  get_neighbors (nb, a_view);
6719
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6720
  for (i = 0; i < FORLIM; i++) {
6721
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
6722
            strcpy (nb_el, atom[nb[i] - 1].element);
6723
            if (strcmp (nb_el, "C ")) {
6724
              if (!strcmp (nb_el, "O ")) {
6725
                      o_count++;
6726
                      a_o = nb[i];
6727
                    }
6728
              if (!strcmp (nb_el, "N ")) {
6729
                      n_count++;
6730
                      a_n = nb[i];
6731
                    }
6732
              if (!strcmp (nb_el, "S ")) {
6733
                      s_count++;
6734
                      a_s = nb[i];
6735
                    }
6785 bpr 6736
            }
14179 bpr 6737
          }
6738
  }
6739
  if (is_oxo_C (a_view)) {
6740
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
18544 georgesk 6741
            if (bond[get_bond (a_view, a_o) - 1].arom == isfalse)
6742
              fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6743
            if (is_hydroxy (a_view, a_o)) {
6785 bpr 6744
              if (atom[a_o - 1].formal_charge == 0)
18544 georgesk 6745
                      fg[fg_carboxylic_acid - 1] = istrue;
6785 bpr 6746
              if (atom[a_o - 1].formal_charge == -1)
18544 georgesk 6747
                      fg[fg_carboxylic_acid_salt - 1] = istrue;
6785 bpr 6748
            }
14179 bpr 6749
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
6750
                is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o)) {
18544 georgesk 6751
              if (bond[get_bond (a_view, a_o) - 1].arom == isfalse)
6752
                      fg[fg_carboxylic_acid_ester - 1] = istrue;
14179 bpr 6753
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
18544 georgesk 6754
                      if (bond[get_bond (a_view, a_o) - 1].arom == istrue) {
6755
                        /*fg[fg_lactone_heteroarom] := istrue else fg[fg_lactone] := istrue; */
6756
                        fg[fg_oxohetarene - 1] = istrue;
14179 bpr 6757
                      }
6758
                    else
18544 georgesk 6759
                      fg[fg_lactone - 1] = istrue;
6785 bpr 6760
                    }
6761
            }
14179 bpr 6762
          }
6763
    if (n_count == 1) {
18544 georgesk 6764
            if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6765
              fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6766
            else {
18544 georgesk 6767
              /*fg[fg_lactam_heteroarom] := istrue;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6768
              fg[fg_oxohetarene - 1] = istrue;
6785 bpr 6769
            }
14179 bpr 6770
            if (is_amino (a_view, a_n) || (!strcmp (atom[a_n - 1].atype, "NAM")
6771
                      && atom[a_n - 1].neighbor_count == 1)) {
18544 georgesk 6772
              fg[fg_carboxylic_acid_amide - 1] = istrue;
6773
              fg[fg_carboxylic_acid_prim_amide - 1] = istrue;
6785 bpr 6774
            }
14179 bpr 6775
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
17891 bpr 6776
            if (is_C_monosubst_amino (a_view, a_n) &&
14179 bpr 6777
                (!is_subst_acylamino (a_view, a_n))) {                  /* v0.3j */
18544 georgesk 6778
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6779
                      fg[fg_carboxylic_acid_amide - 1] = istrue;
6780
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6781
                      fg[fg_carboxylic_acid_sec_amide - 1] = istrue;
14179 bpr 6782
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
18544 georgesk 6783
                      if (bond[get_bond (a_view, a_n) - 1].arom == istrue) {
6784
                        /*fg[fg_lactam_heteroarom]    := istrue else  */
6785
                        fg[fg_oxohetarene - 1] = istrue;
14179 bpr 6786
                      }
6787
                      else
18544 georgesk 6788
                        fg[fg_lactam - 1] = istrue;
6785 bpr 6789
                    }
6790
            }
14179 bpr 6791
            /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6792
            /*   (is_diarylamino(a_view,a_n)) then  */
6793
            if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6794
              /* v0.3j */
18544 georgesk 6795
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6796
                fg[fg_carboxylic_acid_amide - 1] = istrue;
6797
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6798
                fg[fg_carboxylic_acid_tert_amide - 1] = istrue;
14179 bpr 6799
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
18544 georgesk 6800
                if (bond[get_bond (a_view, a_n) - 1].arom == istrue) {
6801
                        /*fg[fg_lactam_heteroarom]    := istrue else  */
6802
                        fg[fg_oxohetarene - 1] = istrue;
14179 bpr 6803
                      }
6804
                      else
18544 georgesk 6805
                        fg[fg_lactam - 1] = istrue;
6785 bpr 6806
                    }
6807
            }
14179 bpr 6808
            if (is_hydroxylamino (a_view, a_n))
18544 georgesk 6809
              fg[fg_hydroxamic_acid - 1] = istrue;
14179 bpr 6810
            if (is_hydrazino (a_view, a_n))
18544 georgesk 6811
              fg[fg_carboxylic_acid_hydrazide - 1] = istrue;
14179 bpr 6812
            if (is_azido (a_view, a_n))
18544 georgesk 6813
              fg[fg_carboxylic_acid_azide - 1] = istrue;
14179 bpr 6814
          }
6815
    if (s_count == 1) {                 /* anhydride is checked somewhere else */
18544 georgesk 6816
            if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6817
              fg[fg_thiocarboxylic_acid_deriv - 1] = istrue;
14179 bpr 6818
            if (is_sulfanyl (a_view, a_s))
18544 georgesk 6819
              fg[fg_thiocarboxylic_acid - 1] = istrue;
14179 bpr 6820
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
18544 georgesk 6821
              if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6822
                      fg[fg_thiocarboxylic_acid_ester - 1] = istrue;
14179 bpr 6823
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
18544 georgesk 6824
                      if (bond[get_bond (a_view, a_s) - 1].arom == istrue) {
6825
                        /*fg[fg_thiolactone_heteroarom] := istrue else fg[fg_thiolactone] := istrue; */
6826
                        fg[fg_oxohetarene - 1] = istrue;
14179 bpr 6827
                      }
6828
                      else
18544 georgesk 6829
                        fg[fg_thiolactone - 1] = istrue;
6785 bpr 6830
                    }
6831
            }
14179 bpr 6832
          }
6833
  }                             /* end Oxo-C */
6834
  if (is_thioxo_C (a_view)) {
18544 georgesk 6835
    /* fg[fg_thiocarboxylic_acid_deriv]  := istrue; */
14179 bpr 6836
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
18544 georgesk 6837
            if (bond[get_bond (a_view, a_o) - 1].arom == isfalse)
6838
              fg[fg_thiocarboxylic_acid_deriv - 1] = istrue;
14179 bpr 6839
            if (is_hydroxy (a_view, a_o))
18544 georgesk 6840
              fg[fg_thiocarboxylic_acid - 1] = istrue;  /* fixed in v0.3c */
14179 bpr 6841
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
18544 georgesk 6842
              if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6843
                      fg[fg_thiocarboxylic_acid_ester - 1] = istrue;
14179 bpr 6844
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
18544 georgesk 6845
                      if (bond[get_bond (a_view, a_o) - 1].arom == istrue) {
6846
                        /*fg[fg_thiolactone_heteroarom] := istrue else fg[fg_thiolactone] := istrue; */
6847
                        fg[fg_thioxohetarene - 1] = istrue;
14179 bpr 6848
                      }
6849
                      else
18544 georgesk 6850
                        fg[fg_thiolactone - 1] = istrue;
6785 bpr 6851
                    }
6852
            }
14179 bpr 6853
          }
6854
    if (n_count == 1) {
18544 georgesk 6855
            if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6856
              fg[fg_thiocarboxylic_acid_deriv - 1] = istrue;
14179 bpr 6857
            else {
18544 georgesk 6858
              /*fg[fg_thiolactam_heteroarom] := istrue;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6859
              fg[fg_thioxohetarene - 1] = istrue;
6785 bpr 6860
            }
14179 bpr 6861
            /* catches also pyridazines, 1,2,3-triazines, etc. */
6862
            if (is_amino (a_view, a_n)){
18544 georgesk 6863
              fg[fg_thiocarboxylic_acid_amide - 1] = istrue;
6864
              /* fg[fg_thiocarboxylic_acid_prim_amide] := istrue; */
6785 bpr 6865
            }
14179 bpr 6866
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6867
            if (is_C_monosubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6868
              /* v0.3j */
18544 georgesk 6869
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6870
                      fg[fg_thiocarboxylic_acid_amide - 1] = istrue;
6871
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := istrue; */
14179 bpr 6872
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
18544 georgesk 6873
                      if (bond[get_bond (a_view, a_n) - 1].arom == istrue) {
6874
                        /*fg[fg_thiolactam_heteroarom] := istrue else fg[fg_thiolactam] := istrue; */
6875
                        fg[fg_thioxohetarene - 1] = istrue;
6785 bpr 6876
                    }
14179 bpr 6877
                    else
18544 georgesk 6878
                      fg[fg_thiolactam - 1] = istrue;
14179 bpr 6879
                  }
6880
          }
6785 bpr 6881
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6882
          /*   (is_diarylamino(a_view,a_n)) then  */
14179 bpr 6883
          if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6884
            /* v0.3j */
18544 georgesk 6885
            if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6886
                    fg[fg_thiocarboxylic_acid_amide - 1] = istrue;
6887
              /*fg[fg_thiocarboxylic_acid_tert_amide] := istrue; */
14179 bpr 6888
            if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
18544 georgesk 6889
                    if (bond[get_bond (a_view, a_n) - 1].arom == istrue) {
6890
                      /*fg[fg_thiolactam_heteroarom] := istrue else fg[fg_thiolactam] := istrue; */
6891
                      fg[fg_thioxohetarene - 1] = istrue;
6785 bpr 6892
                    }
14179 bpr 6893
                    else
18544 georgesk 6894
                      fg[fg_thiolactam - 1] = istrue;
14179 bpr 6895
                  }
6896
          }
6785 bpr 6897
        }
14179 bpr 6898
  if (s_count == 1) {                   /* anhydride is checked somewhere else */
18544 georgesk 6899
          if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6900
            fg[fg_thiocarboxylic_acid_deriv - 1] = istrue;
6785 bpr 6901
          if (is_sulfanyl (a_view, a_s))
18544 georgesk 6902
            fg[fg_thiocarboxylic_acid - 1] = istrue;
14179 bpr 6903
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
18544 georgesk 6904
      if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6905
                    fg[fg_thiocarboxylic_acid_ester - 1] = istrue;
14179 bpr 6906
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
18544 georgesk 6907
                      if (bond[get_bond (a_view, a_s) - 1].arom == istrue) {
6908
                        /*fg[fg_thiolactone_heteroarom] := istrue else fg[fg_thiolactone] := istrue; */
6909
                        fg[fg_thioxohetarene - 1] = istrue;
14179 bpr 6910
                      }
6911
                      else
18544 georgesk 6912
                        fg[fg_thiolactone - 1] = istrue;
6785 bpr 6913
                    }
6914
            }
14179 bpr 6915
          }
6916
  }                             /* end Thioxo-C */
18544 georgesk 6917
  if (is_istrue_imino_C (a_view)) {
14179 bpr 6918
    if (o_count == 1) {
18544 georgesk 6919
            if (bond[get_bond (a_view, a_o) - 1].arom == isfalse)
6920
              fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6921
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
18544 georgesk 6922
              if (bond[get_bond (a_view, a_o) - 1].arom == isfalse)
6923
                      fg[fg_imido_ester - 1] = istrue;
6785 bpr 6924
            }
14179 bpr 6925
          }
18544 georgesk 6926
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == isfalse)) {
6927
            if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6928
              fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6929
            if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n)) {
18544 georgesk 6930
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6931
                      fg[fg_carboxylic_acid_deriv - 1] = istrue;
6932
              fg[fg_carboxylic_acid_amidine - 1] = istrue;
6785 bpr 6933
            }
14179 bpr 6934
            if (is_hydrazino (a_view, a_n)) {
18544 georgesk 6935
              if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6936
                      fg[fg_carboxylic_acid_amidrazone - 1] = istrue;
6785 bpr 6937
            }
14179 bpr 6938
          }
18544 georgesk 6939
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == istrue))
14179 bpr 6940
            /* catches also pyridazines, 1,2,3-triazines, etc. */
18544 georgesk 6941
          fg[fg_iminohetarene - 1] = istrue;
14179 bpr 6942
    if (s_count == 1) {
18544 georgesk 6943
            if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6944
              fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6945
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
18544 georgesk 6946
              if (bond[get_bond (a_view, a_s) - 1].arom == isfalse)
6947
                 fg[fg_imido_thioester - 1] = istrue;
6785 bpr 6948
            }
14179 bpr 6949
          }
6950
  }
6951
  if (is_hydroximino_C (a_view)) {
18544 georgesk 6952
    if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6953
            fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6954
      if (o_count == 1) {
6955
              if (is_hydroxy (a_view, a_o))
18544 georgesk 6956
                fg[fg_hydroxamic_acid - 1] = istrue;
14179 bpr 6957
            }
6785 bpr 6958
    }
14179 bpr 6959
    if (!is_hydrazono_C (a_view))
6960
      return;
18544 georgesk 6961
    if (bond[get_bond (a_view, a_n) - 1].arom == isfalse)
6962
      fg[fg_carboxylic_acid_deriv - 1] = istrue;
14179 bpr 6963
    if (n_count == 1) {
6964
        if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
18544 georgesk 6965
          fg[fg_carboxylic_acid_amidrazone - 1] = istrue;
14179 bpr 6966
  }
6785 bpr 6967
}
6968
 
17891 bpr 6969
static void chk_co2_sp2 (int a_view, int a_ref)
6785 bpr 6970
{
6971
  int i;
6972
  neighbor_rec nb;
6973
  str2 nb_el;
6974
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
6975
    s_count = 0, sr_count = 0;
6976
  int FORLIM;
6977
 
6978
  memset (nb, 0, sizeof (neighbor_rec));
6979
  get_neighbors (nb, a_view);
6980
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6981
  for (i = 0; i < FORLIM; i++) {
6982
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
6983
           strcpy (nb_el, atom[nb[i] - 1].element);
6984
            if (strcmp (nb_el, "C ")) {
6985
              if (!strcmp (nb_el, "O ")) {
6986
                      o_count++;
6987
                      if (is_alkoxy (a_view, nb[i]) |
6988
                          is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,nb[i]))
6989
                        /* v0.3j */
6990
                        or_count++;
6991
                    }
6992
              if (!strcmp (nb_el, "N ")) {
6993
                      n_count++;
6994
                      if (is_hydrazino (a_view, nb[i]))
6995
                        nn_count++;
6996
                      if (is_subst_hydrazino (a_view, nb[i]))   /* more general... */
6997
                        nnx_count++;
6998
                    }
6999
              if (!strcmp (nb_el, "S ")) {
7000
                      s_count++;
7001
                      if (is_alkylsulfanyl (a_view, nb[i]) | is_arylsulfanyl (a_view, nb[i]))
7002
                        sr_count++;
7003
                    }
6785 bpr 7004
            }
14179 bpr 7005
          }
7006
  }
7007
  if (is_oxo_C (a_view)) {
7008
      if (o_count == 2) {
18544 georgesk 7009
              fg[fg_carbonic_acid_deriv - 1] = istrue;
14179 bpr 7010
              if (or_count == 1)
18544 georgesk 7011
                fg[fg_carbonic_acid_monoester - 1] = istrue;
14179 bpr 7012
              if (or_count == 2)
18544 georgesk 7013
                fg[fg_carbonic_acid_diester - 1] = istrue;
14179 bpr 7014
            }
7015
      if (o_count == 1 && s_count == 1) {
18544 georgesk 7016
              fg[fg_thiocarbonic_acid_deriv - 1] = istrue;
14179 bpr 7017
              if (or_count + sr_count == 1)
18544 georgesk 7018
                fg[fg_thiocarbonic_acid_monoester - 1] = istrue;
14179 bpr 7019
              if (or_count + sr_count == 2)
18544 georgesk 7020
                fg[fg_thiocarbonic_acid_diester - 1] = istrue;
14179 bpr 7021
            }
7022
      if (s_count == 2) {
18544 georgesk 7023
              fg[fg_thiocarbonic_acid_deriv - 1] = istrue;
14179 bpr 7024
              if (sr_count == 1)
18544 georgesk 7025
                fg[fg_thiocarbonic_acid_monoester - 1] = istrue;
14179 bpr 7026
              if (sr_count == 2)
18544 georgesk 7027
                fg[fg_thiocarbonic_acid_diester - 1] = istrue;
14179 bpr 7028
            }
7029
      if (o_count == 1 && n_count == 1) {
18544 georgesk 7030
              fg[fg_carbamic_acid_deriv - 1] = istrue;
14179 bpr 7031
              if (or_count == 0)
18544 georgesk 7032
                fg[fg_carbamic_acid - 1] = istrue;
14179 bpr 7033
              if (or_count == 1)
18544 georgesk 7034
                fg[fg_carbamic_acid_ester - 1] = istrue;
14179 bpr 7035
            }
7036
      if (s_count == 1 && n_count == 1) {
18544 georgesk 7037
              fg[fg_thiocarbamic_acid_deriv - 1] = istrue;
14179 bpr 7038
              if (sr_count == 0)
18544 georgesk 7039
                fg[fg_thiocarbamic_acid - 1] = istrue;
14179 bpr 7040
              if (sr_count == 1)
18544 georgesk 7041
                fg[fg_thiocarbamic_acid_ester - 1] = istrue;
14179 bpr 7042
            }
7043
      if (n_count == 2) {
7044
            if (nn_count == 1)
18544 georgesk 7045
              fg[fg_semicarbazide - 1] = istrue;
14179 bpr 7046
            else {
6785 bpr 7047
              if (nnx_count == 0)       /* excludes semicarbazones */
18544 georgesk 7048
                      fg[fg_urea - 1] = istrue;
6785 bpr 7049
            }
14179 bpr 7050
          }
7051
  }                             /* end Oxo-C */
7052
  if (is_thioxo_C (a_view)) {
7053
      if (o_count == 2) {
18544 georgesk 7054
              fg[fg_thiocarbonic_acid_deriv - 1] = istrue;
14179 bpr 7055
              if (or_count == 1)
18544 georgesk 7056
                fg[fg_thiocarbonic_acid_monoester - 1] = istrue;
14179 bpr 7057
              if (or_count == 2)
18544 georgesk 7058
                fg[fg_thiocarbonic_acid_diester - 1] = istrue;
14179 bpr 7059
            }
7060
      if (o_count == 1 && s_count == 1) {
18544 georgesk 7061
              fg[fg_thiocarbonic_acid_deriv - 1] = istrue;
14179 bpr 7062
              if (or_count + sr_count == 1)
18544 georgesk 7063
                fg[fg_thiocarbonic_acid_monoester - 1] = istrue;
14179 bpr 7064
              if (or_count + sr_count == 2)
18544 georgesk 7065
                fg[fg_thiocarbonic_acid_diester - 1] = istrue;
14179 bpr 7066
            }
7067
      if (s_count == 2) {
18544 georgesk 7068
              fg[fg_thiocarbonic_acid_deriv - 1] = istrue;
14179 bpr 7069
              if (sr_count == 1)
18544 georgesk 7070
                fg[fg_thiocarbonic_acid_monoester - 1] = istrue;
14179 bpr 7071
              if (sr_count == 2)
18544 georgesk 7072
                fg[fg_thiocarbonic_acid_diester - 1] = istrue;
14179 bpr 7073
            }
7074
      if (o_count == 1 && n_count == 1) {
18544 georgesk 7075
              fg[fg_thiocarbamic_acid_deriv - 1] = istrue;
14179 bpr 7076
              if (or_count == 0)
18544 georgesk 7077
                fg[fg_thiocarbamic_acid - 1] = istrue;
14179 bpr 7078
              if (or_count == 1)
18544 georgesk 7079
                fg[fg_thiocarbamic_acid_ester - 1] = istrue;
14179 bpr 7080
            }
7081
      if (s_count == 1 && n_count == 1) {
18544 georgesk 7082
              fg[fg_thiocarbamic_acid_deriv - 1] = istrue;
14179 bpr 7083
              if (sr_count == 0)
18544 georgesk 7084
                fg[fg_thiocarbamic_acid - 1] = istrue;
14179 bpr 7085
              if (sr_count == 1)
18544 georgesk 7086
                fg[fg_thiocarbamic_acid_ester - 1] = istrue;
14179 bpr 7087
            }
7088
      if (n_count == 2) {
7089
            if (nn_count == 1)
18544 georgesk 7090
              fg[fg_thiosemicarbazide - 1] = istrue;
14179 bpr 7091
            else {
6785 bpr 7092
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
18544 georgesk 7093
                      fg[fg_thiourea - 1] = istrue;
6785 bpr 7094
            }
14179 bpr 7095
          }
7096
  }                             /* end Thioxo-C */
18544 georgesk 7097
  if (!(is_istrue_imino_C (a_view) &&
7098
       (bond[get_bond (a_view, a_ref) - 1].arom == isfalse))) {
6785 bpr 7099
      return;
14179 bpr 7100
  }                             /* end Imino-C */
6785 bpr 7101
  if (o_count == 1 && n_count == 1)
18544 georgesk 7102
    fg[fg_isourea - 1] = istrue;
6785 bpr 7103
  if (s_count == 1 && n_count == 1)
18544 georgesk 7104
    fg[fg_isothiourea - 1] = istrue;
6785 bpr 7105
  if (n_count == 2)
18544 georgesk 7106
    fg[fg_guanidine - 1] = istrue;
6785 bpr 7107
}
7108
 
17891 bpr 7109
static void chk_co2_sp (int a_view, int a_ref)
6785 bpr 7110
{
7111
  int i;
7112
  neighbor_rec nb;
7113
  str2 nb_el;
7114
  int o_count = 0, n_count = 0, s_count = 0;
7115
  int FORLIM;
7116
 
7117
  memset (nb, 0, sizeof (neighbor_rec));
7118
  get_neighbors (nb, a_view);
7119
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7120
  for (i = 0; i < FORLIM; i++) {
7121
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D') {
7122
            strcpy (nb_el, atom[nb[i] - 1].element);
7123
            if (strcmp (nb_el, "C ")) {
6785 bpr 7124
              if (!strcmp (nb_el, "O "))
14179 bpr 7125
                      o_count++;
6785 bpr 7126
              if (!strcmp (nb_el, "N "))
14179 bpr 7127
                      n_count++;
6785 bpr 7128
              if (!strcmp (nb_el, "S "))
14179 bpr 7129
                      s_count++;
6785 bpr 7130
            }
14179 bpr 7131
          }
7132
  }
6785 bpr 7133
  if (o_count + s_count == 2)   /* new in v0.3b */
18544 georgesk 7134
    fg[fg_co2_deriv - 1] = istrue;
6785 bpr 7135
  if (o_count == 1 && n_count == 1)
18544 georgesk 7136
    fg[fg_isocyanate - 1] = istrue;
6785 bpr 7137
  if (s_count == 1 && n_count == 1)
18544 georgesk 7138
    fg[fg_isothiocyanate - 1] = istrue;
6785 bpr 7139
  if (n_count == 2)
18544 georgesk 7140
    fg[fg_carbodiimide - 1] = istrue;
6785 bpr 7141
}
7142
 
17891 bpr 7143
static void chk_triple(int a1,int a2)
6785 bpr 7144
{
7145
  str2 a1_el, a2_el;
7146
 
7147
  strcpy (a1_el, atom[a1 - 1].element);
7148
  strcpy (a2_el, atom[a2 - 1].element);
17890 bpr 7149
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &&
18544 georgesk 7150
      (bond[get_bond (a1, a2) - 1].arom == isfalse))
7151
    fg[fg_alkyne - 1] = istrue;
6785 bpr 7152
  if (is_nitrile (a1, a2))
18544 georgesk 7153
    fg[fg_nitrile - 1] = istrue;
6785 bpr 7154
  if (is_isonitrile (a1, a2))
18544 georgesk 7155
    fg[fg_isonitrile - 1] = istrue;
6785 bpr 7156
  if (is_cyanate (a1, a2))
18544 georgesk 7157
    fg[fg_cyanate - 1] = istrue;
6785 bpr 7158
  if (is_thiocyanate (a1, a2))
18544 georgesk 7159
    fg[fg_thiocyanate - 1] = istrue;
6785 bpr 7160
}
7161
 
17891 bpr 7162
static void chk_ccx (int a_view, int a_ref)
6785 bpr 7163
{
7164
  int i;
7165
  neighbor_rec nb;
7166
  int oh_count = 0, or_count = 0, n_count = 0;
7167
  int FORLIM;
7168
 
7169
  memset (nb, 0, sizeof (neighbor_rec));
7170
  get_neighbors (nb, a_ref);
7171
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7172
  for (i = 0; i < FORLIM; i++) {
7173
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6785 bpr 7174
          if (is_hydroxy (a_ref, nb[i]))
7175
            oh_count++;
7176
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7177
              is_siloxy (a_ref, nb[i]))
7178
            or_count++;
7179
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7180
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7181
            n_count++;
14179 bpr 7182
          }
7183
  }
6785 bpr 7184
  if (oh_count == 1)
18544 georgesk 7185
    fg[fg_enol - 1] = istrue;
6785 bpr 7186
  if (or_count == 1)
18544 georgesk 7187
    fg[fg_enolether - 1] = istrue;
6785 bpr 7188
  if (n_count == 1)
18544 georgesk 7189
    fg[fg_enamine - 1] = istrue;
6785 bpr 7190
  /* new in v0.2f   (regard anything else as an alkene) */
7191
  if (oh_count + or_count + n_count == 0)
18544 georgesk 7192
    fg[fg_alkene - 1] = istrue;
6785 bpr 7193
}
7194
 
17891 bpr 7195
static void chk_xccx (int a_view, int a_ref)
6785 bpr 7196
{
7197
  int i;
7198
  neighbor_rec nb;
7199
  int oh_count = 0, or_count = 0, n_count = 0;
7200
  int FORLIM;
7201
 
7202
  memset (nb, 0, sizeof (neighbor_rec));
7203
  get_neighbors (nb, a_view);
7204
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7205
  for (i = 0; i < FORLIM; i++) {
7206
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7207
            if (is_hydroxy (a_view, nb[i]))
7208
              oh_count++;
7209
            if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
7210
                is_siloxy (a_view, nb[i]))
7211
              or_count++;
7212
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7213
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7214
              n_count++;
7215
          }
7216
  }
6785 bpr 7217
  memset (nb, 0, sizeof (neighbor_rec));
7218
  get_neighbors (nb, a_ref);
7219
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7220
  for (i = 0; i < FORLIM; i++) {
7221
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
7222
            if (is_hydroxy (a_ref, nb[i]))
7223
              oh_count++;
7224
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7225
                is_siloxy (a_ref, nb[i]))
7226
              or_count++;
7227
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7228
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7229
              n_count++;
7230
          }
7231
  }
6785 bpr 7232
  if (oh_count == 2)
18544 georgesk 7233
    fg[fg_enediol - 1] = istrue;
6785 bpr 7234
  /* new in v0.2f   (regard anything else as an alkene) */
7235
  if (oh_count + or_count + n_count == 0)
18544 georgesk 7236
    fg[fg_alkene - 1] = istrue;
6785 bpr 7237
}
7238
 
17891 bpr 7239
static void chk_n_o_dbl(int a1,int a2)
6785 bpr 7240
{
7241
  int i;
7242
  neighbor_rec nb;
7243
  str2 nb_el;
7244
  int or_count = 0, n_count = 0, c_count = 0;
7245
  int b;                        /* v0.3j */
7246
  int het_count = 0;            /* v0.3k */
7247
  char bt;                      /* v0.3k */
7248
  float bo_sum = 0.0;           /* v0.3k */
7249
  int FORLIM;
7250
 
7251
  memset (nb, 0, sizeof (neighbor_rec));
7252
  get_neighbors (nb, a1);
7253
  FORLIM = atom[a1 - 1].neighbor_count;
7254
  /* v0.3k */
7255
  /* v0.3k */
14179 bpr 7256
  for (i = 0; i < FORLIM; i++) {
7257
    if (nb[i] != a2) {
7258
            b = get_bond (a1, nb[i]);   /* v0.3j */
7259
            strcpy (nb_el, atom[nb[i] - 1].element);
7260
            bt = bond[b - 1].btype;     /* v0.3k */
7261
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7262
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
18544 georgesk 7263
                && strcmp (nb_el, "LP") && bond[b - 1].arom == isfalse)
14179 bpr 7264
                /* added 'D ' in v0.3n */
7265
              het_count++;
7266
            /* v0.3k: ignore hetero atoms */
7267
            /* in aromatic rings like isoxazole  */
7268
            if (bt == 'S')
7269
              bo_sum += 1.0;
7270
            if (bt == 'D')
7271
              bo_sum += 2.0;
7272
            if (bt == 'A')
7273
              bo_sum += 1.5;
7274
            if (!strcmp (nb_el, "O "))
7275
              or_count++;
7276
            if (!strcmp (nb_el, "N "))
7277
              n_count++;
7278
            if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')      /* v0.3k */
7279
              c_count++;
7280
            /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
7281
          }
7282
  }
7283
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2) {
7284
    /* excludes nitro etc. */
7285
    if (or_count == 1)
18544 georgesk 7286
            fg[fg_nitrite - 1] = istrue;
14179 bpr 7287
    if (c_count == 1)
18544 georgesk 7288
            fg[fg_nitroso_compound - 1] = istrue;
14179 bpr 7289
    if (n_count == 1)           /* instead of nitrosamine  v0.3j */
18544 georgesk 7290
            fg[fg_nitroso_compound - 1] = istrue;
7291
    /*if (n_count = 1) then fg[fg_nitrosamine]   := istrue;  (* still missing */
14179 bpr 7292
  }
6785 bpr 7293
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
7294
  /*  begin */
18544 georgesk 7295
  /*    fg[fg_n_oxide] := istrue; */
6785 bpr 7296
  /*  end; */
7297
  /* new approach in v0.3k */
7298
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
18544 georgesk 7299
    fg[fg_n_oxide - 1] = istrue;
6785 bpr 7300
}
7301
 
17891 bpr 7302
static void chk_sulfoxide(int a1,int a2)
6785 bpr 7303
{
7304
  int i;
7305
  neighbor_rec nb;
7306
  str2 nb_el;
7307
  int o_count = 0, c_count = 0;
7308
  int FORLIM;
7309
 
7310
  memset (nb, 0, sizeof (neighbor_rec));
7311
  get_neighbors (nb, a1);
7312
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7313
  for (i = 0; i < FORLIM; i++) {
7314
    strcpy (nb_el, atom[nb[i] - 1].element);
7315
    if (!strcmp (nb_el, "O "))
7316
            o_count++;
7317
    if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
7318
            c_count++;
7319
  }
6785 bpr 7320
  if (o_count == 1 && c_count == 2)
18544 georgesk 7321
    fg[fg_sulfoxide - 1] = istrue;
6785 bpr 7322
}
7323
 
17891 bpr 7324
static void chk_double(int a1,int a2)
6785 bpr 7325
{
7326
  str2 a1_el, a2_el;
7327
 
7328
  strcpy (a1_el, atom[a1 - 1].element);
7329
  strcpy (a2_el, atom[a2 - 1].element);
17890 bpr 7330
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &&
18544 georgesk 7331
      (bond[get_bond (a1, a2) - 1].arom == isfalse)) {
14179 bpr 7332
    if (hetbond_count (a1) == 2)
7333
            chk_carbonyl_deriv (a1, a2);
7334
    if (hetbond_count (a1) == 3)
7335
            chk_carboxyl_deriv (a1, a2);
7336
    if (hetbond_count (a1) == 4) {
7337
            if (!strcmp (atom[a1 - 1].atype, "C2 "))
7338
              chk_co2_sp2 (a1, a2);
7339
            if (!strcmp (atom[a1 - 1].atype, "C1 "))
7340
              chk_co2_sp (a1, a2);
7341
          }
7342
  }                             /* end C=X */
6785 bpr 7343
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
7344
       && !strcmp (atom[a2 - 1].atype,
18544 georgesk 7345
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == isfalse)) {
14179 bpr 7346
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
18544 georgesk 7347
            fg[fg_ketene_acetal_deriv - 1] = istrue;
14179 bpr 7348
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
7349
            chk_ccx (a1, a2);
7350
    if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
7351
            chk_xccx (a1, a2);
7352
    if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
18544 georgesk 7353
              atom[a1 - 1].arom == isfalse && atom[a2 - 1].arom == isfalse)
7354
            fg[fg_alkene - 1] = istrue;
14179 bpr 7355
  }
7356
  if (((!strcmp (a1_el, "N ") && !strcmp (a2_el, "N "))
7357
      && (hetbond_count (a1) == 2) && (hetbond_count (a2) == 2)
18544 georgesk 7358
      && (bond[get_bond (a1, a2) - 1].arom == isfalse))
6785 bpr 7359
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
18544 georgesk 7360
    fg[fg_azo_compound - 1] = istrue;
6785 bpr 7361
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
7362
    chk_n_o_dbl (a1, a2);
7363
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
7364
    chk_sulfoxide (a1, a2);
7365
}
7366
 
17891 bpr 7367
static void chk_c_hal(int a1,int a2)
6785 bpr 7368
{
7369
  str2 a2_el;
7370
 
7371
  strcpy (a2_el, atom[a2 - 1].element);
18544 georgesk 7372
  fg[fg_halogen_deriv - 1] = istrue;
14179 bpr 7373
  if (atom[a1 - 1].arom) {
18544 georgesk 7374
    fg[fg_aryl_halide - 1] = istrue;
14179 bpr 7375
    if (!strcmp (a2_el, "F "))
18544 georgesk 7376
            fg[fg_aryl_fluoride - 1] = istrue;
14179 bpr 7377
    if (!strcmp (a2_el, "CL"))
18544 georgesk 7378
            fg[fg_aryl_chloride - 1] = istrue;
14179 bpr 7379
    if (!strcmp (a2_el, "BR"))
18544 georgesk 7380
            fg[fg_aryl_bromide - 1] = istrue;
14179 bpr 7381
    if (!strcmp (a2_el, "I "))
18544 georgesk 7382
            fg[fg_aryl_iodide - 1] = istrue;
14179 bpr 7383
    return;
7384
  }
7385
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2)) {
7386
    /* alkyl halides */
18544 georgesk 7387
    fg[fg_alkyl_halide - 1] = istrue;
14179 bpr 7388
    if (!strcmp (a2_el, "F "))
18544 georgesk 7389
            fg[fg_alkyl_fluoride - 1] = istrue;
14179 bpr 7390
    if (!strcmp (a2_el, "CL"))
18544 georgesk 7391
            fg[fg_alkyl_chloride - 1] = istrue;
14179 bpr 7392
    if (!strcmp (a2_el, "BR"))
18544 georgesk 7393
            fg[fg_alkyl_bromide - 1] = istrue;
14179 bpr 7394
    if (!strcmp (a2_el, "I "))
18544 georgesk 7395
            fg[fg_alkyl_iodide - 1] = istrue;
14179 bpr 7396
  }
7397
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3)) {
7398
    /* acyl halides and related compounds */
7399
    if (is_oxo_C (a1)) {
18544 georgesk 7400
            fg[fg_acyl_halide - 1] = istrue;
14179 bpr 7401
            if (!strcmp (a2_el, "F "))
18544 georgesk 7402
              fg[fg_acyl_fluoride - 1] = istrue;
14179 bpr 7403
            if (!strcmp (a2_el, "CL"))
18544 georgesk 7404
              fg[fg_acyl_chloride - 1] = istrue;
14179 bpr 7405
            if (!strcmp (a2_el, "BR"))
18544 georgesk 7406
              fg[fg_acyl_bromide - 1] = istrue;
14179 bpr 7407
            if (!strcmp (a2_el, "I "))
18544 georgesk 7408
              fg[fg_acyl_iodide - 1] = istrue;
14179 bpr 7409
          }
7410
    if (is_thioxo_C (a1))
18544 georgesk 7411
            fg[fg_thiocarboxylic_acid_deriv - 1] = istrue;
14179 bpr 7412
    if (is_imino_C (a1))
18544 georgesk 7413
            fg[fg_imidoyl_halide - 1] = istrue;
14179 bpr 7414
  }
7415
  if (!((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
6785 bpr 7416
       && (hetbond_count (a1) == 4)))
7417
    /* chloroformates etc. */
7418
    return;
7419
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
18544 georgesk 7420
  fg[fg_co2_deriv - 1] = istrue;
14179 bpr 7421
  if (is_oxo_C (a1)) {
18544 georgesk 7422
      fg[fg_carbonic_acid_deriv - 1] = istrue;
14179 bpr 7423
    if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
18544 georgesk 7424
            fg[fg_carbonic_acid_ester_halide - 1] = istrue;
14179 bpr 7425
    if (is_carbamoyl (a2, a1)) {
18544 georgesk 7426
            fg[fg_carbamic_acid_deriv - 1] = istrue;
7427
            fg[fg_carbamic_acid_halide - 1] = istrue;
14179 bpr 7428
          }
7429
  }
6785 bpr 7430
  if (!is_thioxo_C (a1))
7431
    return;
18544 georgesk 7432
  fg[fg_thiocarbonic_acid_deriv - 1] = istrue;
6785 bpr 7433
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
18544 georgesk 7434
    fg[fg_thiocarbonic_acid_ester_halide - 1] = istrue;
14179 bpr 7435
  if (is_thiocarbamoyl (a2, a1)) {
18544 georgesk 7436
    fg[fg_thiocarbamic_acid_deriv - 1] = istrue;
7437
    fg[fg_thiocarbamic_acid_halide - 1] = istrue;
6785 bpr 7438
      /* end of non-aromatic halogen compounds */
14179 bpr 7439
  }
6785 bpr 7440
}
7441
 
17891 bpr 7442
static void chk_c_o(int a1,int a2)
6785 bpr 7443
{
7444
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
18544 georgesk 7445
  if (bond[get_bond (a1, a2) - 1].arom == istrue)
6785 bpr 7446
    return;
18544 georgesk 7447
  if (is_istrue_alkyl (a2, a1) && is_hydroxy (a1, a2)) {
7448
    fg[fg_hydroxy - 1] = istrue;
7449
    fg[fg_alcohol - 1] = istrue;
14179 bpr 7450
    if (atom[a1 - 1].neighbor_count <= 2)
18544 georgesk 7451
            fg[fg_prim_alcohol - 1] = istrue;
14179 bpr 7452
    if (atom[a1 - 1].neighbor_count == 3)
18544 georgesk 7453
            fg[fg_sec_alcohol - 1] = istrue;
14179 bpr 7454
    if (atom[a1 - 1].neighbor_count == 4)
18544 georgesk 7455
            fg[fg_tert_alcohol - 1] = istrue;
14179 bpr 7456
  }
7457
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2)) {
18544 georgesk 7458
    fg[fg_hydroxy - 1] = istrue;
7459
    fg[fg_phenol - 1] = istrue;
14179 bpr 7460
  }
18544 georgesk 7461
  if (is_istrue_alkyl (a2, a1) && is_istrue_alkoxy (a1, a2)) {
7462
    fg[fg_ether - 1] = istrue;
7463
    fg[fg_dialkylether - 1] = istrue;
14179 bpr 7464
  }
18544 georgesk 7465
  if ((is_istrue_alkyl (a2, a1) && is_aryloxy (a1, a2)) ||
7466
      (is_aryl (a2, a1) && is_istrue_alkoxy (a1, a2))) {
7467
    fg[fg_ether - 1] = istrue;
7468
    fg[fg_alkylarylether - 1] = istrue;
14179 bpr 7469
  }
7470
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2)) {
18544 georgesk 7471
    fg[fg_ether - 1] = istrue;
7472
    fg[fg_diarylether - 1] = istrue;
14179 bpr 7473
  }
18544 georgesk 7474
  if ((is_istrue_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2)) {
7475
    fg[fg_ether - 1] = istrue;
7476
    ether_generic = istrue;
14179 bpr 7477
  }
7478
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2)) {
18544 georgesk 7479
    fg[fg_hydroxy - 1] = istrue;
7480
    hydroxy_generic = istrue;
14179 bpr 7481
  }
6785 bpr 7482
}
7483
 
17891 bpr 7484
static void chk_c_s(int a1,int a2)
6785 bpr 7485
{
7486
  int i;
7487
  neighbor_rec nb;
7488
  str2 nb_el;
7489
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
7490
    hal_count = 0;
7491
  int FORLIM;
7492
 
7493
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
18544 georgesk 7494
  if (bond[get_bond (a1, a2) - 1].arom == istrue)
6785 bpr 7495
    return;
14179 bpr 7496
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2)) {
18544 georgesk 7497
    fg[fg_thiol - 1] = istrue;
7498
    fg[fg_alkylthiol - 1] = istrue;
14179 bpr 7499
  }
7500
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2)) {
18544 georgesk 7501
    fg[fg_thiol - 1] = istrue;
7502
    fg[fg_arylthiol - 1] = istrue;
14179 bpr 7503
  }
18544 georgesk 7504
  if (is_istrue_alkyl (a2, a1) && is_istrue_alkylsulfanyl (a1, a2))
7505
    fg[fg_thioether - 1] = istrue;
7506
  if ((is_istrue_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) ||
7507
        (is_aryl (a2, a1) && is_istrue_alkylsulfanyl (a1, a2)))
7508
    fg[fg_thioether - 1] = istrue;
6785 bpr 7509
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
18544 georgesk 7510
    fg[fg_thioether - 1] = istrue;
6785 bpr 7511
  /* check for sulfinic/sulfenic acid derivatives */
7512
  memset (nb, 0, sizeof (neighbor_rec));
7513
  get_neighbors (nb, a2);
7514
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7515
  for (i = 0; i < FORLIM; i++) {
7516
    strcpy (nb_el, atom[nb[i] - 1].element);
7517
    if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
7518
            c_count++;
7519
    if (is_hydroxy (a2, nb[i]))
7520
            oh_count++;
7521
    if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
7522
            or_count++;
7523
    if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
7524
            n_count++;
7525
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7526
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
7527
            hal_count++;
7528
    if (!strcmp (nb_el, "O "))
7529
            o_count++;
7530
  }
6785 bpr 7531
  if (c_count != 1)
7532
    return;
14179 bpr 7533
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1) {
7534
    /* sulfinic acid && derivs */
18544 georgesk 7535
    fg[fg_sulfinic_acid_deriv - 1] = istrue;
14179 bpr 7536
    if (oh_count == 1)
18544 georgesk 7537
            fg[fg_sulfinic_acid - 1] = istrue;
14179 bpr 7538
    if (or_count == 1)
18544 georgesk 7539
            fg[fg_sulfinic_acid_ester - 1] = istrue;
14179 bpr 7540
    if (hal_count == 1)
18544 georgesk 7541
            fg[fg_sulfinic_acid_halide - 1] = istrue;
14179 bpr 7542
    if (n_count == 1)
18544 georgesk 7543
            fg[fg_sulfinic_acid_amide - 1] = istrue;
14179 bpr 7544
  }
6785 bpr 7545
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
7546
    /* sulfenic acid && derivs */
7547
    return;
7548
 
18544 georgesk 7549
  fg[fg_sulfenic_acid_deriv - 1] = istrue;
6785 bpr 7550
  if (oh_count == 1)
18544 georgesk 7551
    fg[fg_sulfenic_acid - 1] = istrue;
6785 bpr 7552
  if (or_count == 1)
18544 georgesk 7553
    fg[fg_sulfenic_acid_ester - 1] = istrue;
6785 bpr 7554
  if (hal_count == 1)
18544 georgesk 7555
    fg[fg_sulfenic_acid_halide - 1] = istrue;
6785 bpr 7556
  if (n_count == 1)
18544 georgesk 7557
    fg[fg_sulfenic_acid_amide - 1] = istrue;
6785 bpr 7558
}
7559
 
17891 bpr 7560
static void chk_c_n(int a1,int a2)
6785 bpr 7561
{
7562
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
18544 georgesk 7563
  if (atom[a2 - 1].arom == istrue)
6785 bpr 7564
    return;
18544 georgesk 7565
  if (is_istrue_alkyl (a2, a1) && is_amino (a1, a2)) {
7566
    fg[fg_amine - 1] = istrue;
7567
    fg[fg_prim_amine - 1] = istrue;
7568
    fg[fg_prim_aliph_amine - 1] = istrue;
6785 bpr 7569
    }
14179 bpr 7570
  if (is_aryl (a2, a1) && is_amino (a1, a2)) {
18544 georgesk 7571
    fg[fg_amine - 1] = istrue;
7572
    fg[fg_prim_amine - 1] = istrue;
7573
    fg[fg_prim_arom_amine - 1] = istrue;
14179 bpr 7574
  }
18544 georgesk 7575
  if (is_istrue_alkyl (a2, a1) && is_istrue_alkylamino (a1, a2)) {
7576
    fg[fg_amine - 1] = istrue;
7577
    fg[fg_sec_amine - 1] = istrue;
7578
    fg[fg_sec_aliph_amine - 1] = istrue;
14179 bpr 7579
  }
18544 georgesk 7580
  if (is_aryl (a2, a1) && is_istrue_alkylamino (a1, a2)) {
7581
    fg[fg_amine - 1] = istrue;
7582
    fg[fg_sec_amine - 1] = istrue;
7583
    fg[fg_sec_mixed_amine - 1] = istrue;
14179 bpr 7584
  }
7585
  if (is_aryl (a2, a1) && is_arylamino (a1, a2)) {
18544 georgesk 7586
    fg[fg_amine - 1] = istrue;
7587
    fg[fg_sec_amine - 1] = istrue;
7588
    fg[fg_sec_arom_amine - 1] = istrue;
14179 bpr 7589
  }
18544 georgesk 7590
  if (is_istrue_alkyl (a2, a1) && is_istrue_dialkylamino (a1, a2)) {
7591
    fg[fg_amine - 1] = istrue;
7592
    fg[fg_tert_amine - 1] = istrue;
7593
    fg[fg_tert_aliph_amine - 1] = istrue;
14179 bpr 7594
  }
18544 georgesk 7595
  if ((is_istrue_alkyl (a2, a1) && is_diarylamino (a1, a2)) ||
7596
      (is_aryl (a2, a1) && is_istrue_dialkylamino (a1, a2))) {
7597
    fg[fg_amine - 1] = istrue;
7598
    fg[fg_tert_amine - 1] = istrue;
7599
    fg[fg_tert_mixed_amine - 1] = istrue;
14179 bpr 7600
  }
7601
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2)) {
18544 georgesk 7602
    fg[fg_amine - 1] = istrue;
7603
    fg[fg_tert_amine - 1] = istrue;
7604
    fg[fg_tert_arom_amine - 1] = istrue;
14179 bpr 7605
  }
17890 bpr 7606
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) ||
18544 georgesk 7607
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2, a1) == isfalse))
6785 bpr 7608
    /* v0.3k */
18544 georgesk 7609
    fg[fg_hydroxylamine - 1] = istrue;
6785 bpr 7610
  /* v0.3k */
7611
  /* v0.3k  */
17890 bpr 7612
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) ||
6785 bpr 7613
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
18544 georgesk 7614
    fg[fg_hydrazine - 1] = istrue;
17890 bpr 7615
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) ||
6785 bpr 7616
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
7617
    /* v0.3k */
18544 georgesk 7618
    fg[fg_azide - 1] = istrue;
17890 bpr 7619
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) ||
6785 bpr 7620
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
7621
    /* v0.3k */
18544 georgesk 7622
    fg[fg_diazonium_salt - 1] = istrue;
6785 bpr 7623
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7624
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
7625
    /* v0.3k */
18544 georgesk 7626
    fg[fg_nitro_compound - 1] = istrue;
17891 bpr 7627
  if (is_alkynyl (a2, a1) &&
14179 bpr 7628
        (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
7629
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2))))) {
18544 georgesk 7630
      fg[fg_amine - 1] = istrue;
7631
      amine_generic = istrue;
14179 bpr 7632
  }
6785 bpr 7633
}
7634
 
17891 bpr 7635
static void chk_c_c(int a1,int a2)
6785 bpr 7636
{
7637
  int i;
7638
  neighbor_rec nb;
7639
  int oh_count, nhr_count, FORLIM;
7640
 
7641
  /* ignore aromatic rings */
18544 georgesk 7642
  if (atom[a2 - 1].arom == istrue)
6785 bpr 7643
    return;
7644
  /*check for 1,2-diols and 1,2-aminoalcoholes */
7645
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
14179 bpr 7646
        && !strcmp (atom[a2 - 1].atype, "C3 ")) {
7647
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1)) {
7648
            oh_count = 0;
7649
            nhr_count = 0;
7650
            memset (nb, 0, sizeof (neighbor_rec));
7651
            get_neighbors (nb, a1);
7652
            FORLIM = atom[a1 - 1].neighbor_count;
7653
            for (i = 0; i < FORLIM; i++) {
7654
              if (nb[i] != a2) {
7655
                      if (is_hydroxy (a1, nb[i]))
7656
                        oh_count++;
7657
                      if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7658
                        is_arylamino (a1, nb[i]))
7659
                      nhr_count++;
7660
                    }
6785 bpr 7661
            }
14179 bpr 7662
            memset (nb, 0, sizeof (neighbor_rec));
7663
            get_neighbors (nb, a2);
7664
            FORLIM = atom[a2 - 1].neighbor_count;
7665
            for (i = 0; i < FORLIM; i++) {
7666
              if (nb[i] != a1) {
7667
                      if (is_hydroxy (a2, nb[i]))
7668
                        oh_count++;
7669
                      if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
7670
                          is_arylamino (a2, nb[i]))
7671
                        nhr_count++;
7672
                    }
6785 bpr 7673
            }
14179 bpr 7674
            if (oh_count == 2)
18544 georgesk 7675
              fg[fg_1_2_diol - 1] = istrue;
14179 bpr 7676
            if (oh_count == 1 && nhr_count == 1)
18544 georgesk 7677
              fg[fg_1_2_aminoalcohol - 1] = istrue;
14179 bpr 7678
          }
7679
  }
6785 bpr 7680
  /* check for alpha-aminoacids and alpha-hydroxyacids */
7681
  if (strcmp (atom[a1 - 1].atype, "C3 ")
7682
      || strcmp (atom[a2 - 1].atype, "C2 "))
7683
    return;
7684
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
7685
    return;
7686
  oh_count = 0;
7687
  nhr_count = 0;
7688
  memset (nb, 0, sizeof (neighbor_rec));
7689
  get_neighbors (nb, a1);
7690
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7691
  for (i = 0; i < FORLIM; i++) {
7692
    if (nb[i] != a2) {
7693
            if (is_hydroxy (a1, nb[i]))
7694
              oh_count++;
7695
            if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7696
                is_arylamino (a1, nb[i]))
7697
              nhr_count++;
7698
          }
7699
  }
6785 bpr 7700
  memset (nb, 0, sizeof (neighbor_rec));
7701
  get_neighbors (nb, a2);
7702
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7703
  for (i = 0; i < FORLIM; i++) {
7704
    if (nb[i] != a1) {
7705
            if (is_hydroxy (a2, nb[i]))
7706
              oh_count++;
7707
          }
7708
  }
6785 bpr 7709
  if ((oh_count == 2) && is_oxo_C (a2))
18544 georgesk 7710
    fg[fg_alpha_hydroxyacid - 1] = istrue;
6785 bpr 7711
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
18544 georgesk 7712
    fg[fg_alpha_aminoacid - 1] = istrue;
6785 bpr 7713
}
7714
 
17891 bpr 7715
static void chk_x_y_single (int a_view, int a_ref)
6785 bpr 7716
{
7717
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
14179 bpr 7718
        !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7719
    if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
18544 georgesk 7720
            fg[fg_hydroperoxide - 1] = istrue;
14179 bpr 7721
    if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
7722
              is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,a_ref) |
7723
                        is_aryloxy (a_view, a_ref) |
7724
                        is_siloxy (a_view, a_ref)))
18544 georgesk 7725
            fg[fg_peroxide - 1] = istrue;
14179 bpr 7726
  }                             /* still missing: peracid */
6785 bpr 7727
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
14179 bpr 7728
      !strcmp (atom[a_ref - 1].atype, "S3 ")) {
6785 bpr 7729
      if (atom[a_view - 1].neighbor_count == 2 &&
7730
          atom[a_ref - 1].neighbor_count == 2)
18544 georgesk 7731
          fg[fg_disulfide - 1] = istrue;
14179 bpr 7732
  }
6785 bpr 7733
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7734
       !strcmp (atom[a_ref - 1].element, "N ")) && (hetbond_count (a_view) == 1)
7735
      && (hetbond_count (a_ref) == 1)) {
6785 bpr 7736
      /*if ((is_amino(a_ref,a_view)) or  */
7737
      /*    (is_subst_amino(a_ref,a_view)) or */
7738
      /*    (is_acylamino(a_ref,a_view))) and */
7739
      /*   ((is_amino(a_view,a_ref)) or  */
7740
      /*    (is_subst_amino(a_view,a_ref)) or */
7741
      /*    (is_acylamino(a_ref,a_view))) then  */
18544 georgesk 7742
      if (bond[get_bond (a_view, a_ref) - 1].arom == isfalse)
7743
              fg[fg_hydrazine - 1] = istrue;
14179 bpr 7744
  }
6785 bpr 7745
  if (!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7746
      !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7747
    /* bond is in "opposite" direction */
17891 bpr 7748
    if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &&
14179 bpr 7749
              is_nitro (a_ref, a_view))
18544 georgesk 7750
            fg[fg_nitrate - 1] = istrue;
7751
    if ((is_nitro (a_ref, a_view) == isfalse
7752
              && atom[a_view - 1].arom == isfalse) && (is_amino (a_ref, a_view) |
17891 bpr 7753
                    is_subst_amino (a_ref, a_view)) &&
18544 georgesk 7754
              (is_acylamino (a_ref, a_view) == isfalse))
7755
            fg[fg_hydroxylamine - 1] = istrue;  /* new in v0.3c */
14179 bpr 7756
  }
6785 bpr 7757
  if (!strcmp (atom[a_view - 1].element, "S ") &&
7758
      !strcmp (atom[a_ref - 1].element, "O "))
7759
    chk_sulfoxide (a_view, a_ref);
7760
}
7761
 
17891 bpr 7762
static void chk_single(int a1,int a2)
6785 bpr 7763
{
7764
  str2 a1_el, a2_el;
7765
 
7766
  strcpy (a1_el, atom[a1 - 1].element);
7767
  strcpy (a2_el, atom[a2 - 1].element);
7768
  if (!strcmp (a1_el, "C ") &&
7769
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
7770
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
7771
    chk_c_hal (a1, a2);
7772
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
7773
    chk_c_o (a1, a2);
7774
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
7775
    chk_c_s (a1, a2);
7776
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
7777
    chk_c_n (a1, a2);
18544 georgesk 7778
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) == isfalse)) {
7779
      fg[fg_organometallic - 1] = istrue;
6785 bpr 7780
      if (!strcmp (a2_el, "LI"))
18544 georgesk 7781
              fg[fg_organolithium - 1] = istrue;
6785 bpr 7782
      if (!strcmp (a2_el, "MG"))
18544 georgesk 7783
              fg[fg_organomagnesium - 1] = istrue;
14179 bpr 7784
  }
6785 bpr 7785
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
7786
    chk_c_c (a1, a2);
7787
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
7788
    chk_x_y_single (a1, a2);
7789
}
7790
 
17891 bpr 7791
static void chk_carbonyl_deriv_sp3 (int a_ref)
6785 bpr 7792
{
7793
  int i;
7794
  neighbor_rec nb;
7795
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
7796
  int FORLIM;
7797
 
7798
  memset (nb, 0, sizeof (neighbor_rec));
7799
  get_neighbors (nb, a_ref);
7800
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7801
  for (i = 0; i < FORLIM; i++) {
7802
    if (is_hydroxy (a_ref, nb[i]))
7803
            oh_count++;
7804
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7805
              is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
7806
            or_count++;
7807
    if (is_sulfanyl (a_ref, nb[i]))
7808
            sh_count++;
7809
    if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
7810
              is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref, nb[i]))
7811
            sr_count++;
7812
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
7813
            n_count++;
7814
  }
6785 bpr 7815
  if (oh_count == 2)
18544 georgesk 7816
    fg[fg_carbonyl_hydrate - 1] = istrue;
6785 bpr 7817
  if (oh_count == 1 && or_count == 1)
18544 georgesk 7818
    fg[fg_hemiacetal - 1] = istrue;
6785 bpr 7819
  if (or_count == 2)
18544 georgesk 7820
    fg[fg_acetal - 1] = istrue;
6785 bpr 7821
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
18544 georgesk 7822
    fg[fg_hemiaminal - 1] = istrue;
6785 bpr 7823
  if (n_count == 2)
18544 georgesk 7824
    fg[fg_aminal - 1] = istrue;
6785 bpr 7825
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
18544 georgesk 7826
    fg[fg_thiohemiaminal - 1] = istrue;
6785 bpr 7827
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
18544 georgesk 7828
    fg[fg_thioacetal - 1] = istrue;
6785 bpr 7829
}
7830
 
17891 bpr 7831
static void chk_carboxyl_deriv_sp3 (int a_ref)
6785 bpr 7832
{
7833
  int i;
7834
  neighbor_rec nb;
7835
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
7836
  int electroneg_count = 0;     /* new in v0.3j */
7837
  int hal_count = 0;
7838
  str2 nb_el;
7839
  int FORLIM;
7840
 
7841
  memset (nb, 0, sizeof (neighbor_rec));
7842
  get_neighbors (nb, a_ref);
7843
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7844
  for (i = 0; i < FORLIM; i++) {
7845
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3j */
7846
    if (is_electroneg (nb_el))
7847
            electroneg_count++;
7848
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7849
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7850
              || !strcmp (nb_el, "AT"))
7851
            hal_count++;
7852
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7853
              is_siloxy (a_ref, nb[i]))
7854
            or_count++;
7855
    if (is_hydroxy (a_ref, nb[i]))      /* new in v0.3c    */
7856
            oh_count++;
7857
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7858
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7859
            n_count++;
7860
  }
18544 georgesk 7861
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := istrue;  (* until v0.3i */
6785 bpr 7862
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
18544 georgesk 7863
    fg[fg_orthocarboxylic_acid_deriv - 1] = istrue;
6785 bpr 7864
  if (or_count == 3)
18544 georgesk 7865
    fg[fg_carboxylic_acid_orthoester - 1] = istrue;
6785 bpr 7866
  if (or_count == 2 && n_count == 1)
18544 georgesk 7867
    fg[fg_carboxylic_acid_amide_acetal - 1] = istrue;
6785 bpr 7868
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
18544 georgesk 7869
    fg[fg_orthocarboxylic_acid_deriv - 1] = istrue;
6785 bpr 7870
}
7871
 
17891 bpr 7872
static void chk_anhydride (int a_ref)
6785 bpr 7873
{
7874
  int i;
7875
  neighbor_rec nb;
7876
  int acyl_count = 0;
7877
  int FORLIM;
7878
 
7879
  memset (nb, 0, sizeof (neighbor_rec));
7880
  get_neighbors (nb, a_ref);
7881
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7882
  for (i = 0; i < FORLIM; i++) {
7883
    if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
7884
            acyl_count++;
7885
  }
7886
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 ")) {
18544 georgesk 7887
    fg[fg_carboxylic_acid_deriv - 1] = istrue;
7888
    fg[fg_carboxylic_acid_anhydride - 1] = istrue;
14179 bpr 7889
  }
6785 bpr 7890
}
7891
 
17891 bpr 7892
static void chk_imide (int a_ref)
6785 bpr 7893
{
7894
  int i;
7895
  neighbor_rec nb;
7896
  int acyl_count = 0;
7897
  int FORLIM;
7898
 
7899
  memset (nb, 0, sizeof (neighbor_rec));
7900
  get_neighbors (nb, a_ref);
7901
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7902
  for (i = 0; i < FORLIM; i++) {
7903
    if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))      /* v0.3j */
7904
            acyl_count++;
7905
  }
6785 bpr 7906
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
7907
    /* v0.3j: accept also N-acyl-imides */
7908
    return;
18544 georgesk 7909
  fg[fg_carboxylic_acid_deriv - 1] = istrue;
7910
  fg[fg_carboxylic_acid_imide - 1] = istrue;
6785 bpr 7911
  if (atom[a_ref - 1].neighbor_count == 2)
18544 georgesk 7912
    fg[fg_carboxylic_acid_unsubst_imide - 1] = istrue;
6785 bpr 7913
  if (atom[a_ref - 1].neighbor_count == 3)
18544 georgesk 7914
    fg[fg_carboxylic_acid_subst_imide - 1] = istrue;
6785 bpr 7915
}
7916
 
17891 bpr 7917
static void chk_12diphenol (int a_view, int a_ref)
6785 bpr 7918
{
7919
  int i;
7920
  neighbor_rec nb;
7921
  int oh_count = 0;
7922
  int FORLIM;
7923
 
7924
  memset (nb, 0, sizeof (neighbor_rec));
7925
  get_neighbors (nb, a_view);
7926
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7927
  for (i = 0; i < FORLIM; i++) {
7928
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7929
            if (is_hydroxy (a_view, nb[i]))
7930
              oh_count++;
7931
          }
7932
  }
6785 bpr 7933
  memset (nb, 0, sizeof (neighbor_rec));
7934
  get_neighbors (nb, a_ref);
7935
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7936
  for (i = 0; i < FORLIM; i++) {
7937
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
7938
            if (is_hydroxy (a_ref, nb[i]))
7939
              oh_count++;
7940
          }
7941
  }
6785 bpr 7942
  if (oh_count == 2)
18544 georgesk 7943
    fg[fg_1_2_diphenol - 1] = istrue;
6785 bpr 7944
}
7945
 
17891 bpr 7946
static void chk_arom_fg (int a1, int a2)
6785 bpr 7947
{
7948
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
7949
    chk_12diphenol (a1, a2);
7950
}
7951
 
17891 bpr 7952
static boolean is_arene (int r_id)
6785 bpr 7953
{
7954
  int i, j;
18544 georgesk 7955
  boolean r = istrue;
6785 bpr 7956
  ringpath_type testring;
7957
  int ring_size, a_prev, a_ref;
7958
 
7959
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
7960
  if (r_id < 1 || r_id > n_rings)
18544 georgesk 7961
    return isfalse;
6785 bpr 7962
  memset (testring, 0, sizeof (ringpath_type));
7963
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
7964
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
7965
  for (j = 0; j < ring_size; j++)       /* v0.3j */
7966
    testring[j] = ring[r_id - 1][j];
7967
  /*ring_size := path_length(testring); */
7968
  if (ring_size <= 2)
18544 georgesk 7969
    return isfalse;
6785 bpr 7970
  a_prev = testring[ring_size - 1];
14179 bpr 7971
  for (i = 0; i < ring_size; i++) {
7972
    a_ref = testring[i];
18544 georgesk 7973
    if (bond[get_bond (a_prev, a_ref) - 1].arom == isfalse)
7974
            r = isfalse;
14179 bpr 7975
    a_prev = a_ref;
7976
  }
6785 bpr 7977
  return r;
7978
}
7979
 
17891 bpr 7980
static boolean is_heterocycle (int r_id)
6785 bpr 7981
{
7982
  int i, j;
18544 georgesk 7983
  boolean r = isfalse;
6785 bpr 7984
  ringpath_type testring;
7985
  int ring_size, a_ref;
7986
 
7987
  if (r_id < 1 || r_id > n_rings)
18544 georgesk 7988
    return isfalse;
6785 bpr 7989
  memset (testring, 0, sizeof (ringpath_type));
7990
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
7991
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
7992
  for (j = 0; j < ring_size; j++)       /* v0.3j */
7993
    testring[j] = ring[r_id - 1][j];
7994
  /*ring_size := path_length(testring); */
7995
  if (ring_size <= 2)
18544 georgesk 7996
    return isfalse;
14179 bpr 7997
  for (i = 0; i < ring_size; i++) {
7998
    a_ref = testring[i];
7999
    if (strcmp (atom[a_ref - 1].element, "C "))
18544 georgesk 8000
            r = istrue;
14179 bpr 8001
  }
6785 bpr 8002
  return r;
8003
}
8004
 
17891 bpr 8005
static void chk_oxo_thioxo_imino_hetarene (int r_id)
6785 bpr 8006
{
8007
  int i, j;
8008
  ringpath_type testring;
8009
  int ring_size, a_ref;
8010
 
8011
  if (r_id < 1 || r_id > n_rings)
8012
    return;
8013
  memset (testring, 0, sizeof (ringpath_type));
8014
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8015
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8016
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8017
    testring[j] = ring[r_id - 1][j];
8018
  /*ring_size := path_length(testring); */
18544 georgesk 8019
  /*if (is_arene(r_id)) and (odd(ring_size) = isfalse) then */
6785 bpr 8020
  if (!is_arene (r_id))         /* v0.3j */
8021
    return;
14179 bpr 8022
  for (i = 0; i < ring_size; i++) {
8023
    a_ref = testring[i];
8024
    if (is_oxo_C (a_ref))
18544 georgesk 8025
            fg[fg_oxohetarene - 1] = istrue;
14179 bpr 8026
    if (is_thioxo_C (a_ref))
18544 georgesk 8027
            fg[fg_thioxohetarene - 1] = istrue;
8028
    if (is_istrue_exocyclic_imino_C (a_ref, r_id))      /* v0.3j */
8029
            fg[fg_iminohetarene - 1] = istrue;
14179 bpr 8030
  }
6785 bpr 8031
}
8032
 
17891 bpr 8033
static void chk_ion (int a_ref)
6785 bpr 8034
{
8035
  int i;
8036
  neighbor_rec nb;
8037
  int charge, FORLIM;
8038
 
8039
  memset (nb, 0, sizeof (neighbor_rec));
8040
  get_neighbors (nb, a_ref);
8041
  charge = atom[a_ref - 1].formal_charge;
8042
  if (charge == 0)
8043
    /* check if charge is neutralized by an adjacent opposite charge */
8044
    return;
8045
  FORLIM = atom[a_ref - 1].neighbor_count;
8046
  for (i = 0; i < FORLIM; i++)
8047
    charge += atom[nb[i] - 1].formal_charge;
8048
  if (charge > 0)
18544 georgesk 8049
    fg[fg_cation - 1] = istrue;
6785 bpr 8050
  if (charge < 0)
18544 georgesk 8051
    fg[fg_anion - 1] = istrue;
6785 bpr 8052
}
8053
 
14179 bpr 8054
static void chk_functionalgroups ()
6785 bpr 8055
{
8056
  int i, a1, a2;
8057
  char bt;
8058
  int pos_chg = 0, neg_chg = 0;
8059
  int FORLIM;
8060
 
8061
  if (n_atoms < 1 || n_bonds < 1)
8062
    return;
8063
  FORLIM = n_atoms;
14179 bpr 8064
  for (i = 1; i <= FORLIM; i++) {                               /* a few groups are best discovered in the atom list */
8065
    if (!strcmp (atom[i - 1].atype, "SO2"))
8066
            chk_so2_deriv (i);
18544 georgesk 8067
    /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := istrue;  (* do another check in the bond list!! */
14179 bpr 8068
    if (!strcmp (atom[i - 1].element, "P "))
8069
            chk_p_deriv (i);
8070
    if (!strcmp (atom[i - 1].element, "B "))
8071
            chk_b_deriv (i);
8072
    if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
8073
            chk_ammon (i);
8074
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 2))
8075
            chk_carbonyl_deriv_sp3 (i);
8076
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 3))
8077
            chk_carboxyl_deriv_sp3 (i);
8078
    if (!strcmp (atom[i - 1].atype, "O3 ") && atom[i - 1].neighbor_count == 2)
8079
            chk_anhydride (i);
8080
    if ((!strcmp (atom[i - 1].atype, "N3 ") || !strcmp (atom[i - 1].atype, "NAM"))
8081
              && atom[i - 1].neighbor_count >= 2)
8082
            chk_imide (i);
8083
    if (atom[i - 1].formal_charge > 0)
8084
            pos_chg += atom[i - 1].formal_charge;
8085
    if (atom[i - 1].formal_charge < 0)
8086
            neg_chg += atom[i - 1].formal_charge;
8087
    chk_ion (i);
8088
  }
6785 bpr 8089
  FORLIM = n_bonds;
14179 bpr 8090
  for (i = 0; i < FORLIM; i++) {                                /* most groups are best discovered in the bond list */
8091
    a1 = bond[i].a1;
8092
    a2 = bond[i].a2;
8093
    bt = bond[i].btype;
8094
    if (atom[a1 - 1].heavy && atom[a2 - 1].heavy) {
8095
            orient_bond (&a1, &a2);
8096
            if (bt == 'T')
8097
              chk_triple (a1, a2);
8098
            if (bt == 'D')
8099
              chk_double (a1, a2);
8100
            if (bt == 'S')
8101
              chk_single (a1, a2);
8102
            if (bond[i].arom)
8103
              chk_arom_fg (a1, a2);
8104
          }
8105
  }
8106
  if (n_rings > 0) {
8107
    FORLIM = n_rings;
8108
    for (i = 1; i <= FORLIM; i++) {
8109
            chk_oxo_thioxo_imino_hetarene (i);
8110
            if (is_arene (i))
18544 georgesk 8111
              fg[fg_aromatic - 1] = istrue;
14179 bpr 8112
            if (is_heterocycle (i))
18544 georgesk 8113
              fg[fg_heterocycle - 1] = istrue;
14179 bpr 8114
          }
8115
  }
6785 bpr 8116
  if (pos_chg + neg_chg > 0)
18544 georgesk 8117
    fg[fg_cation - 1] = istrue;
6785 bpr 8118
  if (pos_chg + neg_chg < 0)
18544 georgesk 8119
    fg[fg_anion - 1] = istrue;
6785 bpr 8120
}
8121
 
14179 bpr 8122
static void write_fg_text ()
6785 bpr 8123
{
8124
  if (fg[fg_cation - 1])
8125
    printf ("cation\n");
8126
  if (fg[fg_anion - 1])
8127
    printf ("anion\n");
8128
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
8129
  if (fg[fg_aldehyde - 1])
8130
    printf ("aldehyde\n");
8131
  if (fg[fg_ketone - 1])
8132
    printf ("ketone\n");
8133
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
8134
  if (fg[fg_thioaldehyde - 1])
8135
    printf ("thioaldehyde\n");
8136
  if (fg[fg_thioketone - 1])
8137
    printf ("thioketone\n");
8138
  if (fg[fg_imine - 1])
8139
    printf ("imine\n");
8140
  if (fg[fg_hydrazone - 1])
8141
    printf ("hydrazone\n");
8142
  if (fg[fg_semicarbazone - 1])
8143
    printf ("semicarbazone\n");
8144
  if (fg[fg_thiosemicarbazone - 1])
8145
    printf ("thiosemicarbazone\n");
8146
  if (fg[fg_oxime - 1])
8147
    printf ("oxime\n");
8148
  if (fg[fg_oxime_ether - 1])
8149
    printf ("oxime ether\n");
8150
  if (fg[fg_ketene - 1])
8151
    printf ("ketene\n");
8152
  if (fg[fg_ketene_acetal_deriv - 1])
8153
    printf ("ketene acetal or derivative\n");
8154
  if (fg[fg_carbonyl_hydrate - 1])
8155
    printf ("carbonyl hydrate\n");
8156
  if (fg[fg_hemiacetal - 1])
8157
    printf ("hemiacetal\n");
8158
  if (fg[fg_acetal - 1])
8159
    printf ("acetal\n");
8160
  if (fg[fg_hemiaminal - 1])
8161
    printf ("hemiaminal\n");
8162
  if (fg[fg_aminal - 1])
8163
    printf ("aminal\n");
8164
  if (fg[fg_thiohemiaminal - 1])
8165
    printf ("hemithioaminal\n");
8166
  if (fg[fg_thioacetal - 1])
8167
    printf ("thioacetal\n");
8168
  if (fg[fg_enamine - 1])
8169
    printf ("enamine\n");
8170
  if (fg[fg_enol - 1])
8171
    printf ("enol\n");
8172
  if (fg[fg_enolether - 1])
8173
    printf ("enol ether\n");
8174
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8175
    printf ("hydroxy compound\n");
8176
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
8177
  if (fg[fg_prim_alcohol - 1])
8178
    printf ("primary alcohol\n");
8179
  if (fg[fg_sec_alcohol - 1])
8180
    printf ("secondary alcohol\n");
8181
  if (fg[fg_tert_alcohol - 1])
8182
    printf ("tertiary alcohol\n");
8183
  if (fg[fg_1_2_diol - 1])
8184
    printf ("1,2-diol\n");
8185
  if (fg[fg_1_2_aminoalcohol - 1])
8186
    printf ("1,2-aminoalcohol\n");
8187
  if (fg[fg_phenol - 1])
8188
    printf ("phenol or hydroxyhetarene\n");
8189
  if (fg[fg_1_2_diphenol - 1])
8190
    printf ("1,2-diphenol\n");
8191
  if (fg[fg_enediol - 1])
8192
    printf ("enediol\n");
8193
  if (fg[fg_ether - 1] && ether_generic)
8194
    printf ("ether\n");
8195
  if (fg[fg_dialkylether - 1])
8196
    printf ("dialkyl ether\n");
8197
  if (fg[fg_alkylarylether - 1])
8198
    printf ("alkyl aryl ether \n");
8199
  if (fg[fg_diarylether - 1])
8200
    printf ("diaryl ether\n");
8201
  if (fg[fg_thioether - 1])
8202
    printf ("thioether\n");
8203
  if (fg[fg_disulfide - 1])
8204
    printf ("disulfide\n");
8205
  if (fg[fg_peroxide - 1])
8206
    printf ("peroxide\n");
8207
  if (fg[fg_hydroperoxide - 1])
8208
    printf ("hydroperoxide \n");
8209
  if (fg[fg_hydrazine - 1])
8210
    printf ("hydrazine derivative\n");
8211
  if (fg[fg_hydroxylamine - 1])
8212
    printf ("hydroxylamine\n");
8213
  if (fg[fg_amine - 1] && amine_generic)
8214
    printf ("amine\n");
8215
  if (fg[fg_prim_amine - 1])
8216
    printf ("primary amine\n");
8217
  if (fg[fg_prim_aliph_amine - 1])
8218
    printf ("primary aliphatic amine (alkylamine)\n");
8219
  if (fg[fg_prim_arom_amine - 1])
8220
    printf ("primary aromatic amine\n");
8221
  if (fg[fg_sec_amine - 1])
8222
    printf ("secondary amine\n");
8223
  if (fg[fg_sec_aliph_amine - 1])
8224
    printf ("secondary aliphatic amine (dialkylamine)\n");
8225
  if (fg[fg_sec_mixed_amine - 1])
8226
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
8227
  if (fg[fg_sec_arom_amine - 1])
8228
    printf ("secondary aromatic amine (diarylamine)\n");
8229
  if (fg[fg_tert_amine - 1])
8230
    printf ("tertiary amine\n");
8231
  if (fg[fg_tert_aliph_amine - 1])
8232
    printf ("tertiary aliphatic amine (trialkylamine)\n");
8233
  if (fg[fg_tert_mixed_amine - 1])
8234
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
8235
  if (fg[fg_tert_arom_amine - 1])
8236
    printf ("tertiary aromatic amine (triarylamine)\n");
8237
  if (fg[fg_quart_ammonium - 1])
8238
    printf ("quaternary ammonium salt\n");
8239
  if (fg[fg_n_oxide - 1])
8240
    printf ("N-oxide\n");
8241
  /* new in v0.2f */
14179 bpr 8242
  if (fg[fg_halogen_deriv - 1]) {
6785 bpr 8243
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
14179 bpr 8244
              !fg[fg_acyl_halide - 1])
8245
            printf ("halogen derivative\n");
8246
  }
6785 bpr 8247
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
8248
  if (fg[fg_alkyl_fluoride - 1])
8249
    printf ("alkyl fluoride\n");
8250
  if (fg[fg_alkyl_chloride - 1])
8251
    printf ("alkyl chloride\n");
8252
  if (fg[fg_alkyl_bromide - 1])
8253
    printf ("alkyl bromide\n");
8254
  if (fg[fg_alkyl_iodide - 1])
8255
    printf ("alkyl iodide\n");
8256
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
8257
  if (fg[fg_aryl_fluoride - 1])
8258
    printf ("aryl fluoride\n");
8259
  if (fg[fg_aryl_chloride - 1])
8260
    printf ("aryl chloride\n");
8261
  if (fg[fg_aryl_bromide - 1])
8262
    printf ("aryl bromide\n");
8263
  if (fg[fg_aryl_iodide - 1])
8264
    printf ("aryl iodide\n");
8265
  if (fg[fg_organometallic - 1])
8266
    printf ("organometallic compound\n");
8267
  if (fg[fg_organolithium - 1])
8268
    printf ("organolithium compound\n");
8269
  if (fg[fg_organomagnesium - 1])
8270
    printf ("organomagnesium compound\n");
8271
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
8272
  if (fg[fg_carboxylic_acid - 1])
8273
    printf ("carboxylic acid\n");
8274
  if (fg[fg_carboxylic_acid_salt - 1])
8275
    printf ("carboxylic acid salt\n");
8276
  if (fg[fg_carboxylic_acid_ester - 1])
8277
    printf ("carboxylic acid ester\n");
8278
  if (fg[fg_lactone - 1])
8279
    printf ("lactone\n");
8280
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
8281
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8282
    printf ("primary carboxylic acid amide\n");
8283
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8284
    printf ("secondary carboxylic acid amide\n");
8285
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8286
    printf ("tertiary carboxylic acid amide\n");
8287
  if (fg[fg_lactam - 1])
8288
    printf ("lactam\n");
8289
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8290
    printf ("carboxylic acid hydrazide\n");
8291
  if (fg[fg_carboxylic_acid_azide - 1])
8292
    printf ("carboxylic acid azide\n");
8293
  if (fg[fg_hydroxamic_acid - 1])
8294
    printf ("hydroxamic acid\n");
8295
  if (fg[fg_carboxylic_acid_amidine - 1])
8296
    printf ("carboxylic acid amidine\n");
8297
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8298
    printf ("carboxylic acid amidrazone\n");
8299
  if (fg[fg_nitrile - 1])
8300
    printf ("carbonitrile\n");
8301
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
8302
  if (fg[fg_acyl_fluoride - 1])
8303
    printf ("acyl fluoride\n");
8304
  if (fg[fg_acyl_chloride - 1])
8305
    printf ("acyl chloride\n");
8306
  if (fg[fg_acyl_bromide - 1])
8307
    printf ("acyl bromide\n");
8308
  if (fg[fg_acyl_iodide - 1])
8309
    printf ("acyl iodide\n");
8310
  if (fg[fg_acyl_cyanide - 1])
8311
    printf ("acyl cyanide\n");
8312
  if (fg[fg_imido_ester - 1])
8313
    printf ("imido ester\n");
8314
  if (fg[fg_imidoyl_halide - 1])
8315
    printf ("imidoyl halide\n");
8316
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
8317
  if (fg[fg_thiocarboxylic_acid - 1])
8318
    printf ("thiocarboxylic acid\n");
8319
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8320
    printf ("thiocarboxylic acid ester\n");
8321
  if (fg[fg_thiolactone - 1])
8322
    printf ("thiolactone\n");
8323
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8324
    printf ("thiocarboxylic acid amide\n");
8325
  if (fg[fg_thiolactam - 1])
8326
    printf ("thiolactam\n");
8327
  if (fg[fg_imido_thioester - 1])
8328
    printf ("imidothioester\n");
8329
  if (fg[fg_oxohetarene - 1])
8330
    printf ("oxo(het)arene\n");
8331
  if (fg[fg_thioxohetarene - 1])
8332
    printf ("thioxo(het)arene\n");
8333
  if (fg[fg_iminohetarene - 1])
8334
    printf ("imino(het)arene\n");
8335
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8336
    printf ("orthocarboxylic acid derivative\n");
8337
  if (fg[fg_carboxylic_acid_orthoester - 1])
8338
    printf ("orthoester\n");
8339
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8340
    printf ("amide acetal\n");
8341
  if (fg[fg_carboxylic_acid_anhydride - 1])
8342
    printf ("carboxylic acid anhydride\n");
8343
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
8344
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8345
    printf ("carboxylic acid imide, N-unsubstituted\n");
8346
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8347
    printf ("carboxylic acid imide, N-substituted\n");
8348
  if (fg[fg_co2_deriv - 1])
8349
    printf ("CO2 derivative (general)\n");
8350
  if (fg[fg_carbonic_acid_deriv - 1] &&
8351
      !(fg[fg_carbonic_acid_monoester - 1]
8352
        || fg[fg_carbonic_acid_diester - 1]
8353
        || fg[fg_carbonic_acid_ester_halide - 1]))
8354
    /* changed in v0.3c */
8355
    printf ("carbonic acid derivative\n");
8356
  if (fg[fg_carbonic_acid_monoester - 1])
8357
    printf ("carbonic acid monoester\n");
8358
  if (fg[fg_carbonic_acid_diester - 1])
8359
    printf ("carbonic acid diester\n");
8360
  if (fg[fg_carbonic_acid_ester_halide - 1])
8361
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
8362
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8363
    printf ("thiocarbonic acid derivative\n");
8364
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8365
    printf ("thiocarbonic acid monoester\n");
8366
  if (fg[fg_thiocarbonic_acid_diester - 1])
8367
    printf ("thiocarbonic acid diester\n");
8368
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
8369
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
8370
  if (fg[fg_carbamic_acid_deriv - 1]
8371
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
8372
           || fg[fg_carbamic_acid_halide - 1]))
8373
    /* changed in v0.3c */
8374
    printf ("carbamic acid derivative\n");
8375
  if (fg[fg_carbamic_acid - 1])
8376
    printf ("carbamic acid\n");
8377
  if (fg[fg_carbamic_acid_ester - 1])
8378
    printf ("carbamic acid ester (urethane)\n");
8379
  if (fg[fg_carbamic_acid_halide - 1])
8380
    printf ("carbamic acid halide (haloformic acid amide)\n");
8381
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8382
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
8383
        || fg[fg_thiocarbamic_acid_halide - 1]))
8384
    /* changed in v0.3c */
8385
    printf ("thiocarbamic acid derivative\n");
8386
  if (fg[fg_thiocarbamic_acid - 1])
8387
    printf ("thiocarbamic acid\n");
8388
  if (fg[fg_thiocarbamic_acid_ester - 1])
8389
    printf ("thiocarbamic acid ester\n");
8390
  if (fg[fg_thiocarbamic_acid_halide - 1])
8391
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
8392
  if (fg[fg_urea - 1])
8393
    printf ("urea\n");
8394
  if (fg[fg_isourea - 1])
8395
    printf ("isourea\n");
8396
  if (fg[fg_thiourea - 1])
8397
    printf ("thiourea\n");
8398
  if (fg[fg_isothiourea - 1])
8399
    printf ("isothiourea\n");
8400
  if (fg[fg_guanidine - 1])
8401
    printf ("guanidine\n");
8402
  if (fg[fg_semicarbazide - 1])
8403
    printf ("semicarbazide\n");
8404
  if (fg[fg_thiosemicarbazide - 1])
8405
    printf ("thiosemicarbazide\n");
8406
  if (fg[fg_azide - 1])
8407
    printf ("azide\n");
8408
  if (fg[fg_azo_compound - 1])
8409
    printf ("azo compound\n");
8410
  if (fg[fg_diazonium_salt - 1])
8411
    printf ("diazonium salt\n");
8412
  if (fg[fg_isonitrile - 1])
8413
    printf ("isonitrile\n");
8414
  if (fg[fg_cyanate - 1])
8415
    printf ("cyanate\n");
8416
  if (fg[fg_isocyanate - 1])
8417
    printf ("isocyanate\n");
8418
  if (fg[fg_thiocyanate - 1])
8419
    printf ("thiocyanate\n");
8420
  if (fg[fg_isothiocyanate - 1])
8421
    printf ("isothiocyanate\n");
8422
  if (fg[fg_carbodiimide - 1])
8423
    printf ("carbodiimide\n");
8424
  if (fg[fg_nitroso_compound - 1])
8425
    printf ("nitroso compound\n");
8426
  if (fg[fg_nitro_compound - 1])
8427
    printf ("nitro compound\n");
8428
  if (fg[fg_nitrite - 1])
8429
    printf ("nitrite\n");
8430
  if (fg[fg_nitrate - 1])
8431
    printf ("nitrate\n");
8432
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
8433
  if (fg[fg_sulfuric_acid - 1])
8434
    printf ("sulfuric acid\n");
8435
  if (fg[fg_sulfuric_acid_monoester - 1])
8436
    printf ("sulfuric acid monoester\n");
8437
  if (fg[fg_sulfuric_acid_diester - 1])
8438
    printf ("sulfuric acid diester\n");
8439
  if (fg[fg_sulfuric_acid_amide_ester - 1])
8440
    printf ("sulfuric acid amide ester\n");
8441
  if (fg[fg_sulfuric_acid_amide - 1])
8442
    printf ("sulfuric acid amide\n");
8443
  if (fg[fg_sulfuric_acid_diamide - 1])
8444
    printf ("sulfuric acid diamide\n");
8445
  if (fg[fg_sulfuryl_halide - 1])
8446
    printf ("sulfuryl halide\n");
8447
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
8448
  if (fg[fg_sulfonic_acid - 1])
8449
    printf ("sulfonic acid\n");
8450
  if (fg[fg_sulfonic_acid_ester - 1])
8451
    printf ("sulfonic acid ester\n");
8452
  if (fg[fg_sulfonamide - 1])
8453
    printf ("sulfonamide\n");
8454
  if (fg[fg_sulfonyl_halide - 1])
8455
    printf ("sulfonyl halide\n");
8456
  if (fg[fg_sulfone - 1])
8457
    printf ("sulfone\n");
8458
  if (fg[fg_sulfoxide - 1])
8459
    printf ("sulfoxide\n");
8460
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
8461
  if (fg[fg_sulfinic_acid - 1])
8462
    printf ("sulfinic acid\n");
8463
  if (fg[fg_sulfinic_acid_ester - 1])
8464
    printf ("sulfinic acid ester\n");
8465
  if (fg[fg_sulfinic_acid_halide - 1])
8466
    printf ("sulfinic acid halide\n");
8467
  if (fg[fg_sulfinic_acid_amide - 1])
8468
    printf ("sulfinic acid amide\n");
8469
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
8470
  if (fg[fg_sulfenic_acid - 1])
8471
    printf ("sulfenic acid\n");
8472
  if (fg[fg_sulfenic_acid_ester - 1])
8473
    printf ("sulfenic acid ester\n");
8474
  if (fg[fg_sulfenic_acid_halide - 1])
8475
    printf ("sulfenic acid halide\n");
8476
  if (fg[fg_sulfenic_acid_amide - 1])
8477
    printf ("sulfenic acid amide\n");
8478
  if (fg[fg_thiol - 1])
8479
    printf ("thiol (sulfanyl compound)\n");
8480
  if (fg[fg_alkylthiol - 1])
8481
    printf ("alkylthiol\n");
8482
  if (fg[fg_arylthiol - 1])
8483
    printf ("arylthiol\n");
8484
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
8485
  if (fg[fg_phosphoric_acid - 1])
8486
    printf ("phosphoric acid\n");
8487
  if (fg[fg_phosphoric_acid_ester - 1])
8488
    printf ("phosphoric acid ester\n");
8489
  if (fg[fg_phosphoric_acid_halide - 1])
8490
    printf ("phosphoric acid halide\n");
8491
  if (fg[fg_phosphoric_acid_amide - 1])
8492
    printf ("phosphoric acid amide\n");
8493
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
8494
  if (fg[fg_thiophosphoric_acid - 1])
8495
    printf ("thiophosphoric acid\n");
8496
  if (fg[fg_thiophosphoric_acid_ester - 1])
8497
    printf ("thiophosphoric acid ester\n");
8498
  if (fg[fg_thiophosphoric_acid_halide - 1])
8499
    printf ("thiophosphoric acid halide\n");
8500
  if (fg[fg_thiophosphoric_acid_amide - 1])
8501
    printf ("thiophosphoric acid amide\n");
8502
  if (fg[fg_phosphonic_acid_deriv - 1])
8503
    printf ("phosphonic acid derivative \n");
8504
  if (fg[fg_phosphonic_acid - 1])
8505
    printf ("phosphonic acid\n");
8506
  if (fg[fg_phosphonic_acid_ester - 1])
8507
    printf ("phosphonic acid ester\n");
8508
  if (fg[fg_phosphine - 1])
8509
    printf ("phosphine\n");
8510
  if (fg[fg_phosphinoxide - 1])
8511
    printf ("phosphine oxide\n");
8512
  if (fg[fg_boronic_acid_deriv - 1])
8513
    printf ("boronic acid derivative\n");
8514
  if (fg[fg_boronic_acid - 1])
8515
    printf ("boronic acid\n");
8516
  if (fg[fg_boronic_acid_ester - 1])
8517
    printf ("boronic acid ester\n");
8518
  if (fg[fg_alkene - 1])
8519
    printf ("alkene\n");
8520
  if (fg[fg_alkyne - 1])
8521
    printf ("alkyne\n");
8522
  if (fg[fg_aromatic - 1])
8523
    printf ("aromatic compound\n");
8524
  if (fg[fg_heterocycle - 1])
8525
    printf ("heterocyclic compound\n");
8526
  if (fg[fg_alpha_aminoacid - 1])
8527
    printf ("alpha-aminoacid\n");
8528
  if (fg[fg_alpha_hydroxyacid - 1])
8529
    printf ("alpha-hydroxyacid\n");
8530
}
8531
 
14179 bpr 8532
static void write_fg_text_de ()
6785 bpr 8533
{
8534
  if (fg[fg_cation - 1])
8535
    printf ("Kation\n");
8536
  if (fg[fg_anion - 1])
8537
    printf ("Anion\n");
8538
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
8539
  if (fg[fg_aldehyde - 1])
8540
    printf ("Aldehyd\n");
8541
  if (fg[fg_ketone - 1])
8542
    printf ("Keton\n");
8543
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
8544
  if (fg[fg_thioaldehyde - 1])
8545
    printf ("Thioaldehyd\n");
8546
  if (fg[fg_thioketone - 1])
8547
    printf ("Thioketon\n");
8548
  if (fg[fg_imine - 1])
8549
    printf ("Imin\n");
8550
  if (fg[fg_hydrazone - 1])
8551
    printf ("Hydrazon\n");
8552
  if (fg[fg_semicarbazone - 1])
8553
    printf ("Semicarbazon\n");
8554
  if (fg[fg_thiosemicarbazone - 1])
8555
    printf ("Thiosemicarbazon\n");
8556
  if (fg[fg_oxime - 1])
8557
    printf ("Oxim\n");
8558
  if (fg[fg_oxime_ether - 1])
8559
    printf ("Oximether\n");
8560
  if (fg[fg_ketene - 1])
8561
    printf ("Keten\n");
8562
  if (fg[fg_ketene_acetal_deriv - 1])
8563
    printf ("Keten-Acetal oder Derivat\n");
8564
  if (fg[fg_carbonyl_hydrate - 1])
8565
    printf ("Carbonyl-Hydrat\n");
8566
  if (fg[fg_hemiacetal - 1])
8567
    printf ("Halbacetal\n");
8568
  if (fg[fg_acetal - 1])
8569
    printf ("Acetal\n");
8570
  if (fg[fg_hemiaminal - 1])
8571
    printf ("Halbaminal\n");
8572
  if (fg[fg_aminal - 1])
8573
    printf ("Aminal\n");
8574
  if (fg[fg_thiohemiaminal - 1])
8575
    printf ("Thiohalbaminal\n");
8576
  if (fg[fg_thioacetal - 1])
8577
    printf ("Thioacetal\n");
8578
  if (fg[fg_enamine - 1])
8579
    printf ("Enamin\n");
8580
  if (fg[fg_enol - 1])
8581
    printf ("Enol\n");
8582
  if (fg[fg_enolether - 1])
8583
    printf ("Enolether\n");
8584
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8585
    printf ("Hydroxy-Verbindung\n");
8586
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
8587
  if (fg[fg_prim_alcohol - 1])
8588
    printf ("prim\344rer Alkohol\n");
14179 bpr 8589
  /* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
6785 bpr 8590
  if (fg[fg_sec_alcohol - 1])
8591
    printf ("sekund\344rer Alkohol\n");
14179 bpr 8592
  /* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
6785 bpr 8593
  if (fg[fg_tert_alcohol - 1])
8594
    printf ("terti\344rer Alkohol\n");
14179 bpr 8595
  /* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
6785 bpr 8596
  if (fg[fg_1_2_diol - 1])
8597
    printf ("1,2-Diol\n");
8598
  if (fg[fg_1_2_aminoalcohol - 1])
8599
    printf ("1,2-Aminoalkohol\n");
8600
  if (fg[fg_phenol - 1])
8601
    printf ("Phenol oder Hydroxyhetaren\n");
8602
  if (fg[fg_1_2_diphenol - 1])
8603
    printf ("1,2-Diphenol\n");
8604
  if (fg[fg_enediol - 1])
8605
    printf ("Endiol\n");
8606
  if (fg[fg_ether - 1] && ether_generic)
8607
    printf ("Ether\n");
8608
  if (fg[fg_dialkylether - 1])
8609
    printf ("Dialkylether\n");
8610
  if (fg[fg_alkylarylether - 1])
8611
    printf ("Alkylarylether \n");
8612
  if (fg[fg_diarylether - 1])
8613
    printf ("Diarylether\n");
8614
  if (fg[fg_thioether - 1])
8615
    printf ("Thioether\n");
8616
  if (fg[fg_disulfide - 1])
8617
    printf ("Disulfid\n");
8618
  if (fg[fg_peroxide - 1])
8619
    printf ("Peroxid\n");
8620
  if (fg[fg_hydroperoxide - 1])
8621
    printf ("Hydroperoxid\n");
8622
  if (fg[fg_hydrazine - 1])
8623
    printf ("Hydrazin-Derivat\n");
8624
  if (fg[fg_hydroxylamine - 1])
8625
    printf ("Hydroxylamin\n");
8626
  if (fg[fg_amine - 1] && amine_generic)
8627
    printf ("Amin\n");
8628
  if (fg[fg_prim_amine - 1])
8629
    printf ("prim\344res Amin\n");
14179 bpr 8630
  /* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
6785 bpr 8631
  if (fg[fg_prim_aliph_amine - 1])
8632
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
14179 bpr 8633
  /* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
6785 bpr 8634
  if (fg[fg_prim_arom_amine - 1])
8635
    printf ("prim\344res aromatisches Amin\n");
14179 bpr 8636
  /* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
6785 bpr 8637
  if (fg[fg_sec_amine - 1])
8638
    printf ("sekund\344res Amin\n");
14179 bpr 8639
  /* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
6785 bpr 8640
  if (fg[fg_sec_aliph_amine - 1])
8641
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
14179 bpr 8642
  /* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
6785 bpr 8643
  if (fg[fg_sec_mixed_amine - 1])
8644
    printf
8645
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8646
  /* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
6785 bpr 8647
  if (fg[fg_sec_arom_amine - 1])
8648
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
14179 bpr 8649
  /* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
6785 bpr 8650
  if (fg[fg_tert_amine - 1])
8651
    printf ("terti\344res Amin\n");
14179 bpr 8652
  /* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
6785 bpr 8653
  if (fg[fg_tert_aliph_amine - 1])
8654
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
14179 bpr 8655
  /* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
6785 bpr 8656
  if (fg[fg_tert_mixed_amine - 1])
8657
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8658
  /* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
6785 bpr 8659
  if (fg[fg_tert_arom_amine - 1])
8660
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
14179 bpr 8661
  /* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
6785 bpr 8662
  if (fg[fg_quart_ammonium - 1])
8663
    printf ("quart\344res Ammoniumsalz\n");
14179 bpr 8664
  /* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
6785 bpr 8665
  if (fg[fg_n_oxide - 1])
8666
    printf ("N-Oxid\n");
8667
  /* new in v0.2f */
14179 bpr 8668
  if (fg[fg_halogen_deriv - 1]) {
8669
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
8670
              !fg[fg_acyl_halide - 1])
8671
            printf ("Halogenverbindung\n");
8672
  }
6785 bpr 8673
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
8674
  if (fg[fg_alkyl_fluoride - 1])
8675
    printf ("Alkylfluorid\n");
8676
  if (fg[fg_alkyl_chloride - 1])
8677
    printf ("Alkylchlorid\n");
8678
  if (fg[fg_alkyl_bromide - 1])
8679
    printf ("Alkylbromid\n");
8680
  if (fg[fg_alkyl_iodide - 1])
8681
    printf ("Alkyliodid\n");
8682
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
8683
  if (fg[fg_aryl_fluoride - 1])
8684
    printf ("Arylfluorid\n");
8685
  if (fg[fg_aryl_chloride - 1])
8686
    printf ("Arylchlorid\n");
8687
  if (fg[fg_aryl_bromide - 1])
8688
    printf ("Arylbromid\n");
8689
  if (fg[fg_aryl_iodide - 1])
8690
    printf ("Aryliodid\n");
8691
  if (fg[fg_organometallic - 1])
8692
    printf ("Organometall-Verbindung\n");
8693
  if (fg[fg_organolithium - 1])
8694
    printf ("Organolithium-Verbindung\n");
8695
  if (fg[fg_organomagnesium - 1])
8696
    printf ("Organomagnesium-Verbindung\n");
8697
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
8698
  if (fg[fg_carboxylic_acid - 1])
8699
    printf ("Carbons\344ure\n");
14179 bpr 8700
  /* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
6785 bpr 8701
  if (fg[fg_carboxylic_acid_salt - 1])
8702
    printf ("Carbons\344uresalz\n");
14179 bpr 8703
  /* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
6785 bpr 8704
  if (fg[fg_carboxylic_acid_ester - 1])
8705
    printf ("Carbons\344ureester\n");
14179 bpr 8706
  /* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
6785 bpr 8707
  if (fg[fg_lactone - 1])
8708
    printf ("Lacton\n");
8709
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
8710
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8711
    printf ("prim\344res Carbons\344ureamid\n");
14179 bpr 8712
  /* p2c: checkmol.pas, line 7340:
8713
  * Note: characters >= 128 encountered [281] */
6785 bpr 8714
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8715
    printf ("sekund\344res Carbons\344ureamid\n");
14179 bpr 8716
  /* p2c: checkmol.pas, line 7341:
8717
  * Note: characters >= 128 encountered [281] */
6785 bpr 8718
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8719
    printf ("terti\344res Carbons\344ureamid\n");
14179 bpr 8720
  /* p2c: checkmol.pas, line 7342:
8721
  * Note: characters >= 128 encountered [281] */
6785 bpr 8722
  if (fg[fg_lactam - 1])
8723
    printf ("Lactam\n");
8724
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8725
    printf ("Carbons\344urehydrazid\n");
14179 bpr 8726
  /* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
6785 bpr 8727
  if (fg[fg_carboxylic_acid_azide - 1])
8728
    printf ("Carbons\344ureazid\n");
14179 bpr 8729
  /* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
6785 bpr 8730
  if (fg[fg_hydroxamic_acid - 1])
8731
    printf ("Hydroxams\344ure\n");
14179 bpr 8732
  /* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
6785 bpr 8733
  if (fg[fg_carboxylic_acid_amidine - 1])
8734
    printf ("Carbons\344ureamidin\n");
14179 bpr 8735
  /* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
6785 bpr 8736
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8737
    printf ("Carbons\344ureamidrazon\n");
14179 bpr 8738
  /* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
6785 bpr 8739
  if (fg[fg_nitrile - 1])
8740
    printf ("Carbonitril\n");
8741
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
8742
  if (fg[fg_acyl_fluoride - 1])
8743
    printf ("Acylfluorid\n");
8744
  if (fg[fg_acyl_chloride - 1])
8745
    printf ("Acylchlorid\n");
8746
  if (fg[fg_acyl_bromide - 1])
8747
    printf ("Acylbromid\n");
8748
  if (fg[fg_acyl_iodide - 1])
8749
    printf ("Acyliodid\n");
8750
  if (fg[fg_acyl_cyanide - 1])
8751
    printf ("Acylcyanid\n");
8752
  if (fg[fg_imido_ester - 1])
8753
    printf ("Imidoester\n");
8754
  if (fg[fg_imidoyl_halide - 1])
8755
    printf ("Imidoylhalogenid\n");
8756
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
8757
  if (fg[fg_thiocarboxylic_acid - 1])
8758
    printf ("Thiocarbons\344ure\n");
14179 bpr 8759
  /* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
6785 bpr 8760
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8761
    printf ("Thiocarbons\344ureester\n");
14179 bpr 8762
  /* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
6785 bpr 8763
  if (fg[fg_thiolactone - 1])
8764
    printf ("Thiolacton\n");
8765
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8766
    printf ("Thiocarbons\344ureamid\n");
14179 bpr 8767
  /* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
6785 bpr 8768
  if (fg[fg_thiolactam - 1])
8769
    printf ("Thiolactam\n");
8770
  if (fg[fg_imido_thioester - 1])
8771
    printf ("Imidothioester\n");
8772
  if (fg[fg_oxohetarene - 1])
8773
    printf ("Oxo(het)aren\n");
8774
  if (fg[fg_thioxohetarene - 1])
8775
    printf ("Thioxo(het)aren\n");
8776
  if (fg[fg_iminohetarene - 1])
8777
    printf ("Imino(het)aren\n");
8778
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8779
    printf ("Orthocarbons\344ure-Derivat\n");
14179 bpr 8780
  /* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
6785 bpr 8781
  if (fg[fg_carboxylic_acid_orthoester - 1])
8782
    printf ("Orthoester\n");
8783
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8784
    printf ("Amidacetal\n");
8785
  if (fg[fg_carboxylic_acid_anhydride - 1])
8786
    printf ("Carbons\344ureanhydrid\n");
14179 bpr 8787
  /* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
6785 bpr 8788
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
8789
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8790
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
14179 bpr 8791
  /* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
6785 bpr 8792
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8793
    printf ("Carbons\344ureimid, N-substituiert\n");
14179 bpr 8794
  /* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
6785 bpr 8795
  if (fg[fg_co2_deriv - 1])
8796
    printf ("CO2-Derivat (allgemein)\n");
14179 bpr 8797
  if (fg[fg_carbonic_acid_deriv - 1] && !(fg[fg_carbonic_acid_monoester - 1]
8798
            || fg[fg_carbonic_acid_diester - 1] || fg[fg_carbonic_acid_ester_halide - 1]))
6785 bpr 8799
    /* changed in v0.3c */
8800
    printf ("Kohlens\344ure-Derivat\n");
14179 bpr 8801
  /* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
6785 bpr 8802
  if (fg[fg_carbonic_acid_monoester - 1])
8803
    printf ("Kohlens\344uremonoester\n");
14179 bpr 8804
  /* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
6785 bpr 8805
  if (fg[fg_carbonic_acid_diester - 1])
8806
    printf ("Kohlens\344urediester\n");
14179 bpr 8807
  /* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
6785 bpr 8808
  if (fg[fg_carbonic_acid_ester_halide - 1])
8809
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
14179 bpr 8810
  /* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
6785 bpr 8811
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8812
    printf ("Thiokohlens\344ure-Derivat\n");
14179 bpr 8813
  /* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
6785 bpr 8814
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8815
    printf ("Thiokohlens\344uremonoester\n");
14179 bpr 8816
  /* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
6785 bpr 8817
  if (fg[fg_thiocarbonic_acid_diester - 1])
8818
    printf ("Thiokohlens\344urediester\n");
14179 bpr 8819
  /* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
6785 bpr 8820
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
14179 bpr 8821
    printf ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
8822
  /* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
6785 bpr 8823
  if (fg[fg_carbamic_acid_deriv - 1] &&
8824
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
14179 bpr 8825
            fg[fg_carbamic_acid_halide - 1]))
6785 bpr 8826
    /* changed in v0.3c */
8827
    printf ("Carbamins\344ure-Derivat\n");
14179 bpr 8828
  /* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
6785 bpr 8829
  if (fg[fg_carbamic_acid - 1])
8830
    printf ("Carbamins\344ure\n");
14179 bpr 8831
  /* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
6785 bpr 8832
  if (fg[fg_carbamic_acid_ester - 1])
8833
    printf ("Carbamins\344ureester (Urethan)\n");
14179 bpr 8834
  /* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
6785 bpr 8835
  if (fg[fg_carbamic_acid_halide - 1])
8836
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
14179 bpr 8837
  /* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
6785 bpr 8838
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8839
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
14179 bpr 8840
            || fg[fg_thiocarbamic_acid_halide - 1]))
6785 bpr 8841
    /* changed in v0.3c */
8842
    printf ("Thiocarbamins\344ure-Derivat\n");
14179 bpr 8843
  /* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
6785 bpr 8844
  if (fg[fg_thiocarbamic_acid - 1])
8845
    printf ("Thiocarbamins\344ure\n");
14179 bpr 8846
  /* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
6785 bpr 8847
  if (fg[fg_thiocarbamic_acid_ester - 1])
8848
    printf ("Thiocarbamins\344ureester\n");
14179 bpr 8849
  /* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
6785 bpr 8850
  if (fg[fg_thiocarbamic_acid_halide - 1])
8851
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
14179 bpr 8852
  /* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
6785 bpr 8853
  if (fg[fg_urea - 1])
8854
    printf ("Harnstoff\n");
8855
  if (fg[fg_isourea - 1])
8856
    printf ("Isoharnstoff\n");
8857
  if (fg[fg_thiourea - 1])
8858
    printf ("Thioharnstoff\n");
8859
  if (fg[fg_isothiourea - 1])
8860
    printf ("Isothioharnstoff\n");
8861
  if (fg[fg_guanidine - 1])
8862
    printf ("Guanidin\n");
8863
  if (fg[fg_semicarbazide - 1])
8864
    printf ("Semicarbazid\n");
8865
  if (fg[fg_thiosemicarbazide - 1])
8866
    printf ("Thiosemicarbazid\n");
8867
  if (fg[fg_azide - 1])
8868
    printf ("Azid\n");
8869
  if (fg[fg_azo_compound - 1])
8870
    printf ("Azoverbindung\n");
8871
  if (fg[fg_diazonium_salt - 1])
8872
    printf ("Diazoniumsalz\n");
8873
  if (fg[fg_isonitrile - 1])
8874
    printf ("Isonitril\n");
8875
  if (fg[fg_cyanate - 1])
8876
    printf ("Cyanat\n");
8877
  if (fg[fg_isocyanate - 1])
8878
    printf ("Isocyanat\n");
8879
  if (fg[fg_thiocyanate - 1])
8880
    printf ("Thiocyanat\n");
8881
  if (fg[fg_isothiocyanate - 1])
8882
    printf ("Isothiocyanat\n");
8883
  if (fg[fg_carbodiimide - 1])
8884
    printf ("Carbodiimid\n");
8885
  if (fg[fg_nitroso_compound - 1])
8886
    printf ("Nitroso-Verbindung\n");
8887
  if (fg[fg_nitro_compound - 1])
8888
    printf ("Nitro-Verbindung\n");
8889
  if (fg[fg_nitrite - 1])
8890
    printf ("Nitrit\n");
8891
  if (fg[fg_nitrate - 1])
8892
    printf ("Nitrat\n");
8893
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
8894
  if (fg[fg_sulfuric_acid - 1])
8895
    printf ("Schwefels\344ure\n");
14179 bpr 8896
  /* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
6785 bpr 8897
  if (fg[fg_sulfuric_acid_monoester - 1])
8898
    printf ("Schwefels\344uremonoester\n");
14179 bpr 8899
  /* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
6785 bpr 8900
  if (fg[fg_sulfuric_acid_diester - 1])
8901
    printf ("Schwefels\344urediester\n");
14179 bpr 8902
  /* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
6785 bpr 8903
  if (fg[fg_sulfuric_acid_amide_ester - 1])
8904
    printf ("Schwefels\344ureamidester\n");
14179 bpr 8905
  /* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
6785 bpr 8906
  if (fg[fg_sulfuric_acid_amide - 1])
8907
    printf ("Schwefels\344ureamid\n");
14179 bpr 8908
  /* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
6785 bpr 8909
  if (fg[fg_sulfuric_acid_diamide - 1])
8910
    printf ("Schwefels\344urediamid\n");
14179 bpr 8911
  /* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
6785 bpr 8912
  if (fg[fg_sulfuryl_halide - 1])
8913
    printf ("Sulfurylhalogenid\n");
8914
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
8915
  if (fg[fg_sulfonic_acid - 1])
8916
    printf ("Sulfons\344ure\n");
14179 bpr 8917
  /* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
6785 bpr 8918
  if (fg[fg_sulfonic_acid_ester - 1])
8919
    printf ("Sulfons\344ureester\n");
14179 bpr 8920
  /* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
6785 bpr 8921
  if (fg[fg_sulfonamide - 1])
8922
    printf ("Sulfonamid\n");
8923
  if (fg[fg_sulfonyl_halide - 1])
8924
    printf ("Sulfonylhalogenid\n");
8925
  if (fg[fg_sulfone - 1])
8926
    printf ("Sulfon\n");
8927
  if (fg[fg_sulfoxide - 1])
8928
    printf ("Sulfoxid\n");
8929
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
8930
  if (fg[fg_sulfinic_acid - 1])
8931
    printf ("Sulfins\344ure\n");
14179 bpr 8932
  /* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
6785 bpr 8933
  if (fg[fg_sulfinic_acid_ester - 1])
8934
    printf ("Sulfins\344ureester\n");
14179 bpr 8935
  /* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
6785 bpr 8936
  if (fg[fg_sulfinic_acid_halide - 1])
8937
    printf ("Sulfins\344urehalogenid\n");
14179 bpr 8938
  /* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
6785 bpr 8939
  if (fg[fg_sulfinic_acid_amide - 1])
8940
    printf ("Sulfins\344ureamid\n");
14179 bpr 8941
  /* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
6785 bpr 8942
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
8943
  if (fg[fg_sulfenic_acid - 1])
8944
    printf ("Sulfens\344ure\n");
14179 bpr 8945
  /* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
6785 bpr 8946
  if (fg[fg_sulfenic_acid_ester - 1])
8947
    printf ("Sulfens\344ureester\n");
14179 bpr 8948
  /* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
6785 bpr 8949
  if (fg[fg_sulfenic_acid_halide - 1])
8950
    printf ("Sulfens\344urehalogenid\n");
14179 bpr 8951
  /* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
6785 bpr 8952
  if (fg[fg_sulfenic_acid_amide - 1])
8953
    printf ("Sulfens\344ureamid\n");
14179 bpr 8954
  /* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
6785 bpr 8955
  if (fg[fg_thiol - 1])
8956
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
8957
  if (fg[fg_alkylthiol - 1])
8958
    printf ("Alkylthiol\n");
8959
  if (fg[fg_arylthiol - 1])
8960
    printf ("Arylthiol\n");
8961
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
8962
  if (fg[fg_phosphoric_acid - 1])
8963
    printf ("Phosphors\344ure\n");
14179 bpr 8964
  /* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
6785 bpr 8965
  if (fg[fg_phosphoric_acid_ester - 1])
8966
    printf ("Phosphors\344ureester\n");
14179 bpr 8967
  /* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
6785 bpr 8968
  if (fg[fg_phosphoric_acid_halide - 1])
8969
    printf ("Phosphors\344urehalogenid\n");
14179 bpr 8970
  /* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
6785 bpr 8971
  if (fg[fg_phosphoric_acid_amide - 1])
8972
    printf ("Phosphors\344ureamid\n");
14179 bpr 8973
  /* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
6785 bpr 8974
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
8975
  if (fg[fg_thiophosphoric_acid - 1])
8976
    printf ("Thiophosphors\344ure\n");
14179 bpr 8977
  /* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
6785 bpr 8978
  if (fg[fg_thiophosphoric_acid_ester - 1])
8979
    printf ("Thiophosphors\344ureester\n");
14179 bpr 8980
  /* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
6785 bpr 8981
  if (fg[fg_thiophosphoric_acid_halide - 1])
8982
    printf ("Thiophosphors\344urehalogenid\n");
14179 bpr 8983
  /* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
6785 bpr 8984
  if (fg[fg_thiophosphoric_acid_amide - 1])
8985
    printf ("Thiophosphors\344ureamid\n");
14179 bpr 8986
  /* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
6785 bpr 8987
  if (fg[fg_phosphonic_acid_deriv - 1])
8988
    printf ("Phosphons\344ure-Derivat \n");
14179 bpr 8989
  /* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
6785 bpr 8990
  if (fg[fg_phosphonic_acid - 1])
8991
    printf ("Phosphons\344ure\n");
14179 bpr 8992
  /* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
6785 bpr 8993
  if (fg[fg_phosphonic_acid_ester - 1])
8994
    printf ("Phosphons\344ureester\n");
14179 bpr 8995
  /* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
6785 bpr 8996
  if (fg[fg_phosphine - 1])
8997
    printf ("Phosphin\n");
8998
  if (fg[fg_phosphinoxide - 1])
8999
    printf ("Phosphinoxid\n");
9000
  if (fg[fg_boronic_acid_deriv - 1])
9001
    printf ("Borons\344ure-Derivat\n");
14179 bpr 9002
  /* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
6785 bpr 9003
  if (fg[fg_boronic_acid - 1])
9004
    printf ("Borons\344ure\n");
14179 bpr 9005
  /* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
6785 bpr 9006
  if (fg[fg_boronic_acid_ester - 1])
9007
    printf ("Borons\344ureester\n");
14179 bpr 9008
  /* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
6785 bpr 9009
  if (fg[fg_alkene - 1])
9010
    printf ("Alken\n");
9011
  if (fg[fg_alkyne - 1])
9012
    printf ("Alkin\n");
9013
  if (fg[fg_aromatic - 1])
9014
    printf ("aromatische Verbindung\n");
9015
  if (fg[fg_heterocycle - 1])
9016
    printf ("heterocyclische Verbindung\n");
9017
  if (fg[fg_alpha_aminoacid - 1])
9018
    printf ("alpha-Aminos\344ure\n");
14179 bpr 9019
  /* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
6785 bpr 9020
  if (fg[fg_alpha_hydroxyacid - 1])
9021
    printf ("alpha-Hydroxys\344ure\n");
14179 bpr 9022
  /* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
6785 bpr 9023
}
9024
 
9025
#define sc              ';'
9026
 
14179 bpr 9027
static void write_fg_code ()
6785 bpr 9028
{
9029
  if (fg[fg_cation - 1])
9030
    printf ("000000T2%c", sc);
9031
  if (fg[fg_anion - 1])
9032
    printf ("000000T1%c", sc);
9033
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
9034
  if (fg[fg_aldehyde - 1])
9035
    printf ("C2O1H000%c", sc);
9036
  if (fg[fg_ketone - 1])
9037
    printf ("C2O1C000%c", sc);
9038
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
9039
  if (fg[fg_thioaldehyde - 1])
9040
    printf ("C2S1H000%c", sc);
9041
  if (fg[fg_thioketone - 1])
9042
    printf ("C2S1C000%c", sc);
9043
  if (fg[fg_imine - 1])
9044
    printf ("C2N10000%c", sc);
9045
  if (fg[fg_hydrazone - 1])
9046
    printf ("C2N1N000%c", sc);
9047
  if (fg[fg_semicarbazone - 1])
9048
    printf ("C2NNC4ON%c", sc);
9049
  if (fg[fg_thiosemicarbazone - 1])
9050
    printf ("C2NNC4SN%c", sc);
9051
  if (fg[fg_oxime - 1])
9052
    printf ("C2N1OH00%c", sc);
9053
  if (fg[fg_oxime_ether - 1])
9054
    printf ("C2N1OC00%c", sc);
9055
  if (fg[fg_ketene - 1])
9056
    printf ("C3OC0000%c", sc);
9057
  if (fg[fg_ketene_acetal_deriv - 1])
9058
    printf ("C3OCC000%c", sc);
9059
  if (fg[fg_carbonyl_hydrate - 1])
9060
    printf ("C2O2H200%c", sc);
9061
  if (fg[fg_hemiacetal - 1])
9062
    printf ("C2O2HC00%c", sc);
9063
  if (fg[fg_acetal - 1])
9064
    printf ("C2O2CC00%c", sc);
9065
  if (fg[fg_hemiaminal - 1])
9066
    printf ("C2NOHC10%c", sc);
9067
  if (fg[fg_aminal - 1])
9068
    printf ("C2N2CC10%c", sc);
9069
  if (fg[fg_thiohemiaminal - 1])
9070
    printf ("C2NSHC10%c", sc);
9071
  if (fg[fg_thioacetal - 1])
9072
    printf ("C2S2CC00%c", sc);
9073
  if (fg[fg_enamine - 1])
9074
    printf ("C2CNH000%c", sc);
9075
  if (fg[fg_enol - 1])
9076
    printf ("C2COH000%c", sc);
9077
  if (fg[fg_enolether - 1])
9078
    printf ("C2COC000%c", sc);
9079
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9080
    printf ("O1H00000%c", sc);
9081
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
9082
  if (fg[fg_prim_alcohol - 1])
9083
    printf ("O1H1C000%c", sc);
9084
  if (fg[fg_sec_alcohol - 1])
9085
    printf ("O1H2C000%c", sc);
9086
  if (fg[fg_tert_alcohol - 1])
9087
    printf ("O1H3C000%c", sc);
9088
  if (fg[fg_1_2_diol - 1])
9089
    printf ("O1H0CO1H%c", sc);
9090
  if (fg[fg_1_2_aminoalcohol - 1])
9091
    printf ("O1H0CN1C%c", sc);
9092
  if (fg[fg_phenol - 1])
9093
    printf ("O1H1A000%c", sc);
9094
  if (fg[fg_1_2_diphenol - 1])
9095
    printf ("O1H2A000%c", sc);
9096
  if (fg[fg_enediol - 1])
9097
    printf ("C2COH200%c", sc);
9098
  if (fg[fg_ether - 1] && ether_generic)
9099
    printf ("O1C00000%c", sc);
9100
  if (fg[fg_dialkylether - 1])
9101
    printf ("O1C0CC00%c", sc);
9102
  if (fg[fg_alkylarylether - 1])
9103
    printf ("O1C0CA00%c", sc);
9104
  if (fg[fg_diarylether - 1])
9105
    printf ("O1C0AA00%c", sc);
9106
  if (fg[fg_thioether - 1])
9107
    printf ("S1C00000%c", sc);
9108
  if (fg[fg_disulfide - 1])
9109
    printf ("S1S1C000%c", sc);
9110
  if (fg[fg_peroxide - 1])
9111
    printf ("O1O1C000%c", sc);
9112
  if (fg[fg_hydroperoxide - 1])
9113
    printf ("O1O1H000%c", sc);
9114
  if (fg[fg_hydrazine - 1])
9115
    printf ("N1N10000%c", sc);
9116
  if (fg[fg_hydroxylamine - 1])
9117
    printf ("N1O1H000%c", sc);
9118
  if (fg[fg_amine - 1] && amine_generic)
9119
    printf ("N1C00000%c", sc);
9120
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
9121
  if (fg[fg_prim_aliph_amine - 1])
9122
    printf ("N1C1C000%c", sc);
9123
  if (fg[fg_prim_arom_amine - 1])
9124
    printf ("N1C1A000%c", sc);
9125
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
9126
  if (fg[fg_sec_aliph_amine - 1])
9127
    printf ("N1C2CC00%c", sc);
9128
  if (fg[fg_sec_mixed_amine - 1])
9129
    printf ("N1C2AC00%c", sc);
9130
  if (fg[fg_sec_arom_amine - 1])
9131
    printf ("N1C2AA00%c", sc);
9132
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
9133
  if (fg[fg_tert_aliph_amine - 1])
9134
    printf ("N1C3CC00%c", sc);
9135
  if (fg[fg_tert_mixed_amine - 1])
9136
    printf ("N1C3AC00%c", sc);
9137
  if (fg[fg_tert_arom_amine - 1])
9138
    printf ("N1C3AA00%c", sc);
9139
  if (fg[fg_quart_ammonium - 1])
9140
    printf ("N1C400T2%c", sc);
9141
  if (fg[fg_n_oxide - 1])
9142
    printf ("N0O10000%c", sc);
9143
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
9144
  /* new in v0.2f */
14179 bpr 9145
  if (fg[fg_halogen_deriv - 1]) {
9146
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1])
9147
              printf ("XX000000%c", sc);
9148
  }
6785 bpr 9149
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
9150
  if (fg[fg_alkyl_fluoride - 1])
9151
    printf ("XF00C000%c", sc);
9152
  if (fg[fg_alkyl_chloride - 1])
9153
    printf ("XC00C000%c", sc);
9154
  if (fg[fg_alkyl_bromide - 1])
9155
    printf ("XB00C000%c", sc);
9156
  if (fg[fg_alkyl_iodide - 1])
9157
    printf ("XI00C000%c", sc);
9158
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
9159
  if (fg[fg_aryl_fluoride - 1])
9160
    printf ("XF00A000%c", sc);
9161
  if (fg[fg_aryl_chloride - 1])
9162
    printf ("XC00A000%c", sc);
9163
  if (fg[fg_aryl_bromide - 1])
9164
    printf ("XB00A000%c", sc);
9165
  if (fg[fg_aryl_iodide - 1])
9166
    printf ("XI00A000%c", sc);
9167
  if (fg[fg_organometallic - 1])
9168
    printf ("000000MX%c", sc);
9169
  if (fg[fg_organolithium - 1])
9170
    printf ("000000ML%c", sc);
9171
  if (fg[fg_organomagnesium - 1])
9172
    printf ("000000MM%c", sc);
9173
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
9174
  if (fg[fg_carboxylic_acid - 1])
9175
    printf ("C3O2H000%c", sc);
9176
  if (fg[fg_carboxylic_acid_salt - 1])
9177
    printf ("C3O200T1%c", sc);
9178
  if (fg[fg_carboxylic_acid_ester - 1])
9179
    printf ("C3O2C000%c", sc);
9180
  if (fg[fg_lactone - 1])
9181
    printf ("C3O2CZ00%c", sc);
9182
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
9183
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9184
    printf ("C3ONC100%c", sc);
9185
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9186
    printf ("C3ONC200%c", sc);
9187
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9188
    printf ("C3ONC300%c", sc);
9189
  if (fg[fg_lactam - 1])
9190
    printf ("C3ONCZ00%c", sc);
9191
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9192
    printf ("C3ONN100%c", sc);
9193
  if (fg[fg_carboxylic_acid_azide - 1])
9194
    printf ("C3ONN200%c", sc);
9195
  if (fg[fg_hydroxamic_acid - 1])
9196
    printf ("C3ONOH00%c", sc);
9197
  if (fg[fg_carboxylic_acid_amidine - 1])
9198
    printf ("C3N2H000%c", sc);
9199
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9200
    printf ("C3NNN100%c", sc);
9201
  if (fg[fg_nitrile - 1])
9202
    printf ("C3N00000%c", sc);
9203
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
9204
  if (fg[fg_acyl_fluoride - 1])
9205
    printf ("C3OXF000%c", sc);
9206
  if (fg[fg_acyl_chloride - 1])
9207
    printf ("C3OXC000%c", sc);
9208
  if (fg[fg_acyl_bromide - 1])
9209
    printf ("C3OXB000%c", sc);
9210
  if (fg[fg_acyl_iodide - 1])
9211
    printf ("C3OXI000%c", sc);
9212
  if (fg[fg_acyl_cyanide - 1])
9213
    printf ("C2OC3N00%c", sc);
9214
  if (fg[fg_imido_ester - 1])
9215
    printf ("C3NOC000%c", sc);
9216
  if (fg[fg_imidoyl_halide - 1])
9217
    printf ("C3NXX000%c", sc);
9218
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
9219
  if (fg[fg_thiocarboxylic_acid - 1])
9220
    printf ("C3SOH000%c", sc);
9221
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9222
    printf ("C3SOC000%c", sc);
9223
  if (fg[fg_thiolactone - 1])
9224
    printf ("C3SOCZ00%c", sc);
9225
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9226
    printf ("C3SNH000%c", sc);
9227
  if (fg[fg_thiolactam - 1])
9228
    printf ("C3SNCZ00%c", sc);
9229
  if (fg[fg_imido_thioester - 1])
9230
    printf ("C3NSC000%c", sc);
9231
  if (fg[fg_oxohetarene - 1])
9232
    printf ("C3ONAZ00%c", sc);
9233
  if (fg[fg_thioxohetarene - 1])
9234
    printf ("C3SNAZ00%c", sc);
9235
  if (fg[fg_iminohetarene - 1])
9236
    printf ("C3NNAZ00%c", sc);
9237
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9238
    printf ("C3O30000%c", sc);
9239
  if (fg[fg_carboxylic_acid_orthoester - 1])
9240
    printf ("C3O3C000%c", sc);
9241
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9242
    printf ("C3O3NC00%c", sc);
9243
  if (fg[fg_carboxylic_acid_anhydride - 1])
9244
    printf ("C3O2C3O2%c", sc);
9245
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
9246
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9247
    printf ("C3ONCH10%c", sc);
9248
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9249
    printf ("C3ONCC10%c", sc);
9250
  if (fg[fg_co2_deriv - 1])
9251
    printf ("C4000000%c", sc);
9252
  if (fg[fg_carbonic_acid_deriv - 1])
9253
    printf ("C4O30000%c", sc);
9254
  if (fg[fg_carbonic_acid_monoester - 1])
9255
    printf ("C4O3C100%c", sc);
9256
  if (fg[fg_carbonic_acid_diester - 1])
9257
    printf ("C4O3C200%c", sc);
9258
  if (fg[fg_carbonic_acid_ester_halide - 1])
9259
    printf ("C4O3CX00%c", sc);
9260
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9261
    printf ("C4SO0000%c", sc);
9262
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9263
    printf ("C4SOC100%c", sc);
9264
  if (fg[fg_thiocarbonic_acid_diester - 1])
9265
    printf ("C4SOC200%c", sc);
9266
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9267
    printf ("C4SOX_00%c", sc);
9268
  if (fg[fg_carbamic_acid_deriv - 1])
9269
    printf ("C4O2N000%c", sc);
9270
  if (fg[fg_carbamic_acid - 1])
9271
    printf ("C4O2NH00%c", sc);
9272
  if (fg[fg_carbamic_acid_ester - 1])
9273
    printf ("C4O2NC00%c", sc);
9274
  if (fg[fg_carbamic_acid_halide - 1])
9275
    printf ("C4O2NX00%c", sc);
9276
  if (fg[fg_thiocarbamic_acid_deriv - 1])
9277
    printf ("C4SN0000%c", sc);
9278
  if (fg[fg_thiocarbamic_acid - 1])
9279
    printf ("C4SNOH00%c", sc);
9280
  if (fg[fg_thiocarbamic_acid_ester - 1])
9281
    printf ("C4SNOC00%c", sc);
9282
  if (fg[fg_thiocarbamic_acid_halide - 1])
9283
    printf ("C4SNXX00%c", sc);
9284
  if (fg[fg_urea - 1])
9285
    printf ("C4O1N200%c", sc);
9286
  if (fg[fg_isourea - 1])
9287
    printf ("C4N2O100%c", sc);
9288
  if (fg[fg_thiourea - 1])
9289
    printf ("C4S1N200%c", sc);
9290
  if (fg[fg_isothiourea - 1])
9291
    printf ("C4N2S100%c", sc);
9292
  if (fg[fg_guanidine - 1])
9293
    printf ("C4N30000%c", sc);
9294
  if (fg[fg_semicarbazide - 1])
9295
    printf ("C4ON2N00%c", sc);
9296
  if (fg[fg_thiosemicarbazide - 1])
9297
    printf ("C4SN2N00%c", sc);
9298
  if (fg[fg_azide - 1])
9299
    printf ("N4N20000%c", sc);
9300
  if (fg[fg_azo_compound - 1])
9301
    printf ("N2N10000%c", sc);
9302
  if (fg[fg_diazonium_salt - 1])
9303
    printf ("N3N100T2%c", sc);
9304
  if (fg[fg_isonitrile - 1])
9305
    printf ("N3C10000%c", sc);
9306
  if (fg[fg_cyanate - 1])
9307
    printf ("C4NO1000%c", sc);
9308
  if (fg[fg_isocyanate - 1])
9309
    printf ("C4NO2000%c", sc);
9310
  if (fg[fg_thiocyanate - 1])
9311
    printf ("C4NS1000%c", sc);
9312
  if (fg[fg_isothiocyanate - 1])
9313
    printf ("C4NS2000%c", sc);
9314
  if (fg[fg_carbodiimide - 1])
9315
    printf ("C4N20000%c", sc);
9316
  if (fg[fg_nitroso_compound - 1])
9317
    printf ("N2O10000%c", sc);
9318
  if (fg[fg_nitro_compound - 1])
9319
    printf ("N4O20000%c", sc);
9320
  if (fg[fg_nitrite - 1])
9321
    printf ("N3O20000%c", sc);
9322
  if (fg[fg_nitrate - 1])
9323
    printf ("N4O30000%c", sc);
9324
  if (fg[fg_sulfuric_acid_deriv - 1])
9325
    printf ("S6O00000%c", sc);
9326
  if (fg[fg_sulfuric_acid - 1])
9327
    printf ("S6O4H000%c", sc);
9328
  if (fg[fg_sulfuric_acid_monoester - 1])
9329
    printf ("S6O4HC00%c", sc);
9330
  if (fg[fg_sulfuric_acid_diester - 1])
9331
    printf ("S6O4CC00%c", sc);
9332
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9333
    printf ("S6O3NC00%c", sc);
9334
  if (fg[fg_sulfuric_acid_amide - 1])
9335
    printf ("S6O3N100%c", sc);
9336
  if (fg[fg_sulfuric_acid_diamide - 1])
9337
    printf ("S6O2N200%c", sc);
9338
  if (fg[fg_sulfuryl_halide - 1])
9339
    printf ("S6O3XX00%c", sc);
9340
  if (fg[fg_sulfonic_acid_deriv - 1])
9341
    printf ("S5O00000%c", sc);
9342
  if (fg[fg_sulfonic_acid - 1])
9343
    printf ("S5O3H000%c", sc);
9344
  if (fg[fg_sulfonic_acid_ester - 1])
9345
    printf ("S5O3C000%c", sc);
9346
  if (fg[fg_sulfonamide - 1])
9347
    printf ("S5O2N000%c", sc);
9348
  if (fg[fg_sulfonyl_halide - 1])
9349
    printf ("S5O2XX00%c", sc);
9350
  if (fg[fg_sulfone - 1])
9351
    printf ("S4O20000%c", sc);
9352
  if (fg[fg_sulfoxide - 1])
9353
    printf ("S2O10000%c", sc);
9354
  if (fg[fg_sulfinic_acid_deriv - 1])
9355
    printf ("S3O00000%c", sc);
9356
  if (fg[fg_sulfinic_acid - 1])
9357
    printf ("S3O2H000%c", sc);
9358
  if (fg[fg_sulfinic_acid_ester - 1])
9359
    printf ("S3O2C000%c", sc);
9360
  if (fg[fg_sulfinic_acid_halide - 1])
9361
    printf ("S3O1XX00%c", sc);
9362
  if (fg[fg_sulfinic_acid_amide - 1])
9363
    printf ("S3O1N000%c", sc);
9364
  if (fg[fg_sulfenic_acid_deriv - 1])
9365
    printf ("S1O00000%c", sc);
9366
  if (fg[fg_sulfenic_acid - 1])
9367
    printf ("S1O1H000%c", sc);
9368
  if (fg[fg_sulfenic_acid_ester - 1])
9369
    printf ("S1O1C000%c", sc);
9370
  if (fg[fg_sulfenic_acid_halide - 1])
9371
    printf ("S1O0XX00%c", sc);
9372
  if (fg[fg_sulfenic_acid_amide - 1])
9373
    printf ("S1O0N100%c", sc);
9374
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
9375
  if (fg[fg_alkylthiol - 1])
9376
    printf ("S1H1C000%c", sc);
9377
  if (fg[fg_arylthiol - 1])
9378
    printf ("S1H1A000%c", sc);
9379
  if (fg[fg_phosphoric_acid_deriv - 1])
9380
    printf ("P5O0H000%c", sc);
9381
  if (fg[fg_phosphoric_acid - 1])
9382
    printf ("P5O4H200%c", sc);
9383
  if (fg[fg_phosphoric_acid_ester - 1])
9384
    printf ("P5O4HC00%c", sc);
9385
  if (fg[fg_phosphoric_acid_halide - 1])
9386
    printf ("P5O3HX00%c", sc);
9387
  if (fg[fg_phosphoric_acid_amide - 1])
9388
    printf ("P5O3HN00%c", sc);
9389
  if (fg[fg_thiophosphoric_acid_deriv - 1])
9390
    printf ("P5O0S000%c", sc);
9391
  if (fg[fg_thiophosphoric_acid - 1])
9392
    printf ("P5O3SH00%c", sc);
9393
  if (fg[fg_thiophosphoric_acid_ester - 1])
9394
    printf ("P5O3SC00%c", sc);
9395
  if (fg[fg_thiophosphoric_acid_halide - 1])
9396
    printf ("P5O2SX00%c", sc);
9397
  if (fg[fg_thiophosphoric_acid_amide - 1])
9398
    printf ("P5O2SN00%c", sc);
9399
  if (fg[fg_phosphonic_acid_deriv - 1])
9400
    printf ("P4O30000%c", sc);
9401
  if (fg[fg_phosphonic_acid - 1])
9402
    printf ("P4O3H000%c", sc);
9403
  if (fg[fg_phosphonic_acid_ester - 1])
9404
    printf ("P4O3C000%c", sc);
9405
  if (fg[fg_phosphine - 1])
9406
    printf ("P3000000%c", sc);
9407
  if (fg[fg_phosphinoxide - 1])
9408
    printf ("P2O00000%c", sc);
9409
  if (fg[fg_boronic_acid_deriv - 1])
9410
    printf ("B2O20000%c", sc);
9411
  if (fg[fg_boronic_acid - 1])
9412
    printf ("B2O2H000%c", sc);
9413
  if (fg[fg_boronic_acid_ester - 1])
9414
    printf ("B2O2C000%c", sc);
9415
  if (fg[fg_alkene - 1])
9416
    printf ("000C2C00%c", sc);
9417
  if (fg[fg_alkyne - 1])
9418
    printf ("000C3C00%c", sc);
9419
  if (fg[fg_aromatic - 1])
9420
    printf ("0000A000%c", sc);
9421
  if (fg[fg_heterocycle - 1])
9422
    printf ("0000CZ00%c", sc);
9423
  if (fg[fg_alpha_aminoacid - 1])
9424
    printf ("C3O2HN1C%c", sc);
9425
  if (fg[fg_alpha_hydroxyacid - 1])
9426
    printf ("C3O2HO1H%c", sc);
9427
}
9428
 
9429
#undef sc
9430
 
14179 bpr 9431
static void write_fg_binary ()
6785 bpr 9432
{
9433
  int i, n;
9434
  char o;
9435
 
14179 bpr 9436
  for (i = 1; i <= max_fg / 8; i++) {
9437
    n = 0;
9438
    if (fg[i * 8 - 1])
9439
            n++;
9440
    if (fg[i * 8 - 2])
9441
            n += 2;
9442
    if (fg[i * 8 - 3])
9443
            n += 4;
9444
    if (fg[i * 8 - 4])
9445
            n += 8;
9446
    if (fg[i * 8 - 5])
9447
            n += 16;
9448
    if (fg[i * 8 - 6])
9449
            n += 32;
9450
    if (fg[i * 8 - 7])
9451
            n += 64;
9452
    if (fg[i * 8 - 8])
9453
            n += 128;
9454
    o = (char) n;
9455
    putchar (o);
9456
  }
6785 bpr 9457
}
9458
 
14179 bpr 9459
static void write_fg_bitstring ()
6785 bpr 9460
{
9461
  int i;
9462
 
14179 bpr 9463
  for (i = 0; i < max_fg; i++) {
9464
    if (fg[i])
9465
            putchar ('1');
9466
    else
9467
            putchar ('0');
9468
  }
6785 bpr 9469
}
9470
 
9471
#if 0
9472
static void readinputfile (molfilename) char *molfilename;
14179 bpr 9473
  {
9474
  /* new version in v0.2g */
9475
  char rline[256];
9476
  char *TEMP;
6785 bpr 9477
 
14179 bpr 9478
  molbufindex = 0;
9479
  if (!opt_stdin)
9480
  {
9481
  if (!rfile_is_open)
9482
  {
9483
  assign (rfile, molfilename);
9484
  rewind (rfile);
18544 georgesk 9485
  rfile_is_open = istrue;
14179 bpr 9486
  }
9487
  /* p2c: checkmol.pas, line 7733: Warning:
9488
  * Don't know how to ASSIGN to a non-explicit file variable [207] */
9489
  *rline = '\0';
18544 georgesk 9490
  mol_in_queue = isfalse;
14179 bpr 9491
  while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
9492
  {
9493
  fgets (rline, 256, rfile);
9494
  TEMP = strchr (rline, '\n');
9495
  if (TEMP != NULL)
9496
  *TEMP = 0;
18544 georgesk 9497
  /*mol_in_queue := isfalse; */
14179 bpr 9498
  if (molbufindex >= max_atoms + max_bonds + 64)
9499
  {
9500
  printf ("Not enough memory for molfile! %12ld\n",
9501
  molbufindex);
9502
  if (rfile != NULL)
9503
  fclose (rfile);
9504
  rfile = NULL;
9505
  _Escape (1);
9506
  }
9507
  molbufindex++;
9508
  strcpy (molbuf[molbufindex - 1], rline);
9509
  if (strpos2 (rline, "$$$$", 1) > 0)
18544 georgesk 9510
  mol_in_queue = istrue;
14179 bpr 9511
  }
9512
  if (!P_eof (rfile))
9513
  return;
9514
  if (rfile != NULL)
9515
  fclose (rfile);
9516
  rfile = NULL;
18544 georgesk 9517
  rfile_is_open = isfalse;
9518
  mol_in_queue = isfalse;
14179 bpr 9519
  return;
9520
  }
9521
  *rline = '\0';
18544 georgesk 9522
  mol_in_queue = isfalse;
14179 bpr 9523
  while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
9524
  {
9525
  gets (rline);
9526
  if (molbufindex >= max_atoms + max_bonds + 64)
9527
  {
9528
  printf ("Not enough memory!\n");
9529
  _Escape (1);
9530
  }
9531
  molbufindex++;
9532
  strcpy (molbuf[molbufindex - 1], rline);
9533
  if (strpos2 (rline, "$$$$", 1) > 0)
9534
  {
18544 georgesk 9535
  mol_in_queue = istrue;
14179 bpr 9536
  /* read from standard input
9537
  }
9538
  }
9539
  } */
6785 bpr 9540
#endif
9541
 
14179 bpr 9542
static void readinputfile (char *molfilename)
6785 bpr 9543
{
9544
  /* new version in v0.2g */
9545
  char rline[256];
9546
  char *TEMP;
9547
 
9548
  molbufindex = 0;
14179 bpr 9549
  if (!opt_stdin) {
9550
    if (!rfile_is_open) {
9551
            rfile = fopen (molfilename, "r");
9552
            rewind (rfile);
18544 georgesk 9553
            rfile_is_open = istrue;
14179 bpr 9554
          }
9555
    /* p2c: checkmol.pas, line 7226: Warning:
9556
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
9557
    *rline = '\0';
18544 georgesk 9558
    mol_in_queue = isfalse;
14179 bpr 9559
    while ((fgets (rline, 256, rfile) != NULL) && (strstr (rline, "$$$$") == NULL)) {
9560
            TEMP = strchr (rline, '\n');
9561
            if (TEMP != NULL)
9562
              *TEMP = 0;
18544 georgesk 9563
            /*mol_in_queue := isfalse; */
14179 bpr 9564
            if (molbufindex >= max_atoms + max_bonds + 64) {
6785 bpr 9565
              printf ("Not enough memory for molfile! %d\n", molbufindex);
9566
              if (rfile != NULL)
14179 bpr 9567
                      fclose (rfile);
6785 bpr 9568
              rfile = NULL;
9569
              exit (1);
9570
            }
14179 bpr 9571
            //molbufindex++;
9572
            strcpy (molbuf[molbufindex++], rline);
9573
            if (strstr (rline, "$$$$") != NULL)
18544 georgesk 9574
              mol_in_queue = istrue;
14179 bpr 9575
          }
9576
    if (!feof (rfile))
9577
            return;
9578
    if (rfile != NULL)
9579
            fclose (rfile);
9580
    rfile = NULL;
18544 georgesk 9581
    rfile_is_open = isfalse;
9582
    mol_in_queue = isfalse;
14179 bpr 9583
    return;
9584
  }
6785 bpr 9585
  *rline = '\0';
18544 georgesk 9586
  mol_in_queue = isfalse;
14179 bpr 9587
  do {
9588
    if(fgets (rline, 256, stdin)==NULL || feof (stdin))
9589
            return;
9590
    TEMP = strchr (rline, '\n');
9591
    if (TEMP != NULL)
9592
            *TEMP = '\0';
9593
    if (molbufindex >= max_atoms + max_bonds + 64) {
9594
            printf ("Not enough memory!\n");
9595
            exit (1);
9596
          }
9597
    //molbufindex++;
9598
    strcpy (molbuf[molbufindex++], rline);
9599
    if (strstr (rline, "$$$$") != NULL) {
18544 georgesk 9600
            mol_in_queue = istrue;
14179 bpr 9601
            /* read from standard input */
9602
          }
9603
  }
6785 bpr 9604
  while (strstr (rline, "$$$$") == NULL);
9605
}
9606
 
9607
#if 0
9608
static void copy_mol_to_needle()
9609
{
9610
  int i, j, FORLIM;
9611
 
9612
  if (n_atoms == 0)
9613
    return;
9614
  /* try */
9615
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9616
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9617
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9618
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9619
  /* except*/
9620
    on e:Eoutofmemory do
9621
      begin
9622
        writeln('Not enough memory');
9623
        halt(4);
9624
      end;
14179 bpr 9625
  end;
6785 bpr 9626
  ndl_n_atoms = n_atoms;
9627
  ndl_n_bonds = n_bonds;
9628
  ndl_n_rings = n_rings;
9629
  ndl_n_heavyatoms = n_heavyatoms;
9630
  ndl_n_heavybonds = n_heavybonds;
9631
  strcpy(ndl_molname, molname);
9632
  ndl_n_Ctot = n_Ctot;
9633
  ndl_n_Otot = n_Otot;
9634
  ndl_n_Ntot = n_Ntot;
9635
  FORLIM = n_atoms;
9636
  for (i = 0; i < FORLIM; i++) {
9637
    strcpy(ndl_atom[i].element, atom[i].element);
9638
    strcpy(ndl_atom[i].atype, atom[i].atype);
9639
    ndl_atom[i].x = atom[i].x;
9640
    ndl_atom[i].y = atom[i].y;
9641
    ndl_atom[i].z = atom[i].z;
9642
    ndl_atom[i].formal_charge = atom[i].formal_charge;
9643
    ndl_atom[i].real_charge = atom[i].real_charge;
9644
    ndl_atom[i].Hexp = atom[i].Hexp;
9645
    ndl_atom[i].Htot = atom[i].Htot;
9646
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
9647
    ndl_atom[i].ring_count = atom[i].ring_count;
9648
    ndl_atom[i].arom = atom[i].arom;
9649
    ndl_atom[i].stereo_care = atom[i].stereo_care;
9650
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
9651
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
9652
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
14179 bpr 9653
        }
9654
        if (n_bonds > 0) {
9655
          FORLIM = n_bonds;
9656
          for (i = 0; i < FORLIM; i++) {
9657
            ndl_bond[i].a1 = bond[i].a1;
9658
            ndl_bond[i].a2 = bond[i].a2;
9659
            ndl_bond[i].btype = bond[i].btype;
9660
            ndl_bond[i].arom = bond[i].arom;
9661
            ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
9662
            ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
9663
            ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
9664
          }
9665
        }
9666
        if (n_rings > 0) {
9667
          FORLIM = n_rings;
9668
          for (i = 0; i < FORLIM; i++) {
9669
            for (j = 0; j < max_ringsize; j++)
9670
              ndl_ring[i][j] = ring[i][j];
9671
          }
9672
          for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
9673
            ndl_ringprop[i].size = ringprop[i].size;
9674
            ndl_ringprop[i].arom = ringprop[i].arom;
9675
            ndl_ringprop[i].envelope = ringprop[i].envelope;
9676
          }
9677
        }
9678
        ndl_molstat.n_QA = molstat.n_QA;
9679
  ndl_molstat.n_QB = molstat.n_QB;
9680
  ndl_molstat.n_chg = molstat.n_chg;
9681
  ndl_molstat.n_C1 = molstat.n_C1;
9682
  ndl_molstat.n_C2 = molstat.n_C2;
9683
  ndl_molstat.n_C = molstat.n_C;
9684
  ndl_molstat.n_CHB1p = molstat.n_CHB1p;
9685
  ndl_molstat.n_CHB2p = molstat.n_CHB2p;
9686
  ndl_molstat.n_CHB3p = molstat.n_CHB3p;
9687
  ndl_molstat.n_CHB4 = molstat.n_CHB4;
9688
  ndl_molstat.n_O2 = molstat.n_O2;
9689
  ndl_molstat.n_O3 = molstat.n_O3;
9690
  ndl_molstat.n_N1 = molstat.n_N1;
9691
  ndl_molstat.n_N2 = molstat.n_N2;
9692
  ndl_molstat.n_N3 = molstat.n_N3;
9693
  ndl_molstat.n_S = molstat.n_S;
9694
  ndl_molstat.n_SeTe = molstat.n_SeTe;
9695
  ndl_molstat.n_F = molstat.n_F;
9696
  ndl_molstat.n_Cl = molstat.n_Cl;
9697
  ndl_molstat.n_Br = molstat.n_Br;
9698
  ndl_molstat.n_I = molstat.n_I;
9699
  ndl_molstat.n_P = molstat.n_P;
9700
  ndl_molstat.n_B = molstat.n_B;
9701
  ndl_molstat.n_Met = molstat.n_Met;
9702
  ndl_molstat.n_X = molstat.n_X;
9703
  ndl_molstat.n_b1 = molstat.n_b1;
9704
  ndl_molstat.n_b2 = molstat.n_b2;
9705
  ndl_molstat.n_b3 = molstat.n_b3;
9706
  ndl_molstat.n_bar = molstat.n_bar;
9707
  ndl_molstat.n_C1O = molstat.n_C1O;
9708
  ndl_molstat.n_C2O = molstat.n_C2O;
9709
  ndl_molstat.n_CN = molstat.n_CN;
9710
  ndl_molstat.n_XY = molstat.n_XY;
9711
  ndl_molstat.n_r3 = molstat.n_r3;
9712
  ndl_molstat.n_r4 = molstat.n_r4;
9713
  ndl_molstat.n_r5 = molstat.n_r5;
9714
  ndl_molstat.n_r6 = molstat.n_r6;
9715
  ndl_molstat.n_r7 = molstat.n_r7;
9716
        ndl_molstat.n_r8 = molstat.n_r8;
9717
        ndl_molstat.n_r9 = molstat.n_r9;
9718
        ndl_molstat.n_r10 = molstat.n_r10;
9719
        ndl_molstat.n_r11 = molstat.n_r11;
9720
        ndl_molstat.n_r12 = molstat.n_r12;
9721
        ndl_molstat.n_r13p = molstat.n_r13p;
9722
        ndl_molstat.n_rN = molstat.n_rN;
9723
        ndl_molstat.n_rN1 = molstat.n_rN1;
9724
        ndl_molstat.n_rN2 = molstat.n_rN2;
9725
        ndl_molstat.n_rN3p = molstat.n_rN3p;
9726
        ndl_molstat.n_rO = molstat.n_rO;
9727
        ndl_molstat.n_rO1 = molstat.n_rO1;
9728
        ndl_molstat.n_rO2p = molstat.n_rO2p;
9729
        ndl_molstat.n_rS = molstat.n_rS;
9730
        ndl_molstat.n_rX = molstat.n_rX;
9731
        ndl_molstat.n_rAr = molstat.n_rAr;
9732
        ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
9733
        ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
9734
        /* p2c: checkmol.pas, line 7875:
9735
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
9736
        /*$IFDEF extended_molstat
9737
         v0.3m */
9738
        ndl_molstat.n_psg01 = molstat.n_psg01;
9739
        ndl_molstat.n_psg02 = molstat.n_psg02;
9740
        ndl_molstat.n_psg13 = molstat.n_psg13;
9741
        ndl_molstat.n_psg14 = molstat.n_psg14;
9742
        ndl_molstat.n_psg15 = molstat.n_psg15;
9743
        ndl_molstat.n_psg16 = molstat.n_psg16;
9744
        ndl_molstat.n_psg17 = molstat.n_psg17;
9745
        ndl_molstat.n_psg18 = molstat.n_psg18;
9746
        ndl_molstat.n_pstm = molstat.n_pstm;
9747
        ndl_molstat.n_psla = molstat.n_psla;
9748
        $ENDIF*/
9749
  /* make sure some modes can be switched on only by the query file *M*/
9750
  /* and not by subsequent haystack file(s) */
9751
  if (ez_flag)   /* new in v0.3f */
18544 georgesk 9752
   ez_search = istrue;
14179 bpr 9753
  if (chir_flag)   /* new in v0.3f */
18544 georgesk 9754
    rs_search = istrue;
14179 bpr 9755
}
6785 bpr 9756
#endif
9757
 
14179 bpr 9758
static void copy_mol_to_needle ()
6785 bpr 9759
{
9760
  //int i, j, FORLIM;
9761
 
9762
  /*if (n_atoms == 0)
9763
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9764
 
9765
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9766
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9767
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9768
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9769
 
9770
  ndl_n_atoms = n_atoms;
9771
  ndl_n_bonds = n_bonds;
9772
  ndl_n_rings = n_rings;
9773
  ndl_n_heavyatoms = n_heavyatoms;
9774
  ndl_n_heavybonds = n_heavybonds;
9775
  strcpy (ndl_molname, molname);
9776
  ndl_n_Ctot = n_Ctot;
9777
  ndl_n_Otot = n_Otot;
9778
  ndl_n_Ntot = n_Ntot;
9779
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
9780
 
9781
  if (n_bonds > 0)
9782
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
9783
 
14179 bpr 9784
  if (n_rings > 0) {
9785
    memcpy (ndl_ring, ring, sizeof (ringlist));
9786
    memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
9787
  }
6785 bpr 9788
 
9789
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
9790
 
14179 bpr 9791
  // make sure some modes can be switched on only by the query file
9792
  // and not by subsequent haystack file(s)
9793
  if (ez_flag)                  // new in v0.3f
18544 georgesk 9794
    ez_search = istrue;
6785 bpr 9795
 
14179 bpr 9796
  if (chir_flag)                // new in v0.3f
18544 georgesk 9797
    rs_search = istrue;
6785 bpr 9798
 
9799
  ndl_querymol = found_querymol;        /* 0.3p */
9800
 
9801
}
9802
 
14179 bpr 9803
static void copy_mol_to_tmp ()
6785 bpr 9804
{
9805
  //int i, j, FORLIM;
9806
 
9807
  /*if (n_atoms == 0)
9808
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9809
 
9810
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9811
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9812
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9813
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9814
 
9815
  tmp_n_atoms = n_atoms;
9816
  tmp_n_bonds = n_bonds;
9817
  tmp_n_rings = n_rings;
9818
  tmp_n_heavyatoms = n_heavyatoms;
9819
  tmp_n_heavybonds = n_heavybonds;
9820
  strcpy (tmp_molname, molname);
9821
  tmp_n_Ctot = n_Ctot;
9822
  tmp_n_Otot = n_Otot;
9823
  tmp_n_Ntot = n_Ntot;
9824
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
9825
 
9826
  if (n_bonds > 0)
9827
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
9828
 
14179 bpr 9829
  if (n_rings > 0) {
6785 bpr 9830
      memcpy (tmp_ring, ring, sizeof (ringlist));
9831
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
14179 bpr 9832
  }
6785 bpr 9833
 
9834
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
9835
 
14179 bpr 9836
  // make sure some modes can be switched on only by the query file
9837
  // and not by subsequent haystack file(s)
9838
  if (ez_flag)                  // new in v0.3f
18544 georgesk 9839
    ez_search = istrue;
6785 bpr 9840
 
14179 bpr 9841
  if (chir_flag)                // new in v0.3f
18544 georgesk 9842
    rs_search = istrue;
6785 bpr 9843
 
9844
  ndl_querymol = found_querymol;        /* 0.3p */
9845
 
9846
}
9847
 
9848
#if 0
9849
static void copy_mol_to_tmp()
9850
{
9851
  int i, j, FORLIM;
9852
 
9853
  if (n_atoms == 0)
9854
    return;
9855
  /* try */
9856
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9857
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9858
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9859
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9860
  /* except */
9861
    on e:Eoutofmemory do
9862
      begin
9863
        writeln('Not enough memory');
9864
        halt(4);
9865
      end;
9866
  end;
9867
  tmp_n_atoms = n_atoms;
9868
  tmp_n_bonds = n_bonds;
9869
  tmp_n_rings = n_rings;
9870
  tmp_n_heavyatoms = n_heavyatoms;
9871
  tmp_n_heavybonds = n_heavybonds;
9872
  strcpy(tmp_molname, molname);
9873
  tmp_n_Ctot = n_Ctot;
9874
  tmp_n_Otot = n_Otot;
9875
  tmp_n_Ntot = n_Ntot;
9876
  FORLIM = n_atoms;
9877
  for (i = 0; i < FORLIM; i++) {
9878
    strcpy(tmp_atom[i].element, atom[i].element);
9879
    strcpy(tmp_atom[i].atype, atom[i].atype);
9880
    tmp_atom[i].x = atom[i].x;
9881
    tmp_atom[i].y = atom[i].y;
9882
    tmp_atom[i].z = atom[i].z;
9883
    tmp_atom[i].formal_charge = atom[i].formal_charge;
9884
    tmp_atom[i].real_charge = atom[i].real_charge;
9885
    tmp_atom[i].Hexp = atom[i].Hexp;
9886
    tmp_atom[i].Htot = atom[i].Htot;
9887
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
9888
    tmp_atom[i].ring_count = atom[i].ring_count;
9889
    tmp_atom[i].arom = atom[i].arom;
9890
    tmp_atom[i].stereo_care = atom[i].stereo_care;
9891
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
9892
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
9893
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
9894
  }
9895
  if (n_bonds > 0) {
9896
    FORLIM = n_bonds;
9897
    for (i = 0; i < FORLIM; i++) {
9898
      tmp_bond[i].a1 = bond[i].a1;
9899
      tmp_bond[i].a2 = bond[i].a2;
9900
      tmp_bond[i].btype = bond[i].btype;
9901
      tmp_bond[i].arom = bond[i].arom;
9902
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
9903
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
9904
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
9905
    }
9906
  }
9907
  if (n_rings > 0) {
9908
    FORLIM = n_rings;
9909
    for (i = 0; i < FORLIM; i++) {
9910
      for (j = 0; j < max_ringsize; j++)
9911
        tmp_ring[i][j] = ring[i][j];
9912
    }
9913
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
9914
      tmp_ringprop[i].size = ringprop[i].size;
9915
      tmp_ringprop[i].arom = ringprop[i].arom;
9916
      tmp_ringprop[i].envelope = ringprop[i].envelope;
9917
    }
9918
  }
9919
  tmp_molstat.n_QA = molstat.n_QA;
9920
  tmp_molstat.n_QB = molstat.n_QB;
9921
  tmp_molstat.n_chg = molstat.n_chg;
9922
  tmp_molstat.n_C1 = molstat.n_C1;
9923
  tmp_molstat.n_C2 = molstat.n_C2;
9924
  tmp_molstat.n_C = molstat.n_C;
9925
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
9926
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
9927
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
9928
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
9929
  tmp_molstat.n_O2 = molstat.n_O2;
9930
  tmp_molstat.n_O3 = molstat.n_O3;
9931
  tmp_molstat.n_N1 = molstat.n_N1;
9932
  tmp_molstat.n_N2 = molstat.n_N2;
9933
  tmp_molstat.n_N3 = molstat.n_N3;
9934
  tmp_molstat.n_S = molstat.n_S;
9935
  tmp_molstat.n_SeTe = molstat.n_SeTe;
9936
  tmp_molstat.n_F = molstat.n_F;
9937
  tmp_molstat.n_Cl = molstat.n_Cl;
9938
  tmp_molstat.n_Br = molstat.n_Br;
9939
  tmp_molstat.n_I = molstat.n_I;
9940
  tmp_molstat.n_P = molstat.n_P;
9941
  tmp_molstat.n_B = molstat.n_B;
9942
  tmp_molstat.n_Met = molstat.n_Met;
9943
  tmp_molstat.n_X = molstat.n_X;
9944
  tmp_molstat.n_b1 = molstat.n_b1;
9945
  tmp_molstat.n_b2 = molstat.n_b2;
9946
  tmp_molstat.n_b3 = molstat.n_b3;
9947
  tmp_molstat.n_bar = molstat.n_bar;
9948
  tmp_molstat.n_C1O = molstat.n_C1O;
9949
  tmp_molstat.n_C2O = molstat.n_C2O;
9950
  tmp_molstat.n_CN = molstat.n_CN;
9951
  tmp_molstat.n_XY = molstat.n_XY;
9952
  tmp_molstat.n_r3 = molstat.n_r3;
9953
  tmp_molstat.n_r4 = molstat.n_r4;
9954
  tmp_molstat.n_r5 = molstat.n_r5;
9955
  tmp_molstat.n_r6 = molstat.n_r6;
9956
  tmp_molstat.n_r7 = molstat.n_r7;
9957
  tmp_molstat.n_r8 = molstat.n_r8;
9958
  tmp_molstat.n_r9 = molstat.n_r9;
9959
  tmp_molstat.n_r10 = molstat.n_r10;
9960
  tmp_molstat.n_r11 = molstat.n_r11;
9961
  tmp_molstat.n_r12 = molstat.n_r12;
9962
  tmp_molstat.n_r13p = molstat.n_r13p;
9963
  tmp_molstat.n_rN = molstat.n_rN;
9964
  tmp_molstat.n_rN1 = molstat.n_rN1;
9965
  tmp_molstat.n_rN2 = molstat.n_rN2;
9966
  tmp_molstat.n_rN3p = molstat.n_rN3p;
9967
  tmp_molstat.n_rO = molstat.n_rO;
9968
  tmp_molstat.n_rO1 = molstat.n_rO1;
9969
  tmp_molstat.n_rO2p = molstat.n_rO2p;
9970
  tmp_molstat.n_rS = molstat.n_rS;
9971
  tmp_molstat.n_rX = molstat.n_rX;
9972
  tmp_molstat.n_rAr = molstat.n_rAr;
9973
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
9974
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
9975
/* p2c: checkmol.pas, line 8022:
9976
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
9977
  /*$IFDEF extended_molstat
14179 bpr 9978
   v0.3m
6785 bpr 9979
  tmp_molstat.n_psg01 = molstat.n_psg01;
9980
  tmp_molstat.n_psg02 = molstat.n_psg02;
9981
  tmp_molstat.n_psg13 = molstat.n_psg13;
9982
  tmp_molstat.n_psg14 = molstat.n_psg14;
9983
  tmp_molstat.n_psg15 = molstat.n_psg15;
9984
  tmp_molstat.n_psg16 = molstat.n_psg16;
9985
  tmp_molstat.n_psg17 = molstat.n_psg17;
9986
  tmp_molstat.n_psg18 = molstat.n_psg18;
9987
  tmp_molstat.n_pstm = molstat.n_pstm;
9988
  tmp_molstat.n_psla = molstat.n_psla;
9989
  $ENDIF*/
9990
  /* make sure some modes can be switched on only by the query file */
9991
  /* and not by subsequent haystack file(s) */
9992
  if (ez_flag)   /* new in v0.3f */
18544 georgesk 9993
    ez_search = istrue;
6785 bpr 9994
  if (chir_flag)   /* new in v0.3f */
18544 georgesk 9995
    rs_search = istrue;
6785 bpr 9996
}
9997
#endif
9998
 
14179 bpr 9999
static void copy_tmp_to_mol ()
6785 bpr 10000
{
10001
  //int i, j, FORLIM;
10002
 
10003
  /*if (n_atoms == 0)
10004
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10005
 
10006
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10007
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10008
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10009
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10010
 
10011
  n_atoms = tmp_n_atoms;
10012
  n_bonds = tmp_n_bonds;
10013
  n_rings = tmp_n_rings;
10014
  n_heavyatoms = tmp_n_heavyatoms;
10015
  n_heavybonds = tmp_n_heavybonds;
10016
  strcpy (molname, tmp_molname);
10017
  n_Ctot = tmp_n_Ctot;
10018
  n_Otot = tmp_n_Otot;
10019
  n_Ntot = tmp_n_Ntot;
10020
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
10021
 
10022
  if (tmp_n_bonds > 0)
10023
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
10024
 
14179 bpr 10025
  if (tmp_n_rings > 0) {
6785 bpr 10026
      memcpy (ring, tmp_ring, sizeof (ringlist));
10027
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
14179 bpr 10028
  }
6785 bpr 10029
 
10030
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
10031
 
14179 bpr 10032
  // make sure some modes can be switched on only by the query file
10033
  // and not by subsequent haystack file(s)
10034
  if (ez_flag)                  // new in v0.3f
18544 georgesk 10035
    ez_search = istrue;
6785 bpr 10036
 
14179 bpr 10037
  if (chir_flag)                // new in v0.3f
18544 georgesk 10038
    rs_search = istrue;
6785 bpr 10039
 
10040
}
10041
 
10042
#if 0
10043
static void copy_tmp_to_mol()
10044
{
10045
  int i, j, FORLIM;
10046
 
10047
  if (tmp_n_atoms == 0)
10048
    return;
10049
  n_atoms = tmp_n_atoms;
10050
  n_bonds = tmp_n_bonds;
10051
  n_rings = tmp_n_rings;
10052
  n_heavyatoms = tmp_n_heavyatoms;
10053
  n_heavybonds = tmp_n_heavybonds;
10054
  strcpy(molname, tmp_molname);
10055
  n_Ctot = tmp_n_Ctot;
10056
  n_Otot = tmp_n_Otot;
10057
  n_Ntot = tmp_n_Ntot;
10058
  /* try */
10059
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10060
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10061
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10062
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10063
  FORLIM = tmp_n_atoms;
10064
  /* except*/
10065
    on e:Eoutofmemory do
10066
      begin
10067
        writeln('Not enough memory');
10068
        halt(4);
10069
      end;
14179 bpr 10070
  end;
6785 bpr 10071
  for (i = 0; i < FORLIM; i++) {
10072
    strcpy(atom[i].element, tmp_atom[i].element);
10073
    strcpy(atom[i].atype, tmp_atom[i].atype);
10074
    atom[i].x = tmp_atom[i].x;
10075
    atom[i].y = tmp_atom[i].y;
10076
    atom[i].z = tmp_atom[i].z;
10077
    atom[i].formal_charge = tmp_atom[i].formal_charge;
10078
    atom[i].real_charge = tmp_atom[i].real_charge;
10079
    atom[i].Hexp = tmp_atom[i].Hexp;
10080
    atom[i].Htot = tmp_atom[i].Htot;
10081
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
10082
    atom[i].ring_count = tmp_atom[i].ring_count;
10083
    atom[i].arom = tmp_atom[i].arom;
10084
    atom[i].stereo_care = tmp_atom[i].stereo_care;
10085
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
10086
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
10087
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
10088
  }
10089
  if (tmp_n_bonds > 0) {
10090
    FORLIM = tmp_n_bonds;
10091
    for (i = 0; i < FORLIM; i++) {
10092
      bond[i].a1 = tmp_bond[i].a1;
10093
      bond[i].a2 = tmp_bond[i].a2;
10094
      bond[i].btype = tmp_bond[i].btype;
10095
      bond[i].arom = tmp_bond[i].arom;
10096
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
10097
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
10098
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
10099
    }
10100
  }
10101
  if (tmp_n_rings > 0) {
10102
    FORLIM = tmp_n_rings;
10103
    for (i = 0; i < FORLIM; i++) {
10104
      for (j = 0; j < max_ringsize; j++)
10105
        ring[i][j] = tmp_ring[i][j];
10106
    }
10107
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10108
      ringprop[i].size = tmp_ringprop[i].size;
10109
      ringprop[i].arom = tmp_ringprop[i].arom;
10110
      ringprop[i].envelope = tmp_ringprop[i].envelope;
10111
    }
10112
  }
10113
  molstat.n_QA = tmp_molstat.n_QA;
10114
  molstat.n_QB = tmp_molstat.n_QB;
10115
  molstat.n_chg = tmp_molstat.n_chg;
10116
  molstat.n_C1 = tmp_molstat.n_C1;
10117
  molstat.n_C2 = tmp_molstat.n_C2;
10118
  molstat.n_C = tmp_molstat.n_C;
10119
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
10120
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
10121
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
10122
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
10123
  molstat.n_O2 = tmp_molstat.n_O2;
10124
  molstat.n_O3 = tmp_molstat.n_O3;
10125
  molstat.n_N1 = tmp_molstat.n_N1;
10126
  molstat.n_N2 = tmp_molstat.n_N2;
10127
  molstat.n_N3 = tmp_molstat.n_N3;
10128
  molstat.n_S = tmp_molstat.n_S;
10129
  molstat.n_SeTe = tmp_molstat.n_SeTe;
10130
  molstat.n_F = tmp_molstat.n_F;
10131
  molstat.n_Cl = tmp_molstat.n_Cl;
10132
  molstat.n_Br = tmp_molstat.n_Br;
10133
  molstat.n_I = tmp_molstat.n_I;
10134
  molstat.n_P = tmp_molstat.n_P;
10135
  molstat.n_B = tmp_molstat.n_B;
10136
  molstat.n_Met = tmp_molstat.n_Met;
10137
  molstat.n_X = tmp_molstat.n_X;
10138
  molstat.n_b1 = tmp_molstat.n_b1;
10139
  molstat.n_b2 = tmp_molstat.n_b2;
10140
  molstat.n_b3 = tmp_molstat.n_b3;
10141
  molstat.n_bar = tmp_molstat.n_bar;
10142
  molstat.n_C1O = tmp_molstat.n_C1O;
10143
  molstat.n_C2O = tmp_molstat.n_C2O;
10144
  molstat.n_CN = tmp_molstat.n_CN;
10145
  molstat.n_XY = tmp_molstat.n_XY;
10146
  molstat.n_r3 = tmp_molstat.n_r3;
10147
  molstat.n_r4 = tmp_molstat.n_r4;
10148
  molstat.n_r5 = tmp_molstat.n_r5;
10149
  molstat.n_r6 = tmp_molstat.n_r6;
10150
  molstat.n_r7 = tmp_molstat.n_r7;
10151
  molstat.n_r8 = tmp_molstat.n_r8;
10152
  molstat.n_r9 = tmp_molstat.n_r9;
10153
  molstat.n_r10 = tmp_molstat.n_r10;
10154
  molstat.n_r11 = tmp_molstat.n_r11;
10155
  molstat.n_r12 = tmp_molstat.n_r12;
10156
  molstat.n_r13p = tmp_molstat.n_r13p;
10157
  molstat.n_rN = tmp_molstat.n_rN;
10158
  molstat.n_rN1 = tmp_molstat.n_rN1;
10159
  molstat.n_rN2 = tmp_molstat.n_rN2;
10160
  molstat.n_rN3p = tmp_molstat.n_rN3p;
10161
  molstat.n_rO = tmp_molstat.n_rO;
10162
  molstat.n_rO1 = tmp_molstat.n_rO1;
10163
  molstat.n_rO2p = tmp_molstat.n_rO2p;
10164
  molstat.n_rS = tmp_molstat.n_rS;
10165
  molstat.n_rX = tmp_molstat.n_rX;
10166
  molstat.n_rAr = tmp_molstat.n_rAr;
10167
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
10168
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
10169
/* p2c: checkmol.pas, line 8169:
10170
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10171
  /*$IFDEF extended_molstat
10172
     molstat.n_psg01 = tmp_molstat.n_psg01;
10173
     molstat.n_psg02 = tmp_molstat.n_psg02;
10174
     molstat.n_psg13 = tmp_molstat.n_psg13;
10175
     molstat.n_psg14 = tmp_molstat.n_psg14;
10176
     molstat.n_psg15 = tmp_molstat.n_psg15;
10177
     molstat.n_psg16 = tmp_molstat.n_psg16;
10178
     molstat.n_psg17 = tmp_molstat.n_psg17;
10179
     molstat.n_psg18 = tmp_molstat.n_psg18;
10180
     molstat.n_pstm = tmp_molstat.n_pstm;
10181
     molstat.n_psla = tmp_molstat.n_psla;
10182
     $ENDIF */
10183
  /* make sure some modes can be switched on only by the query file */
10184
  /* and not by subsequent haystack file(s) */
10185
     if (ez_flag)
18544 georgesk 10186
     ez_search = istrue;
6785 bpr 10187
     if (chir_flag)
18544 georgesk 10188
     rs_search = istrue;
6785 bpr 10189
     }
10190
#endif
10191
 
17891 bpr 10192
static void get_ringstat (int r_id)
6785 bpr 10193
{
10194
  int i, j;
10195
  ringpath_type testring;
10196
  int ring_size, a_ref;
10197
  str2 elem;
10198
  int nN = 0, nO = 0, nS = 0, nX = 0;
10199
 
10200
  if (r_id < 1 || r_id > n_rings)
10201
    return;
10202
  memset (testring, 0, sizeof (ringpath_type));
10203
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
10204
  for (j = 0; j < ring_size; j++)       /* v0.3j */
10205
    testring[j] = ring[r_id - 1][j];
14179 bpr 10206
    /* p2c: checkmol.pas, line 8238:
10207
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10208
#ifdef reduced_SAR
18544 georgesk 10209
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != isfalse)
6785 bpr 10210
    /* v0.3n: ignore envelope rings */
10211
    return;
10212
#else
10213
  if (ring_size <= 2)
10214
    return;
10215
#endif
14179 bpr 10216
  for (i = 0; i < ring_size; i++) {
10217
    a_ref = testring[i];
10218
    strcpy (elem, atom[a_ref - 1].element);
10219
    if (strcmp (elem, "C ") && strcmp (elem, "A ")) {
10220
            nX++;                       /* general heteroatom count */
10221
            if (!strcmp (elem, "N "))
10222
              nN++;
10223
            if (!strcmp (elem, "O "))
10224
              nO++;
10225
            if (!strcmp (elem, "S "))
10226
              nS++;
10227
          }
10228
  }
10229
  if (nN > 0) {
10230
    molstat.n_rN++;
10231
    if (nN == 1)
10232
            molstat.n_rN1++;
10233
    if (nN == 2)
10234
            molstat.n_rN2++;
10235
    if (nN > 2)
10236
            molstat.n_rN3p++;
10237
  }
10238
  if (nO > 0) {
10239
    molstat.n_rO++;
10240
    if (nO == 1)
10241
            molstat.n_rO1++;
10242
    if (nO == 2)
10243
            molstat.n_rO2p++;
10244
  }
6785 bpr 10245
  if (nS > 0)
10246
    molstat.n_rS++;
10247
  if (nX > 0)
10248
    molstat.n_rX++;
10249
  /* general ringsize descriptors; v0.3m */
14179 bpr 10250
  switch (ring_size) {
6785 bpr 10251
    case 3:
10252
      molstat.n_r3++;
10253
      break;
10254
 
10255
    case 4:
10256
      molstat.n_r4++;
10257
      break;
10258
 
10259
    case 5:
10260
      molstat.n_r5++;
10261
      break;
10262
 
10263
    case 6:
10264
      molstat.n_r6++;
10265
      break;
10266
 
10267
    case 7:
10268
      molstat.n_r7++;
10269
      break;
10270
 
10271
    case 8:
10272
      molstat.n_r8++;
10273
      break;
10274
 
10275
    case 9:
10276
      molstat.n_r9++;
10277
      break;
10278
 
10279
    case 10:
10280
      molstat.n_r10++;
10281
      break;
10282
 
10283
    case 11:
10284
      molstat.n_r11++;
10285
      break;
10286
 
10287
    case 12:
10288
      molstat.n_r12++;
10289
      break;
10290
 
10291
    default:
10292
      molstat.n_r13p++;
10293
      break;
14179 bpr 10294
  }                             /* end v0.3m        */
6785 bpr 10295
}
10296
 
14179 bpr 10297
static void get_molstat ()
6785 bpr 10298
{
10299
  int i;
10300
  str2 elem;
10301
  str3 atype;
10302
  int a1, a2;
10303
  str2 a1el, a2el;
10304
  char btype;
10305
  int hbc;
10306
  int n_b2formal = 0;           /* new in v0.2e */
10307
  int FORLIM;
10308
 
10309
  if (n_atoms == 0)
10310
    return;
10311
  FORLIM = n_atoms;
14179 bpr 10312
  for (i = 0; i < FORLIM; i++) {
10313
    if (atom[i].heavy) {
10314
            strcpy (elem, atom[i].element);
10315
            strcpy (atype, atom[i].atype);
10316
            if (!strcmp (atype, "C1 "))
10317
              molstat.n_C1++;
10318
            if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
10319
              molstat.n_C2++;
10320
            if (!strcmp (elem, "C "))
10321
              molstat.n_C++;
10322
            if (!strcmp (atype, "O2 "))
10323
              molstat.n_O2++;
10324
            if (!strcmp (atype, "O3 "))
10325
              molstat.n_O3++;
10326
            if (!strcmp (atype, "N1 "))
10327
              molstat.n_N1++;
10328
            if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
18544 georgesk 10329
                (!strcmp (atype, "NAM") && atom[i].arom == istrue))
14179 bpr 10330
              /* v0.3n */
10331
              molstat.n_N2++;
10332
            if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
10333
                !strcmp (atype, "N3+") ||
18544 georgesk 10334
                (!strcmp (atype, "NAM") && atom[i].arom == isfalse))
14179 bpr 10335
              /* v0.3n */
10336
              molstat.n_N3++;
10337
            if (!strcmp (elem, "A "))   /* query atom */
10338
              molstat.n_QA++;
10339
            if (!strcmp (elem, "Q "))   /* query atom */
10340
              molstat.n_QA++;
10341
            if (!strcmp (elem, "X "))   /* query atom */
10342
              molstat.n_QA++;
10343
            if (!strcmp (elem, "S "))
10344
              molstat.n_S++;
10345
            if (!strcmp (elem, "SE"))
6785 bpr 10346
            molstat.n_SeTe++;
14179 bpr 10347
            if (!strcmp (elem, "TE"))
10348
              molstat.n_SeTe++;
10349
            if (!strcmp (elem, "F "))
10350
              molstat.n_F++;
10351
            if (!strcmp (elem, "CL"))
10352
              molstat.n_Cl++;
10353
            if (!strcmp (elem, "BR"))
10354
              molstat.n_Br++;
10355
            if (!strcmp (elem, "I "))
10356
              molstat.n_I++;
10357
            if (!strcmp (elem, "P "))
10358
              molstat.n_P++;
10359
            if (!strcmp (elem, "B "))
10360
              molstat.n_B++;
10361
            /* check for known metals */
10362
            if (atom[i].metal)  /* v0.3l */
10363
              molstat.n_Met++;
10364
            /* still missing: unknown elements */
6785 bpr 10365
 
14179 bpr 10366
            /* check number of heteroatom bonds per C atom */
10367
            if (!strcmp (elem, "C ")) {
6785 bpr 10368
              hbc = raw_hetbond_count (i + 1);
10369
              /* new in v0.2j (replaces hetbond_count) */
10370
              if (hbc >= 1)
14179 bpr 10371
                      molstat.n_CHB1p++;
6785 bpr 10372
              if (hbc >= 2)
14179 bpr 10373
                      molstat.n_CHB2p++;
6785 bpr 10374
              if (hbc >= 3)
14179 bpr 10375
                      molstat.n_CHB3p++;
6785 bpr 10376
              if (hbc == 4)
14179 bpr 10377
                      molstat.n_CHB4++;
6785 bpr 10378
            }
14179 bpr 10379
            if (atom[i].formal_charge != 0) {
6785 bpr 10380
              molstat.n_chg++;
10381
              //n_charges++;
10382
            }
14179 bpr 10383
            if (atom[i].nucleon_number != 0) {
6785 bpr 10384
              molstat.n_iso++;
10385
            }
14179 bpr 10386
            if (atom[i].radical_type != 0) {
6785 bpr 10387
              molstat.n_rad++;
10388
            }
14179 bpr 10389
            /* check for "other" elements;  v0.3l */
10390
            if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
10391
                && strcmp (elem, "O ") && strcmp (elem, "S ")
10392
                && strcmp (elem, "SE") && strcmp (elem, "TE")
10393
                && strcmp (elem, "P ") && strcmp (elem, "B ")
10394
                && strcmp (elem, "A ") && strcmp (elem, "Q "))
10395
              molstat.n_X++;
10396
            /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
10397
      /* p2c: checkmol.pas, line 8353:
10398
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10399
            /*$IFDEF extended_molstat */
10400
            if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
10401
                || !strcmp (elem, "K ") || !strcmp (elem, "RB")
10402
                || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
10403
              molstat.n_psg01++;
10404
            if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
10405
                || !strcmp (elem, "CA") || !strcmp (elem, "SR")
10406
                || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
10407
              molstat.n_psg02++;
10408
            if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
10409
                || !strcmp (elem, "GA") || !strcmp (elem, "IN")
10410
                || !strcmp (elem, "TL"))
10411
              molstat.n_psg13++;
10412
            if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
10413
                || !strcmp (elem, "GE") || !strcmp (elem, "SN")
10414
                || !strcmp (elem, "PB"))
10415
              molstat.n_psg14++;
10416
            if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
6785 bpr 10417
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
10418
              || !strcmp (elem, "BI"))
10419
            molstat.n_psg15++;
14179 bpr 10420
            if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
10421
                || !strcmp (elem, "SE") || !strcmp (elem, "TE")
10422
                || !strcmp (elem, "PO"))
10423
              molstat.n_psg16++;
10424
            if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
10425
                || !strcmp (elem, "BR") || !strcmp (elem, "I ")
10426
                || !strcmp (elem, "AT"))
10427
              molstat.n_psg17++;
10428
            if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
10429
                || !strcmp (elem, "AR") || !strcmp (elem, "KR")
10430
                || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
10431
              molstat.n_psg18++;
10432
            if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
10433
                || !strcmp (elem, "LU") || !strcmp (elem, "LR")
10434
                || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
10435
                || !strcmp (elem, "HF") || !strcmp (elem, "RF")
10436
                || !strcmp (elem, "V ") || !strcmp (elem, "NB")
10437
                || !strcmp (elem, "TA") || !strcmp (elem, "DB")
10438
                || !strcmp (elem, "CR") || !strcmp (elem, "MO")
10439
                || !strcmp (elem, "W ") || !strcmp (elem, "SG")
10440
                || !strcmp (elem, "MN") || !strcmp (elem, "TC")
10441
                || !strcmp (elem, "RE") || !strcmp (elem, "BH")
10442
                || !strcmp (elem, "FE") || !strcmp (elem, "RU")
10443
                || !strcmp (elem, "OS") || !strcmp (elem, "HS")
10444
                || !strcmp (elem, "CO") || !strcmp (elem, "RH")
10445
                || !strcmp (elem, "IR") || !strcmp (elem, "MT")
10446
                || !strcmp (elem, "NI") || !strcmp (elem, "PD")
10447
                || !strcmp (elem, "PT") || !strcmp (elem, "DS")
10448
                || !strcmp (elem, "CU") || !strcmp (elem, "AG")
10449
                || !strcmp (elem, "AU") || !strcmp (elem, "RG")
10450
                || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
10451
                || !strcmp (elem, "HG"))
10452
        /* p2c: checkmol.pas, line 8439:
10453
        * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
10454
              molstat.n_pstm++;
10455
            if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
10456
                || !strcmp (elem, "PR") || !strcmp (elem, "ND")
10457
                || !strcmp (elem, "PM") || !strcmp (elem, "SM")
10458
                || !strcmp (elem, "EU") || !strcmp (elem, "GD")
10459
                || !strcmp (elem, "TB") || !strcmp (elem, "DY")
10460
                || !strcmp (elem, "HO") || !strcmp (elem, "ER")
10461
                || !strcmp (elem, "TM") || !strcmp (elem, "YB")
10462
                || !strcmp (elem, "AC") || !strcmp (elem, "TH")
10463
                || !strcmp (elem, "PA") || !strcmp (elem, "U ")
10464
                || !strcmp (elem, "NP") || !strcmp (elem, "PU")
10465
                || !strcmp (elem, "AM") || !strcmp (elem, "CM")
10466
                || !strcmp (elem, "BK") || !strcmp (elem, "CF")
10467
                || !strcmp (elem, "ES") || !strcmp (elem, "FM")
10468
                || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
10469
      /* p2c: checkmol.pas, line 8439:
10470
      * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
10471
              molstat.n_psla++;
10472
            /*$ENDIF */
10473
          }                     /* is heavy */
10474
  }                             /* atoms */
10475
  if (n_bonds > 0) {
10476
    FORLIM = n_bonds;
10477
    for (i = 0; i < FORLIM; i++) {
10478
            a1 = bond[i].a1;
10479
            a2 = bond[i].a2;
10480
            strcpy (a1el, atom[a1 - 1].element);
10481
            strcpy (a2el, atom[a2 - 1].element);
10482
            btype = bond[i].btype;
10483
            if (bond[i].arom)
10484
              molstat.n_bar++;
10485
            else {
6785 bpr 10486
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
14179 bpr 10487
                      molstat.n_b1++;
6785 bpr 10488
              if (btype == 'D')
14179 bpr 10489
                     molstat.n_b2++;
6785 bpr 10490
              if (btype == 'T')
14179 bpr 10491
                      molstat.n_b3++;
6785 bpr 10492
            }
14179 bpr 10493
            /* v0.3n: ignore bonds to (explicit) hydrogens */
10494
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
10495
                (!strcmp (a1el, "O ") && !strcmp (a2el, "C "))) {
6785 bpr 10496
              if (btype == 'S')
14179 bpr 10497
                      molstat.n_C1O++;
6785 bpr 10498
              if (btype == 'D')
14179 bpr 10499
                      molstat.n_C2O++;
6785 bpr 10500
            }
14179 bpr 10501
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
10502
                (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
10503
              molstat.n_CN++;
10504
            if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
10505
                && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
10506
              molstat.n_XY++;
10507
            /* new in v0.3n: number of bonds belonging to more than one ring */
10508
            if (bond[i].ring_count > 1)
10509
              molstat.n_br2p++;
10510
          }
10511
  }                             /* bonds */
10512
  if (n_rings <= 0) {
6785 bpr 10513
      return;
14179 bpr 10514
  }                             /* rings */
6785 bpr 10515
  /* v0.3n */
10516
  n_countablerings = 0;         /* v0.3n */
10517
  FORLIM = n_rings;
14179 bpr 10518
  for (i = 1; i <= FORLIM; i++) {
18544 georgesk 10519
    if (ringprop[i - 1].envelope == isfalse)    /* v0.3n */
14179 bpr 10520
            n_countablerings++;
18544 georgesk 10521
    if (is_arene (i) && ringprop[i - 1].envelope == isfalse) {
14179 bpr 10522
      /* v0.3n: ignore envelope rings */
10523
            molstat.n_rAr++;
18544 georgesk 10524
            if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == isfalse))
14179 bpr 10525
              /* v0.3l */
10526
              molstat.n_rBz++;
10527
          }
10528
    get_ringstat (i);
18544 georgesk 10529
    if (ringprop[i - 1].arom == istrue && ringprop[i - 1].envelope == isfalse)
14179 bpr 10530
            /* new in v0.3n; replaces assignment below */
10531
            n_b2formal++;
10532
  }
6785 bpr 10533
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
10534
  /* in order to allow an isolated double bond in the needle */
10535
  /* to be matched as a ring fragment of an aromatic ring */
10536
  if (n_b2formal > molstat.n_bar / 2)
10537
    n_b2formal = molstat.n_bar / 2;
10538
  molstat.n_b2 += n_b2formal;
10539
}
10540
 
14179 bpr 10541
static void fix_ssr_ringcounts ()
6785 bpr 10542
{
10543
  /* new in v0.3n */
10544
  /* if SAR -> SSR fallback happens, set some molstat values */
10545
  /* to a maximum (ring counts for various ring sizes); */
10546
  /* this should be necessary only for ring sizes which */
10547
  /* are a) too large for the SSR (depending on ssr_vringsize) */
10548
  /* and b) which are likely to contain "envelope rings" */
10549
  /* (size 6 and above) */
10550
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
10551
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
10552
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
10553
  if (molstat.n_r6 == 0)
10554
    molstat.n_r6 = max_rings;
10555
  if (molstat.n_r7 == 0)
10556
    molstat.n_r7 = max_rings;
10557
  if (molstat.n_r8 == 0)
10558
    molstat.n_r8 = max_rings;
10559
  if (molstat.n_r9 == 0)
10560
    molstat.n_r9 = max_rings;
10561
  if (molstat.n_r10 == 0)
10562
    molstat.n_r10 = max_rings;
10563
  if (molstat.n_r11 == 0)
10564
    molstat.n_r11 = max_rings;
10565
  if (molstat.n_r12 == 0)
10566
    molstat.n_r12 = max_rings;
10567
  if (molstat.n_r13p == 0)
10568
    molstat.n_r13p = max_rings;
10569
}
10570
 
14179 bpr 10571
static void write_molstat ()
6785 bpr 10572
{
10573
  if (auto_ssr)                 /* v0.3n */
10574
    fix_ssr_ringcounts ();
10575
  printf ("n_atoms:%d;", n_heavyatoms);
10576
  /* count only non-H atoms (some molfiles contain explicit H's) */
10577
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
10578
    printf ("n_bonds:%d;", n_heavybonds);
14179 bpr 10579
  /* p2c: checkmol.pas, line 8471:
10580
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10581
#ifdef REDUCED_SAR
10582
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10583
    printf ("n_rings:%d;", n_countablerings);
10584
#else
10585
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10586
    printf ("n_rings:%d;", n_rings);
10587
#endif
10588
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
10589
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
10590
  if (molstat.n_chg > 0)        /* 0.3x */
10591
    printf ("n_chg:%d;", molstat.n_chg);
10592
 
10593
  if (molstat.n_C1 > 0)
10594
    printf ("n_C1:%d;", molstat.n_C1);
10595
  if (molstat.n_C2 > 0)
10596
    printf ("n_C2:%d;", molstat.n_C2);
10597
  /* requirement of a given number of sp3 carbons might be too restrictive, */
10598
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
10599
  if (molstat.n_C > 0)
10600
    printf ("n_C:%d;", molstat.n_C);
10601
  if (molstat.n_CHB1p > 0)
10602
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
10603
  if (molstat.n_CHB2p > 0)
10604
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
10605
  if (molstat.n_CHB3p > 0)
10606
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
10607
  if (molstat.n_CHB4 > 0)
10608
    printf ("n_CHB4:%d;", molstat.n_CHB4);
10609
  if (molstat.n_O2 > 0)
10610
    printf ("n_O2:%d;", molstat.n_O2);
10611
  if (molstat.n_O3 > 0)
10612
    printf ("n_O3:%d;", molstat.n_O3);
10613
  if (molstat.n_N1 > 0)
10614
    printf ("n_N1:%d;", molstat.n_N1);
10615
  if (molstat.n_N2 > 0)
10616
    printf ("n_N2:%d;", molstat.n_N2);
10617
  if (molstat.n_N3 > 0)
10618
    printf ("n_N3:%d;", molstat.n_N3);
10619
  if (molstat.n_S > 0)
10620
    printf ("n_S:%d;", molstat.n_S);
10621
  if (molstat.n_SeTe > 0)
10622
    printf ("n_SeTe:%d;", molstat.n_SeTe);
10623
  if (molstat.n_F > 0)
10624
    printf ("n_F:%d;", molstat.n_F);
10625
  if (molstat.n_Cl > 0)
10626
    printf ("n_Cl:%d;", molstat.n_Cl);
10627
  if (molstat.n_Br > 0)
10628
    printf ("n_Br:%d;", molstat.n_Br);
10629
  if (molstat.n_I > 0)
10630
    printf ("n_I:%d;", molstat.n_I);
10631
  if (molstat.n_P > 0)
10632
    printf ("n_P:%d;", molstat.n_P);
10633
  if (molstat.n_B > 0)
10634
    printf ("n_B:%d;", molstat.n_B);
10635
  if (molstat.n_Met > 0)
10636
    printf ("n_Met:%d;", molstat.n_Met);
10637
  if (molstat.n_X > 0)
10638
    printf ("n_X:%d;", molstat.n_X);
10639
  if (molstat.n_b1 > 0)
10640
    printf ("n_b1:%d;", molstat.n_b1);
10641
  if (molstat.n_b2 > 0)
10642
    printf ("n_b2:%d;", molstat.n_b2);
10643
  if (molstat.n_b3 > 0)
10644
    printf ("n_b3:%d;", molstat.n_b3);
10645
  if (molstat.n_bar > 0)
10646
    printf ("n_bar:%d;", molstat.n_bar);
10647
  if (molstat.n_C1O > 0)
10648
    printf ("n_C1O:%d;", molstat.n_C1O);
10649
  if (molstat.n_C2O > 0)
10650
    printf ("n_C2O:%d;", molstat.n_C2O);
10651
  if (molstat.n_CN > 0)
10652
    printf ("n_CN:%d;", molstat.n_CN);
10653
  if (molstat.n_XY > 0)
10654
    printf ("n_XY:%d;", molstat.n_XY);
10655
  if (molstat.n_r3 > 0)
10656
    printf ("n_r3:%d;", molstat.n_r3);
10657
  if (molstat.n_r4 > 0)
10658
    printf ("n_r4:%d;", molstat.n_r4);
10659
  if (molstat.n_r5 > 0)
10660
    printf ("n_r5:%d;", molstat.n_r5);
10661
  if (molstat.n_r6 > 0)
10662
    printf ("n_r6:%d;", molstat.n_r6);
10663
  if (molstat.n_r7 > 0)
10664
    printf ("n_r7:%d;", molstat.n_r7);
10665
  if (molstat.n_r8 > 0)
10666
    printf ("n_r8:%d;", molstat.n_r8);
10667
  if (molstat.n_r9 > 0)
10668
    printf ("n_r9:%d;", molstat.n_r9);
10669
  if (molstat.n_r10 > 0)
10670
    printf ("n_r10:%d;", molstat.n_r10);
10671
  if (molstat.n_r11 > 0)
10672
    printf ("n_r11:%d;", molstat.n_r11);
10673
  if (molstat.n_r12 > 0)
10674
    printf ("n_r12:%d;", molstat.n_r12);
10675
  if (molstat.n_r13p > 0)
10676
    printf ("n_r13p:%d;", molstat.n_r13p);
10677
  if (molstat.n_rN > 0)
10678
    printf ("n_rN:%d;", molstat.n_rN);
10679
  if (molstat.n_rN1 > 0)
10680
    printf ("n_rN1:%d;", molstat.n_rN1);
10681
  if (molstat.n_rN2 > 0)
10682
    printf ("n_rN2:%d;", molstat.n_rN2);
10683
  if (molstat.n_rN3p > 0)
10684
    printf ("n_rN3p:%d;", molstat.n_rN3p);
10685
  if (molstat.n_rO > 0)
10686
    printf ("n_rO:%d;", molstat.n_rO);
10687
  if (molstat.n_rO1 > 0)
10688
    printf ("n_rO1:%d;", molstat.n_rO1);
10689
  if (molstat.n_rO2p > 0)
10690
    printf ("n_rO2p:%d;", molstat.n_rO2p);
10691
  if (molstat.n_rS > 0)
10692
    printf ("n_rS:%d;", molstat.n_rS);
10693
  if (molstat.n_rX > 0)
10694
    printf ("n_rX:%d;", molstat.n_rX);
10695
  if (molstat.n_rAr > 0)
10696
    printf ("n_rar:%d;", molstat.n_rAr);
10697
/* p2c: checkmol.pas, line 8532:
10698
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10699
  /*$IFDEF extended_molstat */
10700
  if (molstat.n_rBz > 0)
10701
    printf ("n_rbz:%d;", molstat.n_rBz);
10702
  if (molstat.n_br2p > 0)
10703
    printf ("n_br2p:%d;", molstat.n_br2p);
10704
  if (molstat.n_psg01 > 0)
10705
    printf ("n_psg01:%d;", molstat.n_psg01);
10706
  if (molstat.n_psg02 > 0)
10707
    printf ("n_psg02:%d;", molstat.n_psg02);
10708
  if (molstat.n_psg13 > 0)
10709
    printf ("n_psg13:%d;", molstat.n_psg13);
10710
  if (molstat.n_psg14 > 0)
10711
    printf ("n_psg14:%d;", molstat.n_psg14);
10712
  if (molstat.n_psg15 > 0)
10713
    printf ("n_psg15:%d;", molstat.n_psg15);
10714
  if (molstat.n_psg16 > 0)
10715
    printf ("n_psg16:%d;", molstat.n_psg16);
10716
  if (molstat.n_psg17 > 0)
10717
    printf ("n_psg17:%d;", molstat.n_psg17);
10718
  if (molstat.n_psg18 > 0)
10719
    printf ("n_psg18:%d;", molstat.n_psg18);
10720
  if (molstat.n_pstm > 0)
10721
    printf ("n_pstm:%d;", molstat.n_pstm);
10722
  if (molstat.n_psla > 0)
10723
    printf ("n_psla:%d;", molstat.n_psla);
10724
  if (molstat.n_iso > 0)
10725
    printf ("n_iso:%d;", molstat.n_iso);
10726
  if (molstat.n_rad > 0)
10727
    printf ("n_rad:%d;", molstat.n_rad);
10728
  /*$ENDIF */
10729
  putchar ('\n');
10730
}
10731
 
14179 bpr 10732
static void write_molstat_X ()
6785 bpr 10733
{
10734
  if (auto_ssr)                 /* v0.3n */
10735
    fix_ssr_ringcounts ();
14179 bpr 10736
    /* p2c: checkmol.pas, line 8556:
10737
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10738
#ifdef REDUCED_SAR
10739
  printf ("%d,", n_heavyatoms);
10740
  printf ("%d,", n_heavybonds);
10741
  printf ("%d,", n_countablerings);
14179 bpr 10742
    /* v0.3n: n_rings =?> n_countablerings */
6785 bpr 10743
#else
10744
  printf ("%d,", n_heavyatoms);
10745
  printf ("%d,", n_heavybonds);
10746
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
10747
#endif
10748
  printf ("%d,", molstat.n_QA);
10749
  printf ("%d,", molstat.n_QB);
10750
 
10751
  /* 0.3x */
10752
  printf ("%d,", molstat.n_chg);
10753
 
10754
  printf ("%d,", molstat.n_C1);
10755
  printf ("%d,", molstat.n_C2);
10756
  printf ("%d,", molstat.n_C);
10757
  printf ("%d,", molstat.n_CHB1p);
10758
  printf ("%d,", molstat.n_CHB2p);
10759
  printf ("%d,", molstat.n_CHB3p);
10760
  printf ("%d,", molstat.n_CHB4);
10761
  printf ("%d,", molstat.n_O2);
10762
  printf ("%d,", molstat.n_O3);
10763
  printf ("%d,", molstat.n_N1);
10764
  printf ("%d,", molstat.n_N2);
10765
  printf ("%d,", molstat.n_N3);
10766
  printf ("%d,", molstat.n_S);
10767
  printf ("%d,", molstat.n_SeTe);
10768
  printf ("%d,", molstat.n_F);
10769
  printf ("%d,", molstat.n_Cl);
10770
  printf ("%d,", molstat.n_Br);
10771
  printf ("%d,", molstat.n_I);
10772
  printf ("%d,", molstat.n_P);
10773
  printf ("%d,", molstat.n_B);
10774
  printf ("%d,", molstat.n_Met);
10775
  printf ("%d,", molstat.n_X);
10776
  printf ("%d,", molstat.n_b1);
10777
  printf ("%d,", molstat.n_b2);
10778
  printf ("%d,", molstat.n_b3);
10779
  printf ("%d,", molstat.n_bar);
10780
  printf ("%d,", molstat.n_C1O);
10781
  printf ("%d,", molstat.n_C2O);
10782
  printf ("%d,", molstat.n_CN);
10783
  printf ("%d,", molstat.n_XY);
10784
  printf ("%d,", molstat.n_r3);
10785
  printf ("%d,", molstat.n_r4);
10786
  printf ("%d,", molstat.n_r5);
10787
  printf ("%d,", molstat.n_r6);
10788
  printf ("%d,", molstat.n_r7);
10789
  printf ("%d,", molstat.n_r8);
10790
  printf ("%d,", molstat.n_r9);
10791
  printf ("%d,", molstat.n_r10);
10792
  printf ("%d,", molstat.n_r11);
10793
  printf ("%d,", molstat.n_r12);
10794
  printf ("%d,", molstat.n_r13p);
10795
  printf ("%d,", molstat.n_rN);
10796
  printf ("%d,", molstat.n_rN1);
10797
  printf ("%d,", molstat.n_rN2);
10798
  printf ("%d,", molstat.n_rN3p);
10799
  printf ("%d,", molstat.n_rO);
10800
  printf ("%d,", molstat.n_rO1);
10801
  printf ("%d,", molstat.n_rO2p);
10802
  printf ("%d,", molstat.n_rS);
10803
  printf ("%d,", molstat.n_rX);
10804
  printf ("%d", molstat.n_rAr);
14179 bpr 10805
  /* p2c: checkmol.pas, line 8579:
10806
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10807
  /*$IFDEF extended_molstat */
10808
  printf (",%d", molstat.n_rBz);
10809
  printf (",%d", molstat.n_br2p);
10810
  printf (",%d", molstat.n_psg01);
10811
  printf (",%d", molstat.n_psg02);
10812
  printf (",%d", molstat.n_psg13);
10813
  printf (",%d", molstat.n_psg14);
10814
  printf (",%d", molstat.n_psg15);
10815
  printf (",%d", molstat.n_psg16);
10816
  printf (",%d", molstat.n_psg17);
10817
  printf (",%d", molstat.n_psg18);
10818
  printf (",%d", molstat.n_pstm);
10819
  printf (",%d", molstat.n_psla);
10820
  printf (",%d", molstat.n_iso);
10821
  printf (",%d\n", molstat.n_rad);
10822
  /*$ENDIF */
10823
}
10824
 
10825
/* routines for substructure matching */
10826
 
14179 bpr 10827
static int find_ndl_ref_atom ()
6785 bpr 10828
{
6786 kbelabas 10829
  int i;
6785 bpr 10830
  int score = -1, index = 0;
10831
  int n_nb, n_hc, FORLIM;
10832
 
10833
  /* finds a characteristic atom in the needle molecule, */
10834
  /* i.e., one with as many substituents as possible and */
10835
  /* with as many heteroatom substitutents as possible; */
10836
  /* added in v0.2d: make sure that reference atom is a heavy atom */
10837
  /* and not (accidentally) an explicit hydrogen; */
10838
  /* new in v0.3d: special treatment in case of E/Z geometry search */
10839
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
10840
  /* matchpath, regardless where the recursive search starts; */
10841
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
10842
  /* added in v0.3o: needle atom must be "tagged" in order to be */
10843
  /* selected (prevents unconnected fragments from being overlooked) */
10844
  if (ndl_n_atoms == 0)
18544 georgesk 10845
    return isfalse;
14179 bpr 10846
  if (ez_search && ndl_n_heavyatoms > 2) {
10847
    FORLIM = ndl_n_atoms;
10848
    for (i = 1; i <= FORLIM; i++) {                     /* ignore sp2-carbons if not aromatic */
18544 georgesk 10849
           /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = istrue)) then */
10850
            if (ndl_alkene_C (i) == isfalse && ndl_atom[i - 1].tag) {                   /* v0.3o */
6785 bpr 10851
              n_nb = ndl_atom[i - 1].neighbor_count;
10852
              n_hc = ndl_hetatom_count (i);
14179 bpr 10853
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy) {
10854
                /* v0.3j */
10855
                index = i;
10856
                score = n_nb * 11 + n_hc * 7;   /* changed in v0.3j */
10857
              }
6785 bpr 10858
            }
14179 bpr 10859
          }
10860
  }
6785 bpr 10861
  /* it is possible that no suitable reference atom has been found here */
10862
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
14179 bpr 10863
  if (index == 0) {
18544 georgesk 10864
    ez_search = isfalse;        /* just in case it was istrue */
10865
    opt_geom = isfalse;         /* just in case it was istrue */
14179 bpr 10866
    FORLIM = ndl_n_atoms;
10867
    for (i = 1; i <= FORLIM; i++) {
10868
            n_nb = ndl_atom[i - 1].neighbor_count;
10869
            n_hc = ndl_hetatom_count (i);
10870
            if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
10871
                ndl_atom[i - 1].tag) {                  /* v0.3j */
6785 bpr 10872
              index = i;
10873
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
10874
            }
14179 bpr 10875
            /* v0.3o */
10876
          }
10877
  }
6785 bpr 10878
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
10879
  if (index == 0)               /* just to be sure... */
10880
    index++;
10881
  return index;
10882
}
10883
 
14179 bpr 10884
static void cv_init ()
6785 bpr 10885
{
10886
  /* new in v0.3j */
10887
  int i;
10888
 
10889
  if (cv == NULL)
10890
    return;
10891
  memset (cv, 0, sizeof (connval_type));
10892
 
10893
  for (i = 0; i < ndl_n_atoms; i++)
10894
    cv[i].def = ndl_atom[i].neighbor_count;
10895
}
10896
 
14179 bpr 10897
static int cv_count ()
6785 bpr 10898
{
10899
  /* new in v0.3j, modified in v0.3m */
10900
  int i, j;
10901
  int cvlist[max_atoms];
10902
  int cvdef;
10903
  boolean isnew;
10904
  int entries = 0;
10905
  int FORLIM;
10906
 
10907
  if (cv == NULL)
10908
    return 0;
10909
  memset (cvlist, 0, sizeof (int) * max_atoms);
10910
  FORLIM = ndl_n_atoms;
14179 bpr 10911
  for (i = 0; i < FORLIM; i++) {
18544 georgesk 10912
    if (ndl_atom[i].heavy == istrue) {
14179 bpr 10913
            cvdef = cv[i].def;
18544 georgesk 10914
            isnew = istrue;
14179 bpr 10915
            if (entries > 0) {
10916
              for (j = 0; j < entries; j++) {
10917
                      if (cvlist[j] == cvdef)
18544 georgesk 10918
                        isnew = isfalse;
14179 bpr 10919
                    }
6785 bpr 10920
            }
14179 bpr 10921
            if (isnew) {
10922
                entries++;
10923
                cvlist[entries - 1] = cvdef;
6785 bpr 10924
            }
14179 bpr 10925
            /* now we have a list of unique connection values */
10926
          }
10927
  }
6785 bpr 10928
  return entries;
10929
}
10930
 
17891 bpr 10931
static int cv_iterate (int n_cv_prev)
6785 bpr 10932
{
10933
  /* new in v0.3j, modified in v0.3m */
6788 kbelabas 10934
  int i, j;
6785 bpr 10935
  neighbor_rec nb;
10936
  int nnb, nsum, n_cv, FORLIM;
10937
 
10938
  if (cv == NULL || ndl_n_atoms == 0)
18544 georgesk 10939
    return isfalse;
6785 bpr 10940
  FORLIM = ndl_n_atoms;
10941
  /* update the connection values (Morgan algorithm) */
10942
 
10943
  memset (nb, 0, sizeof (neighbor_rec));
10944
 
14179 bpr 10945
  for (i = 1; i <= FORLIM; i++) {
18544 georgesk 10946
    if (ndl_atom[i - 1].heavy == istrue) {
14179 bpr 10947
            get_ndl_neighbors (nb, i);
10948
            nnb = ndl_atom[i - 1].neighbor_count;
10949
            nsum = 0;
10950
            if (nnb > 0) {
10951
              for (j = 0; j < nnb; j++) {
18544 georgesk 10952
                if (ndl_atom[nb[j] - 1].heavy == istrue)
14179 bpr 10953
                  nsum += cv[nb[j] - 1].def;
10954
              }
6785 bpr 10955
            }
14179 bpr 10956
            cv[i - 1].tmp = nsum;
10957
          }
10958
  }
6785 bpr 10959
  n_cv = cv_count ();
14179 bpr 10960
  if (n_cv > n_cv_prev) {
10961
    FORLIM = ndl_n_atoms;
10962
    for (i = 0; i < FORLIM; i++)
10963
            cv[i].def = cv[i].tmp;
10964
  }
6785 bpr 10965
  return n_cv;
10966
}
10967
 
14179 bpr 10968
static int find_ndl_ref_atom_cv ()
6785 bpr 10969
{
10970
  /* new in v0.3j, modified in v0.3m */
10971
  int Result, i;
10972
  int res = 1, it = 0;
10973
  int n_cv;
10974
  int n_cv_prev = 0;
18544 georgesk 10975
  boolean finished = isfalse;
6785 bpr 10976
  int cvmax = 0;
10977
  int FORLIM;
10978
 
10979
  if (ndl_n_atoms == 0)
10980
    return 0;
10981
  /* try */
10982
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
10983
  /* except
10984
     on e:Eoutofmemory do
10985
     begin
10986
     res := find_ndl_ref_atom;
10987
     $IFDEF debug
10988
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
10989
     $ENDIF
10990
     end;
10991
     end; */
10992
  cv_init ();
14179 bpr 10993
  do {
10994
    it++;                       /* iteration counter (a safeguard against infinite loops) */
10995
    n_cv = cv_iterate (n_cv_prev);
10996
    if (n_cv <= n_cv_prev)
18544 georgesk 10997
            finished = istrue;
14179 bpr 10998
    n_cv_prev = n_cv;
10999
  }
6785 bpr 11000
  while (!(finished || it > 10000));
11001
  FORLIM = ndl_n_atoms;
11002
  /* now that we have canonical connection values (Morgan algorithm), */
11003
  /* pick the atom with the highest value */
11004
  /* added in v0.3o: atom must be "tagged" */
14179 bpr 11005
  for (i = 1; i <= FORLIM; i++) {
6785 bpr 11006
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
18544 georgesk 11007
    if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == isfalse || ez_search == isfalse))
14179 bpr 11008
              && ndl_atom[i - 1].tag) {                 /* v0.3o */
11009
            cvmax = cv[i - 1].def;
11010
            res = i;
11011
          }
11012
  }
6785 bpr 11013
  Result = res;
11014
  /* try */
14179 bpr 11015
  if (cv != NULL) {
6785 bpr 11016
      free (cv);
11017
      cv = NULL;
11018
    }
11019
  /* except
11020
     on e:Einvalidpointer do begin end;
11021
     end; */
11022
  return Result;
11023
}
11024
 
17891 bpr 11025
static boolean atomtypes_OK_strict (int ndl_a, int hst_a)
6785 bpr 11026
{
11027
  /* new in v0.2f */
11028
  str2 ndl_el;
11029
  str3 ndl_atype;
11030
  str2 hst_el;
11031
  str3 hst_atype;
11032
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
18544 georgesk 11033
  boolean res = isfalse;
6785 bpr 11034
 
11035
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11036
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
11037
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11038
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11039
  strcpy (hst_el, atom[hst_a - 1].element);
11040
  strcpy (hst_atype, atom[hst_a - 1].atype);
11041
  hst_nbc = atom[hst_a - 1].neighbor_count;
11042
  hst_Htot = atom[hst_a - 1].Htot;
11043
  /* v0.3o: formal charges must be the same */
11044
 
11045
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
18544 georgesk 11046
    return isfalse;
6785 bpr 11047
 
11048
  /* v0.3x: isotope nucleon numbers must be the same */
11049
 
11050
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
18544 georgesk 11051
    return isfalse;
6785 bpr 11052
 
11053
  /* v0.3x: radicals must be the same */
11054
 
11055
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
18544 georgesk 11056
    return isfalse;
6785 bpr 11057
 
11058
  if (!strcmp (ndl_atype, hst_atype))
18544 georgesk 11059
    res = istrue;
14179 bpr 11060
  else {
11061
    if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom && atom[hst_a - 1].arom)
18544 georgesk 11062
            res = istrue;
14179 bpr 11063
    if (ndl_querymol && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
18544 georgesk 11064
            res = istrue;               /* 0.3 p */
14179 bpr 11065
  }
6785 bpr 11066
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
18544 georgesk 11067
    res = istrue;
14179 bpr 11068
  if (!strcmp (ndl_el, "Q ")) {
11069
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
18544 georgesk 11070
            res = istrue;
14179 bpr 11071
  }
11072
  if (!strcmp (ndl_el, "X ")) {
11073
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11074
            !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11075
            || !strcmp (hst_el, "AT"))
18544 georgesk 11076
          res = istrue;
14179 bpr 11077
  }
6785 bpr 11078
  /* if needle atom has more substituents than haystack atom ==> no match */
11079
  if (ndl_nbc > hst_nbc)
18544 georgesk 11080
    res = isfalse;
6785 bpr 11081
  /* check for explicit hydrogens */
11082
  if (ndl_Hexp > hst_Htot)
18544 georgesk 11083
    res = isfalse;
14179 bpr 11084
    /* p2c: checkmol.pas, line 8859:
11085
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11086
    /*$IFDEF debug */
11087
    /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
6785 bpr 11088
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
14179 bpr 11089
    /*$ENDIF */
11090
    /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
11091
  if (opt_fp) {
11092
    if (strcmp (ndl_el, hst_el))
18544 georgesk 11093
            res = isfalse;
14179 bpr 11094
  }
6785 bpr 11095
  return res;
11096
}
11097
 
17891 bpr 11098
static boolean atomtypes_OK (int ndl_a, int hst_a)
6785 bpr 11099
{
11100
  str2 ndl_el, hst_el;
11101
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
18544 georgesk 11102
  boolean res = isfalse;
6785 bpr 11103
 
11104
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
18544 georgesk 11105
    return isfalse;
6785 bpr 11106
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
11107
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
11108
  /* are tolerated (this is a feature, not a bug) */
14179 bpr 11109
  if (opt_chg) {
11110
    if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
18544 georgesk 11111
        return isfalse;
14179 bpr 11112
  }
11113
  //  else
11114
  //    {
11115
  //      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
11116
  //        atom[hst_a - 1].formal_charge != 0 &&
11117
  //        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
18544 georgesk 11118
  //      return isfalse;
14179 bpr 11119
  //    }
11120
  //
11121
  //  /* v0.3x: isotopes must be the same */
11122
  if (opt_iso) {
11123
    if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
18544 georgesk 11124
            return isfalse;
14179 bpr 11125
  }
11126
  //  else
11127
  //    {
11128
  //      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
11129
  //        atom[hst_a - 1].nucleon_number != 0 &&
11130
  //        ndl_atom[ndl_a - 1].nucleon_number !=
11131
  //        atom[hst_a - 1].nucleon_number)
18544 georgesk 11132
  //      return isfalse;
14179 bpr 11133
  //    }
11134
  //
11135
  //  /* v0.3x: radicals must be the same */
11136
  if (opt_rad) {
11137
    if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
18544 georgesk 11138
            return isfalse;
14179 bpr 11139
  }
11140
  //  else
11141
  //    {
11142
  //      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
11143
  //        atom[hst_a - 1].radical_type != 0 &&
11144
  //        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
18544 georgesk 11145
  //      return isfalse;
14179 bpr 11146
  //    }
6785 bpr 11147
 
11148
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
18544 georgesk 11149
  if (opt_exact && atom[hst_a - 1].tag == istrue) {
14179 bpr 11150
    /* p2c: checkmol.pas, line 8899:
11151
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11152
      /*$IFDEF debug */
11153
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
11154
      /*$ENDIF */
18544 georgesk 11155
      return isfalse;
14179 bpr 11156
  }
6785 bpr 11157
  if (opt_strict)               /* new in v0.2f */
11158
    return (atomtypes_OK_strict (ndl_a, hst_a));
11159
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11160
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11161
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11162
  strcpy (hst_el, atom[hst_a - 1].element);
11163
  hst_nbc = atom[hst_a - 1].neighbor_count;
11164
  hst_Htot = atom[hst_a - 1].Htot;
11165
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
18544 georgesk 11166
    res = istrue;
6785 bpr 11167
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
18544 georgesk 11168
    res = istrue;
14179 bpr 11169
  if (!strcmp (ndl_el, "Q ")) {
11170
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
18544 georgesk 11171
            res = istrue;
14179 bpr 11172
  }
11173
  if (!strcmp (ndl_el, "X ")) {
11174
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11175
              !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11176
              || !strcmp (hst_el, "AT"))
18544 georgesk 11177
            res = istrue;
14179 bpr 11178
  }
6785 bpr 11179
  /* v0.3o: in exact mode, check for identical neighbor_count */
14179 bpr 11180
  if (opt_exact) {
11181
    if (ndl_nbc != hst_nbc) {
18544 georgesk 11182
          res = isfalse;
14179 bpr 11183
    /* p2c: checkmol.pas, line 8934:
11184
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11185
          /*$IFDEF debug */
11186
          //debugoutput
11187
          //  ("exact match failed: different number of neighbor atoms");
11188
          /*$ENDIF */
11189
          }
11190
  }
6785 bpr 11191
  /* if needle atom has more substituents than haystack atom ==> no match */
11192
  if (ndl_nbc > hst_nbc)
18544 georgesk 11193
    res = isfalse;
6785 bpr 11194
  /* check for explicit hydrogens */
11195
  if (ndl_Hexp > hst_Htot)
18544 georgesk 11196
    res = isfalse;
14179 bpr 11197
  /* p2c: checkmol.pas, line 8943:
11198
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11199
  /*$IFDEF debug */
11200
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
11201
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
11202
  /*$ENDIF */
11203
  return res;
11204
}
11205
 
17891 bpr 11206
static boolean bondtypes_OK_strict (int ndl_b, int hst_b)
6785 bpr 11207
{
11208
  boolean ndl_arom, hst_arom;
11209
  char ndl_btype, hst_btype;
11210
  int ndl_rc;                   /* new in v0.3d */
11211
  int hst_rc;                   /* new in v0.3d */
11212
  int ndl_btopo;                /* new in v0.3d */
18544 georgesk 11213
  boolean res = isfalse;
14179 bpr 11214
  /* p2c: checkmol.pas, line 8960:
11215
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11216
  /*$IFDEF debug */
11217
  /*char na[256]; char ha[256];*/
11218
  char tstr[256];
11219
 
11220
  /*$ENDIF */
14179 bpr 11221
  /* p2c: checkmol.pas, line 8966:
11222
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11223
  /*$IFDEF debug */
11224
  *tstr = '\0';                 /* for debugging purposes only */
11225
  /*$ENDIF */
11226
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11227
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11228
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11229
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
11230
  hst_arom = bond[hst_b - 1].arom;
11231
  hst_btype = bond[hst_b - 1].btype;
11232
  hst_rc = bond[hst_b - 1].ring_count;
14179 bpr 11233
  /* p2c: checkmol.pas, line 8976:
11234
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11235
   /*$IFDEF debug */
11236
   /*if (ndl_arom)
11237
     strcpy (na, "(ar)");
11238
   else
11239
     *na = '\0';
11240
   if (hst_arom)
11241
     strcpy (ha, "(ar)");
11242
   else
11243
     *ha = '\0';*/
11244
   /*$ENDIF */
18544 georgesk 11245
  if (ndl_arom == istrue && hst_arom == istrue)
11246
    res = istrue;
11247
  if (ndl_arom == isfalse && hst_arom == isfalse) {
14179 bpr 11248
    if (ndl_btype == hst_btype)
18544 georgesk 11249
            res = istrue;
14179 bpr 11250
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
18544 georgesk 11251
            res = istrue;
14179 bpr 11252
    if (ndl_btype == 's' && hst_btype == 'S')
18544 georgesk 11253
            res = istrue;
14179 bpr 11254
    if (ndl_btype == 'd' && hst_btype == 'D')
18544 georgesk 11255
            res = istrue;
14179 bpr 11256
  }
6785 bpr 11257
  /* a little exception: */
18544 georgesk 11258
  if (ndl_arom == isfalse && hst_arom == istrue) {
14179 bpr 11259
    if (ndl_btype == 'A')
18544 georgesk 11260
            res = istrue;
14179 bpr 11261
    if (ndl_btype == 's' || ndl_btype == 'd')
18544 georgesk 11262
            res = istrue;
14179 bpr 11263
    if (ndl_bond[ndl_b - 1].q_arom)
18544 georgesk 11264
            res = istrue;               /* 0.3p */
14179 bpr 11265
  }
6785 bpr 11266
  if (ndl_btype == 'a')
18544 georgesk 11267
    res = istrue;
6785 bpr 11268
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
14179 bpr 11269
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc) {
11270
    if (ndl_rc != hst_rc) {
18544 georgesk 11271
            res = isfalse;              /* this excludes further ring annulations as well as */
14179 bpr 11272
      /* p2c: checkmol.pas, line 9001:
11273
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11274
            /*$IFDEF debug */
11275
            /* open-chains query structures to be found in rings */
11276
            /*
11277
               tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
11278
            /*$ENDIF */
11279
          }
11280
  }
11281
  else {
11282
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc) {
18544 georgesk 11283
            res = isfalse;
14179 bpr 11284
    /* p2c: checkmol.pas, line 9010:
11285
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11286
          /*$IFDEF debug */
11287
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
11288
          /*$ENDIF */
14179 bpr 11289
          }
11290
  }
11291
  /* p2c: checkmol.pas, line 9015:
11292
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11293
    /*$IFDEF debug */
11294
    /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11295
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11296
    /*$ENDIF */
6785 bpr 11297
  return res;
11298
}
11299
 
17891 bpr 11300
static boolean bondtypes_OK (int ndl_b, int hst_b)
6785 bpr 11301
{
11302
  boolean ndl_arom, hst_arom;
11303
  char ndl_btype, hst_btype;
11304
  int ndl_rc;                   /* new in v0.3d */
11305
  int hst_rc;                   /* new in v0.3d */
11306
  int ndl_btopo;                /* new in v0.3d */
18544 georgesk 11307
  boolean res = isfalse;
14179 bpr 11308
  /* p2c: checkmol.pas, line 9032:
11309
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11310
  /*$IFDEF debug */
11311
  /*char na[256], ha[256];*/
11312
  char tstr[256];
11313
  /*$ENDIF */
11314
  int a1, a2;
11315
  str2 a1_el, a2_el;
11316
 
11317
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
18544 georgesk 11318
    return isfalse;
6785 bpr 11319
  if (opt_strict)               /* new in v0.2f */
11320
    return (bondtypes_OK_strict (ndl_b, hst_b));
14179 bpr 11321
  /* p2c: checkmol.pas, line 9051:
11322
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11323
  /*$IFDEF debug */
11324
  *tstr = '\0';                 /* for debug purposes only */
11325
  /*$ENDIF */
11326
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11327
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11328
  hst_arom = bond[hst_b - 1].arom;
11329
  hst_btype = bond[hst_b - 1].btype;
11330
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11331
  hst_rc = bond[hst_b - 1].ring_count;
11332
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
14179 bpr 11333
  /* p2c: checkmol.pas, line 9061:
11334
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11335
    /*$IFDEF debug */
11336
    //if (ndl_arom)
11337
  //    strcpy (na, "(ar)");
11338
  //  else
11339
  //    *na = '\0';
11340
  //  if (hst_arom)
11341
  //    strcpy (ha, "(ar)");
11342
  //  else
11343
  //    *ha = '\0';
6785 bpr 11344
  /*$ENDIF */
18544 georgesk 11345
  if (ndl_arom == istrue && hst_arom == istrue)
11346
    res = istrue;
11347
  if (ndl_arom == isfalse && hst_arom == isfalse) {
14179 bpr 11348
    if (ndl_btype == hst_btype)
18544 georgesk 11349
            res = istrue;
14179 bpr 11350
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
18544 georgesk 11351
            res = istrue;
14179 bpr 11352
    if (ndl_btype == 's' && hst_btype == 'S')
18544 georgesk 11353
            res = istrue;
14179 bpr 11354
    if (ndl_btype == 'd' && hst_btype == 'D')
18544 georgesk 11355
            res = istrue;
14179 bpr 11356
  }
6785 bpr 11357
  /* a little exception: */
18544 georgesk 11358
  if (ndl_arom == isfalse && hst_arom == istrue) {
14179 bpr 11359
    if (ndl_btype == 'A')
18544 georgesk 11360
            res = istrue;
14179 bpr 11361
    if (ndl_btype == 's' || ndl_btype == 'd')
18544 georgesk 11362
            res = istrue;
14179 bpr 11363
    if (ndl_btype == 'D') {                     /* added in 0.2d: do not accept C=O etc. as C-O/arom */
11364
            a1 = ndl_bond[ndl_b - 1].a1;
11365
            a2 = ndl_bond[ndl_b - 1].a2;
11366
            strcpy (a1_el, ndl_atom[a1 - 1].element);
11367
            strcpy (a2_el, ndl_atom[a2 - 1].element);
11368
            if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
11369
                && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
11370
                && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
11371
                && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
18544 georgesk 11372
              res = istrue;
14179 bpr 11373
          }
11374
    if (ndl_bond[ndl_b - 1].q_arom)
18544 georgesk 11375
            res = istrue;               /* 0.3p */
14179 bpr 11376
  }
6785 bpr 11377
  if (ndl_btype == 'a')
18544 georgesk 11378
    res = istrue;
6785 bpr 11379
  /* new in v0.3d: obey topology requirements in query structure */
14179 bpr 11380
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any) {
11381
    if (ndl_btopo == btopo_ring && hst_rc == 0)
18544 georgesk 11382
      res = isfalse;
14179 bpr 11383
    if (ndl_btopo == btopo_chain && hst_rc > 0)
18544 georgesk 11384
      res = isfalse;
14179 bpr 11385
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
18544 georgesk 11386
      res = isfalse;
14179 bpr 11387
    if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
18544 georgesk 11388
      res = isfalse;
14179 bpr 11389
  }
11390
  /* p2c: checkmol.pas, line 9098:
11391
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11392
    /*$IFDEF debug */
18544 georgesk 11393
    /* if res = isfalse then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
14179 bpr 11394
    /*$ENDIF */
11395
  /* p2c: checkmol.pas, line 9102:
11396
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11397
    /*$IFDEF debug */
11398
    /*
11399
       if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11400
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11401
    /*$ENDIF */
6785 bpr 11402
  return res;
11403
}
11404
 
17891 bpr 11405
static boolean matrix_OK (boolean (*m)[max_neighbors], int ndl_dim, int hst_dim)
6785 bpr 11406
{
11407
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
18544 georgesk 11408
  boolean mr = isfalse;
6785 bpr 11409
  matchmatrix lm;
11410
  int i, ii, j, lndl_dim, lhst_dim;
11411
 
11412
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
11413
      hst_dim > max_neighbors || ndl_dim > hst_dim)
18544 georgesk 11414
    return isfalse;
14179 bpr 11415
  if (ndl_dim == 1) {
11416
    for (i = 0; i < hst_dim; i++) {
11417
            if (m[0][i])
18544 georgesk 11418
              mr = istrue;
14179 bpr 11419
          }
11420
    return mr;
11421
  }
11422
  for (i = 1; i <= hst_dim; i++) {
11423
    if (m[0][i - 1]) {
11424
            /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
18544 georgesk 11425
            memset (lm, isfalse, sizeof (matchmatrix));
14179 bpr 11426
            for (j = 2; j <= ndl_dim; j++) {
6785 bpr 11427
              lhst_dim = 0;
14179 bpr 11428
              for (ii = 1; ii <= hst_dim; ii++) {
11429
                if (ii != i) {
11430
                  lhst_dim++;
11431
                  lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
11432
                }
11433
              }
6785 bpr 11434
            }
14179 bpr 11435
            lndl_dim = ndl_dim - 1;
11436
            if (matrix_OK (lm, lndl_dim, lhst_dim)) {                   /* recursive call to matrix_OK */
18544 georgesk 11437
              return istrue;
14179 bpr 11438
            /* stop any further work immediately */
6785 bpr 11439
            }
14179 bpr 11440
          }
11441
  }
18544 georgesk 11442
  return isfalse;
6785 bpr 11443
}
11444
 
17891 bpr 11445
static boolean is_flat (double angle_deg)
6785 bpr 11446
{
11447
  /* new in v0.3j */
11448
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
18544 georgesk 11449
    return isfalse;
6785 bpr 11450
  else
18544 georgesk 11451
    return istrue;
6785 bpr 11452
}
11453
 
17891 bpr 11454
static boolean chirality_OK (int *ndl_cp, int *hst_cp)
6785 bpr 11455
{
18544 georgesk 11456
  boolean res = istrue;
6785 bpr 11457
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
11458
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
11459
  int level = 0;
11460
  int i;
18544 georgesk 11461
  boolean up = isfalse, down = isfalse, updown = isfalse;
6785 bpr 11462
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
11463
 
11464
  /* fill temporary atom variables */
11465
  ta1 = ndl_cp[0];              /* this is the central atom */
11466
  ta2 = ndl_cp[1];
11467
  ta3 = ndl_cp[2];
11468
  ta4 = ndl_cp[3];
11469
  /* first, get the central atom of the needle */
11470
  np2.x = ndl_atom[ta1 - 1].x;
11471
  np2.y = ndl_atom[ta1 - 1].y;
11472
  np2.z = ndl_atom[ta1 - 1].z;
11473
  /* next, do the same for all 3 substituent atoms */
11474
  np1.x = ndl_atom[ta2 - 1].x;
11475
  np1.y = ndl_atom[ta2 - 1].y;
11476
  np1.z = ndl_atom[ta2 - 1].z;
11477
  np3.x = ndl_atom[ta3 - 1].x;
11478
  np3.y = ndl_atom[ta3 - 1].y;
11479
  np3.z = ndl_atom[ta3 - 1].z;
11480
  np4.x = ndl_atom[ta4 - 1].x;
11481
  np4.y = ndl_atom[ta4 - 1].y;
11482
  np4.z = ndl_atom[ta4 - 1].z;
11483
  /* now check all needle bonds if we should care about up/down bonds */
14179 bpr 11484
  if (ndl_n_bonds > 0) {
11485
    FORLIM = ndl_n_bonds;
11486
    for (i = 0; i < FORLIM; i++) {
11487
            if (ndl_bond[i].stereo == bstereo_up ||
11488
                  ndl_bond[i].stereo == bstereo_down) {
6785 bpr 11489
              ba1 = ndl_bond[i].a1;
11490
              ba2 = ndl_bond[i].a2;
14179 bpr 11491
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up) {
18544 georgesk 11492
                      up = istrue;
14179 bpr 11493
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
18544 georgesk 11494
                        updown = istrue;
14179 bpr 11495
                        if (ba2 == ta2)
11496
                                np1.z += 0.8;
11497
                        if (ba2 == ta3)
11498
                                np3.z += 0.8;
11499
                        if (ba2 == ta4)
11500
                                np4.z += 0.8;
11501
                      }
11502
                      else
11503
                        level++;
6785 bpr 11504
                    }
14179 bpr 11505
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down) {
18544 georgesk 11506
                      down = istrue;
14179 bpr 11507
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
18544 georgesk 11508
                        updown = istrue;
14179 bpr 11509
                        if (ba2 == ta2)
11510
                                np1.z -= 0.8;
11511
                        if (ba2 == ta3)
11512
                                np3.z -= 0.8;
11513
                        if (ba2 == ta4)
11514
                                np4.z -= 0.8;
11515
                      }
11516
                      else
11517
                        level--;
6785 bpr 11518
                    }
14179 bpr 11519
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up) {
18544 georgesk 11520
                      down = istrue;
14179 bpr 11521
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
18544 georgesk 11522
                        updown = istrue;
14179 bpr 11523
                        if (ba1 == ta2)
11524
                          np1.z -= 0.8;
11525
                        if (ba1 == ta3)
11526
                          np3.z -= 0.8;
11527
                        if (ba1 == ta4)
11528
                          np4.z -= 0.8;
11529
                      }
11530
                      else
11531
                        level--;
6785 bpr 11532
                    }
14179 bpr 11533
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down) {
18544 georgesk 11534
                      up = istrue;
14179 bpr 11535
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
18544 georgesk 11536
                        updown = istrue;
14179 bpr 11537
                        if (ba1 == ta2)
11538
                                np1.z += 0.8;
11539
                        if (ba1 == ta3)
11540
                                np3.z += 0.8;
11541
                        if (ba1 == ta4)
11542
                                np4.z += 0.8;
11543
                      }
11544
                      else
11545
                        level++;
6785 bpr 11546
                    }
11547
            }
14179 bpr 11548
          }                     /* for i ... */
18544 georgesk 11549
    if (updown == isfalse && level != 0) {
14179 bpr 11550
            if (level > 0)
11551
              np2.z += 0.3;
11552
            if (level < 0)
11553
              np2.z -= 0.3;
11554
          }
11555
    else {
11556
            if (up)
11557
              np2.z += 0.1;
11558
            if (down)
11559
              np2.z -= 0.1;
11560
          }
11561
  }
6785 bpr 11562
  /* fill temporary atom variables again */
11563
  ta1 = hst_cp[0];
11564
  ta2 = hst_cp[1];
11565
  ta3 = hst_cp[2];
11566
  ta4 = hst_cp[3];
11567
  /* then, get the central atom of the haystack */
11568
  hp2.x = atom[ta1 - 1].x;
11569
  hp2.y = atom[ta1 - 1].y;
11570
  hp2.z = atom[ta1 - 1].z;
11571
  /* next, do the same for all 3 substituent atoms */
11572
  hp1.x = atom[ta2 - 1].x;
11573
  hp1.y = atom[ta2 - 1].y;
11574
  hp1.z = atom[ta2 - 1].z;
11575
  hp3.x = atom[ta3 - 1].x;
11576
  hp3.y = atom[ta3 - 1].y;
11577
  hp3.z = atom[ta3 - 1].z;
11578
  hp4.x = atom[ta4 - 1].x;
11579
  hp4.y = atom[ta4 - 1].y;
11580
  hp4.z = atom[ta4 - 1].z;
11581
  /* now check all haystack bonds if we should care about up/down bonds */
11582
  level = 0;
18544 georgesk 11583
  updown = isfalse;
11584
  up = isfalse;
11585
  down = isfalse;
14179 bpr 11586
  if (n_bonds > 0) {
11587
    FORLIM = n_bonds;
11588
    for (i = 0; i < FORLIM; i++) {
11589
            if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down) {
6785 bpr 11590
              ba1 = bond[i].a1;
11591
              ba2 = bond[i].a2;
14179 bpr 11592
              if (ba1 == ta1 && bond[i].stereo == bstereo_up) {
18544 georgesk 11593
                      up = istrue;
14179 bpr 11594
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
18544 georgesk 11595
                        updown = istrue;
14179 bpr 11596
                        if (ba2 == ta2)
11597
                                hp1.z += 0.8;
11598
                        if (ba2 == ta3)
11599
                                hp3.z += 0.8;
11600
                        if (ba2 == ta4)
11601
                                hp4.z += 0.8;
11602
                      }
11603
                      else
11604
                        level++;
6785 bpr 11605
                    }
14179 bpr 11606
              if (ba1 == ta1 && bond[i].stereo == bstereo_down) {
18544 georgesk 11607
                      down = istrue;
14179 bpr 11608
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
18544 georgesk 11609
                        updown = istrue;
14179 bpr 11610
                        if (ba2 == ta2)
11611
                              hp1.z -= 0.8;
11612
                        if (ba2 == ta3)
11613
                                hp3.z -= 0.8;
11614
                        if (ba2 == ta4)
11615
                              hp4.z -= 0.8;
11616
                     }
11617
                    else
11618
                      level--;
6785 bpr 11619
                    }
14179 bpr 11620
              if (ba2 == ta1 && bond[i].stereo == bstereo_up) {
18544 georgesk 11621
                      down = istrue;
14179 bpr 11622
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
18544 georgesk 11623
                        updown = istrue;
14179 bpr 11624
                        if (ba1 == ta2)
11625
                               hp1.z -= 0.8;
11626
                        if (ba1 == ta3)
11627
                                hp3.z -= 0.8;
11628
                        if (ba1 == ta4)
11629
                                hp4.z -= 0.8;
11630
                      }
11631
                      else
11632
                        level--;
6785 bpr 11633
                    }
14179 bpr 11634
              if (ba2 == ta1 && bond[i].stereo == bstereo_down) {
18544 georgesk 11635
                      up = istrue;
14179 bpr 11636
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
18544 georgesk 11637
                        updown = istrue;
14179 bpr 11638
                        if (ba1 == ta2)
11639
                                hp1.z += 0.8;
11640
                        if (ba1 == ta3)
11641
                                hp3.z += 0.8;
11642
                        if (ba1 == ta4)
11643
                                hp4.z += 0.8;
11644
                      }
11645
                      else
11646
                        level++;
6785 bpr 11647
                    }
11648
            }
14179 bpr 11649
          }                     /* for i ... */
18544 georgesk 11650
    if (updown == isfalse && level != 0) {
14179 bpr 11651
            if (level > 0)
11652
              hp2.z += 0.3;
11653
            if (level < 0)
11654
              hp2.z -= 0.3;
11655
          }
11656
    else {
11657
            if (up)
11658
              hp2.z += 0.1;
11659
            if (down)
11660
              hp2.z -= 0.1;
11661
          }
11662
  }
6785 bpr 11663
  /* get the pseudo-torsion angles */
11664
  ndl_ct = ctorsion (np1, np2, np3, np4);
11665
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
11666
  ndl_ct_deg = radtodeg (ndl_ct);
11667
  hst_ct_deg = radtodeg (hst_ct);
11668
  /* now do a plausibility check and finally check the sense */
11669
  /* (clockwise or counterclockwise) */
11670
  /*
11671
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
11672
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
18544 georgesk 11673
     (ndl_ct_deg * hst_ct_deg < 0) then res := isfalse;
6785 bpr 11674
   */
11675
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
11676
      ndl_ct_deg * hst_ct_deg < 0)
18544 georgesk 11677
    res = isfalse;
14179 bpr 11678
  if (rs_strict) {
17890 bpr 11679
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) ||
14179 bpr 11680
                (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
11681
                ndl_ct_deg * hst_ct_deg < 0)
18544 georgesk 11682
              res = isfalse;
14179 bpr 11683
  }
6785 bpr 11684
  return res;
11685
}
11686
 
17891 bpr 11687
static boolean ndl_maybe_chiral (int na)
6785 bpr 11688
{
11689
  /* new in v0.3h */
18544 georgesk 11690
  boolean res = isfalse;
6785 bpr 11691
  str2 el;
11692
  str3 at;
11693
  int n_nb;
11694
 
11695
  strcpy (el, ndl_atom[na - 1].element);
11696
  strcpy (at, ndl_atom[na - 1].atype);
11697
  n_nb = ndl_atom[na - 1].neighbor_count;
11698
  if (!strcmp (at, "C3 ") && n_nb > 2)
18544 georgesk 11699
    res = istrue;
14179 bpr 11700
  if (!strcmp (el, "N ")) {
11701
    if (!strcmp (at, "N3+") && n_nb == 4)
18544 georgesk 11702
            res = istrue;
14179 bpr 11703
  }
11704
  if (!strcmp (el, "S ")) {                             /* sulfoxide */
11705
    if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
18544 georgesk 11706
            res = istrue;
14179 bpr 11707
  }
6785 bpr 11708
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
11709
    return res;
11710
  if (n_nb > 3)                 /* are we missing something here? */
18544 georgesk 11711
    res = istrue;
6785 bpr 11712
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
18544 georgesk 11713
    res = isfalse;
6785 bpr 11714
  return res;
11715
}
11716
 
17891 bpr 11717
static boolean is_matching (int *ndl_xmp, int *hst_xmp)
6785 bpr 11718
{
11719
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
11720
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
11721
  int next_ndl_a, next_hst_a;
11722
  neighbor_rec ndl_nb, hst_nb;
11723
  matchmatrix mm;
11724
  int ndl_mp_len, hst_mp_len;
11725
  matchpath_type ndl_mp, hst_mp;
11726
  boolean emptyline, res, ndl_cis, hst_cis;
11727
  int na1, na2, na3, na4;       /* v0.3d */
11728
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
11729
  int prev_ndl_b;
11730
  int prev_hst_b;
11731
  p_3d p1, p2, p3, p4;
11732
  /*hst_torsion, ndl_torsion : double; */
11733
  chirpath_type ncp, hcp;
11734
  int n_hits, n_singlehits;
14179 bpr 11735
  /* p2c: checkmol.pas, line 9433:
11736
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11737
  /*$IFDEF debug */
11738
  //char tmpstr[256];
11739
 
11740
  /*$ENDIF */
11741
  /* initialize local matchpath variables */
11742
  //memset (ndl_mp, 0, sizeof (matchpath_type));
11743
  //memset (hst_mp, 0, sizeof (matchpath_type));
11744
  /* copy content of external variables into local ones */
11745
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
11746
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
11747
 
11748
  /*for (i = 0; i < max_matchpath_length; i++)
11749
     {
11750
     ndl_mp[i] = ndl_xmp[i];
11751
     hst_mp[i] = hst_xmp[i];
11752
     } */
11753
 
11754
  ndl_mp_len = matchpath_length (ndl_mp);
11755
  hst_mp_len = matchpath_length (hst_mp);
14179 bpr 11756
  if (ndl_mp_len != hst_mp_len) {
6785 bpr 11757
      /* this should never happen.... */
14179 bpr 11758
  /* p2c: checkmol.pas, line 9451:
11759
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11760
      /*$IFDEF debug */
11761
      //debugoutput ("needle and haystack matchpaths are of different length");
11762
      /*$ENDIF */
18544 georgesk 11763
    return isfalse;
14179 bpr 11764
  }
6785 bpr 11765
  ndl_a = ndl_mp[ndl_mp_len - 1];
11766
  hst_a = hst_mp[hst_mp_len - 1];
18544 georgesk 11767
  ndl_atom[ndl_a - 1].tag = isfalse;
6785 bpr 11768
  /* new in v0.3o: mark the last needle atom as "visited" */
14179 bpr 11769
  if (ndl_mp_len > 1) {
11770
    prev_ndl_a = ndl_mp[ndl_mp_len - 2];
11771
    prev_hst_a = hst_mp[hst_mp_len - 2];
6785 bpr 11772
    }
11773
  /* if geometry checking is on, check it here */
18544 georgesk 11774
  if (ez_search == istrue && ndl_mp_len > 3) {
14179 bpr 11775
    na1 = ndl_mp[ndl_mp_len - 1];
11776
    na2 = ndl_mp[ndl_mp_len - 2];
11777
    na3 = ndl_mp[ndl_mp_len - 3];
11778
    na4 = ndl_mp[ndl_mp_len - 4];
11779
    ha1 = hst_mp[hst_mp_len - 1];
11780
    ha2 = hst_mp[hst_mp_len - 2];
11781
    ha3 = hst_mp[hst_mp_len - 3];
11782
    ha4 = hst_mp[hst_mp_len - 4];
11783
    prev_ndl_b = get_ndl_bond (na2, na3);
11784
    prev_hst_b = get_bond (ha2, ha3);
18544 georgesk 11785
    if (ndl_bond[prev_ndl_b - 1].btype == 'D' && bond[prev_hst_b - 1].arom == isfalse
14179 bpr 11786
              && (ndl_bond[prev_ndl_b - 1].stereo != bstereo_double_either
11787
              && bond[prev_hst_b - 1].stereo != bstereo_double_either)
11788
              /* 0.3x always match if needle and/or haystack bond is double_either */
11789
              && (!strcmp (atom[ha2 - 1].element, "C ")
11790
              || !strcmp (atom[ha2 - 1].element, "N "))
11791
              && (!strcmp (atom[ha3 - 1].element, "C ")
11792
              || !strcmp (atom[ha3 - 1].element, "N "))){
11793
                /* v0.3g; check C=C, C=N, N=N bonds */
11794
            p1.x = atom[ha1 - 1].x;
11795
            p1.y = atom[ha1 - 1].y;
11796
            p1.z = atom[ha1 - 1].z;
11797
            p2.x = atom[ha2 - 1].x;
11798
            p2.y = atom[ha2 - 1].y;
11799
            p2.z = atom[ha2 - 1].z;
11800
            p3.x = atom[ha3 - 1].x;
11801
            p3.y = atom[ha3 - 1].y;
11802
            p3.z = atom[ha3 - 1].z;
11803
            p4.x = atom[ha4 - 1].x;
11804
            p4.y = atom[ha4 - 1].y;
11805
            p4.z = atom[ha4 - 1].z;
11806
            hst_cis = is_cis (p1, p2, p3, p4);
11807
            /*hst_torsion := torsion(p1,p2,p3,p4); */
11808
            p1.x = ndl_atom[na1 - 1].x;
11809
            p1.y = ndl_atom[na1 - 1].y;
11810
            p1.z = ndl_atom[na1 - 1].z;
11811
            p2.x = ndl_atom[na2 - 1].x;
11812
            p2.y = ndl_atom[na2 - 1].y;
11813
            p2.z = ndl_atom[na2 - 1].z;
11814
            p3.x = ndl_atom[na3 - 1].x;
11815
            p3.y = ndl_atom[na3 - 1].y;
11816
            p3.z = ndl_atom[na3 - 1].z;
11817
            p4.x = ndl_atom[na4 - 1].x;
11818
            p4.y = ndl_atom[na4 - 1].y;
11819
            p4.z = ndl_atom[na4 - 1].z;
11820
            /*ndl_torsion := torsion(p1,p2,p3,p4); */
11821
            ndl_cis = is_cis (p1, p2, p3, p4);
11822
            if (ndl_cis != hst_cis) {
11823
        /* p2c: checkmol.pas, line 9501:
11824
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11825
              /*$IFDEF debug */
11826
              //debugoutput ("E/Z geometry mismatch");
11827
              /*$ENDIF */
18544 georgesk 11828
              return isfalse;
6785 bpr 11829
            }
14179 bpr 11830
          }
11831
  }                             /* end of E/Z geometry check */
6785 bpr 11832
  /* check whatever can be checked as early as now: */
11833
  /* e.g. different elements or more substituents on needle atom than on haystack */
11834
  if (!atomtypes_OK (ndl_a, hst_a))
18544 georgesk 11835
    return isfalse;
6785 bpr 11836
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
14179 bpr 11837
  if (atom[hst_a - 1].neighbor_count == 0 && ndl_atom[ndl_a - 1].neighbor_count == 0) {
11838
    if (!atomtypes_OK (ndl_a, hst_a))
18544 georgesk 11839
            return isfalse;
14179 bpr 11840
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
18544 georgesk 11841
    atom[hst_a - 1].tag = istrue;
11842
    return istrue;
14179 bpr 11843
  }
6785 bpr 11844
  /* and other possibilities: */
11845
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
11846
  hst_b = get_bond (prev_hst_a, hst_a);
14179 bpr 11847
  /* p2c: checkmol.pas, line 9529:
11848
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11849
  /*$IFDEF debug */
11850
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
11851
  /*$ENDIF */
14179 bpr 11852
  if (ndl_b > 0 && hst_b > 0) {
11853
    /* do a quick check if bond types match */
11854
    if (!bondtypes_OK (ndl_b, hst_b)) {
11855
      /* p2c: checkmol.pas, line 9537:
11856
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11857
            /*$IFDEF debug */
11858
            /*
6785 bpr 11859
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
14179 bpr 11860
           /*$ENDIF */
18544 georgesk 11861
            return isfalse;
14179 bpr 11862
          }
11863
  }
6785 bpr 11864
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
14179 bpr 11865
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a, hst_a) &&
11866
      bondtypes_OK (ndl_b, hst_b)) {
18544 georgesk 11867
    return istrue;
14179 bpr 11868
  /* p2c: checkmol.pas, line 9549:
11869
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11870
      /*$IFDEF debug */
11871
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
11872
      /*$ENDIF */
14179 bpr 11873
  }
6785 bpr 11874
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
11875
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
14179 bpr 11876
        (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp))) {
18544 georgesk 11877
    return isfalse;
14179 bpr 11878
    /* p2c: checkmol.pas, line 9559:
11879
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11880
      /*$IFDEF debug */
11881
      /*
11882
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
11883
         {$ENDIF */
14179 bpr 11884
  }
6785 bpr 11885
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
11886
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
14179 bpr 11887
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp))) {
11888
    if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
11889
              atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b)) {
11890
              /* 1st chirality check */
11891
            if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
11892
                                                       ndl_atom[ndl_a -1].stereo_care)) && ndl_maybe_chiral (ndl_a))) {
11893
                                        /* new in v0.3h */
18544 georgesk 11894
              return istrue;
6785 bpr 11895
            }                   /* end of 1st chirality check */
14179 bpr 11896
            na1 = ndl_a;                /* the (potential) chiral center (v0.3f) */
11897
            na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
11898
            na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
11899
            na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
11900
            ha1 = hst_a;
11901
            ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
11902
            ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
11903
            ha4 = hst_mp[matchpath_length (hst_mp) - 2];
11904
            memset (ncp, 0, sizeof (chirpath_type));
11905
            memset (hcp, 0, sizeof (chirpath_type));
11906
            ncp[0] = na1;
11907
            ncp[1] = na2;
11908
            ncp[2] = na3;
11909
            ncp[3] = na4;
11910
            hcp[0] = ha1;
11911
            hcp[1] = ha2;
11912
            hcp[2] = ha3;
11913
            hcp[3] = ha4;
11914
            if (!chirality_OK (ncp, hcp)) {
11915
        /* p2c: checkmol.pas, line 9589:
11916
         * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11917
                      /*$IFDEF debug */
11918
                      //debugoutput ("chirality check failed at ring junction");
11919
                      /*$ENDIF */
18544 georgesk 11920
        return isfalse;
14179 bpr 11921
      }
11922
      /* p2c: checkmol.pas, line 9596:
11923
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11924
          /*$IFDEF debug */
11925
          //debugoutput ("chirality check succeeded at ring junction");
11926
          /*$ENDIF */
18544 georgesk 11927
      return istrue;
14179 bpr 11928
      /* p2c: checkmol.pas, line 9602:
11929
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11930
            /*$IFDEF debug */
11931
            /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
11932
            /*$ENDIF */
11933
          }
11934
    else {
18544 georgesk 11935
            return isfalse;
14179 bpr 11936
      /* p2c: checkmol.pas, line 9609:
11937
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11938
            /*$IFDEF debug */
11939
            /*
11940
               debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
11941
            /*$ENDIF */
11942
          }
11943
  }
6785 bpr 11944
  /* in all other cases, do the hard work: */
11945
  /* first, get all heavy-atom neighbors of needle and haystack; */
11946
  /* at the beginning of the search, this means all neighbors, then it means */
11947
  /* all but the previous atom (where we came from) */
11948
  memset (ndl_nb, 0, sizeof (neighbor_rec));
11949
  memset (hst_nb, 0, sizeof (neighbor_rec));
11950
 
14179 bpr 11951
  if (matchpath_length (ndl_mp) == 1) {
11952
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
11953
    n_nb = atom[hst_a - 1].neighbor_count;
11954
    get_ndl_neighbors (ndl_nb, ndl_a);
11955
    get_neighbors (hst_nb, hst_a);
11956
  }
11957
  else {
11958
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
11959
    n_nb = atom[hst_a - 1].neighbor_count - 1;
11960
    get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
11961
    get_nextneighbors (hst_nb, hst_a, prev_hst_a);
11962
  }
6785 bpr 11963
  /* v0.3o: mark all neighbor atoms as "visited" */
11964
  for (i = 0; i < ndl_n_nb; i++)
18544 georgesk 11965
    ndl_atom[ndl_nb[i] - 1].tag = isfalse;
6785 bpr 11966
  /* now that the neighbor-arrays are filled, get all */
11967
  /* combinations of matches recursively; */
11968
  /* first, initialize the match matrix */
18544 georgesk 11969
  memset (mm, isfalse, sizeof (matchmatrix));   /* new in v0.2i */
6785 bpr 11970
  /* make sure there are not too many neighbors (max. max_neighbors)   */
14179 bpr 11971
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors) {                               /* updated in v0.2i */
11972
    /* p2c: checkmol.pas, line 9644:
11973
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11974
      /*$IFDEF debug */
11975
      //debugoutput ("too many neighbors - exiting");
11976
      /*$ENDIF */
18544 georgesk 11977
    return isfalse;
14179 bpr 11978
  }
6785 bpr 11979
  /* check if matchpath is not already filled up */
14179 bpr 11980
  if (matchpath_length (ndl_mp) == max_matchpath_length) {
11981
    /* p2c: checkmol.pas, line 9653:
11982
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11983
      /*$IFDEF debug */
11984
      //debugoutput ("matchpath too int - exiting");
11985
      /*$ENDIF */
18544 georgesk 11986
    return isfalse;
14179 bpr 11987
  }
6785 bpr 11988
  /* next, check which chain of the needle matches which chain of the haystack  */
14179 bpr 11989
  for (i = 0; i < ndl_n_nb; i++) {
18544 georgesk 11990
    emptyline = istrue;
14179 bpr 11991
    next_ndl_a = ndl_nb[i];
11992
    for (j = 0; j < n_nb; j++) {
11993
            next_hst_a = hst_nb[j];
11994
            ndl_mp[ndl_mp_len] = next_ndl_a;
11995
            hst_mp[hst_mp_len] = next_hst_a;
11996
            if (is_matching (ndl_mp, hst_mp)) {                 /* recursive function call */
6785 bpr 11997
              if (max_match_recursion_depth != 0
14179 bpr 11998
                          && ++recursion_depth > max_match_recursion_depth) {
6785 bpr 11999
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 12000
                      if (opt_verbose)
6785 bpr 12001
#endif
14179 bpr 12002
                        printf
6785 bpr 12003
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
14179 bpr 12004
                      max_match_recursion_depth);
12005
                      //n_rings = max_rings;
18544 georgesk 12006
                     return istrue;
14179 bpr 12007
                    }
18544 georgesk 12008
              mm[i][j] = istrue;
12009
              emptyline = isfalse;
6785 bpr 12010
            }
14179 bpr 12011
          }
12012
    /* if a needle substituent does not match any of the haystack substituents, */
12013
    /* stop any further work immediately */
12014
    if (emptyline)
18544 georgesk 12015
            return isfalse;
14179 bpr 12016
  }
6785 bpr 12017
  /* finally, check the content of the matrix */
12018
  res = matrix_OK (mm, ndl_n_nb, n_nb);
12019
  /* optional: chirality check */
14179 bpr 12020
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) && ndl_maybe_chiral (ndl_a)))
6785 bpr 12021
    return res;
12022
  /* first, we have to clean up the match matrix in order to remove */
12023
  /* "impossible" multiple matches (new in v0.3h) */
14179 bpr 12024
  for (i = 1; i <= 3; i++) {
12025
    for (j = 1; j <= max_neighbors; j++) {                      /* haystack dimension */
12026
            n_hits = 0;
12027
            l = 0;
12028
            for (k = 1; k <= max_neighbors; k++) {                      /* needle dimension */
12029
              if (mm[k - 1][j - 1]) {
12030
                      n_hits++;
12031
                      l = k;
12032
                    }
6785 bpr 12033
            }
14179 bpr 12034
            if (n_hits == 1) {                  /* a unique match ==> kick out any other match at this pos. */
12035
              for (m = 1; m <= max_neighbors; m++) {
12036
                      if (m != j)
18544 georgesk 12037
                        mm[l - 1][m - 1] = isfalse;
14179 bpr 12038
                    }
6785 bpr 12039
            }
14179 bpr 12040
          }
12041
  }
6785 bpr 12042
  /* end of match matrix clean-up */
14179 bpr 12043
  if (prev_ndl_a > 0) {
12044
    n_singlehits = 1;
12045
    ncp[1] = prev_ndl_a;
12046
    hcp[1] = prev_hst_a;
12047
  }
6785 bpr 12048
  else
12049
    n_singlehits = 0;
12050
  ncp[0] = ndl_a;
12051
  hcp[0] = hst_a;
12052
  i = 0;
12053
  l = 0;
14179 bpr 12054
  while (n_singlehits < 3 && i < 4) {
12055
    i++;
12056
    n_hits = 0;
12057
    for (k = 1; k <= n_nb; k++) {
12058
            if (mm[i - 1][k - 1]) {
6785 bpr 12059
              n_hits++;
12060
              l = k;
12061
            }
14179 bpr 12062
          }
12063
    if (n_hits == 1) {
12064
            n_singlehits++;
12065
            ncp[n_singlehits] = ndl_nb[i - 1];
12066
            hcp[n_singlehits] = hst_nb[l - 1];
12067
          }
12068
  }
6785 bpr 12069
  if (n_singlehits != 3)
12070
    return res;
14179 bpr 12071
  if (!chirality_OK (ncp, hcp)) {
12072
    /* p2c: checkmol.pas, line 9749:
12073
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12074
          /*$IFDEF debug */
12075
          //debugoutput ("chirality check failed");
12076
          /*$ENDIF */
18544 georgesk 12077
          res = isfalse;
14179 bpr 12078
  }
12079
  else {
6785 bpr 12080
/* p2c: checkmol.pas, line 9755:
12081
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12082
      /*$IFDEF debug */
12083
      //debugoutput ("chirality check OK");
12084
      /*$ENDIF */
14179 bpr 12085
  }
6785 bpr 12086
  return res;
14179 bpr 12087
  /* p2c: checkmol.pas, line 9762:
12088
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12089
    /*$IFDEF debug */
12090
    /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
12091
       debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
12092
    /*$ENDIF */
6785 bpr 12093
}
12094
 
14179 bpr 12095
static boolean quick_match ()
6785 bpr 12096
{
12097
  /* added in v0.2c */
12098
  int i;
18544 georgesk 12099
  boolean res = istrue;
14179 bpr 12100
  /* str3 ndl_atype;*/
6785 bpr 12101
  str2 ndl_el;                  /* v0.3l */
6788 kbelabas 12102
  int ndl_chg = 0;              /* v0.3l */
12103
  int ndl_rad = 0;              /* v0.3x */
12104
  int ndl_iso = 0;              /* v0.3x */
6785 bpr 12105
 
12106
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
12107
    /* v0.3f, v0.3m, v0.3o */
18544 georgesk 12108
    return isfalse;
6785 bpr 12109
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
14179 bpr 12110
        ndl_n_bonds > n_bonds) {                                /* just to be sure... */
12111
    /* p2c: checkmol.pas, line 9786:
12112
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12113
          /*$IFDEF debug */
12114
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
12115
          //debugoutput (" ==> quick_match failed");
12116
          /*$ENDIF */
18544 georgesk 12117
    return isfalse;
14179 bpr 12118
  }
6785 bpr 12119
 
14179 bpr 12120
  if (ndl_n_heavyatoms > 1) {
12121
    for (i = 0; i < ndl_n_atoms; i++) {
18544 georgesk 12122
            /*if atom^[i].atype <> ndl_atom^[i].atype then res := isfalse;    (* changed in */
14179 bpr 12123
            if (strcmp (atom[i].element, ndl_atom[i].element))  /* v0.2k */
18544 georgesk 12124
              return isfalse;
14179 bpr 12125
            //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
18544 georgesk 12126
            //res = isfalse;
6785 bpr 12127
 
14179 bpr 12128
            if (opt_chg) {
6785 bpr 12129
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
18544 georgesk 12130
                      return isfalse;
6785 bpr 12131
            }
14179 bpr 12132
      /*  else {
12133
            if (ndl_atom[i].formal_charge != 0 &&
12134
          atom[i].formal_charge != 0 &&
12135
          ndl_atom[i].formal_charge != atom[i].formal_charge)
18544 georgesk 12136
        return isfalse;
14179 bpr 12137
          } */
6785 bpr 12138
 
14179 bpr 12139
          /* v0.3x: isotopes must be the same */
12140
            if (opt_iso) {
6785 bpr 12141
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
18544 georgesk 12142
                      return isfalse;
6785 bpr 12143
            }
14179 bpr 12144
          /*  else {
12145
          if (ndl_atom[i].nucleon_number != 0 &&
12146
          atom[i].nucleon_number != 0 &&
12147
          ndl_atom[i].nucleon_number !=
12148
          atom[i].nucleon_number)
18544 georgesk 12149
        return isfalse;
14179 bpr 12150
        }*/
6785 bpr 12151
 
14179 bpr 12152
            /* v0.3x: radicals must be the same */
12153
            if (opt_rad) {
6785 bpr 12154
              if (ndl_atom[i].radical_type != atom[i].radical_type)
18544 georgesk 12155
                      return isfalse;
6785 bpr 12156
            }
14179 bpr 12157
      /*  else {
12158
         if (ndl_atom[i].radical_type != 0 &&
12159
             atom[i].radical_type != 0 &&
12160
             ndl_atom[i].radical_type != atom[i].radical_type)
18544 georgesk 12161
           return isfalse;
14179 bpr 12162
       }*/
6785 bpr 12163
 
12164
        }
14179 bpr 12165
  /* p2c: checkmol.pas, line 9798:
12166
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12167
      /*$IFDEF debug */
12168
      //if (res)
12169
      //debugoutput (" ==> quick_match: atoms OK");
12170
      //else
12171
      //  debugoutput (" ==> quick_match: atoms not OK");
12172
      /*$ENDIF */
14179 bpr 12173
    if (ndl_n_bonds > 0) {
12174
            for (i = 0; i < ndl_n_bonds; i++) {
6785 bpr 12175
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
14179 bpr 12176
                        || ndl_bond[i].btype != bond[i].btype)
18544 georgesk 12177
                      return isfalse;
6785 bpr 12178
            }
14179 bpr 12179
          }
12180
    /* p2c: checkmol.pas, line 9810:
12181
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12182
         /*$IFDEF debug */
12183
         //if (res)
12184
         //  debugoutput (" ==> quick_match: bonds OK");
12185
         //else
12186
         //  debugoutput (" ==> quick_match: bonds not OK");
12187
         /*$ENDIF */
12188
         /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
12189
   }
12190
  else {
12191
    /* first, find out the element and atom type of the only heavy atom       */
12192
    for (i = 0; i < ndl_n_atoms; i++) {
12193
            if (ndl_atom[i].heavy) {
6785 bpr 12194
              //strcpy (ndl_atype, ndl_atom[i].atype);
12195
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
12196
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
12197
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
12198
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
12199
            }
14179 bpr 12200
          }
12201
    for (i = 0; i < n_atoms; i++) {                     /* v0.3l, v0.3o */
12202
            if (                //      !strcmp (atom[i].atype, ndl_atype) &&
12203
                !strcmp (atom[i].element, ndl_el)) {
12204
              if (opt_chg || opt_strict) {
12205
                      if (ndl_chg != atom[i].formal_charge)
18544 georgesk 12206
                        return isfalse;
14179 bpr 12207
                    }
12208
              if (opt_iso || opt_strict) {
12209
                      if (ndl_iso != atom[i].nucleon_number)
18544 georgesk 12210
                        return isfalse;
14179 bpr 12211
                    }
6785 bpr 12212
 
14179 bpr 12213
              if (opt_rad || opt_strict) {
12214
                      if (ndl_rad != atom[i].radical_type)
18544 georgesk 12215
                        return isfalse;
14179 bpr 12216
                    }
18544 georgesk 12217
                    return istrue;
14179 bpr 12218
            }
12219
            else {
18544 georgesk 12220
              res=isfalse;
14179 bpr 12221
            }
12222
          }
12223
  }
12224
  /* p2c: checkmol.pas, line 9828:
12225
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12226
  /*$IFDEF debug */
12227
  //if (res)
12228
  //  debugoutput (" ==> quick_match succeeded");
12229
  //else
12230
  //  debugoutput (" ==> quick_match failed (2)");
12231
  /*$ENDIF */
12232
  return res;
12233
}
12234
 
14179 bpr 12235
static void perform_match ()
6785 bpr 12236
{
12237
  int i = 0;
12238
  int j;
12239
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
12240
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
12241
  boolean qm;                   /* v0.3l */
12242
  /* check for NoStruct (0 atoms);  v0.3l */
14179 bpr 12243
  if (n_atoms == 0 || ndl_n_atoms == 0) {
18544 georgesk 12244
      matchresult = isfalse;
14179 bpr 12245
  /* p2c: checkmol.pas, line 9849:
12246
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12247
      /*$IFDEF debug */
12248
      //debugoutput ("NoStruct encountered - aborted match routine");
12249
      /*$ENDIF */
14179 bpr 12250
    return;
12251
  }
6785 bpr 12252
  /* if we perform an exact match, needle and haystack must have */
12253
  /* the same number of atoms, bonds, and rings */
14179 bpr 12254
  if (opt_exact && opt_iso)     /* 0.3x */ {
12255
      if (n_heavyatoms != ndl_n_heavyatoms || n_heavybonds != ndl_n_heavybonds) {
18544 georgesk 12256
              matchresult = isfalse;
14179 bpr 12257
      /* p2c: checkmol.pas, line 9861:
12258
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12259
          /*$IFDEF debug */
12260
          //debugoutput ("different number of heavy atoms and/or bonds");
12261
          /*$ENDIF */
12262
          //return;
12263
          }
12264
  }
6785 bpr 12265
 
12266
  /* have a quick look if needle and haystack are identical molfiles */
12267
  qm = quick_match ();          /* v0.3l */
14179 bpr 12268
  if (qm) {
18544 georgesk 12269
    matchresult = istrue;
14179 bpr 12270
    clear_ndl_atom_tags ();     /* v0.3o */
12271
    return;
12272
  }
18544 georgesk 12273
  /* if we have only one heavy atom and quick_match fails, return "isfalse";  v0.3l */
14179 bpr 12274
  if (ndl_n_heavyatoms == 1) {
18544 georgesk 12275
    matchresult = isfalse;
14179 bpr 12276
    return;
12277
  }
12278
  /* p2c: checkmol.pas, line 9881:
12279
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12280
  /*$IFDEF debug */
12281
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
12282
  /*$ENDIF */
12283
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
12284
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
14179 bpr 12285
  /* p2c: checkmol.pas, line 9886:
12286
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12287
  /*$IFDEF debug */
12288
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
12289
  /*$ENDIF */
18544 georgesk 12290
  matchresult = isfalse;
14179 bpr 12291
  for (j = 0; j < max_matchpath_length; j++) {
12292
    ndl_matchpath[j] = 0;
12293
    hst_matchpath[j] = 0;
12294
  }
6785 bpr 12295
  ndl_matchpath[0] = ndl_ref_atom;
18544 georgesk 12296
  while (i < n_atoms && matchresult == isfalse) {
14179 bpr 12297
    i++;
12298
    n_nb = atom[i - 1].neighbor_count;
12299
    n_hc = hetatom_count (i);
12300
    if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc) {
12301
      /* p2c: checkmol.pas, line 9904:
12302
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12303
              /*$IFDEF debug */
12304
              /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
12305
              /*$ENDIF */
6785 bpr 12306
 
14179 bpr 12307
            recursion_depth = 0;
12308
            hst_matchpath[0] = i;
12309
            matchresult = is_matching (ndl_matchpath, hst_matchpath);
12310
      /* p2c: checkmol.pas, line 9909:
12311
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12312
          /*$IFDEF debug */
12313
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
12314
          /*$ENDIF */
12315
      if (matchresult)  /* v0.3o; mark this fragment as matched */
18544 georgesk 12316
        atom[i - 1].tag = istrue;
14179 bpr 12317
          }
12318
  }
6785 bpr 12319
}
12320
 
14179 bpr 12321
static void clear_rings ()
6785 bpr 12322
{
12323
  int i, FORLIM;
12324
  n_rings = 0;
12325
  memset (ring, 0, sizeof (ringlist));
14179 bpr 12326
  for (i = 0; i < max_rings; i++) {                             /* new in v0.3 */
12327
    ringprop[i].size = 0;
18544 georgesk 12328
    ringprop[i].arom = isfalse;
12329
    ringprop[i].envelope = isfalse;
14179 bpr 12330
  }
12331
  if (n_atoms > 0) {
12332
    FORLIM = n_atoms;
12333
    for (i = 0; i < FORLIM; i++)
12334
            atom[i].ring_count = 0;
12335
  }
12336
  if (n_bonds > 0) {
12337
    FORLIM = n_bonds;
12338
    for (i = 0; i < FORLIM; i++)
12339
            bond[i].ring_count = 0;
12340
  }
6785 bpr 12341
}
12342
 
17891 bpr 12343
static int ring_lastpos (int *s)
6785 bpr 12344
{
12345
  int i, rc;
12346
  int rlp = 0;
12347
  int FORLIM;
12348
  if (n_rings <= 0)
12349
    return rlp;
12350
  FORLIM = n_rings;
14179 bpr 12351
  for (i = 1; i <= FORLIM; i++) {
12352
    rc = ringcompare (s, ring[i - 1]);
12353
    if (rc_identical (rc))
12354
            rlp = i;
12355
  }
6785 bpr 12356
  return rlp;
12357
}
12358
 
14179 bpr 12359
static void remove_redundant_rings ()
6785 bpr 12360
{
12361
  int i, j, k, rlp;
12362
  ringpath_type tmp_path;
12363
  int FORLIM, FORLIM1;
12364
  if (n_rings < 2)
12365
    return;
12366
  FORLIM = n_rings;
14179 bpr 12367
  for (i = 1; i < FORLIM; i++) {
12368
    memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
12369
    rlp = ring_lastpos (tmp_path);
12370
    while (rlp > i) {
12371
           FORLIM1 = n_rings;
12372
      /* p2c: checkmol.pas, line 9970:
12373
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12374
          /*$IFDEF debug */
12375
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
12376
          /*$ENDIF */
14179 bpr 12377
            for (j = rlp; j < FORLIM1; j++) {
6785 bpr 12378
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
12379
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
12380
              ringprop[j - 1].arom = ringprop[j].arom;
12381
              ringprop[j - 1].envelope = ringprop[j].envelope;
12382
            }
14179 bpr 12383
            for (k = 0; k < max_ringsize; k++)
12384
              ring[n_rings - 1][k] = 0;
12385
            n_rings--;
12386
            rlp = ring_lastpos (tmp_path);
12387
          }
12388
  }
6785 bpr 12389
}
12390
 
14179 bpr 12391
static int count_aromatic_rings ()
6785 bpr 12392
{
12393
  int i;
12394
  int n = 0;
12395
  int FORLIM;
12396
  if (n_rings <= 0)
12397
    return n;
12398
  FORLIM = n_rings;
14179 bpr 12399
  for (i = 0; i < FORLIM; i++) {
12400
    if (ringprop[i].arom)
12401
            n++;
12402
  }
6785 bpr 12403
  return n;
12404
}
12405
 
14179 bpr 12406
static void chk_envelopes ()
6785 bpr 12407
{
12408
  /* new in v0.3d */
12409
  /* checks if a ring completely contains one or more other rings */
12410
  int a, i, j, k, l, pl, pli;
12411
  boolean found_atom, found_all_atoms, found_ring;
12412
  int FORLIM;
12413
  if (n_rings < 2)
12414
    return;
12415
  FORLIM = n_rings;
14179 bpr 12416
  for (i = 1; i < FORLIM; i++) {
18544 georgesk 12417
    found_ring = isfalse;
14179 bpr 12418
    j = 0;
12419
    pli = ringprop[i].size;     /* path_length(ring^[i]); */
18544 georgesk 12420
    while (j < i && found_ring == isfalse) {
14179 bpr 12421
            j++;
18544 georgesk 12422
            found_all_atoms = istrue;
14179 bpr 12423
            pl = ringprop[j - 1].size;  /* path_length(ring^[j]); */
12424
            for (k = 0; k < pl; k++) {
18544 georgesk 12425
              found_atom = isfalse;
6785 bpr 12426
              a = ring[j - 1][k];
14179 bpr 12427
              for (l = 0; l < pli; l++) {
12428
                      if (ring[i][l] == a)
18544 georgesk 12429
                        found_atom = istrue;
14179 bpr 12430
                    }
18544 georgesk 12431
              if (found_atom == isfalse)
12432
                      found_all_atoms = isfalse;
6785 bpr 12433
            }
14179 bpr 12434
            if (found_all_atoms)
18544 georgesk 12435
              found_ring = istrue;
14179 bpr 12436
          }
12437
    if (found_ring)
18544 georgesk 12438
            ringprop[i].envelope = istrue;
14179 bpr 12439
  }
6785 bpr 12440
}
12441
 
14179 bpr 12442
static void update_ringcount ()
6785 bpr 12443
{
12444
  int i, j, a1, a2, b, pl, FORLIM;
12445
  if (n_rings <= 0)
12446
    return;
12447
  chk_envelopes ();
12448
  FORLIM = n_rings;
14179 bpr 12449
  for (i = 0; i < FORLIM; i++) {
18544 georgesk 12450
      if (ringprop[i].envelope == isfalse) {
14179 bpr 12451
            pl = ringprop[i].size;      /* path_length(ring^[i]);  (* v0.3d */
12452
            a2 = ring[i][pl - 1];
12453
            for (j = 0; j < pl; j++) {
6785 bpr 12454
              a1 = ring[i][j];
12455
              atom[a1 - 1].ring_count++;
12456
              b = get_bond (a1, a2);
12457
              bond[b - 1].ring_count++;
12458
              a2 = a1;
12459
            }
14179 bpr 12460
          }
12461
  }
6785 bpr 12462
}
12463
 
14179 bpr 12464
static boolean normalize_ionic_bonds ()
6785 bpr 12465
{
12466
  /* v0.3k */
12467
  /* changed from a procedure into a function in v0.3m */
12468
  int i, a1, a2, fc1, fc2;
12469
  char bt;
18544 georgesk 12470
  boolean res = isfalse;                /* v0.3m */
6785 bpr 12471
  int FORLIM;
12472
  /* v0.3m */
12473
  if (n_bonds == 0)
18544 georgesk 12474
    return isfalse;
6785 bpr 12475
  FORLIM = n_bonds;
14179 bpr 12476
  for (i = 0; i < FORLIM; i++) {
12477
    a1 = bond[i].a1;
12478
    a2 = bond[i].a2;
12479
    bt = bond[i].btype;
12480
    fc1 = atom[a1 - 1].formal_charge;
12481
    fc2 = atom[a2 - 1].formal_charge;
12482
    if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D')) {
12483
            atom[a1 - 1].formal_charge = 0;
12484
            atom[a2 - 1].formal_charge = 0;
12485
            if (!strcmp (atom[a1 - 1].atype, "N3+"))    /* v0.3m */
12486
              strcpy (atom[a1 - 1].atype, "N3 ");
12487
            if (!strcmp (atom[a2 - 1].atype, "N3+"))    /* v0.3m */
12488
              strcpy (atom[a2 - 1].atype, "N3 ");
12489
            if (bt == 'D')
12490
              bond[i].btype = 'T';
12491
            if (bt == 'S')
12492
              bond[i].btype = 'D';
18544 georgesk 12493
            res = istrue;               /* v0.3m */
14179 bpr 12494
          }
12495
  }
18544 georgesk 12496
  return res;                   /* v0.3m (return istrue if any change was made */
6785 bpr 12497
}
12498
 
12499
#if 0
14179 bpr 12500
static void chk_wildcard_rings ()               // new in v0.3p
6785 bpr 12501
// checks if there are any wildcard atom types or bond types
12502
// in a ring of the needle; if yes ==> set the q_arom flag in the
14179 bpr 12503
// atom and bond record of all ring members in order to perform the
6785 bpr 12504
// match a bit more generously
12505
{
12506
 
12507
  int i, j, rs;
12508
  int a1, a2, b;
12509
  boolean wcr;
12510
  str3 at;
12511
  char bt;
12512
 
18544 georgesk 12513
  if (ndl_querymol == isfalse)
6785 bpr 12514
    return;
12515
  if (ndl_n_rings == 0)
12516
    return;
12517
  // now look for any not-yet-aromatic rings which contain a wildcard
14179 bpr 12518
  for (i = 0; i < ndl_n_rings; i++) {
18544 georgesk 12519
    wcr = isfalse;
12520
    if (ndl_ringprop[i].arom == isfalse) {
14179 bpr 12521
            rs = ndl_ringprop[i].size;
12522
            a2 = ndl_ring[i][rs];
12523
            for (j = 0; j < rs; j++) {
6785 bpr 12524
              a1 = ndl_ring[i][j];
12525
              b = get_ndl_bond (a1, a2);
12526
              strcpy (at, ndl_atom[a1].atype);
12527
              bt = ndl_bond[b].btype;
12528
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
18544 georgesk 12529
                      wcr = istrue;
6785 bpr 12530
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
18544 georgesk 12531
                      wcr = istrue;
6785 bpr 12532
              a2 = a1;
12533
            }
14179 bpr 12534
            if (wcr) {                  // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
6785 bpr 12535
              // {$IFDEF debug}
12536
              // debugoutput('wildcard ring found');
12537
              // {$ENDIF}
12538
              a2 = ndl_ring[i][rs];
14179 bpr 12539
              for (j = 0; j < rs; j++) {
12540
                      a1 = ndl_ring[i][j];
12541
                      b = get_ndl_bond (a1, a2);
12542
                      strcpy (at, ndl_atom[a1].atype);
12543
                      bt = ndl_bond[b].btype;
18544 georgesk 12544
                      ndl_atom[a1].q_arom = istrue;
12545
                      ndl_bond[b].q_arom = istrue;
14179 bpr 12546
                      a2 = a1;
12547
                    }
6785 bpr 12548
            }
14179 bpr 12549
          }
12550
  }
6785 bpr 12551
  // and now undo this flagging for all rings which contain no wildcard
14179 bpr 12552
  for (i = 0; i < ndl_n_rings; i++) {
18544 georgesk 12553
    wcr = isfalse;
14179 bpr 12554
    rs = ndl_ringprop[i].size;
12555
    a2 = ndl_ring[i][rs];
12556
    for (j = 0; j < rs; j++) {
12557
            a1 = ndl_ring[i][j];
12558
            b = get_ndl_bond (a1, a2);
12559
            strcpy (at, ndl_atom[a1].atype);
12560
            bt = ndl_bond[b].btype;
12561
            if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
18544 georgesk 12562
              wcr = istrue;
14179 bpr 12563
            if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
18544 georgesk 12564
              wcr = istrue;
14179 bpr 12565
            a2 = a1;
12566
          }
12567
    if (!wcr) {                 // if yes, unflag all atoms and bonds in this ring
12568
            a2 = ndl_ring[i][rs];
12569
            for (j = 0; j < rs; j++) {
6785 bpr 12570
              a1 = ndl_ring[i][j];
12571
              b = get_ndl_bond (a1, a2);
12572
              strcpy (at, ndl_atom[a1].atype);
12573
              bt = ndl_bond[b].btype;
18544 georgesk 12574
              ndl_atom[a1].q_arom = isfalse;
12575
              ndl_bond[b].q_arom = isfalse;
6785 bpr 12576
              a2 = a1;
12577
            }
14179 bpr 12578
          }
12579
  }
6785 bpr 12580
  // some further refinement would be necessary here in order to unflag everything
12581
  // which contains a wildcard but which definitely cannot be aromatic
12582
}
12583
#endif
12584
 
12585
#ifndef MAKE_SHARED_LIBRARY
12586
 
14179 bpr 12587
int main (int argc, char *argv[])
6785 bpr 12588
{                               /* main routine */
12589
  char STR1[256], STR6[256];
12590
  int FORLIM;
12591
  /* progmode = pmMatchMol */
12592
  rfile = NULL;
12593
  strcpy (progname, argv[0]);
12594
  strncpy (STR1, progname, 253);
12595
  if (strstr (STR1, "matchmol") != NULL)
12596
    progmode = pmMatchMol;
14179 bpr 12597
  else {
12598
    strncpy (STR6, progname, 253);
12599
    if (strstr (STR6, "checkmol") == NULL) {
12600
            printf ("THOU SHALLST NOT RENAME ME!\n");
12601
            exit (9);
12602
          }
12603
    progmode = pmCheckMol;
12604
  }
12605
  if (argc == 1) {
12606
    show_usage ();
12607
    exit (1);
12608
  }
6785 bpr 12609
  init_globals ();
12610
  init_molstat (&molstat);
12611
  parse_args (argc, argv);
12612
  if (ringsearch_mode == rs_sar)
12613
    max_vringsize = max_ringsize;
12614
  else
12615
    max_vringsize = ssr_vringsize;
12616
  /* v0.3n (was: 10) */
12617
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14179 bpr 12618
  if (progmode == pmMatchMol) {
12619
    left_trim (ndl_molfilename);
12620
    left_trim (molfilename);
12621
    if ((*molfilename == '\0' || *ndl_molfilename == '\0' || argc < 3) && !opt_stdin) {
6785 bpr 12622
            show_usage ();
14179 bpr 12623
            exit (2);           /* new in v0.2k */
12624
          }
12625
    if (!(file_exists (ndl_molfilename)) && !opt_stdin) {
12626
      /*not  fileexists(ndl_molfilename) REPLACE!!! */
12627
                  printf("2");
12628
                  /* p2c: checkmol.pas, line 10128:
12629
                  * Warning: Expected an expression, found a ')' [227] */
12630
            if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
12631
              show_usage ();
12632
            else
12633
              printf ("file %s not found!\n", ndl_molfilename);
12634
            /* new in v0.2k */
12635
            exit (2);
12636
          }
12637
  }
6785 bpr 12638
 
14179 bpr 12639
  if (!(file_exists (molfilename)) && !opt_stdin) {                             /*not  fileexists(ndl_molfilename) REPLACE!!! */
12640
    /* p2c: checkmol.pas, line 10128:
12641
    * Warning: Expected an expression, found a ')' [227] */
6785 bpr 12642
 
14179 bpr 12643
    if (strlen (molfilename) > 1 && molfilename[0] == '-')
12644
            show_usage ();
12645
    else
12646
            printf ("file %s not found!\n", molfilename);
6785 bpr 12647
      /* new in v0.2k */
12648
      exit (2);
14179 bpr 12649
  }
6785 bpr 12650
 
12651
  /* read the first molecule and process it; if we are in "matchmol" mode, */
12652
  /* this is the "needle" */
12653
  if (progmode == pmMatchMol)
12654
    readinputfile (ndl_molfilename);
12655
  else
12656
    readinputfile (molfilename);
12657
  li = 1;                       /* initialize line pointer for input buffer */
12658
  get_filetype (filetype, ndl_molfilename);
14179 bpr 12659
  if (!strcmp (filetype, "unknown")) {
12660
    printf ("unknown query file format!\n");
12661
    if (!opt_verbose)
12662
            exit (3);
12663
    printf ("===========================================\n");
12664
    FORLIM = molbufindex;
12665
    for (i = 1; i <= FORLIM; i++)
12666
            puts (molbuf[i - 1]);
12667
    exit (3);
12668
  }
18544 georgesk 12669
  mol_OK = istrue;              /* added in v0.2i */
6785 bpr 12670
  if (!strcmp (filetype, "alchemy"))
12671
    read_molfile (ndl_molfilename);
12672
  if (!strcmp (filetype, "sybyl"))
12673
    read_mol2file (ndl_molfilename);
12674
  if (!strcmp (filetype, "mdl"))
12675
    read_MDLmolfile (ndl_molfilename);
12676
  count_neighbors ();
14179 bpr 12677
  if (!mol_OK || n_atoms < 1) {                                 /* v0.3g; check if this is a valid query structure */
12678
    printf ("invalid molecule\n");
12679
    exit (3);
12680
  }
12681
  if (!found_arominfo || progmode == pmCheckMol) {                              /* added in v0.2b/0.2c */
12682
  /* p2c: checkmol.pas, line 10172:
12683
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12684
      /*$IFDEF debug
6785 bpr 12685
         if (!found_arominfo)
12686
         debugoutput
12687
         ("no aromaticity information found - checking myself...");
12688
         else
12689
         debugoutput ("performing full aromaticity check");
14179 bpr 12690
         // new in v0.3d
6785 bpr 12691
      $ENDIF */
14179 bpr 12692
    chk_ringbonds ();
12693
    if (ringsearch_mode == rs_ssr)
12694
            remove_redundant_rings ();
12695
    if (n_rings >= max_rings) {
12696
            if (opt_verbose)
12697
              printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12698
                 max_rings);
12699
            ringsearch_mode = rs_ssr;
18544 georgesk 12700
            auto_ssr = istrue;  /* v0.3n */
14179 bpr 12701
            clear_rings ();
12702
            max_vringsize = ssr_vringsize;      /* v0.3n (was: 10) */
12703
            chk_ringbonds ();
12704
            remove_redundant_rings ();
12705
          }
12706
    update_ringcount ();
12707
    /* new in v0.3k: if output is a molfile, leave the original */
12708
    /* representation of N-oxides, S-oxides, nitro groups, etc. */
12709
    /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
12710
    if (!opt_xmdlout)           /* v0.3k */
12711
            normalize_ionic_bonds ();
12712
    update_atypes ();
12713
    update_Htotal ();           /* added in v0.3 */
12714
    chk_arom ();
12715
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
12716
            do {
6785 bpr 12717
              prev_n_ar = count_aromatic_rings ();
12718
              chk_arom ();
12719
              n_ar = count_aromatic_rings ();
12720
            }
14179 bpr 12721
            while (prev_n_ar - n_ar != 0);
12722
          }
12723
  }
12724
  else {                                /* v0.3k */
12725
    /* p2c: checkmol.pas, line 10206:
12726
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12727
      /*$IFDEF debug
6785 bpr 12728
         debugoutput ("found aromaticity information in input file");
12729
         $ENDIF */
14179 bpr 12730
    if (!opt_xmdlout)
12731
            normalize_ionic_bonds ();
12732
    update_atypes ();           /* added in v0.2f */
12733
    update_Htotal ();           /* end v0.2b snippet */
12734
  }
12735
  if (progmode == pmCheckMol) {
12736
    if (opt_verbose)
12737
            write_mol ();
12738
    get_molstat ();
12739
    if (opt_molstat) {
12740
            if (opt_molstat_X)
12741
              write_molstat_X ();
12742
            else
12743
              write_molstat ();
12744
          }
12745
    else {
12746
            if (found_querymol) {
12747
                printf ("input structure contains query atom or query bond!\n");
12748
                exit (1);
6785 bpr 12749
            }
14179 bpr 12750
            chk_functionalgroups ();
12751
            if (opt_none)
18544 georgesk 12752
              opt_text = istrue;
14179 bpr 12753
            if (opt_text)
12754
              write_fg_text ();
12755
            if (opt_text_de)
12756
              write_fg_text_de ();
12757
            if (opt_code)
12758
              write_fg_code ();
12759
            if (opt_bin)
12760
              write_fg_binary ();
12761
            if (opt_bitstring)
12762
              write_fg_bitstring ();
12763
            if (opt_xmdlout)
12764
              write_MDLmolfile ();
12765
          }
6785 bpr 12766
      /*if opt_verbose   then write_mol; */
14179 bpr 12767
    zap_molecule ();
12768
  }
12769
  else {
6785 bpr 12770
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14179 bpr 12771
    if (!opt_fp) {                      /* v0.3m */
12772
            copy_mol_to_needle ();
12773
            //chk_wildcard_rings (); /* 0.3p */
12774
            set_ndl_atom_tags ();       /* v0.3o */
12775
            if (opt_verbose)
12776
              write_needle_mol ();
12777
            if (rs_strict)      /* v0.3j */
12778
              ndl_ref_atom = find_ndl_ref_atom_cv ();
12779
            else
12780
              ndl_ref_atom = find_ndl_ref_atom ();
12781
          }
12782
    else {
12783
            copy_mol_to_tmp (); /* v0.3m */
12784
            if (opt_verbose)
12785
              printf ("1st molecule stored in buffer: %s\n", tmp_molname);
12786
          }
12787
    /* next, read the "haystack" file and process it */
12788
    li = 1;
12789
    mol_count = 0;
12790
    fpdecimal = 0;              /* v0.3m */
12791
    fpindex = 0;                /* v0.3m */
12792
    do {
12793
            /* new in v0.3i: reset ringsearch_mode to its initial value */
12794
            /* for each new molecule */
12795
            ringsearch_mode = opt_rs;
12796
            if (ringsearch_mode == rs_sar)
12797
              max_vringsize = max_ringsize;
12798
            else
12799
              max_vringsize = ssr_vringsize;
12800
            /* v0.3n (was: 10) */
12801
            readinputfile (molfilename);
12802
            li = 1;
12803
            get_filetype (filetype, molfilename);
12804
            if (strcmp (filetype, "unknown")) {
18544 georgesk 12805
              found_arominfo = isfalse; /* added in v0.2b */
12806
              mol_OK = istrue;  /* added in v0.2i */
6785 bpr 12807
              if (!strcmp (filetype, "alchemy"))
14179 bpr 12808
                      read_molfile (molfilename);
6785 bpr 12809
              if (!strcmp (filetype, "sybyl"))
14179 bpr 12810
                      read_mol2file (molfilename);
6785 bpr 12811
              if (!strcmp (filetype, "mdl"))
14179 bpr 12812
                      read_MDLmolfile (molfilename);
6785 bpr 12813
              mol_count++;
12814
              fpindex++;
12815
              count_neighbors ();
12816
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14179 bpr 12817
              if (!mol_OK || (n_atoms < 1 && !(opt_fp && fpformat == fpf_decimal)))
12818
                      printf ("%i:F\n", mol_count);
12819
              else {
12820
                      if (opt_exact && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
12821
                                || n_Ntot != ndl_n_Ntot)) {             /* new in v0.3g */
12822
                        if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
12823
                                printf ("%i:F\n", mol_count);
12824
                      }
12825
                      else {
12826
                        if (!found_arominfo || (opt_strict && tmfmismatch)) {   /* added in v0.3m */
12827
              /* p2c: checkmol.pas, line 10294:
12828
               * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12829
                                  /*$IFDEF debug
12830
                              debugoutput
12831
                              ("no aromaticity information found (or tweak mismatch) - checking myself...");
12832
                              *$ENDIF */
6785 bpr 12833
                              chk_ringbonds ();
14179 bpr 12834
                              if (ringsearch_mode == rs_ssr)
12835
                                remove_redundant_rings ();
12836
                               if (n_rings == max_rings) {
12837
                                if (opt_verbose)
12838
                                        printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12839
                                         max_rings);
12840
                                ringsearch_mode = rs_ssr;
12841
                                clear_rings ();
12842
                                max_vringsize = ssr_vringsize;  /* v0.3n (was: 10) */
12843
                                chk_ringbonds ();
12844
                                remove_redundant_rings ();
12845
                              }
12846
                              update_ringcount ();
12847
                              update_atypes ();
12848
                              update_Htotal (); /* added in v0.3 */
12849
                              chk_arom ();
12850
                              if (ringsearch_mode == rs_ssr) {  /* new in v0.3 */
12851
                                do {
12852
                                        prev_n_ar = count_aromatic_rings ();
12853
                                        chk_arom ();
12854
                                        n_ar = count_aromatic_rings ();
12855
                                      }
12856
                                while (prev_n_ar - n_ar != 0);
12857
                              }
6785 bpr 12858
                            }
14179 bpr 12859
                      else {    /* added in v0.2f */
12860
            /* p2c: checkmol.pas, line 10322:
12861
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12862
                            /*$IFDEF debug
6785 bpr 12863
                             debugoutput
12864
                             ("found aromaticity information in input file");
12865
                             $ENDIF */
14179 bpr 12866
                              if (opt_strict)
12867
                                update_atypes ();
12868
                              update_Htotal ();
12869
                            }
6785 bpr 12870
                      init_molstat (&ndl_molstat);
12871
                      if (normalize_ionic_bonds ())
14179 bpr 12872
                              /* new in v0.3k, modified in v0.3m */
12873
                              update_atypes ();
6785 bpr 12874
                      if (opt_verbose && !opt_fp)
14179 bpr 12875
                              write_mol ();
6785 bpr 12876
                      /* if in "fingerprint mode", exchange needle and haystack */
14179 bpr 12877
                      if (opt_fp) {     /* v0.3m */
12878
                              zap_needle ();
12879
                              copy_mol_to_needle ();
12880
                              //chk_wildcard_rings (); /* 0.3p */
12881
                              zap_molecule ();
12882
                              copy_tmp_to_mol ();
12883
                              if (opt_verbose)
12884
                                write_needle_mol ();
12885
                              if (rs_strict)    /* v0.3j */
12886
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
12887
                              else
12888
                                ndl_ref_atom = find_ndl_ref_atom ();
12889
                              if (opt_verbose)
12890
                                write_mol ();
12891
                            }   /* v0.3m */
6785 bpr 12892
                      /* now that we have both molecules, perform the comparison */
12893
                      /* v0.3o: takes care of disconnected fragment... */
12894
                      clear_atom_tags ();
12895
                      set_ndl_atom_tags ();
18544 georgesk 12896
                      matchsummary = istrue;
6785 bpr 12897
                      perform_match ();
12898
                      matchsummary = matchresult;
18544 georgesk 12899
                      if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == istrue) {
14179 bpr 12900
                              do {
12901
                                if (rs_strict)
12902
                                        ndl_ref_atom = find_ndl_ref_atom_cv ();
12903
                                else
12904
                                        ndl_ref_atom = find_ndl_ref_atom ();
12905
                                perform_match ();
18544 georgesk 12906
                                if (matchresult == isfalse)
12907
                                        matchsummary = isfalse;
14179 bpr 12908
                              }
18544 georgesk 12909
                              while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != isfalse);
6785 bpr 12910
                            }
12911
                      /* end of disconnected-fragment matching (v0.3o) */
18544 georgesk 12912
                      if (matchsummary == istrue) {     /* v0.3o */
14179 bpr 12913
                              if (opt_molout) {
12914
                                FORLIM = molbufindex;
12915
                                for (i = 1; i <= FORLIM; i++)
12916
                                        puts (molbuf[i - 1]);
12917
                              }
12918
                              else {
12919
                                if (!opt_fp)    /* inttostr(mol_count) REPLACE!!!, */
12920
                                        printf ("%i:T\n", mol_count);
12921
                                else {
12922
                                        if (ndl_n_heavyatoms == n_heavyatoms &&
12923
                                            ndl_n_heavybonds == n_heavybonds)
18544 georgesk 12924
                                          fp_exacthit = istrue;
14179 bpr 12925
                                        else
18544 georgesk 12926
                                          fp_exacthit = isfalse;
14179 bpr 12927
                                        if (fp_exacthit)
18544 georgesk 12928
                                          fp_exactblock = istrue;
14179 bpr 12929
                                        if (fpformat == fpf_boolean) {
12930
                                          if (fp_exacthit)      /* inttostr(mol_count), REPACE!!! */
12931
                                                  printf ("%i:TX\n", mol_count);
12932
                                          else
12933
                                                  printf ("%i:T\n", mol_count);
12934
                                        }
12935
                                        /* inttostr(mol_count), REPLACE!!! */
12936
                                        if (fpformat == fpf_decimal) {
12937
                                          fpincrement = 1;
12938
                                          FORLIM = fpindex;
12939
                                          for (i = 1; i <= FORLIM; i++)
12940
                                                  fpincrement <<= 1;
12941
                                          fpdecimal += fpincrement;
12942
                                        }
12943
                                      }
12944
                              }
6785 bpr 12945
                            }
14179 bpr 12946
                      else {
12947
                              if (!(opt_molout || (opt_fp && fpformat == fpf_decimal)))
12948
                                /* inttostr(mol_count), REPLACE!!! */
12949
                               printf ("%i:F\n", mol_count);
6785 bpr 12950
                            }
14179 bpr 12951
                      if (opt_fp && fpformat == fpf_decimal && fpindex == fp_blocksize) {
12952
                              if (fp_exactblock)
12953
                                fpdecimal++;
12954
                              printf ("%lld\n", fpdecimal);
12955
                              fpindex = 0;
12956
                              fpdecimal = 0;
18544 georgesk 12957
                              fp_exactblock = isfalse;
14179 bpr 12958
                            }
6785 bpr 12959
                      zap_molecule ();
12960
                      molbufindex = 0;
12961
                    }
14179 bpr 12962
                  }
12963
          }
12964
          else {
12965
            /* v0.3l */
12966
            /* mol_OK */
12967
            printf ("%i:unknown file format\n", mol_count);
12968
          }
6785 bpr 12969
        }
18544 georgesk 12970
  while (mol_in_queue != isfalse);
14179 bpr 12971
    /* if filetype <> 'unknown' */
12972
    if (opt_fp && fpformat == fpf_decimal && fpindex > 0) {
12973
            if (fp_exactblock)
12974
              fpdecimal++;
12975
            printf ("%lld\n", fpdecimal);
12976
          }
12977
    zap_needle ();
12978
    if (rfile_is_open){                 /* new in v0.2g */
12979
            if (rfile != NULL)
12980
              fclose (rfile);
12981
            rfile = NULL;
12982
          }
12983
  }
6785 bpr 12984
  if (rfile != NULL)
12985
    fclose (rfile);
12986
  exit (0);
12987
}
12988
 
12989
#else
12990
 
17891 bpr 12991
static void init_globals_dll ( )
6785 bpr 12992
{
12993
 
12994
//printf("init_globals_dll\n");
12995
 
12996
  int i;
18544 georgesk 12997
  opt_verbose = isfalse;
12998
  opt_debug = isfalse;
12999
  opt_stdin = isfalse;
13000
  opt_text = isfalse;
13001
  opt_code = isfalse;
13002
  opt_bin = isfalse;
13003
  opt_bitstring = isfalse;
13004
  opt_molout = isfalse;
13005
  opt_molstat = isfalse;
13006
  opt_molstat_X = isfalse;
13007
  opt_xmdlout = isfalse;
13008
  opt_fp = isfalse;             /* new in v0.3m */
13009
  /*cm_mdlmolfile   := isfalse; */
13010
  found_arominfo = isfalse;
13011
  found_querymol = isfalse;
13012
  ndl_querymol = isfalse;
6785 bpr 13013
  opt_rs = rs_sar;              /* v0.3i */
13014
  ringsearch_mode = opt_rs;
18544 georgesk 13015
  rfile_is_open = isfalse;      /* new in v0.2g */
13016
  ez_flag = isfalse;            /* new in v0.3f */
13017
  chir_flag = isfalse;          /* new in v0.3f */
6785 bpr 13018
  n_Ctot = 0;
13019
  n_Otot = 0;
13020
  n_Ntot = 0;                   /* new in v0.3g */
13021
  //for (i = 0; i < max_fg; i++)
18544 georgesk 13022
  //  fg[i] = isfalse;
6785 bpr 13023
  memset (fg, 0, sizeof (fglist));
13024
 
14179 bpr 13025
  if (!yet_initialized) {
13026
    molbuf = (void *) safe_malloc (sizeof (molbuftype));
18544 georgesk 13027
    opt_exact = isfalse;
13028
    opt_strict = isfalse;       /* new in v0.2f */
13029
    opt_metalrings = isfalse;   /* new in v0.3 */
13030
    opt_geom = isfalse;         /* new in v0.3d */
13031
    opt_chiral = isfalse;       /* new in v0.3f */
13032
    opt_iso = isfalse;          /* new in v0.3x */
13033
    opt_chg = isfalse;          /* new in v0.3x */
13034
    opt_rad = isfalse;          /* new in v0.3x */
13035
    ez_search = isfalse;        /* new in v0.3d */
13036
    rs_search = isfalse;        /* new in v0.3f */
13037
    rs_strict = isfalse;        /* new in v0.3j */
14179 bpr 13038
    ndl_n_Ctot = 0;
13039
    ndl_n_Otot = 0;
13040
    ndl_n_Ntot = 0;             /* new in v0.3g */
18544 georgesk 13041
    yet_initialized = istrue;
14179 bpr 13042
  }
6785 bpr 13043
 
18544 georgesk 13044
  ether_generic = isfalse;      /* v0.3j */
13045
  amine_generic = isfalse;      /* v0.3j */
13046
  hydroxy_generic = isfalse;    /* v0.3j */
6785 bpr 13047
  fpformat = fpf_decimal;       /* v0.3m */
13048
  fpindex = 0;                  /* v0.3m */
18544 georgesk 13049
  fp_exacthit = isfalse;                /* v0.3m */
13050
  fp_exactblock = isfalse;      /* v0.3m */
6785 bpr 13051
  tmfcode = 0;                  /* v0.3m */
18544 georgesk 13052
  tmfmismatch = isfalse;                /* v0.3m */
13053
  auto_ssr = isfalse;
6785 bpr 13054
  recursion_depth = 0;
13055
}
13056
 
17891 bpr 13057
static void mm_init_mol ( )
6785 bpr 13058
{
13059
//printf("mm_init_mol\n");
13060
  init_globals_dll ();
13061
  init_molstat (&molstat);
14179 bpr 13062
  if (opt_rs_dll == RPA_DEFAULT) {
13063
    ringsearch_mode = opt_rs;
13064
    //printf("DEFAULT: %i\n",ringsearch_mode);
13065
  }
13066
  else {
13067
    ringsearch_mode = opt_rs_dll;
13068
  }
6785 bpr 13069
  //printf("RPA: %i\n",ringsearch_mode);
13070
 
14179 bpr 13071
  if (ringsearch_mode == rs_sar) {
6785 bpr 13072
      max_vringsize = max_ringsize;
14179 bpr 13073
  }
13074
  else {
6785 bpr 13075
      max_vringsize = ssr_vringsize;
14179 bpr 13076
  }
6785 bpr 13077
  zap_molecule ();
13078
  molbufindex = 0;
13079
  mol_count = 0;
13080
//printf("mm_init_mol\n");
13081
}
13082
 
14179 bpr 13083
static void mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
6785 bpr 13084
{
13085
//printf("mm_elab_mol\n");
13086
 
13087
  li = 1;                       // initialize line pointer for input buffer
13088
  get_filetype (filetype, ndl_molfilename);
14179 bpr 13089
  if (strcmp (filetype, "unknown") == 0) {
13090
    //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
13091
    exit (3);
13092
  }
6785 bpr 13093
 
18544 georgesk 13094
  if (checkmol_mode == istrue)
6785 bpr 13095
    progmode = pmCheckMol;
13096
  else
13097
    progmode = pmMatchMol;
13098
  if (strcmp (filetype, "alchemy") == 0)
13099
    read_molfile (ndl_molfilename);
13100
  if (strcmp (filetype, "sybyl") == 0)
13101
    read_mol2file (ndl_molfilename);
13102
  if (strcmp (filetype, "mdl") == 0)
13103
    read_MDLmolfile (ndl_molfilename);
14179 bpr 13104
  if (checkmol_mode) {
13105
    if (found_querymol) {
13106
            printf ("Warning: Input structure contains query atom or query bond.\n");
13107
          }
13108
  }
6785 bpr 13109
 
13110
  count_neighbors ();
14179 bpr 13111
  if (!found_arominfo || checkmol_mode || opt_strict) {
13112
    //printf("No arom found or checkmol mode\n");
13113
    chk_ringbonds ();
13114
    if (ringsearch_mode == rs_ssr)
13115
            remove_redundant_rings ();
13116
    if (n_rings >= max_rings) {
13117
            printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
13118
               max_rings);
13119
            ringsearch_mode = rs_ssr;
18544 georgesk 13120
            auto_ssr = istrue;
14179 bpr 13121
            clear_rings ();
13122
            max_vringsize = ssr_vringsize;
13123
            chk_ringbonds ();
13124
            remove_redundant_rings ();
13125
          }
6785 bpr 13126
 
14179 bpr 13127
    update_ringcount ();
13128
    if (normalize_ionic_bnds)   /* v0.3k */
13129
            normalize_ionic_bonds ();
13130
    update_atypes ();
13131
    update_Htotal ();
13132
    chk_arom ();
13133
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
13134
            do {
6785 bpr 13135
              prev_n_ar = count_aromatic_rings ();
13136
              chk_arom ();
13137
              n_ar = count_aromatic_rings ();
13138
            }
14179 bpr 13139
            while (prev_n_ar - n_ar != 0);
13140
          }
13141
  }
13142
  else {
13143
    if (normalize_ionic_bnds)   /* v0.3k  */
13144
            normalize_ionic_bonds ();
13145
    //if (opt_strict)
13146
    update_atypes ();
13147
    update_Htotal ();
13148
  }
13149
  //printf("mm_elab_mol\n");
6785 bpr 13150
}
13151
 
17891 bpr 13152
DLLEXPORT void mm_set_current_mol_as_query ()
6785 bpr 13153
{
14179 bpr 13154
  //printf("mm_set_current_mol_as_query\n");
6785 bpr 13155
  zap_needle ();
14179 bpr 13156
  //mm_ElabMol;
6785 bpr 13157
  copy_mol_to_needle ();
13158
  //chk_wildcard_rings (); /* 0.3p */
13159
  set_ndl_atom_tags ();         /* v0.3o */
13160
  if (opt_geom)                 /* v0.3d */
18544 georgesk 13161
    ez_search = istrue;
6785 bpr 13162
  else if (!ez_flag && ez_search)
18544 georgesk 13163
    ez_search = isfalse;                //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14179 bpr 13164
  if (opt_chiral) {                             /* v0.3f */
18544 georgesk 13165
      rs_search = istrue;
6785 bpr 13166
      //printf("%i\n",rs_search);
14179 bpr 13167
  }
13168
  else
13169
    if (!chir_flag && rs_search) {
18544 georgesk 13170
      rs_search = isfalse;      //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
6785 bpr 13171
      //printf("%i\n",rs_search);
13172
    }
13173
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
18544 georgesk 13174
    rs_strict = istrue;
6785 bpr 13175
  else
18544 georgesk 13176
    rs_strict = isfalse;
14179 bpr 13177
    /* if (rs_strict)              // v0.3j
13178
       ndl_ref_atom = find_ndl_ref_atom_cv ();
13179
       //ndl_ref_atom = find_ndl_ref_atom ();
13180
       else
13181
       ndl_ref_atom = find_ndl_ref_atom (); */
6785 bpr 13182
 
13183
  molbufindex = 0;
13184
  mol_count = 0;
14179 bpr 13185
  /*printf("mm_set_current_mol_as_query\n");*/
6785 bpr 13186
}
13187
 
17891 bpr 13188
DLLEXPORT int mm_get_rings ()
6785 bpr 13189
{
13190
  return n_rings;
13191
}
13192
 
14179 bpr 13193
DLLEXPORT void xm_version (char *buffer)
6785 bpr 13194
{
13195
  buffer[0] = '\0';
13196
  strncpy (buffer, version, 255);
13197
}
13198
 
14179 bpr 13199
DLLEXPORT int mm_get_atom_ring (int atom_number)
6785 bpr 13200
{
13201
 
13202
  int i, j, a1, pl;
13203
  int ret = 0;
13204
  a1 = atom[atom_number].ring_count;
14179 bpr 13205
  if (n_rings > 0) {
13206
    for (i = 1; i < n_rings; i++) {
13207
            pl = path_length (ring[i]);
13208
      //          a2 := ring^[i,pl];
13209
            for (j = 1; j < pl; j++) {
6785 bpr 13210
              a1 = ring[i][j];
13211
              if (atom_number == a1)
14179 bpr 13212
                      ret = i;
13213
          //
13214
          //              inc(atom^[a1].ring_count);
13215
          //              b := get_bond(a1,a2);
13216
          //              inc(bond^[b].ring_count);
13217
          //              a2 := a1;
6785 bpr 13218
            }
14179 bpr 13219
          }
13220
  }
6785 bpr 13221
  return ret;
13222
}
13223
 
14179 bpr 13224
static void mm_read_input_line (char *st)
6785 bpr 13225
{
13226
//printf("mm_read_input_line_in\n");
13227
//var
13228
//yyy:pchar;
13229
 
18544 georgesk 13230
  mol_in_queue = isfalse;
14179 bpr 13231
  if (molbufindex < (max_atoms + max_bonds + slack)) {
6785 bpr 13232
 
14179 bpr 13233
    //yyy:=Pchar(IntToStr(molbufindex));
13234
    //messagebox (0,yyy,'',0);
13235
    //printf("%i\n",molbufindex);
13236
    //printf("B:%s\n",st);
13237
          strcpy (molbuf[molbufindex++], st);
13238
    //printf("%x %x\n",&molbuf,molbuf);
13239
    //printf("%s\n",molbuf[molbufindex-1]);
13240
          //  molbufindex++;
13241
  }
13242
  else {
13243
    //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
13244
    printf ("Not enough memory for molfile! %i\n", molbufindex);
13245
    exit (1);
13246
  }
6785 bpr 13247
//printf("mm_read_input_line_out\n");
13248
}
13249
 
14179 bpr 13250
static void mm_set_mol_dll (const char *st, boolean checkmol_mode,
6785 bpr 13251
                boolean normalize_ionic_bnds)
13252
{
14179 bpr 13253
  //printf("mm_set_mol\n");
13254
  //printf("%s\n",st);
6785 bpr 13255
  char bb;
13256
  char aa;
13257
  int i;
13258
  int k;
13259
  int J;
13260
  int spt = 0;
13261
  char tt[256];
13262
  char bb10 = '\n';
13263
  char bb13 = '\r';
13264
  char bb0 = '\0';
13265
  int lenst;
14179 bpr 13266
  //char d[256];
6785 bpr 13267
  lenst = strlen (st);
14179 bpr 13268
  //tt=(char*)safe_malloc(256*sizeof(char));
6785 bpr 13269
  tt[0] = '\0';
14179 bpr 13270
  //messagebox(0,st,'',0);
6785 bpr 13271
  mm_init_mol ();
14179 bpr 13272
  for (i = spt; i < lenst; i++) {
13273
    bb = st[i];
13274
    if ((bb == bb10) || (i == lenst)) {
13275
            J = 0;
13276
            // d:='';
13277
            for (k = spt; k < i; k++) {
6785 bpr 13278
              aa = st[k];
14179 bpr 13279
              if ((aa != bb10) && (aa != bb13)) {
13280
                      //d:=d+aa;
13281
                      tt[J] = aa;
13282
                      J++;
13283
                    }
6785 bpr 13284
            }
14179 bpr 13285
            tt[J] = bb0;
13286
            spt = i;
13287
            //messagebox (0,tt,tt,0);
13288
      //printf("A:%s\n",tt);
13289
            mm_read_input_line (tt);
13290
          }
13291
  }
6785 bpr 13292
//free(tt);
13293
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
13294
//printf("mm_set_mol\n");
13295
}
13296
 
14179 bpr 13297
DLLEXPORT void cm_set_mol (const char *st, int normalize_ionic_bnds)
6785 bpr 13298
{
18544 georgesk 13299
  mm_set_mol_dll (st, istrue, (normalize_ionic_bnds != FEATURE_OFF));
6785 bpr 13300
}
13301
 
14179 bpr 13302
DLLEXPORT void mm_set_mol (const char *st)
6785 bpr 13303
{
18544 georgesk 13304
  mm_set_mol_dll (st, isfalse, istrue);
6785 bpr 13305
}
13306
 
14179 bpr 13307
DLLEXPORT void xm_set_strict_typing (int strict_typing)
6785 bpr 13308
{
13309
  if (!yet_initialized)
13310
    init_globals_dll ();
13311
  opt_strict = (strict_typing != FEATURE_OFF);
18544 georgesk 13312
  //opt_strict=isfalse; //This never worked right and is harmful
6785 bpr 13313
}
13314
 
14179 bpr 13315
DLLEXPORT void mm_set_r_s_check (int r_s_check)
6785 bpr 13316
{
13317
  if (!yet_initialized)
13318
    init_globals_dll ();
13319
  opt_chiral = (r_s_check != FEATURE_OFF);
13320
}
13321
 
14179 bpr 13322
DLLEXPORT void mm_set_e_z_check (int e_z_check)
6785 bpr 13323
{
13324
  if (!yet_initialized)
13325
    init_globals_dll ();
13326
  opt_geom = (e_z_check != FEATURE_OFF);
13327
}
13328
 
14179 bpr 13329
DLLEXPORT void mm_set_chg_check (int chg_check)
6785 bpr 13330
{
13331
  if (!yet_initialized)
13332
    init_globals_dll ();
13333
  opt_chg = (chg_check != FEATURE_OFF);
13334
}
13335
 
14179 bpr 13336
DLLEXPORT void mm_set_iso_check (int iso_check)
6785 bpr 13337
{
13338
  if (!yet_initialized)
13339
    init_globals_dll ();
13340
  opt_iso = (iso_check != FEATURE_OFF);
13341
}
13342
 
14179 bpr 13343
DLLEXPORT void mm_set_rad_check (int rad_check)
6785 bpr 13344
{
13345
  if (!yet_initialized)
13346
    init_globals_dll ();
13347
  opt_rad = (rad_check != FEATURE_OFF);
13348
}
13349
 
14179 bpr 13350
DLLEXPORT void mm_set_exact_match (int exact)
6785 bpr 13351
{
13352
  if (!yet_initialized)
13353
    init_globals_dll ();
13354
  opt_exact = (exact != FEATURE_OFF);
13355
}
13356
 
14179 bpr 13357
DLLEXPORT int mm_match ()
6785 bpr 13358
{
13359
  mol_count = 1;
14179 bpr 13360
  //     mm_ElabMol;
13361
  /*printf("%i\n",opt_exact);
13362
  printf("%i\n",n_Ctot);
13363
  printf("%i\n",ndl_n_Ctot);
13364
  printf("%i\n",n_Otot);
13365
  printf("%i\n",ndl_n_Otot);
13366
  printf("%i\n",n_Ntot);
13367
  printf("%i\n",ndl_n_Ntot);*/
6785 bpr 13368
  if (opt_exact
13369
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14179 bpr 13370
            || n_Ntot != ndl_n_Ntot))
6785 bpr 13371
    return 0;
13372
  init_molstat (&ndl_molstat);
13373
  //perform_match ();
13374
  //---------------------------------------------------- 0.3o
13375
  if (rs_strict)                /* v0.3j */
13376
    ndl_ref_atom = find_ndl_ref_atom_cv ();
13377
  //ndl_ref_atom = find_ndl_ref_atom ();
13378
  else
13379
    ndl_ref_atom = find_ndl_ref_atom ();
13380
  clear_atom_tags ();
13381
  set_ndl_atom_tags ();
18544 georgesk 13382
  matchsummary = istrue;
6785 bpr 13383
  perform_match ();
13384
  matchsummary = matchresult;
18544 georgesk 13385
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == istrue) {
14179 bpr 13386
    do {
13387
            if (rs_strict)
13388
              ndl_ref_atom = find_ndl_ref_atom_cv ();
13389
            else
13390
              ndl_ref_atom = find_ndl_ref_atom ();
13391
            perform_match ();
18544 georgesk 13392
            if (matchresult == isfalse)
13393
             matchsummary = isfalse;
14179 bpr 13394
          }
18544 georgesk 13395
    while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != isfalse);
14179 bpr 13396
  }
6785 bpr 13397
 
13398
  //-----------------------------------------------------
13399
 
13400
  //mol_count = 0;
13401
 
13402
  //molbufindex = 0;
13403
 
13404
  //return matchresult ? 1 : 0;
13405
 
13406
  return matchsummary ? 1 : 0;
13407
}
13408
 
13409
//-------------------------
13410
 
14179 bpr 13411
DLLEXPORT void xm_set_ring_perception_algorithm (int algo)
6785 bpr 13412
{
14179 bpr 13413
  switch (algo) {
6785 bpr 13414
    case RPA_SAR:
13415
      opt_rs_dll = rs_sar;
13416
      break;
13417
    case RPA_SSR:
13418
      opt_rs_dll = rs_ssr;
13419
      break;
13420
    default:
13421
      opt_rs_dll = RPA_DEFAULT;
13422
      break;
13423
    }
13424
  //printf("RPA_SET: %i\n",opt_rs_dll);
13425
}
13426
 
14179 bpr 13427
static void write_molstat_X_dll (char *out_buffer)
6785 bpr 13428
{
13429
  char tmp_buf[256];
13430
  out_buffer[0] = '\0';
13431
  if (auto_ssr)                 /* v0.3n */
13432
    fix_ssr_ringcounts ();
13433
  sprintf (tmp_buf, "%d,", n_heavyatoms);
13434
  strcat (out_buffer, tmp_buf);
13435
  sprintf (tmp_buf, "%d,", n_heavybonds);
13436
  strcat (out_buffer, tmp_buf);
13437
#ifdef REDUCED_SAR
13438
  sprintf (tmp_buf, "%d,", n_countablerings);
13439
  strcat (out_buffer, tmp_buf);
13440
#else
13441
  sprintf (tmp_buf, "%d,", n_rings);
13442
  strcat (out_buffer, tmp_buf);
13443
#endif
13444
  sprintf (tmp_buf, "%d,", molstat.n_QA);
13445
  strcat (out_buffer, tmp_buf);
13446
  sprintf (tmp_buf, "%d,", molstat.n_QB);
13447
  strcat (out_buffer, tmp_buf);
13448
  //if (opt_chg)
13449
//    {                         /* 0.3x */
13450
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
13451
//    }
13452
//  else
13453
//    {
13454
  sprintf (tmp_buf, "%d,", molstat.n_chg);
13455
  //   }
13456
  strcat (out_buffer, tmp_buf);
13457
  sprintf (tmp_buf, "%d,", molstat.n_C1);
13458
  strcat (out_buffer, tmp_buf);
13459
  sprintf (tmp_buf, "%d,", molstat.n_C2);
13460
  strcat (out_buffer, tmp_buf);
13461
  sprintf (tmp_buf, "%d,", molstat.n_C);
13462
  strcat (out_buffer, tmp_buf);
13463
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
13464
  strcat (out_buffer, tmp_buf);
13465
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
13466
  strcat (out_buffer, tmp_buf);
13467
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
13468
  strcat (out_buffer, tmp_buf);
13469
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
13470
  strcat (out_buffer, tmp_buf);
13471
  sprintf (tmp_buf, "%d,", molstat.n_O2);
13472
  strcat (out_buffer, tmp_buf);
13473
  sprintf (tmp_buf, "%d,", molstat.n_O3);
13474
  strcat (out_buffer, tmp_buf);
13475
  sprintf (tmp_buf, "%d,", molstat.n_N1);
13476
  strcat (out_buffer, tmp_buf);
13477
  sprintf (tmp_buf, "%d,", molstat.n_N2);
13478
  strcat (out_buffer, tmp_buf);
13479
  sprintf (tmp_buf, "%d,", molstat.n_N3);
13480
  strcat (out_buffer, tmp_buf);
13481
  sprintf (tmp_buf, "%d,", molstat.n_S);
13482
  strcat (out_buffer, tmp_buf);
13483
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
13484
  strcat (out_buffer, tmp_buf);
13485
  sprintf (tmp_buf, "%d,", molstat.n_F);
13486
  strcat (out_buffer, tmp_buf);
13487
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
13488
  strcat (out_buffer, tmp_buf);
13489
  sprintf (tmp_buf, "%d,", molstat.n_Br);
13490
  strcat (out_buffer, tmp_buf);
13491
  sprintf (tmp_buf, "%d,", molstat.n_I);
13492
  strcat (out_buffer, tmp_buf);
13493
  sprintf (tmp_buf, "%d,", molstat.n_P);
13494
  strcat (out_buffer, tmp_buf);
13495
  sprintf (tmp_buf, "%d,", molstat.n_B);
13496
  strcat (out_buffer, tmp_buf);
13497
  sprintf (tmp_buf, "%d,", molstat.n_Met);
13498
  strcat (out_buffer, tmp_buf);
13499
  sprintf (tmp_buf, "%d,", molstat.n_X);
13500
  strcat (out_buffer, tmp_buf);
13501
  sprintf (tmp_buf, "%d,", molstat.n_b1);
13502
  strcat (out_buffer, tmp_buf);
13503
  sprintf (tmp_buf, "%d,", molstat.n_b2);
13504
  strcat (out_buffer, tmp_buf);
13505
  sprintf (tmp_buf, "%d,", molstat.n_b3);
13506
  strcat (out_buffer, tmp_buf);
13507
  sprintf (tmp_buf, "%d,", molstat.n_bar);
13508
  strcat (out_buffer, tmp_buf);
13509
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
13510
  strcat (out_buffer, tmp_buf);
13511
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
13512
  strcat (out_buffer, tmp_buf);
13513
  sprintf (tmp_buf, "%d,", molstat.n_CN);
13514
  strcat (out_buffer, tmp_buf);
13515
  sprintf (tmp_buf, "%d,", molstat.n_XY);
13516
  strcat (out_buffer, tmp_buf);
13517
  sprintf (tmp_buf, "%d,", molstat.n_r3);
13518
  strcat (out_buffer, tmp_buf);
13519
  sprintf (tmp_buf, "%d,", molstat.n_r4);
13520
  strcat (out_buffer, tmp_buf);
13521
  sprintf (tmp_buf, "%d,", molstat.n_r5);
13522
  strcat (out_buffer, tmp_buf);
13523
  sprintf (tmp_buf, "%d,", molstat.n_r6);
13524
  strcat (out_buffer, tmp_buf);
13525
  sprintf (tmp_buf, "%d,", molstat.n_r7);
13526
  strcat (out_buffer, tmp_buf);
13527
  sprintf (tmp_buf, "%d,", molstat.n_r8);
13528
  strcat (out_buffer, tmp_buf);
13529
  sprintf (tmp_buf, "%d,", molstat.n_r9);
13530
  strcat (out_buffer, tmp_buf);
13531
  sprintf (tmp_buf, "%d,", molstat.n_r10);
13532
  strcat (out_buffer, tmp_buf);
13533
  sprintf (tmp_buf, "%d,", molstat.n_r11);
13534
  strcat (out_buffer, tmp_buf);
13535
  sprintf (tmp_buf, "%d,", molstat.n_r12);
13536
  strcat (out_buffer, tmp_buf);
13537
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
13538
  strcat (out_buffer, tmp_buf);
13539
  sprintf (tmp_buf, "%d,", molstat.n_rN);
13540
  strcat (out_buffer, tmp_buf);
13541
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
13542
  strcat (out_buffer, tmp_buf);
13543
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
13544
  strcat (out_buffer, tmp_buf);
13545
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
13546
  strcat (out_buffer, tmp_buf);
13547
  sprintf (tmp_buf, "%d,", molstat.n_rO);
13548
  strcat (out_buffer, tmp_buf);
13549
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
13550
  strcat (out_buffer, tmp_buf);
13551
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
13552
  strcat (out_buffer, tmp_buf);
13553
  sprintf (tmp_buf, "%d,", molstat.n_rS);
13554
  strcat (out_buffer, tmp_buf);
13555
  sprintf (tmp_buf, "%d,", molstat.n_rX);
13556
  strcat (out_buffer, tmp_buf);
13557
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
13558
  strcat (out_buffer, tmp_buf);
13559
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
13560
  strcat (out_buffer, tmp_buf);
13561
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
13562
  strcat (out_buffer, tmp_buf);
13563
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
13564
  strcat (out_buffer, tmp_buf);
13565
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
13566
  strcat (out_buffer, tmp_buf);
13567
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
13568
  strcat (out_buffer, tmp_buf);
13569
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
13570
  strcat (out_buffer, tmp_buf);
13571
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
13572
  strcat (out_buffer, tmp_buf);
13573
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
13574
  strcat (out_buffer, tmp_buf);
13575
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
13576
  strcat (out_buffer, tmp_buf);
13577
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
13578
  strcat (out_buffer, tmp_buf);
13579
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
13580
  strcat (out_buffer, tmp_buf);
13581
  sprintf (tmp_buf, "%d,", molstat.n_psla);
13582
  strcat (out_buffer, tmp_buf);
13583
  sprintf (tmp_buf, "%d,", molstat.n_iso);
13584
  strcat (out_buffer, tmp_buf);
13585
  sprintf (tmp_buf, "%d", molstat.n_rad);
13586
  strcat (out_buffer, tmp_buf);
13587
}
13588
 
14179 bpr 13589
static void write_molstat_dll (char *out_buffer, int mode) {
6785 bpr 13590
  char tmp_buf[256];
13591
  char *sep1;
13592
  char *sep2;
14179 bpr 13593
  switch (mode) {
6785 bpr 13594
    case 1:
13595
      sep1 = "=";
13596
      sep2 = " AND ";
13597
      break;
13598
    case 2:
13599
      sep1 = "<=";
13600
      sep2 = " AND ";
13601
      break;
13602
    default:
13603
      sep1 = ":";
13604
      sep2 = ";";
13605
      break;
13606
    }
13607
 
13608
  out_buffer[0] = '\0';
13609
 
13610
  if (auto_ssr)                 /* v0.3n */
13611
    fix_ssr_ringcounts ();
13612
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
13613
  strcat (out_buffer, tmp_buf);
14179 bpr 13614
  if (n_bonds > 0) {
6785 bpr 13615
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
13616
      strcat (out_buffer, tmp_buf);
13617
    }
13618
 
13619
#ifdef REDUCED_SAR
14179 bpr 13620
  if (n_rings > 0) {
6785 bpr 13621
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
13622
      strcat (out_buffer, tmp_buf);
13623
    }
13624
#else
14179 bpr 13625
  if (n_rings > 0) {
6785 bpr 13626
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
13627
      strcat (out_buffer, tmp_buf);
13628
    }
13629
#endif
13630
 
14179 bpr 13631
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */ {
13632
    sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
13633
    strcat (out_buffer, tmp_buf);
13634
  }
13635
  if (molstat.n_C1 > 0) {
13636
    sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
13637
    strcat (out_buffer, tmp_buf);
13638
  }
13639
  if (molstat.n_C2 > 0) {
13640
    sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
13641
    strcat (out_buffer, tmp_buf);
13642
  }
6785 bpr 13643
 
14179 bpr 13644
  if (molstat.n_C > 0) {
13645
    sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
13646
    strcat (out_buffer, tmp_buf);
13647
  }
13648
  if (molstat.n_CHB1p > 0) {
13649
    sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
13650
    strcat (out_buffer, tmp_buf);
13651
  }
13652
  if (molstat.n_CHB2p > 0) {
13653
    sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
13654
    strcat (out_buffer, tmp_buf);
13655
  }
13656
  if (molstat.n_CHB3p > 0) {
13657
    sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
13658
    strcat (out_buffer, tmp_buf);
13659
  }
13660
  if (molstat.n_CHB4 > 0) {
13661
    sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
13662
    strcat (out_buffer, tmp_buf);
13663
  }
13664
  if (molstat.n_O2 > 0) {
13665
    sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
13666
    strcat (out_buffer, tmp_buf);
13667
  }
13668
  if (molstat.n_O3 > 0) {
13669
    sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
13670
    strcat (out_buffer, tmp_buf);
13671
  }
13672
  if (molstat.n_N1 > 0) {
13673
    sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
13674
    strcat (out_buffer, tmp_buf);
13675
  }
13676
  if (molstat.n_N2 > 0) {
13677
    sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
13678
    strcat (out_buffer, tmp_buf);
13679
  }
13680
  if (molstat.n_N3 > 0) {
13681
    sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
13682
    strcat (out_buffer, tmp_buf);
13683
  }
13684
  if (molstat.n_S > 0) {
13685
    sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
13686
    strcat (out_buffer, tmp_buf);
13687
  }
13688
  if (molstat.n_SeTe > 0) {
13689
    sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
13690
    strcat (out_buffer, tmp_buf);
13691
  }
13692
  if (molstat.n_F > 0) {
13693
    sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
13694
    strcat (out_buffer, tmp_buf);
13695
  }
13696
  if (molstat.n_Cl > 0) {
13697
    sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
13698
    strcat (out_buffer, tmp_buf);
13699
  }
13700
  if (molstat.n_Br > 0) {
13701
    sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
13702
    strcat (out_buffer, tmp_buf);
13703
  }
13704
  if (molstat.n_I > 0) {
13705
    sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
13706
    strcat (out_buffer, tmp_buf);
13707
  }
13708
  if (molstat.n_P > 0) {
13709
    sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
13710
    strcat (out_buffer, tmp_buf);
13711
  }
13712
  if (molstat.n_B > 0) {
13713
    sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
13714
    strcat (out_buffer, tmp_buf);
13715
  }
13716
  if (molstat.n_Met > 0) {
13717
    sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
13718
    strcat (out_buffer, tmp_buf);
13719
  }
13720
  if (molstat.n_X > 0) {
13721
    sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
13722
    strcat (out_buffer, tmp_buf);
13723
  }
13724
  if (molstat.n_b1 > 0) {
13725
    sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
13726
    strcat (out_buffer, tmp_buf);
13727
  }
13728
  if (molstat.n_b2 > 0) {
13729
    sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
13730
    strcat (out_buffer, tmp_buf);
13731
  }
13732
  if (molstat.n_b3 > 0) {
13733
    sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
13734
    strcat (out_buffer, tmp_buf);
13735
  }
13736
  if (molstat.n_bar > 0) {
13737
   sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
13738
   strcat (out_buffer, tmp_buf);
13739
  }
13740
  if (molstat.n_C1O > 0) {
13741
    sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
13742
    strcat (out_buffer, tmp_buf);
13743
  }
13744
  if (molstat.n_C2O > 0) {
6785 bpr 13745
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
13746
      strcat (out_buffer, tmp_buf);
13747
    }
14179 bpr 13748
  if (molstat.n_CN > 0) {
6785 bpr 13749
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
13750
      strcat (out_buffer, tmp_buf);
13751
    }
14179 bpr 13752
  if (molstat.n_XY > 0) {
13753
    sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
13754
    strcat (out_buffer, tmp_buf);
13755
  }
13756
  if (molstat.n_r3 > 0) {
13757
    sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
13758
    strcat (out_buffer, tmp_buf);
13759
  }
13760
  if (molstat.n_r4 > 0) {
13761
    sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
13762
    strcat (out_buffer, tmp_buf);
13763
  }
13764
  if (molstat.n_r5 > 0) {
13765
    sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
13766
    strcat (out_buffer, tmp_buf);
13767
  }
13768
  if (molstat.n_r6 > 0) {
13769
    sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
13770
    strcat (out_buffer, tmp_buf);
13771
  }
13772
  if (molstat.n_r7 > 0) {
13773
    sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
13774
    strcat (out_buffer, tmp_buf);
13775
  }
13776
  if (molstat.n_r8 > 0) {
13777
    sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
13778
    strcat (out_buffer, tmp_buf);
13779
  }
13780
  if (molstat.n_r9 > 0) {
13781
    sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
13782
    strcat (out_buffer, tmp_buf);
13783
  }
13784
  if (molstat.n_r10 > 0) {
13785
    sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
13786
    strcat (out_buffer, tmp_buf);
13787
  }
13788
  if (molstat.n_r11 > 0) {
13789
    sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
13790
    strcat (out_buffer, tmp_buf);
13791
  }
13792
  if (molstat.n_r12 > 0) {
13793
    sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
13794
    strcat (out_buffer, tmp_buf);
13795
  }
13796
  if (molstat.n_r13p > 0) {
6785 bpr 13797
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
13798
      strcat (out_buffer, tmp_buf);
13799
    }
14179 bpr 13800
  if (molstat.n_rN > 0) {
13801
    sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
13802
    strcat (out_buffer, tmp_buf);
13803
  }
13804
  if (molstat.n_rN1 > 0) {
13805
    sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
13806
    strcat (out_buffer, tmp_buf);
13807
  }
13808
  if (molstat.n_rN2 > 0) {
13809
    sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
13810
    strcat (out_buffer, tmp_buf);
13811
  }
13812
  if (molstat.n_rN3p > 0) {
13813
    sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
13814
    strcat (out_buffer, tmp_buf);
13815
  }
13816
  if (molstat.n_rO > 0) {
13817
    sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
13818
    strcat (out_buffer, tmp_buf);
13819
  }
13820
  if (molstat.n_rO1 > 0) {
13821
    sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
13822
    strcat (out_buffer, tmp_buf);
13823
  }
13824
  if (molstat.n_rO2p > 0) {
13825
    sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
13826
    strcat (out_buffer, tmp_buf);
13827
  }
13828
  if (molstat.n_rS > 0) {
13829
    sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
13830
    strcat (out_buffer, tmp_buf);
13831
  }
13832
  if (molstat.n_rX > 0) {
13833
    sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
13834
    strcat (out_buffer, tmp_buf);
13835
  }
13836
  if (molstat.n_rAr > 0) {
13837
    sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
13838
    strcat (out_buffer, tmp_buf);
13839
  }
6785 bpr 13840
 
14179 bpr 13841
  if (molstat.n_rBz > 0) {
13842
    sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
13843
    strcat (out_buffer, tmp_buf);
13844
  }
6785 bpr 13845
 
14179 bpr 13846
  if (molstat.n_br2p > 0) {
13847
    sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
13848
    strcat (out_buffer, tmp_buf);
13849
  }
6785 bpr 13850
 
14179 bpr 13851
  if (molstat.n_psg01 > 0) {
13852
    sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
13853
    strcat (out_buffer, tmp_buf);
13854
  }
6785 bpr 13855
 
14179 bpr 13856
  if (molstat.n_psg02 > 0) {
13857
    sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
13858
    strcat (out_buffer, tmp_buf);
13859
  }
6785 bpr 13860
 
14179 bpr 13861
  if (molstat.n_psg13 > 0) {
13862
    sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
13863
    strcat (out_buffer, tmp_buf);
13864
  }
6785 bpr 13865
 
14179 bpr 13866
  if (molstat.n_psg14 > 0) {
13867
    sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
13868
    strcat (out_buffer, tmp_buf);
13869
  }
6785 bpr 13870
 
14179 bpr 13871
  if (molstat.n_psg15 > 0) {
13872
    sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
13873
    strcat (out_buffer, tmp_buf);
13874
  }
6785 bpr 13875
 
14179 bpr 13876
  if (molstat.n_psg16 > 0) {
13877
    sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
13878
    strcat (out_buffer, tmp_buf);
13879
  }
6785 bpr 13880
 
14179 bpr 13881
  if (molstat.n_psg17 > 0) {
13882
    sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
13883
    strcat (out_buffer, tmp_buf);
13884
  }
6785 bpr 13885
 
14179 bpr 13886
  if (molstat.n_psg18 > 0) {
13887
    sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
13888
    strcat (out_buffer, tmp_buf);
13889
  }
6785 bpr 13890
 
14179 bpr 13891
  if (molstat.n_pstm > 0) {
6785 bpr 13892
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
13893
      strcat (out_buffer, tmp_buf);
13894
    }
13895
 
14179 bpr 13896
  if (molstat.n_psla > 0) {
6785 bpr 13897
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
13898
      strcat (out_buffer, tmp_buf);
13899
    }
13900
 
14179 bpr 13901
  if (opt_iso && molstat.n_iso > 0) {
13902
    sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
13903
    strcat (out_buffer, tmp_buf);
13904
  }
6785 bpr 13905
 
14179 bpr 13906
  if (opt_rad && molstat.n_rad > 0) {
13907
    sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
13908
    strcat (out_buffer, tmp_buf);
13909
  }
6785 bpr 13910
}
13911
 
17891 bpr 13912
static void write_fg_code_dll (char *out_buffer)
6785 bpr 13913
{
13914
  char tmp_buf[256];
13915
  out_buffer[0] = '\0';
14179 bpr 13916
  if (fg[fg_cation - 1]) {
13917
    sprintf (tmp_buf, "000000T2;");
13918
    strcat (out_buffer, tmp_buf);
13919
  }
13920
  if (fg[fg_anion - 1]) {
13921
    sprintf (tmp_buf, "000000T1;");
13922
    strcat (out_buffer, tmp_buf);
13923
  }
6785 bpr 13924
 
14179 bpr 13925
  if (fg[fg_aldehyde - 1]) {
13926
    sprintf (tmp_buf, "C2O1H000;");
13927
    strcat (out_buffer, tmp_buf);
13928
  }
13929
  if (fg[fg_ketone - 1]) {
13930
    sprintf (tmp_buf, "C2O1C000;");
13931
    strcat (out_buffer, tmp_buf);
13932
  }
6785 bpr 13933
 
14179 bpr 13934
  if (fg[fg_thioaldehyde - 1]) {
13935
    sprintf (tmp_buf, "C2S1H000;");
13936
    strcat (out_buffer, tmp_buf);
13937
  }
13938
  if (fg[fg_thioketone - 1]) {
13939
    sprintf (tmp_buf, "C2S1C000;");
13940
    strcat (out_buffer, tmp_buf);
13941
  }
13942
  if (fg[fg_imine - 1]) {
13943
    sprintf (tmp_buf, "C2N10000;");
13944
    strcat (out_buffer, tmp_buf);
13945
  }
13946
  if (fg[fg_hydrazone - 1]) {
13947
    sprintf (tmp_buf, "C2N1N000;");
13948
    strcat (out_buffer, tmp_buf);
13949
  }
13950
  if (fg[fg_semicarbazone - 1]) {
13951
    sprintf (tmp_buf, "C2NNC4ON;");
13952
    strcat (out_buffer, tmp_buf);
13953
  }
13954
  if (fg[fg_thiosemicarbazone - 1]) {
13955
    sprintf (tmp_buf, "C2NNC4SN;");
13956
    strcat (out_buffer, tmp_buf);
13957
  }
13958
  if (fg[fg_oxime - 1]) {
13959
    sprintf (tmp_buf, "C2N1OH00;");
13960
    strcat (out_buffer, tmp_buf);
13961
  }
13962
  if (fg[fg_oxime_ether - 1]) {
13963
    sprintf (tmp_buf, "C2N1OC00;");
13964
    strcat (out_buffer, tmp_buf);
13965
  }
13966
  if (fg[fg_ketene - 1]) {
13967
    sprintf (tmp_buf, "C3OC0000;");
13968
    strcat (out_buffer, tmp_buf);
13969
  }
13970
  if (fg[fg_ketene_acetal_deriv - 1]) {
13971
    sprintf (tmp_buf, "C3OCC000;");
13972
    strcat (out_buffer, tmp_buf);
13973
  }
13974
  if (fg[fg_carbonyl_hydrate - 1]) {
13975
    sprintf (tmp_buf, "C2O2H200;");
13976
    strcat (out_buffer, tmp_buf);
13977
  }
13978
  if (fg[fg_hemiacetal - 1]) {
13979
    sprintf (tmp_buf, "C2O2HC00;");
13980
    strcat (out_buffer, tmp_buf);
13981
  }
13982
  if (fg[fg_acetal - 1]) {
13983
   sprintf (tmp_buf, "C2O2CC00;");
13984
   strcat (out_buffer, tmp_buf);
13985
  }
13986
  if (fg[fg_hemiaminal - 1]) {
13987
    sprintf (tmp_buf, "C2NOHC10;");
13988
    strcat (out_buffer, tmp_buf);
13989
  }
13990
  if (fg[fg_aminal - 1]) {
13991
    sprintf (tmp_buf, "C2N2CC10;");
13992
    strcat (out_buffer, tmp_buf);
13993
  }
13994
  if (fg[fg_thiohemiaminal - 1]) {
13995
    sprintf (tmp_buf, "C2NSHC10;");
13996
    strcat (out_buffer, tmp_buf);
13997
  }
13998
  if (fg[fg_thioacetal - 1]) {
13999
    sprintf (tmp_buf, "C2S2CC00;");
14000
    strcat (out_buffer, tmp_buf);
14001
  }
14002
  if (fg[fg_enamine - 1]) {
14003
    sprintf (tmp_buf, "C2CNH000;");
14004
    strcat (out_buffer, tmp_buf);
14005
  }
14006
  if (fg[fg_enol - 1]) {
14007
    sprintf (tmp_buf, "C2COH000;");
14008
    strcat (out_buffer, tmp_buf);
14009
  }
14010
  if (fg[fg_enolether - 1]) {
14011
    sprintf (tmp_buf, "C2COC000;");
14012
    strcat (out_buffer, tmp_buf);
14013
  }
6785 bpr 14014
 
14179 bpr 14015
  if (fg[fg_prim_alcohol - 1]) {
14016
    sprintf (tmp_buf, "O1H1C000;");
14017
    strcat (out_buffer, tmp_buf);
14018
  }
14019
  if (fg[fg_sec_alcohol - 1]) {
14020
    sprintf (tmp_buf, "O1H2C000;");
14021
    strcat (out_buffer, tmp_buf);
14022
  }
14023
  if (fg[fg_tert_alcohol - 1]) {
14024
    sprintf (tmp_buf, "O1H3C000;");
14025
    strcat (out_buffer, tmp_buf);
14026
  }
14027
  if (fg[fg_1_2_diol - 1]) {
14028
    sprintf (tmp_buf, "O1H0CO1H;");
14029
    strcat (out_buffer, tmp_buf);
14030
  }
14031
  if (fg[fg_1_2_aminoalcohol - 1]) {
14032
    sprintf (tmp_buf, "O1H0CN1C;");
14033
    strcat (out_buffer, tmp_buf);
14034
  }
14035
  if (fg[fg_phenol - 1]) {
14036
    sprintf (tmp_buf, "O1H1A000;");
14037
    strcat (out_buffer, tmp_buf);
14038
  }
14039
  if (fg[fg_1_2_diphenol - 1]) {
14040
    sprintf (tmp_buf, "O1H2A000;");
14041
    strcat (out_buffer, tmp_buf);
14042
  }
14043
  if (fg[fg_enediol - 1]) {
14044
    sprintf (tmp_buf, "C2COH200;");
14045
    strcat (out_buffer, tmp_buf);
14046
  }
6785 bpr 14047
 
14179 bpr 14048
  if (fg[fg_dialkylether - 1]) {
14049
    sprintf (tmp_buf, "O1C0CC00;");
14050
    strcat (out_buffer, tmp_buf);
14051
  }
14052
  if (fg[fg_alkylarylether - 1]) {
14053
    sprintf (tmp_buf, "O1C0CA00;");
14054
    strcat (out_buffer, tmp_buf);
14055
  }
14056
  if (fg[fg_diarylether - 1]) {
14057
    sprintf (tmp_buf, "O1C0AA00;");
14058
    strcat (out_buffer, tmp_buf);
14059
  }
14060
  if (fg[fg_thioether - 1]) {
14061
    sprintf (tmp_buf, "S1C00000;");
14062
    strcat (out_buffer, tmp_buf);
14063
  }
14064
  if (fg[fg_disulfide - 1]) {
14065
    sprintf (tmp_buf, "S1S1C000;");
14066
    strcat (out_buffer, tmp_buf);
14067
  }
14068
  if (fg[fg_peroxide - 1]) {
14069
    sprintf (tmp_buf, "O1O1C000;");
14070
    strcat (out_buffer, tmp_buf);
14071
  }
14072
  if (fg[fg_hydroperoxide - 1]) {
14073
    sprintf (tmp_buf, "O1O1H000;");
14074
    strcat (out_buffer, tmp_buf);
14075
  }
14076
  if (fg[fg_hydrazine - 1]) {
14077
    sprintf (tmp_buf, "N1N10000;");
14078
    strcat (out_buffer, tmp_buf);
14079
  }
14080
  if (fg[fg_hydroxylamine - 1]) {
14081
    sprintf (tmp_buf, "N1O1H000;");
14082
    strcat (out_buffer, tmp_buf);
14083
  }
6785 bpr 14084
 
14179 bpr 14085
  if (fg[fg_prim_aliph_amine - 1]) {
14086
    sprintf (tmp_buf, "N1C1C000;");
14087
    strcat (out_buffer, tmp_buf);
14088
  }
14089
  if (fg[fg_prim_arom_amine - 1]) {
14090
    sprintf (tmp_buf, "N1C1A000;");
14091
    strcat (out_buffer, tmp_buf);
14092
  }
6785 bpr 14093
 
14179 bpr 14094
  if (fg[fg_sec_aliph_amine - 1]) {
14095
    sprintf (tmp_buf, "N1C2CC00;");
14096
    strcat (out_buffer, tmp_buf);
14097
  }
14098
  if (fg[fg_sec_mixed_amine - 1]) {
14099
    sprintf (tmp_buf, "N1C2AC00;");
14100
    strcat (out_buffer, tmp_buf);
14101
  }
14102
  if (fg[fg_sec_arom_amine - 1]) {
14103
    sprintf (tmp_buf, "N1C2AA00;");
14104
    strcat (out_buffer, tmp_buf);
14105
  }
6785 bpr 14106
 
14179 bpr 14107
  if (fg[fg_tert_aliph_amine - 1]) {
14108
    sprintf (tmp_buf, "N1C3CC00;");
14109
    strcat (out_buffer, tmp_buf);
14110
  }
14111
  if (fg[fg_tert_mixed_amine - 1]) {
14112
    sprintf (tmp_buf, "N1C3AC00;");
14113
    strcat (out_buffer, tmp_buf);
14114
  }
14115
  if (fg[fg_tert_arom_amine - 1]) {
14116
    sprintf (tmp_buf, "N1C3AA00;");
14117
    strcat (out_buffer, tmp_buf);
14118
  }
14119
  if (fg[fg_quart_ammonium - 1]) {
14120
    sprintf (tmp_buf, "N1C400T2;");
14121
    strcat (out_buffer, tmp_buf);
14122
  }
14123
  if (fg[fg_n_oxide - 1]) {
14124
    sprintf (tmp_buf, "N0O10000;");
14125
    strcat (out_buffer, tmp_buf);
14126
  }
6785 bpr 14127
 
14179 bpr 14128
  if (fg[fg_halogen_deriv - 1]) {
14129
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1]) {
14130
            sprintf (tmp_buf, "XX000000;");
14131
            strcat (out_buffer, tmp_buf);
14132
          }
14133
  }
6785 bpr 14134
 
14179 bpr 14135
  if (fg[fg_alkyl_fluoride - 1]) {
14136
    sprintf (tmp_buf, "XF00C000;");
14137
    strcat (out_buffer, tmp_buf);
14138
  }
14139
  if (fg[fg_alkyl_chloride - 1]) {
14140
    sprintf (tmp_buf, "XC00C000;");
14141
    strcat (out_buffer, tmp_buf);
14142
  }
14143
  if (fg[fg_alkyl_bromide - 1]) {
14144
    sprintf (tmp_buf, "XB00C000;");
14145
    strcat (out_buffer, tmp_buf);
14146
  }
14147
  if (fg[fg_alkyl_iodide - 1]) {
14148
    sprintf (tmp_buf, "XI00C000;");
14149
    strcat (out_buffer, tmp_buf);
14150
  }
6785 bpr 14151
 
14179 bpr 14152
  if (fg[fg_aryl_fluoride - 1]) {
14153
    sprintf (tmp_buf, "XF00A000;");
14154
    strcat (out_buffer, tmp_buf);
14155
  }
14156
  if (fg[fg_aryl_chloride - 1]) {
14157
    sprintf (tmp_buf, "XC00A000;");
14158
    strcat (out_buffer, tmp_buf);
14159
  }
14160
  if (fg[fg_aryl_bromide - 1]) {
14161
    sprintf (tmp_buf, "XB00A000;");
14162
    strcat (out_buffer, tmp_buf);
14163
  }
14164
  if (fg[fg_aryl_iodide - 1]) {
14165
    sprintf (tmp_buf, "XI00A000;");
14166
    strcat (out_buffer, tmp_buf);
14167
  }
14168
  if (fg[fg_organometallic - 1]) {
14169
    sprintf (tmp_buf, "000000MX;");
14170
    strcat (out_buffer, tmp_buf);
14171
  }
14172
  if (fg[fg_organolithium - 1]) {
14173
    sprintf (tmp_buf, "000000ML;");
14174
    strcat (out_buffer, tmp_buf);
14175
  }
14176
  if (fg[fg_organomagnesium - 1]) {
14177
    sprintf (tmp_buf, "000000MM;");
14178
    strcat (out_buffer, tmp_buf);
14179
  }
6785 bpr 14180
 
14179 bpr 14181
  if (fg[fg_carboxylic_acid - 1]) {
14182
    sprintf (tmp_buf, "C3O2H000;");
14183
    strcat (out_buffer, tmp_buf);
14184
  }
14185
  if (fg[fg_carboxylic_acid_salt - 1]) {
14186
    sprintf (tmp_buf, "C3O200T1;");
14187
    strcat (out_buffer, tmp_buf);
14188
  }
14189
  if (fg[fg_carboxylic_acid_ester - 1]) {
14190
    sprintf (tmp_buf, "C3O2C000;");
14191
    strcat (out_buffer, tmp_buf);
14192
  }
14193
  if (fg[fg_lactone - 1]) {
14194
    sprintf (tmp_buf, "C3O2CZ00;");
14195
    strcat (out_buffer, tmp_buf);
14196
  }
6785 bpr 14197
 
14179 bpr 14198
  if (fg[fg_carboxylic_acid_prim_amide - 1]) {
14199
    sprintf (tmp_buf, "C3ONC100;");
14200
    strcat (out_buffer, tmp_buf);
14201
  }
14202
  if (fg[fg_carboxylic_acid_sec_amide - 1]) {
14203
    sprintf (tmp_buf, "C3ONC200;");
14204
    strcat (out_buffer, tmp_buf);
14205
  }
14206
  if (fg[fg_carboxylic_acid_tert_amide - 1]) {
14207
    sprintf (tmp_buf, "C3ONC300;");
14208
    strcat (out_buffer, tmp_buf);
14209
  }
14210
  if (fg[fg_lactam - 1]) {
14211
    sprintf (tmp_buf, "C3ONCZ00;");
14212
    strcat (out_buffer, tmp_buf);
14213
  }
14214
  if (fg[fg_carboxylic_acid_hydrazide - 1]) {
14215
    sprintf (tmp_buf, "C3ONN100;");
14216
    strcat (out_buffer, tmp_buf);
14217
  }
14218
  if (fg[fg_carboxylic_acid_azide - 1]) {
14219
    sprintf (tmp_buf, "C3ONN200;");
14220
    strcat (out_buffer, tmp_buf);
14221
  }
14222
  if (fg[fg_hydroxamic_acid - 1]) {
14223
    sprintf (tmp_buf, "C3ONOH00;");
14224
    strcat (out_buffer, tmp_buf);
14225
  }
14226
  if (fg[fg_carboxylic_acid_amidine - 1]) {
14227
    sprintf (tmp_buf, "C3N2H000;");
14228
    strcat (out_buffer, tmp_buf);
14229
  }
14230
  if (fg[fg_carboxylic_acid_amidrazone - 1]) {
14231
    sprintf (tmp_buf, "C3NNN100;");
14232
    strcat (out_buffer, tmp_buf);
14233
  }
14234
  if (fg[fg_nitrile - 1]) {
14235
    sprintf (tmp_buf, "C3N00000;");
14236
    strcat (out_buffer, tmp_buf);
14237
  }
6785 bpr 14238
 
14179 bpr 14239
  if (fg[fg_acyl_fluoride - 1]) {
14240
    sprintf (tmp_buf, "C3OXF000;");
14241
    strcat (out_buffer, tmp_buf);
14242
  }
14243
  if (fg[fg_acyl_chloride - 1]) {
14244
    sprintf (tmp_buf, "C3OXC000;");
14245
    strcat (out_buffer, tmp_buf);
14246
  }
14247
  if (fg[fg_acyl_bromide - 1]) {
14248
    sprintf (tmp_buf, "C3OXB000;");
14249
    strcat (out_buffer, tmp_buf);
14250
  }
14251
  if (fg[fg_acyl_iodide - 1]) {
14252
    sprintf (tmp_buf, "C3OXI000;");
14253
    strcat (out_buffer, tmp_buf);
14254
  }
14255
  if (fg[fg_acyl_cyanide - 1]) {
14256
    sprintf (tmp_buf, "C2OC3N00;");
14257
    strcat (out_buffer, tmp_buf);
14258
  }
14259
  if (fg[fg_imido_ester - 1]) {
14260
    sprintf (tmp_buf, "C3NOC000;");
14261
    strcat (out_buffer, tmp_buf);
14262
  }
14263
  if (fg[fg_imidoyl_halide - 1]) {
14264
    sprintf (tmp_buf, "C3NXX000;");
14265
    strcat (out_buffer, tmp_buf);
14266
  }
6785 bpr 14267
 
14179 bpr 14268
  if (fg[fg_thiocarboxylic_acid - 1]) {
14269
    sprintf (tmp_buf, "C3SOH000;");
14270
    strcat (out_buffer, tmp_buf);
14271
  }
14272
  if (fg[fg_thiocarboxylic_acid_ester - 1]) {
14273
    sprintf (tmp_buf, "C3SOC000;");
14274
    strcat (out_buffer, tmp_buf);
14275
  }
14276
  if (fg[fg_thiolactone - 1]) {
14277
    sprintf (tmp_buf, "C3SOCZ00;");
14278
    strcat (out_buffer, tmp_buf);
14279
  }
14280
  if (fg[fg_thiocarboxylic_acid_amide - 1]) {
14281
    sprintf (tmp_buf, "C3SNH000;");
14282
    strcat (out_buffer, tmp_buf);
14283
  }
14284
  if (fg[fg_thiolactam - 1]) {
14285
    sprintf (tmp_buf, "C3SNCZ00;");
14286
    strcat (out_buffer, tmp_buf);
14287
  }
14288
  if (fg[fg_imido_thioester - 1]) {
14289
    sprintf (tmp_buf, "C3NSC000;");
14290
    strcat (out_buffer, tmp_buf);
14291
  }
14292
  if (fg[fg_oxohetarene - 1]) {
14293
    sprintf (tmp_buf, "C3ONAZ00;");
14294
    strcat (out_buffer, tmp_buf);
14295
  }
14296
  if (fg[fg_thioxohetarene - 1]) {
14297
    sprintf (tmp_buf, "C3SNAZ00;");
14298
    strcat (out_buffer, tmp_buf);
14299
  }
14300
  if (fg[fg_iminohetarene - 1]) {
14301
    sprintf (tmp_buf, "C3NNAZ00;");
14302
    strcat (out_buffer, tmp_buf);
14303
  }
14304
  if (fg[fg_orthocarboxylic_acid_deriv - 1]) {
14305
    sprintf (tmp_buf, "C3O30000;");
14306
    strcat (out_buffer, tmp_buf);
14307
  }
14308
  if (fg[fg_carboxylic_acid_orthoester - 1]) {
14309
    sprintf (tmp_buf, "C3O3C000;");
14310
    strcat (out_buffer, tmp_buf);
14311
  }
14312
  if (fg[fg_carboxylic_acid_amide_acetal - 1]) {
14313
    sprintf (tmp_buf, "C3O3NC00;");
14314
    strcat (out_buffer, tmp_buf);
14315
  }
14316
  if (fg[fg_carboxylic_acid_anhydride - 1]) {
14317
    sprintf (tmp_buf, "C3O2C3O2;");
14318
    strcat (out_buffer, tmp_buf);
14319
  }
6785 bpr 14320
 
14179 bpr 14321
  if (fg[fg_carboxylic_acid_unsubst_imide - 1]) {
14322
    sprintf (tmp_buf, "C3ONCH10;");
14323
    strcat (out_buffer, tmp_buf);
14324
  }
14325
  if (fg[fg_carboxylic_acid_subst_imide - 1]) {
14326
    sprintf (tmp_buf, "C3ONCC10;");
14327
    strcat (out_buffer, tmp_buf);
14328
  }
14329
  if (fg[fg_co2_deriv - 1]) {
14330
    sprintf (tmp_buf, "C4000000;");
14331
    strcat (out_buffer, tmp_buf);
14332
  }
14333
  if (fg[fg_carbonic_acid_deriv - 1]) {
14334
    sprintf (tmp_buf, "C4O30000;");
14335
    strcat (out_buffer, tmp_buf);
14336
  }
14337
  if (fg[fg_carbonic_acid_monoester - 1]) {
14338
    sprintf (tmp_buf, "C4O3C100;");
14339
    strcat (out_buffer, tmp_buf);
14340
  }
14341
  if (fg[fg_carbonic_acid_diester - 1]) {
14342
    sprintf (tmp_buf, "C4O3C200;");
14343
    strcat (out_buffer, tmp_buf);
14344
  }
14345
  if (fg[fg_carbonic_acid_ester_halide - 1]) {
14346
    sprintf (tmp_buf, "C4O3CX00;");
14347
    strcat (out_buffer, tmp_buf);
14348
  }
14349
  if (fg[fg_thiocarbonic_acid_deriv - 1]) {
14350
    sprintf (tmp_buf, "C4SO0000;");
14351
    strcat (out_buffer, tmp_buf);
14352
  }
14353
  if (fg[fg_thiocarbonic_acid_monoester - 1]) {
14354
    sprintf (tmp_buf, "C4SOC100;");
14355
    strcat (out_buffer, tmp_buf);
14356
  }
14357
  if (fg[fg_thiocarbonic_acid_diester - 1]) {
14358
    sprintf (tmp_buf, "C4SOC200;");
14359
    strcat (out_buffer, tmp_buf);
14360
  }
14361
  if (fg[fg_thiocarbonic_acid_ester_halide - 1]) {
14362
    sprintf (tmp_buf, "C4SOX_00;");
14363
    strcat (out_buffer, tmp_buf);
14364
  }
14365
  if (fg[fg_carbamic_acid_deriv - 1]) {
14366
    sprintf (tmp_buf, "C4O2N000;");
14367
    strcat (out_buffer, tmp_buf);
14368
  }
14369
  if (fg[fg_carbamic_acid - 1]) {
14370
    sprintf (tmp_buf, "C4O2NH00;");
14371
    strcat (out_buffer, tmp_buf);
14372
  }
14373
  if (fg[fg_carbamic_acid_ester - 1]) {
14374
    sprintf (tmp_buf, "C4O2NC00;");
14375
    strcat (out_buffer, tmp_buf);
14376
  }
14377
  if (fg[fg_carbamic_acid_halide - 1]) {
14378
    sprintf (tmp_buf, "C4O2NX00;");
14379
    strcat (out_buffer, tmp_buf);
14380
  }
14381
  if (fg[fg_thiocarbamic_acid_deriv - 1]) {
14382
    sprintf (tmp_buf, "C4SN0000;");
14383
    strcat (out_buffer, tmp_buf);
14384
  }
14385
  if (fg[fg_thiocarbamic_acid - 1]) {
14386
    sprintf (tmp_buf, "C4SNOH00;");
14387
    strcat (out_buffer, tmp_buf);
14388
  }
14389
  if (fg[fg_thiocarbamic_acid_ester - 1]) {
14390
    sprintf (tmp_buf, "C4SNOC00;");
14391
    strcat (out_buffer, tmp_buf);
14392
  }
14393
  if (fg[fg_thiocarbamic_acid_halide - 1]) {
14394
    sprintf (tmp_buf, "C4SNXX00;");
14395
    strcat (out_buffer, tmp_buf);
14396
  }
14397
  if (fg[fg_urea - 1]) {
14398
    sprintf (tmp_buf, "C4O1N200;");
14399
    strcat (out_buffer, tmp_buf);
14400
  }
14401
  if (fg[fg_isourea - 1]) {
14402
    sprintf (tmp_buf, "C4N2O100;");
14403
    strcat (out_buffer, tmp_buf);
14404
  }
14405
  if (fg[fg_thiourea - 1]) {
14406
    sprintf (tmp_buf, "C4S1N200;");
14407
    strcat (out_buffer, tmp_buf);
14408
  }
14409
  if (fg[fg_isothiourea - 1]) {
14410
    sprintf (tmp_buf, "C4N2S100;");
14411
    strcat (out_buffer, tmp_buf);
14412
  }
14413
  if (fg[fg_guanidine - 1]) {
14414
    sprintf (tmp_buf, "C4N30000;");
14415
    strcat (out_buffer, tmp_buf);
14416
  }
14417
  if (fg[fg_semicarbazide - 1]) {
14418
    sprintf (tmp_buf, "C4ON2N00;");
14419
    strcat (out_buffer, tmp_buf);
14420
  }
14421
  if (fg[fg_thiosemicarbazide - 1]) {
14422
    sprintf (tmp_buf, "C4SN2N00;");
14423
    strcat (out_buffer, tmp_buf);
14424
  }
14425
  if (fg[fg_azide - 1]) {
14426
    sprintf (tmp_buf, "N4N20000;");
14427
    strcat (out_buffer, tmp_buf);
14428
  }
14429
  if (fg[fg_azo_compound - 1]) {
14430
    sprintf (tmp_buf, "N2N10000;");
14431
    strcat (out_buffer, tmp_buf);
14432
  }
14433
  if (fg[fg_diazonium_salt - 1]) {
14434
    sprintf (tmp_buf, "N3N100T2;");
14435
    strcat (out_buffer, tmp_buf);
14436
  }
14437
  if (fg[fg_isonitrile - 1]) {
14438
    sprintf (tmp_buf, "N3C10000;");
14439
    strcat (out_buffer, tmp_buf);
14440
  }
14441
  if (fg[fg_cyanate - 1]) {
14442
    sprintf (tmp_buf, "C4NO1000;");
14443
    strcat (out_buffer, tmp_buf);
14444
  }
14445
  if (fg[fg_isocyanate - 1]) {
14446
    sprintf (tmp_buf, "C4NO2000;");
14447
    strcat (out_buffer, tmp_buf);
14448
  }
14449
  if (fg[fg_thiocyanate - 1]) {
14450
    sprintf (tmp_buf, "C4NS1000;");
14451
    strcat (out_buffer, tmp_buf);
14452
  }
14453
  if (fg[fg_isothiocyanate - 1]) {
14454
    sprintf (tmp_buf, "C4NS2000;");
14455
    strcat (out_buffer, tmp_buf);
14456
  }
14457
  if (fg[fg_carbodiimide - 1]) {
14458
    sprintf (tmp_buf, "C4N20000;");
14459
    strcat (out_buffer, tmp_buf);
14460
  }
14461
  if (fg[fg_nitroso_compound - 1]) {
14462
    sprintf (tmp_buf, "N2O10000;");
14463
    strcat (out_buffer, tmp_buf);
14464
  }
14465
  if (fg[fg_nitro_compound - 1]) {
14466
    sprintf (tmp_buf, "N4O20000;");
14467
    strcat (out_buffer, tmp_buf);
14468
  }
14469
  if (fg[fg_nitrite - 1]) {
14470
    sprintf (tmp_buf, "N3O20000;");
14471
    strcat (out_buffer, tmp_buf);
14472
  }
14473
  if (fg[fg_nitrate - 1]) {
14474
    sprintf (tmp_buf, "N4O30000;");
14475
    strcat (out_buffer, tmp_buf);
14476
  }
14477
  if (fg[fg_sulfuric_acid_deriv - 1]) {
14478
    sprintf (tmp_buf, "S6O00000;");
14479
    strcat (out_buffer, tmp_buf);
14480
  }
14481
  if (fg[fg_sulfuric_acid - 1]) {
14482
    sprintf (tmp_buf, "S6O4H000;");
14483
    strcat (out_buffer, tmp_buf);
14484
  }
14485
  if (fg[fg_sulfuric_acid_monoester - 1]) {
14486
    sprintf (tmp_buf, "S6O4HC00;");
14487
    strcat (out_buffer, tmp_buf);
14488
  }
14489
  if (fg[fg_sulfuric_acid_diester - 1]) {
14490
    sprintf (tmp_buf, "S6O4CC00;");
14491
    strcat (out_buffer, tmp_buf);
14492
  }
14493
  if (fg[fg_sulfuric_acid_amide_ester - 1]) {
14494
    sprintf (tmp_buf, "S6O3NC00;");
14495
    strcat (out_buffer, tmp_buf);
14496
  }
14497
  if (fg[fg_sulfuric_acid_amide - 1]) {
14498
    sprintf (tmp_buf, "S6O3N100;");
14499
    strcat (out_buffer, tmp_buf);
14500
  }
14501
  if (fg[fg_sulfuric_acid_diamide - 1]) {
14502
    sprintf (tmp_buf, "S6O2N200;");
14503
    strcat (out_buffer, tmp_buf);
14504
  }
14505
  if (fg[fg_sulfuryl_halide - 1]) {
14506
    sprintf (tmp_buf, "S6O3XX00;");
14507
    strcat (out_buffer, tmp_buf);
14508
  }
14509
  if (fg[fg_sulfonic_acid_deriv - 1]) {
14510
    sprintf (tmp_buf, "S5O00000;");
14511
    strcat (out_buffer, tmp_buf);
14512
  }
14513
  if (fg[fg_sulfonic_acid - 1]) {
14514
    sprintf (tmp_buf, "S5O3H000;");
14515
    strcat (out_buffer, tmp_buf);
14516
  }
14517
  if (fg[fg_sulfonic_acid_ester - 1]) {
14518
    sprintf (tmp_buf, "S5O3C000;");
14519
    strcat (out_buffer, tmp_buf);
14520
  }
14521
  if (fg[fg_sulfonamide - 1]) {
14522
    sprintf (tmp_buf, "S5O2N000;");
14523
    strcat (out_buffer, tmp_buf);
14524
  }
14525
  if (fg[fg_sulfonyl_halide - 1]) {
14526
    sprintf (tmp_buf, "S5O2XX00;");
14527
    strcat (out_buffer, tmp_buf);
14528
  }
14529
  if (fg[fg_sulfone - 1]) {
14530
    sprintf (tmp_buf, "S4O20000;");
14531
    strcat (out_buffer, tmp_buf);
14532
  }
14533
  if (fg[fg_sulfoxide - 1]) {
14534
    sprintf (tmp_buf, "S2O10000;");
14535
    strcat (out_buffer, tmp_buf);
14536
  }
14537
  if (fg[fg_sulfinic_acid_deriv - 1]) {
14538
    sprintf (tmp_buf, "S3O00000;");
14539
    strcat (out_buffer, tmp_buf);
14540
  }
14541
  if (fg[fg_sulfinic_acid - 1]) {
14542
    sprintf (tmp_buf, "S3O2H000;");
14543
    strcat (out_buffer, tmp_buf);
14544
  }
14545
  if (fg[fg_sulfinic_acid_ester - 1]) {
14546
    sprintf (tmp_buf, "S3O2C000;");
14547
    strcat (out_buffer, tmp_buf);
14548
  }
14549
  if (fg[fg_sulfinic_acid_halide - 1]) {
14550
    sprintf (tmp_buf, "S3O1XX00;");
14551
    strcat (out_buffer, tmp_buf);
14552
  }
14553
  if (fg[fg_sulfinic_acid_amide - 1]) {
6785 bpr 14554
      sprintf (tmp_buf, "S3O1N000;");
14555
      strcat (out_buffer, tmp_buf);
14556
    }
14179 bpr 14557
  if (fg[fg_sulfenic_acid_deriv - 1]) {
14558
    sprintf (tmp_buf, "S1O00000;");
14559
    strcat (out_buffer, tmp_buf);
14560
  }
14561
  if (fg[fg_sulfenic_acid - 1]) {
14562
    sprintf (tmp_buf, "S1O1H000;");
14563
    strcat (out_buffer, tmp_buf);
14564
  }
14565
  if (fg[fg_sulfenic_acid_ester - 1]) {
14566
    sprintf (tmp_buf, "S1O1C000;");
14567
    strcat (out_buffer, tmp_buf);
14568
  }
14569
  if (fg[fg_sulfenic_acid_halide - 1]) {
14570
    sprintf (tmp_buf, "S1O0XX00;");
14571
    strcat (out_buffer, tmp_buf);
14572
  }
14573
  if (fg[fg_sulfenic_acid_amide - 1]) {
14574
    sprintf (tmp_buf, "S1O0N100;");
14575
    strcat (out_buffer, tmp_buf);
14576
  }
6785 bpr 14577
 
14179 bpr 14578
  if (fg[fg_alkylthiol - 1]) {
14579
    sprintf (tmp_buf, "S1H1C000;");
14580
    strcat (out_buffer, tmp_buf);
14581
  }
14582
  if (fg[fg_arylthiol - 1]) {
14583
    sprintf (tmp_buf, "S1H1A000;");
14584
    strcat (out_buffer, tmp_buf);
14585
  }
14586
  if (fg[fg_phosphoric_acid_deriv - 1]) {
14587
    sprintf (tmp_buf, "P5O0H000;");
14588
    strcat (out_buffer, tmp_buf);
14589
  }
14590
  if (fg[fg_phosphoric_acid - 1]) {
14591
    sprintf (tmp_buf, "P5O4H200;");
14592
    strcat (out_buffer, tmp_buf);
14593
  }
14594
  if (fg[fg_phosphoric_acid_ester - 1]) {
14595
    sprintf (tmp_buf, "P5O4HC00;");
14596
    strcat (out_buffer, tmp_buf);
14597
  }
14598
  if (fg[fg_phosphoric_acid_halide - 1]) {
14599
    sprintf (tmp_buf, "P5O3HX00;");
14600
    strcat (out_buffer, tmp_buf);
14601
  }
14602
  if (fg[fg_phosphoric_acid_amide - 1]) {
14603
    sprintf (tmp_buf, "P5O3HN00;");
14604
    strcat (out_buffer, tmp_buf);
14605
  }
14606
  if (fg[fg_thiophosphoric_acid_deriv - 1]) {
14607
    sprintf (tmp_buf, "P5O0S000;");
14608
    strcat (out_buffer, tmp_buf);
14609
  }
14610
  if (fg[fg_thiophosphoric_acid - 1]) {
14611
    sprintf (tmp_buf, "P5O3SH00;");
14612
    strcat (out_buffer, tmp_buf);
14613
  }
14614
  if (fg[fg_thiophosphoric_acid_ester - 1]) {
14615
    sprintf (tmp_buf, "P5O3SC00;");
14616
    strcat (out_buffer, tmp_buf);
14617
  }
14618
  if (fg[fg_thiophosphoric_acid_halide - 1]) {
14619
    sprintf (tmp_buf, "P5O2SX00;");
14620
    strcat (out_buffer, tmp_buf);
14621
  }
14622
  if (fg[fg_thiophosphoric_acid_amide - 1]) {
14623
    sprintf (tmp_buf, "P5O2SN00;");
14624
    strcat (out_buffer, tmp_buf);
14625
  }
14626
  if (fg[fg_phosphonic_acid_deriv - 1]) {
14627
    sprintf (tmp_buf, "P4O30000;");
14628
    strcat (out_buffer, tmp_buf);
14629
  }
14630
  if (fg[fg_phosphonic_acid - 1]) {
14631
    sprintf (tmp_buf, "P4O3H000;");
14632
    strcat (out_buffer, tmp_buf);
14633
  }
14634
  if (fg[fg_phosphonic_acid_ester - 1]) {
14635
    sprintf (tmp_buf, "P4O3C000;");
14636
    strcat (out_buffer, tmp_buf);
14637
  }
14638
  if (fg[fg_phosphine - 1]) {
14639
    sprintf (tmp_buf, "P3000000;");
14640
    strcat (out_buffer, tmp_buf);
14641
  }
14642
  if (fg[fg_phosphinoxide - 1]) {
14643
    sprintf (tmp_buf, "P2O00000;");
14644
    strcat (out_buffer, tmp_buf);
14645
  }
14646
  if (fg[fg_boronic_acid_deriv - 1]) {
14647
    sprintf (tmp_buf, "B2O20000;");
14648
    strcat (out_buffer, tmp_buf);
14649
  }
14650
  if (fg[fg_boronic_acid - 1]) {
14651
    sprintf (tmp_buf, "B2O2H000;");
14652
    strcat (out_buffer, tmp_buf);
14653
  }
14654
  if (fg[fg_boronic_acid_ester - 1]) {
14655
    sprintf (tmp_buf, "B2O2C000;");
14656
    strcat (out_buffer, tmp_buf);
14657
  }
14658
  if (fg[fg_alkene - 1]) {
14659
    sprintf (tmp_buf, "000C2C00;");
14660
    strcat (out_buffer, tmp_buf);
14661
  }
14662
  if (fg[fg_alkyne - 1]) {
14663
    sprintf (tmp_buf, "000C3C00;");
14664
    strcat (out_buffer, tmp_buf);
14665
  }
14666
  if (fg[fg_aromatic - 1]) {
14667
    sprintf (tmp_buf, "0000A000;");
14668
    strcat (out_buffer, tmp_buf);
14669
  }
14670
  if (fg[fg_heterocycle - 1]) {
14671
    sprintf (tmp_buf, "0000CZ00;");
14672
    strcat (out_buffer, tmp_buf);
14673
  }
14674
  if (fg[fg_alpha_aminoacid - 1]) {
14675
    sprintf (tmp_buf, "C3O2HN1C;");
14676
    strcat (out_buffer, tmp_buf);
14677
  }
14678
  if (fg[fg_alpha_hydroxyacid - 1]) {
14679
    sprintf (tmp_buf, "C3O2HO1H;");
14680
    strcat (out_buffer, tmp_buf);
14681
  }
6785 bpr 14682
}
14683
 
14684
/*static void mm_elab_molstat(void)
14685
{
14686
                count_neighbors();
14687
//      init_molstat(&molstat);
14688
        if (!found_arominfo) {
14689
    chk_ringbonds();
14690
    if (ringsearch_mode == rs_ssr)
14691
      remove_redundant_rings();
14692
    if (n_rings == max_rings) {
14693
      if (opt_verbose)
14694
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
14695
      ringsearch_mode = rs_ssr;
14696
      clear_rings();
14697
      max_vringsize = 10;
14698
      chk_ringbonds();
14699
      remove_redundant_rings();
14700
    }
14179 bpr 14701
 
6785 bpr 14702
    update_ringcount();
14703
    update_atypes();
14704
    update_Htotal();
14705
    chk_arom();
14706
 
14707
    if (ringsearch_mode == rs_ssr) {
14708
      do {
14709
        prev_n_ar = count_aromatic_rings();
14710
        chk_arom();
14711
        n_ar = count_aromatic_rings();
14712
      } while (prev_n_ar - n_ar != 0);
14713
    }
14714
        } else {
14715
 update_atypes();
14179 bpr 14716
    update_Htotal();
14717
 
6785 bpr 14718
        }
14179 bpr 14719
 
6785 bpr 14720
 // get_molstat();
14721
}*/
14722
 
14723
DLLEXPORT void
14724
cm_molstat_X (char *buf)
14725
{
14726
  init_molstat (&molstat);
14727
//mm_elab_molstat();
14728
  get_molstat ();
14729
  write_molstat_X_dll (buf);
14730
}
14731
 
14732
DLLEXPORT void
14733
cm_molstat (char *buf)
14734
{
14735
  init_molstat (&molstat);
14736
//mm_elab_molstat();
14737
  get_molstat ();
14738
  write_molstat_dll (buf, 0);
14739
}
14740
 
14741
DLLEXPORT void
14742
cm_molstat_sql_exact (char *buf)
14743
{
14744
  init_molstat (&molstat);
14745
//mm_elab_molstat();
14746
  get_molstat ();
14747
  write_molstat_dll (buf, 1);
14748
}
14749
 
14750
DLLEXPORT void
14751
cm_molstat_sql_substruct (char *buf)
14752
{
14753
  init_molstat (&molstat);
14754
//mm_elab_molstat();
14755
  get_molstat ();
14756
  write_molstat_dll (buf, 2);
14757
}
14758
 
14759
DLLEXPORT void
14760
cm_fg_codes (char *buf)
14761
{
14762
//mm_elab_molstat();
14763
  chk_functionalgroups ();
14764
  write_fg_code_dll (buf);
14765
}
14766
 
14179 bpr 14767
static void write_MDLmolfile_dll (char *out_buffer)
6785 bpr 14768
{
14769
  int i;
14770
  char tmpstr[256];
14771
  char wline[256];
14772
  int a_chg;
14773
  int a_iso;
14774
  int a_rad;
14775
  char tmflabel[256];           /* v0.3m */
14776
  char STR1[256], STR7[256];
14777
  int FORLIM;
14778
  *out_buffer = '\0';
14779
  *tmpstr = '\0';
14780
  *wline = '\0';
14781
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
14782
  while (strlen (tmflabel) < 2) /* v0.3m */
14783
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
14784
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
14785
  if (strlen (molname) > 80)
14786
    sprintf (molname, "%.80s", strcpy (STR1, molname));
14787
  strncat (out_buffer, molname, 80);
14788
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
14789
  if (ringsearch_mode == rs_sar)        /* v0.3m */
14790
    strcat (wline, ":r0");
14791
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
14792
    strcat (wline, ":r1");
14793
  if (opt_metalrings)
14794
    strcat (wline, ":m1");
14795
  else
14796
    strcat (wline, ":m0");
14797
  /* v0.3m */
14798
  sprintf (tmpstr, "\n%s\n", molcomment);
14799
  strcat (wline, tmpstr);
14800
  sprintf (tmpstr, "%d", n_atoms);
14801
  lblank (3L, tmpstr);
14802
  strcat (wline, tmpstr);
14803
  /* first 3 digits: number of atoms */
14804
  sprintf (tmpstr, "%d", n_bonds);
14805
  lblank (3L, tmpstr);
14806
  strcat (wline, tmpstr);
14807
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
14808
  strcpy (tmpstr, "  0");
14809
  strcat (wline, tmpstr);
14810
  /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 14811
  /* p2c: checkmol.pas, line 2388:
14812
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 14813
#ifdef REDUCED_SAR
14814
  sprintf (tmpstr, "%d", n_countablerings);
14815
  /* v0.3n; changed n_rings into n_countablerings */
14816
#else
14817
  sprintf (tmpstr, "%d", n_rings);
14818
#endif
14819
  lblank (3L, tmpstr);
14820
  strcat (wline, tmpstr);
14821
  /* officially "obsolete", we use it for the number of rings */
14822
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
14823
  if (chir_flag)
14824
    strcat (wline, "1");
14825
  else
14826
    strcat (wline, "0");
14827
  /* v0.3n */
14828
  strcat (wline, "               999 V2000\n");
14829
  /* v0.3n (adjust string length) */
14830
  strcat (out_buffer, wline);
14831
  FORLIM = n_atoms;
14179 bpr 14832
  for (i = 0; i < FORLIM; i++) {
14833
    *wline = '\0';
14834
    *tmpstr = '\0';
14835
    sprintf (tmpstr, "%1.4f", atom[i].x);
14836
    lblank (10L, tmpstr);
14837
    strcat (wline, tmpstr);
14838
    sprintf (tmpstr, "%1.4f", atom[i].y);
14839
    lblank (10L, tmpstr);
14840
    strcat (wline, tmpstr);
14841
    sprintf (tmpstr, "%1.4f", atom[i].z);
14842
    lblank (10L, tmpstr);
14843
    strcat (wline, tmpstr);
14844
    strcpy (tmpstr, atom[i].element);
14845
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
14846
    //tmpstr[0] = toupper (tmpstr[0]);
14847
    all_lowercase (tmpstr);
14848
    tmpstr[0] = toupper (tmpstr[0]);
14849
    /*wline := wline + ' '+atom^[i].element+' '; */
14850
    sprintf (wline + strlen (wline), " %s ", tmpstr);
14851
    strcat (wline, " 0");       /* mass difference (isotopes) */
14852
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
14853
    if (atom[i].arom)
14854
            strcpy (tmpstr, " 00");
14855
    else
14856
            strcpy (tmpstr, "  0");
14857
    strcat (wline, tmpstr);
14858
    strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
14859
    strcat (out_buffer, wline);
14860
  }
6785 bpr 14861
  FORLIM = n_bonds;
14179 bpr 14862
  for (i = 0; i < FORLIM; i++) {
14863
    *wline = '\0';
14864
    *tmpstr = '\0';
14865
    sprintf (tmpstr, "%d", bond[i].a1);
14866
    lblank (3L, tmpstr);
14867
    strcat (wline, tmpstr);
14868
    sprintf (tmpstr, "%d", bond[i].a2);
14869
    lblank (3L, tmpstr);
14870
    strcat (wline, tmpstr);
14871
    if (bond[i].btype == 'S')
14872
            strcpy (tmpstr, "  1");
14873
    if (bond[i].btype == 'D')
14874
            strcpy (tmpstr, "  2");
14875
    if (bond[i].btype == 'T')
14876
            strcpy (tmpstr, "  3");
14877
    if (bond[i].btype == 'A')
14878
            strcpy (tmpstr, "  4");
14879
    if (bond[i].btype == 'l')
14880
            strcpy (tmpstr, "  5");
14881
    if (bond[i].btype == 's')
14882
            strcpy (tmpstr, "  6");
14883
    if (bond[i].btype == 'd')
14884
            strcpy (tmpstr, "  7");
14885
    if (bond[i].btype == 'a')
14886
            strcpy (tmpstr, "  8");
14887
        /* now encode our own aromaticity information */
14888
    if (bond[i].arom)
14889
            tmpstr[1] = '0';
14890
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
14891
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
14892
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
14893
    /*    wline := wline + '  0'; */
14894
    /* restore original value from MDL molfile (v0.3n) */
14895
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
14896
    *tmpstr = '\0';
14897
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
14898
    strcat (wline, "  ");
14899
    strcat (wline, tmpstr);
14900
    *tmpstr = '\0';
14901
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
14902
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
14903
    sprintf (tmpstr, "%i", bond[i].ring_count);
14904
    while (strlen (tmpstr) < 3)
14905
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
14906
    sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
14907
    strcat (out_buffer, wline);
14908
  }
6785 bpr 14909
  FORLIM = n_atoms;
14179 bpr 14910
  for (i = 1; i <= FORLIM; i++) {
14911
    a_chg = atom[i - 1].formal_charge;
14912
    if (a_chg != 0) {
14913
            strcpy (wline, "M  CHG  1 ");
14914
            sprintf (tmpstr, "%d", i);
14915
            lblank (3L, tmpstr);
14916
            sprintf (wline + strlen (wline), "%s ", tmpstr);
14917
            sprintf (tmpstr, "%d", a_chg);
14918
            lblank (3L, tmpstr);
14919
            strcat (wline, tmpstr);
14920
            strcat (out_buffer, wline);
14921
            strcat (out_buffer, "\n");
14922
          }
14923
  }
14924
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
14925
    a_iso = atom[i - 1].nucleon_number;
14926
    if (a_iso != 0) {
14927
            strcpy (wline, "M  ISO  1 ");
14928
            sprintf (tmpstr, "%d", i);
14929
            lblank (3L, tmpstr);
14930
            sprintf (wline + strlen (wline), "%s ", tmpstr);
14931
            sprintf (tmpstr, "%d", a_iso);
14932
            lblank (3L, tmpstr);
14933
            strcat (wline, tmpstr);
14934
            strcat (out_buffer, wline);
14935
            strcat (out_buffer, "\n");
14936
          }
14937
  }
14938
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
14939
    a_rad = atom[i - 1].radical_type;
14940
    if (a_rad != 0) {
14941
            strcpy (wline, "M  RAD  1 ");
14942
            sprintf (tmpstr, "%d", i);
14943
            lblank (3L, tmpstr);
14944
            sprintf (wline + strlen (wline), "%s ", tmpstr);
14945
            sprintf (tmpstr, "%d", a_rad);
14946
            lblank (3L, tmpstr);
14947
            strcat (wline, tmpstr);
14948
            strcat (out_buffer, wline);
14949
            strcat (out_buffer, "\n");
14950
          }
14951
  }
6785 bpr 14952
  strcat (out_buffer, "M  END\n");
14953
}
14954
 
17891 bpr 14955
DLLEXPORT void cm_tweak_molfile (char *buf)
6785 bpr 14956
{
14957
//chk_functionalgroups();
14958
  write_MDLmolfile_dll (buf);
14959
}
14960
#endif