Subversion Repositories wimsdev

Rev

Rev 6788 | Rev 11128 | Go to most recent revision | 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
7
 
8
   compile with gcc without optimizations (except -march= -mcpu=) or it gets SLOWER!
9
 
10
   THIS VERSION HAS extended_molstat SWITCHED ON BY DEFAULT!
11
 
12
   This file is part of the xchem::tigress project.
13
 
14
   --- DUAL LICENSING ---
15
 
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!
19
 
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.
23
 
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.
28
 
29
   --- DUAL LICENSING ---
30
 
31
   ORIGINAL HEADER:
32
 
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
 
56
Compile with fpc (Free Pascal, see http://www.freepascal.org), using
57
the -Sd or -S2 option (Delphi mode; IMPORTANT!)
58
 
59
example for compilation (with optimization) and installation:
60
 
61
fpc checkmol.pas -S2 -Xs -OG -Or -O2u -Op1
62
 
63
as "root", do the following:
64
 
65
cp checkmol /usr/local/bin
66
cd /usr/local/bin
67
ln checkmol matchmol
68
 
69
 
70
Version history
71
 
72
v0.1   extends "chkmol" utility (N. Haider, 2002), adds matching functionality;
73
 
74
v0.1a  minor bugfixes:
75
       stop ring search when max_rings is reached (function is_ringpath);
76
       fixed upper/lowercase of element symbol in MDL molfile output;
77
       added debug output for checkmol (-D option)
78
 
79
v0.2   added functionality to switch ring search from SAR (set of all rings) to
80
       SSR (set of small rings; see below) if number of rings exceeds max_rings
81
       (1024), e.g. with Buckminster-fullerenes (thanks to E.-G. Schmid for a hint);
82
       added -r command-line option to force ring search into SSR mode;
83
       as SSR, we regard the set of all rings with max. 10 ring members, and in
84
       which no ring is completely contained in another one
85
 
86
v0.2a  fixed a bug in function is_ringpath which could cause SAR ring search to
87
       overlook a few rings (e.g., the six 8-membered rings in cubane)
88
 
89
v0.2b  fixed unequal treatment of needle and haystack structures with respect
90
       to aromaticity check (trusting input file vs. full check)
91
 
92
v0.2c  modified the changes of v0.2b so that they affect only "matchmol" mode;
93
       added quick_match function
94
 
95
v0.2d  refined function bondtypes_OK so that it does not accept C=O fragments
96
       (and C=S, C=Se, C=Te) as equivalent to aromatic C-O (C-S, C-Se, C-Te);
97
       fixed function find_ndl_ref_atom to use only heavy atoms as "needle"
98
       reference atoms for atom-to-atom match; update function quick_match to
99
       handle queries with only one heavy atom (thanks to A. Barozza for a hint)
100
 
101
v0.2e  modified procedure get_molstat: adds 1 formal double bond for each aromatic
102
       ring to the "fingerprint" in order to allow an isolated double bond in the
103
       needle to be matched as a fragment of an aromatic ring
104
       ATTENTION: "fingerprints" (molecular statistics) generated with a previous
105
       version of checkmol(-x and -X option) must be updated for structure/
106
       substructure database searching with matchmaol.
107
 
108
v0.2f  modified procedures chk_ccx, chk_xccx, write_fg_text, write_fg_text_de,
109
       write_fg_code in order to report halogen derivatives other than alkyl halides,
110
       aryl halides and acyl halides (e.g., vinyl halides) and C=C compounds other
111
       than "true" alkenes, enols, enediols, enamines, etc. (e.g. vinyl halides);
112
       added "strict mode" (option -s) for matching: this uses a more thorough
113
       comparison of atom types and bond types (new functions atomtypes_OK_strict,
114
       bondtypes_OK_strict, several minor modifications in other subroutines).
115
 
116
v0.2g  changed procedure readinputfile (+ minor changes in main routine) in
117
       order to read very large SD input files without "not enough memory" error
118
       (the previous version attempted to read the entire SD file into a buffer,
119
       the new version reads only one molecule at once);
120
       fixed a minor bug in read_mol2file which led to undefined bond types;
121
       added definition of "debug" option as a compiler flag.
122
 
123
v0.2h  fixed a small bug which caused program hangs with (e.g.) some metal
124
       complexes: this was solved just by increasing the number of possible
125
       neighbor atoms from 8 to 16 (now defined in the constant max_neighbors).
126
 
127
v0.2i  introduced some more plausibility checking (number of directly connected
128
       atoms), result stored in variable mol_OK (set in count_neighbors);
129
       completely rewrote function matrix_OK which now can handle up to
130
       max_neighbors substituents per atom (previous versions were limited to
131
       4 substituents; larger numbers are required e.g. for ferrocenes and
132
       similar compounds).
133
 
134
v0.2j  new function raw_hetbond_count: ignores bond order (in contrast to function
135
       hetbond_count), this is better suitable for molecular statistics.
136
       ATTENTION: previously generated "fingerprints" in databases must be updated!
137
       improved recognition of non-conformant SD files (with missing "M  END" line)
138
 
139
v0.2k  changed quick_match routine to compare atom types only by element in
140
       order to avoid (rare) cases of non-matching identical input files;
141
       slightly changed error message for non-existant input files
142
 
143
v0.3   changed function update_Htotal in order to distinguish between 3-valent
144
       and 5-valent phosphorus (thanks to H. Feldman for this suggestion);
145
       added a table (array ringprop) to store ring sizes and aromaticity for
146
       faster lookup; changed aromaticity detection (chk_arom) to be fully
147
       independent of Kekule structures in condensed ring systems; changed add_ring
148
       to store new rings in ascending order (with respect to ring size): this
149
       will cause the aromaticity detection to start with smaller rings;
150
       added additional calls to chk_arom when in SSR ring search mode (to ensure
151
       that all aromatic rings are found); speeded up function is_newring;
152
       added option "-M": this restores the behavior of previous versions,
153
       i.e. metal atoms will be accepted as ring members (which costs a lot
154
       of performance for coordinate compounds like ferrocenes but gives
155
       only little useful information); when used in databases: use the _same_
156
       mode ("-M" or not) _both_ for checkmol (creation of fingerprints) and matchmol;
157
       fixed ugly linebreaks in show_usage;
158
 
159
v0.3a  fixed a bug in read_charges (which was introduced in the v0.3 code cleanup)
160
 
161
v0.3b  fixed recognition of ketenes, CO2, CS2, CSO, phosphines, boronic esters
162
 
163
v0.3c  fixed recognition of hydrazines, hydroxylamines, thiocarboxylic acids,
164
       orthocarboxylic acids; slightly changed textual output for a few functional
165
       groups
166
 
167
v0.3d  added bond topology feature ("any", "ring", "chain", as defined by MDL specs,
168
       plus "always_any", "excess-ringcount", "exact-ringcount") to bond properties
169
       and implemented its use for substructure searches, either as specified in the
170
       query MDL molfile or by using "strict" mode; added ring_count property to
171
       "bonds" section of Checkmol-tweaked molfiles (using an unused field in the MDL
172
       molfile specs);
173
       added option for E/Z isomer search, either globally (-g option) or per
174
       double bond: bstereo_xyz property, encoded either by a leading "0" in the
175
       bond block of a checkmol-tweaked molfile or by using the "stereo care" flag
176
       as defined in the MDL file specs (both atoms of a double bond must carry
177
       this flag)
178
 
179
v0.3e  fixed wrong position of "stereo care" flag expected in input molfile;
180
 
181
v0.3f  added option for enantiospecific search (R/S isomer search); this can be
182
       turned on either globally (-G option or using the "chiral" flag in the
183
       "counts line" of the query MDL molfile) or per atom (using - or abusing -
184
       the "stereo care" flag); enantiomers are compared using the 3D coordinates
185
       of the substituents at a chiral center, so we do not have to rely on the
186
       presence of correct "up" and "down" bond types in the candidate structures;
187
       nevertheless, "pseudo-3D" structures (i.e. flat 2D structures with "up"
188
       and "down" bond notation) can be also used, even in mixed mode both as
189
       query structure and candidate structure; added support for "up" and "down"
190
       bond notation in MDL molfile output (if -m option is used and these bond
191
       types were present in the input file); refined function find_ndl_ref_atom;
192
       fixed Alchemy atom type misinterpretation (upper/lower case mismatch);
193
 
194
v0.3g  minor fixes: recognition of sp2 nitrogen in N=N structures (function
195
       update_atypes); extended E/Z geometry check to C=N and N=N bonds; accelerated
196
       exact search by initial comparison of C,O,N counts; added meaningful error
197
       message for input structures with 0 (zero) atoms;
198
 
199
v0.3h  added a match matrix clean-up step to function is_matching in order to
200
       remove "impossible" multiple matches prior to chirality check; added
201
       function ndl_maybe_chiral as a plausibility check; added support for other
202
       atoms than carbon as chiral centers; changed function is_cis from a
203
       distance-based cis/trans check into a torsion-based check;
204
 
205
v0.3i  minor fixes in functions max_neighbors and chk_ammon;
206
       revert ringsearch_mode to its original value for each new molecule
207
       (main routine)
208
 
209
v0.3j  various improvements in checkmol: added alkenyl (vinyl) and alkynyl
210
       residues as possible substituents for amides, esters, ethers, etc.;
211
       extended recognition of orthocarboxylic acid derivatives; refined
212
       recognition of oxohetarenes and iminohetareenes, ureas, nitroso
213
       compounds; fixed reading of "old-style" charges from MDL files;
214
       refined aromaticity check; fixed a bug in procedure chk_arom and
215
       renamed function is_exocyclic_methylene_C into
216
       find_exocyclic_methylene_C; added assignment of pointers to "nil"
217
       after calling "freemem" in procedure zap_molecule and zap_needle;
218
       matchmol: refined selection of needle reference atom; added "strict
219
       chirality check" mode (if -x -s and -G options are used): returns
220
       "false" if a chiral or pseudochiral atom is matched against its
221
       counterpart with undefined or "flat" geometry; added an alternative
222
       selection mechanism for the needle reference atom, based on the
223
       Morgan algorithm;
224
 
225
v0.3k  improved matching of nitro compounds (ionic vs. non-ionic
226
       representation); some finetuning in recognition of N-oxides,
227
       hydroxylamines, etc.; modified get_molstat in order to ignore
228
       charges in nitro groups, N-oxides, sulfoxides, azides, etc. in
229
       ionic representation; added function normalize_ionic_bonds;
230
       fixed a bug in is_alkenyl; fixed a bug (introduced in v0.3j) in
231
       the treatment of "old-style" MDL charges;
232
 
233
v0.3l  minor adjustments in quick_match (for unknown atom types,
234
       opposite charges); some performance improvements, e.g. in function
235
       path_pos, reduced extensive calls to is_heavyatom and is_metal
236
       by extending atom_rec with boolean fields 'heavy' and 'metal'
237
       (thanks to E.-G.Schmid); added molstat field n_rBz (number of
238
       benzene rings; deactivated by default); added -l command-line
239
       option to checkmol (lists all molstat codes with a short
240
       explanation); added graceful handling of NoStruct (i.e.,
241
       zero-atom) molecules
242
 
243
v0.3m  minor bug fixes (chk_imine), let normalize_ionic_bonds return "true"
244
       if some bond-order change was made; fixed incorrect implementation
245
       of the Morgan algorithm (thanks to H.Feldman), fixed is_matching in
246
       order to prevent wrong matches of larger rings on smaller ones; count
247
       halogens also as type "X" in molstat (as before v0.3l); added some more
248
       molstat descriptors for most elements (deactivated by default; for
249
       activation, uncomment the definition of "extended_molstat", see below);
250
       added support for the generation of binary fingerprints with output
251
       either as boolean values (-f option) or as decimal values (-F option),
252
       fingerprint patterns are supplied by the user (in SDF format, max. 62
253
       structures per file); added a version check ("tweaklevel",
254
       ringsearch_mode, opt_metalrings) for "tweaked" MDL molfiles
255
 
256
v0.3n  increased max_vringsize in SSR mode from 10 to 12 (now defined in
257
       ssr_vringsize); optionally changed ring statistics to ignore envelope
258
       rings (which completely contain another ring, "reduced SAR") in order to
259
       make molstat in SAR and SSR mode more compatible) - disabled by default;
260
       introduced a new molstat descriptor: n_br2p (number of bonds which
261
       belong to two or more rings); changed n_b1 counter to ignore bonds to
262
       explicit hydrogens; added procedure fix_ssr_ringcounts
263
       (see comment in the code); added bond property mdl_stereo for preservation
264
       of original value; slightly changed "get_molstat" and "update_atypes" in
265
       order to consolidate atom type for various N atoms; remember "chiral" flag
266
       status in molfile output (-m); modified chk_arom in order to accept rings
267
       as aromatic if all bonds are of type 'A'; several minor bug fixes
268
 
269
v0.3o  minor changes in update_atypes (nitrogen); changed the matching
270
       algorithm in order to take care of disconnected molecular graphs
271
       (e.g., salts); refined matching of atoms with formal charges
272
 
273
 
274
Credits:
275
 
276
Rami Jbara (rami_jbara@hotmail.com) designed the 8-character functional
277
group codes.
278
 
279
I am also very grateful to Ernst-Georg Schmid (Bayer Business Services,
280
Leverkusen/Germany) and to Howard Feldman (The Blueprint Initiative,
281
Toronto/Canada) for numerous bug reports and suggestions for improvements.
282
 
283
 
284
 
285
===============================================================================
286
DISCLAIMER
287
This program is free software; you can redistribute it and/or
288
modify it under the terms of the GNU General Public License
289
as published by the Free Software Foundation; either version 2
290
of the License, or (at your option) any later version.
291
 
292
This program is distributed in the hope that it will be useful,
293
but WITHOUT ANY WARRANTY; without even the implied warranty of
294
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
295
GNU General Public License for more details.
296
 
297
You should have received a copy of the GNU General Public License
298
along with this program; if not, write to the Free Software Foundation,
299
Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
300
===============================================================================
301
*/
302
 
303
/* $DEFINE debug                    uncomment if desired */
304
/* $DEFINE extended_molstat         uncomment if desired */
305
/* $DEFINE reduced_SAR              uncomment if desired */
306
 
307
/* uses
308
  SYSUTILS, MATH; */
309
 
310
#include <stdlib.h>
311
#include <stdio.h>
312
#include <math.h>
313
#include <string.h>
314
#include <ctype.h>
315
#include <sys/types.h>
316
#include <sys/stat.h>
317
#include "safemem.h"
318
#ifdef MAKE_SHARED_LIBRARY
319
#include "barsoi.h"
320
#endif
321
 
322
#ifdef MAKE_SHARED_LIBRARY
323
#define version         "0.3p C (pgchem::barsoi)"
324
#else
325
#define version         "0.3p C"
326
#endif
327
 
328
#undef REDUCED_SAR
329
 
330
/* How many recursions before aborting is_ringpath and reverting to SSR */
331
#define max_ringpath_recursion_depth   500000
332
 
333
/* How many recursions before aborting is_match and reverting to non-exhaustive match */
334
#define max_match_recursion_depth   500000
335
 
336
#define tweaklevel      2
337
    /* v0.3m; accept tweaks in MDL molfiles only if same level */
338
#define max_atoms       1024
339
#define max_bonds       1024
340
#define slack           8192
341
#define max_ringsize    128
342
#define max_rings       1024
343
#define max_fg          256
344
#define max_neighbors   16      /* new in v0.2h */
345
 
346
#define TAB             '\t'
347
 
348
#define max_matchpath_length  256
349
#define pmCheckMol      1001
350
#define pmMatchMol      1002
351
 
352
#define rs_sar          2001    /* ring search mode: SAR = set of all rings */
353
#define rs_ssr          2002
354
    /*                   SSR = set of small rings */
355
 
356
#define btopo_any       0       /* bond topology, new in v0.3d */
357
#define btopo_ring      1
358
#define btopo_chain     2
359
#define btopo_always_any  3     /* even in "strict mode" */
360
#define btopo_excess_rc  4
361
/* bond in candidate must be included in _more_ rings than
362
                        the matching bond in the query ==> specific search for
363
                        annulated systems */
364
#define btopo_exact_rc  5
365
    /* bond in query and candidate must have same ring count */
366
 
367
#define bstereo_any     0
368
    /* new in v0.3d, any E/Z isomer matches (for double bonds) */
369
#define bstereo_xyz     1
370
    /* E/Z match is checked by using XYZ coordinates of the atoms */
371
#define bstereo_up      11      /* new in v0.3f, flags for single bonds */
372
#define bstereo_down    16
373
#define bstereo_either    14    /* 0.3x */
374
#define bstereo_double_either    13     /* 0.3x */
375
 
376
#define fpf_boolean     3001
377
    /* v0.3m; format for fingerprint output (n:T, n:F) */
378
#define fpf_decimal     3002
379
    /* v0.3m; format for fingerprint output as decimal value of bitstring */
380
#define fp_blocksize    62
381
    /* v0.3m; 1 bit may be used for sign (e.g. by PHP), 1 bit for "exact hit" */
382
#define ssr_vringsize   12      /* v0.3n; max. ring size in SSR mode */
383
 
384
/* Definitions for functional groups: */
385
#define fg_cation       1
386
#define fg_anion        2
387
#define fg_carbonyl     3
388
#define fg_aldehyde     4
389
#define fg_ketone       5
390
#define fg_thiocarbonyl  6
391
#define fg_thioaldehyde  7
392
#define fg_thioketone   8
393
#define fg_imine        9
394
#define fg_hydrazone    10
395
#define fg_semicarbazone  11
396
#define fg_thiosemicarbazone  12
397
#define fg_oxime        13
398
#define fg_oxime_ether  14
399
#define fg_ketene       15
400
#define fg_ketene_acetal_deriv  16
401
#define fg_carbonyl_hydrate  17
402
#define fg_hemiacetal   18
403
#define fg_acetal       19
404
#define fg_hemiaminal   20
405
#define fg_aminal       21
406
#define fg_thiohemiaminal  22
407
#define fg_thioacetal   23
408
#define fg_enamine      24
409
#define fg_enol         25
410
#define fg_enolether    26
411
#define fg_hydroxy      27
412
#define fg_alcohol      28
413
#define fg_prim_alcohol  29
414
#define fg_sec_alcohol  30
415
#define fg_tert_alcohol  31
416
#define fg_1_2_diol     32
417
#define fg_1_2_aminoalcohol  33
418
#define fg_phenol       34
419
#define fg_1_2_diphenol  35
420
#define fg_enediol      36
421
#define fg_ether        37
422
#define fg_dialkylether  38
423
#define fg_alkylarylether  39
424
#define fg_diarylether  40
425
#define fg_thioether    41
426
#define fg_disulfide    42
427
#define fg_peroxide     43
428
#define fg_hydroperoxide  44
429
#define fg_hydrazine    45
430
#define fg_hydroxylamine  46
431
#define fg_amine        47
432
#define fg_prim_amine   48
433
#define fg_prim_aliph_amine  49
434
#define fg_prim_arom_amine  50
435
#define fg_sec_amine    51
436
#define fg_sec_aliph_amine  52
437
#define fg_sec_mixed_amine  53
438
#define fg_sec_arom_amine  54
439
#define fg_tert_amine   55
440
#define fg_tert_aliph_amine  56
441
#define fg_tert_mixed_amine  57
442
#define fg_tert_arom_amine  58
443
#define fg_quart_ammonium  59
444
#define fg_n_oxide      60
445
#define fg_halogen_deriv  61
446
#define fg_alkyl_halide  62
447
#define fg_alkyl_fluoride  63
448
#define fg_alkyl_chloride  64
449
#define fg_alkyl_bromide  65
450
#define fg_alkyl_iodide  66
451
#define fg_aryl_halide  67
452
#define fg_aryl_fluoride  68
453
#define fg_aryl_chloride  69
454
#define fg_aryl_bromide  70
455
#define fg_aryl_iodide  71
456
#define fg_organometallic  72
457
#define fg_organolithium  73
458
#define fg_organomagnesium  74
459
#define fg_carboxylic_acid_deriv  75
460
#define fg_carboxylic_acid  76
461
#define fg_carboxylic_acid_salt  77
462
#define fg_carboxylic_acid_ester  78
463
#define fg_lactone      79
464
#define fg_carboxylic_acid_amide  80
465
#define fg_carboxylic_acid_prim_amide  81
466
#define fg_carboxylic_acid_sec_amide  82
467
#define fg_carboxylic_acid_tert_amide  83
468
#define fg_lactam       84
469
#define fg_carboxylic_acid_hydrazide  85
470
#define fg_carboxylic_acid_azide  86
471
#define fg_hydroxamic_acid  87
472
#define fg_carboxylic_acid_amidine  88
473
#define fg_carboxylic_acid_amidrazone  89
474
#define fg_nitrile      90
475
#define fg_acyl_halide  91
476
#define fg_acyl_fluoride  92
477
#define fg_acyl_chloride  93
478
#define fg_acyl_bromide  94
479
#define fg_acyl_iodide  95
480
#define fg_acyl_cyanide  96
481
#define fg_imido_ester  97
482
#define fg_imidoyl_halide  98
483
#define fg_thiocarboxylic_acid_deriv  99
484
#define fg_thiocarboxylic_acid  100
485
#define fg_thiocarboxylic_acid_ester  101
486
#define fg_thiolactone  102
487
#define fg_thiocarboxylic_acid_amide  103
488
#define fg_thiolactam   104
489
#define fg_imido_thioester  105
490
#define fg_oxohetarene  106
491
#define fg_thioxohetarene  107
492
#define fg_iminohetarene  108
493
#define fg_orthocarboxylic_acid_deriv  109
494
#define fg_carboxylic_acid_orthoester  110
495
#define fg_carboxylic_acid_amide_acetal  111
496
#define fg_carboxylic_acid_anhydride  112
497
#define fg_carboxylic_acid_imide  113
498
#define fg_carboxylic_acid_unsubst_imide  114
499
#define fg_carboxylic_acid_subst_imide  115
500
#define fg_co2_deriv    116
501
#define fg_carbonic_acid_deriv  117
502
#define fg_carbonic_acid_monoester  118
503
#define fg_carbonic_acid_diester  119
504
#define fg_carbonic_acid_ester_halide  120
505
#define fg_thiocarbonic_acid_deriv  121
506
#define fg_thiocarbonic_acid_monoester  122
507
#define fg_thiocarbonic_acid_diester  123
508
#define fg_thiocarbonic_acid_ester_halide  124
509
#define fg_carbamic_acid_deriv  125
510
#define fg_carbamic_acid  126
511
#define fg_carbamic_acid_ester  127
512
#define fg_carbamic_acid_halide  128
513
#define fg_thiocarbamic_acid_deriv  129
514
#define fg_thiocarbamic_acid  130
515
#define fg_thiocarbamic_acid_ester  131
516
#define fg_thiocarbamic_acid_halide  132
517
#define fg_urea         133
518
#define fg_isourea      134
519
#define fg_thiourea     135
520
#define fg_isothiourea  136
521
#define fg_guanidine    137
522
#define fg_semicarbazide  138
523
#define fg_thiosemicarbazide  139
524
#define fg_azide        140
525
#define fg_azo_compound  141
526
#define fg_diazonium_salt  142
527
#define fg_isonitrile   143
528
#define fg_cyanate      144
529
#define fg_isocyanate   145
530
#define fg_thiocyanate  146
531
#define fg_isothiocyanate  147
532
#define fg_carbodiimide  148
533
#define fg_nitroso_compound  149
534
#define fg_nitro_compound  150
535
#define fg_nitrite      151
536
#define fg_nitrate      152
537
#define fg_sulfuric_acid_deriv  153
538
#define fg_sulfuric_acid  154
539
#define fg_sulfuric_acid_monoester  155
540
#define fg_sulfuric_acid_diester  156
541
#define fg_sulfuric_acid_amide_ester  157
542
#define fg_sulfuric_acid_amide  158
543
#define fg_sulfuric_acid_diamide  159
544
#define fg_sulfuryl_halide  160
545
#define fg_sulfonic_acid_deriv  161
546
#define fg_sulfonic_acid  162
547
#define fg_sulfonic_acid_ester  163
548
#define fg_sulfonamide  164
549
#define fg_sulfonyl_halide  165
550
#define fg_sulfone      166
551
#define fg_sulfoxide    167
552
#define fg_sulfinic_acid_deriv  168
553
#define fg_sulfinic_acid  169
554
#define fg_sulfinic_acid_ester  170
555
#define fg_sulfinic_acid_halide  171
556
#define fg_sulfinic_acid_amide  172
557
#define fg_sulfenic_acid_deriv  173
558
#define fg_sulfenic_acid  174
559
#define fg_sulfenic_acid_ester  175
560
#define fg_sulfenic_acid_halide  176
561
#define fg_sulfenic_acid_amide  177
562
#define fg_thiol        178
563
#define fg_alkylthiol   179
564
#define fg_arylthiol    180
565
#define fg_phosphoric_acid_deriv  181
566
#define fg_phosphoric_acid  182
567
#define fg_phosphoric_acid_ester  183
568
#define fg_phosphoric_acid_halide  184
569
#define fg_phosphoric_acid_amide  185
570
#define fg_thiophosphoric_acid_deriv  186
571
#define fg_thiophosphoric_acid  187
572
#define fg_thiophosphoric_acid_ester  188
573
#define fg_thiophosphoric_acid_halide  189
574
#define fg_thiophosphoric_acid_amide  190
575
#define fg_phosphonic_acid_deriv  191
576
#define fg_phosphonic_acid  192
577
#define fg_phosphonic_acid_ester  193
578
#define fg_phosphine    194
579
#define fg_phosphinoxide  195
580
#define fg_boronic_acid_deriv  196
581
#define fg_boronic_acid  197
582
#define fg_boronic_acid_ester  198
583
#define fg_alkene       199
584
#define fg_alkyne       200
585
#define fg_aromatic     201
586
#define fg_heterocycle  202
587
#define fg_alpha_aminoacid  203
588
#define fg_alpha_hydroxyacid  204
589
 
590
typedef enum
591
{ false = 0, true } boolean;
592
 
593
 
594
typedef char str2[3];
595
 
596
typedef char str3[4];
597
 
598
typedef char str4[5];
599
 
600
typedef char str5[6];
601
 
602
typedef char str8[9];
603
 
604
typedef struct atom_rec
605
{
606
  str2 element;
607
  str3 atype;
608
  float x, y, z;
609
  int formal_charge;
610
  float real_charge;
611
  int Hexp;                     /* explicit H count */
612
  int Htot;                     /* total H count */
613
  int neighbor_count, ring_count;
614
  boolean arom, stereo_care;    /* new in v0.3d */
615
  boolean q_arom;               // v0.3p potentially aromatic in a query structure
616
  boolean heavy;                /* new in v0.3l */
617
  boolean metal;                /* new in v0.3l */
618
  int nvalences;                /* new in v0.3m */
619
  boolean tag;                  /* new in v0.3o */
620
  int nucleon_number;           /* 0.3.x */
621
  int radical_type;             /* 0.3.x */
622
} atom_rec;
623
 
624
typedef struct bond_rec
625
{
626
  int a1, a2;
627
  char btype;
628
  int ring_count;
629
  boolean arom;
630
  boolean q_arom;               // v0.3p potentially aromatic in a query structure
631
  int topo;                     /* new in v0.3d, see MDL file description */
632
  int stereo;                   /* new in v0.3d */
633
  int mdl_stereo;               /* new in v0.3n */
634
} bond_rec;
635
 
636
typedef int ringpath_type[max_ringsize];
637
typedef int matchpath_type[max_matchpath_length];
638
 
639
typedef atom_rec atomlist[max_atoms];
640
typedef bond_rec bondlist[max_bonds];
641
typedef ringpath_type ringlist[max_rings];
642
typedef int neighbor_rec[max_neighbors];        /* new in v0.2h */
643
typedef boolean fglist[max_fg];
644
 
645
typedef char molbuftype[max_atoms + max_bonds + slack][256];
646
 
647
typedef boolean matchmatrix[max_neighbors][max_neighbors];
648
    /* new in v0.2i */
649
 
650
typedef struct molstat_rec
651
{
652
  int n_QA, n_QB, n_chg;        /* number of query atoms, query bonds, charges */
653
  int n_C1, n_C2, n_C;
654
  /* number of sp, sp2 hybridized, and total no. of carbons */
655
  int n_CHB1p, n_CHB2p, n_CHB3p, n_CHB4;
656
  /* number of C atoms with at least 1, 2, 3 hetero bonds */
657
  int n_O2, n_O3;               /* number of sp2 and sp3 oxygens */
658
  int n_N1, n_N2, n_N3;         /* number of sp, sp2, and sp3 nitrogens */
659
  int n_S, n_SeTe;
660
  /* number of sulfur atoms and selenium or tellurium atoms */
661
  int n_F, n_Cl, n_Br, n_I;
662
  /* number of fluorine, chlorine, bromine, iodine atoms */
663
  int n_P, n_B;                 /* number of phosphorus and boron atoms */
664
  int n_Met, n_X;
665
  /* number of metal and "other" atoms (not listed elsewhere); v0.3l */
666
  int n_b1, n_b2, n_b3, n_bar;
667
  /* number single, double, triple, and aromatic bonds */
668
  int n_C1O, n_C2O, n_CN, n_XY;
669
  /* number of C-O single bonds, C=O double bonds, CN bonds (any type), hetero/hetero bonds */
670
  int n_r3, n_r4, n_r5, n_r6, n_r7, n_r8;
671
  /* number of 3-, 4-, 5-, 6-, 7-, and 8-membered rings */
672
  int n_r9, n_r10, n_r11, n_r12, n_r13p;
673
  /* number of 9-, 10-, 11-, 12-, and 13plus-membered rings */
674
  int n_rN, n_rN1, n_rN2, n_rN3p;
675
  /* number of rings containing N (any number), 1 N, 2 N, and 3 N or more */
676
  int n_rO, n_rO1, n_rO2p;
677
  /* number of rings containing O (any number), 1 O, and 2 O or more */
678
  int n_rS, n_rX, n_rAr, n_rBz;
679
  /* number of rings containing S (any number), any heteroatom (any number),  */
680
  /* number of aromatic rings, number of benzene rings */
681
  int n_br2p;                   /* number of bonds belonging to more than one ring (v0.3n) */
682
/* p2c: checkmol.pas, line 590:
683
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
684
  /*$IFDEF extended_molstat */
685
  int n_psg01, n_psg02, n_psg13, n_psg14;
686
  /* number of atoms belonging to elements of group 1, 2, etc.  */
687
  int n_psg15, n_psg16, n_psg17, n_psg18;
688
  /* number of atoms belonging to elements of group 15, 16, etc.  */
689
  int n_pstm, n_psla;
690
  /* number of transition metals, lanthanides/actinides */
691
  int n_iso, n_rad;
692
  /* number of isotopes, radicals */
693
  /*$ENDIF */
694
} molstat_rec;
695
 
696
typedef struct ringprop_rec
697
{
698
  /* new in v0.3 */
699
  int size;
700
  boolean arom, envelope;
701
} ringprop_rec;
702
 
703
typedef ringprop_rec ringprop_type[max_rings];
704
 
705
typedef struct p_3d
706
{
707
  /* new in v0.3d */
708
  double x, y, z;
709
} p_3d;
710
 
711
typedef int chirpath_type[4];   /* new in v0.3f */
712
 
713
#ifdef MAKE_SHARED_LIBRARY
714
static boolean yet_initialized = false;
715
#endif
716
 
717
typedef struct connval_rec
718
{
719
  /* new in v0.3j */
720
  int def;                      /* better as longint for large molecules? */
721
  int tmp;
722
} connval_rec;
723
 
724
typedef connval_rec connval_type[max_atoms];    /* new in v0.3j  */
725
 
726
 
727
static int progmode;
728
static char progname[256];
729
 
730
#ifndef MAKE_SHARED_LIBRARY
731
static int i;                   /* general purpose index */
732
#endif
733
 
734
static int li;
735
static boolean opt_none, opt_verbose, opt_text, opt_text_de, opt_code,
736
  opt_bin, opt_bitstring, opt_stdin, opt_exact, opt_debug,
737
  opt_molout, opt_molstat, opt_molstat_X, opt_xmdlout, opt_strict;
738
    /* new in v0.2f */
739
static boolean opt_metalrings;  /* new in v0.3 */
740
static boolean opt_geom;        /* new in v0.3d */
741
static boolean opt_chiral;      /* new in v0.3f */
742
static boolean opt_iso;         /* new in v0.3x */
743
static boolean opt_chg;         /* new in v0.3x */
744
static boolean opt_rad;         /* new in v0.3x */
745
static int opt_rs;              /* new in v0.3i */
746
 
747
#ifdef MAKE_SHARED_LIBRARY
748
static int opt_rs_dll = RPA_DEFAULT;
749
#endif
750
 
751
static boolean opt_fp;          /* new in v0.3m */
752
static int fpformat;            /* new in v0.3m */
753
static char filetype[256];
754
/*molfile : text; */
755
static char molfilename[256];
756
static char ndl_molfilename[256];
757
static char molname[256];
758
static char ndl_molname[256];
759
static char tmp_molname[256];   /* v0.3m */
760
static char molcomment[256];
761
static int n_atoms, n_bonds, n_rings;
762
    /* the number of rings we determined ourselves */
763
static int n_countablerings;
764
    /* v0.3n; number of rings which are not envelope rings */
765
static int n_cmrings;
766
    /* the number of rings we read from a (CheckMol-tweaked) MDL molfile */
767
//static int n_charges;         /* number of charges */
768
static int n_heavyatoms, n_heavybonds, ndl_n_atoms, ndl_n_bonds, ndl_n_rings,
769
  ndl_n_heavyatoms, ndl_n_heavybonds;
770
/*cm_mdlmolfile  : boolean; */
771
static boolean found_arominfo, found_querymol, ndl_querymol;
772
static int tmp_n_atoms;         /* v0.3m */
773
static int tmp_n_bonds;         /* v0.3m */
774
static int tmp_n_rings;         /* v0.3m */
775
static int tmp_n_heavyatoms;    /* v0.3m */
776
static int tmp_n_heavybonds;    /* v0.3m */
777
 
778
static atom_rec *atom;
779
static bond_rec *bond;
780
static ringpath_type *ring;
781
static ringprop_rec *ringprop;  /* new in v0.3 */
782
 
783
static atom_rec *ndl_atom;
784
static bond_rec *ndl_bond;
785
static ringpath_type *ndl_ring;
786
static ringprop_rec *ndl_ringprop;      /* new in v0.3 */
787
static int ndl_ref_atom;        /* since v0.3j as a global variable */
788
static atom_rec *tmp_atom;      /* v0.3m */
789
static bond_rec *tmp_bond;      /* v0.3m */
790
static ringpath_type *tmp_ring; /* v0.3m */
791
static ringprop_rec *tmp_ringprop;      /* v0.3m */
792
 
793
static boolean matchresult, matchsummary;       /* v0.3o */
794
static matchpath_type ndl_matchpath, hst_matchpath;
795
 
796
static fglist fg;
797
static str4 atomtype;
798
static str3 newatomtype;
799
 
800
static char (*molbuf)[256];
801
static int molbufindex;
802
 
803
static boolean mol_in_queue;
804
static int mol_count;
805
 
806
static molstat_rec molstat, ndl_molstat, tmp_molstat;   /* v0.3m */
807
 
808
static int ringsearch_mode, max_vringsize;      /* for SSR ring search */
809
 
810
static FILE *rfile;
811
static boolean rfile_is_open, mol_OK;   /* new in v0.2i */
812
 
813
static int n_ar;                /* new in v0.3 */
814
static int prev_n_ar;           /* new in v0.3 */
815
static boolean ez_search;       /* new in v0.3d */
816
static boolean rs_search;       /* new in v0.3f */
817
static boolean ez_flag;         /* new in v0.3f */
818
static boolean chir_flag;       /* new in v0.3f */
819
static boolean rs_strict;       /* new in v0.3j */
820
 
821
static int n_Ctot, n_Otot, n_Ntot;      /* new in v0.3g */
822
static int ndl_n_Ctot, ndl_n_Otot, ndl_n_Ntot;  /* new in v0.3g */
823
static int tmp_n_Ctot, tmp_n_Otot, tmp_n_Ntot;  /* new in v0.3m */
824
static boolean ether_generic;   /* v0.3j */
825
static boolean amine_generic;   /* v0.3j   */
826
static boolean hydroxy_generic; /* v0.3j */
827
static connval_rec *cv;         /* new in v0.3j */
828
static long long fpdecimal;     /* v0.3m */
829
static long long fpincrement;
830
static int fpindex;
831
static boolean fp_exacthit, fp_exactblock;
832
static int tmfcode;
833
    /* v0.3m; version number for tweaked MDL molfiles (tweaklevel) */
834
static boolean tmfmismatch;
835
    /* v0.3m; rely on tweaked MDL molfiles only if same level */
836
static boolean auto_ssr;
837
    /* v0.3n; indicates that SAR -> SSR fallback has happened */
838
static int recursion_depth;
839
    /* ====================emulated pascal functions============================ */
840
 
841
static boolean
842
file_exists (const char *fileName)
843
{
844
  struct stat filestat;
845
 
846
  return stat (fileName, &filestat) == 0 ? true : false;
847
}
848
 
849
static void
850
lblank (int cols, char *nstr)
851
{
852
  /* inserts leading blanks up to a given number of total characters */
853
  char STR1[256];
854
 
855
  if (strlen (nstr) >= cols)
856
    return;
857
  while (strlen (nstr) < cols)
858
    sprintf (nstr, " %s", strcpy (STR1, nstr));
859
}
860
 
861
static inline double
862
radtodeg (double rads)
863
{
864
  return (180.0 / M_PI) * rads;
865
}
866
 
867
static void
868
strdelete (char *s, int pos, int len)
869
{
870
  int slen;
871
 
872
  if (--pos < 0)
873
    return;
874
  slen = strlen (s) - pos;
875
  if (slen <= 0)
876
    return;
877
  s += pos;
878
  if (slen <= len)
879
    {
880
      *s = 0;
881
      return;
882
    }
883
  while ((*s = s[len]))
884
    s++;
885
}
886
 
887
static int
888
strpos2 (char *s, char *pat, int pos)
889
{
890
  char *cp, ch;
891
  int slen;
892
 
893
  if (--pos < 0)
894
    return 0;
895
  slen = strlen (s) - pos;
896
  cp = s + pos;
897
  if (!(ch = *pat++))
898
    return 0;
899
  pos = strlen (pat);
900
  slen -= pos;
901
  while (--slen >= 0)
902
    {
903
      if (*cp++ == ch && !strncmp (cp, pat, pos))
904
        return cp - s;
905
    }
906
  return 0;
907
}
908
 
909
static char *
910
strsub (char *ret, char *s, int pos, int len)
911
{
912
  char *s2;
913
 
914
  if (--pos < 0 || len <= 0)
915
    {
916
      *ret = 0;
917
      return ret;
918
    }
919
  while (pos > 0)
920
    {
921
      if (!*s++)
922
        {
923
          *ret = 0;
924
          return ret;
925
        }
926
      pos--;
927
    }
928
  s2 = ret;
929
  while (--len >= 0)
930
    {
931
      if (!(*s2++ = *s++))
932
        return ret;
933
    }
934
  *s2 = 0;
935
  return ret;
936
}
937
 
938
 
939
/*============================= auxiliary functions & procedures */
940
 
941
inline static void
942
all_lowercase (char *astring)
943
{
944
  int i;
945
  int l = strlen (astring);
946
 
947
  for (i = 0; i < l; i++)
948
    {
949
      astring[i] = tolower (astring[i]);
950
    }
951
}
952
 
953
static void
954
init_globals ()
955
{
956
  /*int i;*/
957
 
958
  opt_verbose = false;
959
  opt_debug = false;
960
  opt_exact = false;
961
  opt_stdin = false;
962
  opt_text = false;
963
  opt_code = false;
964
  opt_bin = false;
965
  opt_bitstring = false;
966
  opt_molout = false;
967
  opt_molstat = false;
968
  opt_molstat_X = false;
969
  opt_xmdlout = false;
970
  opt_strict = false;           /* new in v0.2f */
971
  opt_metalrings = false;       /* new in v0.3 */
972
  opt_geom = false;             /* new in v0.3d */
973
  opt_chiral = false;           /* new in v0.3f */
974
  opt_fp = false;               /* new in v0.3m */
975
  opt_iso = false;              /* new in v0.3x */
976
  opt_chg = false;              /* new in v0.3x */
977
  opt_rad = false;              /* new in v0.3x */
978
  /*cm_mdlmolfile   := false; */
979
  found_arominfo = false;
980
  found_querymol = false;
981
  ndl_querymol = false;
982
  opt_rs = rs_sar;              /* v0.3i */
983
  /*ringsearch_mode := rs_sar; */
984
  rfile_is_open = false;        /* new in v0.2g */
985
  ez_search = false;            /* new in v0.3d */
986
  rs_search = false;            /* new in v0.3f */
987
  ez_flag = false;              /* new in v0.3f */
988
  chir_flag = false;            /* new in v0.3f */
989
  rs_strict = false;            /* new in v0.3j */
990
  n_Ctot = 0;
991
  n_Otot = 0;
992
  n_Ntot = 0;                   /* new in v0.3g */
993
  ndl_n_Ctot = 0;
994
  ndl_n_Otot = 0;
995
  ndl_n_Ntot = 0;               /* new in v0.3g */
996
  //for (i = 0; i < max_fg; i++)
997
  //  fg[i] = false;
998
  memset (fg, 0, sizeof (fglist));
999
  /*try */
1000
  molbuf = safe_malloc (sizeof (molbuftype));
1001
  /*except
1002
     on e:Eoutofmemory do
1003
     begin
1004
     writeln('Not enough memory');
1005
     halt(4);
1006
     end;
1007
     end; */
1008
  ether_generic = false;        /* v0.3j */
1009
  amine_generic = false;        /* v0.3j */
1010
  hydroxy_generic = false;      /* v0.3j */
1011
  fpformat = fpf_decimal;       /* v0.3m */
1012
  fpindex = 0;                  /* v0.3m */
1013
  fp_exacthit = false;          /* v0.3m */
1014
  fp_exactblock = false;        /* v0.3m */
1015
  tmfcode = 0;                  /* v0.3m */
1016
  tmfmismatch = false;          /* v0.3m */
1017
  auto_ssr = false;             /* v0.3n */
1018
  recursion_depth = 0;
1019
}
1020
 
1021
 
1022
static inline void
1023
init_molstat (mstat)
1024
     molstat_rec *mstat;
1025
{
1026
  /*
1027
     with mstat do
1028
     begin
1029
     n_QA := 0; n_QB := 0; n_chg := 0;
1030
     n_C1 := 0; n_C2 := 0; n_C  := 0;
1031
     n_CHB1p := 0; n_CHB2p := 0; n_CHB3p := 0; n_CHB4 := 0;
1032
     n_O2 := 0; n_O3  := 0;
1033
     n_N1 := 0; n_N2 := 0; n_N3 := 0;
1034
     n_S := 0; n_SeTe := 0;
1035
     n_F := 0; n_Cl := 0; n_Br := 0; n_I := 0;
1036
     n_P := 0; n_B := 0;
1037
     n_Met := 0; n_X := 0;
1038
     n_b1 := 0; n_b2 := 0; n_b3 := 0; n_bar := 0;
1039
     n_C1O := 0; n_C2O := 0; n_CN := 0; n_XY := 0;
1040
     n_r3 := 0; n_r4 := 0; n_r5 := 0; n_r6 := 0; n_r7 := 0;
1041
     n_r8 := 0; n_r9 := 0; n_r10 := 0; n_r11 := 0; n_r12 := 0; n_r13p := 0;
1042
     n_rN := 0; n_rN1 := 0; n_rN2 := 0; n_rN3p := 0;
1043
     n_rO := 0; n_rO1 := 0; n_rO2p := 0;
1044
     n_rS := 0; n_rX := 0;
1045
     n_rAr := 0; n_rBz := 0; n_br2p := 0;
1046
     end;
1047
   */
1048
  memset (mstat, 0, sizeof (molstat_rec));      /* v0.3k */
1049
}
1050
 
1051
 
1052
#if 0
1053
static void
1054
debugoutput (dstr)
1055
     char *dstr;
1056
{
1057
  if (opt_debug)
1058
    printf ("%s\n", dstr);
1059
}
1060
#endif
1061
 
1062
static void
1063
left_trim (trimstr)
1064
     char *trimstr;
1065
{
1066
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1067
    strdelete (trimstr, 1, 1);
1068
}
1069
 
1070
 
1071
static int
1072
left_int (trimstr)
1073
     char *trimstr;
1074
{
1075
  char numstr[256];
1076
  char auxstr[256];
1077
  int auxint = 0;
1078
  char STR1[256];
1079
 
1080
  strcpy (numstr, "-+0123456789");
1081
  *auxstr = '\0';
1082
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1083
    strdelete (trimstr, 1, 1);
1084
  while ((*trimstr != '\0') &&
1085
         (strpos2 (numstr, (sprintf (STR1, "%c", trimstr[0]), STR1), 1) > 0))
1086
    {
1087
      sprintf (auxstr + strlen (auxstr), "%c", trimstr[0]);
1088
      strdelete (trimstr, 1, 1);
1089
    }
1090
  return auxint;
1091
}
1092
 
1093
static int
1094
path_pos (int id, int *a_path)
1095
{
1096
  int i = 0;
1097
 
1098
  for (i = 0; i < max_ringsize; i++)
1099
    {
1100
      if (*(a_path++) == id)
1101
        {
1102
          return ++i;
1103
        }
1104
    }
1105
  return 0;
1106
}
1107
 
1108
static int
1109
path_length (int *a_path)
1110
{
1111
  if ((a_path[max_ringsize - 1] != 0) && (path_pos (0, a_path) == 0))
1112
    return max_ringsize;
1113
  else
1114
    return (path_pos (0, a_path) - 1);
1115
}
1116
 
1117
static int
1118
get_bond (int ba1, int ba2)
1119
{
1120
  int i;
1121
  int b_id = 0;
1122
  int FORLIM;
1123
 
1124
  if (n_bonds <= 0)
1125
    return b_id;
1126
  FORLIM = n_bonds;
1127
  for (i = 1; i <= FORLIM; i++)
1128
    {
1129
      if ((bond[i - 1].a1 == ba1 && bond[i - 1].a2 == ba2) ||
1130
          (bond[i - 1].a1 == ba2 && bond[i - 1].a2 == ba1))
1131
        b_id = i;
1132
    }
1133
  return b_id;
1134
}
1135
 
1136
static void
1137
clear_atom_tags ()
1138
{
1139
  int i, FORLIM;
1140
 
1141
  if (n_atoms > 0)
1142
    {
1143
      FORLIM = n_atoms;
1144
      for (i = 0; i < FORLIM; i++)
1145
        atom[i].tag = false;
1146
    }
1147
}
1148
 
1149
#if 0
1150
static void
1151
set_atom_tags ()
1152
{
1153
  int i, FORLIM;
1154
 
1155
  if (n_atoms > 0)
1156
    {
1157
      FORLIM = n_atoms;
1158
      for (i = 0; i < FORLIM; i++)
1159
        atom[i].tag = true;
1160
    }
1161
}
1162
#endif
1163
static void
1164
order_ringpath (int *r_path)
1165
{
1166
  /* order should be: array starts with atom of lowest number, followed by neighbor atom with lower number */
1167
  int i, pl, a_ref, a_left, a_right, a_tmp;
1168
 
1169
  pl = path_length (r_path);
1170
  if (pl < 3)
1171
    return;
1172
  a_ref = n_atoms;
1173
  /* start with highest possible value for an atom number */
1174
  for (i = 0; i < pl; i++)
1175
    {
1176
      if (r_path[i] < a_ref)    /* find the minimum value ==> reference atom */
1177
        a_ref = r_path[i];
1178
    }
1179
  if (a_ref < 1)                /* just to be sure */
1180
    return;
1181
  if (path_pos (a_ref, r_path) < pl)
1182
    a_right = r_path[path_pos (a_ref, r_path)];
1183
  else
1184
    a_right = r_path[0];
1185
  if (path_pos (a_ref, r_path) > 1)
1186
    a_left = r_path[path_pos (a_ref, r_path) - 2];
1187
  else
1188
    a_left = r_path[pl - 1];
1189
  if (a_right == a_left)        /* should never happen */
1190
    return;
1191
  if (a_right < a_left)
1192
    {
1193
      /* correct ring numbering direction, only shift of the reference atom to the left end required */
1194
      while (path_pos (a_ref, r_path) > 1)
1195
        {
1196
          a_tmp = r_path[0];
1197
          for (i = 1; i < pl; i++)
1198
            r_path[i - 1] = r_path[i];
1199
          r_path[pl - 1] = a_tmp;
1200
        }
1201
      return;
1202
    }
1203
  while (path_pos (a_ref, r_path) < pl)
1204
    {
1205
      /* step one: create "mirrored" ring path with reference atom at right end */
1206
      a_tmp = r_path[pl - 1];
1207
      for (i = pl; i >= 2; i--)
1208
        r_path[i - 1] = r_path[i - 2];
1209
      r_path[0] = a_tmp;
1210
    }
1211
  for (i = 1; i <= pl / 2; i++)
1212
    {                           /* one more mirroring */
1213
      a_tmp = r_path[i - 1];
1214
      r_path[i - 1] = r_path[pl - i];
1215
      r_path[pl - i] = a_tmp;
1216
      /* wrong ring numbering direction, two steps required */
1217
    }
1218
}
1219
 
1220
static void
1221
clear_ndl_atom_tags ()
1222
{
1223
  int i;
1224
 
1225
  if (ndl_n_atoms > 0)
1226
    {
1227
 
1228
      for (i = 0; i < ndl_n_atoms; i++)
1229
        ndl_atom[i].tag = false;
1230
    }
1231
}
1232
 
1233
 
1234
static void
1235
set_ndl_atom_tags ()
1236
{
1237
  int i;
1238
 
1239
  if (ndl_n_atoms > 0)
1240
    {
1241
 
1242
      for (i = 0; i < ndl_n_atoms; i++)
1243
        ndl_atom[i].tag = true;
1244
    }
1245
}
1246
 
1247
 
1248
static int
1249
count_tagged_ndl_heavyatoms ()
1250
{
1251
  int i;
1252
  int n = 0;
1253
 
1254
  if (ndl_n_atoms < 1)
1255
    return n;
1256
 
1257
  for (i = 0; i < ndl_n_atoms; i++)
1258
    {
1259
      if (ndl_atom[i].heavy && ndl_atom[i].tag)
1260
        n++;
1261
    }
1262
  return n;
1263
}
1264
 
1265
 
1266
 
1267
/*============================= geometry functions ========================== */
1268
 
1269
static double
1270
dist3d (p1, p2)
1271
     p_3d p1, p2;
1272
{
1273
  double res, TEMP, TEMP1, TEMP2;
1274
 
1275
  TEMP = p1.x - p2.x;
1276
  TEMP1 = p1.y - p2.y;
1277
  TEMP2 = p1.z - p2.z;
1278
  res = sqrt (TEMP * TEMP + TEMP1 * TEMP1 + TEMP2 * TEMP2);
1279
  return res;
1280
}
1281
 
1282
 
1283
/*
1284
function is_cis(p1,p2,p3,p4:p_3d):boolean;  (* new in v0.3d
1285
var                         (* just a simple, distance-based estimation
1286
  total_dist  : double;     (* instead of calculating the dihedral angle
1287
  direct_dist : double;
1288
  res         : boolean;
1289
begin
1290
  res := false;
1291
  total_dist  := dist3d(p1,p2) + dist3d(p2,p3) + dist3d(p3,p4);
1292
  direct_dist := dist3d(p1,p4);
1293
  if (direct_dist < 0.78 * total_dist) then res := true;  (* cutoff value of 0.78 was
1294
  is_cis := res;                                          (* experimentally determined
1295
end;
1296
*/
1297
/* function is_cis was replaced by a new one in v0.3h */
1298
 
1299
 
1300
static p_3d
1301
subtract_3d (p1, p2)
1302
     p_3d p1, p2;
1303
{
1304
  p_3d p;
1305
 
1306
  p.x = p1.x - p2.x;
1307
  p.y = p1.y - p2.y;
1308
  p.z = p1.z - p2.z;
1309
  return p;
1310
}
1311
 
1312
 
1313
static p_3d
1314
add_3d (p1, p2)
1315
     p_3d p1, p2;
1316
{
1317
  p_3d p;
1318
 
1319
  p.x = p1.x + p2.x;
1320
  p.y = p1.y + p2.y;
1321
  p.z = p1.z + p2.z;
1322
  return p;
1323
}
1324
 
1325
#if 0
1326
static void
1327
vec2origin (p1, p2)
1328
     p_3d *p1, *p2;
1329
{
1330
  p_3d p;
1331
 
1332
  p = subtract_3d (*p2, *p1);
1333
  *p2 = p;
1334
  p1->x = 0.0;
1335
  p1->y = 0.0;
1336
  p1->z = 0.0;
1337
}
1338
#endif
1339
 
1340
static double
1341
scalar_prod (p1, p2, p3)
1342
     p_3d p1, p2, p3;
1343
{
1344
  p_3d p;
1345
  double res;
1346
 
1347
  p = subtract_3d (p2, p1);
1348
  p2 = p;
1349
  p = subtract_3d (p3, p1);
1350
  p3 = p;
1351
  p1.x = 0.0;
1352
  p1.y = 0.0;
1353
  p1.z = 0.0;
1354
  res = p2.x * p3.x + p2.y * p3.y + p2.z * p3.z;
1355
  return res;
1356
}
1357
 
1358
 
1359
static p_3d
1360
cross_prod (p1, p2, p3)
1361
     p_3d p1, p2, p3;
1362
{
1363
  p_3d p, orig_p1;
1364
 
1365
  orig_p1 = p1;
1366
  p = subtract_3d (p2, p1);
1367
  p2 = p;
1368
  p = subtract_3d (p3, p1);
1369
  p3 = p;
1370
  p.x = p2.y * p3.z - p2.z * p3.y;
1371
  p.y = p2.z * p3.x - p2.x * p3.z;
1372
  p.z = p2.x * p3.y - p2.y * p3.x;
1373
  return (add_3d (orig_p1, p));
1374
}
1375
 
1376
 
1377
static double
1378
angle_3d (p1, p2, p3)
1379
     p_3d p1, p2, p3;
1380
{
1381
  p_3d lp1, lp2, lp3, p;
1382
  double res = 0.0;
1383
  double magn_1, magn_2, cos_phi;
1384
 
1385
  lp1 = p1;
1386
  lp2 = p2;
1387
  lp3 = p3;
1388
  p = subtract_3d (lp2, lp1);
1389
  lp2 = p;
1390
  p = subtract_3d (lp3, lp1);
1391
  lp3 = p;
1392
  lp1.x = 0.0;
1393
  lp1.y = 0.0;
1394
  lp1.z = 0.0;
1395
  magn_1 = dist3d (lp1, lp2);
1396
  magn_2 = dist3d (lp1, lp3);
1397
  if (magn_1 * magn_2 == 0)     /* emergency exit */
1398
    return M_PI;
1399
  cos_phi = scalar_prod (lp1, lp2, lp3) / (magn_1 * magn_2);
1400
  if (cos_phi < -1)
1401
    cos_phi = -1.0;
1402
  if (cos_phi > 1)
1403
    cos_phi = 1.0;
1404
  res = acos (cos_phi);
1405
  return res;
1406
}
1407
 
1408
 
1409
static double
1410
torsion (p1, p2, p3, p4)
1411
     p_3d p1, p2, p3, p4;
1412
{
1413
  p_3d lp1, lp2, lp3, lp4, d1, c1, c2;
1414
  double res;
1415
  p_3d c1xc2, c2xc1;
1416
  double dist1, dist2, sign;
1417
 
1418
  /* copy everything into local variables */
1419
  lp1 = p1;
1420
  lp2 = p2;
1421
  lp3 = p3;
1422
  lp4 = p4;
1423
  /* get the vector between the two central atoms */
1424
  d1 = subtract_3d (p3, p2);
1425
  /* shift the first atom parallel to be attached to p3 instead of p2 */
1426
  lp1 = add_3d (p1, d1);
1427
  /* now get the cross product vectors */
1428
  c1 = cross_prod (lp3, lp2, lp1);
1429
  c2 = cross_prod (lp3, lp2, lp4);
1430
  res = angle_3d (p3, c1, c2);
1431
  /*now check if it is clockwise or anticlockwise: */
1432
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1433
  c1xc2 = cross_prod (lp3, c1, c2);
1434
  c2xc1 = cross_prod (lp3, c2, c1);
1435
  /*next, get the distances from these points to our refernce point lp2 */
1436
  dist1 = dist3d (lp2, c1xc2);
1437
  dist2 = dist3d (lp2, c2xc1);
1438
  if (dist1 <= dist2)
1439
    sign = 1.0;
1440
  else
1441
    sign = -1.0;
1442
  return (sign * res);
1443
}
1444
 
1445
 
1446
static double
1447
ctorsion (p1, p2, p3, p4)
1448
     p_3d p1, p2, p3, p4;
1449
{
1450
  /* calculates "pseudo-torsion" defined by atoms 3 and 4, being both */
1451
  /* attached to atom 2, with respect to axis of atoms 1 and 2 */
1452
  p_3d lp1, lp2, lp3, lp4;
1453
  /*d1 : p_3d; */
1454
  p_3d c1, c2;
1455
  double res;
1456
  p_3d c1xc2, c2xc1;
1457
  double dist1, dist2, sign;
1458
 
1459
  /* copy everything into local variables */
1460
  lp1 = p1;
1461
  lp2 = p2;
1462
  lp3 = p3;
1463
  lp4 = p4;
1464
  /* get the cross product vectors */
1465
  c1 = cross_prod (lp2, lp1, lp3);
1466
  c2 = cross_prod (lp2, lp1, lp4);
1467
  res = angle_3d (p2, c1, c2);
1468
  /*now check if it is clockwise or anticlockwise: */
1469
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1470
  c1xc2 = cross_prod (lp2, c1, c2);
1471
  c2xc1 = cross_prod (lp2, c2, c1);
1472
  /*next, get the distances from these points to our refernce point lp1 */
1473
  dist1 = dist3d (lp1, c1xc2);
1474
  dist2 = dist3d (lp1, c2xc1);
1475
  if (dist1 <= dist2)
1476
    sign = 1.0;
1477
  else
1478
    sign = -1.0;
1479
  return (sign * res);
1480
}
1481
 
1482
 
1483
static boolean
1484
is_cis (p1, p2, p3, p4)
1485
     p_3d p1, p2, p3, p4;
1486
{
1487
  /* new in v0.3h, uses the dihedral angle */
1488
  double phi;
1489
  boolean res = false;
1490
 
1491
  phi = torsion (p1, p2, p3, p4);
1492
  if (fabs (phi) < M_PI / 2)
1493
    res = true;
1494
  return res;
1495
}
1496
 
1497
 
1498
/*====================== end of geometry functions ========================== */
1499
 
1500
static void
1501
show_usage ()
1502
{
1503
  if (progmode == pmMatchMol)
1504
    {
1505
      printf
1506
        ("matchmol version %s  N. Haider, University of Vienna, 2003-2007\n",
1507
         version);
1508
      printf ("Usage: matchmol [options] <needle> <haystack>\n");
1509
      printf
1510
        (" where <needle> and <haystack> are the two molecules to compare\n");
1511
      printf
1512
        (" (supported formats: MDL *.mol or *.sdf, Alchemy *.mol, Sybyl *.mol2)\n");
1513
      printf (" options can be:\n");
1514
      printf ("    -v  verbose output\n");
1515
      printf ("    -x  exact match\n");
1516
      printf
1517
        ("    -s  strict comparison of atom and bond types (including ring check)\n");
1518
      /* new in v0.2f, v0.3d */
1519
      printf ("    -r  force SSR (set of small rings) ring search mode\n");
1520
      printf
1521
        ("    -m  write matching molecule as MDL molfile to standard output\n");
1522
      printf
1523
        ("        (default output: record number + \":T\" for hit  or \":F\" for miss\n");
1524
      printf ("    -M  accept metal atoms as ring members\n");
1525
      printf ("    -g  check geometry of double bonds (E/Z)\n");
1526
      printf ("    -G  check geometry of chiral centers (R/S)\n");
1527
      printf ("    -a  check charges strict\n");        /* 0.3x */
1528
      printf ("    -i  check isotopes strict\n");       /* 0.3x */
1529
      printf ("    -d  check radicals strict\n");       /* 0.3x */
1530
      printf
1531
        ("    -f  fingerprint mode (1 haystack, multiple needles) with boolean output\n");
1532
      printf
1533
        ("    -F  fingerprint mode (1 haystack, multiple needles) with decimal output\n");
1534
      return;
1535
    }
1536
  printf ("checkmol version %s  N. Haider, University of Vienna, 2003-2007\n",
1537
          version);
1538
  printf ("Usage: checkmol [options] <filename>\n");
1539
  printf (" where options can be:\n");
1540
  printf
1541
    ("    -l  print a list of fingerprint codes + explanation and exit\n");
1542
  printf ("    -v  verbose output\n");
1543
  printf ("    -r  force SSR (set of small rings) ring search mode\n");
1544
  printf ("    -M  accept metal atoms as ring members\n");
1545
  printf ("  and one of the following:\n");
1546
  printf
1547
    ("    -e  english text (common name of functional group; default)\n");
1548
  printf ("    -d  german text (common name of functional group)\n");
1549
  printf ("    -c  code (acronym-like code for functional group)\n");
1550
  printf
1551
    ("    -b  binary (a bitstring representing absence or presence of each group)\n");
1552
  printf
1553
    ("    -s  the ASCII representation of the above bitstring, i.e. 0s and 1s)\n");
1554
  printf
1555
    ("    -x  print molecular statistics (number of various atom types, bond types,\n");
1556
  printf ("        ring sizes, etc.\n");
1557
  printf
1558
    ("    -X  same as above, listing all records (even if 0) as comma-separated list\n");
1559
  printf ("    -a  count charges in fingerprint\n");    /* 0.3x */
1560
  printf
1561
    ("    -m  write MDL molfile (with special encoding for aromatic atoms/bonds)\n");
1562
  printf (" options can be combined like -vc\n");
1563
  printf (" <filename> specifies any file in the formats supported\n");
1564
  printf
1565
    (" (MDL *.mol, Alchemy *.mol, Sybyl *.mol2), the filename \"-\" (without quotes)\n");
1566
  printf (" specifies standard input\n");
1567
  /* the "debug" option (-D) remains undocumented */
1568
}
1569
 
1570
 
1571
static void
1572
list_molstat_codes ()
1573
{
1574
  printf ("n_atoms:     number of heavy atoms\n");
1575
  printf ("n_bonds:     number of bonds between non-H atoms\n");
1576
  printf ("n_rings:     number of rings\n");
1577
  printf ("n_QA:        number of query atoms\n");
1578
  printf ("n_QB:        number of query bonds\n");
1579
  printf ("n_chg:       number of charges\n");
1580
  printf ("n_C1:        number of sp-hybridized carbon atoms\n");
1581
  printf ("n_C2:        number of sp2-hybridized carbon atoms\n");
1582
  printf ("n_C:         total number of carbon atoms\n");
1583
  printf
1584
    ("n_CHB1p:     number of carbon atoms with at least 1 bond to a hetero atom\n");
1585
  printf
1586
    ("n_CHB2p:     number of carbon atoms with at least 2 bonds to a hetero atom\n");
1587
  printf
1588
    ("n_CHB3p:     number of carbon atoms with at least 3 bonds to a hetero atom\n");
1589
  printf
1590
    ("n_CHB4:      number of carbon atoms with 4 bonds to a hetero atom\n");
1591
  printf ("n_O2:        number of sp2-hybridized oxygen atoms\n");
1592
  printf ("n_O3:        number of sp3-hybridized oxygen atoms\n");
1593
  printf ("n_N1:        number of sp-hybridized nitrogen atoms\n");
1594
  printf ("n_N2:        number of sp2-hybridized nitrogen atoms\n");
1595
  printf ("n_N3:        number of sp3-hybridized nitrogen atoms\n");
1596
  printf ("n_S:         number of sulfur atoms\n");
1597
  printf ("n_SeTe:      total number of selenium and tellurium atoms\n");
1598
  printf ("n_F:         number of fluorine atoms\n");
1599
  printf ("n_Cl:        number of chlorine atoms\n");
1600
  printf ("n_Br:        number of bromine atoms\n");
1601
  printf ("n_I:         number of iodine atoms\n");
1602
  printf ("n_P:         number of phosphorus atoms\n");
1603
  printf ("n_B:         number of boron atoms\n");
1604
  printf ("n_Met:       total number of metal atoms\n");
1605
  printf
1606
    ("n_X:         total number of \"other\" atoms (not listed above) and halogens\n");
1607
  printf ("n_b1:        number of single bonds\n");
1608
  printf ("n_b2:        number of double bonds\n");
1609
  printf ("n_b3:        number of triple bonds\n");
1610
  printf ("n_bar:       number of aromatic bonds\n");
1611
  printf ("n_C1O:       number of C-O single bonds\n");
1612
  printf ("n_C2O:       number of C=O double bonds\n");
1613
  printf ("n_CN:        number of C/N bonds (any type)\n");
1614
  printf ("n_XY:        number of heteroatom/heteroatom bonds (any type)\n");
1615
  printf ("n_r3:        number of 3-membered rings\n");
1616
  printf ("n_r4:        number of 4-membered rings\n");
1617
  printf ("n_r5:        number of 5-membered rings\n");
1618
  printf ("n_r6:        number of 6-membered rings\n");
1619
  printf ("n_r7:        number of 7-membered rings\n");
1620
  printf ("n_r8:        number of 8-membered rings\n");
1621
  printf ("n_r9:        number of 9-membered rings\n");
1622
  printf ("n_r10:       number of 10-membered rings\n");
1623
  printf ("n_r11:       number of 11-membered rings\n");
1624
  printf ("n_r12:       number of 12-membered rings\n");
1625
  printf ("n_r13p:      number of 13-membered or larger rings\n");
1626
  printf ("n_rN:        number of rings containing nitrogen (any number)\n");
1627
  printf ("n_rN1:       number of rings containing 1 nitrogen atom\n");
1628
  printf ("n_rN2:       number of rings containing 2 nitrogen atoms\n");
1629
  printf
1630
    ("n_rN3p:      number of rings containing 3 or more nitrogen atoms\n");
1631
  printf ("n_rO:        number of rings containing oxygen (any number)\n");
1632
  printf ("n_rO1:       number of rings containing 1 oxygen atom\n");
1633
  printf ("n_rO2p:      number of rings containing 2 or more oxygen atoms\n");
1634
  printf ("n_rS:        number of rings containing sulfur (any number)\n");
1635
  printf ("n_rX:        number of heterocycles (any type)\n");
1636
  printf ("n_rar:       number of aromatic rings (any type)\n");
1637
/* p2c: checkmol.pas, line 1207:
1638
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1639
  /*$IFDEF extended_molstat */
1640
  printf ("n_rbz:       number of benzene rings\n");
1641
  printf ("n_br2p:      number of bonds belonging to two or more rings\n");
1642
  printf
1643
    ("n_psg01:     number of atoms belonging to group 1 of the periodic system\n");
1644
  printf
1645
    ("n_psg02:     number of atoms belonging to group 2 of the periodic system\n");
1646
  printf
1647
    ("n_psg13:     number of atoms belonging to group 13 of the periodic system\n");
1648
  printf
1649
    ("n_psg14:     number of atoms belonging to group 14 of the periodic system\n");
1650
  printf
1651
    ("n_psg15:     number of atoms belonging to group 15 of the periodic system\n");
1652
  printf
1653
    ("n_psg16:     number of atoms belonging to group 16 of the periodic system\n");
1654
  printf
1655
    ("n_psg17:     number of atoms belonging to group 17 of the periodic system\n");
1656
  printf
1657
    ("n_psg18:     number of atoms belonging to group 18 of the periodic system\n");
1658
  printf
1659
    ("n_pstm:      number of atoms belonging to the transition metals\n");
1660
  printf
1661
    ("n_psla:      number of atoms belonging to the lanthanides or actinides\n");
1662
  printf ("n_iso:      number of isotopes\n");
1663
  printf ("n_rad:      number of radicals\n");
1664
  /*$ENDIF */
1665
}
1666
 
1667
 
1668
#if 0
1669
static void parse_args()
1670
{
1671
  int p;
1672
  char parstr[256];
1673
  char tmpstr[256];
1674
  int l;
1675
 
1676
  *tmpstr = '\0';
1677
  opt_none = true;
1678
  if (progmode == pmCheckMol) {
1679
    for (p = 1; p < P_argc; p++) {
1680
      strcpy(parstr, P_argv[p]);
1681
      if (!strcmp(parstr, "-l")) {   /* new in v0.3l */
1682
        list_molstat_codes();
1683
        _Escape(0);
1684
      }
1685
      if (p < P_argc - 1) {
1686
        if (strpos2(parstr, "-", 1) == 1 && p < P_argc - 1) {
1687
          strcpy(tmpstr, P_argv[p]);
1688
          left_trim(tmpstr);
1689
          l = 0;
1690
          if (strpos2(tmpstr, "v", 1) > 0)
1691
            l++;
1692
          if (strpos2(tmpstr, "D", 1) > 0)
1693
            l++;
1694
          if (strpos2(tmpstr, "r", 1) > 0)
1695
            l++;
1696
          if (strpos2(tmpstr, "M", 1) > 0)   /* new in v0.3 */
1697
            l++;
1698
          if (strlen(tmpstr) > l + 2) {
1699
            show_usage();
1700
            _Escape(1);
1701
          }
1702
          opt_none = false;
1703
          if (strpos2(tmpstr, "M", 1) > 0)
1704
            opt_metalrings = true;
1705
          if (strpos2(tmpstr, "v", 1) > 0)
1706
            opt_verbose = true;
1707
/* p2c: checkmol.pas, line 1261:
1708
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1709
          /*$IFDEF debug
1710
          if (strpos2(tmpstr, "D", 1) > 0)
1711
            opt_debug = true;
1712
          $ENDIF*/
1713
          if (strpos2(tmpstr, "e", 1) > 0)
1714
            opt_text = true;
1715
          else {
1716
            if (strpos2(tmpstr, "d", 1) > 0)
1717
              opt_text_de = true;
1718
            else {
1719
              if (strpos2(tmpstr, "c", 1) > 0)
1720
                opt_code = true;
1721
              else {
1722
                if (strpos2(tmpstr, "b", 1) > 0)
1723
                  opt_bin = true;
1724
                else {
1725
                  if (strpos2(tmpstr, "s", 1) > 0)
1726
                    opt_bitstring = true;
1727
                }
1728
              }
1729
            }
1730
            if (strpos2(tmpstr, "x", 1) > 0)
1731
              opt_molstat = true;
1732
            if (strpos2(tmpstr, "r", 1) > 0)
1733
              opt_rs = rs_ssr;
1734
            if (strpos2(tmpstr, "X", 1) > 0) {
1735
              opt_molstat = true;
1736
              opt_molstat_X = true;
1737
            }
1738
            if (strpos2(tmpstr, "m", 1) > 0) {
1739
              opt_text = false;
1740
              opt_text_de = false;
1741
              opt_bin = false;
1742
              opt_bitstring = false;
1743
              opt_code = false;
1744
              opt_molstat = false;
1745
              opt_xmdlout = true;
1746
            }
1747
          }
1748
          strcpy(molfilename, tmpstr);
1749
        }
1750
      } else {
1751
        if (strpos2(parstr, "-", 1) == 1) {
1752
          if (strlen(parstr) > 1) {
1753
            show_usage();
1754
            _Escape(1);
1755
          }
1756
          opt_stdin = true;
1757
        } else {
1758
          opt_stdin = false;
1759
          strcpy(molfilename, parstr);
1760
        }
1761
      }
1762
    }
1763
    if (opt_text == false && opt_text_de == false && opt_code == false &&
1764
        opt_bin == false && opt_bitstring == false && opt_molstat == false &&
1765
        opt_molstat_X == false && opt_xmdlout == false)
1766
      opt_none = true;
1767
  }
1768
  if (progmode == pmMatchMol) {
1769
    *ndl_molfilename = '\0';
1770
    *molfilename = '\0';
1771
    for (p = 1; p < P_argc; p++) {
1772
      strcpy(parstr, P_argv[p]);
1773
      if (p == 1) {
1774
        if (strpos2(parstr, "-", 1) == 1) {
1775
          if (strpos2(parstr, "v", 1) > 1)
1776
            opt_verbose = true;
1777
/* p2c: checkmol.pas, line 1329:
1778
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1779
          /*$IFDEF debug
1780
             if (strpos2(parstr, "D", 1) > 1)
1781
             opt_debug = true;
1782
             $ENDIF*/
1783
             if (strpos2(parstr, "x", 1) > 1)
1784
             opt_exact = true;
1785
             if (strpos2(parstr, "s", 1) > 1)   /* new in v0.2f */
1786
             opt_strict = true;
1787
             if (strpos2(parstr, "m", 1) > 1)
1788
             opt_molout = true;
1789
             if (strpos2(parstr, "r", 1) > 1)
1790
             opt_rs = rs_ssr;
1791
             if (strpos2(parstr, "M", 1) > 0)   /* new in v0.3 */
1792
             opt_metalrings = true;
1793
             if (strpos2(parstr, "g", 1) > 0)   /* new in v0.3d */
1794
             opt_geom = true;
1795
             if (strpos2(parstr, "G", 1) > 0)   /* new in v0.3f */
1796
             opt_chiral = true;
1797
             if (strpos2(parstr, "f", 1) > 0) {   /* new in v0.3m */
1798
             opt_fp = true;
1799
             fpformat = fpf_boolean;
1800
             }
1801
             if (strpos2(parstr, "F", 1) > 0) {   /* new in v0.3m */
1802
             opt_fp = true;
1803
             fpformat = fpf_decimal;
1804
             }
1805
             if (strpos2(parstr, "h", 1) > 1) {
1806
             show_usage();
1807
             _Escape(0);
1808
             }
1809
             } else
1810
             strcpy(ndl_molfilename, parstr);
1811
             }
1812
             if (p == P_argc - 2) {
1813
             if (strpos2(parstr, "-", 1) != 1)
1814
             strcpy(ndl_molfilename, parstr);
1815
             }
1816
             if (p == P_argc - 1) {
1817
             if (strcmp(parstr, "-"))
1818
             strcpy(molfilename, parstr);
1819
             else
1820
             opt_stdin = true;
1821
             }
1822
             }
1823
             if (opt_geom)   /* v0.3d */
1824
             ez_search = true;
1825
             if (opt_chiral)   /* v0.3f */
1826
             rs_search = true;
1827
             if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1828
             /* new in v0.3j, v0.3m */
1829
             rs_strict = true;
1830
             if (opt_fp) {   /* v0.3m */
1831
             opt_molout = false;
1832
             opt_exact = false;
1833
             }
1834
             }  /* progmode = pmMatchMol */
1835
             ringsearch_mode = opt_rs;   /* v0.3i */
1836
             }
1837
#endif
1838
 
1839
static void
1840
parse_args (int argc, char *argv[])
1841
{
1842
  short p;
1843
  char parstr[256];
1844
  char tmpstr[256];
1845
  short l;
1846
 
1847
  *tmpstr = '\0';
1848
  opt_none = true;
1849
  *molfilename = '\0';
1850
  *ndl_molfilename = '\0';
1851
  if (progmode == pmCheckMol)
1852
    {
1853
      for (p = 1; p <= argc - 1; p++)
1854
        {
1855
          strcpy (parstr, argv[p]);
1856
          if (!strcmp (parstr, "-l"))
1857
            {                   /* new in v0.3l */
1858
              list_molstat_codes ();
1859
              exit (0);
1860
            }
1861
          if (p < argc - 1)
1862
            {
1863
              if (strpos2 (parstr, "-", 1) == 1 && p < argc - 1)
1864
                {
1865
                  strcpy (tmpstr, argv[p]);
1866
                  left_trim (tmpstr);
1867
                  l = 0;
1868
                  if (strpos2 (tmpstr, "v", 1) > 0)
1869
                    l++;
1870
                  if (strpos2 (tmpstr, "D", 1) > 0)
1871
                    l++;
1872
                  if (strpos2 (tmpstr, "r", 1) > 0)
1873
                    l++;
1874
                  /*if (strpos2 (tmpstr, "a", 1) > 0)   // 0.3x
1875
                     l++; */
1876
                  if (strpos2 (tmpstr, "M", 1) > 0)     /* new in v0.3 */
1877
                    l++;
1878
                  if (strlen (tmpstr) > l + 2)
1879
                    {
1880
                      show_usage ();
1881
                      exit (1);
1882
                    }
1883
                  opt_none = false;
1884
                  if (strpos2 (tmpstr, "M", 1) > 0)
1885
                    opt_metalrings = true;
1886
                  if (strpos2 (tmpstr, "v", 1) > 0)
1887
                    opt_verbose = true;
1888
                  /*{$IFDEF debug
1889
                     if pos('D',tmpstr)>0 then opt_debug       := true;
1890
                     {$ENDIF */
1891
                  if (strpos2 (tmpstr, "e", 1) > 0)
1892
                    opt_text = true;
1893
                  else
1894
                    {
1895
                      if (strpos2 (tmpstr, "d", 1) > 0)
1896
                        opt_text_de = true;
1897
                      else
1898
                        {
1899
                          if (strpos2 (tmpstr, "c", 1) > 0)
1900
                            opt_code = true;
1901
                          else
1902
                            {
1903
                              if (strpos2 (tmpstr, "b", 1) > 0)
1904
                                opt_bin = true;
1905
                              else
1906
                                {
1907
                                  if (strpos2 (tmpstr, "s", 1) > 0)
1908
                                    opt_bitstring = true;
1909
                                }
1910
                            }
1911
                        }
1912
                      if (strpos2 (tmpstr, "x", 1) > 0)
1913
                        opt_molstat = true;
1914
                      if (strpos2 (tmpstr, "r", 1) > 0)
1915
                        opt_rs = rs_ssr;
1916
                      /* if (strpos2 (tmpstr, "a", 1) > 0)
1917
                         opt_chg = true; */ /* 0.3x  */
1918
                      if (strpos2 (tmpstr, "X", 1) > 0)
1919
                        {
1920
                          opt_molstat = true;
1921
                          opt_molstat_X = true;
1922
                        }
1923
                      if (strpos2 (tmpstr, "m", 1) > 0)
1924
                        {
1925
                          opt_text = false;
1926
                          opt_text_de = false;
1927
                          opt_bin = false;
1928
                          opt_bitstring = false;
1929
                          opt_code = false;
1930
                          opt_molstat = false;
1931
                          opt_xmdlout = true;
1932
                        }
1933
                    }
1934
                  strcpy (molfilename, tmpstr);
1935
                }
1936
            }
1937
          else
1938
            {
1939
              if (strpos2 (parstr, "-", 1) == 1)
1940
                {
1941
                  if (strlen (parstr) > 1)
1942
                    {
1943
                      show_usage ();
1944
                      exit (1);
1945
                    }
1946
                  opt_stdin = true;
1947
                }
1948
              else
1949
                {
1950
                  opt_stdin = false;
1951
                  strcpy (molfilename, parstr);
1952
                }
1953
            }
1954
        }
1955
      if (opt_text == false && opt_text_de == false && opt_code == false &&
1956
          opt_bin == false && opt_bitstring == false && opt_molstat == false
1957
          && opt_molstat_X == false && opt_xmdlout == false
1958
          && opt_chg == false)
1959
        opt_none = true;        /* 0.3x */
1960
    }
1961
  if (progmode == pmMatchMol)
1962
    {
1963
 
1964
      for (p = 1; p <= argc - 1; p++)
1965
        {
1966
          strcpy (parstr, argv[p]);
1967
          if (p == 1)
1968
            {
1969
              if (strpos2 (parstr, "-", 1) == 1)
1970
                {
1971
                  if (strpos2 (parstr, "v", 1) > 1)
1972
                    opt_verbose = true;
1973
                  /*{$IFDEF debug
1974
                     if pos('D',parstr)>1 then opt_debug       := true;
1975
                     {$ENDIF */
1976
                  if (strpos2 (parstr, "x", 1) > 1)
1977
                    opt_exact = true;
1978
                  if (strpos2 (parstr, "s", 1) > 1)     /* new in v0.2f */
1979
                    opt_strict = true;
1980
                  if (strpos2 (parstr, "m", 1) > 1)
1981
                    opt_molout = true;
1982
                  if (strpos2 (parstr, "r", 1) > 1)
1983
                    opt_rs = rs_ssr;
1984
                  if (strpos2 (parstr, "a", 1) > 0)
1985
                    opt_chg = true;     /* 0.3x */
1986
                  if (strpos2 (parstr, "i", 1) > 0)
1987
                    opt_iso = true;     /* 0.3x */
1988
                  if (strpos2 (parstr, "d", 1) > 0)
1989
                    opt_rad = true;     /* 0.3x */
1990
                  if (strpos2 (parstr, "M", 1) > 0)     /* new in v0.3 */
1991
                    opt_metalrings = true;
1992
                  if (strpos2 (parstr, "g", 1) > 0)     /* new in v0.3d */
1993
                    opt_geom = true;
1994
                  if (strpos2 (parstr, "G", 1) > 0)     /* new in v0.3f */
1995
                    opt_chiral = true;
1996
                  if (strpos2 (parstr, "f", 1) > 0)
1997
                    {           /* new in v0.3m */
1998
                      opt_fp = true;
1999
                      fpformat = fpf_boolean;
2000
                    }
2001
                  if (strpos2 (parstr, "F", 1) > 0)
2002
                    {           /* new in v0.3m */
2003
                      opt_fp = true;
2004
                      fpformat = fpf_decimal;
2005
                    }
2006
                  if (strpos2 (parstr, "h", 1) > 1)
2007
                    {
2008
                      show_usage ();
2009
                      exit (0);
2010
                    }
2011
                }
2012
              else
2013
                strcpy (ndl_molfilename, parstr);
2014
            }
2015
          if (p == argc - 2)
2016
            {
2017
              if (strpos2 (parstr, "-", 1) != 1)
2018
                strcpy (ndl_molfilename, parstr);
2019
            }
2020
          if (p == argc - 1)
2021
            {
2022
              if (strcmp (parstr, "-"))
2023
                strcpy (molfilename, parstr);
2024
              else
2025
                opt_stdin = true;
2026
            }
2027
        }
2028
      if (opt_geom)             /* v0.3d */
2029
        ez_search = true;
2030
      if (opt_chiral)           /* v0.3f */
2031
        rs_search = true;
2032
      if (opt_chiral && opt_strict && (opt_exact || opt_fp))
2033
        /* new in v0.3j, v0.3m  */
2034
        rs_strict = true;
2035
      if (opt_fp)
2036
        {                       /* v0.3m */
2037
          opt_molout = false;
2038
          opt_exact = false;
2039
        }
2040
    }                           /* progmode = pmMatchMol */
2041
  ringsearch_mode = opt_rs;     /* v0.3i */
2042
}
2043
 
2044
/*============== input-related functions & procedures ===================== */
2045
 
2046
static char *
2047
get_filetype (Result, f)
2048
     char *Result;
2049
     char *f;
2050
{
2051
  char rline[256];
2052
  char auxstr[256];
2053
  int i;
2054
  boolean mdl1 = false;
2055
  int ri;
2056
  int sepcount = 0;
2057
  char STR1[256], STR6[256], STR7[256];
2058
 
2059
  strcpy (auxstr, "unknown");
2060
  i = li;
2061
  ri = li - 1;
2062
  while (ri < molbufindex && sepcount < 1)
2063
    {
2064
      ri++;
2065
      strcpy (rline, molbuf[ri - 1]);
2066
      if (strpos2 (rline, "$$$$", 1) > 0)
2067
        sepcount++;
2068
      if ((i == li) && (strcmp (strsub (STR1, rline, 7, 5), "ATOMS") == 0) &&
2069
          (strcmp (strsub (STR6, rline, 20, 5), "BONDS") == 0) &&
2070
          (strcmp (strsub (STR7, rline, 33, 7), "CHARGES") == 0))
2071
        strcpy (auxstr, "alchemy");
2072
      if ((i == li + 3) && (strcmp (strsub (STR1, rline, 35, 5), "V2000") ==
2073
                            0))
2074
        /* and (copy(rline,31,3)='999') */
2075
        mdl1 = true;
2076
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 6), "-ISIS-") ==
2077
                            0))
2078
        mdl1 = true;
2079
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "WLViewer") ==
2080
                            0))
2081
        mdl1 = true;
2082
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CheckMol") ==
2083
                            0))
2084
        mdl1 = true;
2085
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CATALYST") ==
2086
                            0))
2087
        {
2088
          mdl1 = true;
2089
          strcpy (auxstr, "mdl");
2090
        }
2091
      if (strpos2 (rline, "M  END", 1) == 1 || mdl1)
2092
        strcpy (auxstr, "mdl");
2093
      if (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) > 0)
2094
        strcpy (auxstr, "sybyl");
2095
      i++;
2096
    }
2097
  /* new in v0.2j: try to identify non-conformant SD-files */
2098
  if (!strcmp (auxstr, "unknown") && sepcount > 0)
2099
    strcpy (auxstr, "mdl");
2100
  return strcpy (Result, auxstr);
2101
}
2102
 
2103
 
2104
static void
2105
zap_molecule ()
2106
{
2107
  /* try */
2108
  if (atom != NULL)
2109
    {
2110
      free (atom);
2111
      atom = NULL;              /* added in v0.3j */
2112
    }
2113
  if (bond != NULL)
2114
    {
2115
      free (bond);
2116
      bond = NULL;              /* added in v0.3j */
2117
    }
2118
  if (ring != NULL)
2119
    {
2120
      free (ring);
2121
      ring = NULL;              /* added in v0.3j */
2122
    }
2123
  if (ringprop != NULL)
2124
    {
2125
      free (ringprop);
2126
      ringprop = NULL;          /* added in v0.3j */
2127
    }
2128
  /* except
2129
     on e:Einvalidpointer do begin end;
2130
     end; */
2131
  n_atoms = 0;
2132
  n_bonds = 0;
2133
  n_rings = 0;
2134
}
2135
 
2136
 
2137
static void
2138
zap_needle ()
2139
{
2140
  /* try */
2141
  if (ndl_atom != NULL)
2142
    {
2143
      free (ndl_atom);
2144
      ndl_atom = NULL;          /* added in v0.3j */
2145
    }
2146
  if (ndl_bond != NULL)
2147
    {
2148
      free (ndl_bond);
2149
      ndl_bond = NULL;          /* added in v0.3j */
2150
    }
2151
  if (ndl_ring != NULL)
2152
    {
2153
      free (ndl_ring);
2154
      ndl_ring = NULL;          /* added in v0.3j */
2155
    }
2156
  if (ndl_ringprop != NULL)
2157
    {
2158
      free (ndl_ringprop);      /* fixed in v0.3g */
2159
      ndl_ringprop = NULL;      /* added in v0.3j */
2160
    }
2161
  /* except
2162
     on e:Einvalidpointer do begin end;
2163
     end; */
2164
  ndl_n_atoms = 0;
2165
  ndl_n_bonds = 0;
2166
  ndl_n_rings = 0;
2167
}
2168
 
2169
#if 0
2170
static void
2171
zap_tmp ()
2172
{
2173
  /* try */
2174
  if (tmp_atom != NULL)
2175
    {
2176
      free (tmp_atom);
2177
      tmp_atom = NULL;          /* added in v0.3j */
2178
    }
2179
  if (tmp_bond != NULL)
2180
    {
2181
      free (tmp_bond);
2182
      tmp_bond = NULL;          /* added in v0.3j */
2183
    }
2184
  if (tmp_ring != NULL)
2185
    {
2186
      free (tmp_ring);
2187
      tmp_ring = NULL;          /* added in v0.3j */
2188
    }
2189
  if (tmp_ringprop != NULL)
2190
    {
2191
      free (tmp_ringprop);      /* fixed in v0.3g */
2192
      tmp_ringprop = NULL;      /* added in v0.3j */
2193
    }
2194
  /* except
2195
     on e:Einvalidpointer do begin end;
2196
     end; */
2197
  tmp_n_atoms = 0;
2198
  tmp_n_bonds = 0;
2199
  tmp_n_rings = 0;
2200
}
2201
#endif
2202
 
2203
static boolean
2204
is_heavyatom (id)
2205
     int id;
2206
{
2207
  str2 el;
2208
 
2209
  strcpy (el, atom[id - 1].element);
2210
 
2211
  if (!strcmp (el, "DU") || !strcmp (el, "LP"))
2212
    return false;
2213
  /*if (progmode == pmCheckMol && !strcmp (el, "H ")
2214
     && atom[id - 1].nucleon_number < 2)
2215
     return false;               0.3x  */
2216
  if (!strcmp (el, "H "))       /* 0.3 p */
2217
    {
2218
      if (progmode == pmMatchMol && !opt_iso)
2219
        {
2220
          return false;
2221
        }
2222
      else
2223
        {
2224
          if (atom[id - 1].nucleon_number < 2)
2225
            return false;
2226
        }
2227
    }
2228
  return true;
2229
}
2230
 
2231
 
2232
static boolean
2233
ndl_alkene_C (ba)
2234
     int ba;
2235
{
2236
  /* new in v0.3f */
2237
  boolean res = false;
2238
  int i, ba2, FORLIM;
2239
 
2240
  if (ndl_n_atoms <= 0 || ndl_n_bonds <= 0)
2241
    return false;
2242
  FORLIM = ndl_n_bonds;
2243
  for (i = 0; i < FORLIM; i++)
2244
    {
2245
      if (ndl_bond[i].a1 == ba || ndl_bond[i].a2 == ba)
2246
        {
2247
          if (ndl_bond[i].a1 == ba)
2248
            ba2 = ndl_bond[i].a2;
2249
          else
2250
            ba2 = ndl_bond[i].a1;
2251
          if (!strcmp (ndl_atom[ba - 1].atype, "C2 ") &&
2252
              !strcmp (ndl_atom[ba2 - 1].atype, "C2 ")
2253
              && ndl_bond[i].btype == 'D' && ndl_bond[i].arom == false)
2254
            res = true;
2255
        }
2256
    }
2257
  return res;
2258
}
2259
 
2260
 
2261
static boolean
2262
is_metal (id)
2263
     int id;
2264
{
2265
  boolean r = false;
2266
  str2 el;
2267
 
2268
  strcpy (el, atom[id - 1].element);
2269
  if (!strcmp (el, "LI") || !strcmp (el, "NA") || !strcmp (el, "K ") ||
2270
      !strcmp (el, "RB") || !strcmp (el, "CS") || !strcmp (el, "BE") ||
2271
      !strcmp (el, "MG") || !strcmp (el, "CA") || !strcmp (el, "SR") ||
2272
      !strcmp (el, "BA") || !strcmp (el, "TI") || !strcmp (el, "ZR") ||
2273
      !strcmp (el, "CR") || !strcmp (el, "MO") || !strcmp (el, "MN") ||
2274
      !strcmp (el, "FE") || !strcmp (el, "CO") || !strcmp (el, "NI") ||
2275
      !strcmp (el, "PD") || !strcmp (el, "PT") || !strcmp (el, "SN") ||
2276
      !strcmp (el, "CU") || !strcmp (el, "AG") || !strcmp (el, "AU") ||
2277
      !strcmp (el, "ZN") || !strcmp (el, "CD") || !strcmp (el, "HG") ||
2278
      !strcmp (el, "AL") || !strcmp (el, "SN") || !strcmp (el, "PB") ||
2279
      !strcmp (el, "SB") || !strcmp (el, "BI"))
2280
/* p2c: checkmol.pas, line 1577:
2281
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 1686 [251] */
2282
    /* etc. etc. */
2283
    r = true;
2284
  return r;
2285
}
2286
 
2287
 
2288
static int
2289
get_nvalences (a_el)
2290
     char *a_el;
2291
{
2292
  /* changed name and position in v0.3m */
2293
  /* preliminary version; should be extended to element/atomtype */
2294
  int res = 1;
2295
 
2296
  if (!strcmp (a_el, "H "))
2297
    res = 1;
2298
  /*if (!strcmp (a_el, "D "))   // v0.3n
2299
     res = 1; */
2300
  if (!strcmp (a_el, "C "))
2301
    res = 4;
2302
  if (!strcmp (a_el, "N "))
2303
    res = 3;
2304
  if (!strcmp (a_el, "O "))
2305
    res = 2;
2306
  if (!strcmp (a_el, "S "))
2307
    res = 2;
2308
  if (!strcmp (a_el, "SE"))
2309
    res = 2;
2310
  if (!strcmp (a_el, "TE"))
2311
    res = 2;
2312
  if (!strcmp (a_el, "P "))
2313
    res = 3;
2314
  if (!strcmp (a_el, "F "))
2315
    res = 1;
2316
  if (!strcmp (a_el, "CL"))
2317
    res = 1;
2318
  if (!strcmp (a_el, "BR"))
2319
    res = 1;
2320
  if (!strcmp (a_el, "I "))
2321
    res = 1;
2322
  if (!strcmp (a_el, "AT"))
2323
    res = 1;
2324
  if (!strcmp (a_el, "B "))
2325
    res = 3;
2326
  if (!strcmp (a_el, "LI"))
2327
    res = 1;
2328
  if (!strcmp (a_el, "NA"))
2329
    res = 1;
2330
  if (!strcmp (a_el, "K "))
2331
    res = 1;
2332
  if (!strcmp (a_el, "CA"))
2333
    res = 2;
2334
  if (!strcmp (a_el, "SR"))
2335
    res = 2;
2336
  if (!strcmp (a_el, "MG"))
2337
    res = 2;
2338
  if (!strcmp (a_el, "FE"))
2339
    res = 3;
2340
  if (!strcmp (a_el, "MN"))
2341
    res = 2;
2342
  if (!strcmp (a_el, "HG"))
2343
    res = 2;
2344
  if (!strcmp (a_el, "SI"))
2345
    res = 4;
2346
  if (!strcmp (a_el, "SN"))
2347
    res = 4;
2348
  if (!strcmp (a_el, "ZN"))
2349
    res = 2;
2350
  if (!strcmp (a_el, "CU"))
2351
    res = 2;
2352
  if (!strcmp (a_el, "A "))
2353
    res = 4;
2354
  if (!strcmp (a_el, "Q "))
2355
    res = 4;
2356
  return res;
2357
}
2358
 
2359
 
2360
static char *
2361
convert_type (Result, oldtype)
2362
     char *Result;
2363
     char *oldtype;
2364
{
2365
  int i;
2366
  str3 newtype;
2367
 
2368
  sprintf (newtype, "%.3s", oldtype);
2369
  for (i = 0; i <= 2; i++)
2370
    newtype[i] = toupper (newtype[i]);
2371
  if (newtype[0] == '~')
2372
    strcpy (newtype, "VAL");
2373
  if (newtype[0] == '*')
2374
    strcpy (newtype, "STR");
2375
  return strcpy (Result, newtype);
2376
}
2377
 
2378
 
2379
static char *
2380
convert_sybtype (Result, oldtype)
2381
     char *Result;
2382
     char *oldtype;
2383
{
2384
  str3 newtype;
2385
 
2386
  /*  NewType := Copy(OldType,1,3); */
2387
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2388
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2389
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2390
  strcpy (newtype, "DU ");
2391
  if (!strcmp (oldtype, "H    "))
2392
    strcpy (newtype, "H  ");
2393
  if (!strcmp (oldtype, "C.ar "))
2394
    strcpy (newtype, "CAR");
2395
  if (!strcmp (oldtype, "C.2  "))
2396
    strcpy (newtype, "C2 ");
2397
  if (!strcmp (oldtype, "C.3  "))
2398
    strcpy (newtype, "C3 ");
2399
  if (!strcmp (oldtype, "C.1  "))
2400
    strcpy (newtype, "C1 ");
2401
  if (!strcmp (oldtype, "O.2  "))
2402
    strcpy (newtype, "O2 ");
2403
  if (!strcmp (oldtype, "O.3  "))
2404
    strcpy (newtype, "O3 ");
2405
  if (!strcmp (oldtype, "O.co2"))
2406
    strcpy (newtype, "O2 ");
2407
  if (!strcmp (oldtype, "O.spc"))
2408
    strcpy (newtype, "O3 ");
2409
  if (!strcmp (oldtype, "O.t3p"))
2410
    strcpy (newtype, "O3 ");
2411
  if (!strcmp (oldtype, "N.1  "))
2412
    strcpy (newtype, "N1 ");
2413
  if (!strcmp (oldtype, "N.2  "))
2414
    strcpy (newtype, "N2 ");
2415
  if (!strcmp (oldtype, "N.3  "))
2416
    strcpy (newtype, "N3 ");
2417
  if (!strcmp (oldtype, "N.pl3"))
2418
    strcpy (newtype, "NPL");
2419
  if (!strcmp (oldtype, "N.4  "))
2420
    strcpy (newtype, "N3+");
2421
  if (!strcmp (oldtype, "N.am "))
2422
    strcpy (newtype, "NAM");
2423
  if (!strcmp (oldtype, "N.ar "))
2424
    strcpy (newtype, "NAR");
2425
  if (!strcmp (oldtype, "F    "))
2426
    strcpy (newtype, "F  ");
2427
  if (!strcmp (oldtype, "Cl   "))
2428
    strcpy (newtype, "CL ");
2429
  if (!strcmp (oldtype, "Br   "))
2430
    strcpy (newtype, "BR ");
2431
  if (!strcmp (oldtype, "I    "))
2432
    strcpy (newtype, "I  ");
2433
  if (!strcmp (oldtype, "Al   "))
2434
    strcpy (newtype, "AL ");
2435
  if (!strcmp (oldtype, "ANY  "))
2436
    strcpy (newtype, "A  ");
2437
  if (!strcmp (oldtype, "Ca   "))
2438
    strcpy (newtype, "CA ");
2439
  if (!strcmp (oldtype, "Du   "))
2440
    strcpy (newtype, "DU ");
2441
  if (!strcmp (oldtype, "Du.C "))
2442
    strcpy (newtype, "DU ");
2443
  if (!strcmp (oldtype, "H.spc"))
2444
    strcpy (newtype, "H  ");
2445
  if (!strcmp (oldtype, "H.t3p"))
2446
    strcpy (newtype, "H  ");
2447
  if (!strcmp (oldtype, "HAL  "))
2448
    strcpy (newtype, "Cl ");
2449
  if (!strcmp (oldtype, "HET  "))
2450
    strcpy (newtype, "Q  ");
2451
  if (!strcmp (oldtype, "HEV  "))
2452
    strcpy (newtype, "DU ");
2453
  if (!strcmp (oldtype, "K    "))
2454
    strcpy (newtype, "K  ");
2455
  if (!strcmp (oldtype, "Li   "))
2456
    strcpy (newtype, "LI ");
2457
  if (!strcmp (oldtype, "LP   "))
2458
    strcpy (newtype, "LP ");
2459
  if (!strcmp (oldtype, "Na   "))
2460
    strcpy (newtype, "NA ");
2461
  if (!strcmp (oldtype, "P.3  "))
2462
    strcpy (newtype, "P3 ");
2463
  if (!strcmp (oldtype, "S.2  "))
2464
    strcpy (newtype, "S2 ");
2465
  if (!strcmp (oldtype, "S.3  "))
2466
    strcpy (newtype, "S3 ");
2467
  if (!strcmp (oldtype, "S.o  "))
2468
    strcpy (newtype, "SO ");
2469
  if (!strcmp (oldtype, "S.o2 "))
2470
    strcpy (newtype, "SO2");
2471
  if (!strcmp (oldtype, "Si   "))
2472
    strcpy (newtype, "SI ");
2473
  if (!strcmp (oldtype, "P.4  "))
2474
    strcpy (newtype, "P4 ");
2475
  return strcpy (Result, newtype);
2476
}
2477
 
2478
 
2479
static char *
2480
convert_MDLtype (Result, oldtype)
2481
     char *Result, *oldtype;
2482
{
2483
  str3 newtype;
2484
 
2485
  /*  NewType := Copy(OldType,1,3); */
2486
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2487
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2488
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2489
  strcpy (newtype, "DU ");
2490
  if (!strcmp (oldtype, "H  "))
2491
    strcpy (newtype, "H  ");
2492
  if (!strcmp (oldtype, "C  "))
2493
    strcpy (newtype, "C3 ");
2494
  if (!strcmp (oldtype, "O  "))
2495
    strcpy (newtype, "O2 ");
2496
  if (!strcmp (oldtype, "N  "))
2497
    strcpy (newtype, "N3 ");
2498
  if (!strcmp (oldtype, "F  "))
2499
    strcpy (newtype, "F  ");
2500
  if (!strcmp (oldtype, "Cl "))
2501
    strcpy (newtype, "CL ");
2502
  if (!strcmp (oldtype, "Br "))
2503
    strcpy (newtype, "BR ");
2504
  if (!strcmp (oldtype, "I  "))
2505
    strcpy (newtype, "I  ");
2506
  if (!strcmp (oldtype, "Al "))
2507
    strcpy (newtype, "AL ");
2508
  if (!strcmp (oldtype, "ANY"))
2509
    strcpy (newtype, "A  ");
2510
  if (!strcmp (oldtype, "Ca "))
2511
    strcpy (newtype, "CA ");
2512
  if (!strcmp (oldtype, "Du "))
2513
    strcpy (newtype, "DU ");
2514
  if (!strcmp (oldtype, "K  "))
2515
    strcpy (newtype, "K  ");
2516
  if (!strcmp (oldtype, "Li "))
2517
    strcpy (newtype, "LI ");
2518
  if (!strcmp (oldtype, "LP "))
2519
    strcpy (newtype, "LP ");
2520
  if (!strcmp (oldtype, "Na "))
2521
    strcpy (newtype, "NA ");
2522
  if (!strcmp (oldtype, "P  "))
2523
    strcpy (newtype, "P3 ");
2524
  if (!strcmp (oldtype, "S  "))
2525
    strcpy (newtype, "S3 ");
2526
  if (!strcmp (oldtype, "Si "))
2527
    strcpy (newtype, "SI ");
2528
  if (!strcmp (oldtype, "P  "))
2529
    strcpy (newtype, "P4 ");
2530
  if (!strcmp (oldtype, "A  "))
2531
    strcpy (newtype, "A  ");
2532
  if (!strcmp (oldtype, "Q  "))
2533
    strcpy (newtype, "Q  ");
2534
  return strcpy (Result, newtype);
2535
}
2536
 
2537
 
2538
static char *
2539
get_element (Result, oldtype)
2540
     char *Result;
2541
     char *oldtype;
2542
{
2543
  char elemstr[256];
2544
 
2545
  if (!strcmp (oldtype, "H   "))
2546
    strcpy (elemstr, "H ");
2547
  /* if (!strcmp (oldtype, "D   "))  // v0.3n
2548
     strcpy (elemstr, "D "); */
2549
  if (!strcmp (oldtype, "CAR "))
2550
    strcpy (elemstr, "C ");
2551
  if (!strcmp (oldtype, "C2  "))
2552
    strcpy (elemstr, "C ");
2553
  if (!strcmp (oldtype, "C3  "))
2554
    strcpy (elemstr, "C ");
2555
  if (!strcmp (oldtype, "C1  "))
2556
    strcpy (elemstr, "C ");
2557
  if (!strcmp (oldtype, "O2  "))
2558
    strcpy (elemstr, "O ");
2559
  if (!strcmp (oldtype, "O3  "))
2560
    strcpy (elemstr, "O ");
2561
  if (!strcmp (oldtype, "O2  "))
2562
    strcpy (elemstr, "O ");
2563
  if (!strcmp (oldtype, "O3  "))
2564
    strcpy (elemstr, "O ");
2565
  if (!strcmp (oldtype, "O3  "))
2566
    strcpy (elemstr, "O ");
2567
  if (!strcmp (oldtype, "N1  "))
2568
    strcpy (elemstr, "N ");
2569
  if (!strcmp (oldtype, "N2  "))
2570
    strcpy (elemstr, "N ");
2571
  if (!strcmp (oldtype, "N3  "))
2572
    strcpy (elemstr, "N ");
2573
  if (!strcmp (oldtype, "NPL "))
2574
    strcpy (elemstr, "N ");
2575
  if (!strcmp (oldtype, "N3+ "))
2576
    strcpy (elemstr, "N ");
2577
  if (!strcmp (oldtype, "NAM "))
2578
    strcpy (elemstr, "N ");
2579
  if (!strcmp (oldtype, "NAR "))
2580
    strcpy (elemstr, "N ");
2581
  if (!strcmp (oldtype, "F   "))
2582
    strcpy (elemstr, "F ");
2583
  if (!strcmp (oldtype, "CL  "))
2584
    strcpy (elemstr, "CL");
2585
  if (!strcmp (oldtype, "BR  "))
2586
    strcpy (elemstr, "BR");
2587
  if (!strcmp (oldtype, "I   "))
2588
    strcpy (elemstr, "I ");
2589
  if (!strcmp (oldtype, "AT  "))
2590
    strcpy (elemstr, "AT");
2591
  if (!strcmp (oldtype, "AL  "))
2592
    strcpy (elemstr, "AL");
2593
  if (!strcmp (oldtype, "DU  "))
2594
    strcpy (elemstr, "DU");
2595
  if (!strcmp (oldtype, "CA  "))
2596
    strcpy (elemstr, "CA");
2597
  if (!strcmp (oldtype, "DU  "))
2598
    strcpy (elemstr, "DU");
2599
  if (!strcmp (oldtype, "Cl  "))
2600
    strcpy (elemstr, "CL");
2601
  if (!strcmp (oldtype, "K   "))
2602
    strcpy (elemstr, "K ");
2603
  if (!strcmp (oldtype, "LI  "))
2604
    strcpy (elemstr, "LI");
2605
  if (!strcmp (oldtype, "LP  "))
2606
    strcpy (elemstr, "LP");
2607
  if (!strcmp (oldtype, "NA  "))
2608
    strcpy (elemstr, "NA");
2609
  if (!strcmp (oldtype, "P3  "))
2610
    strcpy (elemstr, "P ");
2611
  if (!strcmp (oldtype, "S2  "))
2612
    strcpy (elemstr, "S ");
2613
  if (!strcmp (oldtype, "S3  "))
2614
    strcpy (elemstr, "S ");
2615
  if (!strcmp (oldtype, "SO  "))
2616
    strcpy (elemstr, "S ");
2617
  if (!strcmp (oldtype, "SO2 "))
2618
    strcpy (elemstr, "S ");
2619
  if (!strcmp (oldtype, "SI  "))
2620
    strcpy (elemstr, "SI");
2621
  if (!strcmp (oldtype, "P4  "))
2622
    strcpy (elemstr, "P ");
2623
  if (!strcmp (oldtype, "A   "))
2624
    strcpy (elemstr, "A ");
2625
  if (!strcmp (oldtype, "Q   "))
2626
    strcpy (elemstr, "Q ");
2627
  return strcpy (Result, elemstr);
2628
}
2629
 
2630
 
2631
static char *
2632
get_sybelement (Result, oldtype)
2633
     char *Result;
2634
     char *oldtype;
2635
{
2636
  int i;
2637
  str2 elemstr;
2638
 
2639
  if (strpos2 (oldtype, ".", 1) < 2)
2640
    sprintf (elemstr, "%.2s", oldtype);
2641
  else
2642
    {
2643
      sprintf (elemstr, "%.*s", strpos2 (oldtype, ".", 1) - 1, oldtype);
2644
      if (strlen (elemstr) < 2)
2645
        strcat (elemstr, " ");
2646
    }
2647
  for (i = 0; i <= 1; i++)
2648
    elemstr[i] = toupper (elemstr[i]);
2649
  return strcpy (Result, elemstr);
2650
}
2651
 
2652
 
2653
static char *
2654
get_MDLelement (Result, oldtype)
2655
     char *Result;
2656
     char *oldtype;
2657
{
2658
  int i;
2659
  str2 elemstr;
2660
 
2661
  sprintf (elemstr, "%.2s", oldtype);
2662
  for (i = 0; i <= 1; i++)
2663
    elemstr[i] = toupper (elemstr[i]);
2664
  if (elemstr[0] == '~')
2665
    strcpy (elemstr, "??");
2666
  if (elemstr[0] == '*')
2667
    strcpy (elemstr, "??");
2668
  return strcpy (Result, elemstr);
2669
}
2670
 
2671
static void
2672
read_molfile (mfilename)
2673
     char *mfilename;
2674
{
2675
  /* reads ALCHEMY mol files */
6787 kbelabas 2676
  int n;
6785 bpr 2677
  char rline[256], tmpstr[256];
2678
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2679
  float xval, yval, zval, chgval;
2680
  char a1str[256], a2str[256], elemstr[256];
2681
  int a1val, a2val, ri;
2682
  char STR1[256];
2683
  int FORLIM;
2684
  atom_rec *WITH;
2685
  bond_rec *WITH1;
2686
 
2687
  if (n_atoms > 0)
2688
    zap_molecule ();
2689
  ri = li;
2690
  strcpy (rline, molbuf[ri - 1]);
2691
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2692
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2693
  strsub (tmpstr, rline, 14, 5);
6787 kbelabas 2694
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2695
  strsub (molname, rline, 42, (int) (strlen (rline) - 42L));
2696
  /* try */
2697
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2698
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2699
  ring = safe_calloc (1, sizeof (ringlist));
2700
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2701
  /* except
2702
     on e:Eoutofmemory do
2703
     begin
2704
     writeln('Not enough memory');
2705
     halt(4);
2706
     end;
2707
     end; */
2708
  n_heavyatoms = 0;
2709
  n_heavybonds = 0;
2710
  n_Ctot = 0;                   /* v0.3g */
2711
  n_Otot = 0;                   /* v0.3g */
2712
  n_Ntot = 0;                   /* v0.3g */
2713
  FORLIM = n_atoms;
2714
  for (n = 1; n <= FORLIM; n++)
2715
    {
2716
      ri++;
2717
      strcpy (rline, molbuf[ri - 1]);
2718
      strsub (atomtype, rline, 7, 4);
2719
      sprintf (STR1, "%c", toupper (*atomtype));
2720
      strcpy (atomtype, STR1);  /* fixed in v0.3f */
2721
      get_element (elemstr, atomtype);
2722
      if (!strcmp (elemstr, "C "))
2723
        n_Ctot++;
2724
      if (!strcmp (elemstr, "O "))
2725
        n_Otot++;
2726
      if (!strcmp (elemstr, "N "))
2727
        n_Ntot++;
2728
      convert_type (newatomtype, atomtype);
2729
      strsub (xstr, rline, 14, 7);
2730
      strsub (ystr, rline, 23, 7);
2731
      strsub (zstr, rline, 32, 7);
2732
      strsub (chgstr, rline, 43, 7);
6787 kbelabas 2733
      (void)sscanf (xstr, "%g", &xval);
2734
      (void)sscanf (ystr, "%g", &yval);
2735
      (void)sscanf (zstr, "%g", &zval);
2736
      (void)sscanf (chgstr, "%g", &chgval);
6785 bpr 2737
      WITH = &atom[n - 1];
2738
      strcpy (WITH->element, elemstr);
2739
      strcpy (WITH->atype, newatomtype);
2740
      WITH->x = xval;
2741
      WITH->y = yval;
2742
      WITH->z = zval;
2743
      WITH->real_charge = chgval;
2744
      if (is_heavyatom (n))
2745
        {
2746
          n_heavyatoms++;
2747
          WITH->heavy = true;
2748
          if (is_metal (n))
2749
            WITH->metal = true;
2750
        }
2751
      WITH->nvalences = get_nvalences (WITH->element);  /* v0.3m   */
2752
    }
2753
  /*
2754
     with atom^[n] do
2755
     begin
2756
     x := 0; y := 0; z := 0;  (* v0.3g
2757
     formal_charge  := 0;
2758
     real_charge    := 0;
2759
     Hexp           := 0;
2760
     Htot           := 0;
2761
     neighbor_count := 0;
2762
     ring_count     := 0;
2763
     arom           := false;
2764
     stereo_care    := false;
2765
     heavy          := false;
2766
     metal          := false;
2767
     tag            := false;
2768
     end;
2769
   */
2770
  FORLIM = n_bonds;
2771
  for (n = 0; n < FORLIM; n++)
2772
    {
2773
      ri++;
2774
      strcpy (rline, molbuf[ri - 1]);
2775
      strsub (a1str, rline, 9, 3);
2776
      strsub (a2str, rline, 15, 3);
6787 kbelabas 2777
      (void)sscanf(a1str, "%d", &a1val);
2778
      (void)sscanf(a2str, "%d", &a2val);
6785 bpr 2779
      WITH1 = &bond[n];
2780
      WITH1->a1 = a1val;
2781
      WITH1->a2 = a2val;
2782
      WITH1->btype = rline[19];
2783
      WITH1->ring_count = 0;
2784
      WITH1->arom = false;
2785
      WITH1->topo = btopo_any;
2786
      WITH1->stereo = bstereo_any;
2787
      WITH1->mdl_stereo = 0;    /* v0.3n */
2788
      if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2789
        n_heavybonds++;
2790
    }
2791
  memset (ring, 0, sizeof (ringlist));
2792
  for (n = 0; n < max_rings; n++)
2793
    {                           /* new in v0.3 */
2794
      ringprop[n].size = 0;
2795
      ringprop[n].arom = false;
2796
      ringprop[n].envelope = false;
2797
    }
2798
  li = ri + 1;
2799
}
2800
 
2801
 
2802
static void
2803
read_mol2file (mfilename)
2804
     char *mfilename;
2805
{
2806
  /* reads SYBYL mol2 files */
2807
  int n, code;
2808
  char sybatomtype[6];
2809
  char tmpstr[256], rline[256];
2810
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2811
  float xval, yval, zval, chgval;
2812
  char a1str[256], a2str[256], elemstr[256];
2813
  int a1val, a2val, ri, FORLIM;
2814
  atom_rec *WITH;
2815
  bond_rec *WITH1;
2816
 
2817
  if (n_atoms > 0)
2818
    zap_molecule ();
2819
  *rline = '\0';
2820
  ri = li - 1;
2821
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) == 0))
2822
    {
2823
      ri++;
2824
      strcpy (rline, molbuf[ri - 1]);
2825
    }
2826
  if (ri < molbufindex)
2827
    {
2828
      ri++;
2829
      strcpy (molname, molbuf[ri - 1]);
2830
    }
2831
  if (ri < molbufindex)
2832
    {
2833
      ri++;
2834
      strcpy (rline, molbuf[ri - 1]);
2835
    }
2836
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2837
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2838
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2839
  strsub (tmpstr, rline, 7, 5);
6787 kbelabas 2840
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2841
  /* try */
2842
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2843
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2844
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2845
  ring = safe_calloc (1, sizeof (ringlist));
2846
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2847
  /* except
2848
     on e:Eoutofmemory do
2849
     begin
2850
     writeln('Not enough memory');
2851
     halt(4);
2852
     end;
2853
     end; */
2854
  n_heavyatoms = 0;
2855
  n_heavybonds = 0;
2856
  n_Ctot = 0;                   /* v0.3g */
2857
  n_Otot = 0;                   /* v0.3g */
2858
  n_Ntot = 0;                   /* v0.3g */
2859
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>ATOM", 1) == 0))
2860
    {
2861
      ri++;
2862
      strcpy (rline, molbuf[ri - 1]);
2863
    }
2864
  FORLIM = n_atoms;
2865
  for (n = 1; n <= FORLIM; n++)
2866
    {
2867
      /*
2868
         with atom^[n] do
2869
         begin
2870
         x := 0; y := 0; z := 0;  (* v0.3g
2871
         formal_charge  := 0;
2872
         real_charge    := 0;
2873
         Hexp           := 0;
2874
         Htot           := 0;
2875
         neighbor_count := 0;
2876
         ring_count     := 0;
2877
         arom           := false;
2878
         stereo_care    := false;
2879
         heavy          := false;
2880
         metal          := false;
2881
         tag            := false;
2882
         end;
2883
       */
2884
      if (ri < molbufindex)
2885
        {
2886
          ri++;
2887
          strcpy (rline, molbuf[ri - 1]);
2888
        }
2889
      strsub (sybatomtype, rline, 48, 5);
2890
      get_sybelement (elemstr, sybatomtype);
2891
      if (!strcmp (elemstr, "C "))
2892
        n_Ctot++;
2893
      if (!strcmp (elemstr, "O "))
2894
        n_Otot++;
2895
      if (!strcmp (elemstr, "N "))
2896
        n_Ntot++;
2897
      convert_sybtype (newatomtype, sybatomtype);
2898
      strsub (xstr, rline, 18, 9);
2899
      strsub (ystr, rline, 28, 9);
2900
      strsub (zstr, rline, 38, 9);
2901
      strsub (chgstr, rline, 70, 9);
6787 kbelabas 2902
      (void)sscanf (xstr, "%g", &xval);
2903
      (void)sscanf (ystr, "%g", &yval);
2904
      (void)sscanf (zstr, "%g", &zval);
2905
      (void)sscanf (chgstr, "%g", &chgval);
6785 bpr 2906
      WITH = &atom[n - 1];
2907
      strcpy (WITH->element, elemstr);
2908
      strcpy (WITH->atype, newatomtype);
2909
      WITH->x = xval;
2910
      WITH->y = yval;
2911
      WITH->z = zval;
2912
      WITH->real_charge = chgval;
2913
      if (is_heavyatom (n))
2914
        {
2915
          n_heavyatoms++;
2916
          WITH->heavy = true;
2917
          if (is_metal (n))
2918
            WITH->metal = true;
2919
        }
2920
      WITH->nvalences = get_nvalences (WITH->element);  /* v0.3m   */
2921
    }
2922
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>BOND", 1) == 0))
2923
    {
2924
      ri++;
2925
      strcpy (rline, molbuf[ri - 1]);
2926
    }
2927
  FORLIM = n_bonds;
2928
  for (n = 0; n < FORLIM; n++)
2929
    {
2930
      if (ri < molbufindex)
2931
        {
2932
          ri++;
2933
          strcpy (rline, molbuf[ri - 1]);
2934
        }
2935
      strsub (a1str, rline, 9, 3);
2936
      strsub (a2str, rline, 14, 3);
2937
      code = (sscanf (a1str, "%d", &a1val) == 0);
2938
      if (code != 0)
2939
        printf ("%s\007\n", rline);
2940
      code = (sscanf (a2str, "%d", &a2val) == 0);
2941
      if (code != 0)
2942
        printf ("%s\007\n", rline);
2943
      WITH1 = &bond[n];
2944
      WITH1->a1 = a1val;
2945
      WITH1->a2 = a2val;
2946
      if (rline[17] == '1')
2947
        WITH1->btype = 'S';
2948
      if (rline[17] == '2')
2949
        WITH1->btype = 'D';
2950
      if (rline[17] == '3')
2951
        WITH1->btype = 'T';
2952
      if (rline[17] == 'a')
2953
        WITH1->btype = 'A';
2954
      WITH1->ring_count = 0;
2955
      WITH1->arom = false;
2956
      WITH1->topo = btopo_any;
2957
      WITH1->stereo = bstereo_any;
2958
      WITH1->mdl_stereo = 0;    /* v0.3n */
2959
      if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2960
        n_heavybonds++;
2961
    }
2962
  memset (ring, 0, sizeof (ringlist));
2963
  for (n = 0; n < max_rings; n++)
2964
    {                           /* new in v0.3 */
2965
      ringprop[n].size = 0;
2966
      ringprop[n].arom = false;
2967
      ringprop[n].envelope = false;
2968
    }
2969
  li = ri + 1;
2970
}
2971
 
2972
 
2973
static void
2974
read_charges (chgstring_)
2975
     char *chgstring_;
2976
{
2977
  char chgstring[256];
2978
  int a_id, a_chg;
2979
  /* int n_chrg;*/
2980
 
2981
  /* typical example: a molecule with 2 cations + 1 anion */
2982
  /* M  CHG  3   8   1  10   1  11  -1 */
2983
  strcpy (chgstring, chgstring_);
2984
  if (strpos2 (chgstring, "M  CHG", 1) <= 0)
2985
    return;
2986
  strdelete (chgstring, 1, 6);
2987
  left_trim (chgstring);
2988
 /* n_chrg = left_int (chgstring);*/
2989
  /* this assignment must be kept also in non-debug mode! */
2990
/* p2c: checkmol.pas, line 2077:
2991
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
2992
  /*$IFDEF debug */
2993
  /*if (n_chrg == 0)
2994
     debugoutput ("strange... M  CHG present, but no charges found"); */
2995
  /*$ENDIF */
2996
  while (*chgstring != '\0')
2997
    {
2998
      a_id = left_int (chgstring);
2999
      a_chg = left_int (chgstring);
3000
      if (a_id != 0 && a_chg != 0)
3001
        atom[a_id - 1].formal_charge = a_chg;
3002
      //printf ("CHG %i %i\n", a_id, a_chg);
3003
    }
3004
}
3005
 
3006
static void
3007
read_isotopes (char *isotopestring_)
3008
{
3009
  char isotopestring[256];
3010
  int a_id, a_nucleon_number;
3011
  /* int n_isotopes;*/
3012
 
3013
  /* typical example: a molecule with 2 cations + 1 anion */
3014
  /* M  CHG  3   8   1  10   1  11  -1 */
3015
  strcpy (isotopestring, isotopestring_);
3016
  if (strpos2 (isotopestring, "M  ISO", 1) <= 0)
3017
    return;
3018
  strdelete (isotopestring, 1, 6);
3019
  left_trim (isotopestring);
3020
  /*n_isotopes = left_int (isotopestring);*/
3021
  /* this assignment must be kept also in non-debug mode! */
3022
/* p2c: checkmol.pas, line 2077:
3023
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3024
  /*$IFDEF debug */
3025
  /*if (n_chrg == 0)
3026
     debugoutput ("strange... M  CHG present, but no charges found"); */
3027
  /*$ENDIF */
3028
  while (*isotopestring != '\0')
3029
    {
3030
      a_id = left_int (isotopestring);
3031
      a_nucleon_number = left_int (isotopestring);
3032
      if (a_id != 0 && a_nucleon_number != 0)
3033
        {
3034
          atom[a_id - 1].nucleon_number = a_nucleon_number;
3035
          if (!strcmp (atom[a_id - 1].element, "H "))
3036
            {
3037
              atom[a_id - 1].heavy = true;
3038
              n_heavyatoms++;
3039
              strcpy (atom[a_id - 1].atype, "DU ");
3040
            }
3041
        }
3042
      //printf ("ISO %i %i\n", a_id, a_nucleon_number);
3043
    }
3044
}
3045
 
3046
static void
3047
read_radicals (radstring_)
3048
     char *radstring_;
3049
{
3050
  char radstring[256];
6788 kbelabas 3051
  int a_id, a_rad;
6785 bpr 3052
 
3053
  /* typical example: a molecule with 2 cations + 1 anion */
3054
  /* M  CHG  3   8   1  10   1  11  -1 */
3055
  strcpy (radstring, radstring_);
3056
  if (strpos2 (radstring, "M  RAD", 1) <= 0)
3057
    return;
3058
  strdelete (radstring, 1, 6);
3059
  left_trim (radstring);
6788 kbelabas 3060
  (void)left_int (radstring);
6785 bpr 3061
  /* this assignment must be kept also in non-debug mode! */
3062
/* p2c: checkmol.pas, line 2077:
3063
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3064
  /*$IFDEF debug */
3065
  /*if (n_chrg == 0)
3066
     debugoutput ("strange... M  CHG present, but no charges found"); */
3067
  /*$ENDIF */
3068
  while (*radstring != '\0')
3069
    {
3070
      a_id = left_int (radstring);
3071
      a_rad = left_int (radstring);
3072
      if (a_id != 0 && a_rad != 0)
3073
        atom[a_id - 1].radical_type = a_rad;
3074
      //printf ("RAD %i %i\n", a_id, a_rad);
3075
    }
3076
}
3077
 
3078
 
3079
static void
3080
read_MDLmolfile (char *mfilename)
3081
{
3082
  /* reads MDL mol files */
3083
  int n, v, tmp_n_atoms, tmp_n_bonds, code;     /* v0.3l */
3084
  char rline[256], tmpstr[256];
3085
  char xstr[256], ystr[256], zstr[256], chgstr[256];
3086
  float xval, yval, zval, chgval;
3087
  char a1str[256], a2str[256], elemstr[256];
3088
  int a1val, a2val, ri, rc, bt, bs;
3089
  int sepcount = 0;
3090
  int i;                        /* v0.3j */
3091
  boolean clearcharges = true;  /* v0.3j */
3092
  char STR1[256];
3093
/*  int FORLIM;*/
3094
  atom_rec *WITH;
3095
  bond_rec *WITH1;
3096
 
3097
  /* v0.3j */
3098
  if (n_atoms > 0)
3099
    zap_molecule ();
3100
  /*cm_mdlmolfile := false; */
3101
  *rline = '\0';
3102
  ri = li;
3103
  strcpy (molname, molbuf[ri - 1]);     /* line 1 */
3104
  if (ri < molbufindex)         /* line 2 */
3105
    ri++;
3106
  strcpy (rline, molbuf[ri - 1]);
3107
  if (strpos2 (rline, "CheckMol", 1) == 3)
3108
    {
3109
      /*cm_mdlmolfile := true; */
3110
      found_arominfo = true;
3111
      tmfcode = 1;              /* v0.3m (begin) */
3112
      code = 0;
3113
      if ((strlen (rline) >= 39) && (strpos2 (rline, "TMF", 1) == 35))
3114
        {                       /* v0.3m; encoding of tweaklevel */
3115
          strsub (tmpstr, rline, 38, 2);
3116
          code = (sscanf (tmpstr, "%d", &tmfcode) == 0);
3117
        }
3118
      if (code != 0 || tmfcode != tweaklevel)
3119
        tmfmismatch = true;
3120
      else
3121
        tmfmismatch = false;
3122
      if ((strpos2 (rline, ":r0", 1) >= 40 && ringsearch_mode != rs_sar) |
3123
          (strpos2 (rline, ":r1", 1) >= 40 && ringsearch_mode != rs_ssr))
3124
        tmfmismatch = true;
3125
      if ((strpos2 (rline, ":m0", 1) >= 40 && opt_metalrings == true) |
3126
          (strpos2 (rline, ":m1", 1) >= 40 && opt_metalrings == false))
3127
        tmfmismatch = true;
3128
/* p2c: checkmol.pas, line 2128:
3129
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3130
      /*$IFDEF debug */
3131
      //if (tmfmismatch)
3132
      //printf ("\"tweaked\" molfile: version mismatch!\n");
3133
      // else
3134
      //printf ("\"tweaked\" molfile: version OK");
3135
    }
3136
  /*$ENDIF */
3137
  /* v0.3m (end) */
3138
  if (ri < molbufindex)         /* line 3 */
3139
    ri++;
3140
  strcpy (rline, molbuf[ri - 1]);
3141
  strcpy (molcomment, rline);
3142
  if (ri < molbufindex)         /* line 4 */
3143
    ri++;
3144
  strcpy (rline, molbuf[ri - 1]);
3145
  sprintf (tmpstr, "%.3s", rline);
6787 kbelabas 3146
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 3147
  strsub (tmpstr, rline, 4, 3);
6787 kbelabas 3148
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 3149
  strsub (tmpstr, rline, 10, 3);
3150
  /* if it is a CheckMol-tweaked molfile, this is the number of rings */
3151
  n_cmrings = 0;
3152
  code = (sscanf (tmpstr, "%d", &n_cmrings) == 0);
3153
  if (code != 0)
3154
    n_cmrings = 0;
3155
  /* do some range checking for n_atoms, n_bonds; new in v0.3l */
3156
  tmp_n_atoms = n_atoms;
3157
  if (n_atoms > max_atoms)
3158
    n_atoms = max_atoms;
3159
  if (n_atoms < 0)
3160
    n_atoms = 0;
3161
  tmp_n_bonds = n_bonds;
3162
  if (n_bonds > max_bonds)
3163
    n_bonds = max_bonds;
3164
  if (n_bonds < 0)
3165
    n_bonds = 0;
3166
  if (n_atoms == 0
3167
#ifndef MAKE_SHARED_LIBRARY
3168
      && opt_verbose
3169
#endif
3170
    )
3171
    {                           /* v0.3l */
3172
      printf ("WARNING: Possible NoStruct read!\n");
3173
      printf ("NoStructs are proprietary, obsolete and dangerous.\n");
3174
    }
3175
  /* try */
3176
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
3177
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
3178
  /* this would be only one safe_calloc() in C;  v0.3l */
3179
  ring = safe_calloc (1, sizeof (ringlist));
3180
  ringprop = safe_calloc (1, sizeof (ringprop_type));
3181
  /* except
3182
     on e:Eoutofmemory do
3183
     begin
3184
     writeln('Not enough memory');
3185
     (* close(molfile);
3186
     halt(4);
3187
     exit;
3188
     end;
3189
     end; */
3190
  /* check for the chirality flag */
3191
  if (strlen (rline) > 14 && rline[14] == '1')  /* new in v0.3f */
3192
    chir_flag = true;
3193
  n_heavyatoms = 0;
3194
  n_heavybonds = 0;
3195
  n_Ctot = 0;                   /* v0.3g */
3196
  n_Otot = 0;                   /* v0.3g */
3197
  n_Ntot = 0;                   /* v0.3g */
3198
  if (n_atoms > 0)
3199
    {                           /* v0.3l */
3200
      for (n = 1; n <= tmp_n_atoms; n++)
3201
        {
3202
          if (n <= max_atoms)
3203
            v = n;
3204
          else
3205
            v = max_atoms;
3206
          /* just for safety; v0.3l */
3207
          /*
3208
             with atom^[v] do
3209
             begin
3210
             x := 0; y := 0; z := 0;  (* v0.3g
3211
             formal_charge  := 0;
3212
             real_charge    := 0;
3213
             Hexp           := 0;
3214
             Htot           := 0;
3215
             neighbor_count := 0;
3216
             ring_count     := 0;
3217
             arom           := false;
3218
             stereo_care    := false;
3219
             metal          := false;
3220
             heavy          := false;
3221
             tag            := false;
3222
             end;
3223
           */
3224
          /* replaced by fillchar() after getmem() (see above); v0.3l */
3225
          ri++;
3226
          strcpy (rline, molbuf[ri - 1]);
3227
          strsub (atomtype, rline, 32, 3);
3228
          get_MDLelement (elemstr, atomtype);
3229
          if (!strcmp (elemstr, "C "))
3230
            n_Ctot++;
3231
          if (!strcmp (elemstr, "O "))
3232
            n_Otot++;
3233
          if (!strcmp (elemstr, "N "))
3234
            n_Ntot++;
3235
 
3236
          convert_MDLtype (newatomtype, atomtype);
3237
          strsub (xstr, rline, 1, 10);  /* fixed in v0.3k (was: 2,9 etc.) */
3238
          strsub (ystr, rline, 11, 10);
3239
          strsub (zstr, rline, 21, 10);
3240
          /*chgstr := '0'; */
3241
          strsub (chgstr, rline, 37, 3);        /* new in v0.3j */
6787 kbelabas 3242
          (void)sscanf (chgstr, "%f", &chgval);
6785 bpr 3243
          if (chgval != 0)
3244
            {
3245
              if (chgval >= 1 && chgval <= 7)
3246
                chgval = 4.0 - chgval;
3247
              else
3248
                {
3249
                  chgval = 0.0;
3250
                }
3251
            }                   /* end (v0.3j) */
6787 kbelabas 3252
          (void)sscanf (xstr, "%f", &xval);
3253
          (void)sscanf (ystr, "%f", &yval);
3254
          (void)sscanf (zstr, "%f", &zval);
6785 bpr 3255
          /* v0.3k: removed superfluous val(chgstr,chgval,code) */
3256
          WITH = &atom[v - 1];
3257
          strcpy (WITH->element, elemstr);
3258
          if (!strcmp (elemstr, "A ") || !strcmp (elemstr, "Q ") ||
3259
              !strcmp (elemstr, "X "))
3260
            /* 'X ' added in v0.3n */
3261
            found_querymol = true;
3262
 
3263
          strcpy (WITH->atype, newatomtype);
3264
 
3265
 
3266
          if (!strcmp (elemstr, "D "))
3267
            {
3268
              strcpy (WITH->element, "H ");
3269
              WITH->nucleon_number = 2;
3270
            }                   /* 0.3x */
3271
          if (!strcmp (elemstr, "T "))
3272
            {
3273
              strcpy (WITH->element, "H ");
3274
              WITH->nucleon_number = 3;
3275
            }                   /* 0.3x */
3276
 
3277
 
3278
 
3279
          WITH->x = xval;
3280
          WITH->y = yval;
3281
          WITH->z = zval;
3282
          WITH->formal_charge = (long) floor (chgval + 0.5);
3283
          WITH->real_charge = 0.0;      /* v0.3j */
3284
          /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3285
          if (strlen (rline) > 37 && rline[37] == '0')
3286
            {
3287
              WITH->arom = true;
3288
              found_arominfo = true;
3289
            }
3290
          /* new in v0.3d: read stereo care flag */
3291
          if (strlen (rline) > 47 && rline[47] == '1')
3292
            WITH->stereo_care = true;
3293
          if (is_heavyatom (n))
3294
            {
3295
              n_heavyatoms++;
3296
              WITH->heavy = true;
3297
              if (is_metal (n))
3298
                WITH->metal = true;
3299
            }
3300
          WITH->nvalences = get_nvalences (WITH->element);
3301
          /* v0.3m                 */
3302
        }
3303
    }                           /* if (n_atoms > 0)... */
3304
  if (n_bonds > 0)
3305
    {                           /* v0.3l */
3306
      for (n = 1; n <= tmp_n_bonds; n++)
3307
        {
3308
          if (n <= max_bonds)
3309
            v = n;
3310
          else
3311
            v = max_bonds;
3312
          /* just for safety; v0.3l */
3313
          ri++;
3314
          strcpy (rline, molbuf[ri - 1]);
3315
          sprintf (a1str, "%.3s", rline);
3316
          strsub (a2str, rline, 4, 3);
3317
          code = (sscanf (a1str, "%d", &a1val) == 0);
3318
          if (code != 0)        /* v0.3l */
3319
            a1val = 1;
3320
          code = (sscanf (a2str, "%d", &a2val) == 0);
3321
          if (code != 0)        /* v0.3l */
3322
            a2val = 1;
3323
          WITH1 = &bond[v - 1];
3324
          WITH1->a1 = a1val;
3325
          WITH1->a2 = a2val;
3326
          if (rline[8] == '1')  /* single */
3327
            WITH1->btype = 'S';
3328
          if (rline[8] == '2')  /* double */
3329
            WITH1->btype = 'D';
3330
          if (rline[8] == '3')  /* triple */
3331
            WITH1->btype = 'T';
3332
          if (rline[8] == '4')  /* aromatic */
3333
            WITH1->btype = 'A';
3334
          if (rline[8] == '5')  /* single or double */
3335
            WITH1->btype = 'l';
3336
          if (rline[8] == '6')  /* single or aromatic */
3337
            WITH1->btype = 's';
3338
          if (rline[8] == '7')  /* double or aromatic */
3339
            WITH1->btype = 'd';
3340
          if (rline[8] == '8')  /* any */
3341
            WITH1->btype = 'a';
3342
          sprintf (STR1, "%c", WITH1->btype);
3343
          if (strpos2 ("lsda", STR1, 1) > 0)
3344
            found_querymol = true;
3345
          WITH1->arom = false;
3346
          WITH1->q_arom = false;        /* 0.3p */
3347
          /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3348
          if (WITH1->btype == 'A' || rline[7] == '0')
3349
            {
3350
              WITH1->arom = true;
3351
              if (rline[7] == '0')
3352
                found_arominfo = true;
3353
            }
3354
          strsub (tmpstr, rline, 13, 3);
3355
          /* new in v0.3d: read ring_count from tweaked molfile */
3356
          code = (sscanf (tmpstr, "%d", &rc) == 0);
3357
          if (code != 0 || rc < 0 || progmode == pmCheckMol || tmfmismatch)
3358
            WITH1->ring_count = 0;
3359
          else
3360
            WITH1->ring_count = rc;
3361
          /* v0.3n: added tmfmismatch check */
3362
          strsub (tmpstr, rline, 16, 3);        /* new in v0.3d: read bond topology; */
3363
          code = (sscanf (tmpstr, "%d", &bt) == 0);
3364
          /* extended features are encoded by leading zero */
3365
          if (code != 0 || (unsigned long) bt > 2)
3366
            WITH1->topo = btopo_any;
3367
          else
3368
            {
3369
              if (tmpstr[1] == '0')
3370
                WITH1->topo = bt + 3;
3371
              else
3372
                WITH1->topo = bt;
3373
            }
3374
          /* v0.3n changed >5 into >2 */
3375
          /* new in v0.3d: add stereo property from MDL "stereo care" flag in atom block */
3376
          WITH1->stereo = bstereo_any;
3377
          if (WITH1->btype == 'D')
3378
            {
3379
              if (atom[WITH1->a1 - 1].stereo_care
3380
                  && atom[WITH1->a2 - 1].stereo_care)
3381
                {               /* this is the MDL-conformant encoding, */
3382
                  WITH1->stereo = bstereo_xyz;  /* for an alternative see below */
3383
                  ez_flag = true;       /* v0.3f */
3384
                }
3385
              else
3386
                {               /* this extended feature is encoded by a leading zero */
3387
                  strsub (tmpstr, rline, 10, 3);
3388
                  /* new in v0.3d: read bond stereo specification; */
3389
                  code = (sscanf (tmpstr, "%d", &bs) == 0);
3390
                  WITH1->mdl_stereo = bs;       /* v0.3n */
3391
                  if (code != 0 || bs <= 0 || bs > 2)
3392
                    WITH1->stereo = bstereo_any;
3393
                  else
3394
                    WITH1->stereo = bstereo_xyz;
3395
                  if (tmpstr[1] == '0')
3396
                    WITH1->stereo = bstereo_xyz;
3397
                }
3398
            }
3399
          /*if stereo <> bstereo_any then ez_search := true; */
3400
          if (WITH1->stereo != bstereo_any)     /* changed in v0.3f */
3401
            ez_flag = true;
3402
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '1')
3403
            WITH1->stereo = bstereo_up;
3404
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '6')
3405
            WITH1->stereo = bstereo_down;
3406
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '4')
3407
            WITH1->stereo = bstereo_either;     /* 0.3x */
3408
          if (WITH1->btype == 'D' && strlen (rline) > 11 && rline[11] == '3')
3409
            WITH1->stereo = bstereo_double_either;      /* 0.3x */
3410
          strsub (tmpstr, rline, 10, 3);
3411
          /* new in v0.3n: save original bond stereo specification; */
6787 kbelabas 3412
          (void)sscanf (tmpstr, "%d", &bs);
6785 bpr 3413
          /* v0.3n */
3414
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3415
          WITH1->mdl_stereo = bs;       /* v0.3n */
3416
          if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
3417
            n_heavybonds++;
3418
        }
3419
    }                           /* if (n_bonds > 0)... */
3420
  while (ri < molbufindex && sepcount < 1)
3421
    {
3422
      ri++;
3423
      strcpy (rline, molbuf[ri - 1]);
3424
      if (strpos2 (rline, "M  CHG", 1) > 0)
3425
        {                       /* new in v0.3j */
3426
          if (clearcharges)
3427
            {                   /* "M  CHG" supersedes all "old-style" charge values */
3428
 
3429
              for (i = 0; i < n_atoms; i++)
3430
                atom[i].formal_charge = 0;
3431
            }
3432
          read_charges (rline);
3433
          clearcharges = false;
3434
          /* subsequent "M  CHG" lines must not clear previous values */
3435
        }
3436
 
3437
      if (strpos2 (rline, "M  ISO", 1) > 0)
3438
        read_isotopes (rline);  /* 0.3x */
3439
 
3440
      if (strpos2 (rline, "M  RAD", 1) > 0)
3441
        read_radicals (rline);  /* 0.3x */
3442
 
3443
      if (strpos2 (rline, "$$$$", 1) > 0)
3444
        {
3445
          sepcount++;
3446
          if (molbufindex > ri + 2)     /* we assume this is an SDF file */
3447
            mol_in_queue = true;
3448
        }
3449
    }
3450
  memset (ring, 0, sizeof (ringlist));
3451
  for (n = 0; n < max_rings; n++)
3452
    {                           /* new in v0.3 */
3453
      ringprop[n].size = 0;
3454
      ringprop[n].arom = false;
3455
      ringprop[n].envelope = false;
3456
    }
3457
  li = ri + 1;
3458
}
3459
 
3460
 
3461
 
3462
static void
3463
write_MDLmolfile ()
3464
{
3465
  int i;
3466
  char tmpstr[256];
3467
  char wline[256];
3468
  int a_chg;
3469
  int a_iso;
3470
  int a_rad;
3471
  char tmflabel[256];           /* v0.3m */
3472
  char STR1[256];
3473
  /*char STR7[256];*/
3474
  int FORLIM;
3475
 
3476
  sprintf (tmflabel, "%d", (int) tweaklevel);   /* v0.3m */
3477
  while (strlen (tmflabel) < 2) /* v0.3m */
3478
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
3479
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
3480
  if (strlen (molname) > 80)
3481
    sprintf (molname, "%.80s", strcpy (STR1, molname));
3482
  puts (molname);
3483
  printf ("  CheckMol                        %s", tmflabel);    /* v0.3m */
3484
  if (ringsearch_mode == rs_sar)        /* v0.3m */
3485
    printf (":r0");
3486
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
3487
    printf (":r1");
3488
  if (opt_metalrings)
3489
    printf (":m1");
3490
  else
3491
    printf (":m0");
3492
  /* v0.3m */
3493
  printf ("\n%s\n", molcomment);
3494
  *wline = '\0';
3495
  *tmpstr = '\0';
3496
  sprintf (tmpstr, "%d", n_atoms);
3497
  lblank (3L, tmpstr);
3498
  strcat (wline, tmpstr);
3499
  *tmpstr = '\0';               /* first 3 digits: number of atoms */
3500
  sprintf (tmpstr, "%d", n_bonds);
3501
  lblank (3L, tmpstr);
3502
  strcat (wline, tmpstr);
3503
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
3504
  strcpy (tmpstr, "  0");
3505
  strcat (wline, tmpstr);
3506
  *tmpstr = '\0';               /* next 3 digits: number of atom lists (not used by us) */
3507
/* p2c: checkmol.pas, line 2388:
3508
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3509
#ifdef REDUCED_SAR
3510
  sprintf (tmpstr, "%d", n_countablerings);
3511
  /* v0.3n; changed n_rings into n_countablerings */
3512
#else
3513
  sprintf (tmpstr, "%d", n_rings);
3514
#endif
3515
  lblank (3L, tmpstr);
3516
  strcat (wline, tmpstr);
3517
  *tmpstr = '\0';
3518
  /* officially "obsolete", we use it for the number of rings */
3519
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
3520
  if (chir_flag)
3521
    strcat (wline, "1");
3522
  else
3523
    strcat (wline, "0");
3524
  /* v0.3n */
3525
  strcat (wline, "               999 V2000");
3526
  /* v0.3n (adjust string length) */
3527
  puts (wline);
3528
  FORLIM = n_atoms;
3529
  for (i = 0; i < FORLIM; i++)
3530
    {
3531
      *wline = '\0';
3532
      sprintf (tmpstr, "%1.4f", atom[i].x);
3533
      lblank (10L, tmpstr);
3534
      strcat (wline, tmpstr);
3535
      sprintf (tmpstr, "%1.4f", atom[i].y);
3536
      lblank (10L, tmpstr);
3537
      strcat (wline, tmpstr);
3538
      sprintf (tmpstr, "%1.4f", atom[i].z);
3539
      lblank (10L, tmpstr);
3540
      strcat (wline, tmpstr);
3541
      strcpy (tmpstr, atom[i].element);
3542
      /* tmpstr := lowercase(tmpstr); REPLACE!!! */
3543
      //tmpstr[0] = toupper (tmpstr[0]);
3544
      all_lowercase (tmpstr);
3545
      tmpstr[0] = toupper (tmpstr[0]);
3546
      /*wline := wline + ' '+atom^[i].element+' '; */
3547
      sprintf (wline + strlen (wline), " %s ", tmpstr);
3548
      strcat (wline, " 0");     /* mass difference (isotopes) */
3549
      /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
3550
      if (atom[i].arom)
3551
        strcpy (tmpstr, " 00");
3552
      else
3553
        strcpy (tmpstr, "  0");
3554
      strcat (wline, tmpstr);
3555
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0");
3556
      puts (wline);
3557
    }
3558
  FORLIM = n_bonds;
3559
  for (i = 0; i < FORLIM; i++)
3560
    {
3561
      *wline = '\0';
3562
      sprintf (tmpstr, "%d", bond[i].a1);
3563
      lblank (3L, tmpstr);
3564
      strcat (wline, tmpstr);
3565
      sprintf (tmpstr, "%d", bond[i].a2);
3566
      lblank (3L, tmpstr);
3567
      strcat (wline, tmpstr);
3568
      if (bond[i].btype == 'S')
3569
        strcpy (tmpstr, "  1");
3570
      if (bond[i].btype == 'D')
3571
        strcpy (tmpstr, "  2");
3572
      if (bond[i].btype == 'T')
3573
        strcpy (tmpstr, "  3");
3574
      if (bond[i].btype == 'A')
3575
        strcpy (tmpstr, "  4");
3576
      if (bond[i].btype == 'l')
3577
        strcpy (tmpstr, "  5");
3578
      if (bond[i].btype == 's')
3579
        strcpy (tmpstr, "  6");
3580
      if (bond[i].btype == 'd')
3581
        strcpy (tmpstr, "  7");
3582
      if (bond[i].btype == 'a')
3583
        strcpy (tmpstr, "  8");
3584
      /* now encode our own aromaticity information */
3585
      if (bond[i].arom)
3586
        tmpstr[1] = '0';
3587
      strcat (wline, tmpstr);   /* next, encode bond stereo property (v0.3f) */
3588
      /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
3589
      /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
3590
      /*    wline := wline + '  0'; */
3591
      /* restore original value from MDL molfile (v0.3n) */
3592
      /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
3593
      *tmpstr = '\0';
3594
      sprintf (tmpstr, "%i", bond[i].mdl_stereo);
3595
      strcat (wline, "  ");
3596
      strcat (wline, tmpstr);
3597
      *tmpstr = '\0';
3598
      /* now encode the ring_count of this bond (using a field which officially is "not used") */
3599
      /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
3600
      sprintf (tmpstr, "%i", bond[i].ring_count);
3601
      while (strlen (tmpstr) < 3)
3602
        sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
3603
      sprintf (wline + strlen (wline), "%s  0  0", tmpstr);
3604
      puts (wline);
3605
    }
3606
  FORLIM = n_atoms;
3607
  for (i = 1; i <= FORLIM; i++)
3608
    {
3609
      a_chg = atom[i - 1].formal_charge;
3610
      if (a_chg != 0)
3611
        {
3612
          strcpy (wline, "M  CHG  1 ");
3613
          sprintf (tmpstr, "%d", i);
3614
          lblank (3L, tmpstr);
3615
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3616
          sprintf (tmpstr, "%d", a_chg);
3617
          lblank (3L, tmpstr);
3618
          strcat (wline, tmpstr);
3619
          puts (wline);
3620
        }
3621
    }
3622
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
3623
    {
3624
      a_iso = atom[i - 1].nucleon_number;
3625
      if (a_iso != 0)
3626
        {
3627
          strcpy (wline, "M  ISO  1 ");
3628
          sprintf (tmpstr, "%d", i);
3629
          lblank (3L, tmpstr);
3630
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3631
          sprintf (tmpstr, "%d", a_iso);
3632
          lblank (3L, tmpstr);
3633
          strcat (wline, tmpstr);
3634
          puts (wline);
3635
        }
3636
    }
3637
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
3638
    {
3639
      a_rad = atom[i - 1].radical_type;
3640
      if (a_rad != 0)
3641
        {
3642
          strcpy (wline, "M  RAD  1 ");
3643
          sprintf (tmpstr, "%d", i);
3644
          lblank (3L, tmpstr);
3645
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3646
          sprintf (tmpstr, "%d", a_rad);
3647
          lblank (3L, tmpstr);
3648
          strcat (wline, tmpstr);
3649
          puts (wline);
3650
        }
3651
    }
3652
  printf ("M  END\n");
3653
}
3654
 
3655
 
3656
/*============= chemical processing functions && procedures ============ */
3657
 
3658
static boolean
3659
is_electroneg (a_el)
3660
     char *a_el;
3661
{
3662
  /* new in v0.3j */
3663
  boolean res = false;
3664
 
3665
  if (!strcmp (a_el, "N "))
3666
    res = true;
3667
  if (!strcmp (a_el, "P "))
3668
    res = true;
3669
  if (!strcmp (a_el, "O "))
3670
    res = true;
3671
  if (!strcmp (a_el, "S "))
3672
    res = true;
3673
  if (!strcmp (a_el, "SE"))
3674
    res = true;
3675
  if (!strcmp (a_el, "TE"))
3676
    res = true;
3677
  if (!strcmp (a_el, "F "))
3678
    res = true;
3679
  if (!strcmp (a_el, "CL"))
3680
    res = true;
3681
  if (!strcmp (a_el, "BR"))
3682
    res = true;
3683
  if (!strcmp (a_el, "I "))
3684
    res = true;
3685
  if (!strcmp (a_el, "AT"))
3686
    res = true;
3687
  return res;
3688
}
3689
 
3690
 
3691
static void
3692
count_neighbors ()
3693
{
3694
  /* counts heavy-atom neighbors and explicit hydrogens */
3695
  int i, FORLIM;
3696
 
3697
  if (n_atoms < 1 || n_bonds < 1)
3698
    return;
3699
  FORLIM = n_bonds;
3700
  for (i = 0; i < FORLIM; i++)
3701
    {
3702
      if (atom[bond[i].a1 - 1].heavy)
3703
        atom[bond[i].a2 - 1].neighbor_count++;
3704
      if (atom[bond[i].a2 - 1].heavy)
3705
        atom[bond[i].a1 - 1].neighbor_count++;
3706
      if (!strcmp (atom[bond[i].a1 - 1].element, "H "))
3707
        atom[bond[i].a2 - 1].Hexp++;
3708
      if (!strcmp (atom[bond[i].a2 - 1].element, "H "))
3709
        atom[bond[i].a1 - 1].Hexp++;
3710
      /* plausibility check (new in v02.i) */
3711
      if (atom[bond[i].a1 - 1].neighbor_count > max_neighbors ||
3712
          atom[bond[i].a2 - 1].neighbor_count > max_neighbors)
3713
        {
3714
          mol_OK = false;
3715
          /*writeln('invalid molecule!'); */
3716
        }
3717
    }
3718
}
3719
 
3720
 
3721
static void
3722
get_neighbors (Result, id)
3723
     int *Result;
3724
     int id;
3725
{
6786 kbelabas 3726
  int i;
6785 bpr 3727
  //neighbor_rec nb_tmp;
3728
  int nb_count = 0;
3729
  //int FORLIM = n_bonds;
3730
 
3731
  //memset (Result, 0, sizeof (neighbor_rec));
3732
 
6786 kbelabas 3733
  for (i = 0; i < n_bonds; i++)
6785 bpr 3734
    {
3735
      if (bond[i].a1 == id && atom[bond[i].a2 - 1].heavy
3736
          && nb_count < max_neighbors)
3737
        {
3738
          Result[nb_count++] = bond[i].a2;
3739
        }
3740
      if (bond[i].a2 == id && atom[bond[i].a1 - 1].heavy
3741
          && nb_count < max_neighbors)
3742
        {
3743
          Result[nb_count++] = bond[i].a1;
3744
        }
3745
    }
3746
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3747
}
3748
 
3749
 
3750
static void
3751
get_ndl_neighbors (int *Result, int id)
3752
{
3753
  int i;
3754
  //neighbor_rec nb_tmp;
3755
  int nb_count = 0;
3756
  /* v0.3i: use max_neighbors instead of a fixed value of 8 */
3757
  //int FORLIM = ndl_n_bonds;
3758
 
3759
  //memset (nb_tmp, 0, sizeof (neighbor_rec));
3760
 
3761
  for (i = 0; i < ndl_n_bonds; i++)
3762
    {
3763
      if (ndl_bond[i].a1 == id && nb_count < max_neighbors &&
3764
          ndl_atom[ndl_bond[i].a2 - 1].heavy)
3765
        {
3766
          nb_count++;
3767
          Result[nb_count - 1] = ndl_bond[i].a2;
3768
        }
3769
      if (ndl_bond[i].a2 == id && nb_count < max_neighbors &&
3770
          ndl_atom[ndl_bond[i].a1 - 1].heavy)
3771
        {
3772
          nb_count++;
3773
          Result[nb_count - 1] = ndl_bond[i].a1;
3774
        }
3775
    }
3776
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3777
}
3778
 
3779
 
3780
static int *
3781
get_nextneighbors (int *Result, int id, int prev_id)
3782
{
3783
  int i;
3784
  neighbor_rec nb_tmp;
3785
  int nb_count = 0;
3786
  int FORLIM;
3787
 
3788
  /* gets all neighbors except prev_id (usually the atom where we came from */
3789
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3790
  FORLIM = n_bonds;
3791
  for (i = 0; i < FORLIM; i++)
3792
    {
3793
      if (bond[i].a1 == id && bond[i].a2 != prev_id &&
3794
          nb_count < max_neighbors && atom[bond[i].a2 - 1].heavy)
3795
        {
3796
          nb_count++;
3797
          nb_tmp[nb_count - 1] = bond[i].a2;
3798
        }
3799
      if (bond[i].a2 == id && bond[i].a1 != prev_id &&
3800
          nb_count < max_neighbors && atom[bond[i].a1 - 1].heavy)
3801
        {
3802
          nb_count++;
3803
          nb_tmp[nb_count - 1] = bond[i].a1;
3804
        }
3805
    }
3806
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3807
}
3808
 
3809
 
3810
static int *
3811
get_ndl_nextneighbors (int *Result, int id, int prev_id)
3812
{
3813
  int i;
3814
  neighbor_rec nb_tmp;
3815
  int nb_count = 0;
3816
  int FORLIM;
3817
 
3818
  /* gets all neighbors except prev_id (usually the atom where we came from */
3819
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3820
  FORLIM = ndl_n_bonds;
3821
  for (i = 0; i < FORLIM; i++)
3822
    {
3823
      if (ndl_bond[i].a1 == id && ndl_bond[i].a2 != prev_id &&
3824
          nb_count < max_neighbors && ndl_atom[ndl_bond[i].a2 - 1].heavy)
3825
        {
3826
          nb_count++;
3827
          nb_tmp[nb_count - 1] = ndl_bond[i].a2;
3828
        }
3829
      if (ndl_bond[i].a2 == id && ndl_bond[i].a1 != prev_id &&
3830
          nb_count < max_neighbors && ndl_atom[ndl_bond[i].a1 - 1].heavy)
3831
        {
3832
          nb_count++;
3833
          nb_tmp[nb_count - 1] = ndl_bond[i].a1;
3834
        }
3835
    }
3836
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3837
}
3838
 
3839
#if 0
3840
static int path_pos (id, a_path) int id;
3841
     int *a_path;
3842
     {
3843
     /* new version in v0.3l */
3844
     int i;
3845
     int pp = 0;
3846
 
3847
     for (i = 1; i <= max_ringsize; i++)
3848
     {
3849
     if (a_path[i - 1] == id)
3850
     {
3851
     pp = i;
3852
     /* p2c: checkmol.pas, line 2620:
3853
     * Warning: Expected a '(', found a semicolon [227]  */
3854
     /* p2c: checkmol.pas, line 2620:
3855
     * Warning: Expected an expression, found a semicolon [227] */
3856
     fflush (0);
3857
     P_ioresult = 0;
3858
     }
3859
     }
3860
     return pp;
3861
     }
3862
#endif
3863
 
3864
static int
3865
matchpath_pos (int id, int *a_path)
3866
{
3867
  int i;
3868
  int pp = 0;
3869
 
3870
  for (i = max_matchpath_length; i >= 1; i--)
3871
    {
3872
      if (a_path[i - 1] == id)
3873
        pp = i;
3874
    }
3875
  return pp;
3876
}
3877
 
3878
 
3879
static int
3880
matchpath_length (int *a_path)
3881
{
3882
  if (a_path[max_matchpath_length - 1] != 0)
3883
    return max_matchpath_length;
3884
  else
3885
    return (matchpath_pos (0L, a_path) - 1);
3886
}
3887
 
3888
static int
3889
get_ndl_bond (int ba1, int ba2)
3890
{
3891
  int i;
3892
  int b_id = 0;
3893
  int FORLIM;
3894
 
3895
  if (ndl_n_bonds <= 0)
3896
    return b_id;
3897
  FORLIM = ndl_n_bonds;
3898
  for (i = 1; i <= FORLIM; i++)
3899
    {
3900
      if ((ndl_bond[i - 1].a1 == ba1 && ndl_bond[i - 1].a2 == ba2) ||
3901
          (ndl_bond[i - 1].a1 == ba2 && ndl_bond[i - 1].a2 == ba1))
3902
        b_id = i;
3903
    }
3904
  return b_id;
3905
}
3906
 
3907
static int
3908
ringcompare (int *rp1, int *rp2)
3909
{
3910
  int i, j;
3911
  int rc = 0;
3912
  int rs1, rs2;
3913
  int n_common = 0;
3914
  int max_cra;
3915
 
3916
  rs1 = path_length (rp1);
3917
  rs2 = path_length (rp2);
3918
  if (rs1 < rs2)
3919
    max_cra = rs1;
3920
  else
3921
    max_cra = rs2;
3922
  for (i = 0; i < rs1; i++)
3923
    {
3924
      for (j = 0; j < rs2; j++)
3925
        {
3926
          if (rp1[i] == rp2[j])
3927
            n_common++;
3928
        }
3929
    }
3930
  if (rs1 == rs2 && n_common == max_cra)
3931
    {
3932
      rc = 0;
3933
      return rc;
3934
    }
3935
  if (n_common == 0)
3936
    rc += 8;
3937
  if (n_common < max_cra)
3938
    {
3939
      rc += 4;
3940
      return rc;
3941
    }
3942
  if (rs1 < rs2)
3943
    rc++;
3944
  else
3945
    rc += 2;
3946
  return rc;
3947
}
3948
 
3949
 
3950
static boolean
3951
rc_identical (int rc_int)
3952
{
3953
  if (rc_int == 0)
3954
    return true;
3955
  else
3956
    return false;
3957
}
3958
 
3959
 
3960
static boolean
3961
rc_1in2 (int rc_int)
3962
{
3963
  if (rc_int & 1)
3964
    return true;
3965
  else
3966
    return false;
3967
}
3968
 
3969
 
3970
static boolean
3971
rc_2in1 (int rc_int)
3972
{
3973
  rc_int /= 2;
3974
  if (rc_int & 1)
3975
    return true;
3976
  else
3977
    return false;
3978
}
3979
 
3980
 
3981
#if 0
3982
static boolean
3983
rc_different (int rc_int)
3984
{
3985
  rc_int /= 4;
3986
  if (rc_int & 1)
3987
    return true;
3988
  else
3989
    return false;
3990
}
3991
#endif
3992
#if 0
3993
static boolean
3994
rc_independent (int rc_int)
3995
{
3996
  rc_int /= 8;
3997
  if (rc_int & 1)
3998
    return true;
3999
  else
4000
    return false;
4001
}
4002
#endif
4003
 
4004
static boolean
4005
is_newring (int *n_path)
4006
{
4007
  int i, j;
4008
  boolean nr = true;
4009
  boolean same_ring;
4010
  ringpath_type tmp_path;
4011
  int rc_result;
4012
  boolean found_ring;
4013
  int pl;                       /* new in v0.3 */
4014
  int FORLIM;
4015
 
4016
  pl = path_length (n_path);    /* new in v0.3 */
4017
  if (n_rings <= 0)
4018
    return true;
4019
  switch (ringsearch_mode)
4020
    {
4021
 
4022
    case rs_sar:
4023
      found_ring = false;
4024
      i = 0;
4025
      while (i < n_rings && !found_ring)
4026
        {
4027
          i++;
4028
          if (pl != ringprop[i - 1].size)       /* compare only rings of same size */
4029
            continue;
4030
          same_ring = true;
4031
          for (j = 0; j < max_ringsize; j++)
4032
            {
4033
              if (ring[i - 1][j] != n_path[j])
4034
                same_ring = false;
4035
            }
4036
          if (same_ring)
4037
            {
4038
              nr = false;
4039
              found_ring = true;
4040
            }
4041
        }
4042
      break;
4043
 
4044
    case rs_ssr:
4045
      FORLIM = n_rings;
4046
      for (i = 0; i < FORLIM; i++)
4047
        {
4048
          for (j = 0; j < max_ringsize; j++)
4049
            tmp_path[j] = ring[i][j];
4050
          rc_result = ringcompare (n_path, tmp_path);
4051
          if (rc_identical (rc_result))
4052
            nr = false;
4053
          if (rc_1in2 (rc_result))
4054
            {
4055
              /* exchange existing ring by smaller one */
4056
              for (j = 0; j < max_ringsize; j++)
4057
                ring[i][j] = n_path[j];
4058
              /* update ring property record (new in v0.3) */
4059
              ringprop[i].size = pl;
4060
              nr = false;
4061
/* p2c: checkmol.pas, line 2841:
4062
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4063
              /*$IFDEF debug */
4064
              /* debugoutput('replacing ring '+inttostr(i)+' by smaller one (ringsize: '+inttostr(path_length(n_path))+')'); */
4065
              /*$ENDIF */
4066
            }
4067
          if (rc_2in1 (rc_result))
4068
            {
4069
              /* new ring contains existing one, but is larger ==> discard */
4070
              nr = false;
4071
            }
4072
        }
4073
      break;
4074
    }
4075
  return nr;
4076
}
4077
 
4078
 
4079
static void
4080
add_ring (int *n_path)
4081
{
4082
  /* new in v0.3: store rings in an ordered way (with ascending ring size) */
4083
  int i;
4084
  int j = 0;
4085
  int k, s, pl;
4086
/* p2c: checkmol.pas, line 2862:
4087
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4088
  /*$IFDEF debug */
4089
  /*char dstr[256];*/
4090
  int FORLIM;
4091
 
4092
  /*$ENDIF */
4093
  pl = path_length (n_path);
4094
 
4095
  if (pl < 1)
4096
    return;
4097
 
4098
  if (n_rings >= max_rings)
4099
    {
4100
 
4101
/* p2c: checkmol.pas, line 2906:
4102
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4103
      /*$IFDEF debug
4104
         debugoutput ("max_rings exceeded!");
4105
         $ENDIF */
4106
      return;
4107
    }
4108
  n_rings++;
4109
 
4110
/* p2c: checkmol.pas, line 2871:
4111
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4112
  /*$IFDEF debug */
4113
  /* dstr := '';
4114
     for j := 1 to pl do dstr := dstr + inttostr((n_path[j])) + ' ';
4115
     debugoutput('adding ring '+inttostr(n_rings)+':  '+dstr); */
4116
  /*$ENDIF */
4117
  if (n_rings > 1)
4118
    {
4119
      FORLIM = n_rings;
4120
      for (i = 1; i < FORLIM; i++)
4121
        {
4122
          s = ringprop[i - 1].size;
4123
          if (pl >= s)
4124
            j = i;
4125
        }
4126
    }
4127
  j++;                          /* the next position is ours */
4128
  if (j < n_rings)
4129
    {                           /* push up the remaining rings by one position */
4130
      for (k = n_rings; k > j; k--)
4131
        {
4132
          ringprop[k - 1].size = ringprop[k - 2].size;
4133
          /*ringprop^[k].arom := ringprop^[(k-1)].arom; */
4134
          for (i = 0; i < max_ringsize; i++)
4135
            ring[k - 1][i] = ring[k - 2][i];
4136
        }
4137
    }
4138
  ringprop[j - 1].size = pl;
4139
  for (i = 0; i < max_ringsize; i++)
4140
    {
4141
      ring[j - 1][i] = n_path[i];
4142
      /*inc(atom^[(n_path[i])].ring_count); */
4143
    }
4144
}
4145
 
4146
 
4147
#if 0
4148
 static boolean is_ringpath (s_path) int *s_path;
4149
     {
4150
     boolean Result;
4151
     int i, j;
4152
     neighbor_rec nb;
4153
     boolean rp = false;
4154
     boolean new_atom;
4155
     int a_last, pl;
4156
     ringpath_type l_path;
4157
     int FORLIM;
4158
 
4159
     /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4160
     memset (nb, 0, sizeof (neighbor_rec));
4161
     memset (l_path, 0, sizeof (ringpath_type));
4162
     pl = path_length (s_path);
4163
     if (pl < 1)
4164
     {
4165
     /* p2c: checkmol.pas, line 2928:
4166
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4167
     /*$IFDEF debug
4168
     debugoutput ("Oops! Got zero-length s_path!");
4169
     $ENDIF */
4170
     return Result;
4171
     }
4172
     for (i = 0; i < pl; i++)
4173
     l_path[i] = s_path[i];
4174
     /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
4175
     if (opt_metalrings == false)
4176
     {
4177
     if (atom[l_path[pl - 1] - 1].metal)
4178
     {
4179
     /* p2c: checkmol.pas, line 2942:
4180
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4181
     /*$IFDEF debug
4182
     debugoutput ("skipping metal in ring search");
4183
     $ENDIF */
4184
     return false;
4185
     }
4186
     }
4187
     /* check if ring is already closed */
4188
     if (pl > 2 && l_path[pl - 1] == l_path[0])
4189
     {
4190
     l_path[pl - 1] = 0;        /* remove last entry (redundant!) */
4191
     order_ringpath (l_path);
4192
     if (is_newring (l_path))
4193
     {
4194
     if (n_rings >= max_rings)
4195
     {
4196
     /* p2c: checkmol.pas, line 2958:
4197
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4198
     /*$IFDEF debug
4199
     debugoutput ("maximum number of rings exceeded!");
4200
     $ENDIF */
4201
     return false;
4202
     }
4203
     add_ring (l_path);
4204
     }
4205
     /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4206
     return true;
4207
     }
4208
     /* any other case: ring is not (yet) closed */
4209
     a_last = l_path[pl - 1];
4210
     get_neighbors (nb, a_last);
4211
     if (atom[a_last - 1].neighbor_count <= 1)
4212
     return false;
4213
     if (n_rings >= max_rings)
4214
     /* added in v0.2: check if max_rings is reached **/
4215
     {                          /* if ring is not closed, continue searching */
4216
     return false;
4217
     }
4218
     FORLIM = atom[a_last - 1].neighbor_count;
4219
     for (i = 0; i < FORLIM; i++)
4220
     {
4221
     new_atom = true;
4222
     for (j = 1; j < pl; j++)
4223
     {
4224
     if (nb[i] == l_path[j])
4225
     {                    /* v0.3k */
4226
     new_atom = false;
4227
     /* p2c: checkmol.pas, line 2982:
4228
     * Warning: Expected a '(', found a semicolon [227] */
4229
     /* p2c: checkmol.pas, line 2982:
4230
     * Warning: Expected an expression, found a semicolon [227] */
4231
     fflush (0);
4232
     P_ioresult = 0;      /* v0.3k */
4233
     }
4234
     }
4235
     /* added in v0.1a: check if max_rings not yet reached */
4236
     /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
4237
     if (new_atom && pl < max_vringsize && n_rings < max_rings)
4238
     {
4239
     l_path[pl] = nb[i];
4240
     if (pl < max_ringsize - 1)   /* just to be sure */
4241
     l_path[pl + 1] = 0;
4242
     if (is_ringpath (l_path))
4243
     rp = true;
4244
     }
4245
     }
4246
     return rp;
4247
     }
4248
#endif
4249
 
4250
static boolean
4251
is_ringpath (int *s_path)
4252
{
4253
  int i, j;
4254
  neighbor_rec nb;
4255
  boolean rp = false;
4256
  boolean new_atom;
4257
  int a_last, pl;
4258
  ringpath_type l_path;
4259
  int FORLIM, pl_prev, pl_next, max_ringsize_dec;
4260
 
4261
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4262
  memset ((void *) nb, 0, sizeof (neighbor_rec));
4263
  memset ((void *) l_path, 0, sizeof (ringpath_type));
4264
  pl = path_length (s_path);
4265
  if (pl < 1)
4266
    {
4267
/* p2c: checkmol.pas, line 2524:
4268
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4269
 
4270
      return false;
4271
    }
4272
 
4273
  pl_prev = pl - 1;
4274
  //memcpy (l_path, s_path, sizeof (ringpath_type));
4275
  memcpy (l_path, s_path, pl * sizeof (int));
4276
 
4277
  /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
4278
  if (opt_metalrings == false)
4279
    {
4280
      if (atom[l_path[pl_prev] - 1].metal)
4281
        {
4282
/* p2c: checkmol.pas, line 2538:
4283
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4284
          return false;
4285
        }
4286
    }
4287
  /* check if ring is already closed */
4288
  if (pl > 2 && l_path[pl_prev] == l_path[0])
4289
    {
4290
      l_path[pl_prev] = 0;      /* remove last entry (redundant!) */
4291
      order_ringpath (l_path);
4292
      if (is_newring (l_path))
4293
        {
4294
          if (n_rings >= max_rings)
4295
            {
4296
/* p2c: checkmol.pas, line 2554:
4297
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4298
 
4299
              return false;
4300
            }
4301
          add_ring (l_path);
4302
        }
4303
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4304
      return true;
4305
    }
4306
  /* any other case: ring is not (yet) closed */
4307
  a_last = l_path[pl_prev];
4308
  get_neighbors (nb, a_last);
4309
  if (atom[a_last - 1].neighbor_count <= 1)
4310
    return false;
4311
  if (n_rings >= max_rings)
4312
    /* added in v0.2: check if max_rings is reached */
4313
    {                           /* if ring is not closed, continue searching */
4314
      return false;
4315
    }
4316
  FORLIM = atom[a_last - 1].neighbor_count;
4317
  pl_next = pl + 1;
4318
  max_ringsize_dec = max_ringsize - 1;
4319
  for (i = 0; i < FORLIM; i++)
4320
    {
4321
      new_atom = true;
4322
      for (j = 1; j < pl; j++)
4323
        {
4324
          if (nb[i] == l_path[j])
4325
            {
4326
              new_atom = false;
4327
              break;
4328
            }
4329
        }
4330
      /* added in v0.1a: check if max_rings not yet reached */
4331
      /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
4332
      if (new_atom && pl < max_vringsize && n_rings < max_rings)
4333
        {
4334
          l_path[pl] = nb[i];
4335
          if (pl < max_ringsize_dec)    /* just to be sure */
4336
            l_path[pl_next] = 0;
4337
 
4338
          if (max_ringpath_recursion_depth != 0
4339
              && ++recursion_depth > max_ringpath_recursion_depth)
4340
            {
4341
#ifndef MAKE_SHARED_LIBRARY
4342
              if (opt_verbose)
4343
#endif
4344
                printf
4345
                  ("Warning: max. number of ringpath recursions (%i) reached\n",
4346
                   max_ringpath_recursion_depth);
4347
              n_rings = max_rings;
4348
              return false;
4349
            }
4350
 
4351
          /*printf("%i\n",recursion_depth);
4352
          fflush(stdout);*/
4353
 
4354
          if (is_ringpath (l_path))
4355
            rp = true;
4356
          /*return true;*/
4357
        }
4358
    }
4359
  return rp;
4360
}
4361
 
4362
static boolean
4363
is_ringbond (int b_id)
4364
{
4365
  int i, ra1, ra2;
4366
  neighbor_rec nb;
4367
  ringpath_type search_path;
4368
  boolean rb = false;
4369
  int FORLIM;
4370
 
4371
  recursion_depth = 0;
4372
 
4373
  ra1 = bond[b_id - 1].a1;
4374
  ra2 = bond[b_id - 1].a2;
4375
  memset (nb, 0, sizeof (neighbor_rec));
4376
  memset (search_path, 0, sizeof (ringpath_type));
4377
  get_neighbors (nb, ra2);
4378
  if (atom[ra2 - 1].neighbor_count <= 1 || atom[ra1 - 1].neighbor_count <= 1)
4379
    return false;
4380
  search_path[0] = ra1;
4381
  search_path[1] = ra2;
4382
  FORLIM = atom[ra2 - 1].neighbor_count;
4383
  for (i = 0; i < FORLIM; i++)
4384
    {
4385
      if (nb[i] != ra1 && atom[nb[i] - 1].heavy)
4386
        {
4387
          search_path[2] = nb[i];
4388
          if (is_ringpath (search_path))
4389
            rb = true;
4390
          //return true;
4391
        }
4392
    }
4393
  return rb;
4394
}
4395
 
4396
 
4397
static void
4398
chk_ringbonds ()
4399
{
4400
  int i, a1rc, a2rc;
4401
 
4402
  if (n_bonds < 1)
4403
    return;
4404
 
4405
  for (i = 0; i < n_bonds; i++)
4406
    {
4407
      a1rc = atom[bond[i].a1 - 1].ring_count;
4408
      a2rc = atom[bond[i].a2 - 1].ring_count;
4409
      if (n_rings == 0 || (a1rc < n_rings && a2rc < n_rings))
4410
        {
4411
          is_ringbond (i + 1);
4412
          /*inc(bond^[i].ring_count); */
4413
        }
4414
    }
4415
}
4416
 
4417
 
4418
/* v0.3d: moved procedure update_ringcount a bit down */
4419
 
4420
 
4421
static int
4422
raw_hetbond_count (int a)
4423
{
4424
  /* new in v0.2j, ignores bond order */
4425
  int i;
4426
  neighbor_rec nb;
4427
  str2 nb_el;
4428
  int hbc = 0;
4429
  int FORLIM;
4430
 
4431
  if (a <= 0 || a > n_atoms)
4432
    return hbc;
4433
  memset (nb, 0, sizeof (neighbor_rec));
4434
  get_neighbors (nb, a);
4435
  if (atom[a - 1].neighbor_count <= 0)
4436
    return hbc;
4437
  FORLIM = atom[a - 1].neighbor_count;
4438
  for (i = 0; i < FORLIM; i++)
4439
    {
4440
      strcpy (nb_el, atom[nb[i] - 1].element);
4441
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /* &&  strcmp (nb_el, "D ") */
4442
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4443
        /* added 'D ' in v0.3n */
4444
        hbc++;
4445
    }
4446
  return hbc;
4447
}
4448
 
4449
 
4450
static int
4451
hetbond_count (int a)
4452
{
4453
  int i;
4454
  neighbor_rec nb;
4455
  str2 nb_el;
4456
  float hbc = 0.0;
4457
  int FORLIM;
4458
 
4459
  if (a <= 0 || a > n_atoms)
4460
    return ((int) floor (hbc + 0.5));
4461
  memset (nb, 0, sizeof (neighbor_rec));
4462
  get_neighbors (nb, a);
4463
  if (atom[a - 1].neighbor_count <= 0)
4464
    return ((int) floor (hbc + 0.5));
4465
  FORLIM = atom[a - 1].neighbor_count;
4466
  for (i = 0; i < FORLIM; i++)
4467
    {
4468
      strcpy (nb_el, atom[nb[i] - 1].element);
4469
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /*&& strcmp (nb_el, "D ") */
4470
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4471
        {                       /* added 'D ' in v0.3n */
4472
          if (bond[get_bond (a, nb[i]) - 1].btype == 'S')
4473
            hbc += 1.0;
4474
          if (bond[get_bond (a, nb[i]) - 1].btype == 'A')
4475
            hbc += 1.5;
4476
          if (bond[get_bond (a, nb[i]) - 1].btype == 'D')
4477
            hbc += 2.0;
4478
          if (bond[get_bond (a, nb[i]) - 1].btype == 'T')
4479
            hbc += 3.0;
4480
        }
4481
    }
4482
  return ((int) floor (hbc + 0.5));
4483
}
4484
 
4485
 
4486
static int
4487
hetatom_count (int a)
4488
{
4489
  int i;
4490
  neighbor_rec nb;
4491
  str2 nb_el;
4492
  int hac = 0;
4493
  int FORLIM;
4494
 
4495
  if (a <= 0 || a > n_atoms)
4496
    return hac;
4497
  memset (nb, 0, sizeof (neighbor_rec));
4498
  get_neighbors (nb, a);
4499
  if (atom[a - 1].neighbor_count <= 0)
4500
    return hac;
4501
  FORLIM = atom[a - 1].neighbor_count;
4502
  for (i = 0; i < FORLIM; i++)
4503
    {
4504
      strcpy (nb_el, atom[nb[i] - 1].element);
4505
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4506
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4507
          && strcmp (nb_el, "DU"))
4508
        /* added 'D ' in v0.3n */
4509
        hac++;
4510
    }
4511
  return hac;
4512
}
4513
 
4514
#if 0
4515
static int
4516
ndl_hetbond_count (int a)
4517
{
4518
  int i;
4519
  neighbor_rec nb;
4520
  str2 nb_el;
4521
  float hbc = 0.0;
4522
  int FORLIM;
4523
 
4524
  if (a <= 0 || a > n_atoms)
4525
    return ((int) floor (hbc + 0.5));
4526
  memset (nb, 0, sizeof (neighbor_rec));
4527
  get_ndl_neighbors (nb, a);
4528
  if (ndl_atom[a - 1].neighbor_count <= 0)
4529
    return ((int) floor (hbc + 0.5));
4530
  FORLIM = ndl_atom[a - 1].neighbor_count;
4531
  for (i = 0; i < FORLIM; i++)
4532
    {
4533
      strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4534
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4535
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4536
          && strcmp (nb_el, "DU"))
4537
        {                       /* added 'D ' in v0.3n */
4538
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'S')
4539
            hbc += 1.0;
4540
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'A')
4541
            hbc += 1.5;
4542
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'D')
4543
            hbc += 2.0;
4544
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'T')
4545
            hbc += 3.0;
4546
        }
4547
    }
4548
  return ((int) floor (hbc + 0.5));
4549
}
4550
#endif
4551
 
4552
static int
4553
ndl_hetatom_count (int a)
4554
{
4555
  int i;
4556
  neighbor_rec nb;
4557
  str2 nb_el;
4558
  int hac = 0;
4559
  int FORLIM;
4560
 
4561
  if (a <= 0 || a > ndl_n_atoms)
4562
    return hac;
4563
  memset (nb, 0, sizeof (neighbor_rec));
4564
  get_ndl_neighbors (nb, a);
4565
  if (ndl_atom[a - 1].neighbor_count <= 0)
4566
    return hac;
4567
  FORLIM = ndl_atom[a - 1].neighbor_count;
4568
  for (i = 0; i < FORLIM; i++)
4569
    {                           /* note: query atoms like 'A' should be present only in the needle */
4570
      strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4571
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /*&&  strcmp (nb_el, "D ") */
4572
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4573
        /* added 'D ' in v0.3n */
4574
        hac++;
4575
    }
4576
  return hac;
4577
}
4578
 
4579
 
4580
static boolean
4581
is_oxo_C (int id)
4582
{
4583
  int i;
4584
  boolean r = false;
4585
  neighbor_rec nb;
4586
  int FORLIM;
4587
 
4588
  memset (nb, 0, sizeof (neighbor_rec));
4589
  if (id < 1 || id > n_atoms)
6786 kbelabas 4590
    return false;
6785 bpr 4591
  get_neighbors (nb, id);
4592
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4593
    return false;
4594
  FORLIM = atom[id - 1].neighbor_count;
4595
  for (i = 0; i < FORLIM; i++)
4596
    {
4597
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4598
          !strcmp (atom[nb[i] - 1].element, "O "))
4599
        /* no N, amidines are different... */
4600
        r = true;
4601
      /* or
4602
         (atom^[(nb[i])].element = 'S ')  or
4603
         (atom^[(nb[i])].element = 'SE') */
4604
    }
4605
  return r;
4606
}
4607
 
4608
 
4609
static boolean
4610
is_thioxo_C (int id)
4611
{
4612
  int i;
4613
  boolean r = false;
4614
  neighbor_rec nb;
4615
  int FORLIM;
4616
 
4617
  memset (nb, 0, sizeof (neighbor_rec));
4618
  if (id < 1 || id > n_atoms)
6786 kbelabas 4619
    return false;
6785 bpr 4620
  get_neighbors (nb, id);
4621
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4622
    return false;
4623
  FORLIM = atom[id - 1].neighbor_count;
4624
  for (i = 0; i < FORLIM; i++)
4625
    {
4626
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4627
          (!strcmp (atom[nb[i] - 1].element, "S ") ||
4628
           !strcmp (atom[nb[i] - 1].element, "SE")))
4629
        /* no N, amidines are different... */
4630
        r = true;
4631
    }
4632
  return r;
4633
}
4634
 
4635
 
4636
static boolean
4637
is_imino_C (int id)
4638
{
4639
  int i;
4640
  boolean r = false;
4641
  neighbor_rec nb;
4642
  int FORLIM;
4643
 
4644
  memset (nb, 0, sizeof (neighbor_rec));
4645
  if (id < 1 || id > n_atoms)
6786 kbelabas 4646
    return false;
6785 bpr 4647
  get_neighbors (nb, id);
4648
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4649
    return false;
4650
  FORLIM = atom[id - 1].neighbor_count;
4651
  for (i = 0; i < FORLIM; i++)
4652
    {
4653
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4654
          !strcmp (atom[nb[i] - 1].element, "N "))
4655
        r = true;
4656
    }
4657
  return r;
4658
}
4659
 
4660
 
4661
static boolean
4662
is_true_imino_C (int id)
4663
{
4664
  int i;
4665
  boolean r = true;
4666
  neighbor_rec nb;
4667
  str2 nb_el;
4668
  int a_n = 0;
4669
  int b;                        /* v0.3j */
4670
  int FORLIM;
4671
 
4672
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4673
  memset (nb, 0, sizeof (neighbor_rec));
4674
  if (id < 1 || id > n_atoms)
6786 kbelabas 4675
    return false;
6785 bpr 4676
  get_neighbors (nb, id);
4677
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4678
    return false;
4679
  FORLIM = atom[id - 1].neighbor_count;
4680
  for (i = 0; i < FORLIM; i++)
4681
    {
4682
      b = get_bond (id, nb[i]); /* v0.3j */
4683
      if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4684
          !strcmp (atom[nb[i] - 1].element, "N "))
4685
        /* v0.3j */
4686
        a_n = nb[i];
4687
    }
4688
  if (a_n <= 0)
4689
    return false;
4690
  memset (nb, 0, sizeof (neighbor_rec));
4691
  get_neighbors (nb, a_n);
4692
  FORLIM = atom[a_n - 1].neighbor_count;
4693
  for (i = 0; i < FORLIM; i++)
4694
    {
4695
      strcpy (nb_el, atom[nb[i] - 1].element);
4696
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4697
          /*&&  strcmp (nb_el, "D ") */ )
4698
        /* v0.3n: D */
4699
        r = false;
4700
    }
4701
  return r;
4702
}
4703
 
4704
 
4705
static boolean
4706
is_true_exocyclic_imino_C (int id, int r_id)
4707
{
4708
  /* v0.3j */
4709
  int i, j;
4710
  boolean r = false;
4711
  neighbor_rec nb;
4712
  ringpath_type testring;
4713
  int ring_size, b, FORLIM;
4714
 
4715
  memset (nb, 0, sizeof (neighbor_rec));
4716
  if (id < 1 || id > n_atoms)
6789 bpr 4717
    return false;
6785 bpr 4718
  get_neighbors (nb, id);
4719
  memset (testring, 0, sizeof (ringpath_type));
4720
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4721
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4722
    testring[j] = ring[r_id - 1][j];
4723
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4724
    return false;
4725
  FORLIM = atom[id - 1].neighbor_count;
4726
  for (i = 0; i < FORLIM; i++)
4727
    {
4728
      b = get_bond (id, nb[i]);
4729
      if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4730
          !strcmp (atom[nb[i] - 1].element, "N "))
4731
        {
4732
          r = true;
4733
          for (j = 0; j < ring_size; j++)
4734
            {
4735
              if (nb[i] == ring[r_id - 1][j])
4736
                r = false;
4737
            }
4738
        }
4739
    }
4740
  return r;
4741
}
4742
 
4743
 
4744
static boolean
4745
is_exocyclic_imino_C (int id, int r_id)
4746
{
4747
  int i, j;
4748
  boolean r = false;
4749
  neighbor_rec nb;
4750
  ringpath_type testring;
4751
  int ring_size, FORLIM;
4752
 
4753
  memset (nb, 0, sizeof (neighbor_rec));
4754
  if (id < 1 || id > n_atoms)
6789 bpr 4755
    return false;
6785 bpr 4756
  get_neighbors (nb, id);
4757
  memset (testring, 0, sizeof (ringpath_type));
4758
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4759
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4760
    testring[j] = ring[r_id - 1][j];
4761
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4762
    return false;
4763
  FORLIM = atom[id - 1].neighbor_count;
4764
  for (i = 0; i < FORLIM; i++)
4765
    {
4766
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4767
          !strcmp (atom[nb[i] - 1].element, "N "))
4768
        {
4769
          r = true;
4770
          for (j = 0; j < ring_size; j++)
4771
            {
4772
              if (nb[i] == ring[r_id - 1][j])
4773
                r = false;
4774
            }
4775
        }
4776
    }
4777
  return r;
4778
}
4779
 
4780
 
4781
static int
4782
find_exocyclic_methylene_C (int id, int r_id)
4783
{
4784
  /* renamed and rewritten in v0.3j */
4785
  int i, j;
4786
  int r = 0;
4787
  neighbor_rec nb;
4788
  ringpath_type testring;
4789
  int ring_size, FORLIM;
4790
 
4791
  memset (nb, 0, sizeof (neighbor_rec));
4792
  if (id < 1 || id > n_atoms)
4793
    return 0;
4794
  get_neighbors (nb, id);
4795
  memset (testring, 0, sizeof (ringpath_type));
4796
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4797
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4798
    testring[j] = ring[r_id - 1][j];
4799
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4800
    return r;
4801
  FORLIM = atom[id - 1].neighbor_count;
4802
  for (i = 0; i < FORLIM; i++)
4803
    {
4804
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4805
          !strcmp (atom[nb[i] - 1].element, "C "))
4806
        {
4807
          r = nb[i];
4808
          for (j = 0; j < ring_size; j++)
4809
            {
4810
              if (nb[i] == ring[r_id - 1][j])
4811
                r = 0;
4812
            }
4813
        }
4814
    }
4815
  return r;
4816
}
4817
 
4818
 
4819
static boolean
4820
is_hydroxy (int a_view, int a_ref)
4821
{
4822
  boolean r = false;
4823
 
4824
  if (atom[a_view - 1].
4825
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4826
    {
4827
      if (!strcmp (atom[a_ref - 1].atype, "O3 ") &&
4828
          atom[a_ref - 1].neighbor_count == 1)
4829
        r = true;
4830
    }
4831
  return r;
4832
}
4833
 
4834
 
4835
static boolean
4836
is_sulfanyl (int a_view, int a_ref)
4837
{
4838
  boolean r = false;
4839
 
4840
  if (atom[a_view - 1].
4841
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4842
    {
4843
      if (!strcmp (atom[a_ref - 1].atype, "S3 ") &&
4844
          atom[a_ref - 1].neighbor_count == 1)
4845
        r = true;
4846
    }
4847
  return r;
4848
}
4849
 
4850
 
4851
static boolean
4852
is_amino (int a_view, int a_ref)
4853
{
4854
  boolean r = false;
4855
 
4856
  if (atom[a_view - 1].
4857
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4858
    {
4859
      if ((!strcmp (atom[a_ref - 1].atype, "N3 ") ||
4860
           !strcmp (atom[a_ref - 1].atype, "N3+")) &&
4861
          atom[a_ref - 1].neighbor_count == 1)
4862
        r = true;
4863
    }
4864
  return r;
4865
}
4866
 
4867
 
4868
static boolean
4869
is_alkyl (int a_view, int a_ref)
4870
{
4871
  int i;
4872
  boolean r = false;
4873
  neighbor_rec nb;
4874
  str2 nb_el;
4875
  int het_count = 0;
4876
  int FORLIM;
4877
 
4878
  memset (nb, 0, sizeof (neighbor_rec));
4879
  if (!
4880
      (atom[a_view - 1].
4881
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4882
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4883
      || atom[a_ref - 1].arom != false)
4884
    return false;
4885
  get_nextneighbors (nb, a_ref, a_view);
4886
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4887
  for (i = 0; i <= FORLIM; i++)
4888
    {
4889
      strcpy (nb_el, atom[nb[i] - 1].element);
4890
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4891
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4892
          && strcmp (nb_el, "LP"))
4893
        /* added 'D ' in v0.3n */
4894
        het_count++;
4895
    }
4896
  if (het_count <= 1)           /* we consider (e.g.) alkoxyalkyl groups as alkyl */
4897
    r = true;
4898
  return r;
4899
}
4900
 
4901
 
4902
static boolean
4903
is_true_alkyl (int a_view, int a_ref)
4904
{
4905
  int i;
4906
  boolean r = false;
4907
  neighbor_rec nb;
4908
  str2 nb_el;
4909
  int het_count = 0;
4910
  int FORLIM;
4911
 
4912
  memset (nb, 0, sizeof (neighbor_rec));
4913
  if (!
4914
      (atom[a_view - 1].
4915
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4916
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4917
      || atom[a_ref - 1].arom != false)
4918
    return false;
4919
  get_nextneighbors (nb, a_ref, a_view);
4920
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4921
  for (i = 0; i <= FORLIM; i++)
4922
    {
4923
      strcpy (nb_el, atom[nb[i] - 1].element);
4924
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4925
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
4926
        /* added 'D ' in v0.3n */
4927
        het_count++;
4928
    }
4929
  if (het_count == 0)           /* */
4930
    r = true;
4931
  return r;
4932
}
4933
 
4934
 
4935
static boolean
4936
is_alkenyl (int a_view, int a_ref)
4937
{
4938
  /* new in v0.3j */
4939
  int i;
4940
  boolean r = false;
4941
  neighbor_rec nb;
4942
  str2 nb_el;
4943
  str3 nb_at;
4944
  int c2_count = 0, het_count = 0;
4945
  int FORLIM;
4946
 
4947
  memset (nb, 0, sizeof (neighbor_rec));
4948
  if (!
4949
      (atom[a_view - 1].
4950
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4951
      || strcmp (atom[a_ref - 1].atype, "C2 ")
4952
      || atom[a_ref - 1].arom != false)
4953
    {
4954
      return false;
4955
    }                           /* v0.3k: changed c2_count = 1 into c2_count >= 1 */
4956
  get_nextneighbors (nb, a_ref, a_view);
4957
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4958
  for (i = 0; i <= FORLIM; i++)
4959
    {
4960
      strcpy (nb_el, atom[nb[i] - 1].element);
4961
      strcpy (nb_at, atom[nb[i] - 1].atype);
4962
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4963
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4964
          && strcmp (nb_el, "LP"))
4965
        /* added 'D ' in v0.3n */
4966
        het_count++;
4967
      if (!strcmp (nb_at, "C2 "))
4968
        c2_count++;
4969
    }
4970
  if (c2_count >= 1 && het_count <= 1)
4971
    /* we consider (e.g.) alkoxyalkenyl groups as alkenyl */
4972
    r = true;
4973
  return r;
4974
}
4975
 
4976
 
4977
static boolean
4978
is_alkynyl (int a_view, int a_ref)
4979
{
4980
  /* new in v0.3j */
4981
  int i;
4982
  boolean r = false;
4983
  neighbor_rec nb;
4984
  str3 nb_at;
4985
  int c1_count = 0;
4986
  int FORLIM;
4987
 
4988
  memset (nb, 0, sizeof (neighbor_rec));
4989
  if (!
4990
      (atom[a_view - 1].
4991
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4992
      || strcmp (atom[a_ref - 1].atype, "C1 ")
4993
      || atom[a_ref - 1].arom != false)
4994
    return false;
4995
  get_nextneighbors (nb, a_ref, a_view);
4996
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4997
  for (i = 0; i <= FORLIM; i++)
4998
    {
4999
      strcpy (nb_at, atom[nb[i] - 1].atype);
5000
      if (!strcmp (nb_at, "C1 "))
5001
        c1_count++;
5002
    }
5003
  if (c1_count == 1)
5004
    r = true;
5005
  return r;
5006
}
5007
 
5008
 
5009
static boolean
5010
is_aryl (int a_view, int a_ref)
5011
{
5012
  boolean r = false;
5013
 
5014
  if ((atom[a_view - 1].
5015
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
5016
      && !strcmp (atom[a_ref - 1].element, "C ")
5017
      && atom[a_ref - 1].arom == true)
5018
    r = true;
5019
  return r;
5020
}
5021
 
5022
 
5023
static boolean
5024
is_alkoxy (int a_view, int a_ref)
5025
{
5026
  boolean r = false;
5027
  neighbor_rec nb;
5028
 
5029
  memset (nb, 0, sizeof (neighbor_rec));
5030
  if (!
5031
      (atom[a_view - 1].
5032
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5033
    return false;
5034
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5035
      || atom[a_ref - 1].neighbor_count != 2)
5036
    return false;
5037
  get_nextneighbors (nb, a_ref, a_view);
5038
  if (is_alkyl (a_ref, nb[0]))
5039
    r = true;
5040
  return r;
5041
}
5042
 
5043
 
5044
static boolean
5045
is_siloxy (int a_view, int a_ref)
5046
{
5047
  boolean r = false;
5048
  neighbor_rec nb;
5049
 
5050
  memset (nb, 0, sizeof (neighbor_rec));
5051
  if (!
5052
      (atom[a_view - 1].
5053
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5054
    return false;
5055
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5056
      || atom[a_ref - 1].neighbor_count != 2)
5057
    return false;
5058
  get_nextneighbors (nb, a_ref, a_view);
5059
  if (!strcmp (atom[nb[0] - 1].element, "SI"))
5060
    r = true;
5061
  return r;
5062
}
5063
 
5064
 
5065
static boolean
5066
is_true_alkoxy (int a_view, int a_ref)
5067
{
5068
  boolean r = false;
5069
  neighbor_rec nb;
5070
 
5071
  memset (nb, 0, sizeof (neighbor_rec));
5072
  if (!
5073
      (atom[a_view - 1].
5074
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5075
    return false;
5076
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5077
      || atom[a_ref - 1].neighbor_count != 2)
5078
    return false;
5079
  get_nextneighbors (nb, a_ref, a_view);
5080
  if (is_true_alkyl (a_ref, nb[0]))
5081
    r = true;
5082
  return r;
5083
}
5084
 
5085
 
5086
static boolean
5087
is_aryloxy (int a_view, int a_ref)
5088
{
5089
  boolean r = false;
5090
  neighbor_rec nb;
5091
 
5092
  memset (nb, 0, sizeof (neighbor_rec));
5093
  if (!
5094
      (atom[a_view - 1].
5095
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5096
    return false;
5097
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5098
      || atom[a_ref - 1].neighbor_count != 2)
5099
    return false;
5100
  get_nextneighbors (nb, a_ref, a_view);
5101
  if (is_aryl (a_ref, nb[0]))
5102
    r = true;
5103
  return r;
5104
}
5105
 
5106
 
5107
static boolean
5108
is_alkenyloxy (int a_view, int a_ref)
5109
{
5110
  /* v0.3j */
5111
  boolean r = false;
5112
  neighbor_rec nb;
5113
 
5114
  memset (nb, 0, sizeof (neighbor_rec));
5115
  if (!
5116
      (atom[a_view - 1].
5117
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5118
    return false;
5119
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5120
      || atom[a_ref - 1].neighbor_count != 2)
5121
    return false;
5122
  get_nextneighbors (nb, a_ref, a_view);
5123
  if (is_alkenyl (a_ref, nb[0]))
5124
    r = true;
5125
  return r;
5126
}
5127
 
5128
 
5129
static boolean
5130
is_alkynyloxy (int a_view, int a_ref)
5131
{
5132
  /* v0.3j */
5133
  boolean r = false;
5134
  neighbor_rec nb;
5135
 
5136
  memset (nb, 0, sizeof (neighbor_rec));
5137
  if (!
5138
      (atom[a_view - 1].
5139
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5140
    return false;
5141
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5142
      || atom[a_ref - 1].neighbor_count != 2)
5143
    return false;
5144
  get_nextneighbors (nb, a_ref, a_view);
5145
  if (is_alkynyl (a_ref, nb[0]))
5146
    r = true;
5147
  return r;
5148
}
5149
 
5150
 
5151
static boolean
5152
is_alkylsulfanyl (int a_view, int a_ref)
5153
{
5154
  boolean r = false;
5155
  neighbor_rec nb;
5156
 
5157
  memset (nb, 0, sizeof (neighbor_rec));
5158
  if (!
5159
      (atom[a_view - 1].
5160
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5161
    return false;
5162
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5163
      || atom[a_ref - 1].neighbor_count != 2)
5164
    return false;
5165
  get_nextneighbors (nb, a_ref, a_view);
5166
  if (is_alkyl (a_ref, nb[0]))
5167
    r = true;
5168
  return r;
5169
}
5170
 
5171
 
5172
static boolean
5173
is_true_alkylsulfanyl (int a_view, int a_ref)
5174
{
5175
  boolean r = false;
5176
  neighbor_rec nb;
5177
 
5178
  memset (nb, 0, sizeof (neighbor_rec));
5179
  if (!
5180
      (atom[a_view - 1].
5181
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5182
    return false;
5183
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5184
      || atom[a_ref - 1].neighbor_count != 2)
5185
    return false;
5186
  get_nextneighbors (nb, a_ref, a_view);
5187
  if (is_true_alkyl (a_ref, nb[0]))
5188
    r = true;
5189
  return r;
5190
}
5191
 
5192
 
5193
static boolean
5194
is_arylsulfanyl (int a_view, int a_ref)
5195
{
5196
  boolean r = false;
5197
  neighbor_rec nb;
5198
 
5199
  memset (nb, 0, sizeof (neighbor_rec));
5200
  if (!
5201
      (atom[a_view - 1].
5202
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5203
    return false;
5204
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5205
      || atom[a_ref - 1].neighbor_count != 2)
5206
    return false;
5207
  get_nextneighbors (nb, a_ref, a_view);
5208
  if (is_aryl (a_ref, nb[0]))
5209
    r = true;
5210
  return r;
5211
}
5212
 
5213
 
5214
static boolean
5215
is_alkenylsulfanyl (a_view, a_ref)
5216
     int a_view, a_ref;
5217
{
5218
  /* v0.3j */
5219
  boolean r = false;
5220
  neighbor_rec nb;
5221
 
5222
  memset (nb, 0, sizeof (neighbor_rec));
5223
  if (!
5224
      (atom[a_view - 1].
5225
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5226
    return false;
5227
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5228
      || atom[a_ref - 1].neighbor_count != 2)
5229
    return false;
5230
  get_nextneighbors (nb, a_ref, a_view);
5231
  if (is_alkenyl (a_ref, nb[0]))
5232
    r = true;
5233
  return r;
5234
}
5235
 
5236
 
5237
static boolean
5238
is_alkynylsulfanyl (a_view, a_ref)
5239
     int a_view, a_ref;
5240
{
5241
  /* v0.3j */
5242
  boolean r = false;
5243
  neighbor_rec nb;
5244
 
5245
  memset (nb, 0, sizeof (neighbor_rec));
5246
  if (!
5247
      (atom[a_view - 1].
5248
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5249
    return false;
5250
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5251
      || atom[a_ref - 1].neighbor_count != 2)
5252
    return false;
5253
  get_nextneighbors (nb, a_ref, a_view);
5254
  if (is_alkynyl (a_ref, nb[0]))
5255
    r = true;
5256
  return r;
5257
}
5258
 
5259
 
5260
static boolean
5261
is_alkylamino (a_view, a_ref)
5262
     int a_view, a_ref;
5263
{
5264
  boolean r = false;
5265
  neighbor_rec nb;
5266
  int alkyl_count = 0;
5267
 
5268
  memset (nb, 0, sizeof (neighbor_rec));
5269
  if (!
5270
      (atom[a_view - 1].
5271
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5272
    return false;
5273
  if (strcmp (atom[a_ref - 1].element, "N ")
5274
      || atom[a_ref - 1].neighbor_count != 2)
5275
    return false;
5276
  get_nextneighbors (nb, a_ref, a_view);
5277
  if (is_alkyl (a_ref, nb[0]))
5278
    alkyl_count++;
5279
  if (alkyl_count == 1)
5280
    r = true;
5281
  return r;
5282
}
5283
 
5284
 
5285
static boolean
5286
is_dialkylamino (a_view, a_ref)
5287
     int a_view, a_ref;
5288
{
5289
  int i;
5290
  boolean r = false;
5291
  neighbor_rec nb;
5292
  int alkyl_count = 0;
5293
 
5294
  memset (nb, 0, sizeof (neighbor_rec));
5295
  if (!
5296
      (atom[a_view - 1].
5297
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5298
    return false;
5299
  if (strcmp (atom[a_ref - 1].element, "N ")
5300
      || atom[a_ref - 1].neighbor_count != 3)
5301
    return false;
5302
  get_nextneighbors (nb, a_ref, a_view);
5303
  for (i = 0; i <= 1; i++)
5304
    {
5305
      if (is_alkyl (a_ref, nb[i]))
5306
        alkyl_count++;
5307
    }
5308
  if (alkyl_count == 2)
5309
    r = true;
5310
  return r;
5311
}
5312
 
5313
 
5314
static boolean
5315
is_arylamino (a_view, a_ref)
5316
     int a_view, a_ref;
5317
{
5318
  boolean r = false;
5319
  neighbor_rec nb;
5320
  int aryl_count = 0;
5321
 
5322
  memset (nb, 0, sizeof (neighbor_rec));
5323
  if (!
5324
      (atom[a_view - 1].
5325
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5326
    return false;
5327
  if (strcmp (atom[a_ref - 1].element, "N ")
5328
      || atom[a_ref - 1].neighbor_count != 2)
5329
    return false;
5330
  get_nextneighbors (nb, a_ref, a_view);
5331
  if (is_aryl (a_ref, nb[0]))
5332
    aryl_count++;
5333
  if (aryl_count == 1)
5334
    r = true;
5335
  return r;
5336
}
5337
 
5338
 
5339
static boolean
5340
is_diarylamino (a_view, a_ref)
5341
     int a_view, a_ref;
5342
{
5343
  int i;
5344
  boolean r = false;
5345
  neighbor_rec nb;
5346
  int aryl_count = 0;
5347
 
5348
  memset (nb, 0, sizeof (neighbor_rec));
5349
  if (!
5350
      (atom[a_view - 1].
5351
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5352
    return false;
5353
  if (strcmp (atom[a_ref - 1].element, "N ")
5354
      || atom[a_ref - 1].neighbor_count != 3)
5355
    return false;
5356
  get_nextneighbors (nb, a_ref, a_view);
5357
  for (i = 0; i <= 1; i++)
5358
    {
5359
      if (is_aryl (a_ref, nb[i]))
5360
        aryl_count++;
5361
    }
5362
  if (aryl_count == 2)
5363
    r = true;
5364
  return r;
5365
}
5366
 
5367
 
5368
static boolean
5369
is_alkylarylamino (a_view, a_ref)
5370
     int a_view, a_ref;
5371
{
5372
  int i;
5373
  boolean r = false;
5374
  neighbor_rec nb;
5375
  int alkyl_count = 0, aryl_count = 0;
5376
 
5377
  memset (nb, 0, sizeof (neighbor_rec));
5378
  if (!
5379
      (atom[a_view - 1].
5380
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5381
    return false;
5382
  if (strcmp (atom[a_ref - 1].element, "N ")
5383
      || atom[a_ref - 1].neighbor_count != 3)
5384
    return false;
5385
  get_nextneighbors (nb, a_ref, a_view);
5386
  for (i = 0; i <= 1; i++)
5387
    {
5388
      if (is_alkyl (a_ref, nb[i]))
5389
        alkyl_count++;
5390
      if (is_aryl (a_ref, nb[i]))
5391
        aryl_count++;
5392
    }
5393
  if (alkyl_count == 1 && aryl_count == 1)
5394
    r = true;
5395
  return r;
5396
}
5397
 
5398
 
5399
static boolean
5400
is_C_monosubst_amino (a_view, a_ref)
5401
     int a_view, a_ref;
5402
{
5403
  /* new in v0.3j */
5404
  boolean r = false;
5405
  neighbor_rec nb;
5406
  int c_count = 0;
5407
 
5408
  memset (nb, 0, sizeof (neighbor_rec));
5409
  if (!
5410
      (atom[a_view - 1].
5411
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5412
    return false;
5413
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5414
      && strcmp (atom[a_ref - 1].atype, "NAM"))
5415
      || atom[a_ref - 1].neighbor_count != 2)
5416
    return false;
5417
  get_nextneighbors (nb, a_ref, a_view);
5418
  if (!strcmp (atom[nb[0] - 1].element, "C "))
5419
    c_count++;
5420
  if (c_count == 1)
5421
    r = true;
5422
  return r;
5423
}
5424
 
5425
 
5426
static boolean
5427
is_C_disubst_amino (a_view, a_ref)
5428
     int a_view, a_ref;
5429
{
5430
  /* new in v0.3j */
5431
  int i;
5432
  boolean r = false;
5433
  neighbor_rec nb;
5434
  int b;
5435
  int c_count = 0;
5436
 
5437
  b = get_bond (a_view, a_ref);
5438
  memset (nb, 0, sizeof (neighbor_rec));
5439
  if (!(atom[a_view - 1].heavy && bond[b - 1].btype == 'S' &&
5440
        bond[b - 1].arom == false))
5441
    return false;
5442
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5443
      && strcmp (atom[a_ref - 1].atype, "NAM"))
5444
      || atom[a_ref - 1].neighbor_count != 3)
5445
    return false;
5446
  get_nextneighbors (nb, a_ref, a_view);
5447
  for (i = 0; i <= 1; i++)
5448
    {
5449
      if (!strcmp (atom[nb[i] - 1].element, "C "))
5450
        c_count++;
5451
    }
5452
  if (c_count == 2)
5453
    r = true;
5454
  return r;
5455
}
5456
 
5457
 
5458
static boolean
5459
is_subst_amino (a_view, a_ref)
5460
     int a_view, a_ref;
5461
{
5462
  boolean r = false;
5463
 
5464
  if (is_amino (a_view, a_ref) || is_alkylamino (a_view, a_ref) |
5465
      is_arylamino (a_view, a_ref) || is_dialkylamino (a_view, a_ref) |
5466
      is_alkylarylamino (a_view, a_ref) || is_diarylamino (a_view, a_ref))
5467
    r = true;
5468
  return r;
5469
}
5470
 
5471
 
5472
static boolean
5473
is_true_alkylamino (a_view, a_ref)
5474
     int a_view, a_ref;
5475
{
5476
  boolean r = false;
5477
  neighbor_rec nb;
5478
  int alkyl_count = 0;
5479
 
5480
  memset (nb, 0, sizeof (neighbor_rec));
5481
  if (!
5482
      (atom[a_view - 1].
5483
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5484
    return false;
5485
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5486
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5487
      || atom[a_ref - 1].neighbor_count != 2)
5488
    return false;
5489
  get_nextneighbors (nb, a_ref, a_view);
5490
  if (is_true_alkyl (a_ref, nb[0]))
5491
    alkyl_count++;
5492
  if (alkyl_count == 1)
5493
    r = true;
5494
  return r;
5495
}
5496
 
5497
 
5498
static boolean
5499
is_true_dialkylamino (a_view, a_ref)
5500
     int a_view, a_ref;
5501
{
5502
  int i;
5503
  boolean r = false;
5504
  neighbor_rec nb;
5505
  int alkyl_count = 0;
5506
 
5507
  memset (nb, 0, sizeof (neighbor_rec));
5508
  if (!
5509
      (atom[a_view - 1].
5510
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5511
    return false;
5512
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5513
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5514
      || atom[a_ref - 1].neighbor_count != 3)
5515
    return false;
5516
  get_nextneighbors (nb, a_ref, a_view);
5517
  for (i = 0; i <= 1; i++)
5518
    {
5519
      if (is_true_alkyl (a_ref, nb[i]))
5520
        alkyl_count++;
5521
    }
5522
  if (alkyl_count == 2)
5523
    r = true;
5524
  return r;
5525
}
5526
 
5527
#if 0
5528
static boolean
5529
is_true_alkylarylamino (a_view, a_ref)
5530
     int a_view, a_ref;
5531
{
5532
  int i;
5533
  boolean r = false;
5534
  neighbor_rec nb;
5535
  int alkyl_count = 0, aryl_count = 0;
5536
 
5537
  memset (nb, 0, sizeof (neighbor_rec));
5538
  if (!
5539
      (atom[a_view - 1].
5540
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5541
    return false;
5542
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5543
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5544
      || atom[a_ref - 1].neighbor_count != 3)
5545
    return false;
5546
  get_nextneighbors (nb, a_ref, a_view);
5547
  for (i = 0; i <= 1; i++)
5548
    {
5549
      if (is_true_alkyl (a_ref, nb[i]))
5550
        alkyl_count++;
5551
      if (is_aryl (a_ref, nb[i]))
5552
        aryl_count++;
5553
    }
5554
  if (alkyl_count == 1 && aryl_count == 1)
5555
    r = true;
5556
  return r;
5557
}
5558
#endif
5559
 
5560
static boolean
5561
is_hydroxylamino (a_view, a_ref)
5562
     int a_view, a_ref;
5563
{
5564
  int i;
5565
  boolean r = false;
5566
  neighbor_rec nb;
5567
  int oh_count = 0, het_count = 0;      /* v0.3k */
5568
  str2 nb_el;                   /* v0.3k */
5569
  int FORLIM;
5570
 
5571
  memset (nb, 0, sizeof (neighbor_rec));
5572
  if (!
5573
      (atom[a_view - 1].
5574
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5575
    return false;
5576
  if (strcmp (atom[a_ref - 1].element, "N ")
5577
      || atom[a_ref - 1].neighbor_count < 2)
5578
    /* v0.3c */
5579
    return false;
5580
  get_nextneighbors (nb, a_ref, a_view);
5581
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
5582
  for (i = 0; i <= FORLIM; i++)
5583
    {                           /* v0.3c */
5584
      if (is_hydroxy (a_ref, nb[i]))
5585
        oh_count++;
5586
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3k */
5587
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
5588
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
5589
          && strcmp (nb_el, "LP"))
5590
        /* v0.3k */
5591
        het_count++;
5592
      /* v0.3n: D */
5593
    }
5594
  if (oh_count == 1 && het_count == 1)
5595
    r = true;
5596
  return r;
5597
}
5598
 
5599
 
5600
static boolean
5601
is_nitro (a_view, a_ref)
5602
     int a_view, a_ref;
5603
{
5604
  int i;
5605
  boolean r = false;
5606
  neighbor_rec nb;
5607
  int o_count = 0, bond_count = 0;
5608
 
5609
  memset (nb, 0, sizeof (neighbor_rec));
5610
  if (!
5611
      (atom[a_view - 1].
5612
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5613
    return false;
5614
  if (strcmp (atom[a_ref - 1].element, "N ")
5615
      || atom[a_ref - 1].neighbor_count != 3)
5616
    return false;
5617
  get_nextneighbors (nb, a_ref, a_view);
5618
  for (i = 0; i <= 1; i++)
5619
    {
5620
      if (!strcmp (atom[nb[i] - 1].element, "O "))
5621
        o_count++;
5622
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
5623
        bond_count++;
5624
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
5625
        bond_count += 2;
5626
    }
5627
  if (o_count == 2 && bond_count >= 3)
5628
    r = true;
5629
  return r;
5630
}
5631
 
5632
 
5633
static boolean
5634
is_azido (a_view, a_ref)
5635
     int a_view, a_ref;
5636
{
5637
  boolean r = false;
5638
  neighbor_rec nb;
5639
  int bond_count = 0, n1 = 0, n2 = 0, n3 = 0;
5640
 
5641
  if (!
5642
      (atom[a_view - 1].
5643
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5644
    return false;
5645
  if (strcmp (atom[a_ref - 1].element, "N ")
5646
      || atom[a_ref - 1].neighbor_count != 2)
5647
    return false;
5648
  n1 = a_ref;
5649
  memset (nb, 0, sizeof (neighbor_rec));
5650
  get_nextneighbors (nb, n1, a_view);
5651
  if (!strcmp (atom[nb[0] - 1].element, "N "))
5652
    {
5653
      n2 = nb[0];
5654
      if (bond[get_bond (n1, n2) - 1].btype == 'S')
5655
        bond_count++;
5656
      if (bond[get_bond (n1, n2) - 1].btype == 'D')
5657
        bond_count += 2;
5658
      if (bond[get_bond (n1, n2) - 1].btype == 'T')
5659
        bond_count += 3;
5660
    }
5661
  if (n2 > 0 && atom[n2 - 1].neighbor_count == 2)
5662
    {
5663
      memset (nb, 0, sizeof (neighbor_rec));
5664
      get_nextneighbors (nb, n2, n1);
5665
      if (!strcmp (atom[nb[0] - 1].element, "N "))
5666
        {
5667
          n3 = nb[0];
5668
          if (bond[get_bond (n2, n3) - 1].btype == 'S')
5669
            bond_count++;
5670
          if (bond[get_bond (n2, n3) - 1].btype == 'D')
5671
            bond_count += 2;
5672
          if (bond[get_bond (n2, n3) - 1].btype == 'T')
5673
            bond_count += 3;
5674
        }
5675
    }
5676
  if (n1 > 0 && n2 > 0 && n3 > 0 && atom[n3 - 1].neighbor_count == 1 &&
5677
      bond_count > 3)
5678
    r = true;
5679
  return r;
5680
}
5681
 
5682
 
5683
static boolean
5684
is_diazonium (a_view, a_ref)
5685
     int a_view, a_ref;
5686
{
5687
  boolean r = false;
5688
  neighbor_rec nb;
5689
  int bond_count = 0, chg_count = 0, n1 = 0, n2 = 0;
5690
 
5691
  if (!
5692
      (atom[a_view - 1].
5693
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5694
    return false;
5695
  if (strcmp (atom[a_ref - 1].element, "N ")
5696
      || atom[a_ref - 1].neighbor_count != 2)
5697
    return false;
5698
  n1 = a_ref;
5699
  chg_count = atom[n1 - 1].formal_charge;
5700
  memset (nb, 0, sizeof (neighbor_rec));
5701
  get_nextneighbors (nb, n1, a_view);
5702
  if (!strcmp (atom[nb[0] - 1].element, "N "))
5703
    {
5704
      n2 = nb[0];
5705
      chg_count += atom[n2 - 1].formal_charge;
5706
      if (bond[get_bond (n1, n2) - 1].btype == 'S')
5707
        bond_count++;
5708
      if (bond[get_bond (n1, n2) - 1].btype == 'D')
5709
        bond_count += 2;
5710
      if (bond[get_bond (n1, n2) - 1].btype == 'T')
5711
        bond_count += 3;
5712
    }
5713
  if (n1 > 0 && n2 > 0 && atom[n2 - 1].neighbor_count == 1
5714
      && bond_count >= 2 && chg_count > 0)
5715
    r = true;
5716
  return r;
5717
}
5718
 
5719
 
5720
static boolean
5721
is_hydroximino_C (id)
5722
     int id;
5723
{
5724
  int i;
5725
  boolean r = false;
5726
  neighbor_rec nb;
5727
  int a_het = 0;
5728
  int FORLIM;
5729
 
5730
  memset (nb, 0, sizeof (neighbor_rec));
5731
  if (id < 1 || id > n_atoms)
6789 bpr 5732
    return false;
6785 bpr 5733
  get_neighbors (nb, id);
5734
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5735
    return false;
5736
  FORLIM = atom[id - 1].neighbor_count;
5737
  for (i = 0; i < FORLIM; i++)
5738
    {
5739
      if ((bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5740
           !strcmp (atom[nb[i] - 1].element,
5741
                    "N ")) && (hetbond_count (nb[i]) == 3))
5742
        a_het = nb[i];
5743
    }
5744
  if (a_het <= 0)
5745
    return false;
5746
  memset (nb, 0, sizeof (neighbor_rec));
5747
  get_neighbors (nb, a_het);
5748
  if (strcmp (atom[a_het - 1].element, "N ")
5749
      || atom[a_het - 1].neighbor_count <= 0)
5750
    return false;
5751
  FORLIM = atom[a_het - 1].neighbor_count;
5752
  for (i = 0; i < FORLIM; i++)
5753
    {
5754
      if (is_hydroxy (a_het, nb[i]))
5755
        r = true;
5756
    }
5757
  return r;
5758
}
5759
 
5760
 
5761
static boolean
5762
is_hydrazono_C (id)
5763
     int id;
5764
{
5765
  int i;
5766
  boolean r = false;
5767
  neighbor_rec nb;
5768
  int a_het = 0;
5769
  int FORLIM;
5770
 
5771
  memset (nb, 0, sizeof (neighbor_rec));
5772
  if (id < 1 || id > n_atoms)
6789 bpr 5773
    return false;
6785 bpr 5774
  get_neighbors (nb, id);
5775
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5776
    return false;
5777
  FORLIM = atom[id - 1].neighbor_count;
5778
  for (i = 0; i < FORLIM; i++)
5779
    {
5780
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5781
          !strcmp (atom[nb[i] - 1].element, "N "))
5782
        {
5783
          /* and
5784
             (hetbond_count(nb[i]) = 3)  */
5785
          a_het = nb[i];
5786
        }
5787
    }
5788
  if (a_het <= 0)
5789
    return false;
5790
  memset (nb, 0, sizeof (neighbor_rec));
5791
  get_neighbors (nb, a_het);
5792
  if (strcmp (atom[a_het - 1].element, "N ")
5793
      || atom[a_het - 1].neighbor_count <= 0)
5794
    return false;
5795
  FORLIM = atom[a_het - 1].neighbor_count;
5796
  for (i = 0; i < FORLIM; i++)
5797
    {
5798
      if (is_amino (a_het, nb[i]) || is_alkylamino (a_het, nb[i]) |
5799
          is_alkylarylamino (a_het, nb[i]) || is_arylamino (a_het, nb[i]) |
5800
          is_dialkylamino (a_het, nb[i]) || is_diarylamino (a_het, nb[i]))
5801
        r = true;
5802
    }
5803
  return r;
5804
}
5805
 
5806
 
5807
static boolean
5808
is_alkoxycarbonyl (a_view, a_ref)
5809
     int a_view, a_ref;
5810
{
5811
  int i;
5812
  boolean r = false;
5813
  neighbor_rec nb;
5814
 
5815
  memset (nb, 0, sizeof (neighbor_rec));
5816
  if (!
5817
      (atom[a_view - 1].
5818
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5819
    return false;
5820
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5821
    return false;
5822
  get_nextneighbors (nb, a_ref, a_view);
5823
  for (i = 0; i <= 1; i++)
5824
    {
5825
      if (is_alkoxy (a_ref, nb[i]))
5826
        r = true;
5827
    }
5828
  return r;
5829
}
5830
 
5831
 
5832
static boolean
5833
is_aryloxycarbonyl (a_view, a_ref)
5834
     int a_view, a_ref;
5835
{
5836
  int i;
5837
  boolean r = false;
5838
  neighbor_rec nb;
5839
 
5840
  memset (nb, 0, sizeof (neighbor_rec));
5841
  if (!
5842
      (atom[a_view - 1].
5843
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5844
    return false;
5845
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5846
    return false;
5847
  get_nextneighbors (nb, a_ref, a_view);
5848
  for (i = 0; i <= 1; i++)
5849
    {
5850
      if (is_aryloxy (a_ref, nb[i]))
5851
        r = true;
5852
    }
5853
  return r;
5854
}
5855
 
5856
 
5857
static boolean
5858
is_carbamoyl (a_view, a_ref)
5859
     int a_view, a_ref;
5860
{
5861
  int i;
5862
  boolean r = false;
5863
  neighbor_rec nb;
5864
 
5865
  memset (nb, 0, sizeof (neighbor_rec));
5866
  if (!
5867
      (atom[a_view - 1].
5868
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5869
    return false;
5870
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5871
    return false;
5872
  get_nextneighbors (nb, a_ref, a_view);
5873
  for (i = 0; i <= 1; i++)
5874
    {
5875
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5876
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
5877
        r = true;
5878
    }
5879
  return r;
5880
}
5881
 
5882
 
5883
static boolean
5884
is_alkoxythiocarbonyl (a_view, a_ref)
5885
     int a_view, a_ref;
5886
{
5887
  int i;
5888
  boolean r = false;
5889
  neighbor_rec nb;
5890
 
5891
  memset (nb, 0, sizeof (neighbor_rec));
5892
  if (!
5893
      (atom[a_view - 1].
5894
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5895
    return false;
5896
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5897
    return false;
5898
  get_nextneighbors (nb, a_ref, a_view);
5899
  for (i = 0; i <= 1; i++)
5900
    {
5901
      if (is_alkoxy (a_ref, nb[i]))
5902
        r = true;
5903
    }
5904
  return r;
5905
}
5906
 
5907
 
5908
static boolean
5909
is_aryloxythiocarbonyl (a_view, a_ref)
5910
     int a_view, a_ref;
5911
{
5912
  int i;
5913
  boolean r = false;
5914
  neighbor_rec nb;
5915
 
5916
  memset (nb, 0, sizeof (neighbor_rec));
5917
  if (!
5918
      (atom[a_view - 1].
5919
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5920
    return false;
5921
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5922
    return false;
5923
  get_nextneighbors (nb, a_ref, a_view);
5924
  for (i = 0; i <= 1; i++)
5925
    {
5926
      if (is_aryloxy (a_ref, nb[i]))
5927
        r = true;
5928
    }
5929
  return r;
5930
}
5931
 
5932
 
5933
static boolean
5934
is_thiocarbamoyl (a_view, a_ref)
5935
     int a_view, a_ref;
5936
{
5937
  int i;
5938
  boolean r = false;
5939
  neighbor_rec nb;
5940
 
5941
  memset (nb, 0, sizeof (neighbor_rec));
5942
  if (!
5943
      (atom[a_view - 1].
5944
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5945
    return false;
5946
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5947
    return false;
5948
  get_nextneighbors (nb, a_ref, a_view);
5949
  for (i = 0; i <= 1; i++)
5950
    {
5951
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5952
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
5953
        r = true;
5954
    }
5955
  return r;
5956
}
5957
 
5958
 
5959
static boolean
5960
is_alkanoyl (a_view, a_ref)
5961
     int a_view, a_ref;
5962
{
5963
  int i;
5964
  boolean r = false;
5965
  neighbor_rec nb;
5966
 
5967
  memset (nb, 0, sizeof (neighbor_rec));
5968
  if (!
5969
      (atom[a_view - 1].
5970
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5971
    return false;
5972
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5973
    return false;
5974
  get_nextneighbors (nb, a_ref, a_view);
5975
  for (i = 0; i <= 1; i++)
5976
    {
5977
      if (is_alkyl (a_ref, nb[i]))
5978
        r = true;
5979
    }
5980
  return r;
5981
}
5982
 
5983
 
5984
static boolean
5985
is_aroyl (a_view, a_ref)
5986
     int a_view, a_ref;
5987
{
5988
  int i;
5989
  boolean r = false;
5990
  neighbor_rec nb;
5991
 
5992
  memset (nb, 0, sizeof (neighbor_rec));
5993
  if (!
5994
      (atom[a_view - 1].
5995
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5996
    return false;
5997
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5998
    return false;
5999
  get_nextneighbors (nb, a_ref, a_view);
6000
  for (i = 0; i <= 1; i++)
6001
    {
6002
      if (is_aryl (a_ref, nb[i]))
6003
        r = true;
6004
    }
6005
  return r;
6006
}
6007
 
6008
 
6009
static boolean
6010
is_acyl (a_view, a_ref)
6011
     int a_view, a_ref;
6012
{
6013
  boolean r = false;
6014
 
6015
  if (is_alkanoyl (a_view, a_ref) || is_aroyl (a_view, a_ref))
6016
    r = true;
6017
  return r;
6018
}
6019
 
6020
 
6021
static boolean
6022
is_acyl_gen (a_view, a_ref)
6023
     int a_view, a_ref;
6024
{
6025
  /* new in v0.3j */
6026
  boolean r = false;
6027
 
6028
  if (is_oxo_C (a_ref))
6029
    r = true;
6030
  return r;
6031
}
6032
 
6033
 
6034
static boolean
6035
is_acylamino (a_view, a_ref)
6036
     int a_view, a_ref;
6037
{
6038
  boolean r = false;
6039
  neighbor_rec nb;
6040
  int acyl_count = 0;
6041
 
6042
  memset (nb, 0, sizeof (neighbor_rec));
6043
  if (!
6044
      (atom[a_view - 1].
6045
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6046
    return false;
6047
  if (strcmp (atom[a_ref - 1].element, "N ")
6048
      || atom[a_ref - 1].neighbor_count != 2)
6049
    return false;
6050
  get_nextneighbors (nb, a_ref, a_view);
6051
  if (is_acyl (a_ref, nb[0]))
6052
    acyl_count++;
6053
  if (acyl_count == 1)
6054
    r = true;
6055
  return r;
6056
}
6057
 
6058
 
6059
static boolean
6060
is_subst_acylamino (a_view, a_ref)
6061
     int a_view, a_ref;
6062
{
6063
  /* may be substituted _or_ unsubstituted acylamino group! */
6064
  int i;
6065
  boolean r = false;
6066
  neighbor_rec nb;
6067
  int acyl_count = 0;
6068
  int FORLIM;
6069
 
6070
  memset (nb, 0, sizeof (neighbor_rec));
6071
  if (!
6072
      (atom[a_view - 1].
6073
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6074
    return false;
6075
  if (strcmp (atom[a_ref - 1].element, "N ")
6076
      || atom[a_ref - 1].neighbor_count < 2)
6077
    return false;
6078
  get_nextneighbors (nb, a_ref, a_view);
6079
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6080
  for (i = 0; i <= FORLIM; i++)
6081
    {
6082
      if (is_acyl_gen (a_ref, nb[i]))   /* v0.3j */
6083
        acyl_count++;
6084
    }
6085
  if (acyl_count > 0)
6086
    r = true;
6087
  return r;
6088
}
6089
 
6090
 
6091
static boolean
6092
is_hydrazino (a_view, a_ref)
6093
     int a_view, a_ref;
6094
{
6095
  int i;
6096
  boolean r = false;
6097
  neighbor_rec nb;
6098
  int nr_count = 0;
6099
  int FORLIM;
6100
 
6101
  memset (nb, 0, sizeof (neighbor_rec));
6102
  if (!
6103
      (atom[a_view - 1].
6104
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6105
    return false;
6106
  if (strcmp (atom[a_ref - 1].element, "N ")
6107
      || atom[a_ref - 1].neighbor_count < 2)
6108
    return false;
6109
  get_nextneighbors (nb, a_ref, a_view);
6110
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6111
  for (i = 0; i <= FORLIM; i++)
6112
    {                           /* fixed in v0.3c */
6113
      if (is_amino (a_ref, nb[i]) || is_subst_amino (a_ref, nb[i]))
6114
        nr_count++;
6115
    }
6116
  if (nr_count == 1)
6117
    r = true;
6118
  return r;
6119
}
6120
 
6121
 
6122
static boolean
6123
is_nitroso (a_view, a_ref)
6124
     int a_view, a_ref;
6125
{
6126
  /* new in v0.3j */
6127
  boolean r = false;
6128
  neighbor_rec nb;
6129
  int o_count = 0;
6130
  int a2;
6131
 
6132
  memset (nb, 0, sizeof (neighbor_rec));
6133
  if (!
6134
      (atom[a_view - 1].
6135
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6136
    return false;
6137
  if (strcmp (atom[a_ref - 1].element, "N ")
6138
      || atom[a_ref - 1].neighbor_count != 2)
6139
    return false;
6140
  get_nextneighbors (nb, a_ref, a_view);
6141
  a2 = nb[0];
6142
  if ((strcmp (atom[a2 - 1].element, "O ") == 0) &
6143
      (bond[get_bond (a_ref, a2) - 1].btype == 'D'))
6144
    o_count++;
6145
  if (o_count == 1)
6146
    r = true;
6147
  return r;
6148
}
6149
 
6150
 
6151
static boolean
6152
is_subst_hydrazino (a_view, a_ref)
6153
     int a_view, a_ref;
6154
{
6155
  int i;
6156
  boolean r = false;
6157
  neighbor_rec nb;
6158
  int nr_count = 0;
6159
  int a2, FORLIM;
6160
 
6161
  memset (nb, 0, sizeof (neighbor_rec));
6162
  if (!
6163
      (atom[a_view - 1].
6164
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6165
    return false;
6166
  if (strcmp (atom[a_ref - 1].element, "N ")
6167
      || atom[a_ref - 1].neighbor_count < 2)
6168
    return false;
6169
  get_nextneighbors (nb, a_ref, a_view);
6170
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6171
  for (i = 0; i <= FORLIM; i++)
6172
    {
6173
      a2 = nb[i];
6174
      if ((strcmp (atom[a2 - 1].element, "N ") ==
6175
           0) && (!is_nitroso (a_ref, a2)))
6176
        /* v0.3j */
6177
        nr_count++;
6178
    }
6179
  if (nr_count == 1)
6180
    r = true;
6181
  return r;
6182
}
6183
 
6184
 
6185
static boolean
6186
is_cyano (a_view, a_ref)
6187
     int a_view, a_ref;
6188
{
6189
  boolean r = false;
6190
 
6191
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
6192
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6193
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
6194
      atom[a_ref - 1].neighbor_count == 1)
6195
    r = true;
6196
  return r;
6197
}
6198
 
6199
 
6200
static boolean
6201
is_cyano_c (a_ref)
6202
     int a_ref;
6203
{
6204
  int i;
6205
  boolean r = false;
6206
  neighbor_rec nb;
6207
  int FORLIM;
6208
 
6209
  memset (nb, 0, sizeof (neighbor_rec));
6210
  if (strcmp (atom[a_ref - 1].atype, "C1 ")
6211
      || atom[a_ref - 1].neighbor_count <= 0)
6212
    return false;
6213
  get_neighbors (nb, a_ref);
6214
  FORLIM = atom[a_ref - 1].neighbor_count;
6215
  for (i = 0; i < FORLIM; i++)
6216
    {
6217
      if (is_cyano (a_ref, nb[i]))
6218
        r = true;
6219
    }
6220
  return r;
6221
}
6222
 
6223
 
6224
static boolean
6225
is_nitrile (a_view, a_ref)
6226
     int a_view, a_ref;
6227
{
6228
  boolean r = false;
6229
  neighbor_rec nb;
6230
  str2 nb_el;
6231
 
6232
  if (!is_cyano (a_view, a_ref))
6233
    return false;
6234
  if (atom[a_view - 1].neighbor_count == 1
6235
      && atom[a_view - 1].formal_charge == 0)
6236
    return true;
6237
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6238
  get_nextneighbors (nb, a_view, a_ref);
6239
  strcpy (nb_el, atom[nb[0] - 1].element);
6240
  if (!strcmp (nb_el, "C ")
6241
      || !strcmp (nb_el, "H ") /*|| !strcmp (nb_el, "D ") */ )
6242
    /* v0.3n: D */
6243
    r = true;
6244
  /* HCN is also a nitrile! */
6245
  return r;
6246
}
6247
 
6248
 
6249
static boolean
6250
is_isonitrile (a_view, a_ref)
6251
     int a_view, a_ref;
6252
{
6253
  /* only recognized with CN triple bond! */
6254
  boolean r = false;
6255
 
6256
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
6257
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6258
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
6259
      atom[a_ref - 1].neighbor_count == 2
6260
      && atom[a_view - 1].neighbor_count == 1)
6261
    r = true;
6262
  return r;
6263
}
6264
 
6265
 
6266
static boolean
6267
is_cyanate (a_view, a_ref)
6268
     int a_view, a_ref;
6269
{
6270
  boolean r = false;
6271
  neighbor_rec nb;
6272
 
6273
  if (!is_cyano (a_view, a_ref))
6274
    return false;
6275
  if (atom[a_view - 1].neighbor_count != 2)
6276
    return false;
6277
  get_nextneighbors (nb, a_view, a_ref);
6278
  if (is_alkoxy (a_view, nb[0]) || is_aryloxy (a_view, nb[0]))
6279
    r = true;
6280
  return r;
6281
}
6282
 
6283
 
6284
static boolean
6285
is_thiocyanate (a_view, a_ref)
6286
     int a_view, a_ref;
6287
{
6288
  boolean r = false;
6289
  neighbor_rec nb;
6290
 
6291
  if (!is_cyano (a_view, a_ref))
6292
    return false;
6293
  if (atom[a_view - 1].neighbor_count != 2)
6294
    return false;
6295
  get_nextneighbors (nb, a_view, a_ref);
6296
  if (is_alkylsulfanyl (a_view, nb[0]) || is_arylsulfanyl (a_view, nb[0]))
6297
    r = true;
6298
  return r;
6299
}
6300
 
6301
 
6302
static void
6303
update_Htotal ()
6304
{
6305
  int i, j, b_id;
6306
  neighbor_rec nb;
6307
  int single_count, double_count, triple_count, arom_count, total_bonds,
6308
    Htotal, nval;
6309
  /* new in v0.3 */
6310
  boolean diazon = false;       /* new in v0.3j */
6311
  neighbor_rec nb2;             /* new in v0.3j */
6312
  int a1, a2, a3;               /* new in v0.3j */
6313
  int FORLIM, FORLIM1;
6314
 
6315
  if (n_atoms < 1)
6316
    return;
6317
  memset (nb, 0, sizeof (neighbor_rec));
6318
  FORLIM = n_atoms;
6319
  for (i = 1; i <= FORLIM; i++)
6320
    {
6321
      single_count = 0;
6322
      double_count = 0;
6323
      triple_count = 0;
6324
      arom_count = 0;
6325
      total_bonds = 0;
6326
      Htotal = 0;
6327
      get_neighbors (nb, i);
6328
      if (atom[i - 1].neighbor_count > 0)
6329
        {
6330
          /* count single, double, triple, and aromatic bonds to all neighbor atoms */
6331
          FORLIM1 = atom[i - 1].neighbor_count;
6332
          for (j = 0; j < FORLIM1; j++)
6333
            {
6334
              b_id = get_bond (i, nb[j]);
6335
              if (b_id > 0)
6336
                {
6337
                  if (bond[b_id - 1].btype == 'S')
6338
                    single_count++;
6339
                  if (bond[b_id - 1].btype == 'D')
6340
                    double_count++;
6341
                  if (bond[b_id - 1].btype == 'T')
6342
                    triple_count++;
6343
                  if (bond[b_id - 1].btype == 'A')
6344
                    arom_count++;
6345
                }
6346
            }
6347
          /*check for diazonium salts */
6348
          a1 = i;
6349
          a2 = nb[0];
6350
          if (!strcmp (atom[a1 - 1].element, "N ") &&
6351
              !strcmp (atom[a2 - 1].element, "N "))
6352
            {
6353
              if (atom[a2 - 1].neighbor_count == 2)
6354
                {
6355
                  get_nextneighbors (nb2, a2, a1);
6356
                  a3 = nb2[0];
6357
                  if ((strcmp (atom[a3 - 1].element, "C ") ==
6358
                       0) && is_diazonium (a3, a2))
6359
                    diazon = true;
6360
                }
6361
            }
6362
        }
6363
      total_bonds = single_count + double_count * 2 + triple_count * 3 +
6364
        (int) (1.5 * arom_count);
6365
      /* calculate number of total hydrogens per atom */
6366
      /*nval := nvalences(atom^[i].element);    (* new in v0.3 */
6367
      nval = atom[i - 1].nvalences;     /* new in v0.3m */
6368
      if (!strcmp (atom[i - 1].element, "P "))
6369
        {
6370
          if (total_bonds - atom[i - 1].formal_charge > 3)      /* refined in v0.3n */
6371
            nval = 5;
6372
        }                       /*  */
6373
      if (!strcmp (atom[i - 1].element, "S "))
6374
        {                       /* v0.3h */
6375
          if (total_bonds > 2 && atom[i - 1].formal_charge < 1)
6376
            /* updated in v0.3j */
6377
            nval = 4;
6378
          if (total_bonds > 4)  /* this will need some refinement... */
6379
            nval = 6;
6380
        }                       /*  */
6381
      Htotal = nval - total_bonds + atom[i - 1].formal_charge;
6382
      if (diazon)               /* v0.3j */
6383
        Htotal = 0;
6384
      if (Htotal < 0)           /* e.g., N in nitro group */
6385
        Htotal = 0;
6386
      atom[i - 1].Htot = Htotal;
6387
      if (atom[i - 1].Hexp > atom[i - 1].Htot)  /* v0.3n; just to be sure... */
6388
        atom[i - 1].Htot = atom[i - 1].Hexp;
6389
    }
6390
}
6391
 
6392
 
6393
static void
6394
update_atypes ()
6395
{
6396
  int i, j, b_id;
6397
  neighbor_rec nb;
6398
  int single_count, double_count, triple_count, arom_count, acyl_count,
6399
    C_count, O_count, total_bonds, NdO_count, NdC_count, Htotal, FORLIM,
6400
    FORLIM1;
6401
 
6402
  if (n_atoms < 1)
6403
    return;
6404
  memset (nb, 0, sizeof (neighbor_rec));
6405
  FORLIM = n_atoms;
6406
  for (i = 0; i < FORLIM; i++)
6407
    {
6408
      single_count = 0;
6409
      double_count = 0;
6410
      triple_count = 0;
6411
      arom_count = 0;
6412
      total_bonds = 0;
6413
      acyl_count = 0;
6414
      C_count = 0;
6415
      O_count = 0;
6416
      NdO_count = 0;
6417
      NdC_count = 0;
6418
      Htotal = 0;
6419
      get_neighbors (nb, i + 1);
6420
      if (atom[i].neighbor_count > 0)
6421
        {
6422
          /* count single, double, triple, and aromatic bonds to all neighbor atoms */
6423
          FORLIM1 = atom[i].neighbor_count;
6424
          for (j = 0; j < FORLIM1; j++)
6425
            {
6426
              if (is_oxo_C (nb[j]) || is_thioxo_C (nb[j]))
6427
                acyl_count++;
6428
              if (!strcmp (atom[nb[j] - 1].element, "C "))
6429
                C_count++;
6430
              if (!strcmp (atom[nb[j] - 1].element, "O "))
6431
                O_count++;
6432
              b_id = get_bond (i + 1, nb[j]);
6433
              if (b_id > 0)
6434
                {
6435
                  if (bond[b_id - 1].btype == 'S')
6436
                    single_count++;
6437
                  if (bond[b_id - 1].btype == 'D')
6438
                    double_count++;
6439
                  if (bond[b_id - 1].btype == 'T')
6440
                    triple_count++;
6441
                  if (bond[b_id - 1].btype == 'A')
6442
                    /* v0.3n: special treatment for acyclic bonds */
6443
                    {           /* flagged as "aromatic" (in query structures) */
6444
                      if (bond[b_id - 1].ring_count > 0)
6445
                        arom_count++;
6446
                      else
6447
                        double_count++;
6448
                    }
6449
                  if ((!strcmp (atom[i].element, "N ") &&
6450
                       !strcmp (atom[nb[j] - 1].element, "O ")) ||
6451
                      (!strcmp (atom[i].element, "O ") &&
6452
                       !strcmp (atom[nb[j] - 1].element, "N ")))
6453
                    {
6454
                      /* check if it is an N-oxide drawn with a double bond ==> should be N3 */
6455
                      if (bond[b_id - 1].btype == 'D')
6456
                        NdO_count++;
6457
                    }
6458
                  if ((!strcmp (atom[i].element, "N ") &&
6459
                       !strcmp (atom[nb[j] - 1].element, "C ")) ||
6460
                      (!strcmp (atom[i].element, "C ") &&
6461
                       !strcmp (atom[nb[j] - 1].element, "N ")))
6462
                    {
6463
                      if (bond[b_id - 1].btype == 'D')
6464
                        NdC_count++;
6465
                    }
6466
                }
6467
            }
6468
          total_bonds = single_count + double_count * 2 + triple_count * 3 +
6469
            (int) (1.5 * arom_count);
6470
          /* calculate number of total hydrogens per atom */
6471
          /*Htotal := nvalences(atom^[i].element) - total_bonds + atom^[i].formal_charge; */
6472
          Htotal = atom[i].nvalences - total_bonds + atom[i].formal_charge;
6473
          if (Htotal < 0)       /* e.g., N in nitro group */
6474
            Htotal = 0;
6475
          atom[i].Htot = Htotal;
6476
          /* refine atom types, based on bond types */
6477
          if (!strcmp (atom[i].element, "C "))
6478
            {
6479
              if (arom_count > 1)
6480
                strcpy (atom[i].atype, "CAR");
6481
              if (triple_count == 1 || double_count == 2)
6482
                strcpy (atom[i].atype, "C1 ");
6483
              if (double_count == 1)
6484
                strcpy (atom[i].atype, "C2 ");
6485
              if (triple_count == 0 && double_count == 0 && arom_count < 2)
6486
                strcpy (atom[i].atype, "C3 ");
6487
            }
6488
          if (!strcmp (atom[i].element, "O "))
6489
            {
6490
              if (double_count == 1)
6491
                strcpy (atom[i].atype, "O2 ");
6492
              if (double_count == 0)
6493
                strcpy (atom[i].atype, "O3 ");
6494
            }
6495
          if (!strcmp (atom[i].element, "N "))
6496
            {
6497
              if (total_bonds > 3)
6498
                {
6499
                  if (O_count == 0)
6500
                    {
6501
                      if (single_count > 3 ||
6502
                          (single_count == 2 && double_count == 1
6503
                          && C_count >= 2))
6504
                        atom[i].formal_charge = 1;
6505
                    }
6506
                  else
6507
                    {
6508
                      if (O_count == 1 && atom[i].formal_charge == 0)   /* v0.3m */
6509
                        strcpy (atom[i].atype, "N3 ");
6510
                      if (O_count == 2 && atom[i].formal_charge == 0)
6511
                        {
6512
                          if (atom[i].neighbor_count > 2)       /* nitro v0.3o */
6513
                            strcpy (atom[i].atype, "N2 ");
6514
                          if (atom[i].neighbor_count == 2)      /* NO2   v0.3o */
6515
                            strcpy (atom[i].atype, "N1 ");
6516
                        }
6517
                      /* the rest is left empty, so far.... */
6518
                    }
6519
                }
6520
              /* could be an N-oxide -> should be found elsewhere  */
6521
              if (triple_count == 1 ||
6522
                  (double_count == 2 && atom[i].neighbor_count == 2))
6523
                /* v0.3n */
6524
                strcpy (atom[i].atype, "N1 ");
6525
              if (double_count == 1)
6526
                {
6527
                  /*if NdC_count > 0 then atom^[i].atype := 'N2 '; */
6528
                  if (NdC_count == 0 && NdO_count > 0 && C_count >= 2)
6529
                    strcpy (atom[i].atype, "N3 ");
6530
                  /* N-oxide is N3 except in hetarene etc. */
6531
                  else
6532
                    strcpy (atom[i].atype, "N2 ");
6533
                }
6534
              /* fallback, added in v0.3g  */
6535
              if (arom_count > 1 || atom[i].arom == true)       /* v0.3n */
6536
                strcpy (atom[i].atype, "NAR");
6537
              if (triple_count == 0 && double_count == 0)
6538
                {
6539
                  if (atom[i].formal_charge == 0)
6540
                    {
6541
                      if (acyl_count == 0)
6542
                        strcpy (atom[i].atype, "N3 ");
6543
                      if (acyl_count > 0)
6544
                        strcpy (atom[i].atype, "NAM");
6545
                    }
6546
                  if (atom[i].formal_charge == 1)
6547
                    strcpy (atom[i].atype, "N3+");
6548
                }
6549
            }
6550
          if (!strcmp (atom[i].element, "P "))
6551
            {
6552
              if (single_count > 4)
6553
                strcpy (atom[i].atype, "P4 ");
6554
              if (single_count <= 4 && double_count == 0)
6555
                strcpy (atom[i].atype, "P3 ");
6556
              if (double_count == 2)
6557
                strcpy (atom[i].atype, "P3D");
6558
            }
6559
          if (!strcmp (atom[i].element, "S "))
6560
            {
6561
              if (double_count == 1 && single_count == 0)
6562
                strcpy (atom[i].atype, "S2 ");
6563
              if (double_count == 0)
6564
                strcpy (atom[i].atype, "S3 ");
6565
              if (double_count == 1 && single_count > 0)
6566
                strcpy (atom[i].atype, "SO ");
6567
              if (double_count == 2 && single_count > 0)
6568
                strcpy (atom[i].atype, "SO2");
6569
            }
6570
          /* further atom types should go here */
6571
        }
6572
    }
6573
}
6574
 
6575
 
6576
static void
6577
chk_arom ()
6578
{
6579
  int i, j, pi_count, ring_size, b, a1, a2;     /* v0.3n */
6580
  ringpath_type testring;
6581
  int a_ref, a_prev, a_next, b_bk, b_fw, b_exo;
6582
  char bt_bk, bt_fw;
6583
  boolean ar_bk, ar_fw, ar_exo; /* new in v0.3 */
6584
  boolean conj_intr, ko, aromatic, aromatic_bt; /* v0.3n */
6585
  int n_db, n_sb, n_ar;
6586
  boolean cumul;
6587
  int exo_mC;                   /* v0.3j */
6588
  int arom_pi_diff;             /* v0.3j */
6589
  int FORLIM;
6590
 
6591
  if (n_rings < 1)
6592
    return;
6593
  FORLIM = n_rings;
6594
  /* first, do a very quick check for benzene, pyridine, etc. */
6595
  for (i = 0; i < FORLIM; i++)
6596
    {
6597
      ring_size = ringprop[i].size;
6598
      if (ring_size == 6)
6599
        {
6600
          memset (testring, 0, sizeof (ringpath_type));
6601
          for (j = 0; j < ring_size; j++)
6602
            testring[j] = ring[i][j];
6603
          cumul = false;
6604
          n_sb = 0;
6605
          n_db = 0;
6606
          n_ar = 0;
6607
          a_prev = testring[ring_size - 1];
6608
          for (j = 1; j <= ring_size; j++)
6609
            {
6610
              a_ref = testring[j - 1];
6611
              if (j < ring_size)
6612
                a_next = testring[j];
6613
              else
6614
                a_next = testring[0];
6615
              b_bk = get_bond (a_prev, a_ref);
6616
              b_fw = get_bond (a_ref, a_next);
6617
              bt_bk = bond[b_bk - 1].btype;
6618
              bt_fw = bond[b_fw - 1].btype;
6619
              if (bt_fw == 'S')
6620
                n_sb++;
6621
              if (bt_fw == 'D')
6622
                n_db++;
6623
              if (bt_fw == 'A')
6624
                n_ar++;
6625
              if (bt_fw != 'A' && bt_bk == bt_fw)
6626
                cumul = true;
6627
              a_prev = a_ref;
6628
            }
6629
          if (n_ar == 6 || (n_sb == 3 && n_db == 3 && cumul == false))
6630
            {                   /* this ring is aromatic */
6631
              a_prev = testring[ring_size - 1];
6632
              for (j = 0; j < ring_size; j++)
6633
                {
6634
                  a_ref = testring[j];
6635
                  b_bk = get_bond (a_prev, a_ref);
6636
                  bond[b_bk - 1].arom = true;
6637
                  a_prev = a_ref;
6638
                }
6639
              ringprop[i].arom = true;
6640
            }
6641
        }
6642
    }
6643
  FORLIM = n_rings;
6644
  for (i = 1; i <= FORLIM; i++)
6645
    {
6646
      if (ringprop[i - 1].arom == false)
6647
        {
6648
          /* do the hard work only for those rings which are not yet flagged aromatic */
6649
          memset (testring, 0, sizeof (ringpath_type));
6650
          ring_size = ringprop[i - 1].size;     /* v0.3j */
6651
          for (j = 0; j < ring_size; j++)       /* v0.3j */
6652
            testring[j] = ring[i - 1][j];
6653
          pi_count = 0;
6654
          arom_pi_diff = 0;     /* v0.3j */
6655
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6656
          ko = false;
6657
          a_prev = testring[ring_size - 1];
6658
          for (j = 1; j <= ring_size; j++)
6659
            {
6660
              a_ref = testring[j - 1];
6661
              if (j < ring_size)
6662
                a_next = testring[j];
6663
              else
6664
                a_next = testring[0];
6665
              b_bk = get_bond (a_prev, a_ref);
6666
              b_fw = get_bond (a_ref, a_next);
6667
              bt_bk = bond[b_bk - 1].btype;
6668
              bt_fw = bond[b_fw - 1].btype;
6669
              ar_bk = bond[b_bk - 1].arom;
6670
              ar_fw = bond[b_fw - 1].arom;
6671
              if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == false
6672
                  && ar_fw == false)
6673
                {
6674
                  /* first, assume the worst case (interrupted conjugation) */
6675
                  conj_intr = true;
6676
                  /* conjugation can be restored by hetero atoms */
6677
                  if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6678
                      !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6679
                      !strcmp (atom[a_ref - 1].element, "N ") ||
6680
                      !strcmp (atom[a_ref - 1].element, "SE"))
6681
                    {
6682
                      conj_intr = false;
6683
                      pi_count += 2;    /* lone pair adds for 2 pi electrons */
6684
                    }
6685
                  /* conjugation can be restored by a formal charge at a methylene group */
6686
                  if (!strcmp (atom[a_ref - 1].element, "C ") &&
6687
                      atom[a_ref - 1].formal_charge != 0)
6688
                    {
6689
                      conj_intr = false;
6690
                      pi_count -= atom[a_ref - 1].formal_charge;
6691
                      /* neg. charge increases pi_count! */
6692
                    }
6693
                  /* conjugation can be restored by carbonyl groups etc. */
6694
                  if (is_oxo_C (a_ref) || is_thioxo_C (a_ref) |
6695
                      is_exocyclic_imino_C (a_ref, i))
6696
                    conj_intr = false;
6697
                  /* conjugation can be restored by exocyclic C=C double bond, */
6698
                  /* adds 2 pi electrons to 5-membered rings, not to 7-membered rings (CAUTION!) */
6699
                  /* apply only to non-aromatic exocyclic C=C bonds */
6700
                  exo_mC = find_exocyclic_methylene_C (a_ref, i);       /* v0.3j */
6701
                  if (exo_mC > 0 && (ring_size & 1))
6702
                    {           /* v0.3j */
6703
                      b_exo = get_bond (a_ref, exo_mC); /* v0.3j  */
6704
                      ar_exo = bond[b_exo - 1].arom;
6705
                      if (((ring_size - 1) & 3) == 0)
6706
                        {       /* 5-membered rings and related */
6707
                          conj_intr = false;
6708
                          pi_count += 2;
6709
                        }
6710
                      else
6711
                        {
6712
                          if (!ar_exo)
6713
                            conj_intr = false;
6714
                        }
6715
                    }
6716
                  /* 7-membered rings and related */
6717
                  /* if conjugation is still interrupted ==> knock-out */
6718
                  if (conj_intr)
6719
                    ko = true;
6720
                }
6721
              else
6722
                {
6723
                  if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == true
6724
                      && ar_fw == true)
6725
                    {
6726
                      if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6727
                          !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6728
                          !strcmp (atom[a_ref - 1].element, "N ") ||
6729
                          !strcmp (atom[a_ref - 1].element, "SE"))
6730
                        pi_count += 2;  /* lone pair adds for 2 pi electrons */
6731
                      if (!strcmp (atom[a_ref - 1].element, "C ") &&
6732
                          atom[a_ref - 1].formal_charge != 0)
6733
                        pi_count -= atom[a_ref - 1].formal_charge;
6734
                      /* neg. charge increases pi_count! */
6735
                      exo_mC = find_exocyclic_methylene_C (a_ref, i);   /* v0.3j */
6736
                      if (exo_mC > 0 && (ring_size & 1))
6737
                        {       /* v0.3j */
6738
                          b_exo = get_bond (a_ref, exo_mC);     /* v0.3j */
6739
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6740
                          if (((ring_size - 1) & 3) == 0)
6741
                            /* 5-membered rings and related */
6742
                            pi_count += 2;
6743
                        }
6744
                    }
6745
                  else
6746
                    {
6747
                      pi_count++;       /* v0.3j; adjustment for bridgehead N: see below */
6748
                      if (bt_bk == 'S' && bt_fw == 'S' &&
6749
                          ((ar_bk == true && ar_fw == false) ||
6750
                           (ar_bk == false && ar_fw == true)))
6751
                        {
6752
                          /* v0.3j; if a bridgehead N were not aromatic, it could  */
6753
                          /* contribute 2 pi electrons --> try also this variant */
6754
                          /* (example: CAS 32278-54-9) */
6755
                          if (!strcmp (atom[a_ref - 1].element, "N "))
6756
                            {
6757
                              arom_pi_diff++;
6758
                              /* any other case: increase pi count by one electron */
6759
                            }
6760
                        }
6761
                    }
6762
                }
6763
              /* last command: */
6764
              a_prev = a_ref;
6765
            }                   /* for j := 1 to ring_size */
6766
          /* now we can draw our conclusion */
6767
          /*if not ((ko) or (odd(pi_count))) then */
6768
          if (!ko)
6769
            /* v0.3j; odd pi_count might be compensated by arom_pi_diff */
6770
            {                   /* apply Hueckel's rule */
6771
              if (labs (ring_size - pi_count) < 2 &&
6772
                  (((pi_count - 2) & 3) == 0 ||
6773
                   ((pi_count + arom_pi_diff - 2) & 3) == 0))
6774
                {
6775
                  /* this ring is aromatic */
6776
                  ringprop[i - 1].arom = true;
6777
                  /* now mark _all_ bonds in the ring as aromatic */
6778
                  a_prev = testring[ring_size - 1];
6779
                  for (j = 0; j < ring_size; j++)
6780
                    {
6781
                      a_ref = testring[j];
6782
                      bond[get_bond (a_prev, a_ref) - 1].arom = true;
6783
                      a_prev = a_ref;
6784
                    }
6785
                }
6786
            }
6787
        }
6788
    }                           /* (for i := 1 to n_rings) */
6789
  FORLIM = n_bonds;
6790
  /* finally, mark all involved atoms as aromatic */
6791
  for (i = 0; i < FORLIM; i++)
6792
    {
6793
      if (bond[i].arom)
6794
        {
6795
          a1 = bond[i].a1;      /* v0.3n */
6796
          a2 = bond[i].a2;      /* v0.3n */
6797
          atom[a1 - 1].arom = true;
6798
          atom[a2 - 1].arom = true;
6799
          /* v0.3n: update atom types if applicable (C and N) */
6800
          if (!strcmp (atom[a1 - 1].element, "C "))
6801
            strcpy (atom[a1 - 1].atype, "CAR");
6802
          if (!strcmp (atom[a2 - 1].element, "C "))
6803
            strcpy (atom[a2 - 1].atype, "CAR");
6804
          if (!strcmp (atom[a1 - 1].element, "N "))
6805
            strcpy (atom[a1 - 1].atype, "NAR");
6806
          if (!strcmp (atom[a2 - 1].element, "N "))
6807
            strcpy (atom[a2 - 1].atype, "NAR");
6808
        }
6809
    }
6810
  FORLIM = n_rings;
6811
  /* update aromaticity information in ringprop */
6812
  /* new in v0.3n: accept rings as aromatic if all bonds are of type 'A' */
6813
  for (i = 0; i < FORLIM; i++)
6814
    {
6815
      memcpy (testring, ring[i], sizeof (ringpath_type));
6816
      /*ring_size := path_length(testring); */
6817
      ring_size = ringprop[i].size;     /* v0.3j */
6818
      aromatic = true;
6819
      aromatic_bt = true;       /* v0.3n */
6820
      a_prev = testring[ring_size - 1];
6821
      for (j = 0; j < ring_size; j++)
6822
        {
6823
          a_ref = testring[j];
6824
          b = get_bond (a_prev, a_ref); /* v0.3n */
6825
          if (!bond[b - 1].arom)
6826
            aromatic = false;
6827
          if (bond[b - 1].btype != 'A') /* v0.3n */
6828
            aromatic_bt = false;
6829
          a_prev = a_ref;
6830
        }
6831
      if (aromatic_bt && !aromatic)
6832
        {                       /* v0.3n: update aromaticity flag */
6833
          a_prev = testring[ring_size - 1];
6834
          for (j = 0; j < ring_size; j++)
6835
            {
6836
              a_ref = testring[j];
6837
              b = get_bond (a_prev, a_ref);
6838
              bond[b - 1].arom = true;
6839
              if (!strcmp (atom[a_ref - 1].element, "C "))
6840
                strcpy (atom[a_ref - 1].atype, "CAR");
6841
              if (!strcmp (atom[a_ref - 1].element, "N "))
6842
                strcpy (atom[a_ref - 1].atype, "NAR");
6843
              a_prev = a_ref;
6844
            }
6845
          aromatic = true;
6846
        }                       /* end v0.3n block   */
6847
      if (aromatic)
6848
        ringprop[i].arom = true;
6849
      else
6850
        ringprop[i].arom = false;
6851
    }
6852
}
6853
 
6854
 
6855
static void
6856
write_mol ()
6857
{
6858
  int i, j;
6859
  ringpath_type testring;
6860
  int ring_size, FORLIM;
6861
 
6862
  /*aromatic : boolean; */
6863
  /*a_prev, a_ref : integer; */
6864
  if (progmode == pmCheckMol)
6865
    printf ("Molecule name: %s\n", molname);
6866
  else
6867
    printf ("Molecule name (haystack): %s\n", molname);
6868
  printf ("atoms: %d  bonds: %d  rings: %d\n", n_atoms, n_bonds, n_rings);
6869
  if (n_atoms < 1)
6870
    return;
6871
  if (n_bonds < 1)
6872
    return;
6873
  FORLIM = n_atoms;
6874
  for (i = 1; i <= FORLIM; i++)
6875
    {
6876
      if (i < 10)
6877
        putchar (' ');
6878
      if (i < 100)
6879
        putchar (' ');
6880
      if (i < 1000)
6881
        putchar (' ');
6882
      printf ("%d %s %s %f %f ",
6883
              i, atom[i - 1].element, atom[i - 1].atype, atom[i - 1].x,
6884
              atom[i - 1].y);
6885
      printf ("%f", atom[i - 1].z);
6886
      printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6887
              atom[i - 1].neighbor_count, atom[i - 1].Hexp, atom[i - 1].Htot);
6888
      if (atom[i - 1].formal_charge != 0)
6786 kbelabas 6889
        printf ("  charge: %d", atom[i - 1].formal_charge);
6785 bpr 6890
      putchar ('\n');
6891
    }
6892
  FORLIM = n_bonds;
6893
  for (i = 1; i <= FORLIM; i++)
6894
    {
6895
      if (i < 10)
6896
        putchar (' ');
6897
      if (i < 100)
6898
        putchar (' ');
6899
      if (i < 1000)
6900
        putchar (' ');
6901
      printf ("%d %d %d %c",
6902
              i, bond[i - 1].a1, bond[i - 1].a2, bond[i - 1].btype);
6903
      if (bond[i - 1].ring_count > 0)
6904
        printf (", contained in %d ring(s)", bond[i - 1].ring_count);
6905
      if (bond[i - 1].arom)
6906
        printf (" (aromatic) ");
6907
      putchar ('\n');
6908
    }
6909
  if (n_rings <= 0)
6910
    return;
6911
  FORLIM = n_rings;
6912
  for (i = 0; i < FORLIM; i++)
6913
    {
6914
      printf ("ring %d: ", i + 1);
6915
      /*aromatic := true; */
6916
      memset (testring, 0, sizeof (ringpath_type));
6917
      ring_size = ringprop[i].size;     /* v0.3j */
6918
      /*for j := 1 to max_ringsize do if ring^[i,j] > 0 then testring[j] := ring^[i,j]; */
6919
      for (j = 0; j < ring_size; j++)   /* v0.3j */
6920
        testring[j] = ring[i][j];
6921
      /*ring_size := path_length(testring); */
6922
      /*a_prev := testring[ring_size]; */
6923
      for (j = 0; j < ring_size; j++)
6924
        {
6925
          printf ("%d ", testring[j]);
6926
          /*a_ref := testring[j]; */
6927
          /*if (not bond^[get_bond(a_prev,a_ref)].arom) then aromatic := false; */
6928
          /*a_prev := a_ref; */
6929
        }
6930
      /*if aromatic then write(' (aromatic)'); */
6931
      if (ringprop[i].arom)
6932
        printf (" (aromatic)");
6933
      if (ringprop[i].envelope)
6934
        printf (" (env)");
6935
      putchar ('\n');
6936
    }
6937
}
6938
 
6939
 
6940
static void
6941
write_needle_mol ()
6942
{
6943
  int i, j;
6944
  ringpath_type testring;
6945
  int ring_size;
6946
  boolean aromatic;
6947
  int a_prev, a_ref, FORLIM;
6948
 
6949
  printf ("Molecule name (needle): %s\n", ndl_molname);
6950
  printf ("atoms: %d  bonds: %d  rings: %d\n",
6951
          ndl_n_atoms, ndl_n_bonds, ndl_n_rings);
6952
  if (ndl_n_atoms < 1)
6953
    return;
6954
  if (ndl_n_bonds < 1)
6955
    return;
6956
  FORLIM = ndl_n_atoms;
6957
  for (i = 1; i <= FORLIM; i++)
6958
    {
6959
      if (i < 10)
6960
        putchar (' ');
6961
      if (i < 100)
6962
        putchar (' ');
6963
      if (i < 1000)
6964
        putchar (' ');
6965
      printf ("%d %s %s %f %f ",
6966
              i, ndl_atom[i - 1].element, ndl_atom[i - 1].atype,
6967
              ndl_atom[i - 1].x, atom[i - 1].y);
6968
      printf ("%f", ndl_atom[i - 1].z);
6969
      printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6970
              ndl_atom[i - 1].neighbor_count, ndl_atom[i - 1].Hexp,
6971
              ndl_atom[i - 1].Htot);
6972
      if (ndl_atom[i - 1].formal_charge != 0)
6973
        printf ("  charge: %d", ndl_atom[i - 1].formal_charge);
6974
      putchar ('\n');
6975
    }
6976
  FORLIM = ndl_n_bonds;
6977
  for (i = 1; i <= FORLIM; i++)
6978
    {
6979
      if (i < 10)
6980
        putchar (' ');
6981
      if (i < 100)
6982
        putchar (' ');
6983
      if (i < 1000)
6984
        putchar (' ');
6985
      printf ("%d %d %d %c",
6986
              i, ndl_bond[i - 1].a1, ndl_bond[i - 1].a2,
6987
              ndl_bond[i - 1].btype);
6988
      if (ndl_bond[i - 1].ring_count > 0)
6989
        printf (", contained in %d ring(s)", ndl_bond[i - 1].ring_count);
6990
      if (ndl_bond[i - 1].arom)
6991
        printf (" (aromatic) ");
6992
      putchar ('\n');
6993
    }
6994
  if (ndl_n_rings <= 0)
6995
    return;
6996
  FORLIM = ndl_n_rings;
6997
  for (i = 0; i < FORLIM; i++)
6998
    {
6999
      aromatic = true;
7000
      memset (testring, 0, sizeof (ringpath_type));
7001
      for (j = 0; j < max_ringsize; j++)
7002
        {
7003
          if (ndl_ring[i][j] > 0)
7004
            testring[j] = ndl_ring[i][j];
7005
        }
7006
      ring_size = path_length (testring);
7007
      printf ("ring %d: ", i + 1);
7008
      a_prev = testring[ring_size - 1];
7009
      for (j = 0; j < ring_size; j++)
7010
        {
7011
          printf ("%d ", testring[j]);
7012
          a_ref = testring[j];
7013
          if (!ndl_bond[get_ndl_bond (a_prev, a_ref) - 1].arom) /* v0.3k */
7014
            aromatic = false;
7015
          a_prev = a_ref;
7016
        }
7017
      if (aromatic)
7018
        printf (" (aromatic)");
7019
      putchar ('\n');
7020
    }
7021
}
7022
 
7023
 
7024
static void
7025
chk_so2_deriv (a_ref)
7026
     int a_ref;
7027
{
7028
  int i;
7029
  neighbor_rec nb;
7030
  str2 nb_el;
7031
  int het_count = 0, o_count = 0, or_count = 0, hal_count = 0, n_count = 0,
7032
    c_count = 0;
7033
  int FORLIM;
7034
 
7035
  memset (nb, 0, sizeof (neighbor_rec));
7036
  if (strcmp (atom[a_ref - 1].atype, "SO2"))
7037
    return;
7038
  get_neighbors (nb, a_ref);
7039
  FORLIM = atom[a_ref - 1].neighbor_count;
7040
  for (i = 0; i < FORLIM; i++)
7041
    {
7042
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7043
        {
7044
          strcpy (nb_el, atom[nb[i] - 1].element);
7045
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7046
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
7047
              && strcmp (nb_el, "LP"))
7048
            /* added 'D ' in v0.3n */
7049
            het_count++;
7050
          if (!strcmp (nb_el, "O "))
7051
            {
7052
              o_count++;
7053
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7054
                or_count++;
7055
            }
7056
          if (!strcmp (nb_el, "N "))
7057
            n_count++;
7058
          if (!strcmp (nb_el, "C "))
7059
            c_count++;
7060
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7061
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7062
              || !strcmp (nb_el, "AT"))
7063
            hal_count++;
7064
        }
7065
    }
7066
  if (het_count == 2)
7067
    {                           /* sulfuric acid derivative */
7068
      fg[fg_sulfuric_acid_deriv - 1] = true;
7069
      if (o_count == 2)
7070
        {
7071
          if (or_count == 0)
7072
            fg[fg_sulfuric_acid - 1] = true;
7073
          if (or_count == 1)
7074
            fg[fg_sulfuric_acid_monoester - 1] = true;
7075
          if (or_count == 2)
7076
            fg[fg_sulfuric_acid_diester - 1] = true;
7077
        }
7078
      if (o_count == 1)
7079
        {
7080
          if (or_count == 1 && n_count == 1)
7081
            fg[fg_sulfuric_acid_amide_ester - 1] = true;
7082
          if (or_count == 0 && n_count == 1)
7083
            fg[fg_sulfuric_acid_amide - 1] = true;
7084
        }
7085
      if (n_count == 2)
7086
        fg[fg_sulfuric_acid_diamide - 1] = true;
7087
      if (hal_count > 0)
7088
        fg[fg_sulfuryl_halide - 1] = true;
7089
    }
7090
  if (het_count == 1 && c_count == 1)
7091
    {                           /* sulfonic acid derivative */
7092
      fg[fg_sulfonic_acid_deriv - 1] = true;
7093
      if (o_count == 1 && or_count == 0)
7094
        fg[fg_sulfonic_acid - 1] = true;
7095
      if (o_count == 1 && or_count == 1)
7096
        fg[fg_sulfonic_acid_ester - 1] = true;
7097
      if (n_count == 1)
7098
        fg[fg_sulfonamide - 1] = true;
7099
      if (hal_count == 1)
7100
        fg[fg_sulfonyl_halide - 1] = true;
7101
    }
7102
  if (het_count == 0 && c_count == 2)   /* sulfone */
7103
    fg[fg_sulfone - 1] = true;
7104
}
7105
 
7106
 
7107
static void
7108
chk_p_deriv (a_ref)
7109
     int a_ref;
7110
{
7111
  int i;
7112
  neighbor_rec nb;
7113
  str2 nb_el, dbl_het;
7114
  int het_count;
7115
  int oh_count = 0, or_count = 0, hal_count = 0, n_count = 0, c_count = 0;
7116
  int FORLIM;
7117
 
7118
  if (strcmp (atom[a_ref - 1].element, "P "))
7119
    return;
7120
  memset (nb, 0, sizeof (neighbor_rec));
7121
  get_neighbors (nb, a_ref);
7122
  *dbl_het = '\0';
7123
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
7124
  FORLIM = atom[a_ref - 1].neighbor_count;
7125
  for (i = 0; i < FORLIM; i++)
7126
    {
7127
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
7128
        strcpy (dbl_het, atom[nb[i] - 1].element);
7129
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7130
        {
7131
          strcpy (nb_el, atom[nb[i] - 1].element);
7132
          if (!strcmp (nb_el, "C "))
7133
            c_count++;
7134
          if (is_hydroxy (a_ref, nb[i]))
7135
            oh_count++;
7136
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7137
            or_count++;
7138
          if (!strcmp (nb_el, "N "))
7139
            n_count++;
7140
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7141
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7142
              || !strcmp (nb_el, "AT"))
7143
            hal_count++;
7144
        }
7145
    }
7146
  het_count = oh_count + or_count + hal_count + n_count;
7147
  if (!strcmp (atom[a_ref - 1].atype, "P3D") ||
7148
      !strcmp (atom[a_ref - 1].atype, "P4 "))
7149
    {
7150
      if (!strcmp (dbl_het, "O "))
7151
        {
7152
          if (c_count == 0)
7153
            {
7154
              fg[fg_phosphoric_acid_deriv - 1] = true;
7155
              if (oh_count == 3)
7156
                fg[fg_phosphoric_acid - 1] = true;
7157
              if (or_count > 0)
7158
                fg[fg_phosphoric_acid_ester - 1] = true;
7159
              if (hal_count > 0)
7160
                fg[fg_phosphoric_acid_halide - 1] = true;
7161
              if (n_count > 0)
7162
                fg[fg_phosphoric_acid_amide - 1] = true;
7163
            }
7164
          if (c_count == 1)
7165
            {
7166
              fg[fg_phosphonic_acid_deriv - 1] = true;
7167
              if (oh_count == 2)
7168
                fg[fg_phosphonic_acid - 1] = true;
7169
              if (or_count > 0)
7170
                fg[fg_phosphonic_acid_ester - 1] = true;
7171
              /*if (hal_count > 0)  then fg[fg_phosphonic_acid_halide] := true;             */
7172
              /*if (n_count > 0)    then fg[fg_phosphonic_acid_amide]  := true; */
7173
            }
7174
          if (c_count == 3)
7175
            fg[fg_phosphinoxide - 1] = true;
7176
        }
7177
      if (!strcmp (dbl_het, "S "))
7178
        {
7179
          if (c_count == 0)
7180
            {
7181
              fg[fg_thiophosphoric_acid_deriv - 1] = true;
7182
              if (oh_count == 3)
7183
                fg[fg_thiophosphoric_acid - 1] = true;
7184
              if (or_count > 0)
7185
                fg[fg_thiophosphoric_acid_ester - 1] = true;
7186
              if (hal_count > 0)
7187
                fg[fg_thiophosphoric_acid_halide - 1] = true;
7188
              if (n_count > 0)
7189
                fg[fg_thiophosphoric_acid_amide - 1] = true;
7190
            }
7191
        }
7192
    }
7193
  /*  if (atom^[a_ref].atype = 'P4 ') then fg[fg_phosphoric_acid_deriv] := true; */
7194
  if (strcmp (atom[a_ref - 1].atype, "P3 "))    /* changed P3D into P3 in v0.3b */
7195
    return;
7196
  if (c_count == 3 && het_count == 0)
7197
    fg[fg_phosphine - 1] = true;
7198
  if (c_count == 3 && oh_count == 1)
7199
    fg[fg_phosphinoxide - 1] = true;
7200
}
7201
 
7202
 
7203
static void
7204
chk_b_deriv (a_ref)
7205
     int a_ref;
7206
{
7207
  int i;
7208
  neighbor_rec nb;
7209
  str2 nb_el;
7210
  int het_count = 0, oh_count = 0, or_count = 0, hal_count = 0, n_count = 0,
7211
    c_count = 0;
7212
  int FORLIM;
7213
 
7214
  if (strcmp (atom[a_ref - 1].element, "B "))
7215
    return;
7216
  memset (nb, 0, sizeof (neighbor_rec));
7217
  get_neighbors (nb, a_ref);
7218
  FORLIM = atom[a_ref - 1].neighbor_count;
7219
  for (i = 0; i < FORLIM; i++)
7220
    {
7221
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7222
        {
7223
          strcpy (nb_el, atom[nb[i] - 1].element);
7224
          if (!strcmp (nb_el, "C "))
7225
            c_count++;
7226
          else if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  &&
7227
                   strcmp (nb_el, "LP"))
7228
            /* v0.3n: D */
7229
            het_count++;
7230
          if (is_hydroxy (a_ref, nb[i]))
7231
            oh_count++;
7232
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7233
            /* fixed in v0.3b */
7234
            or_count++;
7235
          if (!strcmp (nb_el, "N "))
7236
            n_count++;
7237
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7238
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7239
              || !strcmp (nb_el, "AT"))
7240
            hal_count++;
7241
        }
7242
    }
7243
  het_count = oh_count + or_count + hal_count + n_count;
7244
  /* fixed in v0.3b */
7245
  if (c_count != 1 || het_count != 2)
7246
    return;
7247
  fg[fg_boronic_acid_deriv - 1] = true;
7248
  if (oh_count == 2)
7249
    fg[fg_boronic_acid - 1] = true;
7250
  if (or_count > 0)
7251
    fg[fg_boronic_acid_ester - 1] = true;
7252
}
7253
 
7254
 
7255
static void
7256
chk_ammon (a_ref)
7257
     int a_ref;
7258
{
7259
  int i;
7260
  neighbor_rec nb;
7261
  str2 nb_el;
7262
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
7263
  char bt;                      /* v0.3k */
7264
  float bo_sum = 0.0;
7265
  boolean ha;
7266
  int FORLIM;
7267
 
7268
  memset (nb, 0, sizeof (neighbor_rec));
7269
  if (strcmp (atom[a_ref - 1].atype, "N3+")
7270
      && atom[a_ref - 1].formal_charge == 0)
7271
    return;
7272
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
7273
    return;
7274
  get_neighbors (nb, a_ref);
7275
  FORLIM = atom[a_ref - 1].neighbor_count;
7276
  for (i = 0; i < FORLIM; i++)
7277
    {
7278
      bt = bond[get_bond (a_ref, nb[i]) - 1].btype;     /* v0.3k */
7279
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3k */
7280
      ha = atom[nb[i] - 1].heavy;       /* v0.3k */
7281
      if (bt == 'S')
7282
        {
7283
          if (ha)
7284
            bo_sum += 1.0;
7285
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7286
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
7287
            {                   /* added 'D ' in v0.3n */
7288
              het_count++;
7289
              if (!strcmp (nb_el, "O "))
7290
                {
7291
                  o_count++;
7292
                  if (atom[nb[i] - 1].neighbor_count > 1)
7293
                    or_count++;
7294
                }
7295
            }
7296
          if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
7297
              is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
7298
            /* v0.3k */
7299
            r_count++;
7300
        }
7301
      if (bt == 'D')
7302
        {
7303
          if (ha)
7304
            bo_sum += 2.0;
7305
          if (strcmp (nb_el, "C "))
7306
            {
7307
              het_count += 2;
7308
              if (!strcmp (nb_el, "O "))
7309
                o_count += 2;
7310
            }
7311
          if (!strcmp (nb_el, "C "))
7312
            r_count++;
7313
        }
7314
      if (bt == 'A' && ha)
7315
        bo_sum += 1.5;
7316
    }                           /* v0.3k: corrected end of "for ..." loop */
7317
  if (het_count == 0 && r_count == 4)
7318
    fg[fg_quart_ammonium - 1] = true;
7319
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
7320
    return;
7321
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
7322
    fg[fg_n_oxide - 1] = true;  /* finds only aliphatic N-oxides! */
7323
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
7324
      atom[a_ref - 1].arom == true)
7325
    fg[fg_quart_ammonium - 1] = true;
7326
}
7327
 
7328
 
7329
static void
7330
swap_atoms (a1, a2)
7331
     int *a1, *a2;
7332
{
7333
  int a_tmp;
7334
 
7335
  a_tmp = *a1;
7336
  *a1 = *a2;
7337
  *a2 = a_tmp;
7338
}
7339
 
7340
 
7341
static void
7342
orient_bond (a1, a2)
7343
     int *a1, *a2;
7344
{
7345
  str2 a1_el, a2_el;
7346
 
7347
  strcpy (a1_el, atom[*a1 - 1].element);
7348
  strcpy (a2_el, atom[*a2 - 1].element);
7349
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
7350
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
7351
    /* v0.3n: D */
7352
    return;
7353
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
7354
    swap_atoms (a1, a2);
7355
  if (!strcmp (a2_el, a1_el))
7356
    {
7357
      if (hetbond_count (*a1) > hetbond_count (*a2))
7358
        swap_atoms (a1, a2);
7359
    }
7360
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el))
7361
    {
7362
      if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O "))
7363
        {
7364
          if (!strcmp (a1_el, "O "))
7365
            swap_atoms (a1, a2);
7366
        }
7367
    }
7368
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el))
7369
    {
7370
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
7371
          atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
7372
        swap_atoms (a1, a2);
7373
    }
7374
}
7375
 
7376
 
7377
static void
7378
chk_imine (a_ref, a_view)
7379
     int a_ref, a_view;
7380
{
7381
  /* a_ref = C, a_view = N */
7382
  int i;
7383
  neighbor_rec nb;
7384
  str2 nb_el;
6788 kbelabas 7385
  int a_het = 0, a_c;
6785 bpr 7386
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
7387
  int FORLIM;
7388
 
7389
  /* v0.3k */
7390
  if (atom[a_view - 1].neighbor_count == 1)
7391
    {
7392
      if (atom[a_ref - 1].arom == false)
7393
        fg[fg_imine - 1] = true;
7394
      return;
7395
    }
7396
  memset (nb, 0, sizeof (neighbor_rec));
7397
  get_neighbors (nb, a_view);
7398
  if (atom[a_view - 1].neighbor_count <= 1)
7399
    return;
7400
  FORLIM = atom[a_view - 1].neighbor_count;
7401
  for (i = 0; i < FORLIM; i++)
7402
    {
7403
      if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype ==
7404
                               'S'))
7405
        {
7406
          strcpy (nb_el, atom[nb[i] - 1].element);
7407
          if (!strcmp (nb_el, "C "))
7408
            {
7409
              a_c = nb[i];
7410
              c_count++;
7411
            }
7412
          if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N "))
7413
            {
7414
              a_het = nb[i];
7415
              het_count++;
7416
            }
7417
          if ((!strcmp (nb_el, "O ")
7418
               && atom[nb[i] - 1].neighbor_count ==
7419
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
7420
            /* v0.3k */
7421
            o_count++;
7422
        }
7423
      if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype ==
7424
                               'D'))
7425
        {                       /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
7426
          strcpy (nb_el, atom[nb[i] - 1].element);
7427
          if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")
7428
              || !strcmp (nb_el, "S "))
7429
            {
7430
              a_het = nb[i];    /* v0.3m */
7431
              het_count++;
7432
            }
7433
          if ((!strcmp (nb_el, "O ")
7434
               && atom[nb[i] - 1].neighbor_count ==
7435
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
7436
            /* v0.3k */
7437
            o_count++;
7438
        }
7439
    }
7440
  if (c_count == 1)
7441
    {
7442
      if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
7443
           is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
7444
          && atom[a_ref - 1].arom == false && het_count == 0)
7445
        /* v0.3k */
7446
        fg[fg_imine - 1] = true;
7447
    }
7448
  if (het_count == 1)
7449
    {
7450
      strcpy (nb_el, atom[a_het - 1].element);
7451
      if (!strcmp (nb_el, "O "))
7452
        {
7453
          if (is_hydroxy (a_view, a_het))
7454
            fg[fg_oxime - 1] = true;
7455
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
7456
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
7457
            fg[fg_oxime_ether - 1] = true;
7458
        }
7459
      if (!strcmp (nb_el, "N "))
7460
        {
7461
          if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
7462
              is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,
7463
                                                                    a_het) |
7464
              is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
7465
            fg[fg_hydrazone - 1] = true;
7466
          else
7467
            {
7468
              memset (nb, 0, sizeof (neighbor_rec));
7469
              get_neighbors (nb, a_het);
7470
              if (atom[a_het - 1].neighbor_count > 1)
7471
                {
7472
                  FORLIM = atom[a_het - 1].neighbor_count;
7473
                  for (i = 0; i < FORLIM; i++)
7474
                    {
7475
                      if (nb[i] != a_view)
7476
                        {
7477
                          if (is_carbamoyl (a_het, nb[i]))
7478
                            fg[fg_semicarbazone - 1] = true;
7479
                          if (is_thiocarbamoyl (a_het, nb[i]))
7480
                            fg[fg_thiosemicarbazone - 1] = true;
7481
                        }
7482
                    }
7483
                }
7484
            }
7485
        }
7486
    }                           /* v0.3k: nitro groups in "azi" form */
7487
  /* check for semicarbazone or thiosemicarbazone */
7488
  if (het_count == 2 && o_count == 2)
7489
    fg[fg_nitro_compound - 1] = true;
7490
}
7491
 
7492
 
7493
static void
7494
chk_carbonyl_deriv (a_view, a_ref)
7495
     int a_view, a_ref;
7496
{
7497
  /* a_view = C */
7498
  int i;
7499
  neighbor_rec nb;
7500
  str2 nb_el;
7501
  int c_count = 0, cn_count = 0;
7502
  char bt;                      /* new in v0.3b */
7503
  int n_db = 0;                 /* new in v0.3b */
7504
  int FORLIM;
7505
 
7506
  memset (nb, 0, sizeof (neighbor_rec));
7507
  get_neighbors (nb, a_view);
7508
  FORLIM = atom[a_view - 1].neighbor_count;
7509
  /* new in v0.3b */
7510
  for (i = 0; i < FORLIM; i++)
7511
    {
7512
      bt = bond[get_bond (a_view, nb[i]) - 1].btype;
7513
      if (bt == 'S')
7514
        {
7515
          strcpy (nb_el, atom[nb[i] - 1].element);
7516
          if (!strcmp (nb_el, "C "))
7517
            {
7518
              if (is_cyano_c (nb[i]))
7519
                cn_count++;
7520
              else
7521
                c_count++;
7522
            }
7523
        }
7524
      else
7525
        {
7526
          if (bt == 'D')
7527
            n_db++;
7528
        }
7529
    }
7530
  /* new in v0.3b */
7531
  if (is_oxo_C (a_view))
7532
    {
7533
      fg[fg_carbonyl - 1] = true;
7534
      if (c_count + cn_count < 2)
7535
        {                       /* new in v0.3b (detection of ketenes) */
7536
          if (n_db <= 1)
7537
            fg[fg_aldehyde - 1] = true;
7538
          else
7539
            fg[fg_ketene - 1] = true;
7540
        }
7541
      if (c_count == 2)
7542
        {
7543
          if (atom[a_view - 1].arom)
7544
            fg[fg_oxohetarene - 1] = true;
7545
          else
7546
            fg[fg_ketone - 1] = true;
7547
        }
7548
      if (cn_count > 0)
7549
        fg[fg_acyl_cyanide - 1] = true;
7550
    }
7551
  if (is_thioxo_C (a_view))
7552
    {
7553
      fg[fg_thiocarbonyl - 1] = true;
7554
      if (c_count < 2)
7555
        fg[fg_thioaldehyde - 1] = true;
7556
      if (c_count == 2)
7557
        {
7558
          if (atom[a_view - 1].arom)
7559
            fg[fg_thioxohetarene - 1] = true;
7560
          else
7561
            fg[fg_thioketone - 1] = true;
7562
        }
7563
    }
7564
  if (is_imino_C (a_view))
7565
    chk_imine (a_view, a_ref);
7566
}
7567
 
7568
 
7569
static void
7570
chk_carboxyl_deriv (a_view, a_ref)
7571
     int a_view, a_ref;
7572
{
7573
  int i;
7574
  neighbor_rec nb;
7575
  str2 nb_el;
7576
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 7577
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 7578
 
7579
  memset (nb, 0, sizeof (neighbor_rec));
7580
  get_neighbors (nb, a_view);
7581
  FORLIM = atom[a_view - 1].neighbor_count;
7582
  for (i = 0; i < FORLIM; i++)
7583
    {
7584
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
7585
        {
7586
          strcpy (nb_el, atom[nb[i] - 1].element);
7587
          if (strcmp (nb_el, "C "))
7588
            {
7589
              if (!strcmp (nb_el, "O "))
7590
                {
7591
                  o_count++;
7592
                  a_o = nb[i];
7593
                }
7594
              if (!strcmp (nb_el, "N "))
7595
                {
7596
                  n_count++;
7597
                  a_n = nb[i];
7598
                }
7599
              if (!strcmp (nb_el, "S "))
7600
                {
7601
                  s_count++;
7602
                  a_s = nb[i];
7603
                }
7604
            }
7605
        }
7606
    }
7607
  if (is_oxo_C (a_view))
7608
    {
7609
      if (o_count == 1)
7610
        {                       /* anhydride is checked somewhere else */
7611
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7612
            fg[fg_carboxylic_acid_deriv - 1] = true;
7613
          if (is_hydroxy (a_view, a_o))
7614
            {
7615
              if (atom[a_o - 1].formal_charge == 0)
7616
                fg[fg_carboxylic_acid - 1] = true;
7617
              if (atom[a_o - 1].formal_charge == -1)
7618
                fg[fg_carboxylic_acid_salt - 1] = true;
7619
            }
7620
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
7621
              is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o))
7622
            {
7623
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
7624
                fg[fg_carboxylic_acid_ester - 1] = true;
7625
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0)
7626
                {
7627
                  if (bond[get_bond (a_view, a_o) - 1].arom == true)
7628
                    {
7629
                      /*fg[fg_lactone_heteroarom] := true else fg[fg_lactone] := true; */
7630
                      fg[fg_oxohetarene - 1] = true;
7631
                    }
7632
                  else
7633
                    fg[fg_lactone - 1] = true;
7634
                }
7635
            }
7636
        }
7637
      if (n_count == 1)
7638
        {
7639
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7640
            fg[fg_carboxylic_acid_deriv - 1] = true;
7641
          else
7642
            {
7643
              /*fg[fg_lactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
7644
              fg[fg_oxohetarene - 1] = true;
7645
            }
7646
          if (is_amino (a_view, a_n)
7647
              || (!strcmp (atom[a_n - 1].atype, "NAM")
7648
                  && atom[a_n - 1].neighbor_count == 1))
7649
            {
7650
              fg[fg_carboxylic_acid_amide - 1] = true;
7651
              fg[fg_carboxylic_acid_prim_amide - 1] = true;
7652
            }
7653
          /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
7654
          if (is_C_monosubst_amino (a_view, a_n) &
7655
              (!is_subst_acylamino (a_view, a_n)))
7656
            {                   /* v0.3j */
7657
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7658
                fg[fg_carboxylic_acid_amide - 1] = true;
7659
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7660
                fg[fg_carboxylic_acid_sec_amide - 1] = true;
7661
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7662
                {
7663
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7664
                    {
7665
                      /*fg[fg_lactam_heteroarom]    := true else  */
7666
                      fg[fg_oxohetarene - 1] = true;
7667
                    }
7668
                  else
7669
                    fg[fg_lactam - 1] = true;
7670
                }
7671
            }
7672
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
7673
          /*   (is_diarylamino(a_view,a_n)) then  */
7674
          if (is_C_disubst_amino (a_view, a_n) &
7675
              (!is_subst_acylamino (a_view, a_n)))
7676
            {                   /* v0.3j */
7677
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7678
                fg[fg_carboxylic_acid_amide - 1] = true;
7679
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7680
                fg[fg_carboxylic_acid_tert_amide - 1] = true;
7681
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7682
                {
7683
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7684
                    {
7685
                      /*fg[fg_lactam_heteroarom]    := true else  */
7686
                      fg[fg_oxohetarene - 1] = true;
7687
                    }
7688
                  else
7689
                    fg[fg_lactam - 1] = true;
7690
                }
7691
            }
7692
          if (is_hydroxylamino (a_view, a_n))
7693
            fg[fg_hydroxamic_acid - 1] = true;
7694
          if (is_hydrazino (a_view, a_n))
7695
            fg[fg_carboxylic_acid_hydrazide - 1] = true;
7696
          if (is_azido (a_view, a_n))
7697
            fg[fg_carboxylic_acid_azide - 1] = true;
7698
        }
7699
      if (s_count == 1)
7700
        {                       /* anhydride is checked somewhere else */
7701
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7702
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7703
          if (is_sulfanyl (a_view, a_s))
7704
            fg[fg_thiocarboxylic_acid - 1] = true;
7705
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7706
            {
7707
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7708
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7709
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0)
7710
                {
7711
                  if (bond[get_bond (a_view, a_s) - 1].arom == true)
7712
                    {
7713
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7714
                      fg[fg_oxohetarene - 1] = true;
7715
                    }
7716
                  else
7717
                    fg[fg_thiolactone - 1] = true;
7718
                }
7719
            }
7720
        }
7721
    }                           /* end Oxo-C */
7722
  if (is_thioxo_C (a_view))
7723
    {
7724
      /* fg[fg_thiocarboxylic_acid_deriv]  := true; */
7725
      if (o_count == 1)
7726
        {                       /* anhydride is checked somewhere else */
7727
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7728
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7729
          if (is_hydroxy (a_view, a_o))
7730
            fg[fg_thiocarboxylic_acid - 1] = true;      /* fixed in v0.3c */
7731
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o))
7732
            {
7733
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7734
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7735
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0)
7736
                {
7737
                  if (bond[get_bond (a_view, a_o) - 1].arom == true)
7738
                    {
7739
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7740
                      fg[fg_thioxohetarene - 1] = true;
7741
                    }
7742
                  else
7743
                    fg[fg_thiolactone - 1] = true;
7744
                }
7745
            }
7746
        }
7747
      if (n_count == 1)
7748
        {
7749
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7750
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7751
          else
7752
            {
7753
              /*fg[fg_thiolactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
7754
              fg[fg_thioxohetarene - 1] = true;
7755
            }
7756
          /* catches also pyridazines, 1,2,3-triazines, etc. */
7757
          if (is_amino (a_view, a_n))
7758
            {
7759
              fg[fg_thiocarboxylic_acid_amide - 1] = true;
7760
              /* fg[fg_thiocarboxylic_acid_prim_amide] := true; */
7761
            }
7762
          /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
7763
          if (is_C_monosubst_amino (a_view, a_n) &
7764
              (!is_subst_acylamino (a_view, a_n)))
7765
            {                   /* v0.3j */
7766
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7767
                fg[fg_thiocarboxylic_acid_amide - 1] = true;
7768
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := true; */
7769
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7770
                {
7771
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7772
                    {
7773
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
7774
                      fg[fg_thioxohetarene - 1] = true;
7775
                    }
7776
                  else
7777
                    fg[fg_thiolactam - 1] = true;
7778
                }
7779
            }
7780
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
7781
          /*   (is_diarylamino(a_view,a_n)) then  */
7782
          if (is_C_disubst_amino (a_view, a_n) &
7783
              (!is_subst_acylamino (a_view, a_n)))
7784
            {                   /* v0.3j */
7785
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7786
                fg[fg_thiocarboxylic_acid_amide - 1] = true;
7787
              /*fg[fg_thiocarboxylic_acid_tert_amide] := true; */
7788
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7789
                {
7790
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7791
                    {
7792
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
7793
                      fg[fg_thioxohetarene - 1] = true;
7794
                    }
7795
                  else
7796
                    fg[fg_thiolactam - 1] = true;
7797
                }
7798
            }
7799
        }
7800
      if (s_count == 1)
7801
        {                       /* anhydride is checked somewhere else */
7802
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7803
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7804
          if (is_sulfanyl (a_view, a_s))
7805
            fg[fg_thiocarboxylic_acid - 1] = true;
7806
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7807
            {
7808
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7809
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7810
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0)
7811
                {
7812
                  if (bond[get_bond (a_view, a_s) - 1].arom == true)
7813
                    {
7814
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7815
                      fg[fg_thioxohetarene - 1] = true;
7816
                    }
7817
                  else
7818
                    fg[fg_thiolactone - 1] = true;
7819
                }
7820
            }
7821
        }
7822
    }                           /* end Thioxo-C */
7823
  if (is_true_imino_C (a_view))
7824
    {
7825
      if (o_count == 1)
7826
        {
7827
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7828
            fg[fg_carboxylic_acid_deriv - 1] = true;
7829
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o))
7830
            {
7831
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
7832
                fg[fg_imido_ester - 1] = true;
7833
            }
7834
        }
7835
      if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == false))
7836
        {
7837
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7838
            fg[fg_carboxylic_acid_deriv - 1] = true;
7839
          if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7840
            {
7841
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7842
                fg[fg_carboxylic_acid_deriv - 1] = true;
7843
              fg[fg_carboxylic_acid_amidine - 1] = true;
7844
            }
7845
          if (is_hydrazino (a_view, a_n))
7846
            {
7847
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7848
                fg[fg_carboxylic_acid_amidrazone - 1] = true;
7849
            }
7850
        }
7851
      if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == true))
7852
        /* catches also pyridazines, 1,2,3-triazines, etc. */
7853
        fg[fg_iminohetarene - 1] = true;
7854
      if (s_count == 1)
7855
        {
7856
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7857
            fg[fg_carboxylic_acid_deriv - 1] = true;
7858
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7859
            {
7860
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7861
                fg[fg_imido_thioester - 1] = true;
7862
            }
7863
        }
7864
    }
7865
  if (is_hydroximino_C (a_view))
7866
    {
7867
      if (bond[get_bond (a_view, a_n) - 1].arom == false)
7868
        fg[fg_carboxylic_acid_deriv - 1] = true;
7869
      if (o_count == 1)
7870
        {
7871
          if (is_hydroxy (a_view, a_o))
7872
            fg[fg_hydroxamic_acid - 1] = true;
7873
        }
7874
    }
7875
  if (!is_hydrazono_C (a_view))
7876
    return;
7877
  if (bond[get_bond (a_view, a_n) - 1].arom == false)
7878
    fg[fg_carboxylic_acid_deriv - 1] = true;
7879
  if (n_count == 1)
7880
    {
7881
      if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7882
        fg[fg_carboxylic_acid_amidrazone - 1] = true;
7883
    }
7884
}
7885
 
7886
 
7887
static void
7888
chk_co2_sp2 (a_view, a_ref)
7889
     int a_view, a_ref;
7890
{
7891
  int i;
7892
  neighbor_rec nb;
7893
  str2 nb_el;
7894
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
7895
    s_count = 0, sr_count = 0;
7896
  int FORLIM;
7897
 
7898
  memset (nb, 0, sizeof (neighbor_rec));
7899
  get_neighbors (nb, a_view);
7900
  FORLIM = atom[a_view - 1].neighbor_count;
7901
  for (i = 0; i < FORLIM; i++)
7902
    {
7903
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
7904
        {
7905
          strcpy (nb_el, atom[nb[i] - 1].element);
7906
          if (strcmp (nb_el, "C "))
7907
            {
7908
              if (!strcmp (nb_el, "O "))
7909
                {
7910
                  o_count++;
7911
                  if (is_alkoxy (a_view, nb[i]) |
7912
                      is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,
7913
                                                                   nb[i]))
7914
                    /* v0.3j */
7915
                    or_count++;
7916
                }
7917
              if (!strcmp (nb_el, "N "))
7918
                {
7919
                  n_count++;
7920
                  if (is_hydrazino (a_view, nb[i]))
7921
                    nn_count++;
7922
                  if (is_subst_hydrazino (a_view, nb[i]))       /* more general... */
7923
                    nnx_count++;
7924
                }
7925
              if (!strcmp (nb_el, "S "))
7926
                {
7927
                  s_count++;
7928
                  if (is_alkylsulfanyl (a_view, nb[i]) |
7929
                      is_arylsulfanyl (a_view, nb[i]))
7930
                    sr_count++;
7931
                }
7932
            }
7933
        }
7934
    }
7935
  if (is_oxo_C (a_view))
7936
    {
7937
      if (o_count == 2)
7938
        {
7939
          fg[fg_carbonic_acid_deriv - 1] = true;
7940
          if (or_count == 1)
7941
            fg[fg_carbonic_acid_monoester - 1] = true;
7942
          if (or_count == 2)
7943
            fg[fg_carbonic_acid_diester - 1] = true;
7944
        }
7945
      if (o_count == 1 && s_count == 1)
7946
        {
7947
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7948
          if (or_count + sr_count == 1)
7949
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7950
          if (or_count + sr_count == 2)
7951
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7952
        }
7953
      if (s_count == 2)
7954
        {
7955
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7956
          if (sr_count == 1)
7957
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7958
          if (sr_count == 2)
7959
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7960
        }
7961
      if (o_count == 1 && n_count == 1)
7962
        {
7963
          fg[fg_carbamic_acid_deriv - 1] = true;
7964
          if (or_count == 0)
7965
            fg[fg_carbamic_acid - 1] = true;
7966
          if (or_count == 1)
7967
            fg[fg_carbamic_acid_ester - 1] = true;
7968
        }
7969
      if (s_count == 1 && n_count == 1)
7970
        {
7971
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
7972
          if (sr_count == 0)
7973
            fg[fg_thiocarbamic_acid - 1] = true;
7974
          if (sr_count == 1)
7975
            fg[fg_thiocarbamic_acid_ester - 1] = true;
7976
        }
7977
      if (n_count == 2)
7978
        {
7979
          if (nn_count == 1)
7980
            fg[fg_semicarbazide - 1] = true;
7981
          else
7982
            {
7983
              if (nnx_count == 0)       /* excludes semicarbazones */
7984
                fg[fg_urea - 1] = true;
7985
            }
7986
        }
7987
    }                           /* end Oxo-C */
7988
  if (is_thioxo_C (a_view))
7989
    {
7990
      if (o_count == 2)
7991
        {
7992
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7993
          if (or_count == 1)
7994
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7995
          if (or_count == 2)
7996
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7997
        }
7998
      if (o_count == 1 && s_count == 1)
7999
        {
8000
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8001
          if (or_count + sr_count == 1)
8002
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8003
          if (or_count + sr_count == 2)
8004
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8005
        }
8006
      if (s_count == 2)
8007
        {
8008
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8009
          if (sr_count == 1)
8010
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8011
          if (sr_count == 2)
8012
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8013
        }
8014
      if (o_count == 1 && n_count == 1)
8015
        {
8016
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
8017
          if (or_count == 0)
8018
            fg[fg_thiocarbamic_acid - 1] = true;
8019
          if (or_count == 1)
8020
            fg[fg_thiocarbamic_acid_ester - 1] = true;
8021
        }
8022
      if (s_count == 1 && n_count == 1)
8023
        {
8024
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
8025
          if (sr_count == 0)
8026
            fg[fg_thiocarbamic_acid - 1] = true;
8027
          if (sr_count == 1)
8028
            fg[fg_thiocarbamic_acid_ester - 1] = true;
8029
        }
8030
      if (n_count == 2)
8031
        {
8032
          if (nn_count == 1)
8033
            fg[fg_thiosemicarbazide - 1] = true;
8034
          else
8035
            {
8036
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
8037
                fg[fg_thiourea - 1] = true;
8038
            }
8039
        }
8040
    }                           /* end Thioxo-C */
8041
  if (!
8042
      (is_true_imino_C (a_view) &
8043
       (bond[get_bond (a_view, a_ref) - 1].arom == false)))
8044
    {
8045
      return;
8046
    }                           /* end Imino-C */
8047
  if (o_count == 1 && n_count == 1)
8048
    fg[fg_isourea - 1] = true;
8049
  if (s_count == 1 && n_count == 1)
8050
    fg[fg_isothiourea - 1] = true;
8051
  if (n_count == 2)
8052
    fg[fg_guanidine - 1] = true;
8053
}
8054
 
8055
 
8056
static void
8057
chk_co2_sp (a_view, a_ref)
8058
     int a_view, a_ref;
8059
{
8060
  int i;
8061
  neighbor_rec nb;
8062
  str2 nb_el;
8063
  int o_count = 0, n_count = 0, s_count = 0;
8064
  int FORLIM;
8065
 
8066
  memset (nb, 0, sizeof (neighbor_rec));
8067
  get_neighbors (nb, a_view);
8068
  FORLIM = atom[a_view - 1].neighbor_count;
8069
  for (i = 0; i < FORLIM; i++)
8070
    {
8071
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')
8072
        {
8073
          strcpy (nb_el, atom[nb[i] - 1].element);
8074
          if (strcmp (nb_el, "C "))
8075
            {
8076
              if (!strcmp (nb_el, "O "))
8077
                o_count++;
8078
              if (!strcmp (nb_el, "N "))
8079
                n_count++;
8080
              if (!strcmp (nb_el, "S "))
8081
                s_count++;
8082
            }
8083
        }
8084
    }
8085
  if (o_count + s_count == 2)   /* new in v0.3b */
8086
    fg[fg_co2_deriv - 1] = true;
8087
  if (o_count == 1 && n_count == 1)
8088
    fg[fg_isocyanate - 1] = true;
8089
  if (s_count == 1 && n_count == 1)
8090
    fg[fg_isothiocyanate - 1] = true;
8091
  if (n_count == 2)
8092
    fg[fg_carbodiimide - 1] = true;
8093
}
8094
 
8095
 
8096
static void
8097
chk_triple (a1, a2)
8098
     int a1, a2;
8099
{
8100
  str2 a1_el, a2_el;
8101
 
8102
  strcpy (a1_el, atom[a1 - 1].element);
8103
  strcpy (a2_el, atom[a2 - 1].element);
8104
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &
8105
      (bond[get_bond (a1, a2) - 1].arom == false))
8106
    fg[fg_alkyne - 1] = true;
8107
  if (is_nitrile (a1, a2))
8108
    fg[fg_nitrile - 1] = true;
8109
  if (is_isonitrile (a1, a2))
8110
    fg[fg_isonitrile - 1] = true;
8111
  if (is_cyanate (a1, a2))
8112
    fg[fg_cyanate - 1] = true;
8113
  if (is_thiocyanate (a1, a2))
8114
    fg[fg_thiocyanate - 1] = true;
8115
}
8116
 
8117
 
8118
static void
8119
chk_ccx (a_view, a_ref)
8120
     int a_view, a_ref;
8121
{
8122
  int i;
8123
  neighbor_rec nb;
8124
  int oh_count = 0, or_count = 0, n_count = 0;
8125
  int FORLIM;
8126
 
8127
  memset (nb, 0, sizeof (neighbor_rec));
8128
  get_neighbors (nb, a_ref);
8129
  FORLIM = atom[a_ref - 1].neighbor_count;
8130
  for (i = 0; i < FORLIM; i++)
8131
    {
8132
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
8133
        {
8134
          if (is_hydroxy (a_ref, nb[i]))
8135
            oh_count++;
8136
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8137
              is_siloxy (a_ref, nb[i]))
8138
            or_count++;
8139
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8140
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8141
            n_count++;
8142
        }
8143
    }
8144
  if (oh_count == 1)
8145
    fg[fg_enol - 1] = true;
8146
  if (or_count == 1)
8147
    fg[fg_enolether - 1] = true;
8148
  if (n_count == 1)
8149
    fg[fg_enamine - 1] = true;
8150
  /* new in v0.2f   (regard anything else as an alkene) */
8151
  if (oh_count + or_count + n_count == 0)
8152
    fg[fg_alkene - 1] = true;
8153
}
8154
 
8155
 
8156
static void
8157
chk_xccx (a_view, a_ref)
8158
     int a_view, a_ref;
8159
{
8160
  int i;
8161
  neighbor_rec nb;
8162
  int oh_count = 0, or_count = 0, n_count = 0;
8163
  int FORLIM;
8164
 
8165
  memset (nb, 0, sizeof (neighbor_rec));
8166
  get_neighbors (nb, a_view);
8167
  FORLIM = atom[a_view - 1].neighbor_count;
8168
  for (i = 0; i < FORLIM; i++)
8169
    {
8170
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
8171
        {
8172
          if (is_hydroxy (a_view, nb[i]))
8173
            oh_count++;
8174
          if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
8175
              is_siloxy (a_view, nb[i]))
8176
            or_count++;
8177
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8178
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8179
            n_count++;
8180
        }
8181
    }
8182
  memset (nb, 0, sizeof (neighbor_rec));
8183
  get_neighbors (nb, a_ref);
8184
  FORLIM = atom[a_ref - 1].neighbor_count;
8185
  for (i = 0; i < FORLIM; i++)
8186
    {
8187
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
8188
        {
8189
          if (is_hydroxy (a_ref, nb[i]))
8190
            oh_count++;
8191
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8192
              is_siloxy (a_ref, nb[i]))
8193
            or_count++;
8194
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8195
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8196
            n_count++;
8197
        }
8198
    }
8199
  if (oh_count == 2)
8200
    fg[fg_enediol - 1] = true;
8201
  /* new in v0.2f   (regard anything else as an alkene) */
8202
  if (oh_count + or_count + n_count == 0)
8203
    fg[fg_alkene - 1] = true;
8204
}
8205
 
8206
 
8207
static void
8208
chk_n_o_dbl (a1, a2)
8209
     int a1, a2;
8210
{
8211
  int i;
8212
  neighbor_rec nb;
8213
  str2 nb_el;
8214
  int or_count = 0, n_count = 0, c_count = 0;
8215
  int b;                        /* v0.3j */
8216
  int het_count = 0;            /* v0.3k */
8217
  char bt;                      /* v0.3k */
8218
  float bo_sum = 0.0;           /* v0.3k */
8219
  int FORLIM;
8220
 
8221
  memset (nb, 0, sizeof (neighbor_rec));
8222
  get_neighbors (nb, a1);
8223
  FORLIM = atom[a1 - 1].neighbor_count;
8224
  /* v0.3k */
8225
  /* v0.3k */
8226
  for (i = 0; i < FORLIM; i++)
8227
    {
8228
      if (nb[i] != a2)
8229
        {
8230
          b = get_bond (a1, nb[i]);     /* v0.3j */
8231
          strcpy (nb_el, atom[nb[i] - 1].element);
8232
          bt = bond[b - 1].btype;       /* v0.3k */
8233
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
8234
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
8235
              && strcmp (nb_el, "LP") && bond[b - 1].arom == false)
8236
            /* added 'D ' in v0.3n */
8237
            het_count++;
8238
          /* v0.3k: ignore hetero atoms */
8239
          /* in aromatic rings like isoxazole  */
8240
          if (bt == 'S')
8241
            bo_sum += 1.0;
8242
          if (bt == 'D')
8243
            bo_sum += 2.0;
8244
          if (bt == 'A')
8245
            bo_sum += 1.5;
8246
          if (!strcmp (nb_el, "O "))
8247
            or_count++;
8248
          if (!strcmp (nb_el, "N "))
8249
            n_count++;
8250
          if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')        /* v0.3k */
8251
            c_count++;
8252
          /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
8253
        }
8254
    }
8255
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2)
8256
    {                           /* excludes nitro etc. */
8257
      if (or_count == 1)
8258
        fg[fg_nitrite - 1] = true;
8259
      if (c_count == 1)
8260
        fg[fg_nitroso_compound - 1] = true;
8261
      if (n_count == 1)         /* instead of nitrosamine  v0.3j */
8262
        fg[fg_nitroso_compound - 1] = true;
8263
      /*if (n_count = 1) then fg[fg_nitrosamine]   := true;  (* still missing */
8264
    }
8265
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
8266
  /*  begin */
8267
  /*    fg[fg_n_oxide] := true; */
8268
  /*  end; */
8269
  /* new approach in v0.3k */
8270
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
8271
    fg[fg_n_oxide - 1] = true;
8272
}
8273
 
8274
 
8275
static void
8276
chk_sulfoxide (a1, a2)
8277
     int a1, a2;
8278
{
8279
  int i;
8280
  neighbor_rec nb;
8281
  str2 nb_el;
8282
  int o_count = 0, c_count = 0;
8283
  int FORLIM;
8284
 
8285
  memset (nb, 0, sizeof (neighbor_rec));
8286
  get_neighbors (nb, a1);
8287
  FORLIM = atom[a1 - 1].neighbor_count;
8288
  for (i = 0; i < FORLIM; i++)
8289
    {
8290
      strcpy (nb_el, atom[nb[i] - 1].element);
8291
      if (!strcmp (nb_el, "O "))
8292
        o_count++;
8293
      if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
8294
        c_count++;
8295
    }
8296
  if (o_count == 1 && c_count == 2)
8297
    fg[fg_sulfoxide - 1] = true;
8298
}
8299
 
8300
 
8301
static void
8302
chk_double (a1, a2)
8303
     int a1, a2;
8304
{
8305
  str2 a1_el, a2_el;
8306
 
8307
  strcpy (a1_el, atom[a1 - 1].element);
8308
  strcpy (a2_el, atom[a2 - 1].element);
8309
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &
8310
      (bond[get_bond (a1, a2) - 1].arom == false))
8311
    {
8312
      if (hetbond_count (a1) == 2)
8313
        chk_carbonyl_deriv (a1, a2);
8314
      if (hetbond_count (a1) == 3)
8315
        chk_carboxyl_deriv (a1, a2);
8316
      if (hetbond_count (a1) == 4)
8317
        {
8318
          if (!strcmp (atom[a1 - 1].atype, "C2 "))
8319
            chk_co2_sp2 (a1, a2);
8320
          if (!strcmp (atom[a1 - 1].atype, "C1 "))
8321
            chk_co2_sp (a1, a2);
8322
        }
8323
    }                           /* end C=X */
8324
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
8325
       && !strcmp (atom[a2 - 1].atype,
8326
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == false))
8327
    {
8328
      if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
8329
        fg[fg_ketene_acetal_deriv - 1] = true;
8330
      if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
8331
        chk_ccx (a1, a2);
8332
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8333
        chk_xccx (a1, a2);
8334
      if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
8335
          atom[a1 - 1].arom == false && atom[a2 - 1].arom == false)
8336
        fg[fg_alkene - 1] = true;
8337
    }
8338
  if (((!strcmp (a1_el, "N ")
8339
        && !strcmp (a2_el,
8340
                    "N ")) && (hetbond_count (a1) ==
8341
                               2) && (hetbond_count (a2) ==
8342
                                      2) && (bond[get_bond (a1, a2) -
8343
                                                  1].arom == false))
8344
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
8345
    fg[fg_azo_compound - 1] = true;
8346
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
8347
    chk_n_o_dbl (a1, a2);
8348
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
8349
    chk_sulfoxide (a1, a2);
8350
}
8351
 
8352
 
8353
static void
8354
chk_c_hal (a1, a2)
8355
     int a1, a2;
8356
{
8357
  str2 a2_el;
8358
 
8359
  strcpy (a2_el, atom[a2 - 1].element);
8360
  fg[fg_halogen_deriv - 1] = true;
8361
  if (atom[a1 - 1].arom)
8362
    {
8363
      fg[fg_aryl_halide - 1] = true;
8364
      if (!strcmp (a2_el, "F "))
8365
        fg[fg_aryl_fluoride - 1] = true;
8366
      if (!strcmp (a2_el, "CL"))
8367
        fg[fg_aryl_chloride - 1] = true;
8368
      if (!strcmp (a2_el, "BR"))
8369
        fg[fg_aryl_bromide - 1] = true;
8370
      if (!strcmp (a2_el, "I "))
8371
        fg[fg_aryl_iodide - 1] = true;
8372
      return;
8373
    }
8374
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2))
8375
    {                           /* alkyl halides */
8376
      fg[fg_alkyl_halide - 1] = true;
8377
      if (!strcmp (a2_el, "F "))
8378
        fg[fg_alkyl_fluoride - 1] = true;
8379
      if (!strcmp (a2_el, "CL"))
8380
        fg[fg_alkyl_chloride - 1] = true;
8381
      if (!strcmp (a2_el, "BR"))
8382
        fg[fg_alkyl_bromide - 1] = true;
8383
      if (!strcmp (a2_el, "I "))
8384
        fg[fg_alkyl_iodide - 1] = true;
8385
    }
8386
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3))
8387
    {                           /* acyl halides and related compounds */
8388
      if (is_oxo_C (a1))
8389
        {
8390
          fg[fg_acyl_halide - 1] = true;
8391
          if (!strcmp (a2_el, "F "))
8392
            fg[fg_acyl_fluoride - 1] = true;
8393
          if (!strcmp (a2_el, "CL"))
8394
            fg[fg_acyl_chloride - 1] = true;
8395
          if (!strcmp (a2_el, "BR"))
8396
            fg[fg_acyl_bromide - 1] = true;
8397
          if (!strcmp (a2_el, "I "))
8398
            fg[fg_acyl_iodide - 1] = true;
8399
        }
8400
      if (is_thioxo_C (a1))
8401
        fg[fg_thiocarboxylic_acid_deriv - 1] = true;
8402
      if (is_imino_C (a1))
8403
        fg[fg_imidoyl_halide - 1] = true;
8404
    }
8405
  if (!
8406
      ((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
8407
       && (hetbond_count (a1) == 4)))
8408
    /* chloroformates etc. */
8409
    return;
8410
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
8411
  fg[fg_co2_deriv - 1] = true;
8412
  if (is_oxo_C (a1))
8413
    {
8414
      fg[fg_carbonic_acid_deriv - 1] = true;
8415
      if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
8416
        fg[fg_carbonic_acid_ester_halide - 1] = true;
8417
      if (is_carbamoyl (a2, a1))
8418
        {
8419
          fg[fg_carbamic_acid_deriv - 1] = true;
8420
          fg[fg_carbamic_acid_halide - 1] = true;
8421
        }
8422
    }
8423
  if (!is_thioxo_C (a1))
8424
    return;
8425
  fg[fg_thiocarbonic_acid_deriv - 1] = true;
8426
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
8427
    fg[fg_thiocarbonic_acid_ester_halide - 1] = true;
8428
  if (is_thiocarbamoyl (a2, a1))
8429
    {
8430
      fg[fg_thiocarbamic_acid_deriv - 1] = true;
8431
      fg[fg_thiocarbamic_acid_halide - 1] = true;
8432
      /* end of non-aromatic halogen compounds */
8433
    }
8434
}
8435
 
8436
 
8437
static void
8438
chk_c_o (a1, a2)
8439
     int a1, a2;
8440
{
8441
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
8442
  if (bond[get_bond (a1, a2) - 1].arom == true)
8443
    return;
8444
  if (is_true_alkyl (a2, a1) && is_hydroxy (a1, a2))
8445
    {
8446
      fg[fg_hydroxy - 1] = true;
8447
      fg[fg_alcohol - 1] = true;
8448
      if (atom[a1 - 1].neighbor_count <= 2)
8449
        fg[fg_prim_alcohol - 1] = true;
8450
      if (atom[a1 - 1].neighbor_count == 3)
8451
        fg[fg_sec_alcohol - 1] = true;
8452
      if (atom[a1 - 1].neighbor_count == 4)
8453
        fg[fg_tert_alcohol - 1] = true;
8454
    }
8455
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2))
8456
    {
8457
      fg[fg_hydroxy - 1] = true;
8458
      fg[fg_phenol - 1] = true;
8459
    }
8460
  if (is_true_alkyl (a2, a1) && is_true_alkoxy (a1, a2))
8461
    {
8462
      fg[fg_ether - 1] = true;
8463
      fg[fg_dialkylether - 1] = true;
8464
    }
8465
  if ((is_true_alkyl (a2, a1) && is_aryloxy (a1, a2)) |
8466
      (is_aryl (a2, a1) && is_true_alkoxy (a1, a2)))
8467
    {
8468
      fg[fg_ether - 1] = true;
8469
      fg[fg_alkylarylether - 1] = true;
8470
    }
8471
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2))
8472
    {
8473
      fg[fg_ether - 1] = true;
8474
      fg[fg_diarylether - 1] = true;
8475
    }
8476
  if ((is_true_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2))
8477
    {
8478
      fg[fg_ether - 1] = true;
8479
      ether_generic = true;
8480
    }
8481
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2))
8482
    {
8483
      fg[fg_hydroxy - 1] = true;
8484
      hydroxy_generic = true;
8485
    }
8486
 
8487
}
8488
 
8489
 
8490
static void
8491
chk_c_s (a1, a2)
8492
     int a1, a2;
8493
{
8494
  int i;
8495
  neighbor_rec nb;
8496
  str2 nb_el;
8497
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
8498
    hal_count = 0;
8499
  int FORLIM;
8500
 
8501
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
8502
  if (bond[get_bond (a1, a2) - 1].arom == true)
8503
    return;
8504
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2))
8505
    {
8506
      fg[fg_thiol - 1] = true;
8507
      fg[fg_alkylthiol - 1] = true;
8508
    }
8509
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2))
8510
    {
8511
      fg[fg_thiol - 1] = true;
8512
      fg[fg_arylthiol - 1] = true;
8513
    }
8514
  if (is_true_alkyl (a2, a1) && is_true_alkylsulfanyl (a1, a2))
8515
    fg[fg_thioether - 1] = true;
8516
  if ((is_true_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) |
8517
      (is_aryl (a2, a1) && is_true_alkylsulfanyl (a1, a2)))
8518
    fg[fg_thioether - 1] = true;
8519
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
8520
    fg[fg_thioether - 1] = true;
8521
  /* check for sulfinic/sulfenic acid derivatives */
8522
  memset (nb, 0, sizeof (neighbor_rec));
8523
  get_neighbors (nb, a2);
8524
  FORLIM = atom[a2 - 1].neighbor_count;
8525
  for (i = 0; i < FORLIM; i++)
8526
    {
8527
      strcpy (nb_el, atom[nb[i] - 1].element);
8528
      if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
8529
        c_count++;
8530
      if (is_hydroxy (a2, nb[i]))
8531
        oh_count++;
8532
      if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
8533
        or_count++;
8534
      if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
8535
        n_count++;
8536
      if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
8537
          !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
8538
        hal_count++;
8539
      if (!strcmp (nb_el, "O "))
8540
        o_count++;
8541
    }
8542
  if (c_count != 1)
8543
    return;
8544
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1)
8545
    {                           /* sulfinic acid && derivs */
8546
      fg[fg_sulfinic_acid_deriv - 1] = true;
8547
      if (oh_count == 1)
8548
        fg[fg_sulfinic_acid - 1] = true;
8549
      if (or_count == 1)
8550
        fg[fg_sulfinic_acid_ester - 1] = true;
8551
      if (hal_count == 1)
8552
        fg[fg_sulfinic_acid_halide - 1] = true;
8553
      if (n_count == 1)
8554
        fg[fg_sulfinic_acid_amide - 1] = true;
8555
    }
8556
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
8557
    /* sulfenic acid && derivs */
8558
    return;
8559
 
8560
  fg[fg_sulfenic_acid_deriv - 1] = true;
8561
  if (oh_count == 1)
8562
    fg[fg_sulfenic_acid - 1] = true;
8563
  if (or_count == 1)
8564
    fg[fg_sulfenic_acid_ester - 1] = true;
8565
  if (hal_count == 1)
8566
    fg[fg_sulfenic_acid_halide - 1] = true;
8567
  if (n_count == 1)
8568
    fg[fg_sulfenic_acid_amide - 1] = true;
8569
}
8570
 
8571
 
8572
static void
8573
chk_c_n (a1, a2)
8574
     int a1, a2;
8575
{
8576
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
8577
  if (atom[a2 - 1].arom == true)
8578
    return;
8579
  if (is_true_alkyl (a2, a1) && is_amino (a1, a2))
8580
    {
8581
      fg[fg_amine - 1] = true;
8582
      fg[fg_prim_amine - 1] = true;
8583
      fg[fg_prim_aliph_amine - 1] = true;
8584
    }
8585
  if (is_aryl (a2, a1) && is_amino (a1, a2))
8586
    {
8587
      fg[fg_amine - 1] = true;
8588
      fg[fg_prim_amine - 1] = true;
8589
      fg[fg_prim_arom_amine - 1] = true;
8590
    }
8591
  if (is_true_alkyl (a2, a1) && is_true_alkylamino (a1, a2))
8592
    {
8593
      fg[fg_amine - 1] = true;
8594
      fg[fg_sec_amine - 1] = true;
8595
      fg[fg_sec_aliph_amine - 1] = true;
8596
    }
8597
  if (is_aryl (a2, a1) && is_true_alkylamino (a1, a2))
8598
    {
8599
      fg[fg_amine - 1] = true;
8600
      fg[fg_sec_amine - 1] = true;
8601
      fg[fg_sec_mixed_amine - 1] = true;
8602
    }
8603
  if (is_aryl (a2, a1) && is_arylamino (a1, a2))
8604
    {
8605
      fg[fg_amine - 1] = true;
8606
      fg[fg_sec_amine - 1] = true;
8607
      fg[fg_sec_arom_amine - 1] = true;
8608
    }
8609
  if (is_true_alkyl (a2, a1) && is_true_dialkylamino (a1, a2))
8610
    {
8611
      fg[fg_amine - 1] = true;
8612
      fg[fg_tert_amine - 1] = true;
8613
      fg[fg_tert_aliph_amine - 1] = true;
8614
    }
8615
  if ((is_true_alkyl (a2, a1) && is_diarylamino (a1, a2)) |
8616
      (is_aryl (a2, a1) && is_true_dialkylamino (a1, a2)))
8617
    {
8618
      fg[fg_amine - 1] = true;
8619
      fg[fg_tert_amine - 1] = true;
8620
      fg[fg_tert_mixed_amine - 1] = true;
8621
    }
8622
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2))
8623
    {
8624
      fg[fg_amine - 1] = true;
8625
      fg[fg_tert_amine - 1] = true;
8626
      fg[fg_tert_arom_amine - 1] = true;
8627
    }
8628
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8629
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2,
8630
                                                                          a1)
8631
                                                             == false))
8632
    /* v0.3k */
8633
    fg[fg_hydroxylamine - 1] = true;
8634
  /* v0.3k */
8635
  /* v0.3k  */
8636
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) |
8637
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
8638
    fg[fg_hydrazine - 1] = true;
8639
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8640
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
8641
    /* v0.3k */
8642
    fg[fg_azide - 1] = true;
8643
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8644
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
8645
    /* v0.3k */
8646
    fg[fg_diazonium_salt - 1] = true;
8647
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8648
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
8649
    /* v0.3k */
8650
    fg[fg_nitro_compound - 1] = true;
8651
  if (is_alkynyl (a2, a1) &
8652
      (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
8653
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2)))))
8654
    {
8655
      fg[fg_amine - 1] = true;
8656
      amine_generic = true;
8657
    }
8658
}
8659
 
8660
 
8661
static void
8662
chk_c_c (a1, a2)
8663
     int a1, a2;
8664
{
8665
  int i;
8666
  neighbor_rec nb;
8667
  int oh_count, nhr_count, FORLIM;
8668
 
8669
  /* ignore aromatic rings */
8670
  if (atom[a2 - 1].arom == true)
8671
    return;
8672
  /*check for 1,2-diols and 1,2-aminoalcoholes */
8673
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
8674
      && !strcmp (atom[a2 - 1].atype, "C3 "))
8675
    {
8676
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8677
        {
8678
          oh_count = 0;
8679
          nhr_count = 0;
8680
          memset (nb, 0, sizeof (neighbor_rec));
8681
          get_neighbors (nb, a1);
8682
          FORLIM = atom[a1 - 1].neighbor_count;
8683
          for (i = 0; i < FORLIM; i++)
8684
            {
8685
              if (nb[i] != a2)
8686
                {
8687
                  if (is_hydroxy (a1, nb[i]))
8688
                    oh_count++;
8689
                  if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
8690
                      is_arylamino (a1, nb[i]))
8691
                    nhr_count++;
8692
                }
8693
            }
8694
          memset (nb, 0, sizeof (neighbor_rec));
8695
          get_neighbors (nb, a2);
8696
          FORLIM = atom[a2 - 1].neighbor_count;
8697
          for (i = 0; i < FORLIM; i++)
8698
            {
8699
              if (nb[i] != a1)
8700
                {
8701
                  if (is_hydroxy (a2, nb[i]))
8702
                    oh_count++;
8703
                  if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
8704
                      is_arylamino (a2, nb[i]))
8705
                    nhr_count++;
8706
                }
8707
            }
8708
          if (oh_count == 2)
8709
            fg[fg_1_2_diol - 1] = true;
8710
          if (oh_count == 1 && nhr_count == 1)
8711
            fg[fg_1_2_aminoalcohol - 1] = true;
8712
        }
8713
    }
8714
  /* check for alpha-aminoacids and alpha-hydroxyacids */
8715
  if (strcmp (atom[a1 - 1].atype, "C3 ")
8716
      || strcmp (atom[a2 - 1].atype, "C2 "))
8717
    return;
8718
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
8719
    return;
8720
  oh_count = 0;
8721
  nhr_count = 0;
8722
  memset (nb, 0, sizeof (neighbor_rec));
8723
  get_neighbors (nb, a1);
8724
  FORLIM = atom[a1 - 1].neighbor_count;
8725
  for (i = 0; i < FORLIM; i++)
8726
    {
8727
      if (nb[i] != a2)
8728
        {
8729
          if (is_hydroxy (a1, nb[i]))
8730
            oh_count++;
8731
          if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
8732
              is_arylamino (a1, nb[i]))
8733
            nhr_count++;
8734
        }
8735
    }
8736
  memset (nb, 0, sizeof (neighbor_rec));
8737
  get_neighbors (nb, a2);
8738
  FORLIM = atom[a2 - 1].neighbor_count;
8739
  for (i = 0; i < FORLIM; i++)
8740
    {
8741
      if (nb[i] != a1)
8742
        {
8743
          if (is_hydroxy (a2, nb[i]))
8744
            oh_count++;
8745
        }
8746
    }
8747
  if ((oh_count == 2) && is_oxo_C (a2))
8748
    fg[fg_alpha_hydroxyacid - 1] = true;
8749
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
8750
    fg[fg_alpha_aminoacid - 1] = true;
8751
}
8752
 
8753
 
8754
static void
8755
chk_x_y_single (a_view, a_ref)
8756
     int a_view, a_ref;
8757
{
8758
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
8759
      !strcmp (atom[a_ref - 1].atype, "O3 "))
8760
    {
8761
      if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
8762
        fg[fg_hydroperoxide - 1] = true;
8763
      if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
8764
           is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,
8765
                                                     a_ref) |
8766
                                          is_aryloxy (a_view,
8767
                                                      a_ref) |
8768
                                          is_siloxy (a_view, a_ref)))
8769
        fg[fg_peroxide - 1] = true;
8770
    }                           /* still missing: peracid */
8771
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
8772
      !strcmp (atom[a_ref - 1].atype, "S3 "))
8773
    {
8774
      if (atom[a_view - 1].neighbor_count == 2 &&
8775
          atom[a_ref - 1].neighbor_count == 2)
8776
        fg[fg_disulfide - 1] = true;
8777
    }
8778
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
8779
       !strcmp (atom[a_ref - 1].element,
8780
                "N ")) && (hetbond_count (a_view) ==
8781
                           1) && (hetbond_count (a_ref) == 1))
8782
    {
8783
      /*if ((is_amino(a_ref,a_view)) or  */
8784
      /*    (is_subst_amino(a_ref,a_view)) or */
8785
      /*    (is_acylamino(a_ref,a_view))) and */
8786
      /*   ((is_amino(a_view,a_ref)) or  */
8787
      /*    (is_subst_amino(a_view,a_ref)) or */
8788
      /*    (is_acylamino(a_ref,a_view))) then  */
8789
      if (bond[get_bond (a_view, a_ref) - 1].arom == false)
8790
        fg[fg_hydrazine - 1] = true;
8791
    }
8792
  if (!strcmp (atom[a_view - 1].element, "N ") &&
8793
      !strcmp (atom[a_ref - 1].atype, "O3 "))
8794
    {                           /* bond is in "opposite" direction */
8795
      if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &
8796
          is_nitro (a_ref, a_view))
8797
        fg[fg_nitrate - 1] = true;
8798
      if ((is_nitro (a_ref, a_view) == false
8799
           && atom[a_view - 1].arom == false) && (is_amino (a_ref,
8800
                                                            a_view) |
8801
                                                  is_subst_amino (a_ref,
8802
                                                                  a_view)) &
8803
          (is_acylamino (a_ref, a_view) == false))
8804
        fg[fg_hydroxylamine - 1] = true;        /* new in v0.3c */
8805
    }
8806
  if (!strcmp (atom[a_view - 1].element, "S ") &&
8807
      !strcmp (atom[a_ref - 1].element, "O "))
8808
    chk_sulfoxide (a_view, a_ref);
8809
}
8810
 
8811
 
8812
static void
8813
chk_single (a1, a2)
8814
     int a1, a2;
8815
{
8816
  str2 a1_el, a2_el;
8817
 
8818
  strcpy (a1_el, atom[a1 - 1].element);
8819
  strcpy (a2_el, atom[a2 - 1].element);
8820
  if (!strcmp (a1_el, "C ") &&
8821
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
8822
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
8823
    chk_c_hal (a1, a2);
8824
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
8825
    chk_c_o (a1, a2);
8826
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
8827
    chk_c_s (a1, a2);
8828
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
8829
    chk_c_n (a1, a2);
8830
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) ==
8831
                                                            false))
8832
    {
8833
      fg[fg_organometallic - 1] = true;
8834
      if (!strcmp (a2_el, "LI"))
8835
        fg[fg_organolithium - 1] = true;
8836
      if (!strcmp (a2_el, "MG"))
8837
        fg[fg_organomagnesium - 1] = true;
8838
    }
8839
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
8840
    chk_c_c (a1, a2);
8841
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
8842
    chk_x_y_single (a1, a2);
8843
}
8844
 
8845
 
8846
static void
8847
chk_carbonyl_deriv_sp3 (a_ref)
8848
     int a_ref;
8849
{
8850
  int i;
8851
  neighbor_rec nb;
8852
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
8853
  int FORLIM;
8854
 
8855
  memset (nb, 0, sizeof (neighbor_rec));
8856
  get_neighbors (nb, a_ref);
8857
  FORLIM = atom[a_ref - 1].neighbor_count;
8858
  for (i = 0; i < FORLIM; i++)
8859
    {
8860
      if (is_hydroxy (a_ref, nb[i]))
8861
        oh_count++;
8862
      if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8863
          is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
8864
        or_count++;
8865
      if (is_sulfanyl (a_ref, nb[i]))
8866
        sh_count++;
8867
      if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
8868
          is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref,
8869
                                                                   nb[i]))
8870
        sr_count++;
8871
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8872
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
8873
        n_count++;
8874
    }
8875
  if (oh_count == 2)
8876
    fg[fg_carbonyl_hydrate - 1] = true;
8877
  if (oh_count == 1 && or_count == 1)
8878
    fg[fg_hemiacetal - 1] = true;
8879
  if (or_count == 2)
8880
    fg[fg_acetal - 1] = true;
8881
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
8882
    fg[fg_hemiaminal - 1] = true;
8883
  if (n_count == 2)
8884
    fg[fg_aminal - 1] = true;
8885
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
8886
    fg[fg_thiohemiaminal - 1] = true;
8887
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
8888
    fg[fg_thioacetal - 1] = true;
8889
}
8890
 
8891
 
8892
static void
8893
chk_carboxyl_deriv_sp3 (a_ref)
8894
     int a_ref;
8895
{
8896
  int i;
8897
  neighbor_rec nb;
8898
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
8899
  int electroneg_count = 0;     /* new in v0.3j */
8900
  int hal_count = 0;
8901
  str2 nb_el;
8902
  int FORLIM;
8903
 
8904
  memset (nb, 0, sizeof (neighbor_rec));
8905
  get_neighbors (nb, a_ref);
8906
  FORLIM = atom[a_ref - 1].neighbor_count;
8907
  for (i = 0; i < FORLIM; i++)
8908
    {
8909
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3j */
8910
      if (is_electroneg (nb_el))
8911
        electroneg_count++;
8912
      if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
8913
          !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
8914
          || !strcmp (nb_el, "AT"))
8915
        hal_count++;
8916
      if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8917
          is_siloxy (a_ref, nb[i]))
8918
        or_count++;
8919
      if (is_hydroxy (a_ref, nb[i]))    /* new in v0.3c    */
8920
        oh_count++;
8921
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8922
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
8923
        n_count++;
8924
    }
8925
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := true;  (* until v0.3i */
8926
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
8927
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
8928
  if (or_count == 3)
8929
    fg[fg_carboxylic_acid_orthoester - 1] = true;
8930
  if (or_count == 2 && n_count == 1)
8931
    fg[fg_carboxylic_acid_amide_acetal - 1] = true;
8932
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
8933
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
8934
}
8935
 
8936
 
8937
static void
8938
chk_anhydride (a_ref)
8939
     int a_ref;
8940
{
8941
  int i;
8942
  neighbor_rec nb;
8943
  int acyl_count = 0;
8944
  int FORLIM;
8945
 
8946
  memset (nb, 0, sizeof (neighbor_rec));
8947
  get_neighbors (nb, a_ref);
8948
  FORLIM = atom[a_ref - 1].neighbor_count;
8949
  for (i = 0; i < FORLIM; i++)
8950
    {
8951
      if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
8952
        acyl_count++;
8953
    }
8954
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 "))
8955
    {
8956
      fg[fg_carboxylic_acid_deriv - 1] = true;
8957
      fg[fg_carboxylic_acid_anhydride - 1] = true;
8958
    }
8959
}
8960
 
8961
 
8962
static void
8963
chk_imide (a_ref)
8964
     int a_ref;
8965
{
8966
  int i;
8967
  neighbor_rec nb;
8968
  int acyl_count = 0;
8969
  int FORLIM;
8970
 
8971
  memset (nb, 0, sizeof (neighbor_rec));
8972
  get_neighbors (nb, a_ref);
8973
  FORLIM = atom[a_ref - 1].neighbor_count;
8974
  for (i = 0; i < FORLIM; i++)
8975
    {
8976
      if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))    /* v0.3j */
8977
        acyl_count++;
8978
    }
8979
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
8980
    /* v0.3j: accept also N-acyl-imides */
8981
    return;
8982
  fg[fg_carboxylic_acid_deriv - 1] = true;
8983
  fg[fg_carboxylic_acid_imide - 1] = true;
8984
  if (atom[a_ref - 1].neighbor_count == 2)
8985
    fg[fg_carboxylic_acid_unsubst_imide - 1] = true;
8986
  if (atom[a_ref - 1].neighbor_count == 3)
8987
    fg[fg_carboxylic_acid_subst_imide - 1] = true;
8988
}
8989
 
8990
 
8991
static void
8992
chk_12diphenol (a_view, a_ref)
8993
     int a_view, a_ref;
8994
{
8995
  int i;
8996
  neighbor_rec nb;
8997
  int oh_count = 0;
8998
  int FORLIM;
8999
 
9000
  memset (nb, 0, sizeof (neighbor_rec));
9001
  get_neighbors (nb, a_view);
9002
  FORLIM = atom[a_view - 1].neighbor_count;
9003
  for (i = 0; i < FORLIM; i++)
9004
    {
9005
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
9006
        {
9007
          if (is_hydroxy (a_view, nb[i]))
9008
            oh_count++;
9009
        }
9010
    }
9011
  memset (nb, 0, sizeof (neighbor_rec));
9012
  get_neighbors (nb, a_ref);
9013
  FORLIM = atom[a_ref - 1].neighbor_count;
9014
  for (i = 0; i < FORLIM; i++)
9015
    {
9016
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
9017
        {
9018
          if (is_hydroxy (a_ref, nb[i]))
9019
            oh_count++;
9020
        }
9021
    }
9022
  if (oh_count == 2)
9023
    fg[fg_1_2_diphenol - 1] = true;
9024
}
9025
 
9026
 
9027
static void
9028
chk_arom_fg (a1, a2)
9029
     int a1, a2;
9030
{
9031
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
9032
    chk_12diphenol (a1, a2);
9033
}
9034
 
9035
 
9036
static boolean
9037
is_arene (r_id)
9038
     int r_id;
9039
{
9040
  int i, j;
9041
  boolean r = true;
9042
  ringpath_type testring;
9043
  int ring_size, a_prev, a_ref;
9044
 
9045
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
9046
  if (r_id < 1 || r_id > n_rings)
9047
    return false;
9048
  memset (testring, 0, sizeof (ringpath_type));
9049
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9050
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9051
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9052
    testring[j] = ring[r_id - 1][j];
9053
  /*ring_size := path_length(testring); */
9054
  if (ring_size <= 2)
9055
    return false;
9056
  a_prev = testring[ring_size - 1];
9057
  for (i = 0; i < ring_size; i++)
9058
    {
9059
      a_ref = testring[i];
9060
      if (bond[get_bond (a_prev, a_ref) - 1].arom == false)
9061
        r = false;
9062
      a_prev = a_ref;
9063
    }
9064
  return r;
9065
}
9066
 
9067
 
9068
static boolean
9069
is_heterocycle (r_id)
9070
     int r_id;
9071
{
9072
  int i, j;
9073
  boolean r = false;
9074
  ringpath_type testring;
9075
  int ring_size, a_ref;
9076
 
9077
  if (r_id < 1 || r_id > n_rings)
9078
    return false;
9079
  memset (testring, 0, sizeof (ringpath_type));
9080
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9081
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9082
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9083
    testring[j] = ring[r_id - 1][j];
9084
  /*ring_size := path_length(testring); */
9085
  if (ring_size <= 2)
9086
    return false;
9087
  for (i = 0; i < ring_size; i++)
9088
    {
9089
      a_ref = testring[i];
9090
      if (strcmp (atom[a_ref - 1].element, "C "))
9091
        r = true;
9092
    }
9093
  return r;
9094
}
9095
 
9096
 
9097
static void
9098
chk_oxo_thioxo_imino_hetarene (r_id)
9099
     int r_id;
9100
{
9101
  int i, j;
9102
  ringpath_type testring;
9103
  int ring_size, a_ref;
9104
 
9105
  if (r_id < 1 || r_id > n_rings)
9106
    return;
9107
  memset (testring, 0, sizeof (ringpath_type));
9108
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9109
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9110
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9111
    testring[j] = ring[r_id - 1][j];
9112
  /*ring_size := path_length(testring); */
9113
  /*if (is_arene(r_id)) and (odd(ring_size) = false) then */
9114
  if (!is_arene (r_id))         /* v0.3j */
9115
    return;
9116
  for (i = 0; i < ring_size; i++)
9117
    {
9118
      a_ref = testring[i];
9119
      if (is_oxo_C (a_ref))
9120
        fg[fg_oxohetarene - 1] = true;
9121
      if (is_thioxo_C (a_ref))
9122
        fg[fg_thioxohetarene - 1] = true;
9123
      if (is_true_exocyclic_imino_C (a_ref, r_id))      /* v0.3j */
9124
        fg[fg_iminohetarene - 1] = true;
9125
    }
9126
}
9127
 
9128
 
9129
static void
9130
chk_ion (a_ref)
9131
     int a_ref;
9132
{
9133
  int i;
9134
  neighbor_rec nb;
9135
  int charge, FORLIM;
9136
 
9137
  memset (nb, 0, sizeof (neighbor_rec));
9138
  get_neighbors (nb, a_ref);
9139
  charge = atom[a_ref - 1].formal_charge;
9140
  if (charge == 0)
9141
    /* check if charge is neutralized by an adjacent opposite charge */
9142
    return;
9143
  FORLIM = atom[a_ref - 1].neighbor_count;
9144
  for (i = 0; i < FORLIM; i++)
9145
    charge += atom[nb[i] - 1].formal_charge;
9146
  if (charge > 0)
9147
    fg[fg_cation - 1] = true;
9148
  if (charge < 0)
9149
    fg[fg_anion - 1] = true;
9150
}
9151
 
9152
 
9153
static void
9154
chk_functionalgroups ()
9155
{
9156
  int i, a1, a2;
9157
  char bt;
9158
  int pos_chg = 0, neg_chg = 0;
9159
  int FORLIM;
9160
 
9161
  if (n_atoms < 1 || n_bonds < 1)
9162
    return;
9163
  FORLIM = n_atoms;
9164
  for (i = 1; i <= FORLIM; i++)
9165
    {                           /* a few groups are best discovered in the atom list */
9166
      if (!strcmp (atom[i - 1].atype, "SO2"))
9167
        chk_so2_deriv (i);
9168
      /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := true;  (* do another check in the bond list!! */
9169
      if (!strcmp (atom[i - 1].element, "P "))
9170
        chk_p_deriv (i);
9171
      if (!strcmp (atom[i - 1].element, "B "))
9172
        chk_b_deriv (i);
9173
      if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
9174
        chk_ammon (i);
9175
      if ((strcmp (atom[i - 1].atype, "C3 ") == 0)
9176
          && (hetbond_count (i) == 2))
9177
        chk_carbonyl_deriv_sp3 (i);
9178
      if ((strcmp (atom[i - 1].atype, "C3 ") == 0)
9179
          && (hetbond_count (i) == 3))
9180
        chk_carboxyl_deriv_sp3 (i);
9181
      if (!strcmp (atom[i - 1].atype, "O3 ")
9182
          && atom[i - 1].neighbor_count == 2)
9183
        chk_anhydride (i);
9184
      if ((!strcmp (atom[i - 1].atype, "N3 ")
9185
           || !strcmp (atom[i - 1].atype, "NAM"))
9186
          && atom[i - 1].neighbor_count >= 2)
9187
        chk_imide (i);
9188
      if (atom[i - 1].formal_charge > 0)
9189
        pos_chg += atom[i - 1].formal_charge;
9190
      if (atom[i - 1].formal_charge < 0)
9191
        neg_chg += atom[i - 1].formal_charge;
9192
      chk_ion (i);
9193
    }
9194
  FORLIM = n_bonds;
9195
  for (i = 0; i < FORLIM; i++)
9196
    {                           /* most groups are best discovered in the bond list */
9197
      a1 = bond[i].a1;
9198
      a2 = bond[i].a2;
9199
      bt = bond[i].btype;
9200
      if (atom[a1 - 1].heavy && atom[a2 - 1].heavy)
9201
        {
9202
          orient_bond (&a1, &a2);
9203
          if (bt == 'T')
9204
            chk_triple (a1, a2);
9205
          if (bt == 'D')
9206
            chk_double (a1, a2);
9207
          if (bt == 'S')
9208
            chk_single (a1, a2);
9209
          if (bond[i].arom)
9210
            chk_arom_fg (a1, a2);
9211
        }
9212
    }
9213
  if (n_rings > 0)
9214
    {
9215
      FORLIM = n_rings;
9216
      for (i = 1; i <= FORLIM; i++)
9217
        {
9218
          chk_oxo_thioxo_imino_hetarene (i);
9219
          if (is_arene (i))
9220
            fg[fg_aromatic - 1] = true;
9221
          if (is_heterocycle (i))
9222
            fg[fg_heterocycle - 1] = true;
9223
        }
9224
    }
9225
  if (pos_chg + neg_chg > 0)
9226
    fg[fg_cation - 1] = true;
9227
  if (pos_chg + neg_chg < 0)
9228
    fg[fg_anion - 1] = true;
9229
}
9230
 
9231
 
9232
static void
9233
write_fg_text ()
9234
{
9235
  if (fg[fg_cation - 1])
9236
    printf ("cation\n");
9237
  if (fg[fg_anion - 1])
9238
    printf ("anion\n");
9239
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
9240
  if (fg[fg_aldehyde - 1])
9241
    printf ("aldehyde\n");
9242
  if (fg[fg_ketone - 1])
9243
    printf ("ketone\n");
9244
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
9245
  if (fg[fg_thioaldehyde - 1])
9246
    printf ("thioaldehyde\n");
9247
  if (fg[fg_thioketone - 1])
9248
    printf ("thioketone\n");
9249
  if (fg[fg_imine - 1])
9250
    printf ("imine\n");
9251
  if (fg[fg_hydrazone - 1])
9252
    printf ("hydrazone\n");
9253
  if (fg[fg_semicarbazone - 1])
9254
    printf ("semicarbazone\n");
9255
  if (fg[fg_thiosemicarbazone - 1])
9256
    printf ("thiosemicarbazone\n");
9257
  if (fg[fg_oxime - 1])
9258
    printf ("oxime\n");
9259
  if (fg[fg_oxime_ether - 1])
9260
    printf ("oxime ether\n");
9261
  if (fg[fg_ketene - 1])
9262
    printf ("ketene\n");
9263
  if (fg[fg_ketene_acetal_deriv - 1])
9264
    printf ("ketene acetal or derivative\n");
9265
  if (fg[fg_carbonyl_hydrate - 1])
9266
    printf ("carbonyl hydrate\n");
9267
  if (fg[fg_hemiacetal - 1])
9268
    printf ("hemiacetal\n");
9269
  if (fg[fg_acetal - 1])
9270
    printf ("acetal\n");
9271
  if (fg[fg_hemiaminal - 1])
9272
    printf ("hemiaminal\n");
9273
  if (fg[fg_aminal - 1])
9274
    printf ("aminal\n");
9275
  if (fg[fg_thiohemiaminal - 1])
9276
    printf ("hemithioaminal\n");
9277
  if (fg[fg_thioacetal - 1])
9278
    printf ("thioacetal\n");
9279
  if (fg[fg_enamine - 1])
9280
    printf ("enamine\n");
9281
  if (fg[fg_enol - 1])
9282
    printf ("enol\n");
9283
  if (fg[fg_enolether - 1])
9284
    printf ("enol ether\n");
9285
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9286
    printf ("hydroxy compound\n");
9287
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
9288
  if (fg[fg_prim_alcohol - 1])
9289
    printf ("primary alcohol\n");
9290
  if (fg[fg_sec_alcohol - 1])
9291
    printf ("secondary alcohol\n");
9292
  if (fg[fg_tert_alcohol - 1])
9293
    printf ("tertiary alcohol\n");
9294
  if (fg[fg_1_2_diol - 1])
9295
    printf ("1,2-diol\n");
9296
  if (fg[fg_1_2_aminoalcohol - 1])
9297
    printf ("1,2-aminoalcohol\n");
9298
  if (fg[fg_phenol - 1])
9299
    printf ("phenol or hydroxyhetarene\n");
9300
  if (fg[fg_1_2_diphenol - 1])
9301
    printf ("1,2-diphenol\n");
9302
  if (fg[fg_enediol - 1])
9303
    printf ("enediol\n");
9304
  if (fg[fg_ether - 1] && ether_generic)
9305
    printf ("ether\n");
9306
  if (fg[fg_dialkylether - 1])
9307
    printf ("dialkyl ether\n");
9308
  if (fg[fg_alkylarylether - 1])
9309
    printf ("alkyl aryl ether \n");
9310
  if (fg[fg_diarylether - 1])
9311
    printf ("diaryl ether\n");
9312
  if (fg[fg_thioether - 1])
9313
    printf ("thioether\n");
9314
  if (fg[fg_disulfide - 1])
9315
    printf ("disulfide\n");
9316
  if (fg[fg_peroxide - 1])
9317
    printf ("peroxide\n");
9318
  if (fg[fg_hydroperoxide - 1])
9319
    printf ("hydroperoxide \n");
9320
  if (fg[fg_hydrazine - 1])
9321
    printf ("hydrazine derivative\n");
9322
  if (fg[fg_hydroxylamine - 1])
9323
    printf ("hydroxylamine\n");
9324
  if (fg[fg_amine - 1] && amine_generic)
9325
    printf ("amine\n");
9326
  if (fg[fg_prim_amine - 1])
9327
    printf ("primary amine\n");
9328
  if (fg[fg_prim_aliph_amine - 1])
9329
    printf ("primary aliphatic amine (alkylamine)\n");
9330
  if (fg[fg_prim_arom_amine - 1])
9331
    printf ("primary aromatic amine\n");
9332
  if (fg[fg_sec_amine - 1])
9333
    printf ("secondary amine\n");
9334
  if (fg[fg_sec_aliph_amine - 1])
9335
    printf ("secondary aliphatic amine (dialkylamine)\n");
9336
  if (fg[fg_sec_mixed_amine - 1])
9337
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
9338
  if (fg[fg_sec_arom_amine - 1])
9339
    printf ("secondary aromatic amine (diarylamine)\n");
9340
  if (fg[fg_tert_amine - 1])
9341
    printf ("tertiary amine\n");
9342
  if (fg[fg_tert_aliph_amine - 1])
9343
    printf ("tertiary aliphatic amine (trialkylamine)\n");
9344
  if (fg[fg_tert_mixed_amine - 1])
9345
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
9346
  if (fg[fg_tert_arom_amine - 1])
9347
    printf ("tertiary aromatic amine (triarylamine)\n");
9348
  if (fg[fg_quart_ammonium - 1])
9349
    printf ("quaternary ammonium salt\n");
9350
  if (fg[fg_n_oxide - 1])
9351
    printf ("N-oxide\n");
9352
  /* new in v0.2f */
9353
  if (fg[fg_halogen_deriv - 1])
9354
    {
9355
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
9356
          !fg[fg_acyl_halide - 1])
9357
        printf ("halogen derivative\n");
9358
    }
9359
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
9360
  if (fg[fg_alkyl_fluoride - 1])
9361
    printf ("alkyl fluoride\n");
9362
  if (fg[fg_alkyl_chloride - 1])
9363
    printf ("alkyl chloride\n");
9364
  if (fg[fg_alkyl_bromide - 1])
9365
    printf ("alkyl bromide\n");
9366
  if (fg[fg_alkyl_iodide - 1])
9367
    printf ("alkyl iodide\n");
9368
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
9369
  if (fg[fg_aryl_fluoride - 1])
9370
    printf ("aryl fluoride\n");
9371
  if (fg[fg_aryl_chloride - 1])
9372
    printf ("aryl chloride\n");
9373
  if (fg[fg_aryl_bromide - 1])
9374
    printf ("aryl bromide\n");
9375
  if (fg[fg_aryl_iodide - 1])
9376
    printf ("aryl iodide\n");
9377
  if (fg[fg_organometallic - 1])
9378
    printf ("organometallic compound\n");
9379
  if (fg[fg_organolithium - 1])
9380
    printf ("organolithium compound\n");
9381
  if (fg[fg_organomagnesium - 1])
9382
    printf ("organomagnesium compound\n");
9383
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
9384
  if (fg[fg_carboxylic_acid - 1])
9385
    printf ("carboxylic acid\n");
9386
  if (fg[fg_carboxylic_acid_salt - 1])
9387
    printf ("carboxylic acid salt\n");
9388
  if (fg[fg_carboxylic_acid_ester - 1])
9389
    printf ("carboxylic acid ester\n");
9390
  if (fg[fg_lactone - 1])
9391
    printf ("lactone\n");
9392
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
9393
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9394
    printf ("primary carboxylic acid amide\n");
9395
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9396
    printf ("secondary carboxylic acid amide\n");
9397
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9398
    printf ("tertiary carboxylic acid amide\n");
9399
  if (fg[fg_lactam - 1])
9400
    printf ("lactam\n");
9401
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9402
    printf ("carboxylic acid hydrazide\n");
9403
  if (fg[fg_carboxylic_acid_azide - 1])
9404
    printf ("carboxylic acid azide\n");
9405
  if (fg[fg_hydroxamic_acid - 1])
9406
    printf ("hydroxamic acid\n");
9407
  if (fg[fg_carboxylic_acid_amidine - 1])
9408
    printf ("carboxylic acid amidine\n");
9409
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9410
    printf ("carboxylic acid amidrazone\n");
9411
  if (fg[fg_nitrile - 1])
9412
    printf ("carbonitrile\n");
9413
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
9414
  if (fg[fg_acyl_fluoride - 1])
9415
    printf ("acyl fluoride\n");
9416
  if (fg[fg_acyl_chloride - 1])
9417
    printf ("acyl chloride\n");
9418
  if (fg[fg_acyl_bromide - 1])
9419
    printf ("acyl bromide\n");
9420
  if (fg[fg_acyl_iodide - 1])
9421
    printf ("acyl iodide\n");
9422
  if (fg[fg_acyl_cyanide - 1])
9423
    printf ("acyl cyanide\n");
9424
  if (fg[fg_imido_ester - 1])
9425
    printf ("imido ester\n");
9426
  if (fg[fg_imidoyl_halide - 1])
9427
    printf ("imidoyl halide\n");
9428
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
9429
  if (fg[fg_thiocarboxylic_acid - 1])
9430
    printf ("thiocarboxylic acid\n");
9431
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9432
    printf ("thiocarboxylic acid ester\n");
9433
  if (fg[fg_thiolactone - 1])
9434
    printf ("thiolactone\n");
9435
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9436
    printf ("thiocarboxylic acid amide\n");
9437
  if (fg[fg_thiolactam - 1])
9438
    printf ("thiolactam\n");
9439
  if (fg[fg_imido_thioester - 1])
9440
    printf ("imidothioester\n");
9441
  if (fg[fg_oxohetarene - 1])
9442
    printf ("oxo(het)arene\n");
9443
  if (fg[fg_thioxohetarene - 1])
9444
    printf ("thioxo(het)arene\n");
9445
  if (fg[fg_iminohetarene - 1])
9446
    printf ("imino(het)arene\n");
9447
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9448
    printf ("orthocarboxylic acid derivative\n");
9449
  if (fg[fg_carboxylic_acid_orthoester - 1])
9450
    printf ("orthoester\n");
9451
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9452
    printf ("amide acetal\n");
9453
  if (fg[fg_carboxylic_acid_anhydride - 1])
9454
    printf ("carboxylic acid anhydride\n");
9455
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
9456
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9457
    printf ("carboxylic acid imide, N-unsubstituted\n");
9458
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9459
    printf ("carboxylic acid imide, N-substituted\n");
9460
  if (fg[fg_co2_deriv - 1])
9461
    printf ("CO2 derivative (general)\n");
9462
  if (fg[fg_carbonic_acid_deriv - 1] &&
9463
      !(fg[fg_carbonic_acid_monoester - 1]
9464
        || fg[fg_carbonic_acid_diester - 1]
9465
        || fg[fg_carbonic_acid_ester_halide - 1]))
9466
    /* changed in v0.3c */
9467
    printf ("carbonic acid derivative\n");
9468
  if (fg[fg_carbonic_acid_monoester - 1])
9469
    printf ("carbonic acid monoester\n");
9470
  if (fg[fg_carbonic_acid_diester - 1])
9471
    printf ("carbonic acid diester\n");
9472
  if (fg[fg_carbonic_acid_ester_halide - 1])
9473
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
9474
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9475
    printf ("thiocarbonic acid derivative\n");
9476
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9477
    printf ("thiocarbonic acid monoester\n");
9478
  if (fg[fg_thiocarbonic_acid_diester - 1])
9479
    printf ("thiocarbonic acid diester\n");
9480
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9481
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
9482
  if (fg[fg_carbamic_acid_deriv - 1]
9483
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
9484
           || fg[fg_carbamic_acid_halide - 1]))
9485
    /* changed in v0.3c */
9486
    printf ("carbamic acid derivative\n");
9487
  if (fg[fg_carbamic_acid - 1])
9488
    printf ("carbamic acid\n");
9489
  if (fg[fg_carbamic_acid_ester - 1])
9490
    printf ("carbamic acid ester (urethane)\n");
9491
  if (fg[fg_carbamic_acid_halide - 1])
9492
    printf ("carbamic acid halide (haloformic acid amide)\n");
9493
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
9494
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
9495
        || fg[fg_thiocarbamic_acid_halide - 1]))
9496
    /* changed in v0.3c */
9497
    printf ("thiocarbamic acid derivative\n");
9498
  if (fg[fg_thiocarbamic_acid - 1])
9499
    printf ("thiocarbamic acid\n");
9500
  if (fg[fg_thiocarbamic_acid_ester - 1])
9501
    printf ("thiocarbamic acid ester\n");
9502
  if (fg[fg_thiocarbamic_acid_halide - 1])
9503
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
9504
  if (fg[fg_urea - 1])
9505
    printf ("urea\n");
9506
  if (fg[fg_isourea - 1])
9507
    printf ("isourea\n");
9508
  if (fg[fg_thiourea - 1])
9509
    printf ("thiourea\n");
9510
  if (fg[fg_isothiourea - 1])
9511
    printf ("isothiourea\n");
9512
  if (fg[fg_guanidine - 1])
9513
    printf ("guanidine\n");
9514
  if (fg[fg_semicarbazide - 1])
9515
    printf ("semicarbazide\n");
9516
  if (fg[fg_thiosemicarbazide - 1])
9517
    printf ("thiosemicarbazide\n");
9518
  if (fg[fg_azide - 1])
9519
    printf ("azide\n");
9520
  if (fg[fg_azo_compound - 1])
9521
    printf ("azo compound\n");
9522
  if (fg[fg_diazonium_salt - 1])
9523
    printf ("diazonium salt\n");
9524
  if (fg[fg_isonitrile - 1])
9525
    printf ("isonitrile\n");
9526
  if (fg[fg_cyanate - 1])
9527
    printf ("cyanate\n");
9528
  if (fg[fg_isocyanate - 1])
9529
    printf ("isocyanate\n");
9530
  if (fg[fg_thiocyanate - 1])
9531
    printf ("thiocyanate\n");
9532
  if (fg[fg_isothiocyanate - 1])
9533
    printf ("isothiocyanate\n");
9534
  if (fg[fg_carbodiimide - 1])
9535
    printf ("carbodiimide\n");
9536
  if (fg[fg_nitroso_compound - 1])
9537
    printf ("nitroso compound\n");
9538
  if (fg[fg_nitro_compound - 1])
9539
    printf ("nitro compound\n");
9540
  if (fg[fg_nitrite - 1])
9541
    printf ("nitrite\n");
9542
  if (fg[fg_nitrate - 1])
9543
    printf ("nitrate\n");
9544
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
9545
  if (fg[fg_sulfuric_acid - 1])
9546
    printf ("sulfuric acid\n");
9547
  if (fg[fg_sulfuric_acid_monoester - 1])
9548
    printf ("sulfuric acid monoester\n");
9549
  if (fg[fg_sulfuric_acid_diester - 1])
9550
    printf ("sulfuric acid diester\n");
9551
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9552
    printf ("sulfuric acid amide ester\n");
9553
  if (fg[fg_sulfuric_acid_amide - 1])
9554
    printf ("sulfuric acid amide\n");
9555
  if (fg[fg_sulfuric_acid_diamide - 1])
9556
    printf ("sulfuric acid diamide\n");
9557
  if (fg[fg_sulfuryl_halide - 1])
9558
    printf ("sulfuryl halide\n");
9559
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
9560
  if (fg[fg_sulfonic_acid - 1])
9561
    printf ("sulfonic acid\n");
9562
  if (fg[fg_sulfonic_acid_ester - 1])
9563
    printf ("sulfonic acid ester\n");
9564
  if (fg[fg_sulfonamide - 1])
9565
    printf ("sulfonamide\n");
9566
  if (fg[fg_sulfonyl_halide - 1])
9567
    printf ("sulfonyl halide\n");
9568
  if (fg[fg_sulfone - 1])
9569
    printf ("sulfone\n");
9570
  if (fg[fg_sulfoxide - 1])
9571
    printf ("sulfoxide\n");
9572
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
9573
  if (fg[fg_sulfinic_acid - 1])
9574
    printf ("sulfinic acid\n");
9575
  if (fg[fg_sulfinic_acid_ester - 1])
9576
    printf ("sulfinic acid ester\n");
9577
  if (fg[fg_sulfinic_acid_halide - 1])
9578
    printf ("sulfinic acid halide\n");
9579
  if (fg[fg_sulfinic_acid_amide - 1])
9580
    printf ("sulfinic acid amide\n");
9581
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
9582
  if (fg[fg_sulfenic_acid - 1])
9583
    printf ("sulfenic acid\n");
9584
  if (fg[fg_sulfenic_acid_ester - 1])
9585
    printf ("sulfenic acid ester\n");
9586
  if (fg[fg_sulfenic_acid_halide - 1])
9587
    printf ("sulfenic acid halide\n");
9588
  if (fg[fg_sulfenic_acid_amide - 1])
9589
    printf ("sulfenic acid amide\n");
9590
  if (fg[fg_thiol - 1])
9591
    printf ("thiol (sulfanyl compound)\n");
9592
  if (fg[fg_alkylthiol - 1])
9593
    printf ("alkylthiol\n");
9594
  if (fg[fg_arylthiol - 1])
9595
    printf ("arylthiol\n");
9596
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
9597
  if (fg[fg_phosphoric_acid - 1])
9598
    printf ("phosphoric acid\n");
9599
  if (fg[fg_phosphoric_acid_ester - 1])
9600
    printf ("phosphoric acid ester\n");
9601
  if (fg[fg_phosphoric_acid_halide - 1])
9602
    printf ("phosphoric acid halide\n");
9603
  if (fg[fg_phosphoric_acid_amide - 1])
9604
    printf ("phosphoric acid amide\n");
9605
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
9606
  if (fg[fg_thiophosphoric_acid - 1])
9607
    printf ("thiophosphoric acid\n");
9608
  if (fg[fg_thiophosphoric_acid_ester - 1])
9609
    printf ("thiophosphoric acid ester\n");
9610
  if (fg[fg_thiophosphoric_acid_halide - 1])
9611
    printf ("thiophosphoric acid halide\n");
9612
  if (fg[fg_thiophosphoric_acid_amide - 1])
9613
    printf ("thiophosphoric acid amide\n");
9614
  if (fg[fg_phosphonic_acid_deriv - 1])
9615
    printf ("phosphonic acid derivative \n");
9616
  if (fg[fg_phosphonic_acid - 1])
9617
    printf ("phosphonic acid\n");
9618
  if (fg[fg_phosphonic_acid_ester - 1])
9619
    printf ("phosphonic acid ester\n");
9620
  if (fg[fg_phosphine - 1])
9621
    printf ("phosphine\n");
9622
  if (fg[fg_phosphinoxide - 1])
9623
    printf ("phosphine oxide\n");
9624
  if (fg[fg_boronic_acid_deriv - 1])
9625
    printf ("boronic acid derivative\n");
9626
  if (fg[fg_boronic_acid - 1])
9627
    printf ("boronic acid\n");
9628
  if (fg[fg_boronic_acid_ester - 1])
9629
    printf ("boronic acid ester\n");
9630
  if (fg[fg_alkene - 1])
9631
    printf ("alkene\n");
9632
  if (fg[fg_alkyne - 1])
9633
    printf ("alkyne\n");
9634
  if (fg[fg_aromatic - 1])
9635
    printf ("aromatic compound\n");
9636
  if (fg[fg_heterocycle - 1])
9637
    printf ("heterocyclic compound\n");
9638
  if (fg[fg_alpha_aminoacid - 1])
9639
    printf ("alpha-aminoacid\n");
9640
  if (fg[fg_alpha_hydroxyacid - 1])
9641
    printf ("alpha-hydroxyacid\n");
9642
}
9643
 
9644
 
9645
static void
9646
write_fg_text_de ()
9647
{
9648
  if (fg[fg_cation - 1])
9649
    printf ("Kation\n");
9650
  if (fg[fg_anion - 1])
9651
    printf ("Anion\n");
9652
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
9653
  if (fg[fg_aldehyde - 1])
9654
    printf ("Aldehyd\n");
9655
  if (fg[fg_ketone - 1])
9656
    printf ("Keton\n");
9657
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
9658
  if (fg[fg_thioaldehyde - 1])
9659
    printf ("Thioaldehyd\n");
9660
  if (fg[fg_thioketone - 1])
9661
    printf ("Thioketon\n");
9662
  if (fg[fg_imine - 1])
9663
    printf ("Imin\n");
9664
  if (fg[fg_hydrazone - 1])
9665
    printf ("Hydrazon\n");
9666
  if (fg[fg_semicarbazone - 1])
9667
    printf ("Semicarbazon\n");
9668
  if (fg[fg_thiosemicarbazone - 1])
9669
    printf ("Thiosemicarbazon\n");
9670
  if (fg[fg_oxime - 1])
9671
    printf ("Oxim\n");
9672
  if (fg[fg_oxime_ether - 1])
9673
    printf ("Oximether\n");
9674
  if (fg[fg_ketene - 1])
9675
    printf ("Keten\n");
9676
  if (fg[fg_ketene_acetal_deriv - 1])
9677
    printf ("Keten-Acetal oder Derivat\n");
9678
  if (fg[fg_carbonyl_hydrate - 1])
9679
    printf ("Carbonyl-Hydrat\n");
9680
  if (fg[fg_hemiacetal - 1])
9681
    printf ("Halbacetal\n");
9682
  if (fg[fg_acetal - 1])
9683
    printf ("Acetal\n");
9684
  if (fg[fg_hemiaminal - 1])
9685
    printf ("Halbaminal\n");
9686
  if (fg[fg_aminal - 1])
9687
    printf ("Aminal\n");
9688
  if (fg[fg_thiohemiaminal - 1])
9689
    printf ("Thiohalbaminal\n");
9690
  if (fg[fg_thioacetal - 1])
9691
    printf ("Thioacetal\n");
9692
  if (fg[fg_enamine - 1])
9693
    printf ("Enamin\n");
9694
  if (fg[fg_enol - 1])
9695
    printf ("Enol\n");
9696
  if (fg[fg_enolether - 1])
9697
    printf ("Enolether\n");
9698
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9699
    printf ("Hydroxy-Verbindung\n");
9700
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
9701
  if (fg[fg_prim_alcohol - 1])
9702
    printf ("prim\344rer Alkohol\n");
9703
/* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
9704
  if (fg[fg_sec_alcohol - 1])
9705
    printf ("sekund\344rer Alkohol\n");
9706
/* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
9707
  if (fg[fg_tert_alcohol - 1])
9708
    printf ("terti\344rer Alkohol\n");
9709
/* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
9710
  if (fg[fg_1_2_diol - 1])
9711
    printf ("1,2-Diol\n");
9712
  if (fg[fg_1_2_aminoalcohol - 1])
9713
    printf ("1,2-Aminoalkohol\n");
9714
  if (fg[fg_phenol - 1])
9715
    printf ("Phenol oder Hydroxyhetaren\n");
9716
  if (fg[fg_1_2_diphenol - 1])
9717
    printf ("1,2-Diphenol\n");
9718
  if (fg[fg_enediol - 1])
9719
    printf ("Endiol\n");
9720
  if (fg[fg_ether - 1] && ether_generic)
9721
    printf ("Ether\n");
9722
  if (fg[fg_dialkylether - 1])
9723
    printf ("Dialkylether\n");
9724
  if (fg[fg_alkylarylether - 1])
9725
    printf ("Alkylarylether \n");
9726
  if (fg[fg_diarylether - 1])
9727
    printf ("Diarylether\n");
9728
  if (fg[fg_thioether - 1])
9729
    printf ("Thioether\n");
9730
  if (fg[fg_disulfide - 1])
9731
    printf ("Disulfid\n");
9732
  if (fg[fg_peroxide - 1])
9733
    printf ("Peroxid\n");
9734
  if (fg[fg_hydroperoxide - 1])
9735
    printf ("Hydroperoxid\n");
9736
  if (fg[fg_hydrazine - 1])
9737
    printf ("Hydrazin-Derivat\n");
9738
  if (fg[fg_hydroxylamine - 1])
9739
    printf ("Hydroxylamin\n");
9740
  if (fg[fg_amine - 1] && amine_generic)
9741
    printf ("Amin\n");
9742
  if (fg[fg_prim_amine - 1])
9743
    printf ("prim\344res Amin\n");
9744
/* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
9745
  if (fg[fg_prim_aliph_amine - 1])
9746
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
9747
/* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
9748
  if (fg[fg_prim_arom_amine - 1])
9749
    printf ("prim\344res aromatisches Amin\n");
9750
/* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
9751
  if (fg[fg_sec_amine - 1])
9752
    printf ("sekund\344res Amin\n");
9753
/* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
9754
  if (fg[fg_sec_aliph_amine - 1])
9755
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
9756
/* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
9757
  if (fg[fg_sec_mixed_amine - 1])
9758
    printf
9759
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
9760
/* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
9761
  if (fg[fg_sec_arom_amine - 1])
9762
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
9763
/* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
9764
  if (fg[fg_tert_amine - 1])
9765
    printf ("terti\344res Amin\n");
9766
/* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
9767
  if (fg[fg_tert_aliph_amine - 1])
9768
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
9769
/* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
9770
  if (fg[fg_tert_mixed_amine - 1])
9771
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
9772
/* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
9773
  if (fg[fg_tert_arom_amine - 1])
9774
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
9775
/* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
9776
  if (fg[fg_quart_ammonium - 1])
9777
    printf ("quart\344res Ammoniumsalz\n");
9778
/* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
9779
  if (fg[fg_n_oxide - 1])
9780
    printf ("N-Oxid\n");
9781
  /* new in v0.2f */
9782
  if (fg[fg_halogen_deriv - 1])
9783
    {
9784
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
9785
          !fg[fg_acyl_halide - 1])
9786
        printf ("Halogenverbindung\n");
9787
    }
9788
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
9789
  if (fg[fg_alkyl_fluoride - 1])
9790
    printf ("Alkylfluorid\n");
9791
  if (fg[fg_alkyl_chloride - 1])
9792
    printf ("Alkylchlorid\n");
9793
  if (fg[fg_alkyl_bromide - 1])
9794
    printf ("Alkylbromid\n");
9795
  if (fg[fg_alkyl_iodide - 1])
9796
    printf ("Alkyliodid\n");
9797
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
9798
  if (fg[fg_aryl_fluoride - 1])
9799
    printf ("Arylfluorid\n");
9800
  if (fg[fg_aryl_chloride - 1])
9801
    printf ("Arylchlorid\n");
9802
  if (fg[fg_aryl_bromide - 1])
9803
    printf ("Arylbromid\n");
9804
  if (fg[fg_aryl_iodide - 1])
9805
    printf ("Aryliodid\n");
9806
  if (fg[fg_organometallic - 1])
9807
    printf ("Organometall-Verbindung\n");
9808
  if (fg[fg_organolithium - 1])
9809
    printf ("Organolithium-Verbindung\n");
9810
  if (fg[fg_organomagnesium - 1])
9811
    printf ("Organomagnesium-Verbindung\n");
9812
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
9813
  if (fg[fg_carboxylic_acid - 1])
9814
    printf ("Carbons\344ure\n");
9815
/* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
9816
  if (fg[fg_carboxylic_acid_salt - 1])
9817
    printf ("Carbons\344uresalz\n");
9818
/* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
9819
  if (fg[fg_carboxylic_acid_ester - 1])
9820
    printf ("Carbons\344ureester\n");
9821
/* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
9822
  if (fg[fg_lactone - 1])
9823
    printf ("Lacton\n");
9824
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
9825
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9826
    printf ("prim\344res Carbons\344ureamid\n");
9827
/* p2c: checkmol.pas, line 7340:
9828
 * Note: characters >= 128 encountered [281] */
9829
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9830
    printf ("sekund\344res Carbons\344ureamid\n");
9831
/* p2c: checkmol.pas, line 7341:
9832
 * Note: characters >= 128 encountered [281] */
9833
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9834
    printf ("terti\344res Carbons\344ureamid\n");
9835
/* p2c: checkmol.pas, line 7342:
9836
 * Note: characters >= 128 encountered [281] */
9837
  if (fg[fg_lactam - 1])
9838
    printf ("Lactam\n");
9839
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9840
    printf ("Carbons\344urehydrazid\n");
9841
/* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
9842
  if (fg[fg_carboxylic_acid_azide - 1])
9843
    printf ("Carbons\344ureazid\n");
9844
/* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
9845
  if (fg[fg_hydroxamic_acid - 1])
9846
    printf ("Hydroxams\344ure\n");
9847
/* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
9848
  if (fg[fg_carboxylic_acid_amidine - 1])
9849
    printf ("Carbons\344ureamidin\n");
9850
/* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
9851
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9852
    printf ("Carbons\344ureamidrazon\n");
9853
/* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
9854
  if (fg[fg_nitrile - 1])
9855
    printf ("Carbonitril\n");
9856
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
9857
  if (fg[fg_acyl_fluoride - 1])
9858
    printf ("Acylfluorid\n");
9859
  if (fg[fg_acyl_chloride - 1])
9860
    printf ("Acylchlorid\n");
9861
  if (fg[fg_acyl_bromide - 1])
9862
    printf ("Acylbromid\n");
9863
  if (fg[fg_acyl_iodide - 1])
9864
    printf ("Acyliodid\n");
9865
  if (fg[fg_acyl_cyanide - 1])
9866
    printf ("Acylcyanid\n");
9867
  if (fg[fg_imido_ester - 1])
9868
    printf ("Imidoester\n");
9869
  if (fg[fg_imidoyl_halide - 1])
9870
    printf ("Imidoylhalogenid\n");
9871
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
9872
  if (fg[fg_thiocarboxylic_acid - 1])
9873
    printf ("Thiocarbons\344ure\n");
9874
/* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
9875
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9876
    printf ("Thiocarbons\344ureester\n");
9877
/* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
9878
  if (fg[fg_thiolactone - 1])
9879
    printf ("Thiolacton\n");
9880
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9881
    printf ("Thiocarbons\344ureamid\n");
9882
/* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
9883
  if (fg[fg_thiolactam - 1])
9884
    printf ("Thiolactam\n");
9885
  if (fg[fg_imido_thioester - 1])
9886
    printf ("Imidothioester\n");
9887
  if (fg[fg_oxohetarene - 1])
9888
    printf ("Oxo(het)aren\n");
9889
  if (fg[fg_thioxohetarene - 1])
9890
    printf ("Thioxo(het)aren\n");
9891
  if (fg[fg_iminohetarene - 1])
9892
    printf ("Imino(het)aren\n");
9893
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9894
    printf ("Orthocarbons\344ure-Derivat\n");
9895
/* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
9896
  if (fg[fg_carboxylic_acid_orthoester - 1])
9897
    printf ("Orthoester\n");
9898
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9899
    printf ("Amidacetal\n");
9900
  if (fg[fg_carboxylic_acid_anhydride - 1])
9901
    printf ("Carbons\344ureanhydrid\n");
9902
/* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
9903
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
9904
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9905
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
9906
/* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
9907
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9908
    printf ("Carbons\344ureimid, N-substituiert\n");
9909
/* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
9910
  if (fg[fg_co2_deriv - 1])
9911
    printf ("CO2-Derivat (allgemein)\n");
9912
  if (fg[fg_carbonic_acid_deriv - 1] &&
9913
      !(fg[fg_carbonic_acid_monoester - 1]
9914
        || fg[fg_carbonic_acid_diester - 1]
9915
        || fg[fg_carbonic_acid_ester_halide - 1]))
9916
    /* changed in v0.3c */
9917
    printf ("Kohlens\344ure-Derivat\n");
9918
/* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
9919
  if (fg[fg_carbonic_acid_monoester - 1])
9920
    printf ("Kohlens\344uremonoester\n");
9921
/* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
9922
  if (fg[fg_carbonic_acid_diester - 1])
9923
    printf ("Kohlens\344urediester\n");
9924
/* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
9925
  if (fg[fg_carbonic_acid_ester_halide - 1])
9926
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
9927
/* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
9928
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9929
    printf ("Thiokohlens\344ure-Derivat\n");
9930
/* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
9931
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9932
    printf ("Thiokohlens\344uremonoester\n");
9933
/* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
9934
  if (fg[fg_thiocarbonic_acid_diester - 1])
9935
    printf ("Thiokohlens\344urediester\n");
9936
/* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
9937
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9938
    printf
9939
      ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
9940
/* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
9941
  if (fg[fg_carbamic_acid_deriv - 1] &&
9942
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
9943
        fg[fg_carbamic_acid_halide - 1]))
9944
    /* changed in v0.3c */
9945
    printf ("Carbamins\344ure-Derivat\n");
9946
/* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
9947
  if (fg[fg_carbamic_acid - 1])
9948
    printf ("Carbamins\344ure\n");
9949
/* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
9950
  if (fg[fg_carbamic_acid_ester - 1])
9951
    printf ("Carbamins\344ureester (Urethan)\n");
9952
/* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
9953
  if (fg[fg_carbamic_acid_halide - 1])
9954
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
9955
/* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
9956
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
9957
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
9958
        || fg[fg_thiocarbamic_acid_halide - 1]))
9959
    /* changed in v0.3c */
9960
    printf ("Thiocarbamins\344ure-Derivat\n");
9961
/* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
9962
  if (fg[fg_thiocarbamic_acid - 1])
9963
    printf ("Thiocarbamins\344ure\n");
9964
/* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
9965
  if (fg[fg_thiocarbamic_acid_ester - 1])
9966
    printf ("Thiocarbamins\344ureester\n");
9967
/* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
9968
  if (fg[fg_thiocarbamic_acid_halide - 1])
9969
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
9970
/* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
9971
  if (fg[fg_urea - 1])
9972
    printf ("Harnstoff\n");
9973
  if (fg[fg_isourea - 1])
9974
    printf ("Isoharnstoff\n");
9975
  if (fg[fg_thiourea - 1])
9976
    printf ("Thioharnstoff\n");
9977
  if (fg[fg_isothiourea - 1])
9978
    printf ("Isothioharnstoff\n");
9979
  if (fg[fg_guanidine - 1])
9980
    printf ("Guanidin\n");
9981
  if (fg[fg_semicarbazide - 1])
9982
    printf ("Semicarbazid\n");
9983
  if (fg[fg_thiosemicarbazide - 1])
9984
    printf ("Thiosemicarbazid\n");
9985
  if (fg[fg_azide - 1])
9986
    printf ("Azid\n");
9987
  if (fg[fg_azo_compound - 1])
9988
    printf ("Azoverbindung\n");
9989
  if (fg[fg_diazonium_salt - 1])
9990
    printf ("Diazoniumsalz\n");
9991
  if (fg[fg_isonitrile - 1])
9992
    printf ("Isonitril\n");
9993
  if (fg[fg_cyanate - 1])
9994
    printf ("Cyanat\n");
9995
  if (fg[fg_isocyanate - 1])
9996
    printf ("Isocyanat\n");
9997
  if (fg[fg_thiocyanate - 1])
9998
    printf ("Thiocyanat\n");
9999
  if (fg[fg_isothiocyanate - 1])
10000
    printf ("Isothiocyanat\n");
10001
  if (fg[fg_carbodiimide - 1])
10002
    printf ("Carbodiimid\n");
10003
  if (fg[fg_nitroso_compound - 1])
10004
    printf ("Nitroso-Verbindung\n");
10005
  if (fg[fg_nitro_compound - 1])
10006
    printf ("Nitro-Verbindung\n");
10007
  if (fg[fg_nitrite - 1])
10008
    printf ("Nitrit\n");
10009
  if (fg[fg_nitrate - 1])
10010
    printf ("Nitrat\n");
10011
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
10012
  if (fg[fg_sulfuric_acid - 1])
10013
    printf ("Schwefels\344ure\n");
10014
/* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
10015
  if (fg[fg_sulfuric_acid_monoester - 1])
10016
    printf ("Schwefels\344uremonoester\n");
10017
/* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
10018
  if (fg[fg_sulfuric_acid_diester - 1])
10019
    printf ("Schwefels\344urediester\n");
10020
/* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
10021
  if (fg[fg_sulfuric_acid_amide_ester - 1])
10022
    printf ("Schwefels\344ureamidester\n");
10023
/* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
10024
  if (fg[fg_sulfuric_acid_amide - 1])
10025
    printf ("Schwefels\344ureamid\n");
10026
/* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
10027
  if (fg[fg_sulfuric_acid_diamide - 1])
10028
    printf ("Schwefels\344urediamid\n");
10029
/* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
10030
  if (fg[fg_sulfuryl_halide - 1])
10031
    printf ("Sulfurylhalogenid\n");
10032
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
10033
  if (fg[fg_sulfonic_acid - 1])
10034
    printf ("Sulfons\344ure\n");
10035
/* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
10036
  if (fg[fg_sulfonic_acid_ester - 1])
10037
    printf ("Sulfons\344ureester\n");
10038
/* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
10039
  if (fg[fg_sulfonamide - 1])
10040
    printf ("Sulfonamid\n");
10041
  if (fg[fg_sulfonyl_halide - 1])
10042
    printf ("Sulfonylhalogenid\n");
10043
  if (fg[fg_sulfone - 1])
10044
    printf ("Sulfon\n");
10045
  if (fg[fg_sulfoxide - 1])
10046
    printf ("Sulfoxid\n");
10047
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
10048
  if (fg[fg_sulfinic_acid - 1])
10049
    printf ("Sulfins\344ure\n");
10050
/* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
10051
  if (fg[fg_sulfinic_acid_ester - 1])
10052
    printf ("Sulfins\344ureester\n");
10053
/* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
10054
  if (fg[fg_sulfinic_acid_halide - 1])
10055
    printf ("Sulfins\344urehalogenid\n");
10056
/* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
10057
  if (fg[fg_sulfinic_acid_amide - 1])
10058
    printf ("Sulfins\344ureamid\n");
10059
/* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
10060
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
10061
  if (fg[fg_sulfenic_acid - 1])
10062
    printf ("Sulfens\344ure\n");
10063
/* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
10064
  if (fg[fg_sulfenic_acid_ester - 1])
10065
    printf ("Sulfens\344ureester\n");
10066
/* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
10067
  if (fg[fg_sulfenic_acid_halide - 1])
10068
    printf ("Sulfens\344urehalogenid\n");
10069
/* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
10070
  if (fg[fg_sulfenic_acid_amide - 1])
10071
    printf ("Sulfens\344ureamid\n");
10072
/* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
10073
  if (fg[fg_thiol - 1])
10074
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
10075
  if (fg[fg_alkylthiol - 1])
10076
    printf ("Alkylthiol\n");
10077
  if (fg[fg_arylthiol - 1])
10078
    printf ("Arylthiol\n");
10079
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
10080
  if (fg[fg_phosphoric_acid - 1])
10081
    printf ("Phosphors\344ure\n");
10082
/* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
10083
  if (fg[fg_phosphoric_acid_ester - 1])
10084
    printf ("Phosphors\344ureester\n");
10085
/* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
10086
  if (fg[fg_phosphoric_acid_halide - 1])
10087
    printf ("Phosphors\344urehalogenid\n");
10088
/* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
10089
  if (fg[fg_phosphoric_acid_amide - 1])
10090
    printf ("Phosphors\344ureamid\n");
10091
/* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
10092
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
10093
  if (fg[fg_thiophosphoric_acid - 1])
10094
    printf ("Thiophosphors\344ure\n");
10095
/* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
10096
  if (fg[fg_thiophosphoric_acid_ester - 1])
10097
    printf ("Thiophosphors\344ureester\n");
10098
/* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
10099
  if (fg[fg_thiophosphoric_acid_halide - 1])
10100
    printf ("Thiophosphors\344urehalogenid\n");
10101
/* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
10102
  if (fg[fg_thiophosphoric_acid_amide - 1])
10103
    printf ("Thiophosphors\344ureamid\n");
10104
/* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
10105
  if (fg[fg_phosphonic_acid_deriv - 1])
10106
    printf ("Phosphons\344ure-Derivat \n");
10107
/* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
10108
  if (fg[fg_phosphonic_acid - 1])
10109
    printf ("Phosphons\344ure\n");
10110
/* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
10111
  if (fg[fg_phosphonic_acid_ester - 1])
10112
    printf ("Phosphons\344ureester\n");
10113
/* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
10114
  if (fg[fg_phosphine - 1])
10115
    printf ("Phosphin\n");
10116
  if (fg[fg_phosphinoxide - 1])
10117
    printf ("Phosphinoxid\n");
10118
  if (fg[fg_boronic_acid_deriv - 1])
10119
    printf ("Borons\344ure-Derivat\n");
10120
/* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
10121
  if (fg[fg_boronic_acid - 1])
10122
    printf ("Borons\344ure\n");
10123
/* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
10124
  if (fg[fg_boronic_acid_ester - 1])
10125
    printf ("Borons\344ureester\n");
10126
/* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
10127
  if (fg[fg_alkene - 1])
10128
    printf ("Alken\n");
10129
  if (fg[fg_alkyne - 1])
10130
    printf ("Alkin\n");
10131
  if (fg[fg_aromatic - 1])
10132
    printf ("aromatische Verbindung\n");
10133
  if (fg[fg_heterocycle - 1])
10134
    printf ("heterocyclische Verbindung\n");
10135
  if (fg[fg_alpha_aminoacid - 1])
10136
    printf ("alpha-Aminos\344ure\n");
10137
/* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
10138
  if (fg[fg_alpha_hydroxyacid - 1])
10139
    printf ("alpha-Hydroxys\344ure\n");
10140
/* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
10141
}
10142
 
10143
 
10144
#define sc              ';'
10145
 
10146
 
10147
static void
10148
write_fg_code ()
10149
{
10150
  if (fg[fg_cation - 1])
10151
    printf ("000000T2%c", sc);
10152
  if (fg[fg_anion - 1])
10153
    printf ("000000T1%c", sc);
10154
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
10155
  if (fg[fg_aldehyde - 1])
10156
    printf ("C2O1H000%c", sc);
10157
  if (fg[fg_ketone - 1])
10158
    printf ("C2O1C000%c", sc);
10159
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
10160
  if (fg[fg_thioaldehyde - 1])
10161
    printf ("C2S1H000%c", sc);
10162
  if (fg[fg_thioketone - 1])
10163
    printf ("C2S1C000%c", sc);
10164
  if (fg[fg_imine - 1])
10165
    printf ("C2N10000%c", sc);
10166
  if (fg[fg_hydrazone - 1])
10167
    printf ("C2N1N000%c", sc);
10168
  if (fg[fg_semicarbazone - 1])
10169
    printf ("C2NNC4ON%c", sc);
10170
  if (fg[fg_thiosemicarbazone - 1])
10171
    printf ("C2NNC4SN%c", sc);
10172
  if (fg[fg_oxime - 1])
10173
    printf ("C2N1OH00%c", sc);
10174
  if (fg[fg_oxime_ether - 1])
10175
    printf ("C2N1OC00%c", sc);
10176
  if (fg[fg_ketene - 1])
10177
    printf ("C3OC0000%c", sc);
10178
  if (fg[fg_ketene_acetal_deriv - 1])
10179
    printf ("C3OCC000%c", sc);
10180
  if (fg[fg_carbonyl_hydrate - 1])
10181
    printf ("C2O2H200%c", sc);
10182
  if (fg[fg_hemiacetal - 1])
10183
    printf ("C2O2HC00%c", sc);
10184
  if (fg[fg_acetal - 1])
10185
    printf ("C2O2CC00%c", sc);
10186
  if (fg[fg_hemiaminal - 1])
10187
    printf ("C2NOHC10%c", sc);
10188
  if (fg[fg_aminal - 1])
10189
    printf ("C2N2CC10%c", sc);
10190
  if (fg[fg_thiohemiaminal - 1])
10191
    printf ("C2NSHC10%c", sc);
10192
  if (fg[fg_thioacetal - 1])
10193
    printf ("C2S2CC00%c", sc);
10194
  if (fg[fg_enamine - 1])
10195
    printf ("C2CNH000%c", sc);
10196
  if (fg[fg_enol - 1])
10197
    printf ("C2COH000%c", sc);
10198
  if (fg[fg_enolether - 1])
10199
    printf ("C2COC000%c", sc);
10200
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
10201
    printf ("O1H00000%c", sc);
10202
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
10203
  if (fg[fg_prim_alcohol - 1])
10204
    printf ("O1H1C000%c", sc);
10205
  if (fg[fg_sec_alcohol - 1])
10206
    printf ("O1H2C000%c", sc);
10207
  if (fg[fg_tert_alcohol - 1])
10208
    printf ("O1H3C000%c", sc);
10209
  if (fg[fg_1_2_diol - 1])
10210
    printf ("O1H0CO1H%c", sc);
10211
  if (fg[fg_1_2_aminoalcohol - 1])
10212
    printf ("O1H0CN1C%c", sc);
10213
  if (fg[fg_phenol - 1])
10214
    printf ("O1H1A000%c", sc);
10215
  if (fg[fg_1_2_diphenol - 1])
10216
    printf ("O1H2A000%c", sc);
10217
  if (fg[fg_enediol - 1])
10218
    printf ("C2COH200%c", sc);
10219
  if (fg[fg_ether - 1] && ether_generic)
10220
    printf ("O1C00000%c", sc);
10221
  if (fg[fg_dialkylether - 1])
10222
    printf ("O1C0CC00%c", sc);
10223
  if (fg[fg_alkylarylether - 1])
10224
    printf ("O1C0CA00%c", sc);
10225
  if (fg[fg_diarylether - 1])
10226
    printf ("O1C0AA00%c", sc);
10227
  if (fg[fg_thioether - 1])
10228
    printf ("S1C00000%c", sc);
10229
  if (fg[fg_disulfide - 1])
10230
    printf ("S1S1C000%c", sc);
10231
  if (fg[fg_peroxide - 1])
10232
    printf ("O1O1C000%c", sc);
10233
  if (fg[fg_hydroperoxide - 1])
10234
    printf ("O1O1H000%c", sc);
10235
  if (fg[fg_hydrazine - 1])
10236
    printf ("N1N10000%c", sc);
10237
  if (fg[fg_hydroxylamine - 1])
10238
    printf ("N1O1H000%c", sc);
10239
  if (fg[fg_amine - 1] && amine_generic)
10240
    printf ("N1C00000%c", sc);
10241
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
10242
  if (fg[fg_prim_aliph_amine - 1])
10243
    printf ("N1C1C000%c", sc);
10244
  if (fg[fg_prim_arom_amine - 1])
10245
    printf ("N1C1A000%c", sc);
10246
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
10247
  if (fg[fg_sec_aliph_amine - 1])
10248
    printf ("N1C2CC00%c", sc);
10249
  if (fg[fg_sec_mixed_amine - 1])
10250
    printf ("N1C2AC00%c", sc);
10251
  if (fg[fg_sec_arom_amine - 1])
10252
    printf ("N1C2AA00%c", sc);
10253
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
10254
  if (fg[fg_tert_aliph_amine - 1])
10255
    printf ("N1C3CC00%c", sc);
10256
  if (fg[fg_tert_mixed_amine - 1])
10257
    printf ("N1C3AC00%c", sc);
10258
  if (fg[fg_tert_arom_amine - 1])
10259
    printf ("N1C3AA00%c", sc);
10260
  if (fg[fg_quart_ammonium - 1])
10261
    printf ("N1C400T2%c", sc);
10262
  if (fg[fg_n_oxide - 1])
10263
    printf ("N0O10000%c", sc);
10264
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
10265
  /* new in v0.2f */
10266
  if (fg[fg_halogen_deriv - 1])
10267
    {
10268
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
10269
          !fg[fg_acyl_halide - 1])
10270
        printf ("XX000000%c", sc);
10271
    }
10272
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
10273
  if (fg[fg_alkyl_fluoride - 1])
10274
    printf ("XF00C000%c", sc);
10275
  if (fg[fg_alkyl_chloride - 1])
10276
    printf ("XC00C000%c", sc);
10277
  if (fg[fg_alkyl_bromide - 1])
10278
    printf ("XB00C000%c", sc);
10279
  if (fg[fg_alkyl_iodide - 1])
10280
    printf ("XI00C000%c", sc);
10281
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
10282
  if (fg[fg_aryl_fluoride - 1])
10283
    printf ("XF00A000%c", sc);
10284
  if (fg[fg_aryl_chloride - 1])
10285
    printf ("XC00A000%c", sc);
10286
  if (fg[fg_aryl_bromide - 1])
10287
    printf ("XB00A000%c", sc);
10288
  if (fg[fg_aryl_iodide - 1])
10289
    printf ("XI00A000%c", sc);
10290
  if (fg[fg_organometallic - 1])
10291
    printf ("000000MX%c", sc);
10292
  if (fg[fg_organolithium - 1])
10293
    printf ("000000ML%c", sc);
10294
  if (fg[fg_organomagnesium - 1])
10295
    printf ("000000MM%c", sc);
10296
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
10297
  if (fg[fg_carboxylic_acid - 1])
10298
    printf ("C3O2H000%c", sc);
10299
  if (fg[fg_carboxylic_acid_salt - 1])
10300
    printf ("C3O200T1%c", sc);
10301
  if (fg[fg_carboxylic_acid_ester - 1])
10302
    printf ("C3O2C000%c", sc);
10303
  if (fg[fg_lactone - 1])
10304
    printf ("C3O2CZ00%c", sc);
10305
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
10306
  if (fg[fg_carboxylic_acid_prim_amide - 1])
10307
    printf ("C3ONC100%c", sc);
10308
  if (fg[fg_carboxylic_acid_sec_amide - 1])
10309
    printf ("C3ONC200%c", sc);
10310
  if (fg[fg_carboxylic_acid_tert_amide - 1])
10311
    printf ("C3ONC300%c", sc);
10312
  if (fg[fg_lactam - 1])
10313
    printf ("C3ONCZ00%c", sc);
10314
  if (fg[fg_carboxylic_acid_hydrazide - 1])
10315
    printf ("C3ONN100%c", sc);
10316
  if (fg[fg_carboxylic_acid_azide - 1])
10317
    printf ("C3ONN200%c", sc);
10318
  if (fg[fg_hydroxamic_acid - 1])
10319
    printf ("C3ONOH00%c", sc);
10320
  if (fg[fg_carboxylic_acid_amidine - 1])
10321
    printf ("C3N2H000%c", sc);
10322
  if (fg[fg_carboxylic_acid_amidrazone - 1])
10323
    printf ("C3NNN100%c", sc);
10324
  if (fg[fg_nitrile - 1])
10325
    printf ("C3N00000%c", sc);
10326
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
10327
  if (fg[fg_acyl_fluoride - 1])
10328
    printf ("C3OXF000%c", sc);
10329
  if (fg[fg_acyl_chloride - 1])
10330
    printf ("C3OXC000%c", sc);
10331
  if (fg[fg_acyl_bromide - 1])
10332
    printf ("C3OXB000%c", sc);
10333
  if (fg[fg_acyl_iodide - 1])
10334
    printf ("C3OXI000%c", sc);
10335
  if (fg[fg_acyl_cyanide - 1])
10336
    printf ("C2OC3N00%c", sc);
10337
  if (fg[fg_imido_ester - 1])
10338
    printf ("C3NOC000%c", sc);
10339
  if (fg[fg_imidoyl_halide - 1])
10340
    printf ("C3NXX000%c", sc);
10341
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
10342
  if (fg[fg_thiocarboxylic_acid - 1])
10343
    printf ("C3SOH000%c", sc);
10344
  if (fg[fg_thiocarboxylic_acid_ester - 1])
10345
    printf ("C3SOC000%c", sc);
10346
  if (fg[fg_thiolactone - 1])
10347
    printf ("C3SOCZ00%c", sc);
10348
  if (fg[fg_thiocarboxylic_acid_amide - 1])
10349
    printf ("C3SNH000%c", sc);
10350
  if (fg[fg_thiolactam - 1])
10351
    printf ("C3SNCZ00%c", sc);
10352
  if (fg[fg_imido_thioester - 1])
10353
    printf ("C3NSC000%c", sc);
10354
  if (fg[fg_oxohetarene - 1])
10355
    printf ("C3ONAZ00%c", sc);
10356
  if (fg[fg_thioxohetarene - 1])
10357
    printf ("C3SNAZ00%c", sc);
10358
  if (fg[fg_iminohetarene - 1])
10359
    printf ("C3NNAZ00%c", sc);
10360
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
10361
    printf ("C3O30000%c", sc);
10362
  if (fg[fg_carboxylic_acid_orthoester - 1])
10363
    printf ("C3O3C000%c", sc);
10364
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
10365
    printf ("C3O3NC00%c", sc);
10366
  if (fg[fg_carboxylic_acid_anhydride - 1])
10367
    printf ("C3O2C3O2%c", sc);
10368
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
10369
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
10370
    printf ("C3ONCH10%c", sc);
10371
  if (fg[fg_carboxylic_acid_subst_imide - 1])
10372
    printf ("C3ONCC10%c", sc);
10373
  if (fg[fg_co2_deriv - 1])
10374
    printf ("C4000000%c", sc);
10375
  if (fg[fg_carbonic_acid_deriv - 1])
10376
    printf ("C4O30000%c", sc);
10377
  if (fg[fg_carbonic_acid_monoester - 1])
10378
    printf ("C4O3C100%c", sc);
10379
  if (fg[fg_carbonic_acid_diester - 1])
10380
    printf ("C4O3C200%c", sc);
10381
  if (fg[fg_carbonic_acid_ester_halide - 1])
10382
    printf ("C4O3CX00%c", sc);
10383
  if (fg[fg_thiocarbonic_acid_deriv - 1])
10384
    printf ("C4SO0000%c", sc);
10385
  if (fg[fg_thiocarbonic_acid_monoester - 1])
10386
    printf ("C4SOC100%c", sc);
10387
  if (fg[fg_thiocarbonic_acid_diester - 1])
10388
    printf ("C4SOC200%c", sc);
10389
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
10390
    printf ("C4SOX_00%c", sc);
10391
  if (fg[fg_carbamic_acid_deriv - 1])
10392
    printf ("C4O2N000%c", sc);
10393
  if (fg[fg_carbamic_acid - 1])
10394
    printf ("C4O2NH00%c", sc);
10395
  if (fg[fg_carbamic_acid_ester - 1])
10396
    printf ("C4O2NC00%c", sc);
10397
  if (fg[fg_carbamic_acid_halide - 1])
10398
    printf ("C4O2NX00%c", sc);
10399
  if (fg[fg_thiocarbamic_acid_deriv - 1])
10400
    printf ("C4SN0000%c", sc);
10401
  if (fg[fg_thiocarbamic_acid - 1])
10402
    printf ("C4SNOH00%c", sc);
10403
  if (fg[fg_thiocarbamic_acid_ester - 1])
10404
    printf ("C4SNOC00%c", sc);
10405
  if (fg[fg_thiocarbamic_acid_halide - 1])
10406
    printf ("C4SNXX00%c", sc);
10407
  if (fg[fg_urea - 1])
10408
    printf ("C4O1N200%c", sc);
10409
  if (fg[fg_isourea - 1])
10410
    printf ("C4N2O100%c", sc);
10411
  if (fg[fg_thiourea - 1])
10412
    printf ("C4S1N200%c", sc);
10413
  if (fg[fg_isothiourea - 1])
10414
    printf ("C4N2S100%c", sc);
10415
  if (fg[fg_guanidine - 1])
10416
    printf ("C4N30000%c", sc);
10417
  if (fg[fg_semicarbazide - 1])
10418
    printf ("C4ON2N00%c", sc);
10419
  if (fg[fg_thiosemicarbazide - 1])
10420
    printf ("C4SN2N00%c", sc);
10421
  if (fg[fg_azide - 1])
10422
    printf ("N4N20000%c", sc);
10423
  if (fg[fg_azo_compound - 1])
10424
    printf ("N2N10000%c", sc);
10425
  if (fg[fg_diazonium_salt - 1])
10426
    printf ("N3N100T2%c", sc);
10427
  if (fg[fg_isonitrile - 1])
10428
    printf ("N3C10000%c", sc);
10429
  if (fg[fg_cyanate - 1])
10430
    printf ("C4NO1000%c", sc);
10431
  if (fg[fg_isocyanate - 1])
10432
    printf ("C4NO2000%c", sc);
10433
  if (fg[fg_thiocyanate - 1])
10434
    printf ("C4NS1000%c", sc);
10435
  if (fg[fg_isothiocyanate - 1])
10436
    printf ("C4NS2000%c", sc);
10437
  if (fg[fg_carbodiimide - 1])
10438
    printf ("C4N20000%c", sc);
10439
  if (fg[fg_nitroso_compound - 1])
10440
    printf ("N2O10000%c", sc);
10441
  if (fg[fg_nitro_compound - 1])
10442
    printf ("N4O20000%c", sc);
10443
  if (fg[fg_nitrite - 1])
10444
    printf ("N3O20000%c", sc);
10445
  if (fg[fg_nitrate - 1])
10446
    printf ("N4O30000%c", sc);
10447
  if (fg[fg_sulfuric_acid_deriv - 1])
10448
    printf ("S6O00000%c", sc);
10449
  if (fg[fg_sulfuric_acid - 1])
10450
    printf ("S6O4H000%c", sc);
10451
  if (fg[fg_sulfuric_acid_monoester - 1])
10452
    printf ("S6O4HC00%c", sc);
10453
  if (fg[fg_sulfuric_acid_diester - 1])
10454
    printf ("S6O4CC00%c", sc);
10455
  if (fg[fg_sulfuric_acid_amide_ester - 1])
10456
    printf ("S6O3NC00%c", sc);
10457
  if (fg[fg_sulfuric_acid_amide - 1])
10458
    printf ("S6O3N100%c", sc);
10459
  if (fg[fg_sulfuric_acid_diamide - 1])
10460
    printf ("S6O2N200%c", sc);
10461
  if (fg[fg_sulfuryl_halide - 1])
10462
    printf ("S6O3XX00%c", sc);
10463
  if (fg[fg_sulfonic_acid_deriv - 1])
10464
    printf ("S5O00000%c", sc);
10465
  if (fg[fg_sulfonic_acid - 1])
10466
    printf ("S5O3H000%c", sc);
10467
  if (fg[fg_sulfonic_acid_ester - 1])
10468
    printf ("S5O3C000%c", sc);
10469
  if (fg[fg_sulfonamide - 1])
10470
    printf ("S5O2N000%c", sc);
10471
  if (fg[fg_sulfonyl_halide - 1])
10472
    printf ("S5O2XX00%c", sc);
10473
  if (fg[fg_sulfone - 1])
10474
    printf ("S4O20000%c", sc);
10475
  if (fg[fg_sulfoxide - 1])
10476
    printf ("S2O10000%c", sc);
10477
  if (fg[fg_sulfinic_acid_deriv - 1])
10478
    printf ("S3O00000%c", sc);
10479
  if (fg[fg_sulfinic_acid - 1])
10480
    printf ("S3O2H000%c", sc);
10481
  if (fg[fg_sulfinic_acid_ester - 1])
10482
    printf ("S3O2C000%c", sc);
10483
  if (fg[fg_sulfinic_acid_halide - 1])
10484
    printf ("S3O1XX00%c", sc);
10485
  if (fg[fg_sulfinic_acid_amide - 1])
10486
    printf ("S3O1N000%c", sc);
10487
  if (fg[fg_sulfenic_acid_deriv - 1])
10488
    printf ("S1O00000%c", sc);
10489
  if (fg[fg_sulfenic_acid - 1])
10490
    printf ("S1O1H000%c", sc);
10491
  if (fg[fg_sulfenic_acid_ester - 1])
10492
    printf ("S1O1C000%c", sc);
10493
  if (fg[fg_sulfenic_acid_halide - 1])
10494
    printf ("S1O0XX00%c", sc);
10495
  if (fg[fg_sulfenic_acid_amide - 1])
10496
    printf ("S1O0N100%c", sc);
10497
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
10498
  if (fg[fg_alkylthiol - 1])
10499
    printf ("S1H1C000%c", sc);
10500
  if (fg[fg_arylthiol - 1])
10501
    printf ("S1H1A000%c", sc);
10502
  if (fg[fg_phosphoric_acid_deriv - 1])
10503
    printf ("P5O0H000%c", sc);
10504
  if (fg[fg_phosphoric_acid - 1])
10505
    printf ("P5O4H200%c", sc);
10506
  if (fg[fg_phosphoric_acid_ester - 1])
10507
    printf ("P5O4HC00%c", sc);
10508
  if (fg[fg_phosphoric_acid_halide - 1])
10509
    printf ("P5O3HX00%c", sc);
10510
  if (fg[fg_phosphoric_acid_amide - 1])
10511
    printf ("P5O3HN00%c", sc);
10512
  if (fg[fg_thiophosphoric_acid_deriv - 1])
10513
    printf ("P5O0S000%c", sc);
10514
  if (fg[fg_thiophosphoric_acid - 1])
10515
    printf ("P5O3SH00%c", sc);
10516
  if (fg[fg_thiophosphoric_acid_ester - 1])
10517
    printf ("P5O3SC00%c", sc);
10518
  if (fg[fg_thiophosphoric_acid_halide - 1])
10519
    printf ("P5O2SX00%c", sc);
10520
  if (fg[fg_thiophosphoric_acid_amide - 1])
10521
    printf ("P5O2SN00%c", sc);
10522
  if (fg[fg_phosphonic_acid_deriv - 1])
10523
    printf ("P4O30000%c", sc);
10524
  if (fg[fg_phosphonic_acid - 1])
10525
    printf ("P4O3H000%c", sc);
10526
  if (fg[fg_phosphonic_acid_ester - 1])
10527
    printf ("P4O3C000%c", sc);
10528
  if (fg[fg_phosphine - 1])
10529
    printf ("P3000000%c", sc);
10530
  if (fg[fg_phosphinoxide - 1])
10531
    printf ("P2O00000%c", sc);
10532
  if (fg[fg_boronic_acid_deriv - 1])
10533
    printf ("B2O20000%c", sc);
10534
  if (fg[fg_boronic_acid - 1])
10535
    printf ("B2O2H000%c", sc);
10536
  if (fg[fg_boronic_acid_ester - 1])
10537
    printf ("B2O2C000%c", sc);
10538
  if (fg[fg_alkene - 1])
10539
    printf ("000C2C00%c", sc);
10540
  if (fg[fg_alkyne - 1])
10541
    printf ("000C3C00%c", sc);
10542
  if (fg[fg_aromatic - 1])
10543
    printf ("0000A000%c", sc);
10544
  if (fg[fg_heterocycle - 1])
10545
    printf ("0000CZ00%c", sc);
10546
  if (fg[fg_alpha_aminoacid - 1])
10547
    printf ("C3O2HN1C%c", sc);
10548
  if (fg[fg_alpha_hydroxyacid - 1])
10549
    printf ("C3O2HO1H%c", sc);
10550
}
10551
 
10552
#undef sc
10553
 
10554
 
10555
static void
10556
write_fg_binary ()
10557
{
10558
  int i, n;
10559
  char o;
10560
 
10561
  for (i = 1; i <= max_fg / 8; i++)
10562
    {
10563
      n = 0;
10564
      if (fg[i * 8 - 1])
10565
        n++;
10566
      if (fg[i * 8 - 2])
10567
        n += 2;
10568
      if (fg[i * 8 - 3])
10569
        n += 4;
10570
      if (fg[i * 8 - 4])
10571
        n += 8;
10572
      if (fg[i * 8 - 5])
10573
        n += 16;
10574
      if (fg[i * 8 - 6])
10575
        n += 32;
10576
      if (fg[i * 8 - 7])
10577
        n += 64;
10578
      if (fg[i * 8 - 8])
10579
        n += 128;
10580
      o = (char) n;
10581
      putchar (o);
10582
    }
10583
}
10584
 
10585
 
10586
static void
10587
write_fg_bitstring ()
10588
{
10589
  int i;
10590
 
10591
  for (i = 0; i < max_fg; i++)
10592
    {
10593
      if (fg[i])
10594
        putchar ('1');
10595
      else
10596
        putchar ('0');
10597
    }
10598
}
10599
 
10600
 
10601
#if 0
10602
static void readinputfile (molfilename) char *molfilename;
10603
     {
10604
     /* new version in v0.2g */
10605
     char rline[256];
10606
     char *TEMP;
10607
 
10608
     molbufindex = 0;
10609
     if (!opt_stdin)
10610
     {
10611
     if (!rfile_is_open)
10612
     {
10613
     assign (rfile, molfilename);
10614
     rewind (rfile);
10615
     rfile_is_open = true;
10616
     }
10617
     /* p2c: checkmol.pas, line 7733: Warning:
10618
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
10619
     *rline = '\0';
10620
     mol_in_queue = false;
10621
     while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
10622
     {
10623
     fgets (rline, 256, rfile);
10624
     TEMP = strchr (rline, '\n');
10625
     if (TEMP != NULL)
10626
     *TEMP = 0;
10627
     /*mol_in_queue := false; */
10628
     if (molbufindex >= max_atoms + max_bonds + 64)
10629
     {
10630
     printf ("Not enough memory for molfile! %12ld\n",
10631
     molbufindex);
10632
     if (rfile != NULL)
10633
     fclose (rfile);
10634
     rfile = NULL;
10635
     _Escape (1);
10636
     }
10637
     molbufindex++;
10638
     strcpy (molbuf[molbufindex - 1], rline);
10639
     if (strpos2 (rline, "$$$$", 1) > 0)
10640
     mol_in_queue = true;
10641
     }
10642
     if (!P_eof (rfile))
10643
     return;
10644
     if (rfile != NULL)
10645
     fclose (rfile);
10646
     rfile = NULL;
10647
     rfile_is_open = false;
10648
     mol_in_queue = false;
10649
     return;
10650
     }
10651
     *rline = '\0';
10652
     mol_in_queue = false;
10653
     while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
10654
     {
10655
     gets (rline);
10656
     if (molbufindex >= max_atoms + max_bonds + 64)
10657
     {
10658
     printf ("Not enough memory!\n");
10659
     _Escape (1);
10660
     }
10661
     molbufindex++;
10662
     strcpy (molbuf[molbufindex - 1], rline);
10663
     if (strpos2 (rline, "$$$$", 1) > 0)
10664
     {
10665
     mol_in_queue = true;
10666
     /* read from standard input
10667
     }
10668
     }
10669
     } */
10670
#endif
10671
 
10672
static void
10673
readinputfile (char *molfilename)
10674
{
10675
  /* new version in v0.2g */
10676
  char rline[256];
10677
  char *TEMP;
10678
 
10679
  molbufindex = 0;
10680
  if (!opt_stdin)
10681
    {
10682
      if (!rfile_is_open)
10683
        {
10684
          rfile = fopen (molfilename, "r");
10685
          rewind (rfile);
10686
          rfile_is_open = true;
10687
        }
10688
/* p2c: checkmol.pas, line 7226: Warning:
10689
 * Don't know how to ASSIGN to a non-explicit file variable [207] */
10690
      *rline = '\0';
10691
      mol_in_queue = false;
10692
      while ((fgets (rline, 256, rfile) != NULL)
10693
             && (strstr (rline, "$$$$") == NULL))
10694
        {
10695
          TEMP = strchr (rline, '\n');
10696
          if (TEMP != NULL)
10697
            *TEMP = 0;
10698
          /*mol_in_queue := false; */
10699
          if (molbufindex >= max_atoms + max_bonds + 64)
10700
            {
10701
              printf ("Not enough memory for molfile! %d\n", molbufindex);
10702
              if (rfile != NULL)
10703
                fclose (rfile);
10704
              rfile = NULL;
10705
              exit (1);
10706
            }
10707
          //molbufindex++;
10708
          strcpy (molbuf[molbufindex++], rline);
10709
          if (strstr (rline, "$$$$") != NULL)
10710
            mol_in_queue = true;
10711
        }
10712
      if (!feof (rfile))
10713
        return;
10714
      if (rfile != NULL)
10715
        fclose (rfile);
10716
      rfile = NULL;
10717
      rfile_is_open = false;
10718
      mol_in_queue = false;
10719
      return;
10720
    }
10721
  *rline = '\0';
10722
  mol_in_queue = false;
10723
  do
10724
    {
10725
      fgets (rline, 256, stdin);
10726
      if (feof (stdin))
10727
        return;
10728
      TEMP = strchr (rline, '\n');
10729
      if (TEMP != NULL)
10730
        *TEMP = '\0';
10731
      if (molbufindex >= max_atoms + max_bonds + 64)
10732
        {
10733
          printf ("Not enough memory!\n");
10734
          exit (1);
10735
        }
10736
      //molbufindex++;
10737
      strcpy (molbuf[molbufindex++], rline);
10738
      if (strstr (rline, "$$$$") != NULL)
10739
        {
10740
          mol_in_queue = true;
10741
          /* read from standard input */
10742
        }
10743
    }
10744
  while (strstr (rline, "$$$$") == NULL);
10745
}
10746
 
10747
#if 0
10748
static void copy_mol_to_needle()
10749
{
10750
  int i, j, FORLIM;
10751
 
10752
  if (n_atoms == 0)
10753
    return;
10754
  /* try */
10755
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10756
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10757
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10758
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10759
  /* except*/
10760
    on e:Eoutofmemory do
10761
      begin
10762
        writeln('Not enough memory');
10763
        halt(4);
10764
      end;
10765
  end;
10766
  ndl_n_atoms = n_atoms;
10767
  ndl_n_bonds = n_bonds;
10768
  ndl_n_rings = n_rings;
10769
  ndl_n_heavyatoms = n_heavyatoms;
10770
  ndl_n_heavybonds = n_heavybonds;
10771
  strcpy(ndl_molname, molname);
10772
  ndl_n_Ctot = n_Ctot;
10773
  ndl_n_Otot = n_Otot;
10774
  ndl_n_Ntot = n_Ntot;
10775
  FORLIM = n_atoms;
10776
  for (i = 0; i < FORLIM; i++) {
10777
    strcpy(ndl_atom[i].element, atom[i].element);
10778
    strcpy(ndl_atom[i].atype, atom[i].atype);
10779
    ndl_atom[i].x = atom[i].x;
10780
    ndl_atom[i].y = atom[i].y;
10781
    ndl_atom[i].z = atom[i].z;
10782
    ndl_atom[i].formal_charge = atom[i].formal_charge;
10783
    ndl_atom[i].real_charge = atom[i].real_charge;
10784
    ndl_atom[i].Hexp = atom[i].Hexp;
10785
    ndl_atom[i].Htot = atom[i].Htot;
10786
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
10787
    ndl_atom[i].ring_count = atom[i].ring_count;
10788
    ndl_atom[i].arom = atom[i].arom;
10789
    ndl_atom[i].stereo_care = atom[i].stereo_care;
10790
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
10791
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
10792
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
10793
                                           }
10794
                                           if (n_bonds > 0) {
10795
                                           FORLIM = n_bonds;
10796
                                           for (i = 0; i < FORLIM; i++) {
10797
                                           ndl_bond[i].a1 = bond[i].a1;
10798
                                           ndl_bond[i].a2 = bond[i].a2;
10799
                                           ndl_bond[i].btype = bond[i].btype;
10800
                                           ndl_bond[i].arom = bond[i].arom;
10801
                                           ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
10802
                                           ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
10803
                                           ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
10804
                                           }
10805
                                           }
10806
                                           if (n_rings > 0) {
10807
                                           FORLIM = n_rings;
10808
                                           for (i = 0; i < FORLIM; i++) {
10809
                                           for (j = 0; j < max_ringsize; j++)
10810
                                           ndl_ring[i][j] = ring[i][j];
10811
                                           }
10812
                                           for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10813
                                           ndl_ringprop[i].size = ringprop[i].size;
10814
                                           ndl_ringprop[i].arom = ringprop[i].arom;
10815
                                           ndl_ringprop[i].envelope = ringprop[i].envelope;
10816
                                           }
10817
                                           }
10818
                                           ndl_molstat.n_QA = molstat.n_QA;
10819
                                           ndl_molstat.n_QB = molstat.n_QB;
10820
                                           ndl_molstat.n_chg = molstat.n_chg;
10821
                                           ndl_molstat.n_C1 = molstat.n_C1;
10822
                                           ndl_molstat.n_C2 = molstat.n_C2;
10823
                                           ndl_molstat.n_C = molstat.n_C;
10824
                                           ndl_molstat.n_CHB1p = molstat.n_CHB1p;
10825
                                           ndl_molstat.n_CHB2p = molstat.n_CHB2p;
10826
                                           ndl_molstat.n_CHB3p = molstat.n_CHB3p;
10827
                                           ndl_molstat.n_CHB4 = molstat.n_CHB4;
10828
                                           ndl_molstat.n_O2 = molstat.n_O2;
10829
                                           ndl_molstat.n_O3 = molstat.n_O3;
10830
                                           ndl_molstat.n_N1 = molstat.n_N1;
10831
                                           ndl_molstat.n_N2 = molstat.n_N2;
10832
                                           ndl_molstat.n_N3 = molstat.n_N3;
10833
                                           ndl_molstat.n_S = molstat.n_S;
10834
                                           ndl_molstat.n_SeTe = molstat.n_SeTe;
10835
                                           ndl_molstat.n_F = molstat.n_F;
10836
                                           ndl_molstat.n_Cl = molstat.n_Cl;
10837
                                           ndl_molstat.n_Br = molstat.n_Br;
10838
                                           ndl_molstat.n_I = molstat.n_I;
10839
                                           ndl_molstat.n_P = molstat.n_P;
10840
                                           ndl_molstat.n_B = molstat.n_B;
10841
                                           ndl_molstat.n_Met = molstat.n_Met;
10842
                                           ndl_molstat.n_X = molstat.n_X;
10843
                                           ndl_molstat.n_b1 = molstat.n_b1;
10844
                                           ndl_molstat.n_b2 = molstat.n_b2;
10845
                                           ndl_molstat.n_b3 = molstat.n_b3;
10846
                                           ndl_molstat.n_bar = molstat.n_bar;
10847
                                           ndl_molstat.n_C1O = molstat.n_C1O;
10848
                                           ndl_molstat.n_C2O = molstat.n_C2O;
10849
                                           ndl_molstat.n_CN = molstat.n_CN;
10850
                                           ndl_molstat.n_XY = molstat.n_XY;
10851
                                           ndl_molstat.n_r3 = molstat.n_r3;
10852
                                           ndl_molstat.n_r4 = molstat.n_r4;
10853
                                           ndl_molstat.n_r5 = molstat.n_r5;
10854
                                           ndl_molstat.n_r6 = molstat.n_r6;
10855
                                           ndl_molstat.n_r7 = molstat.n_r7;
10856
                                           ndl_molstat.n_r8 = molstat.n_r8;
10857
                                           ndl_molstat.n_r9 = molstat.n_r9;
10858
                                           ndl_molstat.n_r10 = molstat.n_r10;
10859
                                           ndl_molstat.n_r11 = molstat.n_r11;
10860
                                           ndl_molstat.n_r12 = molstat.n_r12;
10861
                                           ndl_molstat.n_r13p = molstat.n_r13p;
10862
                                           ndl_molstat.n_rN = molstat.n_rN;
10863
                                           ndl_molstat.n_rN1 = molstat.n_rN1;
10864
                                           ndl_molstat.n_rN2 = molstat.n_rN2;
10865
                                           ndl_molstat.n_rN3p = molstat.n_rN3p;
10866
                                           ndl_molstat.n_rO = molstat.n_rO;
10867
                                           ndl_molstat.n_rO1 = molstat.n_rO1;
10868
                                           ndl_molstat.n_rO2p = molstat.n_rO2p;
10869
                                           ndl_molstat.n_rS = molstat.n_rS;
10870
                                           ndl_molstat.n_rX = molstat.n_rX;
10871
                                           ndl_molstat.n_rAr = molstat.n_rAr;
10872
                                           ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
10873
                                           ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
10874
                                           /* p2c: checkmol.pas, line 7875:
10875
                                           * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10876
                                           /*$IFDEF extended_molstat
10877
                                            v0.3m */
10878
                                           ndl_molstat.n_psg01 = molstat.n_psg01;
10879
                                           ndl_molstat.n_psg02 = molstat.n_psg02;
10880
                                           ndl_molstat.n_psg13 = molstat.n_psg13;
10881
                                           ndl_molstat.n_psg14 = molstat.n_psg14;
10882
                                           ndl_molstat.n_psg15 = molstat.n_psg15;
10883
                                           ndl_molstat.n_psg16 = molstat.n_psg16;
10884
                                           ndl_molstat.n_psg17 = molstat.n_psg17;
10885
                                           ndl_molstat.n_psg18 = molstat.n_psg18;
10886
                                           ndl_molstat.n_pstm = molstat.n_pstm;
10887
                                           ndl_molstat.n_psla = molstat.n_psla;
10888
                                           $ENDIF*/
10889
                                           /* make sure some modes can be switched on only by the query file *M*/
10890
                                           /* and not by subsequent haystack file(s) */
10891
                                           if (ez_flag)   /* new in v0.3f */
10892
                                           ez_search = true;
10893
                                           if (chir_flag)   /* new in v0.3f */
10894
                                           rs_search = true;
10895
                                           }
10896
#endif
10897
 
10898
 
10899
static void
10900
copy_mol_to_needle ()
10901
{
10902
  //int i, j, FORLIM;
10903
 
10904
  /*if (n_atoms == 0)
10905
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10906
 
10907
 
10908
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10909
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10910
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10911
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10912
 
10913
 
10914
  ndl_n_atoms = n_atoms;
10915
  ndl_n_bonds = n_bonds;
10916
  ndl_n_rings = n_rings;
10917
  ndl_n_heavyatoms = n_heavyatoms;
10918
  ndl_n_heavybonds = n_heavybonds;
10919
  strcpy (ndl_molname, molname);
10920
  ndl_n_Ctot = n_Ctot;
10921
  ndl_n_Otot = n_Otot;
10922
  ndl_n_Ntot = n_Ntot;
10923
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
10924
 
10925
  if (n_bonds > 0)
10926
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
10927
 
10928
  if (n_rings > 0)
10929
    {
10930
      memcpy (ndl_ring, ring, sizeof (ringlist));
10931
      memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
10932
    }
10933
 
10934
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
10935
 
10936
 
10937
  // make sure some modes can be switched on only by the query file 
10938
  // and not by subsequent haystack file(s) 
10939
  if (ez_flag)                  // new in v0.3f 
10940
    ez_search = true;
10941
 
10942
  if (chir_flag)                // new in v0.3f 
10943
    rs_search = true;
10944
 
10945
  ndl_querymol = found_querymol;        /* 0.3p */
10946
 
10947
}
10948
 
10949
static void
10950
copy_mol_to_tmp ()
10951
{
10952
  //int i, j, FORLIM;
10953
 
10954
  /*if (n_atoms == 0)
10955
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10956
 
10957
 
10958
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10959
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10960
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10961
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10962
 
10963
 
10964
  tmp_n_atoms = n_atoms;
10965
  tmp_n_bonds = n_bonds;
10966
  tmp_n_rings = n_rings;
10967
  tmp_n_heavyatoms = n_heavyatoms;
10968
  tmp_n_heavybonds = n_heavybonds;
10969
  strcpy (tmp_molname, molname);
10970
  tmp_n_Ctot = n_Ctot;
10971
  tmp_n_Otot = n_Otot;
10972
  tmp_n_Ntot = n_Ntot;
10973
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
10974
 
10975
  if (n_bonds > 0)
10976
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
10977
 
10978
  if (n_rings > 0)
10979
    {
10980
      memcpy (tmp_ring, ring, sizeof (ringlist));
10981
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
10982
    }
10983
 
10984
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
10985
 
10986
 
10987
  // make sure some modes can be switched on only by the query file 
10988
  // and not by subsequent haystack file(s) 
10989
  if (ez_flag)                  // new in v0.3f 
10990
    ez_search = true;
10991
 
10992
  if (chir_flag)                // new in v0.3f 
10993
    rs_search = true;
10994
 
10995
  ndl_querymol = found_querymol;        /* 0.3p */
10996
 
10997
}
10998
 
10999
#if 0
11000
static void copy_mol_to_tmp()
11001
{
11002
  int i, j, FORLIM;
11003
 
11004
  if (n_atoms == 0)
11005
    return;
11006
  /* try */
11007
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
11008
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
11009
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
11010
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
11011
  /* except */
11012
    on e:Eoutofmemory do
11013
      begin
11014
        writeln('Not enough memory');
11015
        halt(4);
11016
      end;
11017
  end;
11018
  tmp_n_atoms = n_atoms;
11019
  tmp_n_bonds = n_bonds;
11020
  tmp_n_rings = n_rings;
11021
  tmp_n_heavyatoms = n_heavyatoms;
11022
  tmp_n_heavybonds = n_heavybonds;
11023
  strcpy(tmp_molname, molname);
11024
  tmp_n_Ctot = n_Ctot;
11025
  tmp_n_Otot = n_Otot;
11026
  tmp_n_Ntot = n_Ntot;
11027
  FORLIM = n_atoms;
11028
  for (i = 0; i < FORLIM; i++) {
11029
    strcpy(tmp_atom[i].element, atom[i].element);
11030
    strcpy(tmp_atom[i].atype, atom[i].atype);
11031
    tmp_atom[i].x = atom[i].x;
11032
    tmp_atom[i].y = atom[i].y;
11033
    tmp_atom[i].z = atom[i].z;
11034
    tmp_atom[i].formal_charge = atom[i].formal_charge;
11035
    tmp_atom[i].real_charge = atom[i].real_charge;
11036
    tmp_atom[i].Hexp = atom[i].Hexp;
11037
    tmp_atom[i].Htot = atom[i].Htot;
11038
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
11039
    tmp_atom[i].ring_count = atom[i].ring_count;
11040
    tmp_atom[i].arom = atom[i].arom;
11041
    tmp_atom[i].stereo_care = atom[i].stereo_care;
11042
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
11043
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
11044
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
11045
  }
11046
  if (n_bonds > 0) {
11047
    FORLIM = n_bonds;
11048
    for (i = 0; i < FORLIM; i++) {
11049
      tmp_bond[i].a1 = bond[i].a1;
11050
      tmp_bond[i].a2 = bond[i].a2;
11051
      tmp_bond[i].btype = bond[i].btype;
11052
      tmp_bond[i].arom = bond[i].arom;
11053
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
11054
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
11055
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
11056
    }
11057
  }
11058
  if (n_rings > 0) {
11059
    FORLIM = n_rings;
11060
    for (i = 0; i < FORLIM; i++) {
11061
      for (j = 0; j < max_ringsize; j++)
11062
        tmp_ring[i][j] = ring[i][j];
11063
    }
11064
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
11065
      tmp_ringprop[i].size = ringprop[i].size;
11066
      tmp_ringprop[i].arom = ringprop[i].arom;
11067
      tmp_ringprop[i].envelope = ringprop[i].envelope;
11068
    }
11069
  }
11070
  tmp_molstat.n_QA = molstat.n_QA;
11071
  tmp_molstat.n_QB = molstat.n_QB;
11072
  tmp_molstat.n_chg = molstat.n_chg;
11073
  tmp_molstat.n_C1 = molstat.n_C1;
11074
  tmp_molstat.n_C2 = molstat.n_C2;
11075
  tmp_molstat.n_C = molstat.n_C;
11076
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
11077
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
11078
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
11079
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
11080
  tmp_molstat.n_O2 = molstat.n_O2;
11081
  tmp_molstat.n_O3 = molstat.n_O3;
11082
  tmp_molstat.n_N1 = molstat.n_N1;
11083
  tmp_molstat.n_N2 = molstat.n_N2;
11084
  tmp_molstat.n_N3 = molstat.n_N3;
11085
  tmp_molstat.n_S = molstat.n_S;
11086
  tmp_molstat.n_SeTe = molstat.n_SeTe;
11087
  tmp_molstat.n_F = molstat.n_F;
11088
  tmp_molstat.n_Cl = molstat.n_Cl;
11089
  tmp_molstat.n_Br = molstat.n_Br;
11090
  tmp_molstat.n_I = molstat.n_I;
11091
  tmp_molstat.n_P = molstat.n_P;
11092
  tmp_molstat.n_B = molstat.n_B;
11093
  tmp_molstat.n_Met = molstat.n_Met;
11094
  tmp_molstat.n_X = molstat.n_X;
11095
  tmp_molstat.n_b1 = molstat.n_b1;
11096
  tmp_molstat.n_b2 = molstat.n_b2;
11097
  tmp_molstat.n_b3 = molstat.n_b3;
11098
  tmp_molstat.n_bar = molstat.n_bar;
11099
  tmp_molstat.n_C1O = molstat.n_C1O;
11100
  tmp_molstat.n_C2O = molstat.n_C2O;
11101
  tmp_molstat.n_CN = molstat.n_CN;
11102
  tmp_molstat.n_XY = molstat.n_XY;
11103
  tmp_molstat.n_r3 = molstat.n_r3;
11104
  tmp_molstat.n_r4 = molstat.n_r4;
11105
  tmp_molstat.n_r5 = molstat.n_r5;
11106
  tmp_molstat.n_r6 = molstat.n_r6;
11107
  tmp_molstat.n_r7 = molstat.n_r7;
11108
  tmp_molstat.n_r8 = molstat.n_r8;
11109
  tmp_molstat.n_r9 = molstat.n_r9;
11110
  tmp_molstat.n_r10 = molstat.n_r10;
11111
  tmp_molstat.n_r11 = molstat.n_r11;
11112
  tmp_molstat.n_r12 = molstat.n_r12;
11113
  tmp_molstat.n_r13p = molstat.n_r13p;
11114
  tmp_molstat.n_rN = molstat.n_rN;
11115
  tmp_molstat.n_rN1 = molstat.n_rN1;
11116
  tmp_molstat.n_rN2 = molstat.n_rN2;
11117
  tmp_molstat.n_rN3p = molstat.n_rN3p;
11118
  tmp_molstat.n_rO = molstat.n_rO;
11119
  tmp_molstat.n_rO1 = molstat.n_rO1;
11120
  tmp_molstat.n_rO2p = molstat.n_rO2p;
11121
  tmp_molstat.n_rS = molstat.n_rS;
11122
  tmp_molstat.n_rX = molstat.n_rX;
11123
  tmp_molstat.n_rAr = molstat.n_rAr;
11124
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
11125
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
11126
/* p2c: checkmol.pas, line 8022:
11127
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11128
  /*$IFDEF extended_molstat
11129
   v0.3m
11130
  tmp_molstat.n_psg01 = molstat.n_psg01;
11131
  tmp_molstat.n_psg02 = molstat.n_psg02;
11132
  tmp_molstat.n_psg13 = molstat.n_psg13;
11133
  tmp_molstat.n_psg14 = molstat.n_psg14;
11134
  tmp_molstat.n_psg15 = molstat.n_psg15;
11135
  tmp_molstat.n_psg16 = molstat.n_psg16;
11136
  tmp_molstat.n_psg17 = molstat.n_psg17;
11137
  tmp_molstat.n_psg18 = molstat.n_psg18;
11138
  tmp_molstat.n_pstm = molstat.n_pstm;
11139
  tmp_molstat.n_psla = molstat.n_psla;
11140
  $ENDIF*/
11141
  /* make sure some modes can be switched on only by the query file */
11142
  /* and not by subsequent haystack file(s) */
11143
  if (ez_flag)   /* new in v0.3f */
11144
    ez_search = true;
11145
  if (chir_flag)   /* new in v0.3f */
11146
    rs_search = true;
11147
}
11148
#endif
11149
 
11150
static void
11151
copy_tmp_to_mol ()
11152
{
11153
  //int i, j, FORLIM;
11154
 
11155
  /*if (n_atoms == 0)
11156
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
11157
 
11158
 
11159
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
11160
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
11161
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
11162
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
11163
 
11164
 
11165
  n_atoms = tmp_n_atoms;
11166
  n_bonds = tmp_n_bonds;
11167
  n_rings = tmp_n_rings;
11168
  n_heavyatoms = tmp_n_heavyatoms;
11169
  n_heavybonds = tmp_n_heavybonds;
11170
  strcpy (molname, tmp_molname);
11171
  n_Ctot = tmp_n_Ctot;
11172
  n_Otot = tmp_n_Otot;
11173
  n_Ntot = tmp_n_Ntot;
11174
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
11175
 
11176
  if (tmp_n_bonds > 0)
11177
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
11178
 
11179
  if (tmp_n_rings > 0)
11180
    {
11181
      memcpy (ring, tmp_ring, sizeof (ringlist));
11182
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
11183
    }
11184
 
11185
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
11186
 
11187
 
11188
  // make sure some modes can be switched on only by the query file 
11189
  // and not by subsequent haystack file(s) 
11190
  if (ez_flag)                  // new in v0.3f 
11191
    ez_search = true;
11192
 
11193
  if (chir_flag)                // new in v0.3f 
11194
    rs_search = true;
11195
 
11196
}
11197
 
11198
#if 0
11199
static void copy_tmp_to_mol()
11200
{
11201
  int i, j, FORLIM;
11202
 
11203
  if (tmp_n_atoms == 0)
11204
    return;
11205
  n_atoms = tmp_n_atoms;
11206
  n_bonds = tmp_n_bonds;
11207
  n_rings = tmp_n_rings;
11208
  n_heavyatoms = tmp_n_heavyatoms;
11209
  n_heavybonds = tmp_n_heavybonds;
11210
  strcpy(molname, tmp_molname);
11211
  n_Ctot = tmp_n_Ctot;
11212
  n_Otot = tmp_n_Otot;
11213
  n_Ntot = tmp_n_Ntot;
11214
  /* try */
11215
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
11216
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
11217
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
11218
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
11219
  FORLIM = tmp_n_atoms;
11220
  /* except*/
11221
    on e:Eoutofmemory do
11222
      begin
11223
        writeln('Not enough memory');
11224
        halt(4);
11225
      end;
11226
  end;
11227
  for (i = 0; i < FORLIM; i++) {
11228
    strcpy(atom[i].element, tmp_atom[i].element);
11229
    strcpy(atom[i].atype, tmp_atom[i].atype);
11230
    atom[i].x = tmp_atom[i].x;
11231
    atom[i].y = tmp_atom[i].y;
11232
    atom[i].z = tmp_atom[i].z;
11233
    atom[i].formal_charge = tmp_atom[i].formal_charge;
11234
    atom[i].real_charge = tmp_atom[i].real_charge;
11235
    atom[i].Hexp = tmp_atom[i].Hexp;
11236
    atom[i].Htot = tmp_atom[i].Htot;
11237
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
11238
    atom[i].ring_count = tmp_atom[i].ring_count;
11239
    atom[i].arom = tmp_atom[i].arom;
11240
    atom[i].stereo_care = tmp_atom[i].stereo_care;
11241
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
11242
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
11243
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
11244
  }
11245
  if (tmp_n_bonds > 0) {
11246
    FORLIM = tmp_n_bonds;
11247
    for (i = 0; i < FORLIM; i++) {
11248
      bond[i].a1 = tmp_bond[i].a1;
11249
      bond[i].a2 = tmp_bond[i].a2;
11250
      bond[i].btype = tmp_bond[i].btype;
11251
      bond[i].arom = tmp_bond[i].arom;
11252
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
11253
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
11254
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
11255
    }
11256
  }
11257
  if (tmp_n_rings > 0) {
11258
    FORLIM = tmp_n_rings;
11259
    for (i = 0; i < FORLIM; i++) {
11260
      for (j = 0; j < max_ringsize; j++)
11261
        ring[i][j] = tmp_ring[i][j];
11262
    }
11263
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
11264
      ringprop[i].size = tmp_ringprop[i].size;
11265
      ringprop[i].arom = tmp_ringprop[i].arom;
11266
      ringprop[i].envelope = tmp_ringprop[i].envelope;
11267
    }
11268
  }
11269
  molstat.n_QA = tmp_molstat.n_QA;
11270
  molstat.n_QB = tmp_molstat.n_QB;
11271
  molstat.n_chg = tmp_molstat.n_chg;
11272
  molstat.n_C1 = tmp_molstat.n_C1;
11273
  molstat.n_C2 = tmp_molstat.n_C2;
11274
  molstat.n_C = tmp_molstat.n_C;
11275
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
11276
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
11277
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
11278
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
11279
  molstat.n_O2 = tmp_molstat.n_O2;
11280
  molstat.n_O3 = tmp_molstat.n_O3;
11281
  molstat.n_N1 = tmp_molstat.n_N1;
11282
  molstat.n_N2 = tmp_molstat.n_N2;
11283
  molstat.n_N3 = tmp_molstat.n_N3;
11284
  molstat.n_S = tmp_molstat.n_S;
11285
  molstat.n_SeTe = tmp_molstat.n_SeTe;
11286
  molstat.n_F = tmp_molstat.n_F;
11287
  molstat.n_Cl = tmp_molstat.n_Cl;
11288
  molstat.n_Br = tmp_molstat.n_Br;
11289
  molstat.n_I = tmp_molstat.n_I;
11290
  molstat.n_P = tmp_molstat.n_P;
11291
  molstat.n_B = tmp_molstat.n_B;
11292
  molstat.n_Met = tmp_molstat.n_Met;
11293
  molstat.n_X = tmp_molstat.n_X;
11294
  molstat.n_b1 = tmp_molstat.n_b1;
11295
  molstat.n_b2 = tmp_molstat.n_b2;
11296
  molstat.n_b3 = tmp_molstat.n_b3;
11297
  molstat.n_bar = tmp_molstat.n_bar;
11298
  molstat.n_C1O = tmp_molstat.n_C1O;
11299
  molstat.n_C2O = tmp_molstat.n_C2O;
11300
  molstat.n_CN = tmp_molstat.n_CN;
11301
  molstat.n_XY = tmp_molstat.n_XY;
11302
  molstat.n_r3 = tmp_molstat.n_r3;
11303
  molstat.n_r4 = tmp_molstat.n_r4;
11304
  molstat.n_r5 = tmp_molstat.n_r5;
11305
  molstat.n_r6 = tmp_molstat.n_r6;
11306
  molstat.n_r7 = tmp_molstat.n_r7;
11307
  molstat.n_r8 = tmp_molstat.n_r8;
11308
  molstat.n_r9 = tmp_molstat.n_r9;
11309
  molstat.n_r10 = tmp_molstat.n_r10;
11310
  molstat.n_r11 = tmp_molstat.n_r11;
11311
  molstat.n_r12 = tmp_molstat.n_r12;
11312
  molstat.n_r13p = tmp_molstat.n_r13p;
11313
  molstat.n_rN = tmp_molstat.n_rN;
11314
  molstat.n_rN1 = tmp_molstat.n_rN1;
11315
  molstat.n_rN2 = tmp_molstat.n_rN2;
11316
  molstat.n_rN3p = tmp_molstat.n_rN3p;
11317
  molstat.n_rO = tmp_molstat.n_rO;
11318
  molstat.n_rO1 = tmp_molstat.n_rO1;
11319
  molstat.n_rO2p = tmp_molstat.n_rO2p;
11320
  molstat.n_rS = tmp_molstat.n_rS;
11321
  molstat.n_rX = tmp_molstat.n_rX;
11322
  molstat.n_rAr = tmp_molstat.n_rAr;
11323
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
11324
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
11325
/* p2c: checkmol.pas, line 8169:
11326
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11327
  /*$IFDEF extended_molstat
11328
     molstat.n_psg01 = tmp_molstat.n_psg01;
11329
     molstat.n_psg02 = tmp_molstat.n_psg02;
11330
     molstat.n_psg13 = tmp_molstat.n_psg13;
11331
     molstat.n_psg14 = tmp_molstat.n_psg14;
11332
     molstat.n_psg15 = tmp_molstat.n_psg15;
11333
     molstat.n_psg16 = tmp_molstat.n_psg16;
11334
     molstat.n_psg17 = tmp_molstat.n_psg17;
11335
     molstat.n_psg18 = tmp_molstat.n_psg18;
11336
     molstat.n_pstm = tmp_molstat.n_pstm;
11337
     molstat.n_psla = tmp_molstat.n_psla;
11338
     $ENDIF */
11339
  /* make sure some modes can be switched on only by the query file */
11340
  /* and not by subsequent haystack file(s) */
11341
     if (ez_flag)
11342
     ez_search = true;
11343
     if (chir_flag)
11344
     rs_search = true;
11345
     }
11346
#endif
11347
 
11348
 
11349
 
11350
 
11351
 
11352
static void
11353
get_ringstat (r_id)
11354
     int r_id;
11355
{
11356
  int i, j;
11357
  ringpath_type testring;
11358
  int ring_size, a_ref;
11359
  str2 elem;
11360
  int nN = 0, nO = 0, nS = 0, nX = 0;
11361
 
11362
  if (r_id < 1 || r_id > n_rings)
11363
    return;
11364
  memset (testring, 0, sizeof (ringpath_type));
11365
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
11366
  for (j = 0; j < ring_size; j++)       /* v0.3j */
11367
    testring[j] = ring[r_id - 1][j];
11368
/* p2c: checkmol.pas, line 8238:
11369
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11370
#ifdef reduced_SAR
11371
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != false)
11372
    /* v0.3n: ignore envelope rings */
11373
    return;
11374
#else
11375
  if (ring_size <= 2)
11376
    return;
11377
#endif
11378
  for (i = 0; i < ring_size; i++)
11379
    {
11380
      a_ref = testring[i];
11381
      strcpy (elem, atom[a_ref - 1].element);
11382
      if (strcmp (elem, "C ") && strcmp (elem, "A "))
11383
        {
11384
          nX++;                 /* general heteroatom count */
11385
          if (!strcmp (elem, "N "))
11386
            nN++;
11387
          if (!strcmp (elem, "O "))
11388
            nO++;
11389
          if (!strcmp (elem, "S "))
11390
            nS++;
11391
        }
11392
    }
11393
  if (nN > 0)
11394
    {
11395
      molstat.n_rN++;
11396
      if (nN == 1)
11397
        molstat.n_rN1++;
11398
      if (nN == 2)
11399
        molstat.n_rN2++;
11400
      if (nN > 2)
11401
        molstat.n_rN3p++;
11402
    }
11403
  if (nO > 0)
11404
    {
11405
      molstat.n_rO++;
11406
      if (nO == 1)
11407
        molstat.n_rO1++;
11408
      if (nO == 2)
11409
        molstat.n_rO2p++;
11410
    }
11411
  if (nS > 0)
11412
    molstat.n_rS++;
11413
  if (nX > 0)
11414
    molstat.n_rX++;
11415
  /* general ringsize descriptors; v0.3m */
11416
  switch (ring_size)
11417
    {
11418
 
11419
    case 3:
11420
      molstat.n_r3++;
11421
      break;
11422
 
11423
    case 4:
11424
      molstat.n_r4++;
11425
      break;
11426
 
11427
    case 5:
11428
      molstat.n_r5++;
11429
      break;
11430
 
11431
    case 6:
11432
      molstat.n_r6++;
11433
      break;
11434
 
11435
    case 7:
11436
      molstat.n_r7++;
11437
      break;
11438
 
11439
    case 8:
11440
      molstat.n_r8++;
11441
      break;
11442
 
11443
    case 9:
11444
      molstat.n_r9++;
11445
      break;
11446
 
11447
    case 10:
11448
      molstat.n_r10++;
11449
      break;
11450
 
11451
    case 11:
11452
      molstat.n_r11++;
11453
      break;
11454
 
11455
    case 12:
11456
      molstat.n_r12++;
11457
      break;
11458
 
11459
    default:
11460
      molstat.n_r13p++;
11461
      break;
11462
    }                           /* end v0.3m        */
11463
}
11464
 
11465
 
11466
static void
11467
get_molstat ()
11468
{
11469
  int i;
11470
  str2 elem;
11471
  str3 atype;
11472
  int a1, a2;
11473
  str2 a1el, a2el;
11474
  char btype;
11475
  int hbc;
11476
  int n_b2formal = 0;           /* new in v0.2e */
11477
  int FORLIM;
11478
 
11479
  if (n_atoms == 0)
11480
    return;
11481
  FORLIM = n_atoms;
11482
  for (i = 0; i < FORLIM; i++)
11483
    {
11484
      if (atom[i].heavy)
11485
        {
11486
          strcpy (elem, atom[i].element);
11487
          strcpy (atype, atom[i].atype);
11488
          if (!strcmp (atype, "C1 "))
11489
            molstat.n_C1++;
11490
          if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
11491
            molstat.n_C2++;
11492
          if (!strcmp (elem, "C "))
11493
            molstat.n_C++;
11494
          if (!strcmp (atype, "O2 "))
11495
            molstat.n_O2++;
11496
          if (!strcmp (atype, "O3 "))
11497
            molstat.n_O3++;
11498
          if (!strcmp (atype, "N1 "))
11499
            molstat.n_N1++;
11500
          if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
11501
              (!strcmp (atype, "NAM") && atom[i].arom == true))
11502
            /* v0.3n */
11503
            molstat.n_N2++;
11504
          if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
11505
              !strcmp (atype, "N3+") ||
11506
              (!strcmp (atype, "NAM") && atom[i].arom == false))
11507
            /* v0.3n */
11508
            molstat.n_N3++;
11509
          if (!strcmp (elem, "A "))     /* query atom */
11510
            molstat.n_QA++;
11511
          if (!strcmp (elem, "Q "))     /* query atom */
11512
            molstat.n_QA++;
11513
          if (!strcmp (elem, "X "))     /* query atom */
11514
            molstat.n_QA++;
11515
          if (!strcmp (elem, "S "))
11516
            molstat.n_S++;
11517
          if (!strcmp (elem, "SE"))
11518
            molstat.n_SeTe++;
11519
          if (!strcmp (elem, "TE"))
11520
            molstat.n_SeTe++;
11521
          if (!strcmp (elem, "F "))
11522
            molstat.n_F++;
11523
          if (!strcmp (elem, "CL"))
11524
            molstat.n_Cl++;
11525
          if (!strcmp (elem, "BR"))
11526
            molstat.n_Br++;
11527
          if (!strcmp (elem, "I "))
11528
            molstat.n_I++;
11529
          if (!strcmp (elem, "P "))
11530
            molstat.n_P++;
11531
          if (!strcmp (elem, "B "))
11532
            molstat.n_B++;
11533
          /* check for known metals */
11534
          if (atom[i].metal)    /* v0.3l */
11535
            molstat.n_Met++;
11536
          /* still missing: unknown elements */
11537
 
11538
          /* check number of heteroatom bonds per C atom */
11539
          if (!strcmp (elem, "C "))
11540
            {
11541
              hbc = raw_hetbond_count (i + 1);
11542
              /* new in v0.2j (replaces hetbond_count) */
11543
              if (hbc >= 1)
11544
                molstat.n_CHB1p++;
11545
              if (hbc >= 2)
11546
                molstat.n_CHB2p++;
11547
              if (hbc >= 3)
11548
                molstat.n_CHB3p++;
11549
              if (hbc == 4)
11550
                molstat.n_CHB4++;
11551
            }
11552
          if (atom[i].formal_charge != 0)
11553
            {
11554
              molstat.n_chg++;
11555
              //n_charges++;
11556
            }
11557
          if (atom[i].nucleon_number != 0)
11558
            {
11559
              molstat.n_iso++;
11560
            }
11561
          if (atom[i].radical_type != 0)
11562
            {
11563
              molstat.n_rad++;
11564
            }
11565
          /* check for "other" elements;  v0.3l */
11566
          if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
11567
              && strcmp (elem, "O ") && strcmp (elem, "S ")
11568
              && strcmp (elem, "SE") && strcmp (elem, "TE")
11569
              && strcmp (elem, "P ") && strcmp (elem, "B ")
11570
              && strcmp (elem, "A ") && strcmp (elem, "Q "))
11571
            molstat.n_X++;
11572
          /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
11573
/* p2c: checkmol.pas, line 8353:
11574
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11575
          /*$IFDEF extended_molstat */
11576
          if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
11577
              || !strcmp (elem, "K ") || !strcmp (elem, "RB")
11578
              || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
11579
            molstat.n_psg01++;
11580
          if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
11581
              || !strcmp (elem, "CA") || !strcmp (elem, "SR")
11582
              || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
11583
            molstat.n_psg02++;
11584
          if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
11585
              || !strcmp (elem, "GA") || !strcmp (elem, "IN")
11586
              || !strcmp (elem, "TL"))
11587
            molstat.n_psg13++;
11588
          if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
11589
              || !strcmp (elem, "GE") || !strcmp (elem, "SN")
11590
              || !strcmp (elem, "PB"))
11591
            molstat.n_psg14++;
11592
          if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
11593
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
11594
              || !strcmp (elem, "BI"))
11595
            molstat.n_psg15++;
11596
          if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
11597
              || !strcmp (elem, "SE") || !strcmp (elem, "TE")
11598
              || !strcmp (elem, "PO"))
11599
            molstat.n_psg16++;
11600
          if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
11601
              || !strcmp (elem, "BR") || !strcmp (elem, "I ")
11602
              || !strcmp (elem, "AT"))
11603
            molstat.n_psg17++;
11604
          if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
11605
              || !strcmp (elem, "AR") || !strcmp (elem, "KR")
11606
              || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
11607
            molstat.n_psg18++;
11608
          if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
11609
              || !strcmp (elem, "LU") || !strcmp (elem, "LR")
11610
              || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
11611
              || !strcmp (elem, "HF") || !strcmp (elem, "RF")
11612
              || !strcmp (elem, "V ") || !strcmp (elem, "NB")
11613
              || !strcmp (elem, "TA") || !strcmp (elem, "DB")
11614
              || !strcmp (elem, "CR") || !strcmp (elem, "MO")
11615
              || !strcmp (elem, "W ") || !strcmp (elem, "SG")
11616
              || !strcmp (elem, "MN") || !strcmp (elem, "TC")
11617
              || !strcmp (elem, "RE") || !strcmp (elem, "BH")
11618
              || !strcmp (elem, "FE") || !strcmp (elem, "RU")
11619
              || !strcmp (elem, "OS") || !strcmp (elem, "HS")
11620
              || !strcmp (elem, "CO") || !strcmp (elem, "RH")
11621
              || !strcmp (elem, "IR") || !strcmp (elem, "MT")
11622
              || !strcmp (elem, "NI") || !strcmp (elem, "PD")
11623
              || !strcmp (elem, "PT") || !strcmp (elem, "DS")
11624
              || !strcmp (elem, "CU") || !strcmp (elem, "AG")
11625
              || !strcmp (elem, "AU") || !strcmp (elem, "RG")
11626
              || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
11627
              || !strcmp (elem, "HG"))
11628
/* p2c: checkmol.pas, line 8439:
11629
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
11630
            molstat.n_pstm++;
11631
          if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
11632
              || !strcmp (elem, "PR") || !strcmp (elem, "ND")
11633
              || !strcmp (elem, "PM") || !strcmp (elem, "SM")
11634
              || !strcmp (elem, "EU") || !strcmp (elem, "GD")
11635
              || !strcmp (elem, "TB") || !strcmp (elem, "DY")
11636
              || !strcmp (elem, "HO") || !strcmp (elem, "ER")
11637
              || !strcmp (elem, "TM") || !strcmp (elem, "YB")
11638
              || !strcmp (elem, "AC") || !strcmp (elem, "TH")
11639
              || !strcmp (elem, "PA") || !strcmp (elem, "U ")
11640
              || !strcmp (elem, "NP") || !strcmp (elem, "PU")
11641
              || !strcmp (elem, "AM") || !strcmp (elem, "CM")
11642
              || !strcmp (elem, "BK") || !strcmp (elem, "CF")
11643
              || !strcmp (elem, "ES") || !strcmp (elem, "FM")
11644
              || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
11645
/* p2c: checkmol.pas, line 8439:
11646
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
11647
            molstat.n_psla++;
11648
          /*$ENDIF */
11649
        }                       /* is heavy */
11650
    }                           /* atoms */
11651
  if (n_bonds > 0)
11652
    {
11653
      FORLIM = n_bonds;
11654
      for (i = 0; i < FORLIM; i++)
11655
        {
11656
          a1 = bond[i].a1;
11657
          a2 = bond[i].a2;
11658
          strcpy (a1el, atom[a1 - 1].element);
11659
          strcpy (a2el, atom[a2 - 1].element);
11660
          btype = bond[i].btype;
11661
          if (bond[i].arom)
11662
            molstat.n_bar++;
11663
          else
11664
            {
11665
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
11666
                molstat.n_b1++;
11667
              if (btype == 'D')
11668
                molstat.n_b2++;
11669
              if (btype == 'T')
11670
                molstat.n_b3++;
11671
            }
11672
          /* v0.3n: ignore bonds to (explicit) hydrogens */
11673
          if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
11674
              (!strcmp (a1el, "O ") && !strcmp (a2el, "C ")))
11675
            {
11676
              if (btype == 'S')
11677
                molstat.n_C1O++;
11678
              if (btype == 'D')
11679
                molstat.n_C2O++;
11680
            }
11681
          if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
11682
              (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
11683
            molstat.n_CN++;
11684
          if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
11685
              && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
11686
            molstat.n_XY++;
11687
          /* new in v0.3n: number of bonds belonging to more than one ring */
11688
          if (bond[i].ring_count > 1)
11689
            molstat.n_br2p++;
11690
        }
11691
    }                           /* bonds */
11692
  if (n_rings <= 0)
11693
    {
11694
      return;
11695
    }                           /* rings */
11696
  /* v0.3n */
11697
  n_countablerings = 0;         /* v0.3n */
11698
  FORLIM = n_rings;
11699
  for (i = 1; i <= FORLIM; i++)
11700
    {
11701
      if (ringprop[i - 1].envelope == false)    /* v0.3n */
11702
        n_countablerings++;
11703
      if (is_arene (i) && ringprop[i - 1].envelope == false)
11704
        {                       /* v0.3n: ignore envelope rings */
11705
          molstat.n_rAr++;
11706
          if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == false))
11707
            /* v0.3l */
11708
            molstat.n_rBz++;
11709
        }
11710
      get_ringstat (i);
11711
      if (ringprop[i - 1].arom == true && ringprop[i - 1].envelope == false)
11712
        /* new in v0.3n; replaces assignment below */
11713
        n_b2formal++;
11714
    }
11715
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
11716
  /* in order to allow an isolated double bond in the needle */
11717
  /* to be matched as a ring fragment of an aromatic ring */
11718
  if (n_b2formal > molstat.n_bar / 2)
11719
    n_b2formal = molstat.n_bar / 2;
11720
  molstat.n_b2 += n_b2formal;
11721
}
11722
 
11723
 
11724
static void
11725
fix_ssr_ringcounts ()
11726
{
11727
  /* new in v0.3n */
11728
  /* if SAR -> SSR fallback happens, set some molstat values */
11729
  /* to a maximum (ring counts for various ring sizes); */
11730
  /* this should be necessary only for ring sizes which */
11731
  /* are a) too large for the SSR (depending on ssr_vringsize) */
11732
  /* and b) which are likely to contain "envelope rings" */
11733
  /* (size 6 and above) */
11734
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
11735
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
11736
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
11737
  if (molstat.n_r6 == 0)
11738
    molstat.n_r6 = max_rings;
11739
  if (molstat.n_r7 == 0)
11740
    molstat.n_r7 = max_rings;
11741
  if (molstat.n_r8 == 0)
11742
    molstat.n_r8 = max_rings;
11743
  if (molstat.n_r9 == 0)
11744
    molstat.n_r9 = max_rings;
11745
  if (molstat.n_r10 == 0)
11746
    molstat.n_r10 = max_rings;
11747
  if (molstat.n_r11 == 0)
11748
    molstat.n_r11 = max_rings;
11749
  if (molstat.n_r12 == 0)
11750
    molstat.n_r12 = max_rings;
11751
  if (molstat.n_r13p == 0)
11752
    molstat.n_r13p = max_rings;
11753
}
11754
 
11755
 
11756
 
11757
static void
11758
write_molstat ()
11759
{
11760
  if (auto_ssr)                 /* v0.3n */
11761
    fix_ssr_ringcounts ();
11762
  printf ("n_atoms:%d;", n_heavyatoms);
11763
  /* count only non-H atoms (some molfiles contain explicit H's) */
11764
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
11765
    printf ("n_bonds:%d;", n_heavybonds);
11766
/* p2c: checkmol.pas, line 8471:
11767
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11768
#ifdef REDUCED_SAR
11769
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
11770
    printf ("n_rings:%d;", n_countablerings);
11771
#else
11772
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
11773
    printf ("n_rings:%d;", n_rings);
11774
#endif
11775
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
11776
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
11777
  if (molstat.n_chg > 0)        /* 0.3x */
11778
    printf ("n_chg:%d;", molstat.n_chg);
11779
 
11780
  if (molstat.n_C1 > 0)
11781
    printf ("n_C1:%d;", molstat.n_C1);
11782
  if (molstat.n_C2 > 0)
11783
    printf ("n_C2:%d;", molstat.n_C2);
11784
  /* requirement of a given number of sp3 carbons might be too restrictive, */
11785
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
11786
  if (molstat.n_C > 0)
11787
    printf ("n_C:%d;", molstat.n_C);
11788
  if (molstat.n_CHB1p > 0)
11789
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
11790
  if (molstat.n_CHB2p > 0)
11791
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
11792
  if (molstat.n_CHB3p > 0)
11793
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
11794
  if (molstat.n_CHB4 > 0)
11795
    printf ("n_CHB4:%d;", molstat.n_CHB4);
11796
  if (molstat.n_O2 > 0)
11797
    printf ("n_O2:%d;", molstat.n_O2);
11798
  if (molstat.n_O3 > 0)
11799
    printf ("n_O3:%d;", molstat.n_O3);
11800
  if (molstat.n_N1 > 0)
11801
    printf ("n_N1:%d;", molstat.n_N1);
11802
  if (molstat.n_N2 > 0)
11803
    printf ("n_N2:%d;", molstat.n_N2);
11804
  if (molstat.n_N3 > 0)
11805
    printf ("n_N3:%d;", molstat.n_N3);
11806
  if (molstat.n_S > 0)
11807
    printf ("n_S:%d;", molstat.n_S);
11808
  if (molstat.n_SeTe > 0)
11809
    printf ("n_SeTe:%d;", molstat.n_SeTe);
11810
  if (molstat.n_F > 0)
11811
    printf ("n_F:%d;", molstat.n_F);
11812
  if (molstat.n_Cl > 0)
11813
    printf ("n_Cl:%d;", molstat.n_Cl);
11814
  if (molstat.n_Br > 0)
11815
    printf ("n_Br:%d;", molstat.n_Br);
11816
  if (molstat.n_I > 0)
11817
    printf ("n_I:%d;", molstat.n_I);
11818
  if (molstat.n_P > 0)
11819
    printf ("n_P:%d;", molstat.n_P);
11820
  if (molstat.n_B > 0)
11821
    printf ("n_B:%d;", molstat.n_B);
11822
  if (molstat.n_Met > 0)
11823
    printf ("n_Met:%d;", molstat.n_Met);
11824
  if (molstat.n_X > 0)
11825
    printf ("n_X:%d;", molstat.n_X);
11826
  if (molstat.n_b1 > 0)
11827
    printf ("n_b1:%d;", molstat.n_b1);
11828
  if (molstat.n_b2 > 0)
11829
    printf ("n_b2:%d;", molstat.n_b2);
11830
  if (molstat.n_b3 > 0)
11831
    printf ("n_b3:%d;", molstat.n_b3);
11832
  if (molstat.n_bar > 0)
11833
    printf ("n_bar:%d;", molstat.n_bar);
11834
  if (molstat.n_C1O > 0)
11835
    printf ("n_C1O:%d;", molstat.n_C1O);
11836
  if (molstat.n_C2O > 0)
11837
    printf ("n_C2O:%d;", molstat.n_C2O);
11838
  if (molstat.n_CN > 0)
11839
    printf ("n_CN:%d;", molstat.n_CN);
11840
  if (molstat.n_XY > 0)
11841
    printf ("n_XY:%d;", molstat.n_XY);
11842
  if (molstat.n_r3 > 0)
11843
    printf ("n_r3:%d;", molstat.n_r3);
11844
  if (molstat.n_r4 > 0)
11845
    printf ("n_r4:%d;", molstat.n_r4);
11846
  if (molstat.n_r5 > 0)
11847
    printf ("n_r5:%d;", molstat.n_r5);
11848
  if (molstat.n_r6 > 0)
11849
    printf ("n_r6:%d;", molstat.n_r6);
11850
  if (molstat.n_r7 > 0)
11851
    printf ("n_r7:%d;", molstat.n_r7);
11852
  if (molstat.n_r8 > 0)
11853
    printf ("n_r8:%d;", molstat.n_r8);
11854
  if (molstat.n_r9 > 0)
11855
    printf ("n_r9:%d;", molstat.n_r9);
11856
  if (molstat.n_r10 > 0)
11857
    printf ("n_r10:%d;", molstat.n_r10);
11858
  if (molstat.n_r11 > 0)
11859
    printf ("n_r11:%d;", molstat.n_r11);
11860
  if (molstat.n_r12 > 0)
11861
    printf ("n_r12:%d;", molstat.n_r12);
11862
  if (molstat.n_r13p > 0)
11863
    printf ("n_r13p:%d;", molstat.n_r13p);
11864
  if (molstat.n_rN > 0)
11865
    printf ("n_rN:%d;", molstat.n_rN);
11866
  if (molstat.n_rN1 > 0)
11867
    printf ("n_rN1:%d;", molstat.n_rN1);
11868
  if (molstat.n_rN2 > 0)
11869
    printf ("n_rN2:%d;", molstat.n_rN2);
11870
  if (molstat.n_rN3p > 0)
11871
    printf ("n_rN3p:%d;", molstat.n_rN3p);
11872
  if (molstat.n_rO > 0)
11873
    printf ("n_rO:%d;", molstat.n_rO);
11874
  if (molstat.n_rO1 > 0)
11875
    printf ("n_rO1:%d;", molstat.n_rO1);
11876
  if (molstat.n_rO2p > 0)
11877
    printf ("n_rO2p:%d;", molstat.n_rO2p);
11878
  if (molstat.n_rS > 0)
11879
    printf ("n_rS:%d;", molstat.n_rS);
11880
  if (molstat.n_rX > 0)
11881
    printf ("n_rX:%d;", molstat.n_rX);
11882
  if (molstat.n_rAr > 0)
11883
    printf ("n_rar:%d;", molstat.n_rAr);
11884
/* p2c: checkmol.pas, line 8532:
11885
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11886
  /*$IFDEF extended_molstat */
11887
  if (molstat.n_rBz > 0)
11888
    printf ("n_rbz:%d;", molstat.n_rBz);
11889
  if (molstat.n_br2p > 0)
11890
    printf ("n_br2p:%d;", molstat.n_br2p);
11891
  if (molstat.n_psg01 > 0)
11892
    printf ("n_psg01:%d;", molstat.n_psg01);
11893
  if (molstat.n_psg02 > 0)
11894
    printf ("n_psg02:%d;", molstat.n_psg02);
11895
  if (molstat.n_psg13 > 0)
11896
    printf ("n_psg13:%d;", molstat.n_psg13);
11897
  if (molstat.n_psg14 > 0)
11898
    printf ("n_psg14:%d;", molstat.n_psg14);
11899
  if (molstat.n_psg15 > 0)
11900
    printf ("n_psg15:%d;", molstat.n_psg15);
11901
  if (molstat.n_psg16 > 0)
11902
    printf ("n_psg16:%d;", molstat.n_psg16);
11903
  if (molstat.n_psg17 > 0)
11904
    printf ("n_psg17:%d;", molstat.n_psg17);
11905
  if (molstat.n_psg18 > 0)
11906
    printf ("n_psg18:%d;", molstat.n_psg18);
11907
  if (molstat.n_pstm > 0)
11908
    printf ("n_pstm:%d;", molstat.n_pstm);
11909
  if (molstat.n_psla > 0)
11910
    printf ("n_psla:%d;", molstat.n_psla);
11911
  if (molstat.n_iso > 0)
11912
    printf ("n_iso:%d;", molstat.n_iso);
11913
  if (molstat.n_rad > 0)
11914
    printf ("n_rad:%d;", molstat.n_rad);
11915
  /*$ENDIF */
11916
  putchar ('\n');
11917
}
11918
 
11919
 
11920
static void
11921
write_molstat_X ()
11922
{
11923
  if (auto_ssr)                 /* v0.3n */
11924
    fix_ssr_ringcounts ();
11925
/* p2c: checkmol.pas, line 8556:
11926
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11927
#ifdef REDUCED_SAR
11928
  printf ("%d,", n_heavyatoms);
11929
  printf ("%d,", n_heavybonds);
11930
  printf ("%d,", n_countablerings);
11931
  /* v0.3n: n_rings =?> n_countablerings */
11932
#else
11933
  printf ("%d,", n_heavyatoms);
11934
  printf ("%d,", n_heavybonds);
11935
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
11936
#endif
11937
  printf ("%d,", molstat.n_QA);
11938
  printf ("%d,", molstat.n_QB);
11939
 
11940
  /* 0.3x */
11941
  printf ("%d,", molstat.n_chg);
11942
 
11943
 
11944
  printf ("%d,", molstat.n_C1);
11945
  printf ("%d,", molstat.n_C2);
11946
  printf ("%d,", molstat.n_C);
11947
  printf ("%d,", molstat.n_CHB1p);
11948
  printf ("%d,", molstat.n_CHB2p);
11949
  printf ("%d,", molstat.n_CHB3p);
11950
  printf ("%d,", molstat.n_CHB4);
11951
  printf ("%d,", molstat.n_O2);
11952
  printf ("%d,", molstat.n_O3);
11953
  printf ("%d,", molstat.n_N1);
11954
  printf ("%d,", molstat.n_N2);
11955
  printf ("%d,", molstat.n_N3);
11956
  printf ("%d,", molstat.n_S);
11957
  printf ("%d,", molstat.n_SeTe);
11958
  printf ("%d,", molstat.n_F);
11959
  printf ("%d,", molstat.n_Cl);
11960
  printf ("%d,", molstat.n_Br);
11961
  printf ("%d,", molstat.n_I);
11962
  printf ("%d,", molstat.n_P);
11963
  printf ("%d,", molstat.n_B);
11964
  printf ("%d,", molstat.n_Met);
11965
  printf ("%d,", molstat.n_X);
11966
  printf ("%d,", molstat.n_b1);
11967
  printf ("%d,", molstat.n_b2);
11968
  printf ("%d,", molstat.n_b3);
11969
  printf ("%d,", molstat.n_bar);
11970
  printf ("%d,", molstat.n_C1O);
11971
  printf ("%d,", molstat.n_C2O);
11972
  printf ("%d,", molstat.n_CN);
11973
  printf ("%d,", molstat.n_XY);
11974
  printf ("%d,", molstat.n_r3);
11975
  printf ("%d,", molstat.n_r4);
11976
  printf ("%d,", molstat.n_r5);
11977
  printf ("%d,", molstat.n_r6);
11978
  printf ("%d,", molstat.n_r7);
11979
  printf ("%d,", molstat.n_r8);
11980
  printf ("%d,", molstat.n_r9);
11981
  printf ("%d,", molstat.n_r10);
11982
  printf ("%d,", molstat.n_r11);
11983
  printf ("%d,", molstat.n_r12);
11984
  printf ("%d,", molstat.n_r13p);
11985
  printf ("%d,", molstat.n_rN);
11986
  printf ("%d,", molstat.n_rN1);
11987
  printf ("%d,", molstat.n_rN2);
11988
  printf ("%d,", molstat.n_rN3p);
11989
  printf ("%d,", molstat.n_rO);
11990
  printf ("%d,", molstat.n_rO1);
11991
  printf ("%d,", molstat.n_rO2p);
11992
  printf ("%d,", molstat.n_rS);
11993
  printf ("%d,", molstat.n_rX);
11994
  printf ("%d", molstat.n_rAr);
11995
/* p2c: checkmol.pas, line 8579:
11996
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11997
  /*$IFDEF extended_molstat */
11998
  printf (",%d", molstat.n_rBz);
11999
  printf (",%d", molstat.n_br2p);
12000
  printf (",%d", molstat.n_psg01);
12001
  printf (",%d", molstat.n_psg02);
12002
  printf (",%d", molstat.n_psg13);
12003
  printf (",%d", molstat.n_psg14);
12004
  printf (",%d", molstat.n_psg15);
12005
  printf (",%d", molstat.n_psg16);
12006
  printf (",%d", molstat.n_psg17);
12007
  printf (",%d", molstat.n_psg18);
12008
  printf (",%d", molstat.n_pstm);
12009
  printf (",%d", molstat.n_psla);
12010
  printf (",%d", molstat.n_iso);
12011
  printf (",%d\n", molstat.n_rad);
12012
  /*$ENDIF */
12013
}
12014
 
12015
 
12016
/* routines for substructure matching */
12017
 
12018
 
12019
static int
12020
find_ndl_ref_atom ()
12021
{
6786 kbelabas 12022
  int i;
6785 bpr 12023
  int score = -1, index = 0;
12024
  int n_nb, n_hc, FORLIM;
12025
 
12026
  /* finds a characteristic atom in the needle molecule, */
12027
  /* i.e., one with as many substituents as possible and */
12028
  /* with as many heteroatom substitutents as possible; */
12029
  /* added in v0.2d: make sure that reference atom is a heavy atom */
12030
  /* and not (accidentally) an explicit hydrogen; */
12031
  /* new in v0.3d: special treatment in case of E/Z geometry search */
12032
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
12033
  /* matchpath, regardless where the recursive search starts; */
12034
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
12035
  /* added in v0.3o: needle atom must be "tagged" in order to be */
12036
  /* selected (prevents unconnected fragments from being overlooked) */
12037
  if (ndl_n_atoms == 0)
6786 kbelabas 12038
    return false;
6785 bpr 12039
  if (ez_search && ndl_n_heavyatoms > 2)
12040
    {
12041
      FORLIM = ndl_n_atoms;
12042
      for (i = 1; i <= FORLIM; i++)
12043
        {                       /* ignore sp2-carbons if not aromatic */
12044
          /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = true)) then */
12045
          if (ndl_alkene_C (i) == false && ndl_atom[i - 1].tag)
12046
            {                   /* v0.3o */
12047
              n_nb = ndl_atom[i - 1].neighbor_count;
12048
              n_hc = ndl_hetatom_count (i);
12049
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy)
12050
                {
12051
                  /* v0.3j */
12052
                  index = i;
12053
                  score = n_nb * 11 + n_hc * 7; /* changed in v0.3j */
12054
                }
12055
            }
12056
        }
12057
    }
12058
  /* it is possible that no suitable reference atom has been found here */
12059
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
12060
  if (index == 0)
12061
    {
12062
      ez_search = false;        /* just in case it was true */
12063
      opt_geom = false;         /* just in case it was true */
12064
      FORLIM = ndl_n_atoms;
12065
      for (i = 1; i <= FORLIM; i++)
12066
        {
12067
          n_nb = ndl_atom[i - 1].neighbor_count;
12068
          n_hc = ndl_hetatom_count (i);
12069
          if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
12070
              ndl_atom[i - 1].tag)
12071
            {                   /* v0.3j */
12072
              index = i;
12073
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
12074
            }
12075
          /* v0.3o */
12076
        }
12077
    }
12078
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
12079
  if (index == 0)               /* just to be sure... */
12080
    index++;
12081
  return index;
12082
}
12083
 
12084
 
12085
static void
12086
cv_init ()
12087
{
12088
  /* new in v0.3j */
12089
  int i;
12090
 
12091
  if (cv == NULL)
12092
    return;
12093
  memset (cv, 0, sizeof (connval_type));
12094
 
12095
  for (i = 0; i < ndl_n_atoms; i++)
12096
    cv[i].def = ndl_atom[i].neighbor_count;
12097
}
12098
 
12099
 
12100
static int
12101
cv_count ()
12102
{
12103
  /* new in v0.3j, modified in v0.3m */
12104
  int i, j;
12105
  int cvlist[max_atoms];
12106
  int cvdef;
12107
  boolean isnew;
12108
  int entries = 0;
12109
  int FORLIM;
12110
 
12111
  if (cv == NULL)
12112
    return 0;
12113
  memset (cvlist, 0, sizeof (int) * max_atoms);
12114
  FORLIM = ndl_n_atoms;
12115
  for (i = 0; i < FORLIM; i++)
12116
    {
12117
      if (ndl_atom[i].heavy == true)
12118
        {
12119
          cvdef = cv[i].def;
12120
          isnew = true;
12121
          if (entries > 0)
12122
            {
12123
              for (j = 0; j < entries; j++)
12124
                {
12125
                  if (cvlist[j] == cvdef)
12126
                    isnew = false;
12127
                }
12128
            }
12129
          if (isnew)
12130
            {
12131
              entries++;
12132
              cvlist[entries - 1] = cvdef;
12133
            }
12134
          /* now we have a list of unique connection values */
12135
        }
12136
    }
12137
  return entries;
12138
}
12139
 
12140
 
12141
static int
12142
cv_iterate (n_cv_prev)
12143
     int n_cv_prev;
12144
{
12145
  /* new in v0.3j, modified in v0.3m */
6788 kbelabas 12146
  int i, j;
6785 bpr 12147
  neighbor_rec nb;
12148
  int nnb, nsum, n_cv, FORLIM;
12149
 
12150
  if (cv == NULL || ndl_n_atoms == 0)
6788 kbelabas 12151
    return false;
6785 bpr 12152
  FORLIM = ndl_n_atoms;
12153
  /* update the connection values (Morgan algorithm) */
12154
 
12155
  memset (nb, 0, sizeof (neighbor_rec));
12156
 
12157
  for (i = 1; i <= FORLIM; i++)
12158
    {
12159
      if (ndl_atom[i - 1].heavy == true)
12160
        {
12161
          get_ndl_neighbors (nb, i);
12162
          nnb = ndl_atom[i - 1].neighbor_count;
12163
          nsum = 0;
12164
          if (nnb > 0)
12165
            {
12166
              for (j = 0; j < nnb; j++)
12167
                {
12168
                  if (ndl_atom[nb[j] - 1].heavy == true)
12169
                    nsum += cv[nb[j] - 1].def;
12170
                }
12171
            }
12172
          cv[i - 1].tmp = nsum;
12173
        }
12174
    }
12175
  n_cv = cv_count ();
12176
  if (n_cv > n_cv_prev)
12177
    {
12178
      FORLIM = ndl_n_atoms;
12179
      for (i = 0; i < FORLIM; i++)
12180
        cv[i].def = cv[i].tmp;
12181
    }
12182
  return n_cv;
12183
}
12184
 
12185
 
12186
static int
12187
find_ndl_ref_atom_cv ()
12188
{
12189
  /* new in v0.3j, modified in v0.3m */
12190
  int Result, i;
12191
  int res = 1, it = 0;
12192
  int n_cv;
12193
  int n_cv_prev = 0;
12194
  boolean finished = false;
12195
  int cvmax = 0;
12196
  int FORLIM;
12197
 
12198
  if (ndl_n_atoms == 0)
12199
    return 0;
12200
  /* try */
12201
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
12202
  /* except
12203
     on e:Eoutofmemory do
12204
     begin
12205
     res := find_ndl_ref_atom;
12206
     $IFDEF debug
12207
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
12208
     $ENDIF
12209
     end;
12210
     end; */
12211
  cv_init ();
12212
  do
12213
    {
12214
      it++;                     /* iteration counter (a safeguard against infinite loops) */
12215
      n_cv = cv_iterate (n_cv_prev);
12216
      if (n_cv <= n_cv_prev)
12217
        finished = true;
12218
      n_cv_prev = n_cv;
12219
    }
12220
  while (!(finished || it > 10000));
12221
  FORLIM = ndl_n_atoms;
12222
  /* now that we have canonical connection values (Morgan algorithm), */
12223
  /* pick the atom with the highest value */
12224
  /* added in v0.3o: atom must be "tagged" */
12225
  for (i = 1; i <= FORLIM; i++)
12226
    {
12227
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
12228
      if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == false ||
12229
                                       ez_search == false))
12230
          && ndl_atom[i - 1].tag)
12231
        {                       /* v0.3o */
12232
          cvmax = cv[i - 1].def;
12233
          res = i;
12234
        }
12235
    }
12236
  Result = res;
12237
  /* try */
12238
  if (cv != NULL)
12239
    {
12240
      free (cv);
12241
      cv = NULL;
12242
    }
12243
  /* except
12244
     on e:Einvalidpointer do begin end;
12245
     end; */
12246
  return Result;
12247
}
12248
 
12249
 
12250
static boolean
12251
atomtypes_OK_strict (ndl_a, hst_a)
12252
     int ndl_a, hst_a;
12253
{
12254
  /* new in v0.2f */
12255
  str2 ndl_el;
12256
  str3 ndl_atype;
12257
  str2 hst_el;
12258
  str3 hst_atype;
12259
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
12260
  boolean res = false;
12261
 
12262
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
12263
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
12264
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
12265
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
12266
  strcpy (hst_el, atom[hst_a - 1].element);
12267
  strcpy (hst_atype, atom[hst_a - 1].atype);
12268
  hst_nbc = atom[hst_a - 1].neighbor_count;
12269
  hst_Htot = atom[hst_a - 1].Htot;
12270
  /* v0.3o: formal charges must be the same */
12271
 
12272
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12273
    return false;
12274
 
12275
  /* v0.3x: isotope nucleon numbers must be the same */
12276
 
12277
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
12278
    return false;
12279
 
12280
  /* v0.3x: radicals must be the same */
12281
 
12282
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12283
    return false;
12284
 
12285
  if (!strcmp (ndl_atype, hst_atype))
12286
    res = true;
12287
  else
12288
    {
12289
      if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom &&
12290
          atom[hst_a - 1].arom)
12291
        res = true;
12292
      if (ndl_querymol
12293
          && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
12294
        res = true;             /* 0.3 p */
12295
    }
12296
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
12297
    res = true;
12298
  if (!strcmp (ndl_el, "Q "))
12299
    {
12300
      if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
12301
        res = true;
12302
    }
12303
  if (!strcmp (ndl_el, "X "))
12304
    {
12305
      if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
12306
          !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
12307
          || !strcmp (hst_el, "AT"))
12308
        res = true;
12309
    }
12310
  /* if needle atom has more substituents than haystack atom ==> no match */
12311
  if (ndl_nbc > hst_nbc)
12312
    res = false;
12313
  /* check for explicit hydrogens */
12314
  if (ndl_Hexp > hst_Htot)
12315
    res = false;
12316
/* p2c: checkmol.pas, line 8859:
12317
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12318
  /*$IFDEF debug */
12319
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
12320
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
12321
  /*$ENDIF */
12322
  /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
12323
  if (opt_fp)
12324
    {
12325
      if (strcmp (ndl_el, hst_el))
12326
        res = false;
12327
    }
12328
  return res;
12329
}
12330
 
12331
 
12332
static boolean
12333
atomtypes_OK (ndl_a, hst_a)
12334
     int ndl_a, hst_a;
12335
{
12336
  str2 ndl_el, hst_el;
12337
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
12338
  boolean res = false;
12339
 
12340
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
12341
    return false;
12342
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
12343
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
12344
  /* are tolerated (this is a feature, not a bug) */
12345
  if (opt_chg)
12346
    {
12347
      if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12348
        return false;
12349
    }
12350
//  else
12351
//    {
12352
//      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
12353
//        atom[hst_a - 1].formal_charge != 0 &&
12354
//        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12355
//      return false;
12356
//    }
12357
//
12358
//  /* v0.3x: isotopes must be the same */
12359
  if (opt_iso)
12360
    {
12361
      if (ndl_atom[ndl_a - 1].nucleon_number !=
12362
          atom[hst_a - 1].nucleon_number)
12363
        return false;
12364
    }
12365
//  else
12366
//    {
12367
//      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
12368
//        atom[hst_a - 1].nucleon_number != 0 &&
12369
//        ndl_atom[ndl_a - 1].nucleon_number !=
12370
//        atom[hst_a - 1].nucleon_number)
12371
//      return false;
12372
//    }
12373
//
12374
//  /* v0.3x: radicals must be the same */
12375
  if (opt_rad)
12376
    {
12377
      if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12378
        return false;
12379
    }
12380
//  else
12381
//    {
12382
//      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
12383
//        atom[hst_a - 1].radical_type != 0 &&
12384
//        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12385
//      return false;
12386
//    }
12387
 
12388
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
12389
  if (opt_exact && atom[hst_a - 1].tag == true)
12390
    {
12391
/* p2c: checkmol.pas, line 8899:
12392
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12393
      /*$IFDEF debug */
12394
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
12395
      /*$ENDIF */
12396
      return false;
12397
    }
12398
  if (opt_strict)               /* new in v0.2f */
12399
    return (atomtypes_OK_strict (ndl_a, hst_a));
12400
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
12401
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
12402
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
12403
  strcpy (hst_el, atom[hst_a - 1].element);
12404
  hst_nbc = atom[hst_a - 1].neighbor_count;
12405
  hst_Htot = atom[hst_a - 1].Htot;
12406
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
12407
    res = true;
12408
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
12409
    res = true;
12410
  if (!strcmp (ndl_el, "Q "))
12411
    {
12412
      if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
12413
        res = true;
12414
    }
12415
  if (!strcmp (ndl_el, "X "))
12416
    {
12417
      if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
12418
          !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
12419
          || !strcmp (hst_el, "AT"))
12420
        res = true;
12421
    }
12422
  /* v0.3o: in exact mode, check for identical neighbor_count */
12423
  if (opt_exact)
12424
    {
12425
      if (ndl_nbc != hst_nbc)
12426
        {
12427
          res = false;
12428
/* p2c: checkmol.pas, line 8934:
12429
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12430
          /*$IFDEF debug */
12431
          //debugoutput
12432
          //  ("exact match failed: different number of neighbor atoms");
12433
          /*$ENDIF */
12434
        }
12435
    }
12436
  /* if needle atom has more substituents than haystack atom ==> no match */
12437
  if (ndl_nbc > hst_nbc)
12438
    res = false;
12439
  /* check for explicit hydrogens */
12440
  if (ndl_Hexp > hst_Htot)
12441
    res = false;
12442
/* p2c: checkmol.pas, line 8943:
12443
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12444
  /*$IFDEF debug */
12445
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
12446
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
12447
  /*$ENDIF */
12448
  return res;
12449
}
12450
 
12451
 
12452
static boolean
12453
bondtypes_OK_strict (ndl_b, hst_b)
12454
     int ndl_b, hst_b;
12455
{
12456
  boolean ndl_arom, hst_arom;
12457
  char ndl_btype, hst_btype;
12458
  int ndl_rc;                   /* new in v0.3d */
12459
  int hst_rc;                   /* new in v0.3d */
12460
  int ndl_btopo;                /* new in v0.3d */
12461
  boolean res = false;
12462
/* p2c: checkmol.pas, line 8960:
12463
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12464
  /*$IFDEF debug */
12465
  /*char na[256]; char ha[256];*/
12466
  char tstr[256];
12467
 
12468
  /*$ENDIF */
12469
/* p2c: checkmol.pas, line 8966:
12470
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12471
  /*$IFDEF debug */
12472
  *tstr = '\0';                 /* for debugging purposes only */
12473
  /*$ENDIF */
12474
  ndl_arom = ndl_bond[ndl_b - 1].arom;
12475
  ndl_btype = ndl_bond[ndl_b - 1].btype;
12476
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
12477
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
12478
  hst_arom = bond[hst_b - 1].arom;
12479
  hst_btype = bond[hst_b - 1].btype;
12480
  hst_rc = bond[hst_b - 1].ring_count;
12481
/* p2c: checkmol.pas, line 8976:
12482
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12483
  /*$IFDEF debug */
12484
  /*if (ndl_arom)
12485
    strcpy (na, "(ar)");
12486
  else
12487
    *na = '\0';
12488
  if (hst_arom)
12489
    strcpy (ha, "(ar)");
12490
  else
12491
    *ha = '\0';*/
12492
  /*$ENDIF */
12493
  if (ndl_arom == true && hst_arom == true)
12494
    res = true;
12495
  if (ndl_arom == false && hst_arom == false)
12496
    {
12497
      if (ndl_btype == hst_btype)
12498
        res = true;
12499
      if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
12500
        res = true;
12501
      if (ndl_btype == 's' && hst_btype == 'S')
12502
        res = true;
12503
      if (ndl_btype == 'd' && hst_btype == 'D')
12504
        res = true;
12505
    }
12506
  /* a little exception: */
12507
  if (ndl_arom == false && hst_arom == true)
12508
    {
12509
      if (ndl_btype == 'A')
12510
        res = true;
12511
      if (ndl_btype == 's' || ndl_btype == 'd')
12512
        res = true;
12513
      if (ndl_bond[ndl_b - 1].q_arom)
12514
        res = true;             /* 0.3p */
12515
    }
12516
  if (ndl_btype == 'a')
12517
    res = true;
12518
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
12519
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc)
12520
    {
12521
      if (ndl_rc != hst_rc)
12522
        {
12523
          res = false;          /* this excludes further ring annulations as well as */
12524
/* p2c: checkmol.pas, line 9001:
12525
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12526
          /*$IFDEF debug */
12527
          /* open-chains query structures to be found in rings */
12528
          /*
12529
             tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
12530
          /*$ENDIF */
12531
        }
12532
    }
12533
  else
12534
    {
12535
      if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
12536
        {
12537
          res = false;
12538
/* p2c: checkmol.pas, line 9010:
12539
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12540
          /*$IFDEF debug */
12541
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
12542
          /*$ENDIF */
12543
        }
12544
    }
12545
/* p2c: checkmol.pas, line 9015:
12546
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12547
  /*$IFDEF debug */
12548
  /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
12549
     debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
12550
  /*$ENDIF */
12551
  return res;
12552
}
12553
 
12554
 
12555
static boolean
12556
bondtypes_OK (ndl_b, hst_b)
12557
     int ndl_b, hst_b;
12558
{
12559
  boolean ndl_arom, hst_arom;
12560
  char ndl_btype, hst_btype;
12561
  int ndl_rc;                   /* new in v0.3d */
12562
  int hst_rc;                   /* new in v0.3d */
12563
  int ndl_btopo;                /* new in v0.3d */
12564
  boolean res = false;
12565
/* p2c: checkmol.pas, line 9032:
12566
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12567
  /*$IFDEF debug */
12568
  /*char na[256], ha[256];*/
12569
  char tstr[256];
12570
  /*$ENDIF */
12571
  int a1, a2;
12572
  str2 a1_el, a2_el;
12573
 
12574
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
12575
    return false;
12576
  if (opt_strict)               /* new in v0.2f */
12577
    return (bondtypes_OK_strict (ndl_b, hst_b));
12578
/* p2c: checkmol.pas, line 9051:
12579
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12580
  /*$IFDEF debug */
12581
  *tstr = '\0';                 /* for debug purposes only */
12582
  /*$ENDIF */
12583
  ndl_arom = ndl_bond[ndl_b - 1].arom;
12584
  ndl_btype = ndl_bond[ndl_b - 1].btype;
12585
  hst_arom = bond[hst_b - 1].arom;
12586
  hst_btype = bond[hst_b - 1].btype;
12587
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
12588
  hst_rc = bond[hst_b - 1].ring_count;
12589
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
12590
/* p2c: checkmol.pas, line 9061:
12591
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12592
  /*$IFDEF debug */
12593
  //if (ndl_arom)
12594
//    strcpy (na, "(ar)");
12595
//  else
12596
//    *na = '\0';
12597
//  if (hst_arom)
12598
//    strcpy (ha, "(ar)");
12599
//  else
12600
//    *ha = '\0';
12601
  /*$ENDIF */
12602
  if (ndl_arom == true && hst_arom == true)
12603
    res = true;
12604
  if (ndl_arom == false && hst_arom == false)
12605
    {
12606
      if (ndl_btype == hst_btype)
12607
        res = true;
12608
      if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
12609
        res = true;
12610
      if (ndl_btype == 's' && hst_btype == 'S')
12611
        res = true;
12612
      if (ndl_btype == 'd' && hst_btype == 'D')
12613
        res = true;
12614
    }
12615
  /* a little exception: */
12616
  if (ndl_arom == false && hst_arom == true)
12617
    {
12618
      if (ndl_btype == 'A')
12619
        res = true;
12620
      if (ndl_btype == 's' || ndl_btype == 'd')
12621
        res = true;
12622
      if (ndl_btype == 'D')
12623
        {                       /* added in 0.2d: do not accept C=O etc. as C-O/arom */
12624
          a1 = ndl_bond[ndl_b - 1].a1;
12625
          a2 = ndl_bond[ndl_b - 1].a2;
12626
          strcpy (a1_el, ndl_atom[a1 - 1].element);
12627
          strcpy (a2_el, ndl_atom[a2 - 1].element);
12628
          if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
12629
              && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
12630
              && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
12631
              && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
12632
            res = true;
12633
        }
12634
      if (ndl_bond[ndl_b - 1].q_arom)
12635
        res = true;             /* 0.3p */
12636
    }
12637
  if (ndl_btype == 'a')
12638
    res = true;
12639
  /* new in v0.3d: obey topology requirements in query structure */
12640
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any)
12641
    {
12642
  if (ndl_btopo == btopo_ring && hst_rc == 0)
12643
    res = false;
12644
  if (ndl_btopo == btopo_chain && hst_rc > 0)
12645
    res = false;
12646
  if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
12647
    res = false;
12648
  if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
12649
    res = false;
12650
}    
12651
/* p2c: checkmol.pas, line 9098:
12652
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12653
  /*$IFDEF debug */
12654
  /* if res = false then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
12655
  /*$ENDIF */
12656
/* p2c: checkmol.pas, line 9102:
12657
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12658
  /*$IFDEF debug */
12659
  /*
12660
     if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
12661
     debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
12662
  /*$ENDIF */
12663
  return res;
12664
}
12665
 
12666
 
12667
static boolean
12668
matrix_OK (m, ndl_dim, hst_dim)
12669
boolean (*m)[max_neighbors];
12670
     int ndl_dim, hst_dim;
12671
{
12672
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
12673
  boolean mr = false;
12674
  matchmatrix lm;
12675
  int i, ii, j, lndl_dim, lhst_dim;
12676
 
12677
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
12678
      hst_dim > max_neighbors || ndl_dim > hst_dim)
12679
    return false;
12680
  if (ndl_dim == 1)
12681
    {
12682
      for (i = 0; i < hst_dim; i++)
12683
        {
12684
          if (m[0][i])
12685
            mr = true;
12686
        }
12687
      return mr;
12688
    }
12689
  for (i = 1; i <= hst_dim; i++)
12690
    {
12691
      if (m[0][i - 1])
12692
        {
12693
          /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
12694
          memset (lm, false, sizeof (matchmatrix));
12695
          for (j = 2; j <= ndl_dim; j++)
12696
            {
12697
              lhst_dim = 0;
12698
              for (ii = 1; ii <= hst_dim; ii++)
12699
                {
12700
                  if (ii != i)
12701
                    {
12702
                      lhst_dim++;
12703
                      lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
12704
                    }
12705
                }
12706
            }
12707
          lndl_dim = ndl_dim - 1;
12708
          if (matrix_OK (lm, lndl_dim, lhst_dim))
12709
            {                   /* recursive call to matrix_OK */
12710
              return true;
12711
              /* stop any further work immediately */
12712
            }
12713
        }
12714
    }
12715
  return false;
12716
}
12717
 
12718
 
12719
static boolean
12720
is_flat (angle_deg)
12721
     double angle_deg;
12722
{
12723
  /* new in v0.3j */
12724
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
12725
    return false;
12726
  else
12727
    return true;
12728
}
12729
 
12730
 
12731
static boolean
12732
chirality_OK (ndl_cp, hst_cp)
12733
     int *ndl_cp, *hst_cp;
12734
{
12735
  boolean res = true;
12736
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
12737
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
12738
  int level = 0;
12739
  int i;
12740
  boolean up = false, down = false, updown = false;
12741
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
12742
 
12743
  /* fill temporary atom variables */
12744
  ta1 = ndl_cp[0];              /* this is the central atom */
12745
  ta2 = ndl_cp[1];
12746
  ta3 = ndl_cp[2];
12747
  ta4 = ndl_cp[3];
12748
  /* first, get the central atom of the needle */
12749
  np2.x = ndl_atom[ta1 - 1].x;
12750
  np2.y = ndl_atom[ta1 - 1].y;
12751
  np2.z = ndl_atom[ta1 - 1].z;
12752
  /* next, do the same for all 3 substituent atoms */
12753
  np1.x = ndl_atom[ta2 - 1].x;
12754
  np1.y = ndl_atom[ta2 - 1].y;
12755
  np1.z = ndl_atom[ta2 - 1].z;
12756
  np3.x = ndl_atom[ta3 - 1].x;
12757
  np3.y = ndl_atom[ta3 - 1].y;
12758
  np3.z = ndl_atom[ta3 - 1].z;
12759
  np4.x = ndl_atom[ta4 - 1].x;
12760
  np4.y = ndl_atom[ta4 - 1].y;
12761
  np4.z = ndl_atom[ta4 - 1].z;
12762
  /* now check all needle bonds if we should care about up/down bonds */
12763
  if (ndl_n_bonds > 0)
12764
    {
12765
      FORLIM = ndl_n_bonds;
12766
      for (i = 0; i < FORLIM; i++)
12767
        {
12768
          if (ndl_bond[i].stereo == bstereo_up ||
12769
              ndl_bond[i].stereo == bstereo_down)
12770
            {
12771
              ba1 = ndl_bond[i].a1;
12772
              ba2 = ndl_bond[i].a2;
12773
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up)
12774
                {
12775
                  up = true;
12776
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12777
                    {
12778
                      updown = true;
12779
                      if (ba2 == ta2)
12780
                        np1.z += 0.8;
12781
                      if (ba2 == ta3)
12782
                        np3.z += 0.8;
12783
                      if (ba2 == ta4)
12784
                        np4.z += 0.8;
12785
                    }
12786
                  else
12787
                    level++;
12788
                }
12789
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down)
12790
                {
12791
                  down = true;
12792
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12793
                    {
12794
                      updown = true;
12795
                      if (ba2 == ta2)
12796
                        np1.z -= 0.8;
12797
                      if (ba2 == ta3)
12798
                        np3.z -= 0.8;
12799
                      if (ba2 == ta4)
12800
                        np4.z -= 0.8;
12801
                    }
12802
                  else
12803
                    level--;
12804
                }
12805
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up)
12806
                {
12807
                  down = true;
12808
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12809
                    {
12810
                      updown = true;
12811
                      if (ba1 == ta2)
12812
                        np1.z -= 0.8;
12813
                      if (ba1 == ta3)
12814
                        np3.z -= 0.8;
12815
                      if (ba1 == ta4)
12816
                        np4.z -= 0.8;
12817
                    }
12818
                  else
12819
                    level--;
12820
                }
12821
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down)
12822
                {
12823
                  up = true;
12824
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12825
                    {
12826
                      updown = true;
12827
                      if (ba1 == ta2)
12828
                        np1.z += 0.8;
12829
                      if (ba1 == ta3)
12830
                        np3.z += 0.8;
12831
                      if (ba1 == ta4)
12832
                        np4.z += 0.8;
12833
                    }
12834
                  else
12835
                    level++;
12836
                }
12837
            }
12838
        }                       /* for i ... */
12839
      if (updown == false && level != 0)
12840
        {
12841
          if (level > 0)
12842
            np2.z += 0.3;
12843
          if (level < 0)
12844
            np2.z -= 0.3;
12845
        }
12846
      else
12847
        {
12848
          if (up)
12849
            np2.z += 0.1;
12850
          if (down)
12851
            np2.z -= 0.1;
12852
        }
12853
    }
12854
  /* fill temporary atom variables again */
12855
  ta1 = hst_cp[0];
12856
  ta2 = hst_cp[1];
12857
  ta3 = hst_cp[2];
12858
  ta4 = hst_cp[3];
12859
  /* then, get the central atom of the haystack */
12860
  hp2.x = atom[ta1 - 1].x;
12861
  hp2.y = atom[ta1 - 1].y;
12862
  hp2.z = atom[ta1 - 1].z;
12863
  /* next, do the same for all 3 substituent atoms */
12864
  hp1.x = atom[ta2 - 1].x;
12865
  hp1.y = atom[ta2 - 1].y;
12866
  hp1.z = atom[ta2 - 1].z;
12867
  hp3.x = atom[ta3 - 1].x;
12868
  hp3.y = atom[ta3 - 1].y;
12869
  hp3.z = atom[ta3 - 1].z;
12870
  hp4.x = atom[ta4 - 1].x;
12871
  hp4.y = atom[ta4 - 1].y;
12872
  hp4.z = atom[ta4 - 1].z;
12873
  /* now check all haystack bonds if we should care about up/down bonds */
12874
  level = 0;
12875
  updown = false;
12876
  up = false;
12877
  down = false;
12878
  if (n_bonds > 0)
12879
    {
12880
      FORLIM = n_bonds;
12881
      for (i = 0; i < FORLIM; i++)
12882
        {
12883
          if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down)
12884
            {
12885
              ba1 = bond[i].a1;
12886
              ba2 = bond[i].a2;
12887
              if (ba1 == ta1 && bond[i].stereo == bstereo_up)
12888
                {
12889
                  up = true;
12890
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12891
                    {
12892
                      updown = true;
12893
                      if (ba2 == ta2)
12894
                        hp1.z += 0.8;
12895
                      if (ba2 == ta3)
12896
                        hp3.z += 0.8;
12897
                      if (ba2 == ta4)
12898
                        hp4.z += 0.8;
12899
                    }
12900
                  else
12901
                    level++;
12902
                }
12903
              if (ba1 == ta1 && bond[i].stereo == bstereo_down)
12904
                {
12905
                  down = true;
12906
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12907
                    {
12908
                      updown = true;
12909
                      if (ba2 == ta2)
12910
                        hp1.z -= 0.8;
12911
                      if (ba2 == ta3)
12912
                        hp3.z -= 0.8;
12913
                      if (ba2 == ta4)
12914
                        hp4.z -= 0.8;
12915
                    }
12916
                  else
12917
                    level--;
12918
                }
12919
              if (ba2 == ta1 && bond[i].stereo == bstereo_up)
12920
                {
12921
                  down = true;
12922
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12923
                    {
12924
                      updown = true;
12925
                      if (ba1 == ta2)
12926
                        hp1.z -= 0.8;
12927
                      if (ba1 == ta3)
12928
                        hp3.z -= 0.8;
12929
                      if (ba1 == ta4)
12930
                        hp4.z -= 0.8;
12931
                    }
12932
                  else
12933
                    level--;
12934
                }
12935
              if (ba2 == ta1 && bond[i].stereo == bstereo_down)
12936
                {
12937
                  up = true;
12938
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12939
                    {
12940
                      updown = true;
12941
                      if (ba1 == ta2)
12942
                        hp1.z += 0.8;
12943
                      if (ba1 == ta3)
12944
                        hp3.z += 0.8;
12945
                      if (ba1 == ta4)
12946
                        hp4.z += 0.8;
12947
                    }
12948
                  else
12949
                    level++;
12950
                }
12951
            }
12952
        }                       /* for i ... */
12953
      if (updown == false && level != 0)
12954
        {
12955
          if (level > 0)
12956
            hp2.z += 0.3;
12957
          if (level < 0)
12958
            hp2.z -= 0.3;
12959
        }
12960
      else
12961
        {
12962
          if (up)
12963
            hp2.z += 0.1;
12964
          if (down)
12965
            hp2.z -= 0.1;
12966
        }
12967
    }
12968
  /* get the pseudo-torsion angles */
12969
  ndl_ct = ctorsion (np1, np2, np3, np4);
12970
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
12971
  ndl_ct_deg = radtodeg (ndl_ct);
12972
  hst_ct_deg = radtodeg (hst_ct);
12973
  /* now do a plausibility check and finally check the sense */
12974
  /* (clockwise or counterclockwise) */
12975
  /*
12976
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
12977
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
12978
     (ndl_ct_deg * hst_ct_deg < 0) then res := false;
12979
   */
12980
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
12981
      ndl_ct_deg * hst_ct_deg < 0)
12982
    res = false;
12983
  if (rs_strict)
12984
    {
12985
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) |
12986
           (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
12987
          ndl_ct_deg * hst_ct_deg < 0)
12988
        res = false;
12989
    }
12990
  return res;
12991
}
12992
 
12993
 
12994
static boolean
12995
ndl_maybe_chiral (na)
12996
     int na;
12997
{
12998
  /* new in v0.3h */
12999
  boolean res = false;
13000
  str2 el;
13001
  str3 at;
13002
  int n_nb;
13003
 
13004
  strcpy (el, ndl_atom[na - 1].element);
13005
  strcpy (at, ndl_atom[na - 1].atype);
13006
  n_nb = ndl_atom[na - 1].neighbor_count;
13007
  if (!strcmp (at, "C3 ") && n_nb > 2)
13008
    res = true;
13009
  if (!strcmp (el, "N "))
13010
    {
13011
      if (!strcmp (at, "N3+") && n_nb == 4)
13012
        res = true;
13013
    }
13014
  if (!strcmp (el, "S "))
13015
    {                           /* sulfoxide */
13016
      if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
13017
        res = true;
13018
    }
13019
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
13020
    return res;
13021
  if (n_nb > 3)                 /* are we missing something here? */
13022
    res = true;
13023
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
13024
    res = false;
13025
  return res;
13026
}
13027
 
13028
 
13029
static boolean
13030
is_matching (ndl_xmp, hst_xmp)
13031
     int *ndl_xmp, *hst_xmp;
13032
{
13033
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
13034
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
13035
  int next_ndl_a, next_hst_a;
13036
  neighbor_rec ndl_nb, hst_nb;
13037
  matchmatrix mm;
13038
  int ndl_mp_len, hst_mp_len;
13039
  matchpath_type ndl_mp, hst_mp;
13040
  boolean emptyline, res, ndl_cis, hst_cis;
13041
  int na1, na2, na3, na4;       /* v0.3d */
13042
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
13043
  int prev_ndl_b;
13044
  int prev_hst_b;
13045
  p_3d p1, p2, p3, p4;
13046
  /*hst_torsion, ndl_torsion : double; */
13047
  chirpath_type ncp, hcp;
13048
  int n_hits, n_singlehits;
13049
/* p2c: checkmol.pas, line 9433:
13050
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13051
  /*$IFDEF debug */
13052
  //char tmpstr[256];
13053
 
13054
  /*$ENDIF */
13055
  /* initialize local matchpath variables */
13056
  //memset (ndl_mp, 0, sizeof (matchpath_type));
13057
  //memset (hst_mp, 0, sizeof (matchpath_type));
13058
  /* copy content of external variables into local ones */
13059
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
13060
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
13061
 
13062
  /*for (i = 0; i < max_matchpath_length; i++)
13063
     {
13064
     ndl_mp[i] = ndl_xmp[i];
13065
     hst_mp[i] = hst_xmp[i];
13066
     } */
13067
 
13068
 
13069
  ndl_mp_len = matchpath_length (ndl_mp);
13070
  hst_mp_len = matchpath_length (hst_mp);
13071
  if (ndl_mp_len != hst_mp_len)
13072
    {
13073
      /* this should never happen.... */
13074
/* p2c: checkmol.pas, line 9451:
13075
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13076
      /*$IFDEF debug */
13077
      //debugoutput ("needle and haystack matchpaths are of different length");
13078
      /*$ENDIF */
13079
      return false;
13080
    }
13081
  ndl_a = ndl_mp[ndl_mp_len - 1];
13082
  hst_a = hst_mp[hst_mp_len - 1];
13083
  ndl_atom[ndl_a - 1].tag = false;
13084
  /* new in v0.3o: mark the last needle atom as "visited" */
13085
  if (ndl_mp_len > 1)
13086
    {
13087
      prev_ndl_a = ndl_mp[ndl_mp_len - 2];
13088
      prev_hst_a = hst_mp[hst_mp_len - 2];
13089
    }
13090
  /* if geometry checking is on, check it here */
13091
  if (ez_search == true && ndl_mp_len > 3)
13092
    {
13093
      na1 = ndl_mp[ndl_mp_len - 1];
13094
      na2 = ndl_mp[ndl_mp_len - 2];
13095
      na3 = ndl_mp[ndl_mp_len - 3];
13096
      na4 = ndl_mp[ndl_mp_len - 4];
13097
      ha1 = hst_mp[hst_mp_len - 1];
13098
      ha2 = hst_mp[hst_mp_len - 2];
13099
      ha3 = hst_mp[hst_mp_len - 3];
13100
      ha4 = hst_mp[hst_mp_len - 4];
13101
      prev_ndl_b = get_ndl_bond (na2, na3);
13102
      prev_hst_b = get_bond (ha2, ha3);
13103
      if (ndl_bond[prev_ndl_b - 1].btype == 'D' &&
13104
          bond[prev_hst_b - 1].arom == false
13105
          && (ndl_bond[prev_ndl_b - 1].stereo !=
13106
              bstereo_double_either && bond[prev_hst_b - 1].stereo !=
13107
              bstereo_double_either)
13108
          /* 0.3x always match if needle and/or haystack bond is double_either */
13109
          &&
13110
          (!strcmp (atom[ha2 - 1].element, "C ")
13111
           || !strcmp (atom[ha2 - 1].element, "N "))
13112
          && (!strcmp (atom[ha3 - 1].element, "C ")
13113
              || !strcmp (atom[ha3 - 1].element, "N ")))
13114
        {                       /* v0.3g; check C=C, C=N, N=N bonds */
13115
          p1.x = atom[ha1 - 1].x;
13116
          p1.y = atom[ha1 - 1].y;
13117
          p1.z = atom[ha1 - 1].z;
13118
          p2.x = atom[ha2 - 1].x;
13119
          p2.y = atom[ha2 - 1].y;
13120
          p2.z = atom[ha2 - 1].z;
13121
          p3.x = atom[ha3 - 1].x;
13122
          p3.y = atom[ha3 - 1].y;
13123
          p3.z = atom[ha3 - 1].z;
13124
          p4.x = atom[ha4 - 1].x;
13125
          p4.y = atom[ha4 - 1].y;
13126
          p4.z = atom[ha4 - 1].z;
13127
          hst_cis = is_cis (p1, p2, p3, p4);
13128
          /*hst_torsion := torsion(p1,p2,p3,p4); */
13129
          p1.x = ndl_atom[na1 - 1].x;
13130
          p1.y = ndl_atom[na1 - 1].y;
13131
          p1.z = ndl_atom[na1 - 1].z;
13132
          p2.x = ndl_atom[na2 - 1].x;
13133
          p2.y = ndl_atom[na2 - 1].y;
13134
          p2.z = ndl_atom[na2 - 1].z;
13135
          p3.x = ndl_atom[na3 - 1].x;
13136
          p3.y = ndl_atom[na3 - 1].y;
13137
          p3.z = ndl_atom[na3 - 1].z;
13138
          p4.x = ndl_atom[na4 - 1].x;
13139
          p4.y = ndl_atom[na4 - 1].y;
13140
          p4.z = ndl_atom[na4 - 1].z;
13141
          /*ndl_torsion := torsion(p1,p2,p3,p4); */
13142
          ndl_cis = is_cis (p1, p2, p3, p4);
13143
          if (ndl_cis != hst_cis)
13144
            {
13145
/* p2c: checkmol.pas, line 9501:
13146
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13147
              /*$IFDEF debug */
13148
              //debugoutput ("E/Z geometry mismatch");
13149
              /*$ENDIF */
13150
              return false;
13151
            }
13152
        }
13153
    }                           /* end of E/Z geometry check */
13154
  /* check whatever can be checked as early as now: */
13155
  /* e.g. different elements or more substituents on needle atom than on haystack */
13156
  if (!atomtypes_OK (ndl_a, hst_a))
13157
    return false;
13158
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
13159
  if (atom[hst_a - 1].neighbor_count == 0 &&
13160
      ndl_atom[ndl_a - 1].neighbor_count == 0)
13161
    {
13162
      if (!atomtypes_OK (ndl_a, hst_a))
13163
        return false;
13164
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
13165
      atom[hst_a - 1].tag = true;
13166
      return true;
13167
    }
13168
  /* and other possibilities: */
13169
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
13170
  hst_b = get_bond (prev_hst_a, hst_a);
13171
/* p2c: checkmol.pas, line 9529:
13172
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13173
  /*$IFDEF debug */
13174
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
13175
  /*$ENDIF */
13176
  if (ndl_b > 0 && hst_b > 0)
13177
    {
13178
      /* do a quick check if bond types match */
13179
      if (!bondtypes_OK (ndl_b, hst_b))
13180
        {
13181
/* p2c: checkmol.pas, line 9537:
13182
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13183
          /*$IFDEF debug */
13184
          /*
13185
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
13186
          /*$ENDIF */
13187
          return false;
13188
        }
13189
    }
13190
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
13191
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a,
13192
                                                                 hst_a) &&
13193
      bondtypes_OK (ndl_b, hst_b))
13194
    {
13195
      return true;
13196
/* p2c: checkmol.pas, line 9549:
13197
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13198
      /*$IFDEF debug */
13199
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
13200
      /*$ENDIF */
13201
    }
13202
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
13203
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
13204
      (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp)))
13205
    {
13206
      return false;
13207
/* p2c: checkmol.pas, line 9559:
13208
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13209
      /*$IFDEF debug */
13210
      /*
13211
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
13212
         {$ENDIF */
13213
    }
13214
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
13215
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
13216
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp)))
13217
    {
13218
      if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
13219
          atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b))
13220
        {
13221
          /* 1st chirality check */
13222
          if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
13223
                                                       ndl_atom[ndl_a -
13224
                                                                1].
13225
                                                       stereo_care)) &&
13226
                ndl_maybe_chiral (ndl_a)))
13227
            {                   /* new in v0.3h */
13228
              return true;
13229
            }                   /* end of 1st chirality check */
13230
          na1 = ndl_a;          /* the (potential) chiral center (v0.3f) */
13231
          na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
13232
          na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
13233
          na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
13234
          ha1 = hst_a;
13235
          ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
13236
          ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
13237
          ha4 = hst_mp[matchpath_length (hst_mp) - 2];
13238
          memset (ncp, 0, sizeof (chirpath_type));
13239
          memset (hcp, 0, sizeof (chirpath_type));
13240
          ncp[0] = na1;
13241
          ncp[1] = na2;
13242
          ncp[2] = na3;
13243
          ncp[3] = na4;
13244
          hcp[0] = ha1;
13245
          hcp[1] = ha2;
13246
          hcp[2] = ha3;
13247
          hcp[3] = ha4;
13248
          if (!chirality_OK (ncp, hcp))
13249
            {
13250
/* p2c: checkmol.pas, line 9589:
13251
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13252
              /*$IFDEF debug */
13253
              //debugoutput ("chirality check failed at ring junction");
13254
              /*$ENDIF */
13255
              return false;
13256
            }
13257
/* p2c: checkmol.pas, line 9596:
13258
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13259
          /*$IFDEF debug */
13260
          //debugoutput ("chirality check succeeded at ring junction");
13261
          /*$ENDIF */
13262
          return true;
13263
/* p2c: checkmol.pas, line 9602:
13264
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13265
          /*$IFDEF debug */
13266
          /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
13267
          /*$ENDIF */
13268
        }
13269
      else
13270
        {
13271
          return false;
13272
/* p2c: checkmol.pas, line 9609:
13273
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13274
          /*$IFDEF debug */
13275
          /*
13276
             debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
13277
          /*$ENDIF */
13278
        }
13279
    }
13280
  /* in all other cases, do the hard work: */
13281
  /* first, get all heavy-atom neighbors of needle and haystack; */
13282
  /* at the beginning of the search, this means all neighbors, then it means */
13283
  /* all but the previous atom (where we came from) */
13284
  memset (ndl_nb, 0, sizeof (neighbor_rec));
13285
  memset (hst_nb, 0, sizeof (neighbor_rec));
13286
 
13287
  if (matchpath_length (ndl_mp) == 1)
13288
    {
13289
      ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
13290
      n_nb = atom[hst_a - 1].neighbor_count;
13291
      get_ndl_neighbors (ndl_nb, ndl_a);
13292
      get_neighbors (hst_nb, hst_a);
13293
    }
13294
  else
13295
    {
13296
      ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
13297
      n_nb = atom[hst_a - 1].neighbor_count - 1;
13298
      get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
13299
      get_nextneighbors (hst_nb, hst_a, prev_hst_a);
13300
    }
13301
  /* v0.3o: mark all neighbor atoms as "visited" */
13302
  for (i = 0; i < ndl_n_nb; i++)
13303
    ndl_atom[ndl_nb[i] - 1].tag = false;
13304
  /* now that the neighbor-arrays are filled, get all */
13305
  /* combinations of matches recursively; */
13306
  /* first, initialize the match matrix */
13307
  memset (mm, false, sizeof (matchmatrix));     /* new in v0.2i */
13308
  /* make sure there are not too many neighbors (max. max_neighbors)   */
13309
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors)
13310
    {                           /* updated in v0.2i */
13311
/* p2c: checkmol.pas, line 9644:
13312
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13313
      /*$IFDEF debug */
13314
      //debugoutput ("too many neighbors - exiting");
13315
      /*$ENDIF */
13316
      return false;
13317
    }
13318
  /* check if matchpath is not already filled up */
13319
  if (matchpath_length (ndl_mp) == max_matchpath_length)
13320
    {
13321
/* p2c: checkmol.pas, line 9653:
13322
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13323
      /*$IFDEF debug */
13324
      //debugoutput ("matchpath too int - exiting");
13325
      /*$ENDIF */
13326
      return false;
13327
    }
13328
  /* next, check which chain of the needle matches which chain of the haystack  */
13329
  for (i = 0; i < ndl_n_nb; i++)
13330
    {
13331
      emptyline = true;
13332
      next_ndl_a = ndl_nb[i];
13333
      for (j = 0; j < n_nb; j++)
13334
        {
13335
          next_hst_a = hst_nb[j];
13336
          ndl_mp[ndl_mp_len] = next_ndl_a;
13337
          hst_mp[hst_mp_len] = next_hst_a;
13338
          if (is_matching (ndl_mp, hst_mp))
13339
            {                   /* recursive function call */
13340
 
13341
              if (max_match_recursion_depth != 0
13342
                  && ++recursion_depth > max_match_recursion_depth)
13343
                {
13344
#ifndef MAKE_SHARED_LIBRARY
13345
                  if (opt_verbose)
13346
#endif
13347
                    printf
13348
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
13349
                       max_match_recursion_depth);
13350
                  //n_rings = max_rings;
13351
                  return true;
13352
                }
13353
 
13354
              mm[i][j] = true;
13355
              emptyline = false;
13356
            }
13357
        }
13358
      /* if a needle substituent does not match any of the haystack substituents, */
13359
      /* stop any further work immediately */
13360
      if (emptyline)
13361
        return false;
13362
    }
13363
  /* finally, check the content of the matrix */
13364
  res = matrix_OK (mm, ndl_n_nb, n_nb);
13365
  /* optional: chirality check */
13366
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) &&
13367
        ndl_maybe_chiral (ndl_a)))
13368
    return res;
13369
  /* first, we have to clean up the match matrix in order to remove */
13370
  /* "impossible" multiple matches (new in v0.3h) */
13371
  for (i = 1; i <= 3; i++)
13372
    {
13373
      for (j = 1; j <= max_neighbors; j++)
13374
        {                       /* haystack dimension */
13375
          n_hits = 0;
13376
          l = 0;
13377
          for (k = 1; k <= max_neighbors; k++)
13378
            {                   /* needle dimension */
13379
              if (mm[k - 1][j - 1])
13380
                {
13381
                  n_hits++;
13382
                  l = k;
13383
                }
13384
            }
13385
          if (n_hits == 1)
13386
            {                   /* a unique match ==> kick out any other match at this pos. */
13387
              for (m = 1; m <= max_neighbors; m++)
13388
                {
13389
                  if (m != j)
13390
                    mm[l - 1][m - 1] = false;
13391
                }
13392
            }
13393
        }
13394
    }
13395
  /* end of match matrix clean-up */
13396
  if (prev_ndl_a > 0)
13397
    {
13398
      n_singlehits = 1;
13399
      ncp[1] = prev_ndl_a;
13400
      hcp[1] = prev_hst_a;
13401
    }
13402
  else
13403
    n_singlehits = 0;
13404
  ncp[0] = ndl_a;
13405
  hcp[0] = hst_a;
13406
  i = 0;
13407
  l = 0;
13408
  while (n_singlehits < 3 && i < 4)
13409
    {
13410
      i++;
13411
      n_hits = 0;
13412
      for (k = 1; k <= n_nb; k++)
13413
        {
13414
          if (mm[i - 1][k - 1])
13415
            {
13416
              n_hits++;
13417
              l = k;
13418
            }
13419
        }
13420
      if (n_hits == 1)
13421
        {
13422
          n_singlehits++;
13423
          ncp[n_singlehits] = ndl_nb[i - 1];
13424
          hcp[n_singlehits] = hst_nb[l - 1];
13425
        }
13426
    }
13427
  if (n_singlehits != 3)
13428
    return res;
13429
  if (!chirality_OK (ncp, hcp))
13430
    {
13431
/* p2c: checkmol.pas, line 9749:
13432
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13433
      /*$IFDEF debug */
13434
      //debugoutput ("chirality check failed");
13435
      /*$ENDIF */
13436
      res = false;
13437
    }
13438
  else
13439
    {
13440
/* p2c: checkmol.pas, line 9755:
13441
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13442
      /*$IFDEF debug */
13443
      //debugoutput ("chirality check OK");
13444
      /*$ENDIF */
13445
    }
13446
  return res;
13447
/* p2c: checkmol.pas, line 9762:
13448
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13449
  /*$IFDEF debug */
13450
  /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
13451
     debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
13452
  /*$ENDIF */
13453
}
13454
 
13455
 
13456
static boolean
13457
quick_match ()
13458
{
13459
  /* added in v0.2c */
13460
  int i;
13461
  boolean res = true;
13462
 /* str3 ndl_atype;*/
13463
  str2 ndl_el;                  /* v0.3l */
6788 kbelabas 13464
  int ndl_chg = 0;              /* v0.3l */
13465
  int ndl_rad = 0;              /* v0.3x */
13466
  int ndl_iso = 0;              /* v0.3x */
6785 bpr 13467
 
13468
 
13469
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
13470
    /* v0.3f, v0.3m, v0.3o */
13471
    return false;
13472
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
13473
      ndl_n_bonds > n_bonds)
13474
    {                           /* just to be sure... */
13475
/* p2c: checkmol.pas, line 9786:
13476
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13477
      /*$IFDEF debug */
13478
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
13479
      //debugoutput (" ==> quick_match failed");
13480
      /*$ENDIF */
13481
      return false;
13482
    }
13483
 
13484
  if (ndl_n_heavyatoms > 1)
13485
    {
13486
      for (i = 0; i < ndl_n_atoms; i++)
13487
        {
13488
          /*if atom^[i].atype <> ndl_atom^[i].atype then res := false;    (* changed in */
13489
          if (strcmp (atom[i].element, ndl_atom[i].element))    /* v0.2k */
13490
            return false;
13491
          //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
13492
          //res = false;
13493
 
13494
 
13495
          if (opt_chg)
13496
            {
13497
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
13498
                return false;
13499
            }
13500
/*  else
13501
    {
13502
      if (ndl_atom[i].formal_charge != 0 &&
13503
          atom[i].formal_charge != 0 &&
13504
          ndl_atom[i].formal_charge != atom[i].formal_charge)
13505
        return false;
13506
    } */
13507
 
13508
          /* v0.3x: isotopes must be the same */
13509
          if (opt_iso)
13510
            {
13511
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
13512
                return false;
13513
            }
13514
/*  else
13515
    {
13516
      if (ndl_atom[i].nucleon_number != 0 &&
13517
          atom[i].nucleon_number != 0 &&
13518
          ndl_atom[i].nucleon_number !=
13519
          atom[i].nucleon_number)
13520
        return false;
13521
    }*/
13522
 
13523
          /* v0.3x: radicals must be the same */
13524
          if (opt_rad)
13525
            {
13526
              if (ndl_atom[i].radical_type != atom[i].radical_type)
13527
                return false;
13528
            }
13529
/*  else
13530
    {
13531
      if (ndl_atom[i].radical_type != 0 &&
13532
          atom[i].radical_type != 0 &&
13533
          ndl_atom[i].radical_type != atom[i].radical_type)
13534
        return false;
13535
    }*/
13536
 
13537
        }
13538
/* p2c: checkmol.pas, line 9798:
13539
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13540
      /*$IFDEF debug */
13541
      //if (res)
13542
      //debugoutput (" ==> quick_match: atoms OK");
13543
      //else
13544
      //  debugoutput (" ==> quick_match: atoms not OK");
13545
      /*$ENDIF */
13546
      if (ndl_n_bonds > 0)
13547
        {
13548
 
13549
          for (i = 0; i < ndl_n_bonds; i++)
13550
            {
13551
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
13552
                  || ndl_bond[i].btype != bond[i].btype)
13553
                return false;
13554
            }
13555
        }
13556
/* p2c: checkmol.pas, line 9810:
13557
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13558
      /*$IFDEF debug */
13559
      //if (res)
13560
      //  debugoutput (" ==> quick_match: bonds OK");
13561
      //else
13562
      //  debugoutput (" ==> quick_match: bonds not OK");
13563
      /*$ENDIF */
13564
      /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
13565
    }
13566
  else
13567
    {
13568
 
13569
      /* first, find out the element and atom type of the only heavy atom       */
13570
      for (i = 0; i < ndl_n_atoms; i++)
13571
        {
13572
          if (ndl_atom[i].heavy)
13573
            {
13574
              //strcpy (ndl_atype, ndl_atom[i].atype);
13575
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
13576
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
13577
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
13578
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
13579
            }
13580
        }
13581
 
13582
      for (i = 0; i < n_atoms; i++)
13583
        {                       /* v0.3l, v0.3o */
13584
          if (          //      !strcmp (atom[i].atype, ndl_atype) && 
13585
               !strcmp (atom[i].element, ndl_el))
13586
            {
13587
 
13588
 
13589
              if (opt_chg || opt_strict)
13590
                {
13591
                  if (ndl_chg != atom[i].formal_charge)
13592
                    return false;
13593
                }
13594
 
13595
 
13596
              if (opt_iso || opt_strict)
13597
                {
13598
                  if (ndl_iso != atom[i].nucleon_number)
13599
                    return false;
13600
                }
13601
 
13602
 
13603
 
13604
              if (opt_rad || opt_strict)
13605
                {
13606
                  if (ndl_rad != atom[i].radical_type)
13607
                    return false;
13608
                }
13609
                  return true;
13610
            } else {
13611
                res=false;
13612
            }    
13613
        }
13614
    }
13615
/* p2c: checkmol.pas, line 9828:
13616
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13617
  /*$IFDEF debug */
13618
  //if (res)
13619
  //  debugoutput (" ==> quick_match succeeded");
13620
  //else
13621
  //  debugoutput (" ==> quick_match failed (2)");
13622
  /*$ENDIF */
13623
  return res;
13624
}
13625
 
13626
static void
13627
perform_match ()
13628
{
13629
  int i = 0;
13630
  int j;
13631
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
13632
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
13633
  boolean qm;                   /* v0.3l */
13634
  /* check for NoStruct (0 atoms);  v0.3l */
13635
  if (n_atoms == 0 || ndl_n_atoms == 0)
13636
    {
13637
      matchresult = false;
13638
/* p2c: checkmol.pas, line 9849:
13639
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13640
      /*$IFDEF debug */
13641
      //debugoutput ("NoStruct encountered - aborted match routine");
13642
      /*$ENDIF */
13643
      return;
13644
    }
13645
  /* if we perform an exact match, needle and haystack must have */
13646
  /* the same number of atoms, bonds, and rings */
13647
  if (opt_exact && opt_iso)     /* 0.3x */
13648
    {
13649
      if (n_heavyatoms != ndl_n_heavyatoms
13650
          || n_heavybonds != ndl_n_heavybonds)
13651
        {
13652
          matchresult = false;
13653
/* p2c: checkmol.pas, line 9861:
13654
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13655
          /*$IFDEF debug */
13656
          //debugoutput ("different number of heavy atoms and/or bonds");
13657
          /*$ENDIF */
13658
          //return;
13659
        }
13660
    }
13661
 
13662
  /* have a quick look if needle and haystack are identical molfiles */
13663
  qm = quick_match ();          /* v0.3l */
13664
  if (qm)
13665
    {
13666
      matchresult = true;
13667
      clear_ndl_atom_tags ();   /* v0.3o */
13668
      return;
13669
    }
13670
  /* if we have only one heavy atom and quick_match fails, return "false";  v0.3l */
13671
  if (ndl_n_heavyatoms == 1)
13672
    {
13673
      matchresult = false;
13674
      return;
13675
    }
13676
/* p2c: checkmol.pas, line 9881:
13677
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13678
  /*$IFDEF debug */
13679
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
13680
  /*$ENDIF */
13681
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
13682
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
13683
/* p2c: checkmol.pas, line 9886:
13684
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13685
  /*$IFDEF debug */
13686
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
13687
  /*$ENDIF */
13688
  matchresult = false;
13689
  for (j = 0; j < max_matchpath_length; j++)
13690
    {
13691
      ndl_matchpath[j] = 0;
13692
      hst_matchpath[j] = 0;
13693
    }
13694
  ndl_matchpath[0] = ndl_ref_atom;
13695
  while (i < n_atoms && matchresult == false)
13696
    {
13697
      i++;
13698
      n_nb = atom[i - 1].neighbor_count;
13699
      n_hc = hetatom_count (i);
13700
      if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc)
13701
        {
13702
/* p2c: checkmol.pas, line 9904:
13703
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13704
          /*$IFDEF debug */
13705
          /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
13706
          /*$ENDIF */
13707
 
13708
          recursion_depth = 0;
13709
          hst_matchpath[0] = i;
13710
          matchresult = is_matching (ndl_matchpath, hst_matchpath);
13711
/* p2c: checkmol.pas, line 9909:
13712
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13713
          /*$IFDEF debug */
13714
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
13715
          /*$ENDIF */
13716
          if (matchresult)      /* v0.3o; mark this fragment as matched */
13717
            atom[i - 1].tag = true;
13718
        }
13719
    }
13720
}
13721
 
13722
 
13723
static void
13724
clear_rings ()
13725
{
13726
  int i, FORLIM;
13727
  n_rings = 0;
13728
  memset (ring, 0, sizeof (ringlist));
13729
  for (i = 0; i < max_rings; i++)
13730
    {                           /* new in v0.3 */
13731
      ringprop[i].size = 0;
13732
      ringprop[i].arom = false;
13733
      ringprop[i].envelope = false;
13734
    }
13735
  if (n_atoms > 0)
13736
    {
13737
      FORLIM = n_atoms;
13738
      for (i = 0; i < FORLIM; i++)
13739
        atom[i].ring_count = 0;
13740
    }
13741
  if (n_bonds > 0)
13742
    {
13743
      FORLIM = n_bonds;
13744
      for (i = 0; i < FORLIM; i++)
13745
        bond[i].ring_count = 0;
13746
    }
13747
}
13748
 
13749
 
13750
static int
13751
ring_lastpos (s)
13752
     int *s;
13753
{
13754
  int i, rc;
13755
  int rlp = 0;
13756
  int FORLIM;
13757
  if (n_rings <= 0)
13758
    return rlp;
13759
  FORLIM = n_rings;
13760
  for (i = 1; i <= FORLIM; i++)
13761
    {
13762
      rc = ringcompare (s, ring[i - 1]);
13763
      if (rc_identical (rc))
13764
        rlp = i;
13765
    }
13766
  return rlp;
13767
}
13768
 
13769
 
13770
static void
13771
remove_redundant_rings ()
13772
{
13773
  int i, j, k, rlp;
13774
  ringpath_type tmp_path;
13775
  int FORLIM, FORLIM1;
13776
  if (n_rings < 2)
13777
    return;
13778
  FORLIM = n_rings;
13779
  for (i = 1; i < FORLIM; i++)
13780
    {
13781
      memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
13782
      rlp = ring_lastpos (tmp_path);
13783
      while (rlp > i)
13784
        {
13785
          FORLIM1 = n_rings;
13786
/* p2c: checkmol.pas, line 9970:
13787
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13788
          /*$IFDEF debug */
13789
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
13790
          /*$ENDIF */
13791
          for (j = rlp; j < FORLIM1; j++)
13792
            {
13793
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
13794
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
13795
              ringprop[j - 1].arom = ringprop[j].arom;
13796
              ringprop[j - 1].envelope = ringprop[j].envelope;
13797
            }
13798
          for (k = 0; k < max_ringsize; k++)
13799
            ring[n_rings - 1][k] = 0;
13800
          n_rings--;
13801
          rlp = ring_lastpos (tmp_path);
13802
        }
13803
    }
13804
}
13805
 
13806
 
13807
static int
13808
count_aromatic_rings ()
13809
{
13810
  int i;
13811
  int n = 0;
13812
  int FORLIM;
13813
  if (n_rings <= 0)
13814
    return n;
13815
  FORLIM = n_rings;
13816
  for (i = 0; i < FORLIM; i++)
13817
    {
13818
      if (ringprop[i].arom)
13819
        n++;
13820
    }
13821
  return n;
13822
}
13823
 
13824
 
13825
static void
13826
chk_envelopes ()
13827
{
13828
  /* new in v0.3d */
13829
  /* checks if a ring completely contains one or more other rings */
13830
  int a, i, j, k, l, pl, pli;
13831
  boolean found_atom, found_all_atoms, found_ring;
13832
  int FORLIM;
13833
  if (n_rings < 2)
13834
    return;
13835
  FORLIM = n_rings;
13836
  for (i = 1; i < FORLIM; i++)
13837
    {
13838
      found_ring = false;
13839
      j = 0;
13840
      pli = ringprop[i].size;   /* path_length(ring^[i]); */
13841
      while (j < i && found_ring == false)
13842
        {
13843
          j++;
13844
          found_all_atoms = true;
13845
          pl = ringprop[j - 1].size;    /* path_length(ring^[j]); */
13846
          for (k = 0; k < pl; k++)
13847
            {
13848
              found_atom = false;
13849
              a = ring[j - 1][k];
13850
              for (l = 0; l < pli; l++)
13851
                {
13852
                  if (ring[i][l] == a)
13853
                    found_atom = true;
13854
                }
13855
              if (found_atom == false)
13856
                found_all_atoms = false;
13857
            }
13858
          if (found_all_atoms)
13859
            found_ring = true;
13860
        }
13861
      if (found_ring)
13862
        ringprop[i].envelope = true;
13863
    }
13864
}
13865
 
13866
 
13867
static void
13868
update_ringcount ()
13869
{
13870
  int i, j, a1, a2, b, pl, FORLIM;
13871
  if (n_rings <= 0)
13872
    return;
13873
  chk_envelopes ();
13874
  FORLIM = n_rings;
13875
  for (i = 0; i < FORLIM; i++)
13876
    {
13877
      if (ringprop[i].envelope == false)
13878
        {
13879
          pl = ringprop[i].size;        /* path_length(ring^[i]);  (* v0.3d */
13880
          a2 = ring[i][pl - 1];
13881
          for (j = 0; j < pl; j++)
13882
            {
13883
              a1 = ring[i][j];
13884
              atom[a1 - 1].ring_count++;
13885
              b = get_bond (a1, a2);
13886
              bond[b - 1].ring_count++;
13887
              a2 = a1;
13888
            }
13889
        }
13890
    }
13891
}
13892
 
13893
 
13894
static boolean
13895
normalize_ionic_bonds ()
13896
{
13897
  /* v0.3k */
13898
  /* changed from a procedure into a function in v0.3m */
13899
  int i, a1, a2, fc1, fc2;
13900
  char bt;
13901
  boolean res = false;          /* v0.3m */
13902
  int FORLIM;
13903
  /* v0.3m */
13904
  if (n_bonds == 0)
13905
    return false;
13906
  FORLIM = n_bonds;
13907
  for (i = 0; i < FORLIM; i++)
13908
    {
13909
      a1 = bond[i].a1;
13910
      a2 = bond[i].a2;
13911
      bt = bond[i].btype;
13912
      fc1 = atom[a1 - 1].formal_charge;
13913
      fc2 = atom[a2 - 1].formal_charge;
13914
      if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D'))
13915
        {
13916
          atom[a1 - 1].formal_charge = 0;
13917
          atom[a2 - 1].formal_charge = 0;
13918
          if (!strcmp (atom[a1 - 1].atype, "N3+"))      /* v0.3m */
13919
            strcpy (atom[a1 - 1].atype, "N3 ");
13920
          if (!strcmp (atom[a2 - 1].atype, "N3+"))      /* v0.3m */
13921
            strcpy (atom[a2 - 1].atype, "N3 ");
13922
          if (bt == 'D')
13923
            bond[i].btype = 'T';
13924
          if (bt == 'S')
13925
            bond[i].btype = 'D';
13926
          res = true;           /* v0.3m */
13927
        }
13928
    }
13929
  return res;                   /* v0.3m (return true if any change was made */
13930
}
13931
 
13932
#if 0
13933
static void
13934
chk_wildcard_rings ()           // new in v0.3p
13935
// checks if there are any wildcard atom types or bond types
13936
// in a ring of the needle; if yes ==> set the q_arom flag in the
13937
// atom and bond record of all ring members in order to perform the 
13938
// match a bit more generously
13939
{
13940
 
13941
  int i, j, rs;
13942
  int a1, a2, b;
13943
  boolean wcr;
13944
  str3 at;
13945
  char bt;
13946
 
13947
  if (ndl_querymol == false)
13948
    return;
13949
  if (ndl_n_rings == 0)
13950
    return;
13951
  // now look for any not-yet-aromatic rings which contain a wildcard
13952
  for (i = 0; i < ndl_n_rings; i++)
13953
    {
13954
      wcr = false;
13955
      if (ndl_ringprop[i].arom == false)
13956
        {
13957
          rs = ndl_ringprop[i].size;
13958
          a2 = ndl_ring[i][rs];
13959
          for (j = 0; j < rs; j++)
13960
            {
13961
              a1 = ndl_ring[i][j];
13962
              b = get_ndl_bond (a1, a2);
13963
              strcpy (at, ndl_atom[a1].atype);
13964
              bt = ndl_bond[b].btype;
13965
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
13966
                wcr = true;
13967
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
13968
                wcr = true;
13969
              a2 = a1;
13970
            }
13971
          if (wcr)
13972
            {                   // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
13973
              // {$IFDEF debug}
13974
              // debugoutput('wildcard ring found');
13975
              // {$ENDIF}
13976
              a2 = ndl_ring[i][rs];
13977
              for (j = 0; j < rs; j++)
13978
                {
13979
                  a1 = ndl_ring[i][j];
13980
                  b = get_ndl_bond (a1, a2);
13981
                  strcpy (at, ndl_atom[a1].atype);
13982
                  bt = ndl_bond[b].btype;
13983
                  ndl_atom[a1].q_arom = true;
13984
                  ndl_bond[b].q_arom = true;
13985
                  a2 = a1;
13986
                }
13987
            }
13988
        }
13989
    }
13990
  // and now undo this flagging for all rings which contain no wildcard
13991
  for (i = 0; i < ndl_n_rings; i++)
13992
    {
13993
      wcr = false;
13994
      rs = ndl_ringprop[i].size;
13995
      a2 = ndl_ring[i][rs];
13996
      for (j = 0; j < rs; j++)
13997
        {
13998
          a1 = ndl_ring[i][j];
13999
          b = get_ndl_bond (a1, a2);
14000
          strcpy (at, ndl_atom[a1].atype);
14001
          bt = ndl_bond[b].btype;
14002
          if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
14003
            wcr = true;
14004
          if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
14005
            wcr = true;
14006
          a2 = a1;
14007
        }
14008
      if (!wcr)
14009
        {                       // if yes, unflag all atoms and bonds in this ring
14010
          a2 = ndl_ring[i][rs];
14011
          for (j = 0; j < rs; j++)
14012
            {
14013
              a1 = ndl_ring[i][j];
14014
              b = get_ndl_bond (a1, a2);
14015
              strcpy (at, ndl_atom[a1].atype);
14016
              bt = ndl_bond[b].btype;
14017
              ndl_atom[a1].q_arom = false;
14018
              ndl_bond[b].q_arom = false;
14019
              a2 = a1;
14020
            }
14021
        }
14022
    }
14023
  // some further refinement would be necessary here in order to unflag everything
14024
  // which contains a wildcard but which definitely cannot be aromatic
14025
}
14026
#endif
14027
 
14028
#ifndef MAKE_SHARED_LIBRARY
14029
 
14030
int
14031
main (int argc, char *argv[])
14032
{                               /* main routine */
14033
  char STR1[256], STR6[256];
14034
  int FORLIM;
14035
  /* progmode = pmMatchMol */
14036
  rfile = NULL;
14037
  strcpy (progname, argv[0]);
14038
  strncpy (STR1, progname, 253);
14039
  if (strstr (STR1, "matchmol") != NULL)
14040
    progmode = pmMatchMol;
14041
  else
14042
    {
14043
      strncpy (STR6, progname, 253);
14044
      if (strstr (STR6, "checkmol") == NULL)
14045
        {
14046
          printf ("THOU SHALLST NOT RENAME ME!\n");
14047
          exit (9);
14048
        }
14049
      progmode = pmCheckMol;
14050
    }
14051
  if (argc == 1)
14052
    {
14053
      show_usage ();
14054
      exit (1);
14055
    }
14056
  init_globals ();
14057
  init_molstat (&molstat);
14058
  parse_args (argc, argv);
14059
  if (ringsearch_mode == rs_sar)
14060
    max_vringsize = max_ringsize;
14061
  else
14062
    max_vringsize = ssr_vringsize;
14063
  /* v0.3n (was: 10) */
14064
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14065
  if (progmode == pmMatchMol)
14066
    {
14067
      left_trim (ndl_molfilename);
14068
      left_trim (molfilename);
14069
      if ((*molfilename == '\0' || *ndl_molfilename == '\0'
14070
           || argc < 3) && !opt_stdin)
14071
        {
14072
 
14073
          show_usage ();
14074
          exit (2);             /* new in v0.2k */
14075
        }
14076
      if (!(file_exists (ndl_molfilename)) && !opt_stdin)
14077
        {                       /*not  fileexists(ndl_molfilename) REPLACE!!! */
14078
                                   printf("2");
14079
                                   /* p2c: checkmol.pas, line 10128:
14080
                                   * Warning: Expected an expression, found a ')' [227] */
14081
          if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
14082
            show_usage ();
14083
          else
14084
            printf ("file %s not found!\n", ndl_molfilename);
14085
          /* new in v0.2k */
14086
          exit (2);
14087
        }
14088
    }
14089
 
14090
  if (!(file_exists (molfilename)) && !opt_stdin)
14091
    {                           /*not  fileexists(ndl_molfilename) REPLACE!!! */
14092
/* p2c: checkmol.pas, line 10128:
14093
 * Warning: Expected an expression, found a ')' [227] */
14094
 
14095
      if (strlen (molfilename) > 1 && molfilename[0] == '-')
14096
        show_usage ();
14097
      else
14098
        printf ("file %s not found!\n", molfilename);
14099
      /* new in v0.2k */
14100
      exit (2);
14101
    }
14102
 
14103
  /* read the first molecule and process it; if we are in "matchmol" mode, */
14104
  /* this is the "needle" */
14105
  if (progmode == pmMatchMol)
14106
    readinputfile (ndl_molfilename);
14107
  else
14108
    readinputfile (molfilename);
14109
  li = 1;                       /* initialize line pointer for input buffer */
14110
  get_filetype (filetype, ndl_molfilename);
14111
  if (!strcmp (filetype, "unknown"))
14112
    {
14113
      printf ("unknown query file format!\n");
14114
      if (!opt_verbose)
14115
        exit (3);
14116
      printf ("===========================================\n");
14117
      FORLIM = molbufindex;
14118
      for (i = 1; i <= FORLIM; i++)
14119
        puts (molbuf[i - 1]);
14120
      exit (3);
14121
    }
14122
  mol_OK = true;                /* added in v0.2i */
14123
  if (!strcmp (filetype, "alchemy"))
14124
    read_molfile (ndl_molfilename);
14125
  if (!strcmp (filetype, "sybyl"))
14126
    read_mol2file (ndl_molfilename);
14127
  if (!strcmp (filetype, "mdl"))
14128
    read_MDLmolfile (ndl_molfilename);
14129
  count_neighbors ();
14130
  if (!mol_OK || n_atoms < 1)
14131
    {                           /* v0.3g; check if this is a valid query structure */
14132
      printf ("invalid molecule\n");
14133
      exit (3);
14134
    }
14135
  if (!found_arominfo || progmode == pmCheckMol)
14136
    {                           /* added in v0.2b/0.2c */
14137
/* p2c: checkmol.pas, line 10172:
14138
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14139
      /*$IFDEF debug
14140
         if (!found_arominfo)
14141
         debugoutput
14142
         ("no aromaticity information found - checking myself...");
14143
         else
14144
         debugoutput ("performing full aromaticity check");
14145
         // new in v0.3d
14146
      $ENDIF */
14147
      chk_ringbonds ();
14148
      if (ringsearch_mode == rs_ssr)
14149
        remove_redundant_rings ();
14150
      if (n_rings >= max_rings)
14151
        {
14152
          if (opt_verbose)
14153
            printf
14154
              ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14155
               max_rings);
14156
          ringsearch_mode = rs_ssr;
14157
          auto_ssr = true;      /* v0.3n */
14158
          clear_rings ();
14159
          max_vringsize = ssr_vringsize;        /* v0.3n (was: 10) */
14160
          chk_ringbonds ();
14161
          remove_redundant_rings ();
14162
        }
14163
      update_ringcount ();
14164
      /* new in v0.3k: if output is a molfile, leave the original */
14165
      /* representation of N-oxides, S-oxides, nitro groups, etc. */
14166
      /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
14167
      if (!opt_xmdlout)         /* v0.3k */
14168
        normalize_ionic_bonds ();
14169
      update_atypes ();
14170
      update_Htotal ();         /* added in v0.3 */
14171
      chk_arom ();
14172
      if (ringsearch_mode == rs_ssr)
14173
        {                       /* new in v0.3 */
14174
          do
14175
            {
14176
              prev_n_ar = count_aromatic_rings ();
14177
              chk_arom ();
14178
              n_ar = count_aromatic_rings ();
14179
            }
14180
          while (prev_n_ar - n_ar != 0);
14181
        }
14182
    }
14183
  else
14184
    {                           /* v0.3k */
14185
/* p2c: checkmol.pas, line 10206:
14186
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14187
      /*$IFDEF debug
14188
         debugoutput ("found aromaticity information in input file");
14189
         $ENDIF */
14190
      if (!opt_xmdlout)
14191
        normalize_ionic_bonds ();
14192
      update_atypes ();         /* added in v0.2f */
14193
      update_Htotal ();         /* end v0.2b snippet */
14194
    }
14195
  if (progmode == pmCheckMol)
14196
    {
14197
      if (opt_verbose)
14198
        write_mol ();
14199
      get_molstat ();
14200
      if (opt_molstat)
14201
        {
14202
          if (opt_molstat_X)
14203
            write_molstat_X ();
14204
          else
14205
            write_molstat ();
14206
        }
14207
      else
14208
        {
14209
          if (found_querymol)
14210
            {
14211
              printf ("input structure contains query atom or query bond!\n");
14212
              exit (1);
14213
            }
14214
          chk_functionalgroups ();
14215
          if (opt_none)
14216
            opt_text = true;
14217
          if (opt_text)
14218
            write_fg_text ();
14219
          if (opt_text_de)
14220
            write_fg_text_de ();
14221
          if (opt_code)
14222
            write_fg_code ();
14223
          if (opt_bin)
14224
            write_fg_binary ();
14225
          if (opt_bitstring)
14226
            write_fg_bitstring ();
14227
          if (opt_xmdlout)
14228
            write_MDLmolfile ();
14229
        }
14230
      /*if opt_verbose   then write_mol; */
14231
      zap_molecule ();
14232
    }
14233
  else
14234
    {
14235
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14236
      if (!opt_fp)
14237
        {                       /* v0.3m */
14238
          copy_mol_to_needle ();
14239
          //chk_wildcard_rings (); /* 0.3p */
14240
          set_ndl_atom_tags (); /* v0.3o */
14241
          if (opt_verbose)
14242
            write_needle_mol ();
14243
          if (rs_strict)        /* v0.3j */
14244
            ndl_ref_atom = find_ndl_ref_atom_cv ();
14245
          else
14246
            ndl_ref_atom = find_ndl_ref_atom ();
14247
        }
14248
      else
14249
        {
14250
          copy_mol_to_tmp ();   /* v0.3m */
14251
          if (opt_verbose)
14252
            printf ("1st molecule stored in buffer: %s\n", tmp_molname);
14253
        }
14254
      /* next, read the "haystack" file and process it */
14255
      li = 1;
14256
      mol_count = 0;
14257
      fpdecimal = 0;            /* v0.3m */
14258
      fpindex = 0;              /* v0.3m */
14259
      do
14260
        {
14261
          /* new in v0.3i: reset ringsearch_mode to its initial value */
14262
          /* for each new molecule */
14263
          ringsearch_mode = opt_rs;
14264
          if (ringsearch_mode == rs_sar)
14265
            max_vringsize = max_ringsize;
14266
          else
14267
            max_vringsize = ssr_vringsize;
14268
          /* v0.3n (was: 10) */
14269
          readinputfile (molfilename);
14270
          li = 1;
14271
          get_filetype (filetype, molfilename);
14272
          if (strcmp (filetype, "unknown"))
14273
            {
14274
              found_arominfo = false;   /* added in v0.2b */
14275
              mol_OK = true;    /* added in v0.2i */
14276
              if (!strcmp (filetype, "alchemy"))
14277
                read_molfile (molfilename);
14278
              if (!strcmp (filetype, "sybyl"))
14279
                read_mol2file (molfilename);
14280
              if (!strcmp (filetype, "mdl"))
14281
                read_MDLmolfile (molfilename);
14282
              mol_count++;
14283
              fpindex++;
14284
              count_neighbors ();
14285
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14286
              if (!mol_OK || (n_atoms < 1
14287
                  && !(opt_fp && fpformat == fpf_decimal)))
14288
                printf ("%i:F\n", mol_count);
14289
              else
14290
                {
14291
                  if (opt_exact
14292
                      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14293
                          || n_Ntot != ndl_n_Ntot))
14294
                    {           /* new in v0.3g */
14295
                      if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
14296
                        printf ("%i:F\n", mol_count);
14297
                    }
14298
                  else
14299
                    {
14300
                      if (!found_arominfo || (opt_strict && tmfmismatch))
14301
                        {       /* added in v0.3m */
14302
/* p2c: checkmol.pas, line 10294:
14303
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14304
                          /*$IFDEF debug
14305
                             debugoutput
14306
                             ("no aromaticity information found (or tweak mismatch) - checking myself...");
14307
                            *$ENDIF */
14308
                          chk_ringbonds ();
14309
                          if (ringsearch_mode == rs_ssr)
14310
                            remove_redundant_rings ();
14311
                          if (n_rings == max_rings)
14312
                            {
14313
                              if (opt_verbose)
14314
                                printf
14315
                                  ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14316
                                   max_rings);
14317
                              ringsearch_mode = rs_ssr;
14318
                              clear_rings ();
14319
                              max_vringsize = ssr_vringsize;    /* v0.3n (was: 10) */
14320
                              chk_ringbonds ();
14321
                              remove_redundant_rings ();
14322
                            }
14323
                          update_ringcount ();
14324
                          update_atypes ();
14325
                          update_Htotal ();     /* added in v0.3 */
14326
                          chk_arom ();
14327
                          if (ringsearch_mode == rs_ssr)
14328
                            {   /* new in v0.3 */
14329
                              do
14330
                                {
14331
                                  prev_n_ar = count_aromatic_rings ();
14332
                                  chk_arom ();
14333
                                  n_ar = count_aromatic_rings ();
14334
                                }
14335
                              while (prev_n_ar - n_ar != 0);
14336
                            }
14337
                        }
14338
                      else
14339
                        {       /* added in v0.2f */
14340
/* p2c: checkmol.pas, line 10322:
14341
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14342
                          /*$IFDEF debug
14343
                             debugoutput
14344
                             ("found aromaticity information in input file");
14345
                             $ENDIF */
14346
                          if (opt_strict)
14347
                            update_atypes ();
14348
                          update_Htotal ();
14349
                        }
14350
                      init_molstat (&ndl_molstat);
14351
                      if (normalize_ionic_bonds ())
14352
                        /* new in v0.3k, modified in v0.3m */
14353
                        update_atypes ();
14354
                      if (opt_verbose && !opt_fp)
14355
                        write_mol ();
14356
                      /* if in "fingerprint mode", exchange needle and haystack */
14357
                      if (opt_fp)
14358
                        {       /* v0.3m */
14359
                          zap_needle ();
14360
                          copy_mol_to_needle ();
14361
                          //chk_wildcard_rings (); /* 0.3p */
14362
                          zap_molecule ();
14363
                          copy_tmp_to_mol ();
14364
                          if (opt_verbose)
14365
                            write_needle_mol ();
14366
                          if (rs_strict)        /* v0.3j */
14367
                            ndl_ref_atom = find_ndl_ref_atom_cv ();
14368
                          else
14369
                            ndl_ref_atom = find_ndl_ref_atom ();
14370
                          if (opt_verbose)
14371
                            write_mol ();
14372
                        }       /* v0.3m */
14373
                      /* now that we have both molecules, perform the comparison */
14374
                      /* v0.3o: takes care of disconnected fragment... */
14375
                      clear_atom_tags ();
14376
                      set_ndl_atom_tags ();
14377
                      matchsummary = true;
14378
                      perform_match ();
14379
                      matchsummary = matchresult;
14380
                      if (count_tagged_ndl_heavyatoms () > 0
14381
                          && matchsummary == true)
14382
                        {
14383
                          do
14384
                            {
14385
                              if (rs_strict)
14386
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
14387
                              else
14388
                                ndl_ref_atom = find_ndl_ref_atom ();
14389
                              perform_match ();
14390
                              if (matchresult == false)
14391
                                matchsummary = false;
14392
                            }
14393
                          while (count_tagged_ndl_heavyatoms () != 0 &&
14394
                                 matchsummary != false);
14395
                        }
14396
                      /* end of disconnected-fragment matching (v0.3o) */
14397
                      if (matchsummary == true)
14398
                        {       /* v0.3o */
14399
                          if (opt_molout)
14400
                            {
14401
                              FORLIM = molbufindex;
14402
                              for (i = 1; i <= FORLIM; i++)
14403
                                puts (molbuf[i - 1]);
14404
                            }
14405
                          else
14406
                            {
14407
                              if (!opt_fp)      /* inttostr(mol_count) REPLACE!!!, */
14408
                                printf ("%i:T\n", mol_count);
14409
                              else
14410
                                {
14411
                                  if (ndl_n_heavyatoms == n_heavyatoms &&
14412
                                      ndl_n_heavybonds == n_heavybonds)
14413
                                    fp_exacthit = true;
14414
                                  else
14415
                                    fp_exacthit = false;
14416
                                  if (fp_exacthit)
14417
                                    fp_exactblock = true;
14418
                                  if (fpformat == fpf_boolean)
14419
                                    {
14420
                                      if (fp_exacthit)  /* inttostr(mol_count), REPACE!!! */
14421
                                        printf ("%i:TX\n", mol_count);
14422
                                      else
14423
                                        printf ("%i:T\n", mol_count);
14424
                                    }
14425
                                  /* inttostr(mol_count), REPLACE!!! */
14426
                                  if (fpformat == fpf_decimal)
14427
                                    {
14428
                                      fpincrement = 1;
14429
                                      FORLIM = fpindex;
14430
                                      for (i = 1; i <= FORLIM; i++)
14431
                                        fpincrement <<= 1;
14432
                                      fpdecimal += fpincrement;
14433
                                    }
14434
                                }
14435
                            }
14436
                        }
14437
                      else
14438
                        {
14439
                          if (!
14440
                              (opt_molout || (opt_fp
14441
                               && fpformat == fpf_decimal)))
14442
                            /* inttostr(mol_count), REPLACE!!! */
14443
                            printf ("%i:F\n", mol_count);
14444
                        }
14445
                      if (opt_fp && fpformat == fpf_decimal
14446
                          && fpindex == fp_blocksize)
14447
                        {
14448
                          if (fp_exactblock)
14449
                            fpdecimal++;
6786 kbelabas 14450
                          printf ("%lld\n", fpdecimal);
6785 bpr 14451
                          fpindex = 0;
14452
                          fpdecimal = 0;
14453
                          fp_exactblock = false;
14454
                        }
14455
                      zap_molecule ();
14456
                      molbufindex = 0;
14457
                    }
14458
                }
14459
            }
14460
          else
14461
            {
14462
              /* v0.3l */
14463
              /* mol_OK */
14464
              printf ("%i:unknown file format\n", mol_count);
14465
            }
14466
        }
14467
      while (mol_in_queue != false);
14468
      /* if filetype <> 'unknown' */
14469
      if (opt_fp && fpformat == fpf_decimal && fpindex > 0)
14470
        {
14471
          if (fp_exactblock)
14472
            fpdecimal++;
6786 kbelabas 14473
          printf ("%lld\n", fpdecimal);
6785 bpr 14474
        }
14475
      zap_needle ();
14476
      if (rfile_is_open)
14477
        {                       /* new in v0.2g */
14478
          if (rfile != NULL)
14479
            fclose (rfile);
14480
          rfile = NULL;
14481
        }
14482
    }
14483
  if (rfile != NULL)
14484
    fclose (rfile);
14485
  exit (0);
14486
}
14487
 
14488
#else
14489
 
14490
static void
14491
init_globals_dll (void)
14492
{
14493
 
14494
//printf("init_globals_dll\n");
14495
 
14496
  int i;
14497
  opt_verbose = false;
14498
  opt_debug = false;
14499
  opt_stdin = false;
14500
  opt_text = false;
14501
  opt_code = false;
14502
  opt_bin = false;
14503
  opt_bitstring = false;
14504
  opt_molout = false;
14505
  opt_molstat = false;
14506
  opt_molstat_X = false;
14507
  opt_xmdlout = false;
14508
  opt_fp = false;               /* new in v0.3m */
14509
  /*cm_mdlmolfile   := false; */
14510
  found_arominfo = false;
14511
  found_querymol = false;
14512
  ndl_querymol = false;
14513
  opt_rs = rs_sar;              /* v0.3i */
14514
  ringsearch_mode = opt_rs;
14515
  rfile_is_open = false;        /* new in v0.2g */
14516
  ez_flag = false;              /* new in v0.3f */
14517
  chir_flag = false;            /* new in v0.3f */
14518
  n_Ctot = 0;
14519
  n_Otot = 0;
14520
  n_Ntot = 0;                   /* new in v0.3g */
14521
  //for (i = 0; i < max_fg; i++)
14522
  //  fg[i] = false;
14523
  memset (fg, 0, sizeof (fglist));
14524
 
14525
  if (!yet_initialized)
14526
    {
14527
      molbuf = (void *) safe_malloc (sizeof (molbuftype));
14528
      opt_exact = false;
14529
      opt_strict = false;       /* new in v0.2f */
14530
      opt_metalrings = false;   /* new in v0.3 */
14531
      opt_geom = false;         /* new in v0.3d */
14532
      opt_chiral = false;       /* new in v0.3f */
14533
      opt_iso = false;          /* new in v0.3x */
14534
      opt_chg = false;          /* new in v0.3x */
14535
      opt_rad = false;          /* new in v0.3x */
14536
      ez_search = false;        /* new in v0.3d */
14537
      rs_search = false;        /* new in v0.3f */
14538
      rs_strict = false;        /* new in v0.3j */
14539
      ndl_n_Ctot = 0;
14540
      ndl_n_Otot = 0;
14541
      ndl_n_Ntot = 0;           /* new in v0.3g */
14542
      yet_initialized = true;
14543
    }
14544
 
14545
  ether_generic = false;        /* v0.3j */
14546
  amine_generic = false;        /* v0.3j */
14547
  hydroxy_generic = false;      /* v0.3j */
14548
  fpformat = fpf_decimal;       /* v0.3m */
14549
  fpindex = 0;                  /* v0.3m */
14550
  fp_exacthit = false;          /* v0.3m */
14551
  fp_exactblock = false;        /* v0.3m */
14552
  tmfcode = 0;                  /* v0.3m */
14553
  tmfmismatch = false;          /* v0.3m */
14554
  auto_ssr = false;
14555
  recursion_depth = 0;
14556
}
14557
 
14558
static void
14559
mm_init_mol (void)
14560
{
14561
 
14562
//printf("mm_init_mol\n");
14563
  init_globals_dll ();
14564
  init_molstat (&molstat);
14565
  if (opt_rs_dll == RPA_DEFAULT)
14566
    {
14567
      ringsearch_mode = opt_rs;
14568
      //printf("DEFAULT: %i\n",ringsearch_mode);
14569
    }
14570
  else
14571
    {
14572
      ringsearch_mode = opt_rs_dll;
14573
    }
14574
  //printf("RPA: %i\n",ringsearch_mode);
14575
 
14576
  if (ringsearch_mode == rs_sar)
14577
    {
14578
      max_vringsize = max_ringsize;
14579
    }
14580
  else
14581
    {
14582
      max_vringsize = ssr_vringsize;
14583
    }
14584
  zap_molecule ();
14585
  molbufindex = 0;
14586
  mol_count = 0;
14587
//printf("mm_init_mol\n");
14588
}
14589
 
14590
static void
14591
mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
14592
{
14593
//printf("mm_elab_mol\n");
14594
 
14595
  li = 1;                       // initialize line pointer for input buffer
14596
  get_filetype (filetype, ndl_molfilename);
14597
  if (strcmp (filetype, "unknown") == 0)
14598
    {
14599
      //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
14600
      exit (3);
14601
    }
14602
 
14603
  if (checkmol_mode == true)
14604
    progmode = pmCheckMol;
14605
  else
14606
    progmode = pmMatchMol;
14607
  if (strcmp (filetype, "alchemy") == 0)
14608
    read_molfile (ndl_molfilename);
14609
  if (strcmp (filetype, "sybyl") == 0)
14610
    read_mol2file (ndl_molfilename);
14611
  if (strcmp (filetype, "mdl") == 0)
14612
    read_MDLmolfile (ndl_molfilename);
14613
  if (checkmol_mode)
14614
    {
14615
      if (found_querymol)
14616
        {
14617
          printf
14618
            ("Warning: Input structure contains query atom or query bond.\n");
14619
        }
14620
    }
14621
 
14622
  count_neighbors ();
14623
  if (!found_arominfo || checkmol_mode || opt_strict)
14624
    {
14625
      //printf("No arom found or checkmol mode\n");
14626
      chk_ringbonds ();
14627
      if (ringsearch_mode == rs_ssr)
14628
        remove_redundant_rings ();
14629
      if (n_rings >= max_rings)
14630
        {
14631
 
14632
          printf
14633
            ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14634
             max_rings);
14635
          ringsearch_mode = rs_ssr;
14636
          auto_ssr = true;
14637
          clear_rings ();
14638
          max_vringsize = ssr_vringsize;
14639
          chk_ringbonds ();
14640
          remove_redundant_rings ();
14641
        }
14642
 
14643
      update_ringcount ();
14644
      if (normalize_ionic_bnds) /* v0.3k */
14645
        normalize_ionic_bonds ();
14646
      update_atypes ();
14647
      update_Htotal ();
14648
      chk_arom ();
14649
      if (ringsearch_mode == rs_ssr)
14650
        {                       /* new in v0.3 */
14651
          do
14652
            {
14653
              prev_n_ar = count_aromatic_rings ();
14654
              chk_arom ();
14655
              n_ar = count_aromatic_rings ();
14656
            }
14657
          while (prev_n_ar - n_ar != 0);
14658
        }
14659
    }
14660
  else
14661
    {
14662
      if (normalize_ionic_bnds) /* v0.3k  */
14663
        normalize_ionic_bonds ();
14664
      //if (opt_strict)
14665
      update_atypes ();
14666
      update_Htotal ();
14667
    }
14668
 
14669
 
14670
 
14671
//printf("mm_elab_mol\n");
14672
}
14673
 
14674
DLLEXPORT void
14675
mm_set_current_mol_as_query (void)
14676
{
14677
//printf("mm_set_current_mol_as_query\n");
14678
  zap_needle ();
14679
//mm_ElabMol;
14680
  copy_mol_to_needle ();
14681
  //chk_wildcard_rings (); /* 0.3p */
14682
  set_ndl_atom_tags ();         /* v0.3o */
14683
  if (opt_geom)                 /* v0.3d */
14684
    ez_search = true;
14685
  else if (!ez_flag && ez_search)
14686
    ez_search = false;          //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14687
  if (opt_chiral)
14688
    {                           /* v0.3f */
14689
      rs_search = true;
14690
 
14691
      //printf("%i\n",rs_search);
14692
    }
14693
  else if (!chir_flag && rs_search)
14694
    {
14695
      rs_search = false;        //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14696
      //printf("%i\n",rs_search);
14697
    }
14698
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
14699
    rs_strict = true;
14700
  else
14701
    rs_strict = false;
14702
  /* if (rs_strict)              // v0.3j
14703
     ndl_ref_atom = find_ndl_ref_atom_cv ();
14704
     //ndl_ref_atom = find_ndl_ref_atom ();
14705
     else
14706
     ndl_ref_atom = find_ndl_ref_atom (); */
14707
 
14708
 
14709
 
14710
  molbufindex = 0;
14711
  mol_count = 0;
14712
/*printf("mm_set_current_mol_as_query\n");*/
14713
}
14714
 
14715
DLLEXPORT int
14716
mm_get_rings (void)
14717
{
14718
  return n_rings;
14719
}
14720
 
14721
DLLEXPORT void
14722
xm_version (char *buffer)
14723
{
14724
  buffer[0] = '\0';
14725
  strncpy (buffer, version, 255);
14726
}
14727
 
14728
DLLEXPORT int
14729
mm_get_atom_ring (int atom_number)
14730
{
14731
 
14732
  int i, j, a1, pl;
14733
  int ret = 0;
14734
  a1 = atom[atom_number].ring_count;
14735
  if (n_rings > 0)
14736
    {
14737
      for (i = 1; i < n_rings; i++)
14738
        {
14739
 
14740
          pl = path_length (ring[i]);
14741
//          a2 := ring^[i,pl];
14742
          for (j = 1; j < pl; j++)
14743
            {
14744
 
14745
              a1 = ring[i][j];
14746
              if (atom_number == a1)
14747
                ret = i;
14748
//
14749
//              inc(atom^[a1].ring_count);
14750
//              b := get_bond(a1,a2);
14751
//              inc(bond^[b].ring_count);
14752
//              a2 := a1;
14753
            }
14754
        }
14755
    }
14756
  return ret;
14757
}
14758
 
14759
static void
14760
mm_read_input_line (char *st)
14761
{
14762
//printf("mm_read_input_line_in\n");
14763
//var
14764
//yyy:pchar;
14765
 
14766
  mol_in_queue = false;
14767
  if (molbufindex < (max_atoms + max_bonds + slack))
14768
    {
14769
 
14770
//yyy:=Pchar(IntToStr(molbufindex));
14771
//messagebox (0,yyy,'',0);
14772
//printf("%i\n",molbufindex);
14773
//printf("B:%s\n",st);
14774
      strcpy (molbuf[molbufindex++], st);
14775
//printf("%x %x\n",&molbuf,molbuf);
14776
//printf("%s\n",molbuf[molbufindex-1]);
14777
      //  molbufindex++;
14778
    }
14779
  else
14780
    {
14781
      //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
14782
      printf ("Not enough memory for molfile! %i\n", molbufindex);
14783
      exit (1);
14784
    }
14785
//printf("mm_read_input_line_out\n");
14786
}
14787
 
14788
 
14789
static void
14790
mm_set_mol_dll (const char *st, boolean checkmol_mode,
14791
                boolean normalize_ionic_bnds)
14792
{
14793
//printf("mm_set_mol\n");
14794
//printf("%s\n",st);
14795
  char bb;
14796
  char aa;
14797
  int i;
14798
  int k;
14799
  int J;
14800
  int spt = 0;
14801
  char tt[256];
14802
  char bb10 = '\n';
14803
  char bb13 = '\r';
14804
  char bb0 = '\0';
14805
  int lenst;
14806
//char d[256];
14807
  lenst = strlen (st);
14808
//tt=(char*)safe_malloc(256*sizeof(char));
14809
  tt[0] = '\0';
14810
//messagebox(0,st,'',0);
14811
  mm_init_mol ();
14812
  for (i = spt; i < lenst; i++)
14813
    {
14814
      bb = st[i];
14815
      if ((bb == bb10) || (i == lenst))
14816
        {
14817
          J = 0;
14818
          // d:='';
14819
          for (k = spt; k < i; k++)
14820
            {
14821
 
14822
              aa = st[k];
14823
              if ((aa != bb10) && (aa != bb13))
14824
                {
14825
                  //d:=d+aa;
14826
                  tt[J] = aa;
14827
                  J++;
14828
                }
14829
            }
14830
          tt[J] = bb0;
14831
          spt = i;
14832
          //messagebox (0,tt,tt,0);
14833
//printf("A:%s\n",tt);
14834
          mm_read_input_line (tt);
14835
        }
14836
    }
14837
//free(tt);
14838
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
14839
//printf("mm_set_mol\n");
14840
}
14841
 
14842
DLLEXPORT void
14843
cm_set_mol (const char *st, int normalize_ionic_bnds)
14844
{
14845
  mm_set_mol_dll (st, true, (normalize_ionic_bnds != FEATURE_OFF));
14846
}
14847
 
14848
DLLEXPORT void
14849
mm_set_mol (const char *st)
14850
{
14851
  mm_set_mol_dll (st, false, true);
14852
}
14853
 
14854
DLLEXPORT void
14855
xm_set_strict_typing (int strict_typing)
14856
{
14857
  if (!yet_initialized)
14858
    init_globals_dll ();
14859
  opt_strict = (strict_typing != FEATURE_OFF);
14860
  //opt_strict=false; //This never worked right and is harmful
14861
}
14862
 
14863
DLLEXPORT void
14864
mm_set_r_s_check (int r_s_check)
14865
{
14866
  if (!yet_initialized)
14867
    init_globals_dll ();
14868
  opt_chiral = (r_s_check != FEATURE_OFF);
14869
}
14870
 
14871
DLLEXPORT void
14872
mm_set_e_z_check (int e_z_check)
14873
{
14874
  if (!yet_initialized)
14875
    init_globals_dll ();
14876
  opt_geom = (e_z_check != FEATURE_OFF);
14877
}
14878
 
14879
DLLEXPORT void
14880
mm_set_chg_check (int chg_check)
14881
{
14882
  if (!yet_initialized)
14883
    init_globals_dll ();
14884
  opt_chg = (chg_check != FEATURE_OFF);
14885
}
14886
 
14887
DLLEXPORT void
14888
mm_set_iso_check (int iso_check)
14889
{
14890
  if (!yet_initialized)
14891
    init_globals_dll ();
14892
  opt_iso = (iso_check != FEATURE_OFF);
14893
}
14894
 
14895
DLLEXPORT void
14896
mm_set_rad_check (int rad_check)
14897
{
14898
  if (!yet_initialized)
14899
    init_globals_dll ();
14900
  opt_rad = (rad_check != FEATURE_OFF);
14901
}
14902
 
14903
DLLEXPORT void
14904
mm_set_exact_match (int exact)
14905
{
14906
  if (!yet_initialized)
14907
    init_globals_dll ();
14908
  opt_exact = (exact != FEATURE_OFF);
14909
}
14910
 
14911
DLLEXPORT int
14912
mm_match ()
14913
{
14914
  mol_count = 1;
14915
//     mm_ElabMol;
14916
/*printf("%i\n",opt_exact);
14917
printf("%i\n",n_Ctot);
14918
printf("%i\n",ndl_n_Ctot);
14919
printf("%i\n",n_Otot);
14920
printf("%i\n",ndl_n_Otot);
14921
printf("%i\n",n_Ntot);
14922
printf("%i\n",ndl_n_Ntot);*/
14923
  if (opt_exact
14924
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14925
          || n_Ntot != ndl_n_Ntot))
14926
    return 0;
14927
  init_molstat (&ndl_molstat);
14928
  //perform_match ();
14929
  //---------------------------------------------------- 0.3o
14930
  if (rs_strict)                /* v0.3j */
14931
    ndl_ref_atom = find_ndl_ref_atom_cv ();
14932
  //ndl_ref_atom = find_ndl_ref_atom ();
14933
  else
14934
    ndl_ref_atom = find_ndl_ref_atom ();
14935
  clear_atom_tags ();
14936
  set_ndl_atom_tags ();
14937
  matchsummary = true;
14938
  perform_match ();
14939
  matchsummary = matchresult;
14940
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true)
14941
    {
14942
      do
14943
        {
14944
          if (rs_strict)
14945
            ndl_ref_atom = find_ndl_ref_atom_cv ();
14946
          else
14947
            ndl_ref_atom = find_ndl_ref_atom ();
14948
          perform_match ();
14949
          if (matchresult == false)
14950
            matchsummary = false;
14951
        }
14952
      while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
14953
    }
14954
 
14955
  //-----------------------------------------------------
14956
 
14957
  //mol_count = 0;
14958
 
14959
  //molbufindex = 0;
14960
 
14961
  //return matchresult ? 1 : 0;
14962
 
14963
  return matchsummary ? 1 : 0;
14964
}
14965
 
14966
//-------------------------
14967
 
14968
DLLEXPORT void
14969
xm_set_ring_perception_algorithm (int algo)
14970
{
14971
  switch (algo)
14972
    {
14973
    case RPA_SAR:
14974
      opt_rs_dll = rs_sar;
14975
      break;
14976
    case RPA_SSR:
14977
      opt_rs_dll = rs_ssr;
14978
      break;
14979
    default:
14980
      opt_rs_dll = RPA_DEFAULT;
14981
      break;
14982
    }
14983
  //printf("RPA_SET: %i\n",opt_rs_dll);
14984
}
14985
 
14986
static void
14987
write_molstat_X_dll (char *out_buffer)
14988
{
14989
  char tmp_buf[256];
14990
  out_buffer[0] = '\0';
14991
  if (auto_ssr)                 /* v0.3n */
14992
    fix_ssr_ringcounts ();
14993
  sprintf (tmp_buf, "%d,", n_heavyatoms);
14994
  strcat (out_buffer, tmp_buf);
14995
  sprintf (tmp_buf, "%d,", n_heavybonds);
14996
  strcat (out_buffer, tmp_buf);
14997
#ifdef REDUCED_SAR
14998
  sprintf (tmp_buf, "%d,", n_countablerings);
14999
  strcat (out_buffer, tmp_buf);
15000
#else
15001
  sprintf (tmp_buf, "%d,", n_rings);
15002
  strcat (out_buffer, tmp_buf);
15003
#endif
15004
  sprintf (tmp_buf, "%d,", molstat.n_QA);
15005
  strcat (out_buffer, tmp_buf);
15006
  sprintf (tmp_buf, "%d,", molstat.n_QB);
15007
  strcat (out_buffer, tmp_buf);
15008
  //if (opt_chg)
15009
//    {                         /* 0.3x */
15010
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
15011
//    }
15012
//  else
15013
//    {
15014
  sprintf (tmp_buf, "%d,", molstat.n_chg);
15015
  //   }
15016
  strcat (out_buffer, tmp_buf);
15017
  sprintf (tmp_buf, "%d,", molstat.n_C1);
15018
  strcat (out_buffer, tmp_buf);
15019
  sprintf (tmp_buf, "%d,", molstat.n_C2);
15020
  strcat (out_buffer, tmp_buf);
15021
  sprintf (tmp_buf, "%d,", molstat.n_C);
15022
  strcat (out_buffer, tmp_buf);
15023
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
15024
  strcat (out_buffer, tmp_buf);
15025
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
15026
  strcat (out_buffer, tmp_buf);
15027
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
15028
  strcat (out_buffer, tmp_buf);
15029
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
15030
  strcat (out_buffer, tmp_buf);
15031
  sprintf (tmp_buf, "%d,", molstat.n_O2);
15032
  strcat (out_buffer, tmp_buf);
15033
  sprintf (tmp_buf, "%d,", molstat.n_O3);
15034
  strcat (out_buffer, tmp_buf);
15035
  sprintf (tmp_buf, "%d,", molstat.n_N1);
15036
  strcat (out_buffer, tmp_buf);
15037
  sprintf (tmp_buf, "%d,", molstat.n_N2);
15038
  strcat (out_buffer, tmp_buf);
15039
  sprintf (tmp_buf, "%d,", molstat.n_N3);
15040
  strcat (out_buffer, tmp_buf);
15041
  sprintf (tmp_buf, "%d,", molstat.n_S);
15042
  strcat (out_buffer, tmp_buf);
15043
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
15044
  strcat (out_buffer, tmp_buf);
15045
  sprintf (tmp_buf, "%d,", molstat.n_F);
15046
  strcat (out_buffer, tmp_buf);
15047
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
15048
  strcat (out_buffer, tmp_buf);
15049
  sprintf (tmp_buf, "%d,", molstat.n_Br);
15050
  strcat (out_buffer, tmp_buf);
15051
  sprintf (tmp_buf, "%d,", molstat.n_I);
15052
  strcat (out_buffer, tmp_buf);
15053
  sprintf (tmp_buf, "%d,", molstat.n_P);
15054
  strcat (out_buffer, tmp_buf);
15055
  sprintf (tmp_buf, "%d,", molstat.n_B);
15056
  strcat (out_buffer, tmp_buf);
15057
  sprintf (tmp_buf, "%d,", molstat.n_Met);
15058
  strcat (out_buffer, tmp_buf);
15059
  sprintf (tmp_buf, "%d,", molstat.n_X);
15060
  strcat (out_buffer, tmp_buf);
15061
  sprintf (tmp_buf, "%d,", molstat.n_b1);
15062
  strcat (out_buffer, tmp_buf);
15063
  sprintf (tmp_buf, "%d,", molstat.n_b2);
15064
  strcat (out_buffer, tmp_buf);
15065
  sprintf (tmp_buf, "%d,", molstat.n_b3);
15066
  strcat (out_buffer, tmp_buf);
15067
  sprintf (tmp_buf, "%d,", molstat.n_bar);
15068
  strcat (out_buffer, tmp_buf);
15069
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
15070
  strcat (out_buffer, tmp_buf);
15071
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
15072
  strcat (out_buffer, tmp_buf);
15073
  sprintf (tmp_buf, "%d,", molstat.n_CN);
15074
  strcat (out_buffer, tmp_buf);
15075
  sprintf (tmp_buf, "%d,", molstat.n_XY);
15076
  strcat (out_buffer, tmp_buf);
15077
  sprintf (tmp_buf, "%d,", molstat.n_r3);
15078
  strcat (out_buffer, tmp_buf);
15079
  sprintf (tmp_buf, "%d,", molstat.n_r4);
15080
  strcat (out_buffer, tmp_buf);
15081
  sprintf (tmp_buf, "%d,", molstat.n_r5);
15082
  strcat (out_buffer, tmp_buf);
15083
  sprintf (tmp_buf, "%d,", molstat.n_r6);
15084
  strcat (out_buffer, tmp_buf);
15085
  sprintf (tmp_buf, "%d,", molstat.n_r7);
15086
  strcat (out_buffer, tmp_buf);
15087
  sprintf (tmp_buf, "%d,", molstat.n_r8);
15088
  strcat (out_buffer, tmp_buf);
15089
  sprintf (tmp_buf, "%d,", molstat.n_r9);
15090
  strcat (out_buffer, tmp_buf);
15091
  sprintf (tmp_buf, "%d,", molstat.n_r10);
15092
  strcat (out_buffer, tmp_buf);
15093
  sprintf (tmp_buf, "%d,", molstat.n_r11);
15094
  strcat (out_buffer, tmp_buf);
15095
  sprintf (tmp_buf, "%d,", molstat.n_r12);
15096
  strcat (out_buffer, tmp_buf);
15097
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
15098
  strcat (out_buffer, tmp_buf);
15099
  sprintf (tmp_buf, "%d,", molstat.n_rN);
15100
  strcat (out_buffer, tmp_buf);
15101
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
15102
  strcat (out_buffer, tmp_buf);
15103
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
15104
  strcat (out_buffer, tmp_buf);
15105
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
15106
  strcat (out_buffer, tmp_buf);
15107
  sprintf (tmp_buf, "%d,", molstat.n_rO);
15108
  strcat (out_buffer, tmp_buf);
15109
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
15110
  strcat (out_buffer, tmp_buf);
15111
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
15112
  strcat (out_buffer, tmp_buf);
15113
  sprintf (tmp_buf, "%d,", molstat.n_rS);
15114
  strcat (out_buffer, tmp_buf);
15115
  sprintf (tmp_buf, "%d,", molstat.n_rX);
15116
  strcat (out_buffer, tmp_buf);
15117
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
15118
  strcat (out_buffer, tmp_buf);
15119
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
15120
  strcat (out_buffer, tmp_buf);
15121
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
15122
  strcat (out_buffer, tmp_buf);
15123
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
15124
  strcat (out_buffer, tmp_buf);
15125
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
15126
  strcat (out_buffer, tmp_buf);
15127
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
15128
  strcat (out_buffer, tmp_buf);
15129
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
15130
  strcat (out_buffer, tmp_buf);
15131
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
15132
  strcat (out_buffer, tmp_buf);
15133
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
15134
  strcat (out_buffer, tmp_buf);
15135
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
15136
  strcat (out_buffer, tmp_buf);
15137
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
15138
  strcat (out_buffer, tmp_buf);
15139
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
15140
  strcat (out_buffer, tmp_buf);
15141
  sprintf (tmp_buf, "%d,", molstat.n_psla);
15142
  strcat (out_buffer, tmp_buf);
15143
  sprintf (tmp_buf, "%d,", molstat.n_iso);
15144
  strcat (out_buffer, tmp_buf);
15145
  sprintf (tmp_buf, "%d", molstat.n_rad);
15146
  strcat (out_buffer, tmp_buf);
15147
}
15148
 
15149
static void
15150
write_molstat_dll (char *out_buffer, int mode)
15151
{
15152
  char tmp_buf[256];
15153
  char *sep1;
15154
  char *sep2;
15155
  switch (mode)
15156
    {
15157
    case 1:
15158
      sep1 = "=";
15159
      sep2 = " AND ";
15160
      break;
15161
    case 2:
15162
      sep1 = "<=";
15163
      sep2 = " AND ";
15164
      break;
15165
    default:
15166
      sep1 = ":";
15167
      sep2 = ";";
15168
      break;
15169
    }
15170
 
15171
 
15172
 
15173
  out_buffer[0] = '\0';
15174
 
15175
  if (auto_ssr)                 /* v0.3n */
15176
    fix_ssr_ringcounts ();
15177
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
15178
  strcat (out_buffer, tmp_buf);
15179
  if (n_bonds > 0)
15180
    {
15181
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
15182
      strcat (out_buffer, tmp_buf);
15183
    }
15184
 
15185
#ifdef REDUCED_SAR
15186
  if (n_rings > 0)
15187
    {
15188
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
15189
      strcat (out_buffer, tmp_buf);
15190
    }
15191
#else
15192
  if (n_rings > 0)
15193
    {
15194
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
15195
      strcat (out_buffer, tmp_buf);
15196
    }
15197
#endif
15198
 
15199
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */
15200
    {
15201
      sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
15202
      strcat (out_buffer, tmp_buf);
15203
    }
15204
  if (molstat.n_C1 > 0)
15205
    {
15206
      sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
15207
      strcat (out_buffer, tmp_buf);
15208
    }
15209
  if (molstat.n_C2 > 0)
15210
    {
15211
      sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
15212
      strcat (out_buffer, tmp_buf);
15213
    }
15214
 
15215
 
15216
  if (molstat.n_C > 0)
15217
    {
15218
      sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
15219
      strcat (out_buffer, tmp_buf);
15220
    }
15221
  if (molstat.n_CHB1p > 0)
15222
    {
15223
      sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
15224
      strcat (out_buffer, tmp_buf);
15225
    }
15226
  if (molstat.n_CHB2p > 0)
15227
    {
15228
      sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
15229
      strcat (out_buffer, tmp_buf);
15230
    }
15231
  if (molstat.n_CHB3p > 0)
15232
    {
15233
      sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
15234
      strcat (out_buffer, tmp_buf);
15235
    }
15236
  if (molstat.n_CHB4 > 0)
15237
    {
15238
      sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
15239
      strcat (out_buffer, tmp_buf);
15240
    }
15241
  if (molstat.n_O2 > 0)
15242
    {
15243
      sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
15244
      strcat (out_buffer, tmp_buf);
15245
    }
15246
  if (molstat.n_O3 > 0)
15247
    {
15248
      sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
15249
      strcat (out_buffer, tmp_buf);
15250
    }
15251
  if (molstat.n_N1 > 0)
15252
    {
15253
      sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
15254
      strcat (out_buffer, tmp_buf);
15255
    }
15256
  if (molstat.n_N2 > 0)
15257
    {
15258
      sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
15259
      strcat (out_buffer, tmp_buf);
15260
    }
15261
  if (molstat.n_N3 > 0)
15262
    {
15263
      sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
15264
      strcat (out_buffer, tmp_buf);
15265
    }
15266
  if (molstat.n_S > 0)
15267
    {
15268
      sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
15269
      strcat (out_buffer, tmp_buf);
15270
    }
15271
  if (molstat.n_SeTe > 0)
15272
    {
15273
      sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
15274
      strcat (out_buffer, tmp_buf);
15275
    }
15276
  if (molstat.n_F > 0)
15277
    {
15278
      sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
15279
      strcat (out_buffer, tmp_buf);
15280
    }
15281
  if (molstat.n_Cl > 0)
15282
    {
15283
      sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
15284
      strcat (out_buffer, tmp_buf);
15285
    }
15286
  if (molstat.n_Br > 0)
15287
    {
15288
      sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
15289
      strcat (out_buffer, tmp_buf);
15290
    }
15291
  if (molstat.n_I > 0)
15292
    {
15293
      sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
15294
      strcat (out_buffer, tmp_buf);
15295
    }
15296
  if (molstat.n_P > 0)
15297
    {
15298
      sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
15299
      strcat (out_buffer, tmp_buf);
15300
    }
15301
  if (molstat.n_B > 0)
15302
    {
15303
      sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
15304
      strcat (out_buffer, tmp_buf);
15305
    }
15306
  if (molstat.n_Met > 0)
15307
    {
15308
      sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
15309
      strcat (out_buffer, tmp_buf);
15310
    }
15311
  if (molstat.n_X > 0)
15312
    {
15313
      sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
15314
      strcat (out_buffer, tmp_buf);
15315
    }
15316
  if (molstat.n_b1 > 0)
15317
    {
15318
      sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
15319
      strcat (out_buffer, tmp_buf);
15320
    }
15321
  if (molstat.n_b2 > 0)
15322
    {
15323
      sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
15324
      strcat (out_buffer, tmp_buf);
15325
    }
15326
  if (molstat.n_b3 > 0)
15327
    {
15328
      sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
15329
      strcat (out_buffer, tmp_buf);
15330
    }
15331
  if (molstat.n_bar > 0)
15332
    {
15333
      sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
15334
      strcat (out_buffer, tmp_buf);
15335
    }
15336
  if (molstat.n_C1O > 0)
15337
    {
15338
      sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
15339
      strcat (out_buffer, tmp_buf);
15340
    }
15341
  if (molstat.n_C2O > 0)
15342
    {
15343
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
15344
      strcat (out_buffer, tmp_buf);
15345
    }
15346
  if (molstat.n_CN > 0)
15347
    {
15348
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
15349
      strcat (out_buffer, tmp_buf);
15350
    }
15351
  if (molstat.n_XY > 0)
15352
    {
15353
      sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
15354
      strcat (out_buffer, tmp_buf);
15355
    }
15356
  if (molstat.n_r3 > 0)
15357
    {
15358
      sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
15359
      strcat (out_buffer, tmp_buf);
15360
    }
15361
  if (molstat.n_r4 > 0)
15362
    {
15363
      sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
15364
      strcat (out_buffer, tmp_buf);
15365
    }
15366
  if (molstat.n_r5 > 0)
15367
    {
15368
      sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
15369
      strcat (out_buffer, tmp_buf);
15370
    }
15371
  if (molstat.n_r6 > 0)
15372
    {
15373
      sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
15374
      strcat (out_buffer, tmp_buf);
15375
    }
15376
  if (molstat.n_r7 > 0)
15377
    {
15378
      sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
15379
      strcat (out_buffer, tmp_buf);
15380
    }
15381
  if (molstat.n_r8 > 0)
15382
    {
15383
      sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
15384
      strcat (out_buffer, tmp_buf);
15385
    }
15386
  if (molstat.n_r9 > 0)
15387
    {
15388
      sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
15389
      strcat (out_buffer, tmp_buf);
15390
    }
15391
  if (molstat.n_r10 > 0)
15392
    {
15393
      sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
15394
      strcat (out_buffer, tmp_buf);
15395
    }
15396
  if (molstat.n_r11 > 0)
15397
    {
15398
      sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
15399
      strcat (out_buffer, tmp_buf);
15400
    }
15401
  if (molstat.n_r12 > 0)
15402
    {
15403
      sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
15404
      strcat (out_buffer, tmp_buf);
15405
    }
15406
  if (molstat.n_r13p > 0)
15407
    {
15408
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
15409
      strcat (out_buffer, tmp_buf);
15410
    }
15411
  if (molstat.n_rN > 0)
15412
    {
15413
      sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
15414
      strcat (out_buffer, tmp_buf);
15415
    }
15416
  if (molstat.n_rN1 > 0)
15417
    {
15418
      sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
15419
      strcat (out_buffer, tmp_buf);
15420
    }
15421
  if (molstat.n_rN2 > 0)
15422
    {
15423
      sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
15424
      strcat (out_buffer, tmp_buf);
15425
    }
15426
  if (molstat.n_rN3p > 0)
15427
    {
15428
      sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
15429
      strcat (out_buffer, tmp_buf);
15430
    }
15431
  if (molstat.n_rO > 0)
15432
    {
15433
      sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
15434
      strcat (out_buffer, tmp_buf);
15435
    }
15436
  if (molstat.n_rO1 > 0)
15437
    {
15438
      sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
15439
      strcat (out_buffer, tmp_buf);
15440
    }
15441
  if (molstat.n_rO2p > 0)
15442
    {
15443
      sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
15444
      strcat (out_buffer, tmp_buf);
15445
    }
15446
  if (molstat.n_rS > 0)
15447
    {
15448
      sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
15449
      strcat (out_buffer, tmp_buf);
15450
    }
15451
  if (molstat.n_rX > 0)
15452
    {
15453
      sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
15454
      strcat (out_buffer, tmp_buf);
15455
    }
15456
  if (molstat.n_rAr > 0)
15457
    {
15458
      sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
15459
      strcat (out_buffer, tmp_buf);
15460
    }
15461
 
15462
  if (molstat.n_rBz > 0)
15463
    {
15464
      sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
15465
      strcat (out_buffer, tmp_buf);
15466
    }
15467
 
15468
  if (molstat.n_br2p > 0)
15469
    {
15470
      sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
15471
      strcat (out_buffer, tmp_buf);
15472
    }
15473
 
15474
  if (molstat.n_psg01 > 0)
15475
    {
15476
      sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
15477
      strcat (out_buffer, tmp_buf);
15478
    }
15479
 
15480
  if (molstat.n_psg02 > 0)
15481
    {
15482
      sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
15483
      strcat (out_buffer, tmp_buf);
15484
    }
15485
 
15486
  if (molstat.n_psg13 > 0)
15487
    {
15488
      sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
15489
      strcat (out_buffer, tmp_buf);
15490
    }
15491
 
15492
  if (molstat.n_psg14 > 0)
15493
    {
15494
      sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
15495
      strcat (out_buffer, tmp_buf);
15496
    }
15497
 
15498
  if (molstat.n_psg15 > 0)
15499
    {
15500
      sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
15501
      strcat (out_buffer, tmp_buf);
15502
    }
15503
 
15504
  if (molstat.n_psg16 > 0)
15505
    {
15506
      sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
15507
      strcat (out_buffer, tmp_buf);
15508
    }
15509
 
15510
  if (molstat.n_psg17 > 0)
15511
    {
15512
      sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
15513
      strcat (out_buffer, tmp_buf);
15514
    }
15515
 
15516
  if (molstat.n_psg18 > 0)
15517
    {
15518
      sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
15519
      strcat (out_buffer, tmp_buf);
15520
    }
15521
 
15522
  if (molstat.n_pstm > 0)
15523
    {
15524
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
15525
      strcat (out_buffer, tmp_buf);
15526
    }
15527
 
15528
  if (molstat.n_psla > 0)
15529
    {
15530
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
15531
      strcat (out_buffer, tmp_buf);
15532
    }
15533
 
15534
  if (opt_iso && molstat.n_iso > 0)
15535
    {
15536
      sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
15537
      strcat (out_buffer, tmp_buf);
15538
    }
15539
 
15540
  if (opt_rad && molstat.n_rad > 0)
15541
    {
15542
      sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
15543
      strcat (out_buffer, tmp_buf);
15544
    }
15545
}
15546
 
15547
static void
15548
write_fg_code_dll (char *out_buffer)
15549
{
15550
  char tmp_buf[256];
15551
  out_buffer[0] = '\0';
15552
  if (fg[fg_cation - 1])
15553
    {
15554
      sprintf (tmp_buf, "000000T2;");
15555
      strcat (out_buffer, tmp_buf);
15556
    }
15557
  if (fg[fg_anion - 1])
15558
    {
15559
      sprintf (tmp_buf, "000000T1;");
15560
      strcat (out_buffer, tmp_buf);
15561
    }
15562
 
15563
  if (fg[fg_aldehyde - 1])
15564
    {
15565
      sprintf (tmp_buf, "C2O1H000;");
15566
      strcat (out_buffer, tmp_buf);
15567
    }
15568
  if (fg[fg_ketone - 1])
15569
    {
15570
      sprintf (tmp_buf, "C2O1C000;");
15571
      strcat (out_buffer, tmp_buf);
15572
    }
15573
 
15574
  if (fg[fg_thioaldehyde - 1])
15575
    {
15576
      sprintf (tmp_buf, "C2S1H000;");
15577
      strcat (out_buffer, tmp_buf);
15578
    }
15579
  if (fg[fg_thioketone - 1])
15580
    {
15581
      sprintf (tmp_buf, "C2S1C000;");
15582
      strcat (out_buffer, tmp_buf);
15583
    }
15584
  if (fg[fg_imine - 1])
15585
    {
15586
      sprintf (tmp_buf, "C2N10000;");
15587
      strcat (out_buffer, tmp_buf);
15588
    }
15589
  if (fg[fg_hydrazone - 1])
15590
    {
15591
      sprintf (tmp_buf, "C2N1N000;");
15592
      strcat (out_buffer, tmp_buf);
15593
    }
15594
  if (fg[fg_semicarbazone - 1])
15595
    {
15596
      sprintf (tmp_buf, "C2NNC4ON;");
15597
      strcat (out_buffer, tmp_buf);
15598
    }
15599
  if (fg[fg_thiosemicarbazone - 1])
15600
    {
15601
      sprintf (tmp_buf, "C2NNC4SN;");
15602
      strcat (out_buffer, tmp_buf);
15603
    }
15604
  if (fg[fg_oxime - 1])
15605
    {
15606
      sprintf (tmp_buf, "C2N1OH00;");
15607
      strcat (out_buffer, tmp_buf);
15608
    }
15609
  if (fg[fg_oxime_ether - 1])
15610
    {
15611
      sprintf (tmp_buf, "C2N1OC00;");
15612
      strcat (out_buffer, tmp_buf);
15613
    }
15614
  if (fg[fg_ketene - 1])
15615
    {
15616
      sprintf (tmp_buf, "C3OC0000;");
15617
      strcat (out_buffer, tmp_buf);
15618
    }
15619
  if (fg[fg_ketene_acetal_deriv - 1])
15620
    {
15621
      sprintf (tmp_buf, "C3OCC000;");
15622
      strcat (out_buffer, tmp_buf);
15623
    }
15624
  if (fg[fg_carbonyl_hydrate - 1])
15625
    {
15626
      sprintf (tmp_buf, "C2O2H200;");
15627
      strcat (out_buffer, tmp_buf);
15628
    }
15629
  if (fg[fg_hemiacetal - 1])
15630
    {
15631
      sprintf (tmp_buf, "C2O2HC00;");
15632
      strcat (out_buffer, tmp_buf);
15633
    }
15634
  if (fg[fg_acetal - 1])
15635
    {
15636
      sprintf (tmp_buf, "C2O2CC00;");
15637
      strcat (out_buffer, tmp_buf);
15638
    }
15639
  if (fg[fg_hemiaminal - 1])
15640
    {
15641
      sprintf (tmp_buf, "C2NOHC10;");
15642
      strcat (out_buffer, tmp_buf);
15643
    }
15644
  if (fg[fg_aminal - 1])
15645
    {
15646
      sprintf (tmp_buf, "C2N2CC10;");
15647
      strcat (out_buffer, tmp_buf);
15648
    }
15649
  if (fg[fg_thiohemiaminal - 1])
15650
    {
15651
      sprintf (tmp_buf, "C2NSHC10;");
15652
      strcat (out_buffer, tmp_buf);
15653
    }
15654
  if (fg[fg_thioacetal - 1])
15655
    {
15656
      sprintf (tmp_buf, "C2S2CC00;");
15657
      strcat (out_buffer, tmp_buf);
15658
    }
15659
  if (fg[fg_enamine - 1])
15660
    {
15661
      sprintf (tmp_buf, "C2CNH000;");
15662
      strcat (out_buffer, tmp_buf);
15663
    }
15664
  if (fg[fg_enol - 1])
15665
    {
15666
      sprintf (tmp_buf, "C2COH000;");
15667
      strcat (out_buffer, tmp_buf);
15668
    }
15669
  if (fg[fg_enolether - 1])
15670
    {
15671
      sprintf (tmp_buf, "C2COC000;");
15672
      strcat (out_buffer, tmp_buf);
15673
    }
15674
 
15675
 
15676
  if (fg[fg_prim_alcohol - 1])
15677
    {
15678
      sprintf (tmp_buf, "O1H1C000;");
15679
      strcat (out_buffer, tmp_buf);
15680
    }
15681
  if (fg[fg_sec_alcohol - 1])
15682
    {
15683
      sprintf (tmp_buf, "O1H2C000;");
15684
      strcat (out_buffer, tmp_buf);
15685
    }
15686
  if (fg[fg_tert_alcohol - 1])
15687
    {
15688
      sprintf (tmp_buf, "O1H3C000;");
15689
      strcat (out_buffer, tmp_buf);
15690
    }
15691
  if (fg[fg_1_2_diol - 1])
15692
    {
15693
      sprintf (tmp_buf, "O1H0CO1H;");
15694
      strcat (out_buffer, tmp_buf);
15695
    }
15696
  if (fg[fg_1_2_aminoalcohol - 1])
15697
    {
15698
      sprintf (tmp_buf, "O1H0CN1C;");
15699
      strcat (out_buffer, tmp_buf);
15700
    }
15701
  if (fg[fg_phenol - 1])
15702
    {
15703
      sprintf (tmp_buf, "O1H1A000;");
15704
      strcat (out_buffer, tmp_buf);
15705
    }
15706
  if (fg[fg_1_2_diphenol - 1])
15707
    {
15708
      sprintf (tmp_buf, "O1H2A000;");
15709
      strcat (out_buffer, tmp_buf);
15710
    }
15711
  if (fg[fg_enediol - 1])
15712
    {
15713
      sprintf (tmp_buf, "C2COH200;");
15714
      strcat (out_buffer, tmp_buf);
15715
    }
15716
 
15717
  if (fg[fg_dialkylether - 1])
15718
    {
15719
      sprintf (tmp_buf, "O1C0CC00;");
15720
      strcat (out_buffer, tmp_buf);
15721
    }
15722
  if (fg[fg_alkylarylether - 1])
15723
    {
15724
      sprintf (tmp_buf, "O1C0CA00;");
15725
      strcat (out_buffer, tmp_buf);
15726
    }
15727
  if (fg[fg_diarylether - 1])
15728
    {
15729
      sprintf (tmp_buf, "O1C0AA00;");
15730
      strcat (out_buffer, tmp_buf);
15731
    }
15732
  if (fg[fg_thioether - 1])
15733
    {
15734
      sprintf (tmp_buf, "S1C00000;");
15735
      strcat (out_buffer, tmp_buf);
15736
    }
15737
  if (fg[fg_disulfide - 1])
15738
    {
15739
      sprintf (tmp_buf, "S1S1C000;");
15740
      strcat (out_buffer, tmp_buf);
15741
    }
15742
  if (fg[fg_peroxide - 1])
15743
    {
15744
      sprintf (tmp_buf, "O1O1C000;");
15745
      strcat (out_buffer, tmp_buf);
15746
    }
15747
  if (fg[fg_hydroperoxide - 1])
15748
    {
15749
      sprintf (tmp_buf, "O1O1H000;");
15750
      strcat (out_buffer, tmp_buf);
15751
    }
15752
  if (fg[fg_hydrazine - 1])
15753
    {
15754
      sprintf (tmp_buf, "N1N10000;");
15755
      strcat (out_buffer, tmp_buf);
15756
    }
15757
  if (fg[fg_hydroxylamine - 1])
15758
    {
15759
      sprintf (tmp_buf, "N1O1H000;");
15760
      strcat (out_buffer, tmp_buf);
15761
    }
15762
 
15763
 
15764
  if (fg[fg_prim_aliph_amine - 1])
15765
    {
15766
      sprintf (tmp_buf, "N1C1C000;");
15767
      strcat (out_buffer, tmp_buf);
15768
    }
15769
  if (fg[fg_prim_arom_amine - 1])
15770
    {
15771
      sprintf (tmp_buf, "N1C1A000;");
15772
      strcat (out_buffer, tmp_buf);
15773
    }
15774
 
15775
  if (fg[fg_sec_aliph_amine - 1])
15776
    {
15777
      sprintf (tmp_buf, "N1C2CC00;");
15778
      strcat (out_buffer, tmp_buf);
15779
    }
15780
  if (fg[fg_sec_mixed_amine - 1])
15781
    {
15782
      sprintf (tmp_buf, "N1C2AC00;");
15783
      strcat (out_buffer, tmp_buf);
15784
    }
15785
  if (fg[fg_sec_arom_amine - 1])
15786
    {
15787
      sprintf (tmp_buf, "N1C2AA00;");
15788
      strcat (out_buffer, tmp_buf);
15789
    }
15790
 
15791
  if (fg[fg_tert_aliph_amine - 1])
15792
    {
15793
      sprintf (tmp_buf, "N1C3CC00;");
15794
      strcat (out_buffer, tmp_buf);
15795
    }
15796
  if (fg[fg_tert_mixed_amine - 1])
15797
    {
15798
      sprintf (tmp_buf, "N1C3AC00;");
15799
      strcat (out_buffer, tmp_buf);
15800
    }
15801
  if (fg[fg_tert_arom_amine - 1])
15802
    {
15803
      sprintf (tmp_buf, "N1C3AA00;");
15804
      strcat (out_buffer, tmp_buf);
15805
    }
15806
  if (fg[fg_quart_ammonium - 1])
15807
    {
15808
      sprintf (tmp_buf, "N1C400T2;");
15809
      strcat (out_buffer, tmp_buf);
15810
    }
15811
  if (fg[fg_n_oxide - 1])
15812
    {
15813
      sprintf (tmp_buf, "N0O10000;");
15814
      strcat (out_buffer, tmp_buf);
15815
    }
15816
 
15817
 
15818
  if (fg[fg_halogen_deriv - 1])
15819
    {
15820
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
15821
          !fg[fg_acyl_halide - 1])
15822
        {
15823
          sprintf (tmp_buf, "XX000000;");
15824
          strcat (out_buffer, tmp_buf);
15825
        }
15826
    }
15827
 
15828
  if (fg[fg_alkyl_fluoride - 1])
15829
    {
15830
      sprintf (tmp_buf, "XF00C000;");
15831
      strcat (out_buffer, tmp_buf);
15832
    }
15833
  if (fg[fg_alkyl_chloride - 1])
15834
    {
15835
      sprintf (tmp_buf, "XC00C000;");
15836
      strcat (out_buffer, tmp_buf);
15837
    }
15838
  if (fg[fg_alkyl_bromide - 1])
15839
    {
15840
      sprintf (tmp_buf, "XB00C000;");
15841
      strcat (out_buffer, tmp_buf);
15842
    }
15843
  if (fg[fg_alkyl_iodide - 1])
15844
    {
15845
      sprintf (tmp_buf, "XI00C000;");
15846
      strcat (out_buffer, tmp_buf);
15847
    }
15848
 
15849
  if (fg[fg_aryl_fluoride - 1])
15850
    {
15851
      sprintf (tmp_buf, "XF00A000;");
15852
      strcat (out_buffer, tmp_buf);
15853
    }
15854
  if (fg[fg_aryl_chloride - 1])
15855
    {
15856
      sprintf (tmp_buf, "XC00A000;");
15857
      strcat (out_buffer, tmp_buf);
15858
    }
15859
  if (fg[fg_aryl_bromide - 1])
15860
    {
15861
      sprintf (tmp_buf, "XB00A000;");
15862
      strcat (out_buffer, tmp_buf);
15863
    }
15864
  if (fg[fg_aryl_iodide - 1])
15865
    {
15866
      sprintf (tmp_buf, "XI00A000;");
15867
      strcat (out_buffer, tmp_buf);
15868
    }
15869
  if (fg[fg_organometallic - 1])
15870
    {
15871
      sprintf (tmp_buf, "000000MX;");
15872
      strcat (out_buffer, tmp_buf);
15873
    }
15874
  if (fg[fg_organolithium - 1])
15875
    {
15876
      sprintf (tmp_buf, "000000ML;");
15877
      strcat (out_buffer, tmp_buf);
15878
    }
15879
  if (fg[fg_organomagnesium - 1])
15880
    {
15881
      sprintf (tmp_buf, "000000MM;");
15882
      strcat (out_buffer, tmp_buf);
15883
    }
15884
 
15885
  if (fg[fg_carboxylic_acid - 1])
15886
    {
15887
      sprintf (tmp_buf, "C3O2H000;");
15888
      strcat (out_buffer, tmp_buf);
15889
    }
15890
  if (fg[fg_carboxylic_acid_salt - 1])
15891
    {
15892
      sprintf (tmp_buf, "C3O200T1;");
15893
      strcat (out_buffer, tmp_buf);
15894
    }
15895
  if (fg[fg_carboxylic_acid_ester - 1])
15896
    {
15897
      sprintf (tmp_buf, "C3O2C000;");
15898
      strcat (out_buffer, tmp_buf);
15899
    }
15900
  if (fg[fg_lactone - 1])
15901
    {
15902
      sprintf (tmp_buf, "C3O2CZ00;");
15903
      strcat (out_buffer, tmp_buf);
15904
    }
15905
 
15906
  if (fg[fg_carboxylic_acid_prim_amide - 1])
15907
    {
15908
      sprintf (tmp_buf, "C3ONC100;");
15909
      strcat (out_buffer, tmp_buf);
15910
    }
15911
  if (fg[fg_carboxylic_acid_sec_amide - 1])
15912
    {
15913
      sprintf (tmp_buf, "C3ONC200;");
15914
      strcat (out_buffer, tmp_buf);
15915
    }
15916
  if (fg[fg_carboxylic_acid_tert_amide - 1])
15917
    {
15918
      sprintf (tmp_buf, "C3ONC300;");
15919
      strcat (out_buffer, tmp_buf);
15920
    }
15921
  if (fg[fg_lactam - 1])
15922
    {
15923
      sprintf (tmp_buf, "C3ONCZ00;");
15924
      strcat (out_buffer, tmp_buf);
15925
    }
15926
  if (fg[fg_carboxylic_acid_hydrazide - 1])
15927
    {
15928
      sprintf (tmp_buf, "C3ONN100;");
15929
      strcat (out_buffer, tmp_buf);
15930
    }
15931
  if (fg[fg_carboxylic_acid_azide - 1])
15932
    {
15933
      sprintf (tmp_buf, "C3ONN200;");
15934
      strcat (out_buffer, tmp_buf);
15935
    }
15936
  if (fg[fg_hydroxamic_acid - 1])
15937
    {
15938
      sprintf (tmp_buf, "C3ONOH00;");
15939
      strcat (out_buffer, tmp_buf);
15940
    }
15941
  if (fg[fg_carboxylic_acid_amidine - 1])
15942
    {
15943
      sprintf (tmp_buf, "C3N2H000;");
15944
      strcat (out_buffer, tmp_buf);
15945
    }
15946
  if (fg[fg_carboxylic_acid_amidrazone - 1])
15947
    {
15948
      sprintf (tmp_buf, "C3NNN100;");
15949
      strcat (out_buffer, tmp_buf);
15950
    }
15951
  if (fg[fg_nitrile - 1])
15952
    {
15953
      sprintf (tmp_buf, "C3N00000;");
15954
      strcat (out_buffer, tmp_buf);
15955
    }
15956
 
15957
  if (fg[fg_acyl_fluoride - 1])
15958
    {
15959
      sprintf (tmp_buf, "C3OXF000;");
15960
      strcat (out_buffer, tmp_buf);
15961
    }
15962
  if (fg[fg_acyl_chloride - 1])
15963
    {
15964
      sprintf (tmp_buf, "C3OXC000;");
15965
      strcat (out_buffer, tmp_buf);
15966
    }
15967
  if (fg[fg_acyl_bromide - 1])
15968
    {
15969
      sprintf (tmp_buf, "C3OXB000;");
15970
      strcat (out_buffer, tmp_buf);
15971
    }
15972
  if (fg[fg_acyl_iodide - 1])
15973
    {
15974
      sprintf (tmp_buf, "C3OXI000;");
15975
      strcat (out_buffer, tmp_buf);
15976
    }
15977
  if (fg[fg_acyl_cyanide - 1])
15978
    {
15979
      sprintf (tmp_buf, "C2OC3N00;");
15980
      strcat (out_buffer, tmp_buf);
15981
    }
15982
  if (fg[fg_imido_ester - 1])
15983
    {
15984
      sprintf (tmp_buf, "C3NOC000;");
15985
      strcat (out_buffer, tmp_buf);
15986
    }
15987
  if (fg[fg_imidoyl_halide - 1])
15988
    {
15989
      sprintf (tmp_buf, "C3NXX000;");
15990
      strcat (out_buffer, tmp_buf);
15991
    }
15992
 
15993
  if (fg[fg_thiocarboxylic_acid - 1])
15994
    {
15995
      sprintf (tmp_buf, "C3SOH000;");
15996
      strcat (out_buffer, tmp_buf);
15997
    }
15998
  if (fg[fg_thiocarboxylic_acid_ester - 1])
15999
    {
16000
      sprintf (tmp_buf, "C3SOC000;");
16001
      strcat (out_buffer, tmp_buf);
16002
    }
16003
  if (fg[fg_thiolactone - 1])
16004
    {
16005
      sprintf (tmp_buf, "C3SOCZ00;");
16006
      strcat (out_buffer, tmp_buf);
16007
    }
16008
  if (fg[fg_thiocarboxylic_acid_amide - 1])
16009
    {
16010
      sprintf (tmp_buf, "C3SNH000;");
16011
      strcat (out_buffer, tmp_buf);
16012
    }
16013
  if (fg[fg_thiolactam - 1])
16014
    {
16015
      sprintf (tmp_buf, "C3SNCZ00;");
16016
      strcat (out_buffer, tmp_buf);
16017
    }
16018
  if (fg[fg_imido_thioester - 1])
16019
    {
16020
      sprintf (tmp_buf, "C3NSC000;");
16021
      strcat (out_buffer, tmp_buf);
16022
    }
16023
  if (fg[fg_oxohetarene - 1])
16024
    {
16025
      sprintf (tmp_buf, "C3ONAZ00;");
16026
      strcat (out_buffer, tmp_buf);
16027
    }
16028
  if (fg[fg_thioxohetarene - 1])
16029
    {
16030
      sprintf (tmp_buf, "C3SNAZ00;");
16031
      strcat (out_buffer, tmp_buf);
16032
    }
16033
  if (fg[fg_iminohetarene - 1])
16034
    {
16035
      sprintf (tmp_buf, "C3NNAZ00;");
16036
      strcat (out_buffer, tmp_buf);
16037
    }
16038
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
16039
    {
16040
      sprintf (tmp_buf, "C3O30000;");
16041
      strcat (out_buffer, tmp_buf);
16042
    }
16043
  if (fg[fg_carboxylic_acid_orthoester - 1])
16044
    {
16045
      sprintf (tmp_buf, "C3O3C000;");
16046
      strcat (out_buffer, tmp_buf);
16047
    }
16048
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
16049
    {
16050
      sprintf (tmp_buf, "C3O3NC00;");
16051
      strcat (out_buffer, tmp_buf);
16052
    }
16053
  if (fg[fg_carboxylic_acid_anhydride - 1])
16054
    {
16055
      sprintf (tmp_buf, "C3O2C3O2;");
16056
      strcat (out_buffer, tmp_buf);
16057
    }
16058
 
16059
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
16060
    {
16061
      sprintf (tmp_buf, "C3ONCH10;");
16062
      strcat (out_buffer, tmp_buf);
16063
    }
16064
  if (fg[fg_carboxylic_acid_subst_imide - 1])
16065
    {
16066
      sprintf (tmp_buf, "C3ONCC10;");
16067
      strcat (out_buffer, tmp_buf);
16068
    }
16069
  if (fg[fg_co2_deriv - 1])
16070
    {
16071
      sprintf (tmp_buf, "C4000000;");
16072
      strcat (out_buffer, tmp_buf);
16073
    }
16074
  if (fg[fg_carbonic_acid_deriv - 1])
16075
    {
16076
      sprintf (tmp_buf, "C4O30000;");
16077
      strcat (out_buffer, tmp_buf);
16078
    }
16079
  if (fg[fg_carbonic_acid_monoester - 1])
16080
    {
16081
      sprintf (tmp_buf, "C4O3C100;");
16082
      strcat (out_buffer, tmp_buf);
16083
    }
16084
  if (fg[fg_carbonic_acid_diester - 1])
16085
    {
16086
      sprintf (tmp_buf, "C4O3C200;");
16087
      strcat (out_buffer, tmp_buf);
16088
    }
16089
  if (fg[fg_carbonic_acid_ester_halide - 1])
16090
    {
16091
      sprintf (tmp_buf, "C4O3CX00;");
16092
      strcat (out_buffer, tmp_buf);
16093
    }
16094
  if (fg[fg_thiocarbonic_acid_deriv - 1])
16095
    {
16096
      sprintf (tmp_buf, "C4SO0000;");
16097
      strcat (out_buffer, tmp_buf);
16098
    }
16099
  if (fg[fg_thiocarbonic_acid_monoester - 1])
16100
    {
16101
      sprintf (tmp_buf, "C4SOC100;");
16102
      strcat (out_buffer, tmp_buf);
16103
    }
16104
  if (fg[fg_thiocarbonic_acid_diester - 1])
16105
    {
16106
      sprintf (tmp_buf, "C4SOC200;");
16107
      strcat (out_buffer, tmp_buf);
16108
    }
16109
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
16110
    {
16111
      sprintf (tmp_buf, "C4SOX_00;");
16112
      strcat (out_buffer, tmp_buf);
16113
    }
16114
  if (fg[fg_carbamic_acid_deriv - 1])
16115
    {
16116
      sprintf (tmp_buf, "C4O2N000;");
16117
      strcat (out_buffer, tmp_buf);
16118
    }
16119
  if (fg[fg_carbamic_acid - 1])
16120
    {
16121
      sprintf (tmp_buf, "C4O2NH00;");
16122
      strcat (out_buffer, tmp_buf);
16123
    }
16124
  if (fg[fg_carbamic_acid_ester - 1])
16125
    {
16126
      sprintf (tmp_buf, "C4O2NC00;");
16127
      strcat (out_buffer, tmp_buf);
16128
    }
16129
  if (fg[fg_carbamic_acid_halide - 1])
16130
    {
16131
      sprintf (tmp_buf, "C4O2NX00;");
16132
      strcat (out_buffer, tmp_buf);
16133
    }
16134
  if (fg[fg_thiocarbamic_acid_deriv - 1])
16135
    {
16136
      sprintf (tmp_buf, "C4SN0000;");
16137
      strcat (out_buffer, tmp_buf);
16138
    }
16139
  if (fg[fg_thiocarbamic_acid - 1])
16140
    {
16141
      sprintf (tmp_buf, "C4SNOH00;");
16142
      strcat (out_buffer, tmp_buf);
16143
    }
16144
  if (fg[fg_thiocarbamic_acid_ester - 1])
16145
    {
16146
      sprintf (tmp_buf, "C4SNOC00;");
16147
      strcat (out_buffer, tmp_buf);
16148
    }
16149
  if (fg[fg_thiocarbamic_acid_halide - 1])
16150
    {
16151
      sprintf (tmp_buf, "C4SNXX00;");
16152
      strcat (out_buffer, tmp_buf);
16153
    }
16154
  if (fg[fg_urea - 1])
16155
    {
16156
      sprintf (tmp_buf, "C4O1N200;");
16157
      strcat (out_buffer, tmp_buf);
16158
    }
16159
  if (fg[fg_isourea - 1])
16160
    {
16161
      sprintf (tmp_buf, "C4N2O100;");
16162
      strcat (out_buffer, tmp_buf);
16163
    }
16164
  if (fg[fg_thiourea - 1])
16165
    {
16166
      sprintf (tmp_buf, "C4S1N200;");
16167
      strcat (out_buffer, tmp_buf);
16168
    }
16169
  if (fg[fg_isothiourea - 1])
16170
    {
16171
      sprintf (tmp_buf, "C4N2S100;");
16172
      strcat (out_buffer, tmp_buf);
16173
    }
16174
  if (fg[fg_guanidine - 1])
16175
    {
16176
      sprintf (tmp_buf, "C4N30000;");
16177
      strcat (out_buffer, tmp_buf);
16178
    }
16179
  if (fg[fg_semicarbazide - 1])
16180
    {
16181
      sprintf (tmp_buf, "C4ON2N00;");
16182
      strcat (out_buffer, tmp_buf);
16183
    }
16184
  if (fg[fg_thiosemicarbazide - 1])
16185
    {
16186
      sprintf (tmp_buf, "C4SN2N00;");
16187
      strcat (out_buffer, tmp_buf);
16188
    }
16189
  if (fg[fg_azide - 1])
16190
    {
16191
      sprintf (tmp_buf, "N4N20000;");
16192
      strcat (out_buffer, tmp_buf);
16193
    }
16194
  if (fg[fg_azo_compound - 1])
16195
    {
16196
      sprintf (tmp_buf, "N2N10000;");
16197
      strcat (out_buffer, tmp_buf);
16198
    }
16199
  if (fg[fg_diazonium_salt - 1])
16200
    {
16201
      sprintf (tmp_buf, "N3N100T2;");
16202
      strcat (out_buffer, tmp_buf);
16203
    }
16204
  if (fg[fg_isonitrile - 1])
16205
    {
16206
      sprintf (tmp_buf, "N3C10000;");
16207
      strcat (out_buffer, tmp_buf);
16208
    }
16209
  if (fg[fg_cyanate - 1])
16210
    {
16211
      sprintf (tmp_buf, "C4NO1000;");
16212
      strcat (out_buffer, tmp_buf);
16213
    }
16214
  if (fg[fg_isocyanate - 1])
16215
    {
16216
      sprintf (tmp_buf, "C4NO2000;");
16217
      strcat (out_buffer, tmp_buf);
16218
    }
16219
  if (fg[fg_thiocyanate - 1])
16220
    {
16221
      sprintf (tmp_buf, "C4NS1000;");
16222
      strcat (out_buffer, tmp_buf);
16223
    }
16224
  if (fg[fg_isothiocyanate - 1])
16225
    {
16226
      sprintf (tmp_buf, "C4NS2000;");
16227
      strcat (out_buffer, tmp_buf);
16228
    }
16229
  if (fg[fg_carbodiimide - 1])
16230
    {
16231
      sprintf (tmp_buf, "C4N20000;");
16232
      strcat (out_buffer, tmp_buf);
16233
    }
16234
  if (fg[fg_nitroso_compound - 1])
16235
    {
16236
      sprintf (tmp_buf, "N2O10000;");
16237
      strcat (out_buffer, tmp_buf);
16238
    }
16239
  if (fg[fg_nitro_compound - 1])
16240
    {
16241
      sprintf (tmp_buf, "N4O20000;");
16242
      strcat (out_buffer, tmp_buf);
16243
    }
16244
  if (fg[fg_nitrite - 1])
16245
    {
16246
      sprintf (tmp_buf, "N3O20000;");
16247
      strcat (out_buffer, tmp_buf);
16248
    }
16249
  if (fg[fg_nitrate - 1])
16250
    {
16251
      sprintf (tmp_buf, "N4O30000;");
16252
      strcat (out_buffer, tmp_buf);
16253
    }
16254
  if (fg[fg_sulfuric_acid_deriv - 1])
16255
    {
16256
      sprintf (tmp_buf, "S6O00000;");
16257
      strcat (out_buffer, tmp_buf);
16258
    }
16259
  if (fg[fg_sulfuric_acid - 1])
16260
    {
16261
      sprintf (tmp_buf, "S6O4H000;");
16262
      strcat (out_buffer, tmp_buf);
16263
    }
16264
  if (fg[fg_sulfuric_acid_monoester - 1])
16265
    {
16266
      sprintf (tmp_buf, "S6O4HC00;");
16267
      strcat (out_buffer, tmp_buf);
16268
    }
16269
  if (fg[fg_sulfuric_acid_diester - 1])
16270
    {
16271
      sprintf (tmp_buf, "S6O4CC00;");
16272
      strcat (out_buffer, tmp_buf);
16273
    }
16274
  if (fg[fg_sulfuric_acid_amide_ester - 1])
16275
    {
16276
      sprintf (tmp_buf, "S6O3NC00;");
16277
      strcat (out_buffer, tmp_buf);
16278
    }
16279
  if (fg[fg_sulfuric_acid_amide - 1])
16280
    {
16281
      sprintf (tmp_buf, "S6O3N100;");
16282
      strcat (out_buffer, tmp_buf);
16283
    }
16284
  if (fg[fg_sulfuric_acid_diamide - 1])
16285
    {
16286
      sprintf (tmp_buf, "S6O2N200;");
16287
      strcat (out_buffer, tmp_buf);
16288
    }
16289
  if (fg[fg_sulfuryl_halide - 1])
16290
    {
16291
      sprintf (tmp_buf, "S6O3XX00;");
16292
      strcat (out_buffer, tmp_buf);
16293
    }
16294
  if (fg[fg_sulfonic_acid_deriv - 1])
16295
    {
16296
      sprintf (tmp_buf, "S5O00000;");
16297
      strcat (out_buffer, tmp_buf);
16298
    }
16299
  if (fg[fg_sulfonic_acid - 1])
16300
    {
16301
      sprintf (tmp_buf, "S5O3H000;");
16302
      strcat (out_buffer, tmp_buf);
16303
    }
16304
  if (fg[fg_sulfonic_acid_ester - 1])
16305
    {
16306
      sprintf (tmp_buf, "S5O3C000;");
16307
      strcat (out_buffer, tmp_buf);
16308
    }
16309
  if (fg[fg_sulfonamide - 1])
16310
    {
16311
      sprintf (tmp_buf, "S5O2N000;");
16312
      strcat (out_buffer, tmp_buf);
16313
    }
16314
  if (fg[fg_sulfonyl_halide - 1])
16315
    {
16316
      sprintf (tmp_buf, "S5O2XX00;");
16317
      strcat (out_buffer, tmp_buf);
16318
    }
16319
  if (fg[fg_sulfone - 1])
16320
    {
16321
      sprintf (tmp_buf, "S4O20000;");
16322
      strcat (out_buffer, tmp_buf);
16323
    }
16324
  if (fg[fg_sulfoxide - 1])
16325
    {
16326
      sprintf (tmp_buf, "S2O10000;");
16327
      strcat (out_buffer, tmp_buf);
16328
    }
16329
  if (fg[fg_sulfinic_acid_deriv - 1])
16330
    {
16331
      sprintf (tmp_buf, "S3O00000;");
16332
      strcat (out_buffer, tmp_buf);
16333
    }
16334
  if (fg[fg_sulfinic_acid - 1])
16335
    {
16336
      sprintf (tmp_buf, "S3O2H000;");
16337
      strcat (out_buffer, tmp_buf);
16338
    }
16339
  if (fg[fg_sulfinic_acid_ester - 1])
16340
    {
16341
      sprintf (tmp_buf, "S3O2C000;");
16342
      strcat (out_buffer, tmp_buf);
16343
    }
16344
  if (fg[fg_sulfinic_acid_halide - 1])
16345
    {
16346
      sprintf (tmp_buf, "S3O1XX00;");
16347
      strcat (out_buffer, tmp_buf);
16348
    }
16349
  if (fg[fg_sulfinic_acid_amide - 1])
16350
    {
16351
      sprintf (tmp_buf, "S3O1N000;");
16352
      strcat (out_buffer, tmp_buf);
16353
    }
16354
  if (fg[fg_sulfenic_acid_deriv - 1])
16355
    {
16356
      sprintf (tmp_buf, "S1O00000;");
16357
      strcat (out_buffer, tmp_buf);
16358
    }
16359
  if (fg[fg_sulfenic_acid - 1])
16360
    {
16361
      sprintf (tmp_buf, "S1O1H000;");
16362
      strcat (out_buffer, tmp_buf);
16363
    }
16364
  if (fg[fg_sulfenic_acid_ester - 1])
16365
    {
16366
      sprintf (tmp_buf, "S1O1C000;");
16367
      strcat (out_buffer, tmp_buf);
16368
    }
16369
  if (fg[fg_sulfenic_acid_halide - 1])
16370
    {
16371
      sprintf (tmp_buf, "S1O0XX00;");
16372
      strcat (out_buffer, tmp_buf);
16373
    }
16374
  if (fg[fg_sulfenic_acid_amide - 1])
16375
    {
16376
      sprintf (tmp_buf, "S1O0N100;");
16377
      strcat (out_buffer, tmp_buf);
16378
    }
16379
 
16380
  if (fg[fg_alkylthiol - 1])
16381
    {
16382
      sprintf (tmp_buf, "S1H1C000;");
16383
      strcat (out_buffer, tmp_buf);
16384
    }
16385
  if (fg[fg_arylthiol - 1])
16386
    {
16387
      sprintf (tmp_buf, "S1H1A000;");
16388
      strcat (out_buffer, tmp_buf);
16389
    }
16390
  if (fg[fg_phosphoric_acid_deriv - 1])
16391
    {
16392
      sprintf (tmp_buf, "P5O0H000;");
16393
      strcat (out_buffer, tmp_buf);
16394
    }
16395
  if (fg[fg_phosphoric_acid - 1])
16396
    {
16397
      sprintf (tmp_buf, "P5O4H200;");
16398
      strcat (out_buffer, tmp_buf);
16399
    }
16400
  if (fg[fg_phosphoric_acid_ester - 1])
16401
    {
16402
      sprintf (tmp_buf, "P5O4HC00;");
16403
      strcat (out_buffer, tmp_buf);
16404
    }
16405
  if (fg[fg_phosphoric_acid_halide - 1])
16406
    {
16407
      sprintf (tmp_buf, "P5O3HX00;");
16408
      strcat (out_buffer, tmp_buf);
16409
    }
16410
  if (fg[fg_phosphoric_acid_amide - 1])
16411
    {
16412
      sprintf (tmp_buf, "P5O3HN00;");
16413
      strcat (out_buffer, tmp_buf);
16414
    }
16415
  if (fg[fg_thiophosphoric_acid_deriv - 1])
16416
    {
16417
      sprintf (tmp_buf, "P5O0S000;");
16418
      strcat (out_buffer, tmp_buf);
16419
    }
16420
  if (fg[fg_thiophosphoric_acid - 1])
16421
    {
16422
      sprintf (tmp_buf, "P5O3SH00;");
16423
      strcat (out_buffer, tmp_buf);
16424
    }
16425
  if (fg[fg_thiophosphoric_acid_ester - 1])
16426
    {
16427
      sprintf (tmp_buf, "P5O3SC00;");
16428
      strcat (out_buffer, tmp_buf);
16429
    }
16430
  if (fg[fg_thiophosphoric_acid_halide - 1])
16431
    {
16432
      sprintf (tmp_buf, "P5O2SX00;");
16433
      strcat (out_buffer, tmp_buf);
16434
    }
16435
  if (fg[fg_thiophosphoric_acid_amide - 1])
16436
    {
16437
      sprintf (tmp_buf, "P5O2SN00;");
16438
      strcat (out_buffer, tmp_buf);
16439
    }
16440
  if (fg[fg_phosphonic_acid_deriv - 1])
16441
    {
16442
      sprintf (tmp_buf, "P4O30000;");
16443
      strcat (out_buffer, tmp_buf);
16444
    }
16445
  if (fg[fg_phosphonic_acid - 1])
16446
    {
16447
      sprintf (tmp_buf, "P4O3H000;");
16448
      strcat (out_buffer, tmp_buf);
16449
    }
16450
  if (fg[fg_phosphonic_acid_ester - 1])
16451
    {
16452
      sprintf (tmp_buf, "P4O3C000;");
16453
      strcat (out_buffer, tmp_buf);
16454
    }
16455
  if (fg[fg_phosphine - 1])
16456
    {
16457
      sprintf (tmp_buf, "P3000000;");
16458
      strcat (out_buffer, tmp_buf);
16459
    }
16460
  if (fg[fg_phosphinoxide - 1])
16461
    {
16462
      sprintf (tmp_buf, "P2O00000;");
16463
      strcat (out_buffer, tmp_buf);
16464
    }
16465
  if (fg[fg_boronic_acid_deriv - 1])
16466
    {
16467
      sprintf (tmp_buf, "B2O20000;");
16468
      strcat (out_buffer, tmp_buf);
16469
    }
16470
  if (fg[fg_boronic_acid - 1])
16471
    {
16472
      sprintf (tmp_buf, "B2O2H000;");
16473
      strcat (out_buffer, tmp_buf);
16474
    }
16475
  if (fg[fg_boronic_acid_ester - 1])
16476
    {
16477
      sprintf (tmp_buf, "B2O2C000;");
16478
      strcat (out_buffer, tmp_buf);
16479
    }
16480
  if (fg[fg_alkene - 1])
16481
    {
16482
      sprintf (tmp_buf, "000C2C00;");
16483
      strcat (out_buffer, tmp_buf);
16484
    }
16485
  if (fg[fg_alkyne - 1])
16486
    {
16487
      sprintf (tmp_buf, "000C3C00;");
16488
      strcat (out_buffer, tmp_buf);
16489
    }
16490
  if (fg[fg_aromatic - 1])
16491
    {
16492
      sprintf (tmp_buf, "0000A000;");
16493
      strcat (out_buffer, tmp_buf);
16494
    }
16495
  if (fg[fg_heterocycle - 1])
16496
    {
16497
      sprintf (tmp_buf, "0000CZ00;");
16498
      strcat (out_buffer, tmp_buf);
16499
    }
16500
  if (fg[fg_alpha_aminoacid - 1])
16501
    {
16502
      sprintf (tmp_buf, "C3O2HN1C;");
16503
      strcat (out_buffer, tmp_buf);
16504
    }
16505
  if (fg[fg_alpha_hydroxyacid - 1])
16506
    {
16507
      sprintf (tmp_buf, "C3O2HO1H;");
16508
      strcat (out_buffer, tmp_buf);
16509
    }
16510
}
16511
 
16512
/*static void mm_elab_molstat(void)
16513
{
16514
                count_neighbors();
16515
//      init_molstat(&molstat);
16516
        if (!found_arominfo) {
16517
    chk_ringbonds();
16518
    if (ringsearch_mode == rs_ssr)
16519
      remove_redundant_rings();
16520
    if (n_rings == max_rings) {
16521
      if (opt_verbose)
16522
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
16523
      ringsearch_mode = rs_ssr;
16524
      clear_rings();
16525
      max_vringsize = 10;
16526
      chk_ringbonds();
16527
      remove_redundant_rings();
16528
    }
16529
 
16530
    update_ringcount();
16531
    update_atypes();
16532
    update_Htotal();
16533
    chk_arom();
16534
 
16535
    if (ringsearch_mode == rs_ssr) {
16536
      do {
16537
        prev_n_ar = count_aromatic_rings();
16538
        chk_arom();
16539
        n_ar = count_aromatic_rings();
16540
      } while (prev_n_ar - n_ar != 0);
16541
    }
16542
        } else {
16543
 update_atypes();
16544
    update_Htotal();  
16545
 
16546
        }
16547
 
16548
 // get_molstat();
16549
}*/
16550
 
16551
DLLEXPORT void
16552
cm_molstat_X (char *buf)
16553
{
16554
  init_molstat (&molstat);
16555
//mm_elab_molstat();
16556
  get_molstat ();
16557
  write_molstat_X_dll (buf);
16558
}
16559
 
16560
DLLEXPORT void
16561
cm_molstat (char *buf)
16562
{
16563
  init_molstat (&molstat);
16564
//mm_elab_molstat();
16565
  get_molstat ();
16566
  write_molstat_dll (buf, 0);
16567
}
16568
 
16569
DLLEXPORT void
16570
cm_molstat_sql_exact (char *buf)
16571
{
16572
  init_molstat (&molstat);
16573
//mm_elab_molstat();
16574
  get_molstat ();
16575
  write_molstat_dll (buf, 1);
16576
}
16577
 
16578
DLLEXPORT void
16579
cm_molstat_sql_substruct (char *buf)
16580
{
16581
  init_molstat (&molstat);
16582
//mm_elab_molstat();
16583
  get_molstat ();
16584
  write_molstat_dll (buf, 2);
16585
}
16586
 
16587
DLLEXPORT void
16588
cm_fg_codes (char *buf)
16589
{
16590
//mm_elab_molstat();
16591
  chk_functionalgroups ();
16592
  write_fg_code_dll (buf);
16593
}
16594
 
16595
static void
16596
write_MDLmolfile_dll (char *out_buffer)
16597
{
16598
  int i;
16599
  char tmpstr[256];
16600
  char wline[256];
16601
  int a_chg;
16602
  int a_iso;
16603
  int a_rad;
16604
  char tmflabel[256];           /* v0.3m */
16605
  char STR1[256], STR7[256];
16606
  int FORLIM;
16607
  *out_buffer = '\0';
16608
  *tmpstr = '\0';
16609
  *wline = '\0';
16610
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
16611
  while (strlen (tmflabel) < 2) /* v0.3m */
16612
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
16613
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
16614
  if (strlen (molname) > 80)
16615
    sprintf (molname, "%.80s", strcpy (STR1, molname));
16616
  strncat (out_buffer, molname, 80);
16617
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
16618
  if (ringsearch_mode == rs_sar)        /* v0.3m */
16619
    strcat (wline, ":r0");
16620
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
16621
    strcat (wline, ":r1");
16622
  if (opt_metalrings)
16623
    strcat (wline, ":m1");
16624
  else
16625
    strcat (wline, ":m0");
16626
  /* v0.3m */
16627
  sprintf (tmpstr, "\n%s\n", molcomment);
16628
  strcat (wline, tmpstr);
16629
  sprintf (tmpstr, "%d", n_atoms);
16630
  lblank (3L, tmpstr);
16631
  strcat (wline, tmpstr);
16632
  /* first 3 digits: number of atoms */
16633
  sprintf (tmpstr, "%d", n_bonds);
16634
  lblank (3L, tmpstr);
16635
  strcat (wline, tmpstr);
16636
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
16637
  strcpy (tmpstr, "  0");
16638
  strcat (wline, tmpstr);
16639
  /* next 3 digits: number of atom lists (not used by us) */
16640
/* p2c: checkmol.pas, line 2388:
16641
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
16642
#ifdef REDUCED_SAR
16643
  sprintf (tmpstr, "%d", n_countablerings);
16644
  /* v0.3n; changed n_rings into n_countablerings */
16645
#else
16646
  sprintf (tmpstr, "%d", n_rings);
16647
#endif
16648
  lblank (3L, tmpstr);
16649
  strcat (wline, tmpstr);
16650
  /* officially "obsolete", we use it for the number of rings */
16651
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
16652
  if (chir_flag)
16653
    strcat (wline, "1");
16654
  else
16655
    strcat (wline, "0");
16656
  /* v0.3n */
16657
  strcat (wline, "               999 V2000\n");
16658
  /* v0.3n (adjust string length) */
16659
  strcat (out_buffer, wline);
16660
  FORLIM = n_atoms;
16661
  for (i = 0; i < FORLIM; i++)
16662
    {
16663
      *wline = '\0';
16664
      *tmpstr = '\0';
16665
      sprintf (tmpstr, "%1.4f", atom[i].x);
16666
      lblank (10L, tmpstr);
16667
      strcat (wline, tmpstr);
16668
      sprintf (tmpstr, "%1.4f", atom[i].y);
16669
      lblank (10L, tmpstr);
16670
      strcat (wline, tmpstr);
16671
      sprintf (tmpstr, "%1.4f", atom[i].z);
16672
      lblank (10L, tmpstr);
16673
      strcat (wline, tmpstr);
16674
      strcpy (tmpstr, atom[i].element);
16675
      /* tmpstr := lowercase(tmpstr); REPLACE!!! */
16676
      //tmpstr[0] = toupper (tmpstr[0]);
16677
      all_lowercase (tmpstr);
16678
      tmpstr[0] = toupper (tmpstr[0]);
16679
      /*wline := wline + ' '+atom^[i].element+' '; */
16680
      sprintf (wline + strlen (wline), " %s ", tmpstr);
16681
      strcat (wline, " 0");     /* mass difference (isotopes) */
16682
      /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
16683
      if (atom[i].arom)
16684
        strcpy (tmpstr, " 00");
16685
      else
16686
        strcpy (tmpstr, "  0");
16687
      strcat (wline, tmpstr);
16688
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
16689
      strcat (out_buffer, wline);
16690
    }
16691
  FORLIM = n_bonds;
16692
  for (i = 0; i < FORLIM; i++)
16693
    {
16694
      *wline = '\0';
16695
      *tmpstr = '\0';
16696
      sprintf (tmpstr, "%d", bond[i].a1);
16697
      lblank (3L, tmpstr);
16698
      strcat (wline, tmpstr);
16699
      sprintf (tmpstr, "%d", bond[i].a2);
16700
      lblank (3L, tmpstr);
16701
      strcat (wline, tmpstr);
16702
      if (bond[i].btype == 'S')
16703
        strcpy (tmpstr, "  1");
16704
      if (bond[i].btype == 'D')
16705
        strcpy (tmpstr, "  2");
16706
      if (bond[i].btype == 'T')
16707
        strcpy (tmpstr, "  3");
16708
      if (bond[i].btype == 'A')
16709
        strcpy (tmpstr, "  4");
16710
      if (bond[i].btype == 'l')
16711
        strcpy (tmpstr, "  5");
16712
      if (bond[i].btype == 's')
16713
        strcpy (tmpstr, "  6");
16714
      if (bond[i].btype == 'd')
16715
        strcpy (tmpstr, "  7");
16716
      if (bond[i].btype == 'a')
16717
        strcpy (tmpstr, "  8");
16718
      /* now encode our own aromaticity information */
16719
      if (bond[i].arom)
16720
        tmpstr[1] = '0';
16721
      strcat (wline, tmpstr);   /* next, encode bond stereo property (v0.3f) */
16722
      /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
16723
      /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
16724
      /*    wline := wline + '  0'; */
16725
      /* restore original value from MDL molfile (v0.3n) */
16726
      /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
16727
      *tmpstr = '\0';
16728
      sprintf (tmpstr, "%i", bond[i].mdl_stereo);
16729
      strcat (wline, "  ");
16730
      strcat (wline, tmpstr);
16731
      *tmpstr = '\0';
16732
      /* now encode the ring_count of this bond (using a field which officially is "not used") */
16733
      /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
16734
      sprintf (tmpstr, "%i", bond[i].ring_count);
16735
      while (strlen (tmpstr) < 3)
16736
        sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
16737
      sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
16738
      strcat (out_buffer, wline);
16739
    }
16740
  FORLIM = n_atoms;
16741
  for (i = 1; i <= FORLIM; i++)
16742
    {
16743
      a_chg = atom[i - 1].formal_charge;
16744
      if (a_chg != 0)
16745
        {
16746
          strcpy (wline, "M  CHG  1 ");
16747
          sprintf (tmpstr, "%d", i);
16748
          lblank (3L, tmpstr);
16749
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16750
          sprintf (tmpstr, "%d", a_chg);
16751
          lblank (3L, tmpstr);
16752
          strcat (wline, tmpstr);
16753
          strcat (out_buffer, wline);
16754
          strcat (out_buffer, "\n");
16755
        }
16756
    }
16757
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
16758
    {
16759
      a_iso = atom[i - 1].nucleon_number;
16760
      if (a_iso != 0)
16761
        {
16762
          strcpy (wline, "M  ISO  1 ");
16763
          sprintf (tmpstr, "%d", i);
16764
          lblank (3L, tmpstr);
16765
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16766
          sprintf (tmpstr, "%d", a_iso);
16767
          lblank (3L, tmpstr);
16768
          strcat (wline, tmpstr);
16769
          strcat (out_buffer, wline);
16770
          strcat (out_buffer, "\n");
16771
        }
16772
    }
16773
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
16774
    {
16775
      a_rad = atom[i - 1].radical_type;
16776
      if (a_rad != 0)
16777
        {
16778
          strcpy (wline, "M  RAD  1 ");
16779
          sprintf (tmpstr, "%d", i);
16780
          lblank (3L, tmpstr);
16781
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16782
          sprintf (tmpstr, "%d", a_rad);
16783
          lblank (3L, tmpstr);
16784
          strcat (wline, tmpstr);
16785
          strcat (out_buffer, wline);
16786
          strcat (out_buffer, "\n");
16787
        }
16788
    }
16789
  strcat (out_buffer, "M  END\n");
16790
}
16791
 
16792
DLLEXPORT void
16793
cm_tweak_molfile (char *buf)
16794
{
16795
//chk_functionalgroups();
16796
  write_MDLmolfile_dll (buf);
16797
}
16798
#endif