Subversion Repositories wimsdev

Rev

Rev 6785 | Rev 6787 | 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
 /* int code;*/
1079
  char STR1[256];
1080
 
1081
  strcpy (numstr, "-+0123456789");
1082
  *auxstr = '\0';
1083
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1084
    strdelete (trimstr, 1, 1);
1085
  while ((*trimstr != '\0') &&
1086
         (strpos2 (numstr, (sprintf (STR1, "%c", trimstr[0]), STR1), 1) > 0))
1087
    {
1088
      sprintf (auxstr + strlen (auxstr), "%c", trimstr[0]);
1089
      strdelete (trimstr, 1, 1);
1090
    }
1091
 /* code = (sscanf (auxstr, "%d", &auxint) == 0);*/
1092
  return auxint;
1093
}
1094
 
1095
static int
1096
path_pos (int id, int *a_path)
1097
{
1098
  int i = 0;
1099
 
1100
  for (i = 0; i < max_ringsize; i++)
1101
    {
1102
      if (*(a_path++) == id)
1103
        {
1104
          return ++i;
1105
        }
1106
    }
1107
  return 0;
1108
}
1109
 
1110
static int
1111
path_length (int *a_path)
1112
{
1113
  if ((a_path[max_ringsize - 1] != 0) && (path_pos (0, a_path) == 0))
1114
    return max_ringsize;
1115
  else
1116
    return (path_pos (0, a_path) - 1);
1117
}
1118
 
1119
static int
1120
get_bond (int ba1, int ba2)
1121
{
1122
  int i;
1123
  int b_id = 0;
1124
  int FORLIM;
1125
 
1126
  if (n_bonds <= 0)
1127
    return b_id;
1128
  FORLIM = n_bonds;
1129
  for (i = 1; i <= FORLIM; i++)
1130
    {
1131
      if ((bond[i - 1].a1 == ba1 && bond[i - 1].a2 == ba2) ||
1132
          (bond[i - 1].a1 == ba2 && bond[i - 1].a2 == ba1))
1133
        b_id = i;
1134
    }
1135
  return b_id;
1136
}
1137
 
1138
static void
1139
clear_atom_tags ()
1140
{
1141
  int i, FORLIM;
1142
 
1143
  if (n_atoms > 0)
1144
    {
1145
      FORLIM = n_atoms;
1146
      for (i = 0; i < FORLIM; i++)
1147
        atom[i].tag = false;
1148
    }
1149
}
1150
 
1151
#if 0
1152
static void
1153
set_atom_tags ()
1154
{
1155
  int i, FORLIM;
1156
 
1157
  if (n_atoms > 0)
1158
    {
1159
      FORLIM = n_atoms;
1160
      for (i = 0; i < FORLIM; i++)
1161
        atom[i].tag = true;
1162
    }
1163
}
1164
#endif
1165
static void
1166
order_ringpath (int *r_path)
1167
{
1168
  /* order should be: array starts with atom of lowest number, followed by neighbor atom with lower number */
1169
  int i, pl, a_ref, a_left, a_right, a_tmp;
1170
 
1171
  pl = path_length (r_path);
1172
  if (pl < 3)
1173
    return;
1174
  a_ref = n_atoms;
1175
  /* start with highest possible value for an atom number */
1176
  for (i = 0; i < pl; i++)
1177
    {
1178
      if (r_path[i] < a_ref)    /* find the minimum value ==> reference atom */
1179
        a_ref = r_path[i];
1180
    }
1181
  if (a_ref < 1)                /* just to be sure */
1182
    return;
1183
  if (path_pos (a_ref, r_path) < pl)
1184
    a_right = r_path[path_pos (a_ref, r_path)];
1185
  else
1186
    a_right = r_path[0];
1187
  if (path_pos (a_ref, r_path) > 1)
1188
    a_left = r_path[path_pos (a_ref, r_path) - 2];
1189
  else
1190
    a_left = r_path[pl - 1];
1191
  if (a_right == a_left)        /* should never happen */
1192
    return;
1193
  if (a_right < a_left)
1194
    {
1195
      /* correct ring numbering direction, only shift of the reference atom to the left end required */
1196
      while (path_pos (a_ref, r_path) > 1)
1197
        {
1198
          a_tmp = r_path[0];
1199
          for (i = 1; i < pl; i++)
1200
            r_path[i - 1] = r_path[i];
1201
          r_path[pl - 1] = a_tmp;
1202
        }
1203
      return;
1204
    }
1205
  while (path_pos (a_ref, r_path) < pl)
1206
    {
1207
      /* step one: create "mirrored" ring path with reference atom at right end */
1208
      a_tmp = r_path[pl - 1];
1209
      for (i = pl; i >= 2; i--)
1210
        r_path[i - 1] = r_path[i - 2];
1211
      r_path[0] = a_tmp;
1212
    }
1213
  for (i = 1; i <= pl / 2; i++)
1214
    {                           /* one more mirroring */
1215
      a_tmp = r_path[i - 1];
1216
      r_path[i - 1] = r_path[pl - i];
1217
      r_path[pl - i] = a_tmp;
1218
      /* wrong ring numbering direction, two steps required */
1219
    }
1220
}
1221
 
1222
static void
1223
clear_ndl_atom_tags ()
1224
{
1225
  int i;
1226
 
1227
  if (ndl_n_atoms > 0)
1228
    {
1229
 
1230
      for (i = 0; i < ndl_n_atoms; i++)
1231
        ndl_atom[i].tag = false;
1232
    }
1233
}
1234
 
1235
 
1236
static void
1237
set_ndl_atom_tags ()
1238
{
1239
  int i;
1240
 
1241
  if (ndl_n_atoms > 0)
1242
    {
1243
 
1244
      for (i = 0; i < ndl_n_atoms; i++)
1245
        ndl_atom[i].tag = true;
1246
    }
1247
}
1248
 
1249
 
1250
static int
1251
count_tagged_ndl_heavyatoms ()
1252
{
1253
  int i;
1254
  int n = 0;
1255
 
1256
  if (ndl_n_atoms < 1)
1257
    return n;
1258
 
1259
  for (i = 0; i < ndl_n_atoms; i++)
1260
    {
1261
      if (ndl_atom[i].heavy && ndl_atom[i].tag)
1262
        n++;
1263
    }
1264
  return n;
1265
}
1266
 
1267
 
1268
 
1269
/*============================= geometry functions ========================== */
1270
 
1271
static double
1272
dist3d (p1, p2)
1273
     p_3d p1, p2;
1274
{
1275
  double res, TEMP, TEMP1, TEMP2;
1276
 
1277
  TEMP = p1.x - p2.x;
1278
  TEMP1 = p1.y - p2.y;
1279
  TEMP2 = p1.z - p2.z;
1280
  res = sqrt (TEMP * TEMP + TEMP1 * TEMP1 + TEMP2 * TEMP2);
1281
  return res;
1282
}
1283
 
1284
 
1285
/*
1286
function is_cis(p1,p2,p3,p4:p_3d):boolean;  (* new in v0.3d
1287
var                         (* just a simple, distance-based estimation
1288
  total_dist  : double;     (* instead of calculating the dihedral angle
1289
  direct_dist : double;
1290
  res         : boolean;
1291
begin
1292
  res := false;
1293
  total_dist  := dist3d(p1,p2) + dist3d(p2,p3) + dist3d(p3,p4);
1294
  direct_dist := dist3d(p1,p4);
1295
  if (direct_dist < 0.78 * total_dist) then res := true;  (* cutoff value of 0.78 was
1296
  is_cis := res;                                          (* experimentally determined
1297
end;
1298
*/
1299
/* function is_cis was replaced by a new one in v0.3h */
1300
 
1301
 
1302
static p_3d
1303
subtract_3d (p1, p2)
1304
     p_3d p1, p2;
1305
{
1306
  p_3d p;
1307
 
1308
  p.x = p1.x - p2.x;
1309
  p.y = p1.y - p2.y;
1310
  p.z = p1.z - p2.z;
1311
  return p;
1312
}
1313
 
1314
 
1315
static p_3d
1316
add_3d (p1, p2)
1317
     p_3d p1, p2;
1318
{
1319
  p_3d p;
1320
 
1321
  p.x = p1.x + p2.x;
1322
  p.y = p1.y + p2.y;
1323
  p.z = p1.z + p2.z;
1324
  return p;
1325
}
1326
 
1327
#if 0
1328
static void
1329
vec2origin (p1, p2)
1330
     p_3d *p1, *p2;
1331
{
1332
  p_3d p;
1333
 
1334
  p = subtract_3d (*p2, *p1);
1335
  *p2 = p;
1336
  p1->x = 0.0;
1337
  p1->y = 0.0;
1338
  p1->z = 0.0;
1339
}
1340
#endif
1341
 
1342
static double
1343
scalar_prod (p1, p2, p3)
1344
     p_3d p1, p2, p3;
1345
{
1346
  p_3d p;
1347
  double res;
1348
 
1349
  p = subtract_3d (p2, p1);
1350
  p2 = p;
1351
  p = subtract_3d (p3, p1);
1352
  p3 = p;
1353
  p1.x = 0.0;
1354
  p1.y = 0.0;
1355
  p1.z = 0.0;
1356
  res = p2.x * p3.x + p2.y * p3.y + p2.z * p3.z;
1357
  return res;
1358
}
1359
 
1360
 
1361
static p_3d
1362
cross_prod (p1, p2, p3)
1363
     p_3d p1, p2, p3;
1364
{
1365
  p_3d p, orig_p1;
1366
 
1367
  orig_p1 = p1;
1368
  p = subtract_3d (p2, p1);
1369
  p2 = p;
1370
  p = subtract_3d (p3, p1);
1371
  p3 = p;
1372
  p.x = p2.y * p3.z - p2.z * p3.y;
1373
  p.y = p2.z * p3.x - p2.x * p3.z;
1374
  p.z = p2.x * p3.y - p2.y * p3.x;
1375
  return (add_3d (orig_p1, p));
1376
}
1377
 
1378
 
1379
static double
1380
angle_3d (p1, p2, p3)
1381
     p_3d p1, p2, p3;
1382
{
1383
  p_3d lp1, lp2, lp3, p;
1384
  double res = 0.0;
1385
  double magn_1, magn_2, cos_phi;
1386
 
1387
  lp1 = p1;
1388
  lp2 = p2;
1389
  lp3 = p3;
1390
  p = subtract_3d (lp2, lp1);
1391
  lp2 = p;
1392
  p = subtract_3d (lp3, lp1);
1393
  lp3 = p;
1394
  lp1.x = 0.0;
1395
  lp1.y = 0.0;
1396
  lp1.z = 0.0;
1397
  magn_1 = dist3d (lp1, lp2);
1398
  magn_2 = dist3d (lp1, lp3);
1399
  if (magn_1 * magn_2 == 0)     /* emergency exit */
1400
    return M_PI;
1401
  cos_phi = scalar_prod (lp1, lp2, lp3) / (magn_1 * magn_2);
1402
  if (cos_phi < -1)
1403
    cos_phi = -1.0;
1404
  if (cos_phi > 1)
1405
    cos_phi = 1.0;
1406
  res = acos (cos_phi);
1407
  return res;
1408
}
1409
 
1410
 
1411
static double
1412
torsion (p1, p2, p3, p4)
1413
     p_3d p1, p2, p3, p4;
1414
{
1415
  p_3d lp1, lp2, lp3, lp4, d1, c1, c2;
1416
  double res;
1417
  p_3d c1xc2, c2xc1;
1418
  double dist1, dist2, sign;
1419
 
1420
  /* copy everything into local variables */
1421
  lp1 = p1;
1422
  lp2 = p2;
1423
  lp3 = p3;
1424
  lp4 = p4;
1425
  /* get the vector between the two central atoms */
1426
  d1 = subtract_3d (p3, p2);
1427
  /* shift the first atom parallel to be attached to p3 instead of p2 */
1428
  lp1 = add_3d (p1, d1);
1429
  /* now get the cross product vectors */
1430
  c1 = cross_prod (lp3, lp2, lp1);
1431
  c2 = cross_prod (lp3, lp2, lp4);
1432
  res = angle_3d (p3, c1, c2);
1433
  /*now check if it is clockwise or anticlockwise: */
1434
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1435
  c1xc2 = cross_prod (lp3, c1, c2);
1436
  c2xc1 = cross_prod (lp3, c2, c1);
1437
  /*next, get the distances from these points to our refernce point lp2 */
1438
  dist1 = dist3d (lp2, c1xc2);
1439
  dist2 = dist3d (lp2, c2xc1);
1440
  if (dist1 <= dist2)
1441
    sign = 1.0;
1442
  else
1443
    sign = -1.0;
1444
  return (sign * res);
1445
}
1446
 
1447
 
1448
static double
1449
ctorsion (p1, p2, p3, p4)
1450
     p_3d p1, p2, p3, p4;
1451
{
1452
  /* calculates "pseudo-torsion" defined by atoms 3 and 4, being both */
1453
  /* attached to atom 2, with respect to axis of atoms 1 and 2 */
1454
  p_3d lp1, lp2, lp3, lp4;
1455
  /*d1 : p_3d; */
1456
  p_3d c1, c2;
1457
  double res;
1458
  p_3d c1xc2, c2xc1;
1459
  double dist1, dist2, sign;
1460
 
1461
  /* copy everything into local variables */
1462
  lp1 = p1;
1463
  lp2 = p2;
1464
  lp3 = p3;
1465
  lp4 = p4;
1466
  /* get the cross product vectors */
1467
  c1 = cross_prod (lp2, lp1, lp3);
1468
  c2 = cross_prod (lp2, lp1, lp4);
1469
  res = angle_3d (p2, c1, c2);
1470
  /*now check if it is clockwise or anticlockwise: */
1471
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1472
  c1xc2 = cross_prod (lp2, c1, c2);
1473
  c2xc1 = cross_prod (lp2, c2, c1);
1474
  /*next, get the distances from these points to our refernce point lp1 */
1475
  dist1 = dist3d (lp1, c1xc2);
1476
  dist2 = dist3d (lp1, c2xc1);
1477
  if (dist1 <= dist2)
1478
    sign = 1.0;
1479
  else
1480
    sign = -1.0;
1481
  return (sign * res);
1482
}
1483
 
1484
 
1485
static boolean
1486
is_cis (p1, p2, p3, p4)
1487
     p_3d p1, p2, p3, p4;
1488
{
1489
  /* new in v0.3h, uses the dihedral angle */
1490
  double phi;
1491
  boolean res = false;
1492
 
1493
  phi = torsion (p1, p2, p3, p4);
1494
  if (fabs (phi) < M_PI / 2)
1495
    res = true;
1496
  return res;
1497
}
1498
 
1499
 
1500
/*====================== end of geometry functions ========================== */
1501
 
1502
static void
1503
show_usage ()
1504
{
1505
  if (progmode == pmMatchMol)
1506
    {
1507
      printf
1508
        ("matchmol version %s  N. Haider, University of Vienna, 2003-2007\n",
1509
         version);
1510
      printf ("Usage: matchmol [options] <needle> <haystack>\n");
1511
      printf
1512
        (" where <needle> and <haystack> are the two molecules to compare\n");
1513
      printf
1514
        (" (supported formats: MDL *.mol or *.sdf, Alchemy *.mol, Sybyl *.mol2)\n");
1515
      printf (" options can be:\n");
1516
      printf ("    -v  verbose output\n");
1517
      printf ("    -x  exact match\n");
1518
      printf
1519
        ("    -s  strict comparison of atom and bond types (including ring check)\n");
1520
      /* new in v0.2f, v0.3d */
1521
      printf ("    -r  force SSR (set of small rings) ring search mode\n");
1522
      printf
1523
        ("    -m  write matching molecule as MDL molfile to standard output\n");
1524
      printf
1525
        ("        (default output: record number + \":T\" for hit  or \":F\" for miss\n");
1526
      printf ("    -M  accept metal atoms as ring members\n");
1527
      printf ("    -g  check geometry of double bonds (E/Z)\n");
1528
      printf ("    -G  check geometry of chiral centers (R/S)\n");
1529
      printf ("    -a  check charges strict\n");        /* 0.3x */
1530
      printf ("    -i  check isotopes strict\n");       /* 0.3x */
1531
      printf ("    -d  check radicals strict\n");       /* 0.3x */
1532
      printf
1533
        ("    -f  fingerprint mode (1 haystack, multiple needles) with boolean output\n");
1534
      printf
1535
        ("    -F  fingerprint mode (1 haystack, multiple needles) with decimal output\n");
1536
      return;
1537
    }
1538
  printf ("checkmol version %s  N. Haider, University of Vienna, 2003-2007\n",
1539
          version);
1540
  printf ("Usage: checkmol [options] <filename>\n");
1541
  printf (" where options can be:\n");
1542
  printf
1543
    ("    -l  print a list of fingerprint codes + explanation and exit\n");
1544
  printf ("    -v  verbose output\n");
1545
  printf ("    -r  force SSR (set of small rings) ring search mode\n");
1546
  printf ("    -M  accept metal atoms as ring members\n");
1547
  printf ("  and one of the following:\n");
1548
  printf
1549
    ("    -e  english text (common name of functional group; default)\n");
1550
  printf ("    -d  german text (common name of functional group)\n");
1551
  printf ("    -c  code (acronym-like code for functional group)\n");
1552
  printf
1553
    ("    -b  binary (a bitstring representing absence or presence of each group)\n");
1554
  printf
1555
    ("    -s  the ASCII representation of the above bitstring, i.e. 0s and 1s)\n");
1556
  printf
1557
    ("    -x  print molecular statistics (number of various atom types, bond types,\n");
1558
  printf ("        ring sizes, etc.\n");
1559
  printf
1560
    ("    -X  same as above, listing all records (even if 0) as comma-separated list\n");
1561
  printf ("    -a  count charges in fingerprint\n");    /* 0.3x */
1562
  printf
1563
    ("    -m  write MDL molfile (with special encoding for aromatic atoms/bonds)\n");
1564
  printf (" options can be combined like -vc\n");
1565
  printf (" <filename> specifies any file in the formats supported\n");
1566
  printf
1567
    (" (MDL *.mol, Alchemy *.mol, Sybyl *.mol2), the filename \"-\" (without quotes)\n");
1568
  printf (" specifies standard input\n");
1569
  /* the "debug" option (-D) remains undocumented */
1570
}
1571
 
1572
 
1573
static void
1574
list_molstat_codes ()
1575
{
1576
  printf ("n_atoms:     number of heavy atoms\n");
1577
  printf ("n_bonds:     number of bonds between non-H atoms\n");
1578
  printf ("n_rings:     number of rings\n");
1579
  printf ("n_QA:        number of query atoms\n");
1580
  printf ("n_QB:        number of query bonds\n");
1581
  printf ("n_chg:       number of charges\n");
1582
  printf ("n_C1:        number of sp-hybridized carbon atoms\n");
1583
  printf ("n_C2:        number of sp2-hybridized carbon atoms\n");
1584
  printf ("n_C:         total number of carbon atoms\n");
1585
  printf
1586
    ("n_CHB1p:     number of carbon atoms with at least 1 bond to a hetero atom\n");
1587
  printf
1588
    ("n_CHB2p:     number of carbon atoms with at least 2 bonds to a hetero atom\n");
1589
  printf
1590
    ("n_CHB3p:     number of carbon atoms with at least 3 bonds to a hetero atom\n");
1591
  printf
1592
    ("n_CHB4:      number of carbon atoms with 4 bonds to a hetero atom\n");
1593
  printf ("n_O2:        number of sp2-hybridized oxygen atoms\n");
1594
  printf ("n_O3:        number of sp3-hybridized oxygen atoms\n");
1595
  printf ("n_N1:        number of sp-hybridized nitrogen atoms\n");
1596
  printf ("n_N2:        number of sp2-hybridized nitrogen atoms\n");
1597
  printf ("n_N3:        number of sp3-hybridized nitrogen atoms\n");
1598
  printf ("n_S:         number of sulfur atoms\n");
1599
  printf ("n_SeTe:      total number of selenium and tellurium atoms\n");
1600
  printf ("n_F:         number of fluorine atoms\n");
1601
  printf ("n_Cl:        number of chlorine atoms\n");
1602
  printf ("n_Br:        number of bromine atoms\n");
1603
  printf ("n_I:         number of iodine atoms\n");
1604
  printf ("n_P:         number of phosphorus atoms\n");
1605
  printf ("n_B:         number of boron atoms\n");
1606
  printf ("n_Met:       total number of metal atoms\n");
1607
  printf
1608
    ("n_X:         total number of \"other\" atoms (not listed above) and halogens\n");
1609
  printf ("n_b1:        number of single bonds\n");
1610
  printf ("n_b2:        number of double bonds\n");
1611
  printf ("n_b3:        number of triple bonds\n");
1612
  printf ("n_bar:       number of aromatic bonds\n");
1613
  printf ("n_C1O:       number of C-O single bonds\n");
1614
  printf ("n_C2O:       number of C=O double bonds\n");
1615
  printf ("n_CN:        number of C/N bonds (any type)\n");
1616
  printf ("n_XY:        number of heteroatom/heteroatom bonds (any type)\n");
1617
  printf ("n_r3:        number of 3-membered rings\n");
1618
  printf ("n_r4:        number of 4-membered rings\n");
1619
  printf ("n_r5:        number of 5-membered rings\n");
1620
  printf ("n_r6:        number of 6-membered rings\n");
1621
  printf ("n_r7:        number of 7-membered rings\n");
1622
  printf ("n_r8:        number of 8-membered rings\n");
1623
  printf ("n_r9:        number of 9-membered rings\n");
1624
  printf ("n_r10:       number of 10-membered rings\n");
1625
  printf ("n_r11:       number of 11-membered rings\n");
1626
  printf ("n_r12:       number of 12-membered rings\n");
1627
  printf ("n_r13p:      number of 13-membered or larger rings\n");
1628
  printf ("n_rN:        number of rings containing nitrogen (any number)\n");
1629
  printf ("n_rN1:       number of rings containing 1 nitrogen atom\n");
1630
  printf ("n_rN2:       number of rings containing 2 nitrogen atoms\n");
1631
  printf
1632
    ("n_rN3p:      number of rings containing 3 or more nitrogen atoms\n");
1633
  printf ("n_rO:        number of rings containing oxygen (any number)\n");
1634
  printf ("n_rO1:       number of rings containing 1 oxygen atom\n");
1635
  printf ("n_rO2p:      number of rings containing 2 or more oxygen atoms\n");
1636
  printf ("n_rS:        number of rings containing sulfur (any number)\n");
1637
  printf ("n_rX:        number of heterocycles (any type)\n");
1638
  printf ("n_rar:       number of aromatic rings (any type)\n");
1639
/* p2c: checkmol.pas, line 1207:
1640
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1641
  /*$IFDEF extended_molstat */
1642
  printf ("n_rbz:       number of benzene rings\n");
1643
  printf ("n_br2p:      number of bonds belonging to two or more rings\n");
1644
  printf
1645
    ("n_psg01:     number of atoms belonging to group 1 of the periodic system\n");
1646
  printf
1647
    ("n_psg02:     number of atoms belonging to group 2 of the periodic system\n");
1648
  printf
1649
    ("n_psg13:     number of atoms belonging to group 13 of the periodic system\n");
1650
  printf
1651
    ("n_psg14:     number of atoms belonging to group 14 of the periodic system\n");
1652
  printf
1653
    ("n_psg15:     number of atoms belonging to group 15 of the periodic system\n");
1654
  printf
1655
    ("n_psg16:     number of atoms belonging to group 16 of the periodic system\n");
1656
  printf
1657
    ("n_psg17:     number of atoms belonging to group 17 of the periodic system\n");
1658
  printf
1659
    ("n_psg18:     number of atoms belonging to group 18 of the periodic system\n");
1660
  printf
1661
    ("n_pstm:      number of atoms belonging to the transition metals\n");
1662
  printf
1663
    ("n_psla:      number of atoms belonging to the lanthanides or actinides\n");
1664
  printf ("n_iso:      number of isotopes\n");
1665
  printf ("n_rad:      number of radicals\n");
1666
  /*$ENDIF */
1667
}
1668
 
1669
 
1670
#if 0
1671
static void parse_args()
1672
{
1673
  int p;
1674
  char parstr[256];
1675
  char tmpstr[256];
1676
  int l;
1677
 
1678
  *tmpstr = '\0';
1679
  opt_none = true;
1680
  if (progmode == pmCheckMol) {
1681
    for (p = 1; p < P_argc; p++) {
1682
      strcpy(parstr, P_argv[p]);
1683
      if (!strcmp(parstr, "-l")) {   /* new in v0.3l */
1684
        list_molstat_codes();
1685
        _Escape(0);
1686
      }
1687
      if (p < P_argc - 1) {
1688
        if (strpos2(parstr, "-", 1) == 1 && p < P_argc - 1) {
1689
          strcpy(tmpstr, P_argv[p]);
1690
          left_trim(tmpstr);
1691
          l = 0;
1692
          if (strpos2(tmpstr, "v", 1) > 0)
1693
            l++;
1694
          if (strpos2(tmpstr, "D", 1) > 0)
1695
            l++;
1696
          if (strpos2(tmpstr, "r", 1) > 0)
1697
            l++;
1698
          if (strpos2(tmpstr, "M", 1) > 0)   /* new in v0.3 */
1699
            l++;
1700
          if (strlen(tmpstr) > l + 2) {
1701
            show_usage();
1702
            _Escape(1);
1703
          }
1704
          opt_none = false;
1705
          if (strpos2(tmpstr, "M", 1) > 0)
1706
            opt_metalrings = true;
1707
          if (strpos2(tmpstr, "v", 1) > 0)
1708
            opt_verbose = true;
1709
/* p2c: checkmol.pas, line 1261:
1710
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1711
          /*$IFDEF debug
1712
          if (strpos2(tmpstr, "D", 1) > 0)
1713
            opt_debug = true;
1714
          $ENDIF*/
1715
          if (strpos2(tmpstr, "e", 1) > 0)
1716
            opt_text = true;
1717
          else {
1718
            if (strpos2(tmpstr, "d", 1) > 0)
1719
              opt_text_de = true;
1720
            else {
1721
              if (strpos2(tmpstr, "c", 1) > 0)
1722
                opt_code = true;
1723
              else {
1724
                if (strpos2(tmpstr, "b", 1) > 0)
1725
                  opt_bin = true;
1726
                else {
1727
                  if (strpos2(tmpstr, "s", 1) > 0)
1728
                    opt_bitstring = true;
1729
                }
1730
              }
1731
            }
1732
            if (strpos2(tmpstr, "x", 1) > 0)
1733
              opt_molstat = true;
1734
            if (strpos2(tmpstr, "r", 1) > 0)
1735
              opt_rs = rs_ssr;
1736
            if (strpos2(tmpstr, "X", 1) > 0) {
1737
              opt_molstat = true;
1738
              opt_molstat_X = true;
1739
            }
1740
            if (strpos2(tmpstr, "m", 1) > 0) {
1741
              opt_text = false;
1742
              opt_text_de = false;
1743
              opt_bin = false;
1744
              opt_bitstring = false;
1745
              opt_code = false;
1746
              opt_molstat = false;
1747
              opt_xmdlout = true;
1748
            }
1749
          }
1750
          strcpy(molfilename, tmpstr);
1751
        }
1752
      } else {
1753
        if (strpos2(parstr, "-", 1) == 1) {
1754
          if (strlen(parstr) > 1) {
1755
            show_usage();
1756
            _Escape(1);
1757
          }
1758
          opt_stdin = true;
1759
        } else {
1760
          opt_stdin = false;
1761
          strcpy(molfilename, parstr);
1762
        }
1763
      }
1764
    }
1765
    if (opt_text == false && opt_text_de == false && opt_code == false &&
1766
        opt_bin == false && opt_bitstring == false && opt_molstat == false &&
1767
        opt_molstat_X == false && opt_xmdlout == false)
1768
      opt_none = true;
1769
  }
1770
  if (progmode == pmMatchMol) {
1771
    *ndl_molfilename = '\0';
1772
    *molfilename = '\0';
1773
    for (p = 1; p < P_argc; p++) {
1774
      strcpy(parstr, P_argv[p]);
1775
      if (p == 1) {
1776
        if (strpos2(parstr, "-", 1) == 1) {
1777
          if (strpos2(parstr, "v", 1) > 1)
1778
            opt_verbose = true;
1779
/* p2c: checkmol.pas, line 1329:
1780
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1781
          /*$IFDEF debug
1782
             if (strpos2(parstr, "D", 1) > 1)
1783
             opt_debug = true;
1784
             $ENDIF*/
1785
             if (strpos2(parstr, "x", 1) > 1)
1786
             opt_exact = true;
1787
             if (strpos2(parstr, "s", 1) > 1)   /* new in v0.2f */
1788
             opt_strict = true;
1789
             if (strpos2(parstr, "m", 1) > 1)
1790
             opt_molout = true;
1791
             if (strpos2(parstr, "r", 1) > 1)
1792
             opt_rs = rs_ssr;
1793
             if (strpos2(parstr, "M", 1) > 0)   /* new in v0.3 */
1794
             opt_metalrings = true;
1795
             if (strpos2(parstr, "g", 1) > 0)   /* new in v0.3d */
1796
             opt_geom = true;
1797
             if (strpos2(parstr, "G", 1) > 0)   /* new in v0.3f */
1798
             opt_chiral = true;
1799
             if (strpos2(parstr, "f", 1) > 0) {   /* new in v0.3m */
1800
             opt_fp = true;
1801
             fpformat = fpf_boolean;
1802
             }
1803
             if (strpos2(parstr, "F", 1) > 0) {   /* new in v0.3m */
1804
             opt_fp = true;
1805
             fpformat = fpf_decimal;
1806
             }
1807
             if (strpos2(parstr, "h", 1) > 1) {
1808
             show_usage();
1809
             _Escape(0);
1810
             }
1811
             } else
1812
             strcpy(ndl_molfilename, parstr);
1813
             }
1814
             if (p == P_argc - 2) {
1815
             if (strpos2(parstr, "-", 1) != 1)
1816
             strcpy(ndl_molfilename, parstr);
1817
             }
1818
             if (p == P_argc - 1) {
1819
             if (strcmp(parstr, "-"))
1820
             strcpy(molfilename, parstr);
1821
             else
1822
             opt_stdin = true;
1823
             }
1824
             }
1825
             if (opt_geom)   /* v0.3d */
1826
             ez_search = true;
1827
             if (opt_chiral)   /* v0.3f */
1828
             rs_search = true;
1829
             if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1830
             /* new in v0.3j, v0.3m */
1831
             rs_strict = true;
1832
             if (opt_fp) {   /* v0.3m */
1833
             opt_molout = false;
1834
             opt_exact = false;
1835
             }
1836
             }  /* progmode = pmMatchMol */
1837
             ringsearch_mode = opt_rs;   /* v0.3i */
1838
             }
1839
#endif
1840
 
1841
static void
1842
parse_args (int argc, char *argv[])
1843
{
1844
  short p;
1845
  char parstr[256];
1846
  char tmpstr[256];
1847
  short l;
1848
 
1849
  *tmpstr = '\0';
1850
  opt_none = true;
1851
  *molfilename = '\0';
1852
  *ndl_molfilename = '\0';
1853
  if (progmode == pmCheckMol)
1854
    {
1855
      for (p = 1; p <= argc - 1; p++)
1856
        {
1857
          strcpy (parstr, argv[p]);
1858
          if (!strcmp (parstr, "-l"))
1859
            {                   /* new in v0.3l */
1860
              list_molstat_codes ();
1861
              exit (0);
1862
            }
1863
          if (p < argc - 1)
1864
            {
1865
              if (strpos2 (parstr, "-", 1) == 1 && p < argc - 1)
1866
                {
1867
                  strcpy (tmpstr, argv[p]);
1868
                  left_trim (tmpstr);
1869
                  l = 0;
1870
                  if (strpos2 (tmpstr, "v", 1) > 0)
1871
                    l++;
1872
                  if (strpos2 (tmpstr, "D", 1) > 0)
1873
                    l++;
1874
                  if (strpos2 (tmpstr, "r", 1) > 0)
1875
                    l++;
1876
                  /*if (strpos2 (tmpstr, "a", 1) > 0)   // 0.3x
1877
                     l++; */
1878
                  if (strpos2 (tmpstr, "M", 1) > 0)     /* new in v0.3 */
1879
                    l++;
1880
                  if (strlen (tmpstr) > l + 2)
1881
                    {
1882
                      show_usage ();
1883
                      exit (1);
1884
                    }
1885
                  opt_none = false;
1886
                  if (strpos2 (tmpstr, "M", 1) > 0)
1887
                    opt_metalrings = true;
1888
                  if (strpos2 (tmpstr, "v", 1) > 0)
1889
                    opt_verbose = true;
1890
                  /*{$IFDEF debug
1891
                     if pos('D',tmpstr)>0 then opt_debug       := true;
1892
                     {$ENDIF */
1893
                  if (strpos2 (tmpstr, "e", 1) > 0)
1894
                    opt_text = true;
1895
                  else
1896
                    {
1897
                      if (strpos2 (tmpstr, "d", 1) > 0)
1898
                        opt_text_de = true;
1899
                      else
1900
                        {
1901
                          if (strpos2 (tmpstr, "c", 1) > 0)
1902
                            opt_code = true;
1903
                          else
1904
                            {
1905
                              if (strpos2 (tmpstr, "b", 1) > 0)
1906
                                opt_bin = true;
1907
                              else
1908
                                {
1909
                                  if (strpos2 (tmpstr, "s", 1) > 0)
1910
                                    opt_bitstring = true;
1911
                                }
1912
                            }
1913
                        }
1914
                      if (strpos2 (tmpstr, "x", 1) > 0)
1915
                        opt_molstat = true;
1916
                      if (strpos2 (tmpstr, "r", 1) > 0)
1917
                        opt_rs = rs_ssr;
1918
                      /* if (strpos2 (tmpstr, "a", 1) > 0)
1919
                         opt_chg = true; */ /* 0.3x  */
1920
                      if (strpos2 (tmpstr, "X", 1) > 0)
1921
                        {
1922
                          opt_molstat = true;
1923
                          opt_molstat_X = true;
1924
                        }
1925
                      if (strpos2 (tmpstr, "m", 1) > 0)
1926
                        {
1927
                          opt_text = false;
1928
                          opt_text_de = false;
1929
                          opt_bin = false;
1930
                          opt_bitstring = false;
1931
                          opt_code = false;
1932
                          opt_molstat = false;
1933
                          opt_xmdlout = true;
1934
                        }
1935
                    }
1936
                  strcpy (molfilename, tmpstr);
1937
                }
1938
            }
1939
          else
1940
            {
1941
              if (strpos2 (parstr, "-", 1) == 1)
1942
                {
1943
                  if (strlen (parstr) > 1)
1944
                    {
1945
                      show_usage ();
1946
                      exit (1);
1947
                    }
1948
                  opt_stdin = true;
1949
                }
1950
              else
1951
                {
1952
                  opt_stdin = false;
1953
                  strcpy (molfilename, parstr);
1954
                }
1955
            }
1956
        }
1957
      if (opt_text == false && opt_text_de == false && opt_code == false &&
1958
          opt_bin == false && opt_bitstring == false && opt_molstat == false
1959
          && opt_molstat_X == false && opt_xmdlout == false
1960
          && opt_chg == false)
1961
        opt_none = true;        /* 0.3x */
1962
    }
1963
  if (progmode == pmMatchMol)
1964
    {
1965
 
1966
      for (p = 1; p <= argc - 1; p++)
1967
        {
1968
          strcpy (parstr, argv[p]);
1969
          if (p == 1)
1970
            {
1971
              if (strpos2 (parstr, "-", 1) == 1)
1972
                {
1973
                  if (strpos2 (parstr, "v", 1) > 1)
1974
                    opt_verbose = true;
1975
                  /*{$IFDEF debug
1976
                     if pos('D',parstr)>1 then opt_debug       := true;
1977
                     {$ENDIF */
1978
                  if (strpos2 (parstr, "x", 1) > 1)
1979
                    opt_exact = true;
1980
                  if (strpos2 (parstr, "s", 1) > 1)     /* new in v0.2f */
1981
                    opt_strict = true;
1982
                  if (strpos2 (parstr, "m", 1) > 1)
1983
                    opt_molout = true;
1984
                  if (strpos2 (parstr, "r", 1) > 1)
1985
                    opt_rs = rs_ssr;
1986
                  if (strpos2 (parstr, "a", 1) > 0)
1987
                    opt_chg = true;     /* 0.3x */
1988
                  if (strpos2 (parstr, "i", 1) > 0)
1989
                    opt_iso = true;     /* 0.3x */
1990
                  if (strpos2 (parstr, "d", 1) > 0)
1991
                    opt_rad = true;     /* 0.3x */
1992
                  if (strpos2 (parstr, "M", 1) > 0)     /* new in v0.3 */
1993
                    opt_metalrings = true;
1994
                  if (strpos2 (parstr, "g", 1) > 0)     /* new in v0.3d */
1995
                    opt_geom = true;
1996
                  if (strpos2 (parstr, "G", 1) > 0)     /* new in v0.3f */
1997
                    opt_chiral = true;
1998
                  if (strpos2 (parstr, "f", 1) > 0)
1999
                    {           /* new in v0.3m */
2000
                      opt_fp = true;
2001
                      fpformat = fpf_boolean;
2002
                    }
2003
                  if (strpos2 (parstr, "F", 1) > 0)
2004
                    {           /* new in v0.3m */
2005
                      opt_fp = true;
2006
                      fpformat = fpf_decimal;
2007
                    }
2008
                  if (strpos2 (parstr, "h", 1) > 1)
2009
                    {
2010
                      show_usage ();
2011
                      exit (0);
2012
                    }
2013
                }
2014
              else
2015
                strcpy (ndl_molfilename, parstr);
2016
            }
2017
          if (p == argc - 2)
2018
            {
2019
              if (strpos2 (parstr, "-", 1) != 1)
2020
                strcpy (ndl_molfilename, parstr);
2021
            }
2022
          if (p == argc - 1)
2023
            {
2024
              if (strcmp (parstr, "-"))
2025
                strcpy (molfilename, parstr);
2026
              else
2027
                opt_stdin = true;
2028
            }
2029
        }
2030
      if (opt_geom)             /* v0.3d */
2031
        ez_search = true;
2032
      if (opt_chiral)           /* v0.3f */
2033
        rs_search = true;
2034
      if (opt_chiral && opt_strict && (opt_exact || opt_fp))
2035
        /* new in v0.3j, v0.3m  */
2036
        rs_strict = true;
2037
      if (opt_fp)
2038
        {                       /* v0.3m */
2039
          opt_molout = false;
2040
          opt_exact = false;
2041
        }
2042
    }                           /* progmode = pmMatchMol */
2043
  ringsearch_mode = opt_rs;     /* v0.3i */
2044
}
2045
 
2046
/*============== input-related functions & procedures ===================== */
2047
 
2048
static char *
2049
get_filetype (Result, f)
2050
     char *Result;
2051
     char *f;
2052
{
2053
  char rline[256];
2054
  char auxstr[256];
2055
  int i;
2056
  boolean mdl1 = false;
2057
  int ri;
2058
  int sepcount = 0;
2059
  char STR1[256], STR6[256], STR7[256];
2060
 
2061
  strcpy (auxstr, "unknown");
2062
  i = li;
2063
  ri = li - 1;
2064
  while (ri < molbufindex && sepcount < 1)
2065
    {
2066
      ri++;
2067
      strcpy (rline, molbuf[ri - 1]);
2068
      if (strpos2 (rline, "$$$$", 1) > 0)
2069
        sepcount++;
2070
      if ((i == li) && (strcmp (strsub (STR1, rline, 7, 5), "ATOMS") == 0) &&
2071
          (strcmp (strsub (STR6, rline, 20, 5), "BONDS") == 0) &&
2072
          (strcmp (strsub (STR7, rline, 33, 7), "CHARGES") == 0))
2073
        strcpy (auxstr, "alchemy");
2074
      if ((i == li + 3) && (strcmp (strsub (STR1, rline, 35, 5), "V2000") ==
2075
                            0))
2076
        /* and (copy(rline,31,3)='999') */
2077
        mdl1 = true;
2078
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 6), "-ISIS-") ==
2079
                            0))
2080
        mdl1 = true;
2081
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "WLViewer") ==
2082
                            0))
2083
        mdl1 = true;
2084
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CheckMol") ==
2085
                            0))
2086
        mdl1 = true;
2087
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CATALYST") ==
2088
                            0))
2089
        {
2090
          mdl1 = true;
2091
          strcpy (auxstr, "mdl");
2092
        }
2093
      if (strpos2 (rline, "M  END", 1) == 1 || mdl1)
2094
        strcpy (auxstr, "mdl");
2095
      if (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) > 0)
2096
        strcpy (auxstr, "sybyl");
2097
      i++;
2098
    }
2099
  /* new in v0.2j: try to identify non-conformant SD-files */
2100
  if (!strcmp (auxstr, "unknown") && sepcount > 0)
2101
    strcpy (auxstr, "mdl");
2102
  return strcpy (Result, auxstr);
2103
}
2104
 
2105
 
2106
static void
2107
zap_molecule ()
2108
{
2109
  /* try */
2110
  if (atom != NULL)
2111
    {
2112
      free (atom);
2113
      atom = NULL;              /* added in v0.3j */
2114
    }
2115
  if (bond != NULL)
2116
    {
2117
      free (bond);
2118
      bond = NULL;              /* added in v0.3j */
2119
    }
2120
  if (ring != NULL)
2121
    {
2122
      free (ring);
2123
      ring = NULL;              /* added in v0.3j */
2124
    }
2125
  if (ringprop != NULL)
2126
    {
2127
      free (ringprop);
2128
      ringprop = NULL;          /* added in v0.3j */
2129
    }
2130
  /* except
2131
     on e:Einvalidpointer do begin end;
2132
     end; */
2133
  n_atoms = 0;
2134
  n_bonds = 0;
2135
  n_rings = 0;
2136
}
2137
 
2138
 
2139
static void
2140
zap_needle ()
2141
{
2142
  /* try */
2143
  if (ndl_atom != NULL)
2144
    {
2145
      free (ndl_atom);
2146
      ndl_atom = NULL;          /* added in v0.3j */
2147
    }
2148
  if (ndl_bond != NULL)
2149
    {
2150
      free (ndl_bond);
2151
      ndl_bond = NULL;          /* added in v0.3j */
2152
    }
2153
  if (ndl_ring != NULL)
2154
    {
2155
      free (ndl_ring);
2156
      ndl_ring = NULL;          /* added in v0.3j */
2157
    }
2158
  if (ndl_ringprop != NULL)
2159
    {
2160
      free (ndl_ringprop);      /* fixed in v0.3g */
2161
      ndl_ringprop = NULL;      /* added in v0.3j */
2162
    }
2163
  /* except
2164
     on e:Einvalidpointer do begin end;
2165
     end; */
2166
  ndl_n_atoms = 0;
2167
  ndl_n_bonds = 0;
2168
  ndl_n_rings = 0;
2169
}
2170
 
2171
#if 0
2172
static void
2173
zap_tmp ()
2174
{
2175
  /* try */
2176
  if (tmp_atom != NULL)
2177
    {
2178
      free (tmp_atom);
2179
      tmp_atom = NULL;          /* added in v0.3j */
2180
    }
2181
  if (tmp_bond != NULL)
2182
    {
2183
      free (tmp_bond);
2184
      tmp_bond = NULL;          /* added in v0.3j */
2185
    }
2186
  if (tmp_ring != NULL)
2187
    {
2188
      free (tmp_ring);
2189
      tmp_ring = NULL;          /* added in v0.3j */
2190
    }
2191
  if (tmp_ringprop != NULL)
2192
    {
2193
      free (tmp_ringprop);      /* fixed in v0.3g */
2194
      tmp_ringprop = NULL;      /* added in v0.3j */
2195
    }
2196
  /* except
2197
     on e:Einvalidpointer do begin end;
2198
     end; */
2199
  tmp_n_atoms = 0;
2200
  tmp_n_bonds = 0;
2201
  tmp_n_rings = 0;
2202
}
2203
#endif
2204
 
2205
static boolean
2206
is_heavyatom (id)
2207
     int id;
2208
{
2209
  str2 el;
2210
 
2211
  strcpy (el, atom[id - 1].element);
2212
 
2213
  if (!strcmp (el, "DU") || !strcmp (el, "LP"))
2214
    return false;
2215
  /*if (progmode == pmCheckMol && !strcmp (el, "H ")
2216
     && atom[id - 1].nucleon_number < 2)
2217
     return false;               0.3x  */
2218
  if (!strcmp (el, "H "))       /* 0.3 p */
2219
    {
2220
      if (progmode == pmMatchMol && !opt_iso)
2221
        {
2222
          return false;
2223
        }
2224
      else
2225
        {
2226
          if (atom[id - 1].nucleon_number < 2)
2227
            return false;
2228
        }
2229
    }
2230
  return true;
2231
}
2232
 
2233
 
2234
static boolean
2235
ndl_alkene_C (ba)
2236
     int ba;
2237
{
2238
  /* new in v0.3f */
2239
  boolean res = false;
2240
  int i, ba2, FORLIM;
2241
 
2242
  if (ndl_n_atoms <= 0 || ndl_n_bonds <= 0)
2243
    return false;
2244
  FORLIM = ndl_n_bonds;
2245
  for (i = 0; i < FORLIM; i++)
2246
    {
2247
      if (ndl_bond[i].a1 == ba || ndl_bond[i].a2 == ba)
2248
        {
2249
          if (ndl_bond[i].a1 == ba)
2250
            ba2 = ndl_bond[i].a2;
2251
          else
2252
            ba2 = ndl_bond[i].a1;
2253
          if (!strcmp (ndl_atom[ba - 1].atype, "C2 ") &&
2254
              !strcmp (ndl_atom[ba2 - 1].atype, "C2 ")
2255
              && ndl_bond[i].btype == 'D' && ndl_bond[i].arom == false)
2256
            res = true;
2257
        }
2258
    }
2259
  return res;
2260
}
2261
 
2262
 
2263
static boolean
2264
is_metal (id)
2265
     int id;
2266
{
2267
  boolean r = false;
2268
  str2 el;
2269
 
2270
  strcpy (el, atom[id - 1].element);
2271
  if (!strcmp (el, "LI") || !strcmp (el, "NA") || !strcmp (el, "K ") ||
2272
      !strcmp (el, "RB") || !strcmp (el, "CS") || !strcmp (el, "BE") ||
2273
      !strcmp (el, "MG") || !strcmp (el, "CA") || !strcmp (el, "SR") ||
2274
      !strcmp (el, "BA") || !strcmp (el, "TI") || !strcmp (el, "ZR") ||
2275
      !strcmp (el, "CR") || !strcmp (el, "MO") || !strcmp (el, "MN") ||
2276
      !strcmp (el, "FE") || !strcmp (el, "CO") || !strcmp (el, "NI") ||
2277
      !strcmp (el, "PD") || !strcmp (el, "PT") || !strcmp (el, "SN") ||
2278
      !strcmp (el, "CU") || !strcmp (el, "AG") || !strcmp (el, "AU") ||
2279
      !strcmp (el, "ZN") || !strcmp (el, "CD") || !strcmp (el, "HG") ||
2280
      !strcmp (el, "AL") || !strcmp (el, "SN") || !strcmp (el, "PB") ||
2281
      !strcmp (el, "SB") || !strcmp (el, "BI"))
2282
/* p2c: checkmol.pas, line 1577:
2283
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 1686 [251] */
2284
    /* etc. etc. */
2285
    r = true;
2286
  return r;
2287
}
2288
 
2289
 
2290
static int
2291
get_nvalences (a_el)
2292
     char *a_el;
2293
{
2294
  /* changed name and position in v0.3m */
2295
  /* preliminary version; should be extended to element/atomtype */
2296
  int res = 1;
2297
 
2298
  if (!strcmp (a_el, "H "))
2299
    res = 1;
2300
  /*if (!strcmp (a_el, "D "))   // v0.3n
2301
     res = 1; */
2302
  if (!strcmp (a_el, "C "))
2303
    res = 4;
2304
  if (!strcmp (a_el, "N "))
2305
    res = 3;
2306
  if (!strcmp (a_el, "O "))
2307
    res = 2;
2308
  if (!strcmp (a_el, "S "))
2309
    res = 2;
2310
  if (!strcmp (a_el, "SE"))
2311
    res = 2;
2312
  if (!strcmp (a_el, "TE"))
2313
    res = 2;
2314
  if (!strcmp (a_el, "P "))
2315
    res = 3;
2316
  if (!strcmp (a_el, "F "))
2317
    res = 1;
2318
  if (!strcmp (a_el, "CL"))
2319
    res = 1;
2320
  if (!strcmp (a_el, "BR"))
2321
    res = 1;
2322
  if (!strcmp (a_el, "I "))
2323
    res = 1;
2324
  if (!strcmp (a_el, "AT"))
2325
    res = 1;
2326
  if (!strcmp (a_el, "B "))
2327
    res = 3;
2328
  if (!strcmp (a_el, "LI"))
2329
    res = 1;
2330
  if (!strcmp (a_el, "NA"))
2331
    res = 1;
2332
  if (!strcmp (a_el, "K "))
2333
    res = 1;
2334
  if (!strcmp (a_el, "CA"))
2335
    res = 2;
2336
  if (!strcmp (a_el, "SR"))
2337
    res = 2;
2338
  if (!strcmp (a_el, "MG"))
2339
    res = 2;
2340
  if (!strcmp (a_el, "FE"))
2341
    res = 3;
2342
  if (!strcmp (a_el, "MN"))
2343
    res = 2;
2344
  if (!strcmp (a_el, "HG"))
2345
    res = 2;
2346
  if (!strcmp (a_el, "SI"))
2347
    res = 4;
2348
  if (!strcmp (a_el, "SN"))
2349
    res = 4;
2350
  if (!strcmp (a_el, "ZN"))
2351
    res = 2;
2352
  if (!strcmp (a_el, "CU"))
2353
    res = 2;
2354
  if (!strcmp (a_el, "A "))
2355
    res = 4;
2356
  if (!strcmp (a_el, "Q "))
2357
    res = 4;
2358
  return res;
2359
}
2360
 
2361
 
2362
static char *
2363
convert_type (Result, oldtype)
2364
     char *Result;
2365
     char *oldtype;
2366
{
2367
  int i;
2368
  str3 newtype;
2369
 
2370
  sprintf (newtype, "%.3s", oldtype);
2371
  for (i = 0; i <= 2; i++)
2372
    newtype[i] = toupper (newtype[i]);
2373
  if (newtype[0] == '~')
2374
    strcpy (newtype, "VAL");
2375
  if (newtype[0] == '*')
2376
    strcpy (newtype, "STR");
2377
  return strcpy (Result, newtype);
2378
}
2379
 
2380
 
2381
static char *
2382
convert_sybtype (Result, oldtype)
2383
     char *Result;
2384
     char *oldtype;
2385
{
2386
  str3 newtype;
2387
 
2388
  /*  NewType := Copy(OldType,1,3); */
2389
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2390
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2391
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2392
  strcpy (newtype, "DU ");
2393
  if (!strcmp (oldtype, "H    "))
2394
    strcpy (newtype, "H  ");
2395
  if (!strcmp (oldtype, "C.ar "))
2396
    strcpy (newtype, "CAR");
2397
  if (!strcmp (oldtype, "C.2  "))
2398
    strcpy (newtype, "C2 ");
2399
  if (!strcmp (oldtype, "C.3  "))
2400
    strcpy (newtype, "C3 ");
2401
  if (!strcmp (oldtype, "C.1  "))
2402
    strcpy (newtype, "C1 ");
2403
  if (!strcmp (oldtype, "O.2  "))
2404
    strcpy (newtype, "O2 ");
2405
  if (!strcmp (oldtype, "O.3  "))
2406
    strcpy (newtype, "O3 ");
2407
  if (!strcmp (oldtype, "O.co2"))
2408
    strcpy (newtype, "O2 ");
2409
  if (!strcmp (oldtype, "O.spc"))
2410
    strcpy (newtype, "O3 ");
2411
  if (!strcmp (oldtype, "O.t3p"))
2412
    strcpy (newtype, "O3 ");
2413
  if (!strcmp (oldtype, "N.1  "))
2414
    strcpy (newtype, "N1 ");
2415
  if (!strcmp (oldtype, "N.2  "))
2416
    strcpy (newtype, "N2 ");
2417
  if (!strcmp (oldtype, "N.3  "))
2418
    strcpy (newtype, "N3 ");
2419
  if (!strcmp (oldtype, "N.pl3"))
2420
    strcpy (newtype, "NPL");
2421
  if (!strcmp (oldtype, "N.4  "))
2422
    strcpy (newtype, "N3+");
2423
  if (!strcmp (oldtype, "N.am "))
2424
    strcpy (newtype, "NAM");
2425
  if (!strcmp (oldtype, "N.ar "))
2426
    strcpy (newtype, "NAR");
2427
  if (!strcmp (oldtype, "F    "))
2428
    strcpy (newtype, "F  ");
2429
  if (!strcmp (oldtype, "Cl   "))
2430
    strcpy (newtype, "CL ");
2431
  if (!strcmp (oldtype, "Br   "))
2432
    strcpy (newtype, "BR ");
2433
  if (!strcmp (oldtype, "I    "))
2434
    strcpy (newtype, "I  ");
2435
  if (!strcmp (oldtype, "Al   "))
2436
    strcpy (newtype, "AL ");
2437
  if (!strcmp (oldtype, "ANY  "))
2438
    strcpy (newtype, "A  ");
2439
  if (!strcmp (oldtype, "Ca   "))
2440
    strcpy (newtype, "CA ");
2441
  if (!strcmp (oldtype, "Du   "))
2442
    strcpy (newtype, "DU ");
2443
  if (!strcmp (oldtype, "Du.C "))
2444
    strcpy (newtype, "DU ");
2445
  if (!strcmp (oldtype, "H.spc"))
2446
    strcpy (newtype, "H  ");
2447
  if (!strcmp (oldtype, "H.t3p"))
2448
    strcpy (newtype, "H  ");
2449
  if (!strcmp (oldtype, "HAL  "))
2450
    strcpy (newtype, "Cl ");
2451
  if (!strcmp (oldtype, "HET  "))
2452
    strcpy (newtype, "Q  ");
2453
  if (!strcmp (oldtype, "HEV  "))
2454
    strcpy (newtype, "DU ");
2455
  if (!strcmp (oldtype, "K    "))
2456
    strcpy (newtype, "K  ");
2457
  if (!strcmp (oldtype, "Li   "))
2458
    strcpy (newtype, "LI ");
2459
  if (!strcmp (oldtype, "LP   "))
2460
    strcpy (newtype, "LP ");
2461
  if (!strcmp (oldtype, "Na   "))
2462
    strcpy (newtype, "NA ");
2463
  if (!strcmp (oldtype, "P.3  "))
2464
    strcpy (newtype, "P3 ");
2465
  if (!strcmp (oldtype, "S.2  "))
2466
    strcpy (newtype, "S2 ");
2467
  if (!strcmp (oldtype, "S.3  "))
2468
    strcpy (newtype, "S3 ");
2469
  if (!strcmp (oldtype, "S.o  "))
2470
    strcpy (newtype, "SO ");
2471
  if (!strcmp (oldtype, "S.o2 "))
2472
    strcpy (newtype, "SO2");
2473
  if (!strcmp (oldtype, "Si   "))
2474
    strcpy (newtype, "SI ");
2475
  if (!strcmp (oldtype, "P.4  "))
2476
    strcpy (newtype, "P4 ");
2477
  return strcpy (Result, newtype);
2478
}
2479
 
2480
 
2481
static char *
2482
convert_MDLtype (Result, oldtype)
2483
     char *Result, *oldtype;
2484
{
2485
  str3 newtype;
2486
 
2487
  /*  NewType := Copy(OldType,1,3); */
2488
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2489
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2490
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2491
  strcpy (newtype, "DU ");
2492
  if (!strcmp (oldtype, "H  "))
2493
    strcpy (newtype, "H  ");
2494
  if (!strcmp (oldtype, "C  "))
2495
    strcpy (newtype, "C3 ");
2496
  if (!strcmp (oldtype, "O  "))
2497
    strcpy (newtype, "O2 ");
2498
  if (!strcmp (oldtype, "N  "))
2499
    strcpy (newtype, "N3 ");
2500
  if (!strcmp (oldtype, "F  "))
2501
    strcpy (newtype, "F  ");
2502
  if (!strcmp (oldtype, "Cl "))
2503
    strcpy (newtype, "CL ");
2504
  if (!strcmp (oldtype, "Br "))
2505
    strcpy (newtype, "BR ");
2506
  if (!strcmp (oldtype, "I  "))
2507
    strcpy (newtype, "I  ");
2508
  if (!strcmp (oldtype, "Al "))
2509
    strcpy (newtype, "AL ");
2510
  if (!strcmp (oldtype, "ANY"))
2511
    strcpy (newtype, "A  ");
2512
  if (!strcmp (oldtype, "Ca "))
2513
    strcpy (newtype, "CA ");
2514
  if (!strcmp (oldtype, "Du "))
2515
    strcpy (newtype, "DU ");
2516
  if (!strcmp (oldtype, "K  "))
2517
    strcpy (newtype, "K  ");
2518
  if (!strcmp (oldtype, "Li "))
2519
    strcpy (newtype, "LI ");
2520
  if (!strcmp (oldtype, "LP "))
2521
    strcpy (newtype, "LP ");
2522
  if (!strcmp (oldtype, "Na "))
2523
    strcpy (newtype, "NA ");
2524
  if (!strcmp (oldtype, "P  "))
2525
    strcpy (newtype, "P3 ");
2526
  if (!strcmp (oldtype, "S  "))
2527
    strcpy (newtype, "S3 ");
2528
  if (!strcmp (oldtype, "Si "))
2529
    strcpy (newtype, "SI ");
2530
  if (!strcmp (oldtype, "P  "))
2531
    strcpy (newtype, "P4 ");
2532
  if (!strcmp (oldtype, "A  "))
2533
    strcpy (newtype, "A  ");
2534
  if (!strcmp (oldtype, "Q  "))
2535
    strcpy (newtype, "Q  ");
2536
  return strcpy (Result, newtype);
2537
}
2538
 
2539
 
2540
static char *
2541
get_element (Result, oldtype)
2542
     char *Result;
2543
     char *oldtype;
2544
{
2545
  char elemstr[256];
2546
 
2547
  if (!strcmp (oldtype, "H   "))
2548
    strcpy (elemstr, "H ");
2549
  /* if (!strcmp (oldtype, "D   "))  // v0.3n
2550
     strcpy (elemstr, "D "); */
2551
  if (!strcmp (oldtype, "CAR "))
2552
    strcpy (elemstr, "C ");
2553
  if (!strcmp (oldtype, "C2  "))
2554
    strcpy (elemstr, "C ");
2555
  if (!strcmp (oldtype, "C3  "))
2556
    strcpy (elemstr, "C ");
2557
  if (!strcmp (oldtype, "C1  "))
2558
    strcpy (elemstr, "C ");
2559
  if (!strcmp (oldtype, "O2  "))
2560
    strcpy (elemstr, "O ");
2561
  if (!strcmp (oldtype, "O3  "))
2562
    strcpy (elemstr, "O ");
2563
  if (!strcmp (oldtype, "O2  "))
2564
    strcpy (elemstr, "O ");
2565
  if (!strcmp (oldtype, "O3  "))
2566
    strcpy (elemstr, "O ");
2567
  if (!strcmp (oldtype, "O3  "))
2568
    strcpy (elemstr, "O ");
2569
  if (!strcmp (oldtype, "N1  "))
2570
    strcpy (elemstr, "N ");
2571
  if (!strcmp (oldtype, "N2  "))
2572
    strcpy (elemstr, "N ");
2573
  if (!strcmp (oldtype, "N3  "))
2574
    strcpy (elemstr, "N ");
2575
  if (!strcmp (oldtype, "NPL "))
2576
    strcpy (elemstr, "N ");
2577
  if (!strcmp (oldtype, "N3+ "))
2578
    strcpy (elemstr, "N ");
2579
  if (!strcmp (oldtype, "NAM "))
2580
    strcpy (elemstr, "N ");
2581
  if (!strcmp (oldtype, "NAR "))
2582
    strcpy (elemstr, "N ");
2583
  if (!strcmp (oldtype, "F   "))
2584
    strcpy (elemstr, "F ");
2585
  if (!strcmp (oldtype, "CL  "))
2586
    strcpy (elemstr, "CL");
2587
  if (!strcmp (oldtype, "BR  "))
2588
    strcpy (elemstr, "BR");
2589
  if (!strcmp (oldtype, "I   "))
2590
    strcpy (elemstr, "I ");
2591
  if (!strcmp (oldtype, "AT  "))
2592
    strcpy (elemstr, "AT");
2593
  if (!strcmp (oldtype, "AL  "))
2594
    strcpy (elemstr, "AL");
2595
  if (!strcmp (oldtype, "DU  "))
2596
    strcpy (elemstr, "DU");
2597
  if (!strcmp (oldtype, "CA  "))
2598
    strcpy (elemstr, "CA");
2599
  if (!strcmp (oldtype, "DU  "))
2600
    strcpy (elemstr, "DU");
2601
  if (!strcmp (oldtype, "Cl  "))
2602
    strcpy (elemstr, "CL");
2603
  if (!strcmp (oldtype, "K   "))
2604
    strcpy (elemstr, "K ");
2605
  if (!strcmp (oldtype, "LI  "))
2606
    strcpy (elemstr, "LI");
2607
  if (!strcmp (oldtype, "LP  "))
2608
    strcpy (elemstr, "LP");
2609
  if (!strcmp (oldtype, "NA  "))
2610
    strcpy (elemstr, "NA");
2611
  if (!strcmp (oldtype, "P3  "))
2612
    strcpy (elemstr, "P ");
2613
  if (!strcmp (oldtype, "S2  "))
2614
    strcpy (elemstr, "S ");
2615
  if (!strcmp (oldtype, "S3  "))
2616
    strcpy (elemstr, "S ");
2617
  if (!strcmp (oldtype, "SO  "))
2618
    strcpy (elemstr, "S ");
2619
  if (!strcmp (oldtype, "SO2 "))
2620
    strcpy (elemstr, "S ");
2621
  if (!strcmp (oldtype, "SI  "))
2622
    strcpy (elemstr, "SI");
2623
  if (!strcmp (oldtype, "P4  "))
2624
    strcpy (elemstr, "P ");
2625
  if (!strcmp (oldtype, "A   "))
2626
    strcpy (elemstr, "A ");
2627
  if (!strcmp (oldtype, "Q   "))
2628
    strcpy (elemstr, "Q ");
2629
  return strcpy (Result, elemstr);
2630
}
2631
 
2632
 
2633
static char *
2634
get_sybelement (Result, oldtype)
2635
     char *Result;
2636
     char *oldtype;
2637
{
2638
  int i;
2639
  str2 elemstr;
2640
 
2641
  if (strpos2 (oldtype, ".", 1) < 2)
2642
    sprintf (elemstr, "%.2s", oldtype);
2643
  else
2644
    {
2645
      sprintf (elemstr, "%.*s", strpos2 (oldtype, ".", 1) - 1, oldtype);
2646
      if (strlen (elemstr) < 2)
2647
        strcat (elemstr, " ");
2648
    }
2649
  for (i = 0; i <= 1; i++)
2650
    elemstr[i] = toupper (elemstr[i]);
2651
  return strcpy (Result, elemstr);
2652
}
2653
 
2654
 
2655
static char *
2656
get_MDLelement (Result, oldtype)
2657
     char *Result;
2658
     char *oldtype;
2659
{
2660
  int i;
2661
  str2 elemstr;
2662
 
2663
  sprintf (elemstr, "%.2s", oldtype);
2664
  for (i = 0; i <= 1; i++)
2665
    elemstr[i] = toupper (elemstr[i]);
2666
  if (elemstr[0] == '~')
2667
    strcpy (elemstr, "??");
2668
  if (elemstr[0] == '*')
2669
    strcpy (elemstr, "??");
2670
  return strcpy (Result, elemstr);
2671
}
2672
 
2673
static void
2674
read_molfile (mfilename)
2675
     char *mfilename;
2676
{
2677
  /* reads ALCHEMY mol files */
2678
  int n, code;
2679
  char rline[256], tmpstr[256];
2680
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2681
  float xval, yval, zval, chgval;
2682
  char a1str[256], a2str[256], elemstr[256];
2683
  int a1val, a2val, ri;
2684
  char STR1[256];
2685
  int FORLIM;
2686
  atom_rec *WITH;
2687
  bond_rec *WITH1;
2688
 
2689
  if (n_atoms > 0)
2690
    zap_molecule ();
2691
  ri = li;
2692
  strcpy (rline, molbuf[ri - 1]);
2693
  sprintf (tmpstr, "%.5s", rline);
2694
  code = (sscanf (tmpstr, "%d", &n_atoms) == 0);
2695
  strsub (tmpstr, rline, 14, 5);
2696
  code = (sscanf (tmpstr, "%d", &n_bonds) == 0);
2697
  strsub (molname, rline, 42, (int) (strlen (rline) - 42L));
2698
  /* try */
2699
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2700
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2701
  ring = safe_calloc (1, sizeof (ringlist));
2702
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2703
  /* except
2704
     on e:Eoutofmemory do
2705
     begin
2706
     writeln('Not enough memory');
2707
     halt(4);
2708
     end;
2709
     end; */
2710
  n_heavyatoms = 0;
2711
  n_heavybonds = 0;
2712
  n_Ctot = 0;                   /* v0.3g */
2713
  n_Otot = 0;                   /* v0.3g */
2714
  n_Ntot = 0;                   /* v0.3g */
2715
  FORLIM = n_atoms;
2716
  for (n = 1; n <= FORLIM; n++)
2717
    {
2718
      ri++;
2719
      strcpy (rline, molbuf[ri - 1]);
2720
      strsub (atomtype, rline, 7, 4);
2721
      sprintf (STR1, "%c", toupper (*atomtype));
2722
      strcpy (atomtype, STR1);  /* fixed in v0.3f */
2723
      get_element (elemstr, atomtype);
2724
      if (!strcmp (elemstr, "C "))
2725
        n_Ctot++;
2726
      if (!strcmp (elemstr, "O "))
2727
        n_Otot++;
2728
      if (!strcmp (elemstr, "N "))
2729
        n_Ntot++;
2730
      convert_type (newatomtype, atomtype);
2731
      strsub (xstr, rline, 14, 7);
2732
      strsub (ystr, rline, 23, 7);
2733
      strsub (zstr, rline, 32, 7);
2734
      strsub (chgstr, rline, 43, 7);
2735
      code = (sscanf (xstr, "%g", &xval) == 0);
2736
      code = (sscanf (ystr, "%g", &yval) == 0);
2737
      code = (sscanf (zstr, "%g", &zval) == 0);
2738
      code = (sscanf (chgstr, "%g", &chgval) == 0);
2739
      WITH = &atom[n - 1];
2740
      strcpy (WITH->element, elemstr);
2741
      strcpy (WITH->atype, newatomtype);
2742
      WITH->x = xval;
2743
      WITH->y = yval;
2744
      WITH->z = zval;
2745
      WITH->real_charge = chgval;
2746
      if (is_heavyatom (n))
2747
        {
2748
          n_heavyatoms++;
2749
          WITH->heavy = true;
2750
          if (is_metal (n))
2751
            WITH->metal = true;
2752
        }
2753
      WITH->nvalences = get_nvalences (WITH->element);  /* v0.3m   */
2754
    }
2755
  /*
2756
     with atom^[n] do
2757
     begin
2758
     x := 0; y := 0; z := 0;  (* v0.3g
2759
     formal_charge  := 0;
2760
     real_charge    := 0;
2761
     Hexp           := 0;
2762
     Htot           := 0;
2763
     neighbor_count := 0;
2764
     ring_count     := 0;
2765
     arom           := false;
2766
     stereo_care    := false;
2767
     heavy          := false;
2768
     metal          := false;
2769
     tag            := false;
2770
     end;
2771
   */
2772
  FORLIM = n_bonds;
2773
  for (n = 0; n < FORLIM; n++)
2774
    {
2775
      ri++;
2776
      strcpy (rline, molbuf[ri - 1]);
2777
      strsub (a1str, rline, 9, 3);
2778
      strsub (a2str, rline, 15, 3);
2779
      code = (sscanf (a1str, "%d", &a1val) == 0);
2780
      /* if code <> 0 then beep; */
2781
      code = (sscanf (a2str, "%d", &a2val) == 0);
2782
      /* if code <> 0 then beep; */
2783
      WITH1 = &bond[n];
2784
      WITH1->a1 = a1val;
2785
      WITH1->a2 = a2val;
2786
      WITH1->btype = rline[19];
2787
      WITH1->ring_count = 0;
2788
      WITH1->arom = false;
2789
      WITH1->topo = btopo_any;
2790
      WITH1->stereo = bstereo_any;
2791
      WITH1->mdl_stereo = 0;    /* v0.3n */
2792
      if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2793
        n_heavybonds++;
2794
    }
2795
  memset (ring, 0, sizeof (ringlist));
2796
  for (n = 0; n < max_rings; n++)
2797
    {                           /* new in v0.3 */
2798
      ringprop[n].size = 0;
2799
      ringprop[n].arom = false;
2800
      ringprop[n].envelope = false;
2801
    }
2802
  li = ri + 1;
2803
}
2804
 
2805
 
2806
static void
2807
read_mol2file (mfilename)
2808
     char *mfilename;
2809
{
2810
  /* reads SYBYL mol2 files */
2811
  int n, code;
2812
  char sybatomtype[6];
2813
  char tmpstr[256], rline[256];
2814
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2815
  float xval, yval, zval, chgval;
2816
  char a1str[256], a2str[256], elemstr[256];
2817
  int a1val, a2val, ri, FORLIM;
2818
  atom_rec *WITH;
2819
  bond_rec *WITH1;
2820
 
2821
  if (n_atoms > 0)
2822
    zap_molecule ();
2823
  *rline = '\0';
2824
  ri = li - 1;
2825
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) == 0))
2826
    {
2827
      ri++;
2828
      strcpy (rline, molbuf[ri - 1]);
2829
    }
2830
  if (ri < molbufindex)
2831
    {
2832
      ri++;
2833
      strcpy (molname, molbuf[ri - 1]);
2834
    }
2835
  if (ri < molbufindex)
2836
    {
2837
      ri++;
2838
      strcpy (rline, molbuf[ri - 1]);
2839
    }
2840
  sprintf (tmpstr, "%.5s", rline);
2841
  sscanf (tmpstr, "%d", &n_atoms);
2842
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2843
  strsub (tmpstr, rline, 7, 5);
2844
  sscanf (tmpstr, "%d", &n_bonds);
2845
  /* try */
2846
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2847
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2848
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2849
  ring = safe_calloc (1, sizeof (ringlist));
2850
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2851
  /* except
2852
     on e:Eoutofmemory do
2853
     begin
2854
     writeln('Not enough memory');
2855
     halt(4);
2856
     end;
2857
     end; */
2858
  n_heavyatoms = 0;
2859
  n_heavybonds = 0;
2860
  n_Ctot = 0;                   /* v0.3g */
2861
  n_Otot = 0;                   /* v0.3g */
2862
  n_Ntot = 0;                   /* v0.3g */
2863
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>ATOM", 1) == 0))
2864
    {
2865
      ri++;
2866
      strcpy (rline, molbuf[ri - 1]);
2867
    }
2868
  FORLIM = n_atoms;
2869
  for (n = 1; n <= FORLIM; n++)
2870
    {
2871
      /*
2872
         with atom^[n] do
2873
         begin
2874
         x := 0; y := 0; z := 0;  (* v0.3g
2875
         formal_charge  := 0;
2876
         real_charge    := 0;
2877
         Hexp           := 0;
2878
         Htot           := 0;
2879
         neighbor_count := 0;
2880
         ring_count     := 0;
2881
         arom           := false;
2882
         stereo_care    := false;
2883
         heavy          := false;
2884
         metal          := false;
2885
         tag            := false;
2886
         end;
2887
       */
2888
      if (ri < molbufindex)
2889
        {
2890
          ri++;
2891
          strcpy (rline, molbuf[ri - 1]);
2892
        }
2893
      strsub (sybatomtype, rline, 48, 5);
2894
      get_sybelement (elemstr, sybatomtype);
2895
      if (!strcmp (elemstr, "C "))
2896
        n_Ctot++;
2897
      if (!strcmp (elemstr, "O "))
2898
        n_Otot++;
2899
      if (!strcmp (elemstr, "N "))
2900
        n_Ntot++;
2901
      convert_sybtype (newatomtype, sybatomtype);
2902
      strsub (xstr, rline, 18, 9);
2903
      strsub (ystr, rline, 28, 9);
2904
      strsub (zstr, rline, 38, 9);
2905
      strsub (chgstr, rline, 70, 9);
2906
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2907
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2908
      sscanf (xstr, "%g", &xval);
2909
      sscanf (ystr, "%g", &yval);
2910
      sscanf (zstr, "%g", &zval);
2911
      sscanf (chgstr, "%g", &chgval);
2912
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2913
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2914
      WITH = &atom[n - 1];
2915
      strcpy (WITH->element, elemstr);
2916
      strcpy (WITH->atype, newatomtype);
2917
      WITH->x = xval;
2918
      WITH->y = yval;
2919
      WITH->z = zval;
2920
      WITH->real_charge = chgval;
2921
      if (is_heavyatom (n))
2922
        {
2923
          n_heavyatoms++;
2924
          WITH->heavy = true;
2925
          if (is_metal (n))
2926
            WITH->metal = true;
2927
        }
2928
      WITH->nvalences = get_nvalences (WITH->element);  /* v0.3m   */
2929
    }
2930
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>BOND", 1) == 0))
2931
    {
2932
      ri++;
2933
      strcpy (rline, molbuf[ri - 1]);
2934
    }
2935
  FORLIM = n_bonds;
2936
  for (n = 0; n < FORLIM; n++)
2937
    {
2938
      if (ri < molbufindex)
2939
        {
2940
          ri++;
2941
          strcpy (rline, molbuf[ri - 1]);
2942
        }
2943
      strsub (a1str, rline, 9, 3);
2944
      strsub (a2str, rline, 14, 3);
2945
      code = (sscanf (a1str, "%d", &a1val) == 0);
2946
      if (code != 0)
2947
        printf ("%s\007\n", rline);
2948
      code = (sscanf (a2str, "%d", &a2val) == 0);
2949
      if (code != 0)
2950
        printf ("%s\007\n", rline);
2951
      WITH1 = &bond[n];
2952
      WITH1->a1 = a1val;
2953
      WITH1->a2 = a2val;
2954
      if (rline[17] == '1')
2955
        WITH1->btype = 'S';
2956
      if (rline[17] == '2')
2957
        WITH1->btype = 'D';
2958
      if (rline[17] == '3')
2959
        WITH1->btype = 'T';
2960
      if (rline[17] == 'a')
2961
        WITH1->btype = 'A';
2962
      WITH1->ring_count = 0;
2963
      WITH1->arom = false;
2964
      WITH1->topo = btopo_any;
2965
      WITH1->stereo = bstereo_any;
2966
      WITH1->mdl_stereo = 0;    /* v0.3n */
2967
      if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2968
        n_heavybonds++;
2969
    }
2970
  memset (ring, 0, sizeof (ringlist));
2971
  for (n = 0; n < max_rings; n++)
2972
    {                           /* new in v0.3 */
2973
      ringprop[n].size = 0;
2974
      ringprop[n].arom = false;
2975
      ringprop[n].envelope = false;
2976
    }
2977
  li = ri + 1;
2978
}
2979
 
2980
 
2981
static void
2982
read_charges (chgstring_)
2983
     char *chgstring_;
2984
{
2985
  char chgstring[256];
2986
  int a_id, a_chg;
2987
  /* int n_chrg;*/
2988
 
2989
  /* typical example: a molecule with 2 cations + 1 anion */
2990
  /* M  CHG  3   8   1  10   1  11  -1 */
2991
  strcpy (chgstring, chgstring_);
2992
  if (strpos2 (chgstring, "M  CHG", 1) <= 0)
2993
    return;
2994
  strdelete (chgstring, 1, 6);
2995
  left_trim (chgstring);
2996
 /* n_chrg = left_int (chgstring);*/
2997
  /* this assignment must be kept also in non-debug mode! */
2998
/* p2c: checkmol.pas, line 2077:
2999
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3000
  /*$IFDEF debug */
3001
  /*if (n_chrg == 0)
3002
     debugoutput ("strange... M  CHG present, but no charges found"); */
3003
  /*$ENDIF */
3004
  while (*chgstring != '\0')
3005
    {
3006
      a_id = left_int (chgstring);
3007
      a_chg = left_int (chgstring);
3008
      if (a_id != 0 && a_chg != 0)
3009
        atom[a_id - 1].formal_charge = a_chg;
3010
      //printf ("CHG %i %i\n", a_id, a_chg);
3011
    }
3012
}
3013
 
3014
static void
3015
read_isotopes (char *isotopestring_)
3016
{
3017
  char isotopestring[256];
3018
  int a_id, a_nucleon_number;
3019
  /* int n_isotopes;*/
3020
 
3021
  /* typical example: a molecule with 2 cations + 1 anion */
3022
  /* M  CHG  3   8   1  10   1  11  -1 */
3023
  strcpy (isotopestring, isotopestring_);
3024
  if (strpos2 (isotopestring, "M  ISO", 1) <= 0)
3025
    return;
3026
  strdelete (isotopestring, 1, 6);
3027
  left_trim (isotopestring);
3028
  /*n_isotopes = left_int (isotopestring);*/
3029
  /* this assignment must be kept also in non-debug mode! */
3030
/* p2c: checkmol.pas, line 2077:
3031
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3032
  /*$IFDEF debug */
3033
  /*if (n_chrg == 0)
3034
     debugoutput ("strange... M  CHG present, but no charges found"); */
3035
  /*$ENDIF */
3036
  while (*isotopestring != '\0')
3037
    {
3038
      a_id = left_int (isotopestring);
3039
      a_nucleon_number = left_int (isotopestring);
3040
      if (a_id != 0 && a_nucleon_number != 0)
3041
        {
3042
          atom[a_id - 1].nucleon_number = a_nucleon_number;
3043
          if (!strcmp (atom[a_id - 1].element, "H "))
3044
            {
3045
              atom[a_id - 1].heavy = true;
3046
              n_heavyatoms++;
3047
              strcpy (atom[a_id - 1].atype, "DU ");
3048
            }
3049
        }
3050
      //printf ("ISO %i %i\n", a_id, a_nucleon_number);
3051
    }
3052
}
3053
 
3054
static void
3055
read_radicals (radstring_)
3056
     char *radstring_;
3057
{
3058
  char radstring[256];
3059
  int a_id, a_rad, n_rads;
3060
 
3061
  /* typical example: a molecule with 2 cations + 1 anion */
3062
  /* M  CHG  3   8   1  10   1  11  -1 */
3063
  strcpy (radstring, radstring_);
3064
  if (strpos2 (radstring, "M  RAD", 1) <= 0)
3065
    return;
3066
  strdelete (radstring, 1, 6);
3067
  left_trim (radstring);
3068
  n_rads = left_int (radstring);
3069
  /* this assignment must be kept also in non-debug mode! */
3070
/* p2c: checkmol.pas, line 2077:
3071
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3072
  /*$IFDEF debug */
3073
  /*if (n_chrg == 0)
3074
     debugoutput ("strange... M  CHG present, but no charges found"); */
3075
  /*$ENDIF */
3076
  while (*radstring != '\0')
3077
    {
3078
      a_id = left_int (radstring);
3079
      a_rad = left_int (radstring);
3080
      if (a_id != 0 && a_rad != 0)
3081
        atom[a_id - 1].radical_type = a_rad;
3082
      //printf ("RAD %i %i\n", a_id, a_rad);
3083
    }
3084
}
3085
 
3086
 
3087
static void
3088
read_MDLmolfile (char *mfilename)
3089
{
3090
  /* reads MDL mol files */
3091
  int n, v, tmp_n_atoms, tmp_n_bonds, code;     /* v0.3l */
3092
  char rline[256], tmpstr[256];
3093
  char xstr[256], ystr[256], zstr[256], chgstr[256];
3094
  float xval, yval, zval, chgval;
3095
  char a1str[256], a2str[256], elemstr[256];
3096
  int a1val, a2val, ri, rc, bt, bs;
3097
  int sepcount = 0;
3098
  int i;                        /* v0.3j */
3099
  boolean clearcharges = true;  /* v0.3j */
3100
  char STR1[256];
3101
/*  int FORLIM;*/
3102
  atom_rec *WITH;
3103
  bond_rec *WITH1;
3104
 
3105
  /* v0.3j */
3106
  if (n_atoms > 0)
3107
    zap_molecule ();
3108
  /*cm_mdlmolfile := false; */
3109
  *rline = '\0';
3110
  ri = li;
3111
  strcpy (molname, molbuf[ri - 1]);     /* line 1 */
3112
  if (ri < molbufindex)         /* line 2 */
3113
    ri++;
3114
  strcpy (rline, molbuf[ri - 1]);
3115
  if (strpos2 (rline, "CheckMol", 1) == 3)
3116
    {
3117
      /*cm_mdlmolfile := true; */
3118
      found_arominfo = true;
3119
      tmfcode = 1;              /* v0.3m (begin) */
3120
      code = 0;
3121
      if ((strlen (rline) >= 39) && (strpos2 (rline, "TMF", 1) == 35))
3122
        {                       /* v0.3m; encoding of tweaklevel */
3123
          strsub (tmpstr, rline, 38, 2);
3124
          code = (sscanf (tmpstr, "%d", &tmfcode) == 0);
3125
        }
3126
      if (code != 0 || tmfcode != tweaklevel)
3127
        tmfmismatch = true;
3128
      else
3129
        tmfmismatch = false;
3130
      if ((strpos2 (rline, ":r0", 1) >= 40 && ringsearch_mode != rs_sar) |
3131
          (strpos2 (rline, ":r1", 1) >= 40 && ringsearch_mode != rs_ssr))
3132
        tmfmismatch = true;
3133
      if ((strpos2 (rline, ":m0", 1) >= 40 && opt_metalrings == true) |
3134
          (strpos2 (rline, ":m1", 1) >= 40 && opt_metalrings == false))
3135
        tmfmismatch = true;
3136
/* p2c: checkmol.pas, line 2128:
3137
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3138
      /*$IFDEF debug */
3139
      //if (tmfmismatch)
3140
      //printf ("\"tweaked\" molfile: version mismatch!\n");
3141
      // else
3142
      //printf ("\"tweaked\" molfile: version OK");
3143
    }
3144
  /*$ENDIF */
3145
  /* v0.3m (end) */
3146
  if (ri < molbufindex)         /* line 3 */
3147
    ri++;
3148
  strcpy (rline, molbuf[ri - 1]);
3149
  strcpy (molcomment, rline);
3150
  if (ri < molbufindex)         /* line 4 */
3151
    ri++;
3152
  strcpy (rline, molbuf[ri - 1]);
3153
  sprintf (tmpstr, "%.3s", rline);
3154
  sscanf (tmpstr, "%d", &n_atoms);
3155
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3156
  strsub (tmpstr, rline, 4, 3);
3157
  sscanf (tmpstr, "%d", &n_bonds);
3158
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3159
  strsub (tmpstr, rline, 10, 3);
3160
  /* if it is a CheckMol-tweaked molfile, this is the number of rings */
3161
  n_cmrings = 0;
3162
  code = (sscanf (tmpstr, "%d", &n_cmrings) == 0);
3163
  if (code != 0)
3164
    n_cmrings = 0;
3165
  /* do some range checking for n_atoms, n_bonds; new in v0.3l */
3166
  tmp_n_atoms = n_atoms;
3167
  if (n_atoms > max_atoms)
3168
    n_atoms = max_atoms;
3169
  if (n_atoms < 0)
3170
    n_atoms = 0;
3171
  tmp_n_bonds = n_bonds;
3172
  if (n_bonds > max_bonds)
3173
    n_bonds = max_bonds;
3174
  if (n_bonds < 0)
3175
    n_bonds = 0;
3176
  if (n_atoms == 0
3177
#ifndef MAKE_SHARED_LIBRARY
3178
      && opt_verbose
3179
#endif
3180
    )
3181
    {                           /* v0.3l */
3182
      printf ("WARNING: Possible NoStruct read!\n");
3183
      printf ("NoStructs are proprietary, obsolete and dangerous.\n");
3184
    }
3185
  /* try */
3186
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
3187
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
3188
  /* this would be only one safe_calloc() in C;  v0.3l */
3189
  ring = safe_calloc (1, sizeof (ringlist));
3190
  ringprop = safe_calloc (1, sizeof (ringprop_type));
3191
  /* except
3192
     on e:Eoutofmemory do
3193
     begin
3194
     writeln('Not enough memory');
3195
     (* close(molfile);
3196
     halt(4);
3197
     exit;
3198
     end;
3199
     end; */
3200
  /* check for the chirality flag */
3201
  if (strlen (rline) > 14 && rline[14] == '1')  /* new in v0.3f */
3202
    chir_flag = true;
3203
  n_heavyatoms = 0;
3204
  n_heavybonds = 0;
3205
  n_Ctot = 0;                   /* v0.3g */
3206
  n_Otot = 0;                   /* v0.3g */
3207
  n_Ntot = 0;                   /* v0.3g */
3208
  if (n_atoms > 0)
3209
    {                           /* v0.3l */
3210
      for (n = 1; n <= tmp_n_atoms; n++)
3211
        {
3212
          if (n <= max_atoms)
3213
            v = n;
3214
          else
3215
            v = max_atoms;
3216
          /* just for safety; v0.3l */
3217
          /*
3218
             with atom^[v] do
3219
             begin
3220
             x := 0; y := 0; z := 0;  (* v0.3g
3221
             formal_charge  := 0;
3222
             real_charge    := 0;
3223
             Hexp           := 0;
3224
             Htot           := 0;
3225
             neighbor_count := 0;
3226
             ring_count     := 0;
3227
             arom           := false;
3228
             stereo_care    := false;
3229
             metal          := false;
3230
             heavy          := false;
3231
             tag            := false;
3232
             end;
3233
           */
3234
          /* replaced by fillchar() after getmem() (see above); v0.3l */
3235
          ri++;
3236
          strcpy (rline, molbuf[ri - 1]);
3237
          strsub (atomtype, rline, 32, 3);
3238
          get_MDLelement (elemstr, atomtype);
3239
          if (!strcmp (elemstr, "C "))
3240
            n_Ctot++;
3241
          if (!strcmp (elemstr, "O "))
3242
            n_Otot++;
3243
          if (!strcmp (elemstr, "N "))
3244
            n_Ntot++;
3245
 
3246
          convert_MDLtype (newatomtype, atomtype);
3247
          strsub (xstr, rline, 1, 10);  /* fixed in v0.3k (was: 2,9 etc.) */
3248
          strsub (ystr, rline, 11, 10);
3249
          strsub (zstr, rline, 21, 10);
3250
          /*chgstr := '0'; */
3251
          strsub (chgstr, rline, 37, 3);        /* new in v0.3j */
3252
          sscanf (chgstr, "%f", &chgval);
3253
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3254
          if (chgval != 0)
3255
            {
3256
              if (chgval >= 1 && chgval <= 7)
3257
                chgval = 4.0 - chgval;
3258
              else
3259
                {
3260
                  chgval = 0.0;
3261
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3262
                }
3263
            }                   /* end (v0.3j) */
3264
          sscanf (xstr, "%f", &xval);
3265
          sscanf (ystr, "%f", &yval);
3266
          sscanf (zstr, "%f", &zval);
3267
          /* v0.3k: removed superfluous val(chgstr,chgval,code) */
3268
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3269
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3270
          WITH = &atom[v - 1];
3271
          strcpy (WITH->element, elemstr);
3272
          if (!strcmp (elemstr, "A ") || !strcmp (elemstr, "Q ") ||
3273
              !strcmp (elemstr, "X "))
3274
            /* 'X ' added in v0.3n */
3275
            found_querymol = true;
3276
 
3277
          strcpy (WITH->atype, newatomtype);
3278
 
3279
 
3280
          if (!strcmp (elemstr, "D "))
3281
            {
3282
              strcpy (WITH->element, "H ");
3283
              WITH->nucleon_number = 2;
3284
            }                   /* 0.3x */
3285
          if (!strcmp (elemstr, "T "))
3286
            {
3287
              strcpy (WITH->element, "H ");
3288
              WITH->nucleon_number = 3;
3289
            }                   /* 0.3x */
3290
 
3291
 
3292
 
3293
          WITH->x = xval;
3294
          WITH->y = yval;
3295
          WITH->z = zval;
3296
          WITH->formal_charge = (long) floor (chgval + 0.5);
3297
          WITH->real_charge = 0.0;      /* v0.3j */
3298
          /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3299
          if (strlen (rline) > 37 && rline[37] == '0')
3300
            {
3301
              WITH->arom = true;
3302
              found_arominfo = true;
3303
            }
3304
          /* new in v0.3d: read stereo care flag */
3305
          if (strlen (rline) > 47 && rline[47] == '1')
3306
            WITH->stereo_care = true;
3307
          if (is_heavyatom (n))
3308
            {
3309
              n_heavyatoms++;
3310
              WITH->heavy = true;
3311
              if (is_metal (n))
3312
                WITH->metal = true;
3313
            }
3314
          WITH->nvalences = get_nvalences (WITH->element);
3315
          /* v0.3m                 */
3316
        }
3317
    }                           /* if (n_atoms > 0)... */
3318
  if (n_bonds > 0)
3319
    {                           /* v0.3l */
3320
      for (n = 1; n <= tmp_n_bonds; n++)
3321
        {
3322
          if (n <= max_bonds)
3323
            v = n;
3324
          else
3325
            v = max_bonds;
3326
          /* just for safety; v0.3l */
3327
          ri++;
3328
          strcpy (rline, molbuf[ri - 1]);
3329
          sprintf (a1str, "%.3s", rline);
3330
          strsub (a2str, rline, 4, 3);
3331
          code = (sscanf (a1str, "%d", &a1val) == 0);
3332
          if (code != 0)        /* v0.3l */
3333
            a1val = 1;
3334
          code = (sscanf (a2str, "%d", &a2val) == 0);
3335
          if (code != 0)        /* v0.3l */
3336
            a2val = 1;
3337
          WITH1 = &bond[v - 1];
3338
          WITH1->a1 = a1val;
3339
          WITH1->a2 = a2val;
3340
          if (rline[8] == '1')  /* single */
3341
            WITH1->btype = 'S';
3342
          if (rline[8] == '2')  /* double */
3343
            WITH1->btype = 'D';
3344
          if (rline[8] == '3')  /* triple */
3345
            WITH1->btype = 'T';
3346
          if (rline[8] == '4')  /* aromatic */
3347
            WITH1->btype = 'A';
3348
          if (rline[8] == '5')  /* single or double */
3349
            WITH1->btype = 'l';
3350
          if (rline[8] == '6')  /* single or aromatic */
3351
            WITH1->btype = 's';
3352
          if (rline[8] == '7')  /* double or aromatic */
3353
            WITH1->btype = 'd';
3354
          if (rline[8] == '8')  /* any */
3355
            WITH1->btype = 'a';
3356
          sprintf (STR1, "%c", WITH1->btype);
3357
          if (strpos2 ("lsda", STR1, 1) > 0)
3358
            found_querymol = true;
3359
          WITH1->arom = false;
3360
          WITH1->q_arom = false;        /* 0.3p */
3361
          /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3362
          if (WITH1->btype == 'A' || rline[7] == '0')
3363
            {
3364
              WITH1->arom = true;
3365
              if (rline[7] == '0')
3366
                found_arominfo = true;
3367
            }
3368
          strsub (tmpstr, rline, 13, 3);
3369
          /* new in v0.3d: read ring_count from tweaked molfile */
3370
          code = (sscanf (tmpstr, "%d", &rc) == 0);
3371
          if (code != 0 || rc < 0 || progmode == pmCheckMol || tmfmismatch)
3372
            WITH1->ring_count = 0;
3373
          else
3374
            WITH1->ring_count = rc;
3375
          /* v0.3n: added tmfmismatch check */
3376
          strsub (tmpstr, rline, 16, 3);        /* new in v0.3d: read bond topology; */
3377
          code = (sscanf (tmpstr, "%d", &bt) == 0);
3378
          /* extended features are encoded by leading zero */
3379
          if (code != 0 || (unsigned long) bt > 2)
3380
            WITH1->topo = btopo_any;
3381
          else
3382
            {
3383
              if (tmpstr[1] == '0')
3384
                WITH1->topo = bt + 3;
3385
              else
3386
                WITH1->topo = bt;
3387
            }
3388
          /* v0.3n changed >5 into >2 */
3389
          /* new in v0.3d: add stereo property from MDL "stereo care" flag in atom block */
3390
          WITH1->stereo = bstereo_any;
3391
          if (WITH1->btype == 'D')
3392
            {
3393
              if (atom[WITH1->a1 - 1].stereo_care
3394
                  && atom[WITH1->a2 - 1].stereo_care)
3395
                {               /* this is the MDL-conformant encoding, */
3396
                  WITH1->stereo = bstereo_xyz;  /* for an alternative see below */
3397
                  ez_flag = true;       /* v0.3f */
3398
                }
3399
              else
3400
                {               /* this extended feature is encoded by a leading zero */
3401
                  strsub (tmpstr, rline, 10, 3);
3402
                  /* new in v0.3d: read bond stereo specification; */
3403
                  code = (sscanf (tmpstr, "%d", &bs) == 0);
3404
                  WITH1->mdl_stereo = bs;       /* v0.3n */
3405
                  if (code != 0 || bs <= 0 || bs > 2)
3406
                    WITH1->stereo = bstereo_any;
3407
                  else
3408
                    WITH1->stereo = bstereo_xyz;
3409
                  if (tmpstr[1] == '0')
3410
                    WITH1->stereo = bstereo_xyz;
3411
                }
3412
            }
3413
          /*if stereo <> bstereo_any then ez_search := true; */
3414
          if (WITH1->stereo != bstereo_any)     /* changed in v0.3f */
3415
            ez_flag = true;
3416
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '1')
3417
            WITH1->stereo = bstereo_up;
3418
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '6')
3419
            WITH1->stereo = bstereo_down;
3420
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '4')
3421
            WITH1->stereo = bstereo_either;     /* 0.3x */
3422
          if (WITH1->btype == 'D' && strlen (rline) > 11 && rline[11] == '3')
3423
            WITH1->stereo = bstereo_double_either;      /* 0.3x */
3424
          strsub (tmpstr, rline, 10, 3);
3425
          /* new in v0.3n: save original bond stereo specification; */
3426
          sscanf (tmpstr, "%d", &bs);
3427
          /* v0.3n */
3428
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3429
          WITH1->mdl_stereo = bs;       /* v0.3n */
3430
          if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
3431
            n_heavybonds++;
3432
        }
3433
    }                           /* if (n_bonds > 0)... */
3434
  while (ri < molbufindex && sepcount < 1)
3435
    {
3436
      ri++;
3437
      strcpy (rline, molbuf[ri - 1]);
3438
      if (strpos2 (rline, "M  CHG", 1) > 0)
3439
        {                       /* new in v0.3j */
3440
          if (clearcharges)
3441
            {                   /* "M  CHG" supersedes all "old-style" charge values */
3442
 
3443
              for (i = 0; i < n_atoms; i++)
3444
                atom[i].formal_charge = 0;
3445
            }
3446
          read_charges (rline);
3447
          clearcharges = false;
3448
          /* subsequent "M  CHG" lines must not clear previous values */
3449
        }
3450
 
3451
      if (strpos2 (rline, "M  ISO", 1) > 0)
3452
        read_isotopes (rline);  /* 0.3x */
3453
 
3454
      if (strpos2 (rline, "M  RAD", 1) > 0)
3455
        read_radicals (rline);  /* 0.3x */
3456
 
3457
      if (strpos2 (rline, "$$$$", 1) > 0)
3458
        {
3459
          sepcount++;
3460
          if (molbufindex > ri + 2)     /* we assume this is an SDF file */
3461
            mol_in_queue = true;
3462
        }
3463
    }
3464
  memset (ring, 0, sizeof (ringlist));
3465
  for (n = 0; n < max_rings; n++)
3466
    {                           /* new in v0.3 */
3467
      ringprop[n].size = 0;
3468
      ringprop[n].arom = false;
3469
      ringprop[n].envelope = false;
3470
    }
3471
  li = ri + 1;
3472
}
3473
 
3474
 
3475
 
3476
static void
3477
write_MDLmolfile ()
3478
{
3479
  int i;
3480
  char tmpstr[256];
3481
  char wline[256];
3482
  int a_chg;
3483
  int a_iso;
3484
  int a_rad;
3485
  char tmflabel[256];           /* v0.3m */
3486
  char STR1[256];
3487
  /*char STR7[256];*/
3488
  int FORLIM;
3489
 
3490
  sprintf (tmflabel, "%d", (int) tweaklevel);   /* v0.3m */
3491
  while (strlen (tmflabel) < 2) /* v0.3m */
3492
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
3493
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
3494
  if (strlen (molname) > 80)
3495
    sprintf (molname, "%.80s", strcpy (STR1, molname));
3496
  puts (molname);
3497
  printf ("  CheckMol                        %s", tmflabel);    /* v0.3m */
3498
  if (ringsearch_mode == rs_sar)        /* v0.3m */
3499
    printf (":r0");
3500
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
3501
    printf (":r1");
3502
  if (opt_metalrings)
3503
    printf (":m1");
3504
  else
3505
    printf (":m0");
3506
  /* v0.3m */
3507
  printf ("\n%s\n", molcomment);
3508
  *wline = '\0';
3509
  *tmpstr = '\0';
3510
  sprintf (tmpstr, "%d", n_atoms);
3511
  lblank (3L, tmpstr);
3512
  strcat (wline, tmpstr);
3513
  *tmpstr = '\0';               /* first 3 digits: number of atoms */
3514
  sprintf (tmpstr, "%d", n_bonds);
3515
  lblank (3L, tmpstr);
3516
  strcat (wline, tmpstr);
3517
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
3518
  strcpy (tmpstr, "  0");
3519
  strcat (wline, tmpstr);
3520
  *tmpstr = '\0';               /* next 3 digits: number of atom lists (not used by us) */
3521
/* p2c: checkmol.pas, line 2388:
3522
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3523
#ifdef REDUCED_SAR
3524
  sprintf (tmpstr, "%d", n_countablerings);
3525
  /* v0.3n; changed n_rings into n_countablerings */
3526
#else
3527
  sprintf (tmpstr, "%d", n_rings);
3528
#endif
3529
  lblank (3L, tmpstr);
3530
  strcat (wline, tmpstr);
3531
  *tmpstr = '\0';
3532
  /* officially "obsolete", we use it for the number of rings */
3533
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
3534
  if (chir_flag)
3535
    strcat (wline, "1");
3536
  else
3537
    strcat (wline, "0");
3538
  /* v0.3n */
3539
  strcat (wline, "               999 V2000");
3540
  /* v0.3n (adjust string length) */
3541
  puts (wline);
3542
  FORLIM = n_atoms;
3543
  for (i = 0; i < FORLIM; i++)
3544
    {
3545
      *wline = '\0';
3546
      sprintf (tmpstr, "%1.4f", atom[i].x);
3547
      lblank (10L, tmpstr);
3548
      strcat (wline, tmpstr);
3549
      sprintf (tmpstr, "%1.4f", atom[i].y);
3550
      lblank (10L, tmpstr);
3551
      strcat (wline, tmpstr);
3552
      sprintf (tmpstr, "%1.4f", atom[i].z);
3553
      lblank (10L, tmpstr);
3554
      strcat (wline, tmpstr);
3555
      strcpy (tmpstr, atom[i].element);
3556
      /* tmpstr := lowercase(tmpstr); REPLACE!!! */
3557
      //tmpstr[0] = toupper (tmpstr[0]);
3558
      all_lowercase (tmpstr);
3559
      tmpstr[0] = toupper (tmpstr[0]);
3560
      /*wline := wline + ' '+atom^[i].element+' '; */
3561
      sprintf (wline + strlen (wline), " %s ", tmpstr);
3562
      strcat (wline, " 0");     /* mass difference (isotopes) */
3563
      /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
3564
      if (atom[i].arom)
3565
        strcpy (tmpstr, " 00");
3566
      else
3567
        strcpy (tmpstr, "  0");
3568
      strcat (wline, tmpstr);
3569
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0");
3570
      puts (wline);
3571
    }
3572
  FORLIM = n_bonds;
3573
  for (i = 0; i < FORLIM; i++)
3574
    {
3575
      *wline = '\0';
3576
      sprintf (tmpstr, "%d", bond[i].a1);
3577
      lblank (3L, tmpstr);
3578
      strcat (wline, tmpstr);
3579
      sprintf (tmpstr, "%d", bond[i].a2);
3580
      lblank (3L, tmpstr);
3581
      strcat (wline, tmpstr);
3582
      if (bond[i].btype == 'S')
3583
        strcpy (tmpstr, "  1");
3584
      if (bond[i].btype == 'D')
3585
        strcpy (tmpstr, "  2");
3586
      if (bond[i].btype == 'T')
3587
        strcpy (tmpstr, "  3");
3588
      if (bond[i].btype == 'A')
3589
        strcpy (tmpstr, "  4");
3590
      if (bond[i].btype == 'l')
3591
        strcpy (tmpstr, "  5");
3592
      if (bond[i].btype == 's')
3593
        strcpy (tmpstr, "  6");
3594
      if (bond[i].btype == 'd')
3595
        strcpy (tmpstr, "  7");
3596
      if (bond[i].btype == 'a')
3597
        strcpy (tmpstr, "  8");
3598
      /* now encode our own aromaticity information */
3599
      if (bond[i].arom)
3600
        tmpstr[1] = '0';
3601
      strcat (wline, tmpstr);   /* next, encode bond stereo property (v0.3f) */
3602
      /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
3603
      /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
3604
      /*    wline := wline + '  0'; */
3605
      /* restore original value from MDL molfile (v0.3n) */
3606
      /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
3607
      *tmpstr = '\0';
3608
      sprintf (tmpstr, "%i", bond[i].mdl_stereo);
3609
      strcat (wline, "  ");
3610
      strcat (wline, tmpstr);
3611
      *tmpstr = '\0';
3612
      /* now encode the ring_count of this bond (using a field which officially is "not used") */
3613
      /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
3614
      sprintf (tmpstr, "%i", bond[i].ring_count);
3615
      while (strlen (tmpstr) < 3)
3616
        sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
3617
      sprintf (wline + strlen (wline), "%s  0  0", tmpstr);
3618
      puts (wline);
3619
    }
3620
  FORLIM = n_atoms;
3621
  for (i = 1; i <= FORLIM; i++)
3622
    {
3623
      a_chg = atom[i - 1].formal_charge;
3624
      if (a_chg != 0)
3625
        {
3626
          strcpy (wline, "M  CHG  1 ");
3627
          sprintf (tmpstr, "%d", i);
3628
          lblank (3L, tmpstr);
3629
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3630
          sprintf (tmpstr, "%d", a_chg);
3631
          lblank (3L, tmpstr);
3632
          strcat (wline, tmpstr);
3633
          puts (wline);
3634
        }
3635
    }
3636
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
3637
    {
3638
      a_iso = atom[i - 1].nucleon_number;
3639
      if (a_iso != 0)
3640
        {
3641
          strcpy (wline, "M  ISO  1 ");
3642
          sprintf (tmpstr, "%d", i);
3643
          lblank (3L, tmpstr);
3644
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3645
          sprintf (tmpstr, "%d", a_iso);
3646
          lblank (3L, tmpstr);
3647
          strcat (wline, tmpstr);
3648
          puts (wline);
3649
        }
3650
    }
3651
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
3652
    {
3653
      a_rad = atom[i - 1].radical_type;
3654
      if (a_rad != 0)
3655
        {
3656
          strcpy (wline, "M  RAD  1 ");
3657
          sprintf (tmpstr, "%d", i);
3658
          lblank (3L, tmpstr);
3659
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3660
          sprintf (tmpstr, "%d", a_rad);
3661
          lblank (3L, tmpstr);
3662
          strcat (wline, tmpstr);
3663
          puts (wline);
3664
        }
3665
    }
3666
  printf ("M  END\n");
3667
}
3668
 
3669
 
3670
/*============= chemical processing functions && procedures ============ */
3671
 
3672
static boolean
3673
is_electroneg (a_el)
3674
     char *a_el;
3675
{
3676
  /* new in v0.3j */
3677
  boolean res = false;
3678
 
3679
  if (!strcmp (a_el, "N "))
3680
    res = true;
3681
  if (!strcmp (a_el, "P "))
3682
    res = true;
3683
  if (!strcmp (a_el, "O "))
3684
    res = true;
3685
  if (!strcmp (a_el, "S "))
3686
    res = true;
3687
  if (!strcmp (a_el, "SE"))
3688
    res = true;
3689
  if (!strcmp (a_el, "TE"))
3690
    res = true;
3691
  if (!strcmp (a_el, "F "))
3692
    res = true;
3693
  if (!strcmp (a_el, "CL"))
3694
    res = true;
3695
  if (!strcmp (a_el, "BR"))
3696
    res = true;
3697
  if (!strcmp (a_el, "I "))
3698
    res = true;
3699
  if (!strcmp (a_el, "AT"))
3700
    res = true;
3701
  return res;
3702
}
3703
 
3704
 
3705
static void
3706
count_neighbors ()
3707
{
3708
  /* counts heavy-atom neighbors and explicit hydrogens */
3709
  int i, FORLIM;
3710
 
3711
  if (n_atoms < 1 || n_bonds < 1)
3712
    return;
3713
  FORLIM = n_bonds;
3714
  for (i = 0; i < FORLIM; i++)
3715
    {
3716
      if (atom[bond[i].a1 - 1].heavy)
3717
        atom[bond[i].a2 - 1].neighbor_count++;
3718
      if (atom[bond[i].a2 - 1].heavy)
3719
        atom[bond[i].a1 - 1].neighbor_count++;
3720
      if (!strcmp (atom[bond[i].a1 - 1].element, "H "))
3721
        atom[bond[i].a2 - 1].Hexp++;
3722
      if (!strcmp (atom[bond[i].a2 - 1].element, "H "))
3723
        atom[bond[i].a1 - 1].Hexp++;
3724
      /* plausibility check (new in v02.i) */
3725
      if (atom[bond[i].a1 - 1].neighbor_count > max_neighbors ||
3726
          atom[bond[i].a2 - 1].neighbor_count > max_neighbors)
3727
        {
3728
          mol_OK = false;
3729
          /*writeln('invalid molecule!'); */
3730
        }
3731
    }
3732
}
3733
 
3734
 
3735
static void
3736
get_neighbors (Result, id)
3737
     int *Result;
3738
     int id;
3739
{
6786 kbelabas 3740
  int i;
6785 bpr 3741
  //neighbor_rec nb_tmp;
3742
  int nb_count = 0;
3743
  //int FORLIM = n_bonds;
3744
 
3745
  //memset (Result, 0, sizeof (neighbor_rec));
3746
 
6786 kbelabas 3747
  for (i = 0; i < n_bonds; i++)
6785 bpr 3748
    {
3749
      if (bond[i].a1 == id && atom[bond[i].a2 - 1].heavy
3750
          && nb_count < max_neighbors)
3751
        {
3752
          Result[nb_count++] = bond[i].a2;
3753
        }
3754
      if (bond[i].a2 == id && atom[bond[i].a1 - 1].heavy
3755
          && nb_count < max_neighbors)
3756
        {
3757
          Result[nb_count++] = bond[i].a1;
3758
        }
3759
    }
3760
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3761
}
3762
 
3763
 
3764
static void
3765
get_ndl_neighbors (int *Result, int id)
3766
{
3767
  int i;
3768
  //neighbor_rec nb_tmp;
3769
  int nb_count = 0;
3770
  /* v0.3i: use max_neighbors instead of a fixed value of 8 */
3771
  //int FORLIM = ndl_n_bonds;
3772
 
3773
  //memset (nb_tmp, 0, sizeof (neighbor_rec));
3774
 
3775
  for (i = 0; i < ndl_n_bonds; i++)
3776
    {
3777
      if (ndl_bond[i].a1 == id && nb_count < max_neighbors &&
3778
          ndl_atom[ndl_bond[i].a2 - 1].heavy)
3779
        {
3780
          nb_count++;
3781
          Result[nb_count - 1] = ndl_bond[i].a2;
3782
        }
3783
      if (ndl_bond[i].a2 == id && nb_count < max_neighbors &&
3784
          ndl_atom[ndl_bond[i].a1 - 1].heavy)
3785
        {
3786
          nb_count++;
3787
          Result[nb_count - 1] = ndl_bond[i].a1;
3788
        }
3789
    }
3790
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3791
}
3792
 
3793
 
3794
static int *
3795
get_nextneighbors (int *Result, int id, int prev_id)
3796
{
3797
  int i;
3798
  neighbor_rec nb_tmp;
3799
  int nb_count = 0;
3800
  int FORLIM;
3801
 
3802
  /* gets all neighbors except prev_id (usually the atom where we came from */
3803
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3804
  FORLIM = n_bonds;
3805
  for (i = 0; i < FORLIM; i++)
3806
    {
3807
      if (bond[i].a1 == id && bond[i].a2 != prev_id &&
3808
          nb_count < max_neighbors && atom[bond[i].a2 - 1].heavy)
3809
        {
3810
          nb_count++;
3811
          nb_tmp[nb_count - 1] = bond[i].a2;
3812
        }
3813
      if (bond[i].a2 == id && bond[i].a1 != prev_id &&
3814
          nb_count < max_neighbors && atom[bond[i].a1 - 1].heavy)
3815
        {
3816
          nb_count++;
3817
          nb_tmp[nb_count - 1] = bond[i].a1;
3818
        }
3819
    }
3820
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3821
}
3822
 
3823
 
3824
static int *
3825
get_ndl_nextneighbors (int *Result, int id, int prev_id)
3826
{
3827
  int i;
3828
  neighbor_rec nb_tmp;
3829
  int nb_count = 0;
3830
  int FORLIM;
3831
 
3832
  /* gets all neighbors except prev_id (usually the atom where we came from */
3833
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3834
  FORLIM = ndl_n_bonds;
3835
  for (i = 0; i < FORLIM; i++)
3836
    {
3837
      if (ndl_bond[i].a1 == id && ndl_bond[i].a2 != prev_id &&
3838
          nb_count < max_neighbors && ndl_atom[ndl_bond[i].a2 - 1].heavy)
3839
        {
3840
          nb_count++;
3841
          nb_tmp[nb_count - 1] = ndl_bond[i].a2;
3842
        }
3843
      if (ndl_bond[i].a2 == id && ndl_bond[i].a1 != prev_id &&
3844
          nb_count < max_neighbors && ndl_atom[ndl_bond[i].a1 - 1].heavy)
3845
        {
3846
          nb_count++;
3847
          nb_tmp[nb_count - 1] = ndl_bond[i].a1;
3848
        }
3849
    }
3850
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3851
}
3852
 
3853
#if 0
3854
static int path_pos (id, a_path) int id;
3855
     int *a_path;
3856
     {
3857
     /* new version in v0.3l */
3858
     int i;
3859
     int pp = 0;
3860
 
3861
     for (i = 1; i <= max_ringsize; i++)
3862
     {
3863
     if (a_path[i - 1] == id)
3864
     {
3865
     pp = i;
3866
     /* p2c: checkmol.pas, line 2620:
3867
     * Warning: Expected a '(', found a semicolon [227]  */
3868
     /* p2c: checkmol.pas, line 2620:
3869
     * Warning: Expected an expression, found a semicolon [227] */
3870
     fflush (0);
3871
     P_ioresult = 0;
3872
     }
3873
     }
3874
     return pp;
3875
     }
3876
#endif
3877
 
3878
static int
3879
matchpath_pos (int id, int *a_path)
3880
{
3881
  int i;
3882
  int pp = 0;
3883
 
3884
  for (i = max_matchpath_length; i >= 1; i--)
3885
    {
3886
      if (a_path[i - 1] == id)
3887
        pp = i;
3888
    }
3889
  return pp;
3890
}
3891
 
3892
 
3893
static int
3894
matchpath_length (int *a_path)
3895
{
3896
  if (a_path[max_matchpath_length - 1] != 0)
3897
    return max_matchpath_length;
3898
  else
3899
    return (matchpath_pos (0L, a_path) - 1);
3900
}
3901
 
3902
static int
3903
get_ndl_bond (int ba1, int ba2)
3904
{
3905
  int i;
3906
  int b_id = 0;
3907
  int FORLIM;
3908
 
3909
  if (ndl_n_bonds <= 0)
3910
    return b_id;
3911
  FORLIM = ndl_n_bonds;
3912
  for (i = 1; i <= FORLIM; i++)
3913
    {
3914
      if ((ndl_bond[i - 1].a1 == ba1 && ndl_bond[i - 1].a2 == ba2) ||
3915
          (ndl_bond[i - 1].a1 == ba2 && ndl_bond[i - 1].a2 == ba1))
3916
        b_id = i;
3917
    }
3918
  return b_id;
3919
}
3920
 
3921
static int
3922
ringcompare (int *rp1, int *rp2)
3923
{
3924
  int i, j;
3925
  int rc = 0;
3926
  int rs1, rs2;
3927
  int n_common = 0;
3928
  int max_cra;
3929
 
3930
  rs1 = path_length (rp1);
3931
  rs2 = path_length (rp2);
3932
  if (rs1 < rs2)
3933
    max_cra = rs1;
3934
  else
3935
    max_cra = rs2;
3936
  for (i = 0; i < rs1; i++)
3937
    {
3938
      for (j = 0; j < rs2; j++)
3939
        {
3940
          if (rp1[i] == rp2[j])
3941
            n_common++;
3942
        }
3943
    }
3944
  if (rs1 == rs2 && n_common == max_cra)
3945
    {
3946
      rc = 0;
3947
      return rc;
3948
    }
3949
  if (n_common == 0)
3950
    rc += 8;
3951
  if (n_common < max_cra)
3952
    {
3953
      rc += 4;
3954
      return rc;
3955
    }
3956
  if (rs1 < rs2)
3957
    rc++;
3958
  else
3959
    rc += 2;
3960
  return rc;
3961
}
3962
 
3963
 
3964
static boolean
3965
rc_identical (int rc_int)
3966
{
3967
  if (rc_int == 0)
3968
    return true;
3969
  else
3970
    return false;
3971
}
3972
 
3973
 
3974
static boolean
3975
rc_1in2 (int rc_int)
3976
{
3977
  if (rc_int & 1)
3978
    return true;
3979
  else
3980
    return false;
3981
}
3982
 
3983
 
3984
static boolean
3985
rc_2in1 (int rc_int)
3986
{
3987
  rc_int /= 2;
3988
  if (rc_int & 1)
3989
    return true;
3990
  else
3991
    return false;
3992
}
3993
 
3994
 
3995
#if 0
3996
static boolean
3997
rc_different (int rc_int)
3998
{
3999
  rc_int /= 4;
4000
  if (rc_int & 1)
4001
    return true;
4002
  else
4003
    return false;
4004
}
4005
#endif
4006
#if 0
4007
static boolean
4008
rc_independent (int rc_int)
4009
{
4010
  rc_int /= 8;
4011
  if (rc_int & 1)
4012
    return true;
4013
  else
4014
    return false;
4015
}
4016
#endif
4017
 
4018
static boolean
4019
is_newring (int *n_path)
4020
{
4021
  int i, j;
4022
  boolean nr = true;
4023
  boolean same_ring;
4024
  ringpath_type tmp_path;
4025
  int rc_result;
4026
  boolean found_ring;
4027
  int pl;                       /* new in v0.3 */
4028
  int FORLIM;
4029
 
4030
  pl = path_length (n_path);    /* new in v0.3 */
4031
  if (n_rings <= 0)
4032
    return true;
4033
  switch (ringsearch_mode)
4034
    {
4035
 
4036
    case rs_sar:
4037
      found_ring = false;
4038
      i = 0;
4039
      while (i < n_rings && !found_ring)
4040
        {
4041
          i++;
4042
          if (pl != ringprop[i - 1].size)       /* compare only rings of same size */
4043
            continue;
4044
          same_ring = true;
4045
          for (j = 0; j < max_ringsize; j++)
4046
            {
4047
              if (ring[i - 1][j] != n_path[j])
4048
                same_ring = false;
4049
            }
4050
          if (same_ring)
4051
            {
4052
              nr = false;
4053
              found_ring = true;
4054
            }
4055
        }
4056
      break;
4057
 
4058
    case rs_ssr:
4059
      FORLIM = n_rings;
4060
      for (i = 0; i < FORLIM; i++)
4061
        {
4062
          for (j = 0; j < max_ringsize; j++)
4063
            tmp_path[j] = ring[i][j];
4064
          rc_result = ringcompare (n_path, tmp_path);
4065
          if (rc_identical (rc_result))
4066
            nr = false;
4067
          if (rc_1in2 (rc_result))
4068
            {
4069
              /* exchange existing ring by smaller one */
4070
              for (j = 0; j < max_ringsize; j++)
4071
                ring[i][j] = n_path[j];
4072
              /* update ring property record (new in v0.3) */
4073
              ringprop[i].size = pl;
4074
              nr = false;
4075
/* p2c: checkmol.pas, line 2841:
4076
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4077
              /*$IFDEF debug */
4078
              /* debugoutput('replacing ring '+inttostr(i)+' by smaller one (ringsize: '+inttostr(path_length(n_path))+')'); */
4079
              /*$ENDIF */
4080
            }
4081
          if (rc_2in1 (rc_result))
4082
            {
4083
              /* new ring contains existing one, but is larger ==> discard */
4084
              nr = false;
4085
            }
4086
        }
4087
      break;
4088
    }
4089
  return nr;
4090
}
4091
 
4092
 
4093
static void
4094
add_ring (int *n_path)
4095
{
4096
  /* new in v0.3: store rings in an ordered way (with ascending ring size) */
4097
  int i;
4098
  int j = 0;
4099
  int k, s, pl;
4100
/* p2c: checkmol.pas, line 2862:
4101
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4102
  /*$IFDEF debug */
4103
  /*char dstr[256];*/
4104
  int FORLIM;
4105
 
4106
  /*$ENDIF */
4107
  pl = path_length (n_path);
4108
 
4109
  if (pl < 1)
4110
    return;
4111
 
4112
  if (n_rings >= max_rings)
4113
    {
4114
 
4115
/* p2c: checkmol.pas, line 2906:
4116
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4117
      /*$IFDEF debug
4118
         debugoutput ("max_rings exceeded!");
4119
         $ENDIF */
4120
      return;
4121
    }
4122
  n_rings++;
4123
 
4124
/* p2c: checkmol.pas, line 2871:
4125
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4126
  /*$IFDEF debug */
4127
  /* dstr := '';
4128
     for j := 1 to pl do dstr := dstr + inttostr((n_path[j])) + ' ';
4129
     debugoutput('adding ring '+inttostr(n_rings)+':  '+dstr); */
4130
  /*$ENDIF */
4131
  if (n_rings > 1)
4132
    {
4133
      FORLIM = n_rings;
4134
      for (i = 1; i < FORLIM; i++)
4135
        {
4136
          s = ringprop[i - 1].size;
4137
          if (pl >= s)
4138
            j = i;
4139
        }
4140
    }
4141
  j++;                          /* the next position is ours */
4142
  if (j < n_rings)
4143
    {                           /* push up the remaining rings by one position */
4144
      for (k = n_rings; k > j; k--)
4145
        {
4146
          ringprop[k - 1].size = ringprop[k - 2].size;
4147
          /*ringprop^[k].arom := ringprop^[(k-1)].arom; */
4148
          for (i = 0; i < max_ringsize; i++)
4149
            ring[k - 1][i] = ring[k - 2][i];
4150
        }
4151
    }
4152
  ringprop[j - 1].size = pl;
4153
  for (i = 0; i < max_ringsize; i++)
4154
    {
4155
      ring[j - 1][i] = n_path[i];
4156
      /*inc(atom^[(n_path[i])].ring_count); */
4157
    }
4158
}
4159
 
4160
 
4161
#if 0
4162
 static boolean is_ringpath (s_path) int *s_path;
4163
     {
4164
     boolean Result;
4165
     int i, j;
4166
     neighbor_rec nb;
4167
     boolean rp = false;
4168
     boolean new_atom;
4169
     int a_last, pl;
4170
     ringpath_type l_path;
4171
     int FORLIM;
4172
 
4173
     /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4174
     memset (nb, 0, sizeof (neighbor_rec));
4175
     memset (l_path, 0, sizeof (ringpath_type));
4176
     pl = path_length (s_path);
4177
     if (pl < 1)
4178
     {
4179
     /* p2c: checkmol.pas, line 2928:
4180
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4181
     /*$IFDEF debug
4182
     debugoutput ("Oops! Got zero-length s_path!");
4183
     $ENDIF */
4184
     return Result;
4185
     }
4186
     for (i = 0; i < pl; i++)
4187
     l_path[i] = s_path[i];
4188
     /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
4189
     if (opt_metalrings == false)
4190
     {
4191
     if (atom[l_path[pl - 1] - 1].metal)
4192
     {
4193
     /* p2c: checkmol.pas, line 2942:
4194
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4195
     /*$IFDEF debug
4196
     debugoutput ("skipping metal in ring search");
4197
     $ENDIF */
4198
     return false;
4199
     }
4200
     }
4201
     /* check if ring is already closed */
4202
     if (pl > 2 && l_path[pl - 1] == l_path[0])
4203
     {
4204
     l_path[pl - 1] = 0;        /* remove last entry (redundant!) */
4205
     order_ringpath (l_path);
4206
     if (is_newring (l_path))
4207
     {
4208
     if (n_rings >= max_rings)
4209
     {
4210
     /* p2c: checkmol.pas, line 2958:
4211
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4212
     /*$IFDEF debug
4213
     debugoutput ("maximum number of rings exceeded!");
4214
     $ENDIF */
4215
     return false;
4216
     }
4217
     add_ring (l_path);
4218
     }
4219
     /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4220
     return true;
4221
     }
4222
     /* any other case: ring is not (yet) closed */
4223
     a_last = l_path[pl - 1];
4224
     get_neighbors (nb, a_last);
4225
     if (atom[a_last - 1].neighbor_count <= 1)
4226
     return false;
4227
     if (n_rings >= max_rings)
4228
     /* added in v0.2: check if max_rings is reached **/
4229
     {                          /* if ring is not closed, continue searching */
4230
     return false;
4231
     }
4232
     FORLIM = atom[a_last - 1].neighbor_count;
4233
     for (i = 0; i < FORLIM; i++)
4234
     {
4235
     new_atom = true;
4236
     for (j = 1; j < pl; j++)
4237
     {
4238
     if (nb[i] == l_path[j])
4239
     {                    /* v0.3k */
4240
     new_atom = false;
4241
     /* p2c: checkmol.pas, line 2982:
4242
     * Warning: Expected a '(', found a semicolon [227] */
4243
     /* p2c: checkmol.pas, line 2982:
4244
     * Warning: Expected an expression, found a semicolon [227] */
4245
     fflush (0);
4246
     P_ioresult = 0;      /* v0.3k */
4247
     }
4248
     }
4249
     /* added in v0.1a: check if max_rings not yet reached */
4250
     /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
4251
     if (new_atom && pl < max_vringsize && n_rings < max_rings)
4252
     {
4253
     l_path[pl] = nb[i];
4254
     if (pl < max_ringsize - 1)   /* just to be sure */
4255
     l_path[pl + 1] = 0;
4256
     if (is_ringpath (l_path))
4257
     rp = true;
4258
     }
4259
     }
4260
     return rp;
4261
     }
4262
#endif
4263
 
4264
static boolean
4265
is_ringpath (int *s_path)
4266
{
4267
  int i, j;
4268
  neighbor_rec nb;
4269
  boolean rp = false;
4270
  boolean new_atom;
4271
  int a_last, pl;
4272
  ringpath_type l_path;
4273
  int FORLIM, pl_prev, pl_next, max_ringsize_dec;
4274
 
4275
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4276
  memset ((void *) nb, 0, sizeof (neighbor_rec));
4277
  memset ((void *) l_path, 0, sizeof (ringpath_type));
4278
  pl = path_length (s_path);
4279
  if (pl < 1)
4280
    {
4281
/* p2c: checkmol.pas, line 2524:
4282
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4283
 
4284
      return false;
4285
    }
4286
 
4287
  pl_prev = pl - 1;
4288
  //memcpy (l_path, s_path, sizeof (ringpath_type));
4289
  memcpy (l_path, s_path, pl * sizeof (int));
4290
 
4291
  /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
4292
  if (opt_metalrings == false)
4293
    {
4294
      if (atom[l_path[pl_prev] - 1].metal)
4295
        {
4296
/* p2c: checkmol.pas, line 2538:
4297
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4298
          return false;
4299
        }
4300
    }
4301
  /* check if ring is already closed */
4302
  if (pl > 2 && l_path[pl_prev] == l_path[0])
4303
    {
4304
      l_path[pl_prev] = 0;      /* remove last entry (redundant!) */
4305
      order_ringpath (l_path);
4306
      if (is_newring (l_path))
4307
        {
4308
          if (n_rings >= max_rings)
4309
            {
4310
/* p2c: checkmol.pas, line 2554:
4311
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4312
 
4313
              return false;
4314
            }
4315
          add_ring (l_path);
4316
        }
4317
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4318
      return true;
4319
    }
4320
  /* any other case: ring is not (yet) closed */
4321
  a_last = l_path[pl_prev];
4322
  get_neighbors (nb, a_last);
4323
  if (atom[a_last - 1].neighbor_count <= 1)
4324
    return false;
4325
  if (n_rings >= max_rings)
4326
    /* added in v0.2: check if max_rings is reached */
4327
    {                           /* if ring is not closed, continue searching */
4328
      return false;
4329
    }
4330
  FORLIM = atom[a_last - 1].neighbor_count;
4331
  pl_next = pl + 1;
4332
  max_ringsize_dec = max_ringsize - 1;
4333
  for (i = 0; i < FORLIM; i++)
4334
    {
4335
      new_atom = true;
4336
      for (j = 1; j < pl; j++)
4337
        {
4338
          if (nb[i] == l_path[j])
4339
            {
4340
              new_atom = false;
4341
              break;
4342
            }
4343
        }
4344
      /* added in v0.1a: check if max_rings not yet reached */
4345
      /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
4346
      if (new_atom && pl < max_vringsize && n_rings < max_rings)
4347
        {
4348
          l_path[pl] = nb[i];
4349
          if (pl < max_ringsize_dec)    /* just to be sure */
4350
            l_path[pl_next] = 0;
4351
 
4352
          if (max_ringpath_recursion_depth != 0
4353
              && ++recursion_depth > max_ringpath_recursion_depth)
4354
            {
4355
#ifndef MAKE_SHARED_LIBRARY
4356
              if (opt_verbose)
4357
#endif
4358
                printf
4359
                  ("Warning: max. number of ringpath recursions (%i) reached\n",
4360
                   max_ringpath_recursion_depth);
4361
              n_rings = max_rings;
4362
              return false;
4363
            }
4364
 
4365
          /*printf("%i\n",recursion_depth);
4366
          fflush(stdout);*/
4367
 
4368
          if (is_ringpath (l_path))
4369
            rp = true;
4370
          /*return true;*/
4371
        }
4372
    }
4373
  return rp;
4374
}
4375
 
4376
static boolean
4377
is_ringbond (int b_id)
4378
{
4379
  int i, ra1, ra2;
4380
  neighbor_rec nb;
4381
  ringpath_type search_path;
4382
  boolean rb = false;
4383
  int FORLIM;
4384
 
4385
  recursion_depth = 0;
4386
 
4387
  ra1 = bond[b_id - 1].a1;
4388
  ra2 = bond[b_id - 1].a2;
4389
  memset (nb, 0, sizeof (neighbor_rec));
4390
  memset (search_path, 0, sizeof (ringpath_type));
4391
  get_neighbors (nb, ra2);
4392
  if (atom[ra2 - 1].neighbor_count <= 1 || atom[ra1 - 1].neighbor_count <= 1)
4393
    return false;
4394
  search_path[0] = ra1;
4395
  search_path[1] = ra2;
4396
  FORLIM = atom[ra2 - 1].neighbor_count;
4397
  for (i = 0; i < FORLIM; i++)
4398
    {
4399
      if (nb[i] != ra1 && atom[nb[i] - 1].heavy)
4400
        {
4401
          search_path[2] = nb[i];
4402
          if (is_ringpath (search_path))
4403
            rb = true;
4404
          //return true;
4405
        }
4406
    }
4407
  return rb;
4408
}
4409
 
4410
 
4411
static void
4412
chk_ringbonds ()
4413
{
4414
  int i, a1rc, a2rc;
4415
 
4416
  if (n_bonds < 1)
4417
    return;
4418
 
4419
  for (i = 0; i < n_bonds; i++)
4420
    {
4421
      a1rc = atom[bond[i].a1 - 1].ring_count;
4422
      a2rc = atom[bond[i].a2 - 1].ring_count;
4423
      if (n_rings == 0 || (a1rc < n_rings && a2rc < n_rings))
4424
        {
4425
          is_ringbond (i + 1);
4426
          /*inc(bond^[i].ring_count); */
4427
        }
4428
    }
4429
}
4430
 
4431
 
4432
/* v0.3d: moved procedure update_ringcount a bit down */
4433
 
4434
 
4435
static int
4436
raw_hetbond_count (int a)
4437
{
4438
  /* new in v0.2j, ignores bond order */
4439
  int i;
4440
  neighbor_rec nb;
4441
  str2 nb_el;
4442
  int hbc = 0;
4443
  int FORLIM;
4444
 
4445
  if (a <= 0 || a > n_atoms)
4446
    return hbc;
4447
  memset (nb, 0, sizeof (neighbor_rec));
4448
  get_neighbors (nb, a);
4449
  if (atom[a - 1].neighbor_count <= 0)
4450
    return hbc;
4451
  FORLIM = atom[a - 1].neighbor_count;
4452
  for (i = 0; i < FORLIM; i++)
4453
    {
4454
      strcpy (nb_el, atom[nb[i] - 1].element);
4455
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /* &&  strcmp (nb_el, "D ") */
4456
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4457
        /* added 'D ' in v0.3n */
4458
        hbc++;
4459
    }
4460
  return hbc;
4461
}
4462
 
4463
 
4464
static int
4465
hetbond_count (int a)
4466
{
4467
  int i;
4468
  neighbor_rec nb;
4469
  str2 nb_el;
4470
  float hbc = 0.0;
4471
  int FORLIM;
4472
 
4473
  if (a <= 0 || a > n_atoms)
4474
    return ((int) floor (hbc + 0.5));
4475
  memset (nb, 0, sizeof (neighbor_rec));
4476
  get_neighbors (nb, a);
4477
  if (atom[a - 1].neighbor_count <= 0)
4478
    return ((int) floor (hbc + 0.5));
4479
  FORLIM = atom[a - 1].neighbor_count;
4480
  for (i = 0; i < FORLIM; i++)
4481
    {
4482
      strcpy (nb_el, atom[nb[i] - 1].element);
4483
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /*&& strcmp (nb_el, "D ") */
4484
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4485
        {                       /* added 'D ' in v0.3n */
4486
          if (bond[get_bond (a, nb[i]) - 1].btype == 'S')
4487
            hbc += 1.0;
4488
          if (bond[get_bond (a, nb[i]) - 1].btype == 'A')
4489
            hbc += 1.5;
4490
          if (bond[get_bond (a, nb[i]) - 1].btype == 'D')
4491
            hbc += 2.0;
4492
          if (bond[get_bond (a, nb[i]) - 1].btype == 'T')
4493
            hbc += 3.0;
4494
        }
4495
    }
4496
  return ((int) floor (hbc + 0.5));
4497
}
4498
 
4499
 
4500
static int
4501
hetatom_count (int a)
4502
{
4503
  int i;
4504
  neighbor_rec nb;
4505
  str2 nb_el;
4506
  int hac = 0;
4507
  int FORLIM;
4508
 
4509
  if (a <= 0 || a > n_atoms)
4510
    return hac;
4511
  memset (nb, 0, sizeof (neighbor_rec));
4512
  get_neighbors (nb, a);
4513
  if (atom[a - 1].neighbor_count <= 0)
4514
    return hac;
4515
  FORLIM = atom[a - 1].neighbor_count;
4516
  for (i = 0; i < FORLIM; i++)
4517
    {
4518
      strcpy (nb_el, atom[nb[i] - 1].element);
4519
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4520
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4521
          && strcmp (nb_el, "DU"))
4522
        /* added 'D ' in v0.3n */
4523
        hac++;
4524
    }
4525
  return hac;
4526
}
4527
 
4528
#if 0
4529
static int
4530
ndl_hetbond_count (int a)
4531
{
4532
  int i;
4533
  neighbor_rec nb;
4534
  str2 nb_el;
4535
  float hbc = 0.0;
4536
  int FORLIM;
4537
 
4538
  if (a <= 0 || a > n_atoms)
4539
    return ((int) floor (hbc + 0.5));
4540
  memset (nb, 0, sizeof (neighbor_rec));
4541
  get_ndl_neighbors (nb, a);
4542
  if (ndl_atom[a - 1].neighbor_count <= 0)
4543
    return ((int) floor (hbc + 0.5));
4544
  FORLIM = ndl_atom[a - 1].neighbor_count;
4545
  for (i = 0; i < FORLIM; i++)
4546
    {
4547
      strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4548
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4549
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4550
          && strcmp (nb_el, "DU"))
4551
        {                       /* added 'D ' in v0.3n */
4552
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'S')
4553
            hbc += 1.0;
4554
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'A')
4555
            hbc += 1.5;
4556
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'D')
4557
            hbc += 2.0;
4558
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'T')
4559
            hbc += 3.0;
4560
        }
4561
    }
4562
  return ((int) floor (hbc + 0.5));
4563
}
4564
#endif
4565
 
4566
static int
4567
ndl_hetatom_count (int a)
4568
{
4569
  int i;
4570
  neighbor_rec nb;
4571
  str2 nb_el;
4572
  int hac = 0;
4573
  int FORLIM;
4574
 
4575
  if (a <= 0 || a > ndl_n_atoms)
4576
    return hac;
4577
  memset (nb, 0, sizeof (neighbor_rec));
4578
  get_ndl_neighbors (nb, a);
4579
  if (ndl_atom[a - 1].neighbor_count <= 0)
4580
    return hac;
4581
  FORLIM = ndl_atom[a - 1].neighbor_count;
4582
  for (i = 0; i < FORLIM; i++)
4583
    {                           /* note: query atoms like 'A' should be present only in the needle */
4584
      strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4585
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /*&&  strcmp (nb_el, "D ") */
4586
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4587
        /* added 'D ' in v0.3n */
4588
        hac++;
4589
    }
4590
  return hac;
4591
}
4592
 
4593
 
4594
static boolean
4595
is_oxo_C (int id)
4596
{
4597
  int i;
4598
  boolean r = false;
4599
  neighbor_rec nb;
4600
  int FORLIM;
4601
 
4602
  memset (nb, 0, sizeof (neighbor_rec));
4603
  if (id < 1 || id > n_atoms)
6786 kbelabas 4604
    return false;
6785 bpr 4605
  get_neighbors (nb, id);
4606
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4607
    return false;
4608
  FORLIM = atom[id - 1].neighbor_count;
4609
  for (i = 0; i < FORLIM; i++)
4610
    {
4611
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4612
          !strcmp (atom[nb[i] - 1].element, "O "))
4613
        /* no N, amidines are different... */
4614
        r = true;
4615
      /* or
4616
         (atom^[(nb[i])].element = 'S ')  or
4617
         (atom^[(nb[i])].element = 'SE') */
4618
    }
4619
  return r;
4620
}
4621
 
4622
 
4623
static boolean
4624
is_thioxo_C (int id)
4625
{
4626
  int i;
4627
  boolean r = false;
4628
  neighbor_rec nb;
4629
  int FORLIM;
4630
 
4631
  memset (nb, 0, sizeof (neighbor_rec));
4632
  if (id < 1 || id > n_atoms)
6786 kbelabas 4633
    return false;
6785 bpr 4634
  get_neighbors (nb, id);
4635
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4636
    return false;
4637
  FORLIM = atom[id - 1].neighbor_count;
4638
  for (i = 0; i < FORLIM; i++)
4639
    {
4640
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4641
          (!strcmp (atom[nb[i] - 1].element, "S ") ||
4642
           !strcmp (atom[nb[i] - 1].element, "SE")))
4643
        /* no N, amidines are different... */
4644
        r = true;
4645
    }
4646
  return r;
4647
}
4648
 
4649
 
4650
static boolean
4651
is_imino_C (int id)
4652
{
4653
  int i;
4654
  boolean r = false;
4655
  neighbor_rec nb;
4656
  int FORLIM;
4657
 
4658
  memset (nb, 0, sizeof (neighbor_rec));
4659
  if (id < 1 || id > n_atoms)
6786 kbelabas 4660
    return false;
6785 bpr 4661
  get_neighbors (nb, id);
4662
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4663
    return false;
4664
  FORLIM = atom[id - 1].neighbor_count;
4665
  for (i = 0; i < FORLIM; i++)
4666
    {
4667
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4668
          !strcmp (atom[nb[i] - 1].element, "N "))
4669
        r = true;
4670
    }
4671
  return r;
4672
}
4673
 
4674
 
4675
static boolean
4676
is_true_imino_C (int id)
4677
{
4678
  int i;
4679
  boolean r = true;
4680
  neighbor_rec nb;
4681
  str2 nb_el;
4682
  int a_n = 0;
4683
  int b;                        /* v0.3j */
4684
  int FORLIM;
4685
 
4686
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4687
  memset (nb, 0, sizeof (neighbor_rec));
4688
  if (id < 1 || id > n_atoms)
6786 kbelabas 4689
    return false;
6785 bpr 4690
  get_neighbors (nb, id);
4691
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4692
    return false;
4693
  FORLIM = atom[id - 1].neighbor_count;
4694
  for (i = 0; i < FORLIM; i++)
4695
    {
4696
      b = get_bond (id, nb[i]); /* v0.3j */
4697
      if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4698
          !strcmp (atom[nb[i] - 1].element, "N "))
4699
        /* v0.3j */
4700
        a_n = nb[i];
4701
    }
4702
  if (a_n <= 0)
4703
    return false;
4704
  memset (nb, 0, sizeof (neighbor_rec));
4705
  get_neighbors (nb, a_n);
4706
  FORLIM = atom[a_n - 1].neighbor_count;
4707
  for (i = 0; i < FORLIM; i++)
4708
    {
4709
      strcpy (nb_el, atom[nb[i] - 1].element);
4710
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4711
          /*&&  strcmp (nb_el, "D ") */ )
4712
        /* v0.3n: D */
4713
        r = false;
4714
    }
4715
  return r;
4716
}
4717
 
4718
 
4719
static boolean
4720
is_true_exocyclic_imino_C (int id, int r_id)
4721
{
4722
  /* v0.3j */
4723
  boolean Result;
4724
  int i, j;
4725
  boolean r = false;
4726
  neighbor_rec nb;
4727
  ringpath_type testring;
4728
  int ring_size, b, FORLIM;
4729
 
4730
  memset (nb, 0, sizeof (neighbor_rec));
4731
  if (id < 1 || id > n_atoms)
4732
    return Result;
4733
  get_neighbors (nb, id);
4734
  memset (testring, 0, sizeof (ringpath_type));
4735
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4736
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4737
    testring[j] = ring[r_id - 1][j];
4738
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4739
    return false;
4740
  FORLIM = atom[id - 1].neighbor_count;
4741
  for (i = 0; i < FORLIM; i++)
4742
    {
4743
      b = get_bond (id, nb[i]);
4744
      if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4745
          !strcmp (atom[nb[i] - 1].element, "N "))
4746
        {
4747
          r = true;
4748
          for (j = 0; j < ring_size; j++)
4749
            {
4750
              if (nb[i] == ring[r_id - 1][j])
4751
                r = false;
4752
            }
4753
        }
4754
    }
4755
  return r;
4756
}
4757
 
4758
 
4759
static boolean
4760
is_exocyclic_imino_C (int id, int r_id)
4761
{
4762
  boolean Result;
4763
  int i, j;
4764
  boolean r = false;
4765
  neighbor_rec nb;
4766
  ringpath_type testring;
4767
  int ring_size, FORLIM;
4768
 
4769
  memset (nb, 0, sizeof (neighbor_rec));
4770
  if (id < 1 || id > n_atoms)
4771
    return Result;
4772
  get_neighbors (nb, id);
4773
  memset (testring, 0, sizeof (ringpath_type));
4774
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4775
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4776
    testring[j] = ring[r_id - 1][j];
4777
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4778
    return false;
4779
  FORLIM = atom[id - 1].neighbor_count;
4780
  for (i = 0; i < FORLIM; i++)
4781
    {
4782
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4783
          !strcmp (atom[nb[i] - 1].element, "N "))
4784
        {
4785
          r = true;
4786
          for (j = 0; j < ring_size; j++)
4787
            {
4788
              if (nb[i] == ring[r_id - 1][j])
4789
                r = false;
4790
            }
4791
        }
4792
    }
4793
  return r;
4794
}
4795
 
4796
 
4797
static int
4798
find_exocyclic_methylene_C (int id, int r_id)
4799
{
4800
  /* renamed and rewritten in v0.3j */
4801
  int i, j;
4802
  int r = 0;
4803
  neighbor_rec nb;
4804
  ringpath_type testring;
4805
  int ring_size, FORLIM;
4806
 
4807
  memset (nb, 0, sizeof (neighbor_rec));
4808
  if (id < 1 || id > n_atoms)
4809
    return 0;
4810
  get_neighbors (nb, id);
4811
  memset (testring, 0, sizeof (ringpath_type));
4812
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4813
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4814
    testring[j] = ring[r_id - 1][j];
4815
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4816
    return r;
4817
  FORLIM = atom[id - 1].neighbor_count;
4818
  for (i = 0; i < FORLIM; i++)
4819
    {
4820
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4821
          !strcmp (atom[nb[i] - 1].element, "C "))
4822
        {
4823
          r = nb[i];
4824
          for (j = 0; j < ring_size; j++)
4825
            {
4826
              if (nb[i] == ring[r_id - 1][j])
4827
                r = 0;
4828
            }
4829
        }
4830
    }
4831
  return r;
4832
}
4833
 
4834
 
4835
static boolean
4836
is_hydroxy (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, "O3 ") &&
4844
          atom[a_ref - 1].neighbor_count == 1)
4845
        r = true;
4846
    }
4847
  return r;
4848
}
4849
 
4850
 
4851
static boolean
4852
is_sulfanyl (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, "S3 ") &&
4860
          atom[a_ref - 1].neighbor_count == 1)
4861
        r = true;
4862
    }
4863
  return r;
4864
}
4865
 
4866
 
4867
static boolean
4868
is_amino (int a_view, int a_ref)
4869
{
4870
  boolean r = false;
4871
 
4872
  if (atom[a_view - 1].
4873
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4874
    {
4875
      if ((!strcmp (atom[a_ref - 1].atype, "N3 ") ||
4876
           !strcmp (atom[a_ref - 1].atype, "N3+")) &&
4877
          atom[a_ref - 1].neighbor_count == 1)
4878
        r = true;
4879
    }
4880
  return r;
4881
}
4882
 
4883
 
4884
static boolean
4885
is_alkyl (int a_view, int a_ref)
4886
{
4887
  int i;
4888
  boolean r = false;
4889
  neighbor_rec nb;
4890
  str2 nb_el;
4891
  int het_count = 0;
4892
  int FORLIM;
4893
 
4894
  memset (nb, 0, sizeof (neighbor_rec));
4895
  if (!
4896
      (atom[a_view - 1].
4897
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4898
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4899
      || atom[a_ref - 1].arom != false)
4900
    return false;
4901
  get_nextneighbors (nb, a_ref, a_view);
4902
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4903
  for (i = 0; i <= FORLIM; i++)
4904
    {
4905
      strcpy (nb_el, atom[nb[i] - 1].element);
4906
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4907
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4908
          && strcmp (nb_el, "LP"))
4909
        /* added 'D ' in v0.3n */
4910
        het_count++;
4911
    }
4912
  if (het_count <= 1)           /* we consider (e.g.) alkoxyalkyl groups as alkyl */
4913
    r = true;
4914
  return r;
4915
}
4916
 
4917
 
4918
static boolean
4919
is_true_alkyl (int a_view, int a_ref)
4920
{
4921
  int i;
4922
  boolean r = false;
4923
  neighbor_rec nb;
4924
  str2 nb_el;
4925
  int het_count = 0;
4926
  int FORLIM;
4927
 
4928
  memset (nb, 0, sizeof (neighbor_rec));
4929
  if (!
4930
      (atom[a_view - 1].
4931
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4932
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4933
      || atom[a_ref - 1].arom != false)
4934
    return false;
4935
  get_nextneighbors (nb, a_ref, a_view);
4936
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4937
  for (i = 0; i <= FORLIM; i++)
4938
    {
4939
      strcpy (nb_el, atom[nb[i] - 1].element);
4940
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4941
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
4942
        /* added 'D ' in v0.3n */
4943
        het_count++;
4944
    }
4945
  if (het_count == 0)           /* */
4946
    r = true;
4947
  return r;
4948
}
4949
 
4950
 
4951
static boolean
4952
is_alkenyl (int a_view, int a_ref)
4953
{
4954
  /* new in v0.3j */
4955
  int i;
4956
  boolean r = false;
4957
  neighbor_rec nb;
4958
  str2 nb_el;
4959
  str3 nb_at;
4960
  int c2_count = 0, het_count = 0;
4961
  int FORLIM;
4962
 
4963
  memset (nb, 0, sizeof (neighbor_rec));
4964
  if (!
4965
      (atom[a_view - 1].
4966
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4967
      || strcmp (atom[a_ref - 1].atype, "C2 ")
4968
      || atom[a_ref - 1].arom != false)
4969
    {
4970
      return false;
4971
    }                           /* v0.3k: changed c2_count = 1 into c2_count >= 1 */
4972
  get_nextneighbors (nb, a_ref, a_view);
4973
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4974
  for (i = 0; i <= FORLIM; i++)
4975
    {
4976
      strcpy (nb_el, atom[nb[i] - 1].element);
4977
      strcpy (nb_at, atom[nb[i] - 1].atype);
4978
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4979
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4980
          && strcmp (nb_el, "LP"))
4981
        /* added 'D ' in v0.3n */
4982
        het_count++;
4983
      if (!strcmp (nb_at, "C2 "))
4984
        c2_count++;
4985
    }
4986
  if (c2_count >= 1 && het_count <= 1)
4987
    /* we consider (e.g.) alkoxyalkenyl groups as alkenyl */
4988
    r = true;
4989
  return r;
4990
}
4991
 
4992
 
4993
static boolean
4994
is_alkynyl (int a_view, int a_ref)
4995
{
4996
  /* new in v0.3j */
4997
  int i;
4998
  boolean r = false;
4999
  neighbor_rec nb;
5000
  str3 nb_at;
5001
  int c1_count = 0;
5002
  int FORLIM;
5003
 
5004
  memset (nb, 0, sizeof (neighbor_rec));
5005
  if (!
5006
      (atom[a_view - 1].
5007
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
5008
      || strcmp (atom[a_ref - 1].atype, "C1 ")
5009
      || atom[a_ref - 1].arom != false)
5010
    return false;
5011
  get_nextneighbors (nb, a_ref, a_view);
5012
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
5013
  for (i = 0; i <= FORLIM; i++)
5014
    {
5015
      strcpy (nb_at, atom[nb[i] - 1].atype);
5016
      if (!strcmp (nb_at, "C1 "))
5017
        c1_count++;
5018
    }
5019
  if (c1_count == 1)
5020
    r = true;
5021
  return r;
5022
}
5023
 
5024
 
5025
static boolean
5026
is_aryl (int a_view, int a_ref)
5027
{
5028
  boolean r = false;
5029
 
5030
  if ((atom[a_view - 1].
5031
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
5032
      && !strcmp (atom[a_ref - 1].element, "C ")
5033
      && atom[a_ref - 1].arom == true)
5034
    r = true;
5035
  return r;
5036
}
5037
 
5038
 
5039
static boolean
5040
is_alkoxy (int a_view, int a_ref)
5041
{
5042
  boolean r = false;
5043
  neighbor_rec nb;
5044
 
5045
  memset (nb, 0, sizeof (neighbor_rec));
5046
  if (!
5047
      (atom[a_view - 1].
5048
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5049
    return false;
5050
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5051
      || atom[a_ref - 1].neighbor_count != 2)
5052
    return false;
5053
  get_nextneighbors (nb, a_ref, a_view);
5054
  if (is_alkyl (a_ref, nb[0]))
5055
    r = true;
5056
  return r;
5057
}
5058
 
5059
 
5060
static boolean
5061
is_siloxy (int a_view, int a_ref)
5062
{
5063
  boolean r = false;
5064
  neighbor_rec nb;
5065
 
5066
  memset (nb, 0, sizeof (neighbor_rec));
5067
  if (!
5068
      (atom[a_view - 1].
5069
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5070
    return false;
5071
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5072
      || atom[a_ref - 1].neighbor_count != 2)
5073
    return false;
5074
  get_nextneighbors (nb, a_ref, a_view);
5075
  if (!strcmp (atom[nb[0] - 1].element, "SI"))
5076
    r = true;
5077
  return r;
5078
}
5079
 
5080
 
5081
static boolean
5082
is_true_alkoxy (int a_view, int a_ref)
5083
{
5084
  boolean r = false;
5085
  neighbor_rec nb;
5086
 
5087
  memset (nb, 0, sizeof (neighbor_rec));
5088
  if (!
5089
      (atom[a_view - 1].
5090
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5091
    return false;
5092
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5093
      || atom[a_ref - 1].neighbor_count != 2)
5094
    return false;
5095
  get_nextneighbors (nb, a_ref, a_view);
5096
  if (is_true_alkyl (a_ref, nb[0]))
5097
    r = true;
5098
  return r;
5099
}
5100
 
5101
 
5102
static boolean
5103
is_aryloxy (int a_view, int a_ref)
5104
{
5105
  boolean r = false;
5106
  neighbor_rec nb;
5107
 
5108
  memset (nb, 0, sizeof (neighbor_rec));
5109
  if (!
5110
      (atom[a_view - 1].
5111
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5112
    return false;
5113
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5114
      || atom[a_ref - 1].neighbor_count != 2)
5115
    return false;
5116
  get_nextneighbors (nb, a_ref, a_view);
5117
  if (is_aryl (a_ref, nb[0]))
5118
    r = true;
5119
  return r;
5120
}
5121
 
5122
 
5123
static boolean
5124
is_alkenyloxy (int a_view, int a_ref)
5125
{
5126
  /* v0.3j */
5127
  boolean r = false;
5128
  neighbor_rec nb;
5129
 
5130
  memset (nb, 0, sizeof (neighbor_rec));
5131
  if (!
5132
      (atom[a_view - 1].
5133
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5134
    return false;
5135
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5136
      || atom[a_ref - 1].neighbor_count != 2)
5137
    return false;
5138
  get_nextneighbors (nb, a_ref, a_view);
5139
  if (is_alkenyl (a_ref, nb[0]))
5140
    r = true;
5141
  return r;
5142
}
5143
 
5144
 
5145
static boolean
5146
is_alkynyloxy (int a_view, int a_ref)
5147
{
5148
  /* v0.3j */
5149
  boolean r = false;
5150
  neighbor_rec nb;
5151
 
5152
  memset (nb, 0, sizeof (neighbor_rec));
5153
  if (!
5154
      (atom[a_view - 1].
5155
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5156
    return false;
5157
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5158
      || atom[a_ref - 1].neighbor_count != 2)
5159
    return false;
5160
  get_nextneighbors (nb, a_ref, a_view);
5161
  if (is_alkynyl (a_ref, nb[0]))
5162
    r = true;
5163
  return r;
5164
}
5165
 
5166
 
5167
static boolean
5168
is_alkylsulfanyl (int a_view, int a_ref)
5169
{
5170
  boolean r = false;
5171
  neighbor_rec nb;
5172
 
5173
  memset (nb, 0, sizeof (neighbor_rec));
5174
  if (!
5175
      (atom[a_view - 1].
5176
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5177
    return false;
5178
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5179
      || atom[a_ref - 1].neighbor_count != 2)
5180
    return false;
5181
  get_nextneighbors (nb, a_ref, a_view);
5182
  if (is_alkyl (a_ref, nb[0]))
5183
    r = true;
5184
  return r;
5185
}
5186
 
5187
 
5188
static boolean
5189
is_true_alkylsulfanyl (int a_view, int a_ref)
5190
{
5191
  boolean r = false;
5192
  neighbor_rec nb;
5193
 
5194
  memset (nb, 0, sizeof (neighbor_rec));
5195
  if (!
5196
      (atom[a_view - 1].
5197
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5198
    return false;
5199
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5200
      || atom[a_ref - 1].neighbor_count != 2)
5201
    return false;
5202
  get_nextneighbors (nb, a_ref, a_view);
5203
  if (is_true_alkyl (a_ref, nb[0]))
5204
    r = true;
5205
  return r;
5206
}
5207
 
5208
 
5209
static boolean
5210
is_arylsulfanyl (int a_view, int a_ref)
5211
{
5212
  boolean r = false;
5213
  neighbor_rec nb;
5214
 
5215
  memset (nb, 0, sizeof (neighbor_rec));
5216
  if (!
5217
      (atom[a_view - 1].
5218
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5219
    return false;
5220
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5221
      || atom[a_ref - 1].neighbor_count != 2)
5222
    return false;
5223
  get_nextneighbors (nb, a_ref, a_view);
5224
  if (is_aryl (a_ref, nb[0]))
5225
    r = true;
5226
  return r;
5227
}
5228
 
5229
 
5230
static boolean
5231
is_alkenylsulfanyl (a_view, a_ref)
5232
     int a_view, a_ref;
5233
{
5234
  /* v0.3j */
5235
  boolean r = false;
5236
  neighbor_rec nb;
5237
 
5238
  memset (nb, 0, sizeof (neighbor_rec));
5239
  if (!
5240
      (atom[a_view - 1].
5241
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5242
    return false;
5243
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5244
      || atom[a_ref - 1].neighbor_count != 2)
5245
    return false;
5246
  get_nextneighbors (nb, a_ref, a_view);
5247
  if (is_alkenyl (a_ref, nb[0]))
5248
    r = true;
5249
  return r;
5250
}
5251
 
5252
 
5253
static boolean
5254
is_alkynylsulfanyl (a_view, a_ref)
5255
     int a_view, a_ref;
5256
{
5257
  /* v0.3j */
5258
  boolean r = false;
5259
  neighbor_rec nb;
5260
 
5261
  memset (nb, 0, sizeof (neighbor_rec));
5262
  if (!
5263
      (atom[a_view - 1].
5264
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5265
    return false;
5266
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5267
      || atom[a_ref - 1].neighbor_count != 2)
5268
    return false;
5269
  get_nextneighbors (nb, a_ref, a_view);
5270
  if (is_alkynyl (a_ref, nb[0]))
5271
    r = true;
5272
  return r;
5273
}
5274
 
5275
 
5276
static boolean
5277
is_alkylamino (a_view, a_ref)
5278
     int a_view, a_ref;
5279
{
5280
  boolean r = false;
5281
  neighbor_rec nb;
5282
  int alkyl_count = 0;
5283
 
5284
  memset (nb, 0, sizeof (neighbor_rec));
5285
  if (!
5286
      (atom[a_view - 1].
5287
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5288
    return false;
5289
  if (strcmp (atom[a_ref - 1].element, "N ")
5290
      || atom[a_ref - 1].neighbor_count != 2)
5291
    return false;
5292
  get_nextneighbors (nb, a_ref, a_view);
5293
  if (is_alkyl (a_ref, nb[0]))
5294
    alkyl_count++;
5295
  if (alkyl_count == 1)
5296
    r = true;
5297
  return r;
5298
}
5299
 
5300
 
5301
static boolean
5302
is_dialkylamino (a_view, a_ref)
5303
     int a_view, a_ref;
5304
{
5305
  int i;
5306
  boolean r = false;
5307
  neighbor_rec nb;
5308
  int alkyl_count = 0;
5309
 
5310
  memset (nb, 0, sizeof (neighbor_rec));
5311
  if (!
5312
      (atom[a_view - 1].
5313
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5314
    return false;
5315
  if (strcmp (atom[a_ref - 1].element, "N ")
5316
      || atom[a_ref - 1].neighbor_count != 3)
5317
    return false;
5318
  get_nextneighbors (nb, a_ref, a_view);
5319
  for (i = 0; i <= 1; i++)
5320
    {
5321
      if (is_alkyl (a_ref, nb[i]))
5322
        alkyl_count++;
5323
    }
5324
  if (alkyl_count == 2)
5325
    r = true;
5326
  return r;
5327
}
5328
 
5329
 
5330
static boolean
5331
is_arylamino (a_view, a_ref)
5332
     int a_view, a_ref;
5333
{
5334
  boolean r = false;
5335
  neighbor_rec nb;
5336
  int aryl_count = 0;
5337
 
5338
  memset (nb, 0, sizeof (neighbor_rec));
5339
  if (!
5340
      (atom[a_view - 1].
5341
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5342
    return false;
5343
  if (strcmp (atom[a_ref - 1].element, "N ")
5344
      || atom[a_ref - 1].neighbor_count != 2)
5345
    return false;
5346
  get_nextneighbors (nb, a_ref, a_view);
5347
  if (is_aryl (a_ref, nb[0]))
5348
    aryl_count++;
5349
  if (aryl_count == 1)
5350
    r = true;
5351
  return r;
5352
}
5353
 
5354
 
5355
static boolean
5356
is_diarylamino (a_view, a_ref)
5357
     int a_view, a_ref;
5358
{
5359
  int i;
5360
  boolean r = false;
5361
  neighbor_rec nb;
5362
  int aryl_count = 0;
5363
 
5364
  memset (nb, 0, sizeof (neighbor_rec));
5365
  if (!
5366
      (atom[a_view - 1].
5367
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5368
    return false;
5369
  if (strcmp (atom[a_ref - 1].element, "N ")
5370
      || atom[a_ref - 1].neighbor_count != 3)
5371
    return false;
5372
  get_nextneighbors (nb, a_ref, a_view);
5373
  for (i = 0; i <= 1; i++)
5374
    {
5375
      if (is_aryl (a_ref, nb[i]))
5376
        aryl_count++;
5377
    }
5378
  if (aryl_count == 2)
5379
    r = true;
5380
  return r;
5381
}
5382
 
5383
 
5384
static boolean
5385
is_alkylarylamino (a_view, a_ref)
5386
     int a_view, a_ref;
5387
{
5388
  int i;
5389
  boolean r = false;
5390
  neighbor_rec nb;
5391
  int alkyl_count = 0, aryl_count = 0;
5392
 
5393
  memset (nb, 0, sizeof (neighbor_rec));
5394
  if (!
5395
      (atom[a_view - 1].
5396
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5397
    return false;
5398
  if (strcmp (atom[a_ref - 1].element, "N ")
5399
      || atom[a_ref - 1].neighbor_count != 3)
5400
    return false;
5401
  get_nextneighbors (nb, a_ref, a_view);
5402
  for (i = 0; i <= 1; i++)
5403
    {
5404
      if (is_alkyl (a_ref, nb[i]))
5405
        alkyl_count++;
5406
      if (is_aryl (a_ref, nb[i]))
5407
        aryl_count++;
5408
    }
5409
  if (alkyl_count == 1 && aryl_count == 1)
5410
    r = true;
5411
  return r;
5412
}
5413
 
5414
 
5415
static boolean
5416
is_C_monosubst_amino (a_view, a_ref)
5417
     int a_view, a_ref;
5418
{
5419
  /* new in v0.3j */
5420
  boolean r = false;
5421
  neighbor_rec nb;
5422
  int c_count = 0;
5423
 
5424
  memset (nb, 0, sizeof (neighbor_rec));
5425
  if (!
5426
      (atom[a_view - 1].
5427
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5428
    return false;
5429
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5430
      && strcmp (atom[a_ref - 1].atype, "NAM"))
5431
      || atom[a_ref - 1].neighbor_count != 2)
5432
    return false;
5433
  get_nextneighbors (nb, a_ref, a_view);
5434
  if (!strcmp (atom[nb[0] - 1].element, "C "))
5435
    c_count++;
5436
  if (c_count == 1)
5437
    r = true;
5438
  return r;
5439
}
5440
 
5441
 
5442
static boolean
5443
is_C_disubst_amino (a_view, a_ref)
5444
     int a_view, a_ref;
5445
{
5446
  /* new in v0.3j */
5447
  int i;
5448
  boolean r = false;
5449
  neighbor_rec nb;
5450
  int b;
5451
  int c_count = 0;
5452
 
5453
  b = get_bond (a_view, a_ref);
5454
  memset (nb, 0, sizeof (neighbor_rec));
5455
  if (!(atom[a_view - 1].heavy && bond[b - 1].btype == 'S' &&
5456
        bond[b - 1].arom == false))
5457
    return false;
5458
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5459
      && strcmp (atom[a_ref - 1].atype, "NAM"))
5460
      || atom[a_ref - 1].neighbor_count != 3)
5461
    return false;
5462
  get_nextneighbors (nb, a_ref, a_view);
5463
  for (i = 0; i <= 1; i++)
5464
    {
5465
      if (!strcmp (atom[nb[i] - 1].element, "C "))
5466
        c_count++;
5467
    }
5468
  if (c_count == 2)
5469
    r = true;
5470
  return r;
5471
}
5472
 
5473
 
5474
static boolean
5475
is_subst_amino (a_view, a_ref)
5476
     int a_view, a_ref;
5477
{
5478
  boolean r = false;
5479
 
5480
  if (is_amino (a_view, a_ref) || is_alkylamino (a_view, a_ref) |
5481
      is_arylamino (a_view, a_ref) || is_dialkylamino (a_view, a_ref) |
5482
      is_alkylarylamino (a_view, a_ref) || is_diarylamino (a_view, a_ref))
5483
    r = true;
5484
  return r;
5485
}
5486
 
5487
 
5488
static boolean
5489
is_true_alkylamino (a_view, a_ref)
5490
     int a_view, a_ref;
5491
{
5492
  boolean r = false;
5493
  neighbor_rec nb;
5494
  int alkyl_count = 0;
5495
 
5496
  memset (nb, 0, sizeof (neighbor_rec));
5497
  if (!
5498
      (atom[a_view - 1].
5499
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5500
    return false;
5501
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5502
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5503
      || atom[a_ref - 1].neighbor_count != 2)
5504
    return false;
5505
  get_nextneighbors (nb, a_ref, a_view);
5506
  if (is_true_alkyl (a_ref, nb[0]))
5507
    alkyl_count++;
5508
  if (alkyl_count == 1)
5509
    r = true;
5510
  return r;
5511
}
5512
 
5513
 
5514
static boolean
5515
is_true_dialkylamino (a_view, a_ref)
5516
     int a_view, a_ref;
5517
{
5518
  int i;
5519
  boolean r = false;
5520
  neighbor_rec nb;
5521
  int alkyl_count = 0;
5522
 
5523
  memset (nb, 0, sizeof (neighbor_rec));
5524
  if (!
5525
      (atom[a_view - 1].
5526
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5527
    return false;
5528
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5529
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5530
      || atom[a_ref - 1].neighbor_count != 3)
5531
    return false;
5532
  get_nextneighbors (nb, a_ref, a_view);
5533
  for (i = 0; i <= 1; i++)
5534
    {
5535
      if (is_true_alkyl (a_ref, nb[i]))
5536
        alkyl_count++;
5537
    }
5538
  if (alkyl_count == 2)
5539
    r = true;
5540
  return r;
5541
}
5542
 
5543
#if 0
5544
static boolean
5545
is_true_alkylarylamino (a_view, a_ref)
5546
     int a_view, a_ref;
5547
{
5548
  int i;
5549
  boolean r = false;
5550
  neighbor_rec nb;
5551
  int alkyl_count = 0, aryl_count = 0;
5552
 
5553
  memset (nb, 0, sizeof (neighbor_rec));
5554
  if (!
5555
      (atom[a_view - 1].
5556
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5557
    return false;
5558
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5559
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5560
      || atom[a_ref - 1].neighbor_count != 3)
5561
    return false;
5562
  get_nextneighbors (nb, a_ref, a_view);
5563
  for (i = 0; i <= 1; i++)
5564
    {
5565
      if (is_true_alkyl (a_ref, nb[i]))
5566
        alkyl_count++;
5567
      if (is_aryl (a_ref, nb[i]))
5568
        aryl_count++;
5569
    }
5570
  if (alkyl_count == 1 && aryl_count == 1)
5571
    r = true;
5572
  return r;
5573
}
5574
#endif
5575
 
5576
static boolean
5577
is_hydroxylamino (a_view, a_ref)
5578
     int a_view, a_ref;
5579
{
5580
  int i;
5581
  boolean r = false;
5582
  neighbor_rec nb;
5583
  int oh_count = 0, het_count = 0;      /* v0.3k */
5584
  str2 nb_el;                   /* v0.3k */
5585
  int FORLIM;
5586
 
5587
  memset (nb, 0, sizeof (neighbor_rec));
5588
  if (!
5589
      (atom[a_view - 1].
5590
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5591
    return false;
5592
  if (strcmp (atom[a_ref - 1].element, "N ")
5593
      || atom[a_ref - 1].neighbor_count < 2)
5594
    /* v0.3c */
5595
    return false;
5596
  get_nextneighbors (nb, a_ref, a_view);
5597
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
5598
  for (i = 0; i <= FORLIM; i++)
5599
    {                           /* v0.3c */
5600
      if (is_hydroxy (a_ref, nb[i]))
5601
        oh_count++;
5602
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3k */
5603
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
5604
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
5605
          && strcmp (nb_el, "LP"))
5606
        /* v0.3k */
5607
        het_count++;
5608
      /* v0.3n: D */
5609
    }
5610
  if (oh_count == 1 && het_count == 1)
5611
    r = true;
5612
  return r;
5613
}
5614
 
5615
 
5616
static boolean
5617
is_nitro (a_view, a_ref)
5618
     int a_view, a_ref;
5619
{
5620
  int i;
5621
  boolean r = false;
5622
  neighbor_rec nb;
5623
  int o_count = 0, bond_count = 0;
5624
 
5625
  memset (nb, 0, sizeof (neighbor_rec));
5626
  if (!
5627
      (atom[a_view - 1].
5628
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5629
    return false;
5630
  if (strcmp (atom[a_ref - 1].element, "N ")
5631
      || atom[a_ref - 1].neighbor_count != 3)
5632
    return false;
5633
  get_nextneighbors (nb, a_ref, a_view);
5634
  for (i = 0; i <= 1; i++)
5635
    {
5636
      if (!strcmp (atom[nb[i] - 1].element, "O "))
5637
        o_count++;
5638
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
5639
        bond_count++;
5640
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
5641
        bond_count += 2;
5642
    }
5643
  if (o_count == 2 && bond_count >= 3)
5644
    r = true;
5645
  return r;
5646
}
5647
 
5648
 
5649
static boolean
5650
is_azido (a_view, a_ref)
5651
     int a_view, a_ref;
5652
{
5653
  boolean r = false;
5654
  neighbor_rec nb;
5655
  int bond_count = 0, n1 = 0, n2 = 0, n3 = 0;
5656
 
5657
  if (!
5658
      (atom[a_view - 1].
5659
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5660
    return false;
5661
  if (strcmp (atom[a_ref - 1].element, "N ")
5662
      || atom[a_ref - 1].neighbor_count != 2)
5663
    return false;
5664
  n1 = a_ref;
5665
  memset (nb, 0, sizeof (neighbor_rec));
5666
  get_nextneighbors (nb, n1, a_view);
5667
  if (!strcmp (atom[nb[0] - 1].element, "N "))
5668
    {
5669
      n2 = nb[0];
5670
      if (bond[get_bond (n1, n2) - 1].btype == 'S')
5671
        bond_count++;
5672
      if (bond[get_bond (n1, n2) - 1].btype == 'D')
5673
        bond_count += 2;
5674
      if (bond[get_bond (n1, n2) - 1].btype == 'T')
5675
        bond_count += 3;
5676
    }
5677
  if (n2 > 0 && atom[n2 - 1].neighbor_count == 2)
5678
    {
5679
      memset (nb, 0, sizeof (neighbor_rec));
5680
      get_nextneighbors (nb, n2, n1);
5681
      if (!strcmp (atom[nb[0] - 1].element, "N "))
5682
        {
5683
          n3 = nb[0];
5684
          if (bond[get_bond (n2, n3) - 1].btype == 'S')
5685
            bond_count++;
5686
          if (bond[get_bond (n2, n3) - 1].btype == 'D')
5687
            bond_count += 2;
5688
          if (bond[get_bond (n2, n3) - 1].btype == 'T')
5689
            bond_count += 3;
5690
        }
5691
    }
5692
  if (n1 > 0 && n2 > 0 && n3 > 0 && atom[n3 - 1].neighbor_count == 1 &&
5693
      bond_count > 3)
5694
    r = true;
5695
  return r;
5696
}
5697
 
5698
 
5699
static boolean
5700
is_diazonium (a_view, a_ref)
5701
     int a_view, a_ref;
5702
{
5703
  boolean r = false;
5704
  neighbor_rec nb;
5705
  int bond_count = 0, chg_count = 0, n1 = 0, n2 = 0;
5706
 
5707
  if (!
5708
      (atom[a_view - 1].
5709
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5710
    return false;
5711
  if (strcmp (atom[a_ref - 1].element, "N ")
5712
      || atom[a_ref - 1].neighbor_count != 2)
5713
    return false;
5714
  n1 = a_ref;
5715
  chg_count = atom[n1 - 1].formal_charge;
5716
  memset (nb, 0, sizeof (neighbor_rec));
5717
  get_nextneighbors (nb, n1, a_view);
5718
  if (!strcmp (atom[nb[0] - 1].element, "N "))
5719
    {
5720
      n2 = nb[0];
5721
      chg_count += atom[n2 - 1].formal_charge;
5722
      if (bond[get_bond (n1, n2) - 1].btype == 'S')
5723
        bond_count++;
5724
      if (bond[get_bond (n1, n2) - 1].btype == 'D')
5725
        bond_count += 2;
5726
      if (bond[get_bond (n1, n2) - 1].btype == 'T')
5727
        bond_count += 3;
5728
    }
5729
  if (n1 > 0 && n2 > 0 && atom[n2 - 1].neighbor_count == 1
5730
      && bond_count >= 2 && chg_count > 0)
5731
    r = true;
5732
  return r;
5733
}
5734
 
5735
 
5736
static boolean
5737
is_hydroximino_C (id)
5738
     int id;
5739
{
5740
  boolean Result;
5741
  int i;
5742
  boolean r = false;
5743
  neighbor_rec nb;
5744
  int a_het = 0;
5745
  int FORLIM;
5746
 
5747
  memset (nb, 0, sizeof (neighbor_rec));
5748
  if (id < 1 || id > n_atoms)
5749
    return Result;
5750
  get_neighbors (nb, id);
5751
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5752
    return false;
5753
  FORLIM = atom[id - 1].neighbor_count;
5754
  for (i = 0; i < FORLIM; i++)
5755
    {
5756
      if ((bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5757
           !strcmp (atom[nb[i] - 1].element,
5758
                    "N ")) && (hetbond_count (nb[i]) == 3))
5759
        a_het = nb[i];
5760
    }
5761
  if (a_het <= 0)
5762
    return false;
5763
  memset (nb, 0, sizeof (neighbor_rec));
5764
  get_neighbors (nb, a_het);
5765
  if (strcmp (atom[a_het - 1].element, "N ")
5766
      || atom[a_het - 1].neighbor_count <= 0)
5767
    return false;
5768
  FORLIM = atom[a_het - 1].neighbor_count;
5769
  for (i = 0; i < FORLIM; i++)
5770
    {
5771
      if (is_hydroxy (a_het, nb[i]))
5772
        r = true;
5773
    }
5774
  return r;
5775
}
5776
 
5777
 
5778
static boolean
5779
is_hydrazono_C (id)
5780
     int id;
5781
{
5782
  boolean Result;
5783
  int i;
5784
  boolean r = false;
5785
  neighbor_rec nb;
5786
  int a_het = 0;
5787
  int FORLIM;
5788
 
5789
  memset (nb, 0, sizeof (neighbor_rec));
5790
  if (id < 1 || id > n_atoms)
5791
    return Result;
5792
  get_neighbors (nb, id);
5793
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5794
    return false;
5795
  FORLIM = atom[id - 1].neighbor_count;
5796
  for (i = 0; i < FORLIM; i++)
5797
    {
5798
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5799
          !strcmp (atom[nb[i] - 1].element, "N "))
5800
        {
5801
          /* and
5802
             (hetbond_count(nb[i]) = 3)  */
5803
          a_het = nb[i];
5804
        }
5805
    }
5806
  if (a_het <= 0)
5807
    return false;
5808
  memset (nb, 0, sizeof (neighbor_rec));
5809
  get_neighbors (nb, a_het);
5810
  if (strcmp (atom[a_het - 1].element, "N ")
5811
      || atom[a_het - 1].neighbor_count <= 0)
5812
    return false;
5813
  FORLIM = atom[a_het - 1].neighbor_count;
5814
  for (i = 0; i < FORLIM; i++)
5815
    {
5816
      if (is_amino (a_het, nb[i]) || is_alkylamino (a_het, nb[i]) |
5817
          is_alkylarylamino (a_het, nb[i]) || is_arylamino (a_het, nb[i]) |
5818
          is_dialkylamino (a_het, nb[i]) || is_diarylamino (a_het, nb[i]))
5819
        r = true;
5820
    }
5821
  return r;
5822
}
5823
 
5824
 
5825
static boolean
5826
is_alkoxycarbonyl (a_view, a_ref)
5827
     int a_view, a_ref;
5828
{
5829
  int i;
5830
  boolean r = false;
5831
  neighbor_rec nb;
5832
 
5833
  memset (nb, 0, sizeof (neighbor_rec));
5834
  if (!
5835
      (atom[a_view - 1].
5836
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5837
    return false;
5838
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5839
    return false;
5840
  get_nextneighbors (nb, a_ref, a_view);
5841
  for (i = 0; i <= 1; i++)
5842
    {
5843
      if (is_alkoxy (a_ref, nb[i]))
5844
        r = true;
5845
    }
5846
  return r;
5847
}
5848
 
5849
 
5850
static boolean
5851
is_aryloxycarbonyl (a_view, a_ref)
5852
     int a_view, a_ref;
5853
{
5854
  int i;
5855
  boolean r = false;
5856
  neighbor_rec nb;
5857
 
5858
  memset (nb, 0, sizeof (neighbor_rec));
5859
  if (!
5860
      (atom[a_view - 1].
5861
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5862
    return false;
5863
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5864
    return false;
5865
  get_nextneighbors (nb, a_ref, a_view);
5866
  for (i = 0; i <= 1; i++)
5867
    {
5868
      if (is_aryloxy (a_ref, nb[i]))
5869
        r = true;
5870
    }
5871
  return r;
5872
}
5873
 
5874
 
5875
static boolean
5876
is_carbamoyl (a_view, a_ref)
5877
     int a_view, a_ref;
5878
{
5879
  int i;
5880
  boolean r = false;
5881
  neighbor_rec nb;
5882
 
5883
  memset (nb, 0, sizeof (neighbor_rec));
5884
  if (!
5885
      (atom[a_view - 1].
5886
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5887
    return false;
5888
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5889
    return false;
5890
  get_nextneighbors (nb, a_ref, a_view);
5891
  for (i = 0; i <= 1; i++)
5892
    {
5893
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5894
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
5895
        r = true;
5896
    }
5897
  return r;
5898
}
5899
 
5900
 
5901
static boolean
5902
is_alkoxythiocarbonyl (a_view, a_ref)
5903
     int a_view, a_ref;
5904
{
5905
  int i;
5906
  boolean r = false;
5907
  neighbor_rec nb;
5908
 
5909
  memset (nb, 0, sizeof (neighbor_rec));
5910
  if (!
5911
      (atom[a_view - 1].
5912
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5913
    return false;
5914
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5915
    return false;
5916
  get_nextneighbors (nb, a_ref, a_view);
5917
  for (i = 0; i <= 1; i++)
5918
    {
5919
      if (is_alkoxy (a_ref, nb[i]))
5920
        r = true;
5921
    }
5922
  return r;
5923
}
5924
 
5925
 
5926
static boolean
5927
is_aryloxythiocarbonyl (a_view, a_ref)
5928
     int a_view, a_ref;
5929
{
5930
  int i;
5931
  boolean r = false;
5932
  neighbor_rec nb;
5933
 
5934
  memset (nb, 0, sizeof (neighbor_rec));
5935
  if (!
5936
      (atom[a_view - 1].
5937
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5938
    return false;
5939
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5940
    return false;
5941
  get_nextneighbors (nb, a_ref, a_view);
5942
  for (i = 0; i <= 1; i++)
5943
    {
5944
      if (is_aryloxy (a_ref, nb[i]))
5945
        r = true;
5946
    }
5947
  return r;
5948
}
5949
 
5950
 
5951
static boolean
5952
is_thiocarbamoyl (a_view, a_ref)
5953
     int a_view, a_ref;
5954
{
5955
  int i;
5956
  boolean r = false;
5957
  neighbor_rec nb;
5958
 
5959
  memset (nb, 0, sizeof (neighbor_rec));
5960
  if (!
5961
      (atom[a_view - 1].
5962
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5963
    return false;
5964
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5965
    return false;
5966
  get_nextneighbors (nb, a_ref, a_view);
5967
  for (i = 0; i <= 1; i++)
5968
    {
5969
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5970
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
5971
        r = true;
5972
    }
5973
  return r;
5974
}
5975
 
5976
 
5977
static boolean
5978
is_alkanoyl (a_view, a_ref)
5979
     int a_view, a_ref;
5980
{
5981
  int i;
5982
  boolean r = false;
5983
  neighbor_rec nb;
5984
 
5985
  memset (nb, 0, sizeof (neighbor_rec));
5986
  if (!
5987
      (atom[a_view - 1].
5988
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5989
    return false;
5990
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5991
    return false;
5992
  get_nextneighbors (nb, a_ref, a_view);
5993
  for (i = 0; i <= 1; i++)
5994
    {
5995
      if (is_alkyl (a_ref, nb[i]))
5996
        r = true;
5997
    }
5998
  return r;
5999
}
6000
 
6001
 
6002
static boolean
6003
is_aroyl (a_view, a_ref)
6004
     int a_view, a_ref;
6005
{
6006
  int i;
6007
  boolean r = false;
6008
  neighbor_rec nb;
6009
 
6010
  memset (nb, 0, sizeof (neighbor_rec));
6011
  if (!
6012
      (atom[a_view - 1].
6013
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6014
    return false;
6015
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
6016
    return false;
6017
  get_nextneighbors (nb, a_ref, a_view);
6018
  for (i = 0; i <= 1; i++)
6019
    {
6020
      if (is_aryl (a_ref, nb[i]))
6021
        r = true;
6022
    }
6023
  return r;
6024
}
6025
 
6026
 
6027
static boolean
6028
is_acyl (a_view, a_ref)
6029
     int a_view, a_ref;
6030
{
6031
  boolean r = false;
6032
 
6033
  if (is_alkanoyl (a_view, a_ref) || is_aroyl (a_view, a_ref))
6034
    r = true;
6035
  return r;
6036
}
6037
 
6038
 
6039
static boolean
6040
is_acyl_gen (a_view, a_ref)
6041
     int a_view, a_ref;
6042
{
6043
  /* new in v0.3j */
6044
  boolean r = false;
6045
 
6046
  if (is_oxo_C (a_ref))
6047
    r = true;
6048
  return r;
6049
}
6050
 
6051
 
6052
static boolean
6053
is_acylamino (a_view, a_ref)
6054
     int a_view, a_ref;
6055
{
6056
  boolean r = false;
6057
  neighbor_rec nb;
6058
  int acyl_count = 0;
6059
 
6060
  memset (nb, 0, sizeof (neighbor_rec));
6061
  if (!
6062
      (atom[a_view - 1].
6063
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6064
    return false;
6065
  if (strcmp (atom[a_ref - 1].element, "N ")
6066
      || atom[a_ref - 1].neighbor_count != 2)
6067
    return false;
6068
  get_nextneighbors (nb, a_ref, a_view);
6069
  if (is_acyl (a_ref, nb[0]))
6070
    acyl_count++;
6071
  if (acyl_count == 1)
6072
    r = true;
6073
  return r;
6074
}
6075
 
6076
 
6077
static boolean
6078
is_subst_acylamino (a_view, a_ref)
6079
     int a_view, a_ref;
6080
{
6081
  /* may be substituted _or_ unsubstituted acylamino group! */
6082
  int i;
6083
  boolean r = false;
6084
  neighbor_rec nb;
6085
  int acyl_count = 0;
6086
  int FORLIM;
6087
 
6088
  memset (nb, 0, sizeof (neighbor_rec));
6089
  if (!
6090
      (atom[a_view - 1].
6091
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6092
    return false;
6093
  if (strcmp (atom[a_ref - 1].element, "N ")
6094
      || atom[a_ref - 1].neighbor_count < 2)
6095
    return false;
6096
  get_nextneighbors (nb, a_ref, a_view);
6097
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6098
  for (i = 0; i <= FORLIM; i++)
6099
    {
6100
      if (is_acyl_gen (a_ref, nb[i]))   /* v0.3j */
6101
        acyl_count++;
6102
    }
6103
  if (acyl_count > 0)
6104
    r = true;
6105
  return r;
6106
}
6107
 
6108
 
6109
static boolean
6110
is_hydrazino (a_view, a_ref)
6111
     int a_view, a_ref;
6112
{
6113
  int i;
6114
  boolean r = false;
6115
  neighbor_rec nb;
6116
  int nr_count = 0;
6117
  int FORLIM;
6118
 
6119
  memset (nb, 0, sizeof (neighbor_rec));
6120
  if (!
6121
      (atom[a_view - 1].
6122
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6123
    return false;
6124
  if (strcmp (atom[a_ref - 1].element, "N ")
6125
      || atom[a_ref - 1].neighbor_count < 2)
6126
    return false;
6127
  get_nextneighbors (nb, a_ref, a_view);
6128
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6129
  for (i = 0; i <= FORLIM; i++)
6130
    {                           /* fixed in v0.3c */
6131
      if (is_amino (a_ref, nb[i]) || is_subst_amino (a_ref, nb[i]))
6132
        nr_count++;
6133
    }
6134
  if (nr_count == 1)
6135
    r = true;
6136
  return r;
6137
}
6138
 
6139
 
6140
static boolean
6141
is_nitroso (a_view, a_ref)
6142
     int a_view, a_ref;
6143
{
6144
  /* new in v0.3j */
6145
  boolean r = false;
6146
  neighbor_rec nb;
6147
  int o_count = 0;
6148
  int a2;
6149
 
6150
  memset (nb, 0, sizeof (neighbor_rec));
6151
  if (!
6152
      (atom[a_view - 1].
6153
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6154
    return false;
6155
  if (strcmp (atom[a_ref - 1].element, "N ")
6156
      || atom[a_ref - 1].neighbor_count != 2)
6157
    return false;
6158
  get_nextneighbors (nb, a_ref, a_view);
6159
  a2 = nb[0];
6160
  if ((strcmp (atom[a2 - 1].element, "O ") == 0) &
6161
      (bond[get_bond (a_ref, a2) - 1].btype == 'D'))
6162
    o_count++;
6163
  if (o_count == 1)
6164
    r = true;
6165
  return r;
6166
}
6167
 
6168
 
6169
static boolean
6170
is_subst_hydrazino (a_view, a_ref)
6171
     int a_view, a_ref;
6172
{
6173
  int i;
6174
  boolean r = false;
6175
  neighbor_rec nb;
6176
  int nr_count = 0;
6177
  int a2, FORLIM;
6178
 
6179
  memset (nb, 0, sizeof (neighbor_rec));
6180
  if (!
6181
      (atom[a_view - 1].
6182
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6183
    return false;
6184
  if (strcmp (atom[a_ref - 1].element, "N ")
6185
      || atom[a_ref - 1].neighbor_count < 2)
6186
    return false;
6187
  get_nextneighbors (nb, a_ref, a_view);
6188
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6189
  for (i = 0; i <= FORLIM; i++)
6190
    {
6191
      a2 = nb[i];
6192
      if ((strcmp (atom[a2 - 1].element, "N ") ==
6193
           0) && (!is_nitroso (a_ref, a2)))
6194
        /* v0.3j */
6195
        nr_count++;
6196
    }
6197
  if (nr_count == 1)
6198
    r = true;
6199
  return r;
6200
}
6201
 
6202
 
6203
static boolean
6204
is_cyano (a_view, a_ref)
6205
     int a_view, a_ref;
6206
{
6207
  boolean r = false;
6208
 
6209
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
6210
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6211
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
6212
      atom[a_ref - 1].neighbor_count == 1)
6213
    r = true;
6214
  return r;
6215
}
6216
 
6217
 
6218
static boolean
6219
is_cyano_c (a_ref)
6220
     int a_ref;
6221
{
6222
  int i;
6223
  boolean r = false;
6224
  neighbor_rec nb;
6225
  int FORLIM;
6226
 
6227
  memset (nb, 0, sizeof (neighbor_rec));
6228
  if (strcmp (atom[a_ref - 1].atype, "C1 ")
6229
      || atom[a_ref - 1].neighbor_count <= 0)
6230
    return false;
6231
  get_neighbors (nb, a_ref);
6232
  FORLIM = atom[a_ref - 1].neighbor_count;
6233
  for (i = 0; i < FORLIM; i++)
6234
    {
6235
      if (is_cyano (a_ref, nb[i]))
6236
        r = true;
6237
    }
6238
  return r;
6239
}
6240
 
6241
 
6242
static boolean
6243
is_nitrile (a_view, a_ref)
6244
     int a_view, a_ref;
6245
{
6246
  boolean r = false;
6247
  neighbor_rec nb;
6248
  str2 nb_el;
6249
 
6250
  if (!is_cyano (a_view, a_ref))
6251
    return false;
6252
  if (atom[a_view - 1].neighbor_count == 1
6253
      && atom[a_view - 1].formal_charge == 0)
6254
    return true;
6255
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6256
  get_nextneighbors (nb, a_view, a_ref);
6257
  strcpy (nb_el, atom[nb[0] - 1].element);
6258
  if (!strcmp (nb_el, "C ")
6259
      || !strcmp (nb_el, "H ") /*|| !strcmp (nb_el, "D ") */ )
6260
    /* v0.3n: D */
6261
    r = true;
6262
  /* HCN is also a nitrile! */
6263
  return r;
6264
}
6265
 
6266
 
6267
static boolean
6268
is_isonitrile (a_view, a_ref)
6269
     int a_view, a_ref;
6270
{
6271
  /* only recognized with CN triple bond! */
6272
  boolean r = false;
6273
 
6274
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
6275
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6276
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
6277
      atom[a_ref - 1].neighbor_count == 2
6278
      && atom[a_view - 1].neighbor_count == 1)
6279
    r = true;
6280
  return r;
6281
}
6282
 
6283
 
6284
static boolean
6285
is_cyanate (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_alkoxy (a_view, nb[0]) || is_aryloxy (a_view, nb[0]))
6297
    r = true;
6298
  return r;
6299
}
6300
 
6301
 
6302
static boolean
6303
is_thiocyanate (a_view, a_ref)
6304
     int a_view, a_ref;
6305
{
6306
  boolean r = false;
6307
  neighbor_rec nb;
6308
 
6309
  if (!is_cyano (a_view, a_ref))
6310
    return false;
6311
  if (atom[a_view - 1].neighbor_count != 2)
6312
    return false;
6313
  get_nextneighbors (nb, a_view, a_ref);
6314
  if (is_alkylsulfanyl (a_view, nb[0]) || is_arylsulfanyl (a_view, nb[0]))
6315
    r = true;
6316
  return r;
6317
}
6318
 
6319
 
6320
static void
6321
update_Htotal ()
6322
{
6323
  int i, j, b_id;
6324
  neighbor_rec nb;
6325
  int single_count, double_count, triple_count, arom_count, total_bonds,
6326
    Htotal, nval;
6327
  /* new in v0.3 */
6328
  boolean diazon = false;       /* new in v0.3j */
6329
  neighbor_rec nb2;             /* new in v0.3j */
6330
  int a1, a2, a3;               /* new in v0.3j */
6331
  int FORLIM, FORLIM1;
6332
 
6333
  if (n_atoms < 1)
6334
    return;
6335
  memset (nb, 0, sizeof (neighbor_rec));
6336
  FORLIM = n_atoms;
6337
  for (i = 1; i <= FORLIM; i++)
6338
    {
6339
      single_count = 0;
6340
      double_count = 0;
6341
      triple_count = 0;
6342
      arom_count = 0;
6343
      total_bonds = 0;
6344
      Htotal = 0;
6345
      get_neighbors (nb, i);
6346
      if (atom[i - 1].neighbor_count > 0)
6347
        {
6348
          /* count single, double, triple, and aromatic bonds to all neighbor atoms */
6349
          FORLIM1 = atom[i - 1].neighbor_count;
6350
          for (j = 0; j < FORLIM1; j++)
6351
            {
6352
              b_id = get_bond (i, nb[j]);
6353
              if (b_id > 0)
6354
                {
6355
                  if (bond[b_id - 1].btype == 'S')
6356
                    single_count++;
6357
                  if (bond[b_id - 1].btype == 'D')
6358
                    double_count++;
6359
                  if (bond[b_id - 1].btype == 'T')
6360
                    triple_count++;
6361
                  if (bond[b_id - 1].btype == 'A')
6362
                    arom_count++;
6363
                }
6364
            }
6365
          /*check for diazonium salts */
6366
          a1 = i;
6367
          a2 = nb[0];
6368
          if (!strcmp (atom[a1 - 1].element, "N ") &&
6369
              !strcmp (atom[a2 - 1].element, "N "))
6370
            {
6371
              if (atom[a2 - 1].neighbor_count == 2)
6372
                {
6373
                  get_nextneighbors (nb2, a2, a1);
6374
                  a3 = nb2[0];
6375
                  if ((strcmp (atom[a3 - 1].element, "C ") ==
6376
                       0) && is_diazonium (a3, a2))
6377
                    diazon = true;
6378
                }
6379
            }
6380
        }
6381
      total_bonds = single_count + double_count * 2 + triple_count * 3 +
6382
        (int) (1.5 * arom_count);
6383
      /* calculate number of total hydrogens per atom */
6384
      /*nval := nvalences(atom^[i].element);    (* new in v0.3 */
6385
      nval = atom[i - 1].nvalences;     /* new in v0.3m */
6386
      if (!strcmp (atom[i - 1].element, "P "))
6387
        {
6388
          if (total_bonds - atom[i - 1].formal_charge > 3)      /* refined in v0.3n */
6389
            nval = 5;
6390
        }                       /*  */
6391
      if (!strcmp (atom[i - 1].element, "S "))
6392
        {                       /* v0.3h */
6393
          if (total_bonds > 2 && atom[i - 1].formal_charge < 1)
6394
            /* updated in v0.3j */
6395
            nval = 4;
6396
          if (total_bonds > 4)  /* this will need some refinement... */
6397
            nval = 6;
6398
        }                       /*  */
6399
      Htotal = nval - total_bonds + atom[i - 1].formal_charge;
6400
      if (diazon)               /* v0.3j */
6401
        Htotal = 0;
6402
      if (Htotal < 0)           /* e.g., N in nitro group */
6403
        Htotal = 0;
6404
      atom[i - 1].Htot = Htotal;
6405
      if (atom[i - 1].Hexp > atom[i - 1].Htot)  /* v0.3n; just to be sure... */
6406
        atom[i - 1].Htot = atom[i - 1].Hexp;
6407
    }
6408
}
6409
 
6410
 
6411
static void
6412
update_atypes ()
6413
{
6414
  int i, j, b_id;
6415
  neighbor_rec nb;
6416
  int single_count, double_count, triple_count, arom_count, acyl_count,
6417
    C_count, O_count, total_bonds, NdO_count, NdC_count, Htotal, FORLIM,
6418
    FORLIM1;
6419
 
6420
  if (n_atoms < 1)
6421
    return;
6422
  memset (nb, 0, sizeof (neighbor_rec));
6423
  FORLIM = n_atoms;
6424
  for (i = 0; i < FORLIM; i++)
6425
    {
6426
      single_count = 0;
6427
      double_count = 0;
6428
      triple_count = 0;
6429
      arom_count = 0;
6430
      total_bonds = 0;
6431
      acyl_count = 0;
6432
      C_count = 0;
6433
      O_count = 0;
6434
      NdO_count = 0;
6435
      NdC_count = 0;
6436
      Htotal = 0;
6437
      get_neighbors (nb, i + 1);
6438
      if (atom[i].neighbor_count > 0)
6439
        {
6440
          /* count single, double, triple, and aromatic bonds to all neighbor atoms */
6441
          FORLIM1 = atom[i].neighbor_count;
6442
          for (j = 0; j < FORLIM1; j++)
6443
            {
6444
              if (is_oxo_C (nb[j]) || is_thioxo_C (nb[j]))
6445
                acyl_count++;
6446
              if (!strcmp (atom[nb[j] - 1].element, "C "))
6447
                C_count++;
6448
              if (!strcmp (atom[nb[j] - 1].element, "O "))
6449
                O_count++;
6450
              b_id = get_bond (i + 1, nb[j]);
6451
              if (b_id > 0)
6452
                {
6453
                  if (bond[b_id - 1].btype == 'S')
6454
                    single_count++;
6455
                  if (bond[b_id - 1].btype == 'D')
6456
                    double_count++;
6457
                  if (bond[b_id - 1].btype == 'T')
6458
                    triple_count++;
6459
                  if (bond[b_id - 1].btype == 'A')
6460
                    /* v0.3n: special treatment for acyclic bonds */
6461
                    {           /* flagged as "aromatic" (in query structures) */
6462
                      if (bond[b_id - 1].ring_count > 0)
6463
                        arom_count++;
6464
                      else
6465
                        double_count++;
6466
                    }
6467
                  if ((!strcmp (atom[i].element, "N ") &&
6468
                       !strcmp (atom[nb[j] - 1].element, "O ")) ||
6469
                      (!strcmp (atom[i].element, "O ") &&
6470
                       !strcmp (atom[nb[j] - 1].element, "N ")))
6471
                    {
6472
                      /* check if it is an N-oxide drawn with a double bond ==> should be N3 */
6473
                      if (bond[b_id - 1].btype == 'D')
6474
                        NdO_count++;
6475
                    }
6476
                  if ((!strcmp (atom[i].element, "N ") &&
6477
                       !strcmp (atom[nb[j] - 1].element, "C ")) ||
6478
                      (!strcmp (atom[i].element, "C ") &&
6479
                       !strcmp (atom[nb[j] - 1].element, "N ")))
6480
                    {
6481
                      if (bond[b_id - 1].btype == 'D')
6482
                        NdC_count++;
6483
                    }
6484
                }
6485
            }
6486
          total_bonds = single_count + double_count * 2 + triple_count * 3 +
6487
            (int) (1.5 * arom_count);
6488
          /* calculate number of total hydrogens per atom */
6489
          /*Htotal := nvalences(atom^[i].element) - total_bonds + atom^[i].formal_charge; */
6490
          Htotal = atom[i].nvalences - total_bonds + atom[i].formal_charge;
6491
          if (Htotal < 0)       /* e.g., N in nitro group */
6492
            Htotal = 0;
6493
          atom[i].Htot = Htotal;
6494
          /* refine atom types, based on bond types */
6495
          if (!strcmp (atom[i].element, "C "))
6496
            {
6497
              if (arom_count > 1)
6498
                strcpy (atom[i].atype, "CAR");
6499
              if (triple_count == 1 || double_count == 2)
6500
                strcpy (atom[i].atype, "C1 ");
6501
              if (double_count == 1)
6502
                strcpy (atom[i].atype, "C2 ");
6503
              if (triple_count == 0 && double_count == 0 && arom_count < 2)
6504
                strcpy (atom[i].atype, "C3 ");
6505
            }
6506
          if (!strcmp (atom[i].element, "O "))
6507
            {
6508
              if (double_count == 1)
6509
                strcpy (atom[i].atype, "O2 ");
6510
              if (double_count == 0)
6511
                strcpy (atom[i].atype, "O3 ");
6512
            }
6513
          if (!strcmp (atom[i].element, "N "))
6514
            {
6515
              if (total_bonds > 3)
6516
                {
6517
                  if (O_count == 0)
6518
                    {
6519
                      if (single_count > 3 ||
6520
                          (single_count == 2 && double_count == 1
6521
                          && C_count >= 2))
6522
                        atom[i].formal_charge = 1;
6523
                    }
6524
                  else
6525
                    {
6526
                      if (O_count == 1 && atom[i].formal_charge == 0)   /* v0.3m */
6527
                        strcpy (atom[i].atype, "N3 ");
6528
                      if (O_count == 2 && atom[i].formal_charge == 0)
6529
                        {
6530
                          if (atom[i].neighbor_count > 2)       /* nitro v0.3o */
6531
                            strcpy (atom[i].atype, "N2 ");
6532
                          if (atom[i].neighbor_count == 2)      /* NO2   v0.3o */
6533
                            strcpy (atom[i].atype, "N1 ");
6534
                        }
6535
                      /* the rest is left empty, so far.... */
6536
                    }
6537
                }
6538
              /* could be an N-oxide -> should be found elsewhere  */
6539
              if (triple_count == 1 ||
6540
                  (double_count == 2 && atom[i].neighbor_count == 2))
6541
                /* v0.3n */
6542
                strcpy (atom[i].atype, "N1 ");
6543
              if (double_count == 1)
6544
                {
6545
                  /*if NdC_count > 0 then atom^[i].atype := 'N2 '; */
6546
                  if (NdC_count == 0 && NdO_count > 0 && C_count >= 2)
6547
                    strcpy (atom[i].atype, "N3 ");
6548
                  /* N-oxide is N3 except in hetarene etc. */
6549
                  else
6550
                    strcpy (atom[i].atype, "N2 ");
6551
                }
6552
              /* fallback, added in v0.3g  */
6553
              if (arom_count > 1 || atom[i].arom == true)       /* v0.3n */
6554
                strcpy (atom[i].atype, "NAR");
6555
              if (triple_count == 0 && double_count == 0)
6556
                {
6557
                  if (atom[i].formal_charge == 0)
6558
                    {
6559
                      if (acyl_count == 0)
6560
                        strcpy (atom[i].atype, "N3 ");
6561
                      if (acyl_count > 0)
6562
                        strcpy (atom[i].atype, "NAM");
6563
                    }
6564
                  if (atom[i].formal_charge == 1)
6565
                    strcpy (atom[i].atype, "N3+");
6566
                }
6567
            }
6568
          if (!strcmp (atom[i].element, "P "))
6569
            {
6570
              if (single_count > 4)
6571
                strcpy (atom[i].atype, "P4 ");
6572
              if (single_count <= 4 && double_count == 0)
6573
                strcpy (atom[i].atype, "P3 ");
6574
              if (double_count == 2)
6575
                strcpy (atom[i].atype, "P3D");
6576
            }
6577
          if (!strcmp (atom[i].element, "S "))
6578
            {
6579
              if (double_count == 1 && single_count == 0)
6580
                strcpy (atom[i].atype, "S2 ");
6581
              if (double_count == 0)
6582
                strcpy (atom[i].atype, "S3 ");
6583
              if (double_count == 1 && single_count > 0)
6584
                strcpy (atom[i].atype, "SO ");
6585
              if (double_count == 2 && single_count > 0)
6586
                strcpy (atom[i].atype, "SO2");
6587
            }
6588
          /* further atom types should go here */
6589
        }
6590
    }
6591
}
6592
 
6593
 
6594
static void
6595
chk_arom ()
6596
{
6597
  int i, j, pi_count, ring_size, b, a1, a2;     /* v0.3n */
6598
  ringpath_type testring;
6599
  int a_ref, a_prev, a_next, b_bk, b_fw, b_exo;
6600
  char bt_bk, bt_fw;
6601
  boolean ar_bk, ar_fw, ar_exo; /* new in v0.3 */
6602
  boolean conj_intr, ko, aromatic, aromatic_bt; /* v0.3n */
6603
  int n_db, n_sb, n_ar;
6604
  boolean cumul;
6605
  int exo_mC;                   /* v0.3j */
6606
  int arom_pi_diff;             /* v0.3j */
6607
  int FORLIM;
6608
 
6609
  if (n_rings < 1)
6610
    return;
6611
  FORLIM = n_rings;
6612
  /* first, do a very quick check for benzene, pyridine, etc. */
6613
  for (i = 0; i < FORLIM; i++)
6614
    {
6615
      ring_size = ringprop[i].size;
6616
      if (ring_size == 6)
6617
        {
6618
          memset (testring, 0, sizeof (ringpath_type));
6619
          for (j = 0; j < ring_size; j++)
6620
            testring[j] = ring[i][j];
6621
          cumul = false;
6622
          n_sb = 0;
6623
          n_db = 0;
6624
          n_ar = 0;
6625
          a_prev = testring[ring_size - 1];
6626
          for (j = 1; j <= ring_size; j++)
6627
            {
6628
              a_ref = testring[j - 1];
6629
              if (j < ring_size)
6630
                a_next = testring[j];
6631
              else
6632
                a_next = testring[0];
6633
              b_bk = get_bond (a_prev, a_ref);
6634
              b_fw = get_bond (a_ref, a_next);
6635
              bt_bk = bond[b_bk - 1].btype;
6636
              bt_fw = bond[b_fw - 1].btype;
6637
              if (bt_fw == 'S')
6638
                n_sb++;
6639
              if (bt_fw == 'D')
6640
                n_db++;
6641
              if (bt_fw == 'A')
6642
                n_ar++;
6643
              if (bt_fw != 'A' && bt_bk == bt_fw)
6644
                cumul = true;
6645
              a_prev = a_ref;
6646
            }
6647
          if (n_ar == 6 || (n_sb == 3 && n_db == 3 && cumul == false))
6648
            {                   /* this ring is aromatic */
6649
              a_prev = testring[ring_size - 1];
6650
              for (j = 0; j < ring_size; j++)
6651
                {
6652
                  a_ref = testring[j];
6653
                  b_bk = get_bond (a_prev, a_ref);
6654
                  bond[b_bk - 1].arom = true;
6655
                  a_prev = a_ref;
6656
                }
6657
              ringprop[i].arom = true;
6658
            }
6659
        }
6660
    }
6661
  FORLIM = n_rings;
6662
  for (i = 1; i <= FORLIM; i++)
6663
    {
6664
      if (ringprop[i - 1].arom == false)
6665
        {
6666
          /* do the hard work only for those rings which are not yet flagged aromatic */
6667
          memset (testring, 0, sizeof (ringpath_type));
6668
          ring_size = ringprop[i - 1].size;     /* v0.3j */
6669
          for (j = 0; j < ring_size; j++)       /* v0.3j */
6670
            testring[j] = ring[i - 1][j];
6671
          pi_count = 0;
6672
          arom_pi_diff = 0;     /* v0.3j */
6673
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6674
          ko = false;
6675
          a_prev = testring[ring_size - 1];
6676
          for (j = 1; j <= ring_size; j++)
6677
            {
6678
              a_ref = testring[j - 1];
6679
              if (j < ring_size)
6680
                a_next = testring[j];
6681
              else
6682
                a_next = testring[0];
6683
              b_bk = get_bond (a_prev, a_ref);
6684
              b_fw = get_bond (a_ref, a_next);
6685
              bt_bk = bond[b_bk - 1].btype;
6686
              bt_fw = bond[b_fw - 1].btype;
6687
              ar_bk = bond[b_bk - 1].arom;
6688
              ar_fw = bond[b_fw - 1].arom;
6689
              if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == false
6690
                  && ar_fw == false)
6691
                {
6692
                  /* first, assume the worst case (interrupted conjugation) */
6693
                  conj_intr = true;
6694
                  /* conjugation can be restored by hetero atoms */
6695
                  if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6696
                      !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6697
                      !strcmp (atom[a_ref - 1].element, "N ") ||
6698
                      !strcmp (atom[a_ref - 1].element, "SE"))
6699
                    {
6700
                      conj_intr = false;
6701
                      pi_count += 2;    /* lone pair adds for 2 pi electrons */
6702
                    }
6703
                  /* conjugation can be restored by a formal charge at a methylene group */
6704
                  if (!strcmp (atom[a_ref - 1].element, "C ") &&
6705
                      atom[a_ref - 1].formal_charge != 0)
6706
                    {
6707
                      conj_intr = false;
6708
                      pi_count -= atom[a_ref - 1].formal_charge;
6709
                      /* neg. charge increases pi_count! */
6710
                    }
6711
                  /* conjugation can be restored by carbonyl groups etc. */
6712
                  if (is_oxo_C (a_ref) || is_thioxo_C (a_ref) |
6713
                      is_exocyclic_imino_C (a_ref, i))
6714
                    conj_intr = false;
6715
                  /* conjugation can be restored by exocyclic C=C double bond, */
6716
                  /* adds 2 pi electrons to 5-membered rings, not to 7-membered rings (CAUTION!) */
6717
                  /* apply only to non-aromatic exocyclic C=C bonds */
6718
                  exo_mC = find_exocyclic_methylene_C (a_ref, i);       /* v0.3j */
6719
                  if (exo_mC > 0 && (ring_size & 1))
6720
                    {           /* v0.3j */
6721
                      b_exo = get_bond (a_ref, exo_mC); /* v0.3j  */
6722
                      ar_exo = bond[b_exo - 1].arom;
6723
                      if (((ring_size - 1) & 3) == 0)
6724
                        {       /* 5-membered rings and related */
6725
                          conj_intr = false;
6726
                          pi_count += 2;
6727
                        }
6728
                      else
6729
                        {
6730
                          if (!ar_exo)
6731
                            conj_intr = false;
6732
                        }
6733
                    }
6734
                  /* 7-membered rings and related */
6735
                  /* if conjugation is still interrupted ==> knock-out */
6736
                  if (conj_intr)
6737
                    ko = true;
6738
                }
6739
              else
6740
                {
6741
                  if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == true
6742
                      && ar_fw == true)
6743
                    {
6744
                      if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6745
                          !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6746
                          !strcmp (atom[a_ref - 1].element, "N ") ||
6747
                          !strcmp (atom[a_ref - 1].element, "SE"))
6748
                        pi_count += 2;  /* lone pair adds for 2 pi electrons */
6749
                      if (!strcmp (atom[a_ref - 1].element, "C ") &&
6750
                          atom[a_ref - 1].formal_charge != 0)
6751
                        pi_count -= atom[a_ref - 1].formal_charge;
6752
                      /* neg. charge increases pi_count! */
6753
                      exo_mC = find_exocyclic_methylene_C (a_ref, i);   /* v0.3j */
6754
                      if (exo_mC > 0 && (ring_size & 1))
6755
                        {       /* v0.3j */
6756
                          b_exo = get_bond (a_ref, exo_mC);     /* v0.3j */
6757
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6758
                          if (((ring_size - 1) & 3) == 0)
6759
                            /* 5-membered rings and related */
6760
                            pi_count += 2;
6761
                        }
6762
                    }
6763
                  else
6764
                    {
6765
                      pi_count++;       /* v0.3j; adjustment for bridgehead N: see below */
6766
                      if (bt_bk == 'S' && bt_fw == 'S' &&
6767
                          ((ar_bk == true && ar_fw == false) ||
6768
                           (ar_bk == false && ar_fw == true)))
6769
                        {
6770
                          /* v0.3j; if a bridgehead N were not aromatic, it could  */
6771
                          /* contribute 2 pi electrons --> try also this variant */
6772
                          /* (example: CAS 32278-54-9) */
6773
                          if (!strcmp (atom[a_ref - 1].element, "N "))
6774
                            {
6775
                              arom_pi_diff++;
6776
                              /* any other case: increase pi count by one electron */
6777
                            }
6778
                        }
6779
                    }
6780
                }
6781
              /* last command: */
6782
              a_prev = a_ref;
6783
            }                   /* for j := 1 to ring_size */
6784
          /* now we can draw our conclusion */
6785
          /*if not ((ko) or (odd(pi_count))) then */
6786
          if (!ko)
6787
            /* v0.3j; odd pi_count might be compensated by arom_pi_diff */
6788
            {                   /* apply Hueckel's rule */
6789
              if (labs (ring_size - pi_count) < 2 &&
6790
                  (((pi_count - 2) & 3) == 0 ||
6791
                   ((pi_count + arom_pi_diff - 2) & 3) == 0))
6792
                {
6793
                  /* this ring is aromatic */
6794
                  ringprop[i - 1].arom = true;
6795
                  /* now mark _all_ bonds in the ring as aromatic */
6796
                  a_prev = testring[ring_size - 1];
6797
                  for (j = 0; j < ring_size; j++)
6798
                    {
6799
                      a_ref = testring[j];
6800
                      bond[get_bond (a_prev, a_ref) - 1].arom = true;
6801
                      a_prev = a_ref;
6802
                    }
6803
                }
6804
            }
6805
        }
6806
    }                           /* (for i := 1 to n_rings) */
6807
  FORLIM = n_bonds;
6808
  /* finally, mark all involved atoms as aromatic */
6809
  for (i = 0; i < FORLIM; i++)
6810
    {
6811
      if (bond[i].arom)
6812
        {
6813
          a1 = bond[i].a1;      /* v0.3n */
6814
          a2 = bond[i].a2;      /* v0.3n */
6815
          atom[a1 - 1].arom = true;
6816
          atom[a2 - 1].arom = true;
6817
          /* v0.3n: update atom types if applicable (C and N) */
6818
          if (!strcmp (atom[a1 - 1].element, "C "))
6819
            strcpy (atom[a1 - 1].atype, "CAR");
6820
          if (!strcmp (atom[a2 - 1].element, "C "))
6821
            strcpy (atom[a2 - 1].atype, "CAR");
6822
          if (!strcmp (atom[a1 - 1].element, "N "))
6823
            strcpy (atom[a1 - 1].atype, "NAR");
6824
          if (!strcmp (atom[a2 - 1].element, "N "))
6825
            strcpy (atom[a2 - 1].atype, "NAR");
6826
        }
6827
    }
6828
  FORLIM = n_rings;
6829
  /* update aromaticity information in ringprop */
6830
  /* new in v0.3n: accept rings as aromatic if all bonds are of type 'A' */
6831
  for (i = 0; i < FORLIM; i++)
6832
    {
6833
      memcpy (testring, ring[i], sizeof (ringpath_type));
6834
      /*ring_size := path_length(testring); */
6835
      ring_size = ringprop[i].size;     /* v0.3j */
6836
      aromatic = true;
6837
      aromatic_bt = true;       /* v0.3n */
6838
      a_prev = testring[ring_size - 1];
6839
      for (j = 0; j < ring_size; j++)
6840
        {
6841
          a_ref = testring[j];
6842
          b = get_bond (a_prev, a_ref); /* v0.3n */
6843
          if (!bond[b - 1].arom)
6844
            aromatic = false;
6845
          if (bond[b - 1].btype != 'A') /* v0.3n */
6846
            aromatic_bt = false;
6847
          a_prev = a_ref;
6848
        }
6849
      if (aromatic_bt && !aromatic)
6850
        {                       /* v0.3n: update aromaticity flag */
6851
          a_prev = testring[ring_size - 1];
6852
          for (j = 0; j < ring_size; j++)
6853
            {
6854
              a_ref = testring[j];
6855
              b = get_bond (a_prev, a_ref);
6856
              bond[b - 1].arom = true;
6857
              if (!strcmp (atom[a_ref - 1].element, "C "))
6858
                strcpy (atom[a_ref - 1].atype, "CAR");
6859
              if (!strcmp (atom[a_ref - 1].element, "N "))
6860
                strcpy (atom[a_ref - 1].atype, "NAR");
6861
              a_prev = a_ref;
6862
            }
6863
          aromatic = true;
6864
        }                       /* end v0.3n block   */
6865
      if (aromatic)
6866
        ringprop[i].arom = true;
6867
      else
6868
        ringprop[i].arom = false;
6869
    }
6870
}
6871
 
6872
 
6873
static void
6874
write_mol ()
6875
{
6876
  int i, j;
6877
  ringpath_type testring;
6878
  int ring_size, FORLIM;
6879
 
6880
  /*aromatic : boolean; */
6881
  /*a_prev, a_ref : integer; */
6882
  if (progmode == pmCheckMol)
6883
    printf ("Molecule name: %s\n", molname);
6884
  else
6885
    printf ("Molecule name (haystack): %s\n", molname);
6886
  printf ("atoms: %d  bonds: %d  rings: %d\n", n_atoms, n_bonds, n_rings);
6887
  if (n_atoms < 1)
6888
    return;
6889
  if (n_bonds < 1)
6890
    return;
6891
  FORLIM = n_atoms;
6892
  for (i = 1; i <= FORLIM; i++)
6893
    {
6894
      if (i < 10)
6895
        putchar (' ');
6896
      if (i < 100)
6897
        putchar (' ');
6898
      if (i < 1000)
6899
        putchar (' ');
6900
      printf ("%d %s %s %f %f ",
6901
              i, atom[i - 1].element, atom[i - 1].atype, atom[i - 1].x,
6902
              atom[i - 1].y);
6903
      printf ("%f", atom[i - 1].z);
6904
      printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6905
              atom[i - 1].neighbor_count, atom[i - 1].Hexp, atom[i - 1].Htot);
6906
      if (atom[i - 1].formal_charge != 0)
6786 kbelabas 6907
        printf ("  charge: %d", atom[i - 1].formal_charge);
6785 bpr 6908
      putchar ('\n');
6909
    }
6910
  FORLIM = n_bonds;
6911
  for (i = 1; i <= FORLIM; i++)
6912
    {
6913
      if (i < 10)
6914
        putchar (' ');
6915
      if (i < 100)
6916
        putchar (' ');
6917
      if (i < 1000)
6918
        putchar (' ');
6919
      printf ("%d %d %d %c",
6920
              i, bond[i - 1].a1, bond[i - 1].a2, bond[i - 1].btype);
6921
      if (bond[i - 1].ring_count > 0)
6922
        printf (", contained in %d ring(s)", bond[i - 1].ring_count);
6923
      if (bond[i - 1].arom)
6924
        printf (" (aromatic) ");
6925
      putchar ('\n');
6926
    }
6927
  if (n_rings <= 0)
6928
    return;
6929
  FORLIM = n_rings;
6930
  for (i = 0; i < FORLIM; i++)
6931
    {
6932
      printf ("ring %d: ", i + 1);
6933
      /*aromatic := true; */
6934
      memset (testring, 0, sizeof (ringpath_type));
6935
      ring_size = ringprop[i].size;     /* v0.3j */
6936
      /*for j := 1 to max_ringsize do if ring^[i,j] > 0 then testring[j] := ring^[i,j]; */
6937
      for (j = 0; j < ring_size; j++)   /* v0.3j */
6938
        testring[j] = ring[i][j];
6939
      /*ring_size := path_length(testring); */
6940
      /*a_prev := testring[ring_size]; */
6941
      for (j = 0; j < ring_size; j++)
6942
        {
6943
          printf ("%d ", testring[j]);
6944
          /*a_ref := testring[j]; */
6945
          /*if (not bond^[get_bond(a_prev,a_ref)].arom) then aromatic := false; */
6946
          /*a_prev := a_ref; */
6947
        }
6948
      /*if aromatic then write(' (aromatic)'); */
6949
      if (ringprop[i].arom)
6950
        printf (" (aromatic)");
6951
      if (ringprop[i].envelope)
6952
        printf (" (env)");
6953
      putchar ('\n');
6954
    }
6955
}
6956
 
6957
 
6958
static void
6959
write_needle_mol ()
6960
{
6961
  int i, j;
6962
  ringpath_type testring;
6963
  int ring_size;
6964
  boolean aromatic;
6965
  int a_prev, a_ref, FORLIM;
6966
 
6967
  printf ("Molecule name (needle): %s\n", ndl_molname);
6968
  printf ("atoms: %d  bonds: %d  rings: %d\n",
6969
          ndl_n_atoms, ndl_n_bonds, ndl_n_rings);
6970
  if (ndl_n_atoms < 1)
6971
    return;
6972
  if (ndl_n_bonds < 1)
6973
    return;
6974
  FORLIM = ndl_n_atoms;
6975
  for (i = 1; i <= FORLIM; i++)
6976
    {
6977
      if (i < 10)
6978
        putchar (' ');
6979
      if (i < 100)
6980
        putchar (' ');
6981
      if (i < 1000)
6982
        putchar (' ');
6983
      printf ("%d %s %s %f %f ",
6984
              i, ndl_atom[i - 1].element, ndl_atom[i - 1].atype,
6985
              ndl_atom[i - 1].x, atom[i - 1].y);
6986
      printf ("%f", ndl_atom[i - 1].z);
6987
      printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6988
              ndl_atom[i - 1].neighbor_count, ndl_atom[i - 1].Hexp,
6989
              ndl_atom[i - 1].Htot);
6990
      if (ndl_atom[i - 1].formal_charge != 0)
6991
        printf ("  charge: %d", ndl_atom[i - 1].formal_charge);
6992
      putchar ('\n');
6993
    }
6994
  FORLIM = ndl_n_bonds;
6995
  for (i = 1; i <= FORLIM; i++)
6996
    {
6997
      if (i < 10)
6998
        putchar (' ');
6999
      if (i < 100)
7000
        putchar (' ');
7001
      if (i < 1000)
7002
        putchar (' ');
7003
      printf ("%d %d %d %c",
7004
              i, ndl_bond[i - 1].a1, ndl_bond[i - 1].a2,
7005
              ndl_bond[i - 1].btype);
7006
      if (ndl_bond[i - 1].ring_count > 0)
7007
        printf (", contained in %d ring(s)", ndl_bond[i - 1].ring_count);
7008
      if (ndl_bond[i - 1].arom)
7009
        printf (" (aromatic) ");
7010
      putchar ('\n');
7011
    }
7012
  if (ndl_n_rings <= 0)
7013
    return;
7014
  FORLIM = ndl_n_rings;
7015
  for (i = 0; i < FORLIM; i++)
7016
    {
7017
      aromatic = true;
7018
      memset (testring, 0, sizeof (ringpath_type));
7019
      for (j = 0; j < max_ringsize; j++)
7020
        {
7021
          if (ndl_ring[i][j] > 0)
7022
            testring[j] = ndl_ring[i][j];
7023
        }
7024
      ring_size = path_length (testring);
7025
      printf ("ring %d: ", i + 1);
7026
      a_prev = testring[ring_size - 1];
7027
      for (j = 0; j < ring_size; j++)
7028
        {
7029
          printf ("%d ", testring[j]);
7030
          a_ref = testring[j];
7031
          if (!ndl_bond[get_ndl_bond (a_prev, a_ref) - 1].arom) /* v0.3k */
7032
            aromatic = false;
7033
          a_prev = a_ref;
7034
        }
7035
      if (aromatic)
7036
        printf (" (aromatic)");
7037
      putchar ('\n');
7038
    }
7039
}
7040
 
7041
 
7042
static void
7043
chk_so2_deriv (a_ref)
7044
     int a_ref;
7045
{
7046
  int i;
7047
  neighbor_rec nb;
7048
  str2 nb_el;
7049
  int het_count = 0, o_count = 0, or_count = 0, hal_count = 0, n_count = 0,
7050
    c_count = 0;
7051
  int FORLIM;
7052
 
7053
  memset (nb, 0, sizeof (neighbor_rec));
7054
  if (strcmp (atom[a_ref - 1].atype, "SO2"))
7055
    return;
7056
  get_neighbors (nb, a_ref);
7057
  FORLIM = atom[a_ref - 1].neighbor_count;
7058
  for (i = 0; i < FORLIM; i++)
7059
    {
7060
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7061
        {
7062
          strcpy (nb_el, atom[nb[i] - 1].element);
7063
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7064
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
7065
              && strcmp (nb_el, "LP"))
7066
            /* added 'D ' in v0.3n */
7067
            het_count++;
7068
          if (!strcmp (nb_el, "O "))
7069
            {
7070
              o_count++;
7071
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7072
                or_count++;
7073
            }
7074
          if (!strcmp (nb_el, "N "))
7075
            n_count++;
7076
          if (!strcmp (nb_el, "C "))
7077
            c_count++;
7078
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7079
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7080
              || !strcmp (nb_el, "AT"))
7081
            hal_count++;
7082
        }
7083
    }
7084
  if (het_count == 2)
7085
    {                           /* sulfuric acid derivative */
7086
      fg[fg_sulfuric_acid_deriv - 1] = true;
7087
      if (o_count == 2)
7088
        {
7089
          if (or_count == 0)
7090
            fg[fg_sulfuric_acid - 1] = true;
7091
          if (or_count == 1)
7092
            fg[fg_sulfuric_acid_monoester - 1] = true;
7093
          if (or_count == 2)
7094
            fg[fg_sulfuric_acid_diester - 1] = true;
7095
        }
7096
      if (o_count == 1)
7097
        {
7098
          if (or_count == 1 && n_count == 1)
7099
            fg[fg_sulfuric_acid_amide_ester - 1] = true;
7100
          if (or_count == 0 && n_count == 1)
7101
            fg[fg_sulfuric_acid_amide - 1] = true;
7102
        }
7103
      if (n_count == 2)
7104
        fg[fg_sulfuric_acid_diamide - 1] = true;
7105
      if (hal_count > 0)
7106
        fg[fg_sulfuryl_halide - 1] = true;
7107
    }
7108
  if (het_count == 1 && c_count == 1)
7109
    {                           /* sulfonic acid derivative */
7110
      fg[fg_sulfonic_acid_deriv - 1] = true;
7111
      if (o_count == 1 && or_count == 0)
7112
        fg[fg_sulfonic_acid - 1] = true;
7113
      if (o_count == 1 && or_count == 1)
7114
        fg[fg_sulfonic_acid_ester - 1] = true;
7115
      if (n_count == 1)
7116
        fg[fg_sulfonamide - 1] = true;
7117
      if (hal_count == 1)
7118
        fg[fg_sulfonyl_halide - 1] = true;
7119
    }
7120
  if (het_count == 0 && c_count == 2)   /* sulfone */
7121
    fg[fg_sulfone - 1] = true;
7122
}
7123
 
7124
 
7125
static void
7126
chk_p_deriv (a_ref)
7127
     int a_ref;
7128
{
7129
  int i;
7130
  neighbor_rec nb;
7131
  str2 nb_el, dbl_het;
7132
  int het_count;
7133
  int oh_count = 0, or_count = 0, hal_count = 0, n_count = 0, c_count = 0;
7134
  int FORLIM;
7135
 
7136
  if (strcmp (atom[a_ref - 1].element, "P "))
7137
    return;
7138
  memset (nb, 0, sizeof (neighbor_rec));
7139
  get_neighbors (nb, a_ref);
7140
  *dbl_het = '\0';
7141
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
7142
  FORLIM = atom[a_ref - 1].neighbor_count;
7143
  for (i = 0; i < FORLIM; i++)
7144
    {
7145
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
7146
        strcpy (dbl_het, atom[nb[i] - 1].element);
7147
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7148
        {
7149
          strcpy (nb_el, atom[nb[i] - 1].element);
7150
          if (!strcmp (nb_el, "C "))
7151
            c_count++;
7152
          if (is_hydroxy (a_ref, nb[i]))
7153
            oh_count++;
7154
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7155
            or_count++;
7156
          if (!strcmp (nb_el, "N "))
7157
            n_count++;
7158
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7159
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7160
              || !strcmp (nb_el, "AT"))
7161
            hal_count++;
7162
        }
7163
    }
7164
  het_count = oh_count + or_count + hal_count + n_count;
7165
  if (!strcmp (atom[a_ref - 1].atype, "P3D") ||
7166
      !strcmp (atom[a_ref - 1].atype, "P4 "))
7167
    {
7168
      if (!strcmp (dbl_het, "O "))
7169
        {
7170
          if (c_count == 0)
7171
            {
7172
              fg[fg_phosphoric_acid_deriv - 1] = true;
7173
              if (oh_count == 3)
7174
                fg[fg_phosphoric_acid - 1] = true;
7175
              if (or_count > 0)
7176
                fg[fg_phosphoric_acid_ester - 1] = true;
7177
              if (hal_count > 0)
7178
                fg[fg_phosphoric_acid_halide - 1] = true;
7179
              if (n_count > 0)
7180
                fg[fg_phosphoric_acid_amide - 1] = true;
7181
            }
7182
          if (c_count == 1)
7183
            {
7184
              fg[fg_phosphonic_acid_deriv - 1] = true;
7185
              if (oh_count == 2)
7186
                fg[fg_phosphonic_acid - 1] = true;
7187
              if (or_count > 0)
7188
                fg[fg_phosphonic_acid_ester - 1] = true;
7189
              /*if (hal_count > 0)  then fg[fg_phosphonic_acid_halide] := true;             */
7190
              /*if (n_count > 0)    then fg[fg_phosphonic_acid_amide]  := true; */
7191
            }
7192
          if (c_count == 3)
7193
            fg[fg_phosphinoxide - 1] = true;
7194
        }
7195
      if (!strcmp (dbl_het, "S "))
7196
        {
7197
          if (c_count == 0)
7198
            {
7199
              fg[fg_thiophosphoric_acid_deriv - 1] = true;
7200
              if (oh_count == 3)
7201
                fg[fg_thiophosphoric_acid - 1] = true;
7202
              if (or_count > 0)
7203
                fg[fg_thiophosphoric_acid_ester - 1] = true;
7204
              if (hal_count > 0)
7205
                fg[fg_thiophosphoric_acid_halide - 1] = true;
7206
              if (n_count > 0)
7207
                fg[fg_thiophosphoric_acid_amide - 1] = true;
7208
            }
7209
        }
7210
    }
7211
  /*  if (atom^[a_ref].atype = 'P4 ') then fg[fg_phosphoric_acid_deriv] := true; */
7212
  if (strcmp (atom[a_ref - 1].atype, "P3 "))    /* changed P3D into P3 in v0.3b */
7213
    return;
7214
  if (c_count == 3 && het_count == 0)
7215
    fg[fg_phosphine - 1] = true;
7216
  if (c_count == 3 && oh_count == 1)
7217
    fg[fg_phosphinoxide - 1] = true;
7218
}
7219
 
7220
 
7221
static void
7222
chk_b_deriv (a_ref)
7223
     int a_ref;
7224
{
7225
  int i;
7226
  neighbor_rec nb;
7227
  str2 nb_el;
7228
  int het_count = 0, oh_count = 0, or_count = 0, hal_count = 0, n_count = 0,
7229
    c_count = 0;
7230
  int FORLIM;
7231
 
7232
  if (strcmp (atom[a_ref - 1].element, "B "))
7233
    return;
7234
  memset (nb, 0, sizeof (neighbor_rec));
7235
  get_neighbors (nb, a_ref);
7236
  FORLIM = atom[a_ref - 1].neighbor_count;
7237
  for (i = 0; i < FORLIM; i++)
7238
    {
7239
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7240
        {
7241
          strcpy (nb_el, atom[nb[i] - 1].element);
7242
          if (!strcmp (nb_el, "C "))
7243
            c_count++;
7244
          else if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  &&
7245
                   strcmp (nb_el, "LP"))
7246
            /* v0.3n: D */
7247
            het_count++;
7248
          if (is_hydroxy (a_ref, nb[i]))
7249
            oh_count++;
7250
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7251
            /* fixed in v0.3b */
7252
            or_count++;
7253
          if (!strcmp (nb_el, "N "))
7254
            n_count++;
7255
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7256
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7257
              || !strcmp (nb_el, "AT"))
7258
            hal_count++;
7259
        }
7260
    }
7261
  het_count = oh_count + or_count + hal_count + n_count;
7262
  /* fixed in v0.3b */
7263
  if (c_count != 1 || het_count != 2)
7264
    return;
7265
  fg[fg_boronic_acid_deriv - 1] = true;
7266
  if (oh_count == 2)
7267
    fg[fg_boronic_acid - 1] = true;
7268
  if (or_count > 0)
7269
    fg[fg_boronic_acid_ester - 1] = true;
7270
}
7271
 
7272
 
7273
static void
7274
chk_ammon (a_ref)
7275
     int a_ref;
7276
{
7277
  int i;
7278
  neighbor_rec nb;
7279
  str2 nb_el;
7280
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
7281
  char bt;                      /* v0.3k */
7282
  float bo_sum = 0.0;
7283
  boolean ha;
7284
  int FORLIM;
7285
 
7286
  memset (nb, 0, sizeof (neighbor_rec));
7287
  if (strcmp (atom[a_ref - 1].atype, "N3+")
7288
      && atom[a_ref - 1].formal_charge == 0)
7289
    return;
7290
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
7291
    return;
7292
  get_neighbors (nb, a_ref);
7293
  FORLIM = atom[a_ref - 1].neighbor_count;
7294
  for (i = 0; i < FORLIM; i++)
7295
    {
7296
      bt = bond[get_bond (a_ref, nb[i]) - 1].btype;     /* v0.3k */
7297
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3k */
7298
      ha = atom[nb[i] - 1].heavy;       /* v0.3k */
7299
      if (bt == 'S')
7300
        {
7301
          if (ha)
7302
            bo_sum += 1.0;
7303
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7304
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
7305
            {                   /* added 'D ' in v0.3n */
7306
              het_count++;
7307
              if (!strcmp (nb_el, "O "))
7308
                {
7309
                  o_count++;
7310
                  if (atom[nb[i] - 1].neighbor_count > 1)
7311
                    or_count++;
7312
                }
7313
            }
7314
          if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
7315
              is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
7316
            /* v0.3k */
7317
            r_count++;
7318
        }
7319
      if (bt == 'D')
7320
        {
7321
          if (ha)
7322
            bo_sum += 2.0;
7323
          if (strcmp (nb_el, "C "))
7324
            {
7325
              het_count += 2;
7326
              if (!strcmp (nb_el, "O "))
7327
                o_count += 2;
7328
            }
7329
          if (!strcmp (nb_el, "C "))
7330
            r_count++;
7331
        }
7332
      if (bt == 'A' && ha)
7333
        bo_sum += 1.5;
7334
    }                           /* v0.3k: corrected end of "for ..." loop */
7335
  if (het_count == 0 && r_count == 4)
7336
    fg[fg_quart_ammonium - 1] = true;
7337
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
7338
    return;
7339
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
7340
    fg[fg_n_oxide - 1] = true;  /* finds only aliphatic N-oxides! */
7341
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
7342
      atom[a_ref - 1].arom == true)
7343
    fg[fg_quart_ammonium - 1] = true;
7344
}
7345
 
7346
 
7347
static void
7348
swap_atoms (a1, a2)
7349
     int *a1, *a2;
7350
{
7351
  int a_tmp;
7352
 
7353
  a_tmp = *a1;
7354
  *a1 = *a2;
7355
  *a2 = a_tmp;
7356
}
7357
 
7358
 
7359
static void
7360
orient_bond (a1, a2)
7361
     int *a1, *a2;
7362
{
7363
  str2 a1_el, a2_el;
7364
 
7365
  strcpy (a1_el, atom[*a1 - 1].element);
7366
  strcpy (a2_el, atom[*a2 - 1].element);
7367
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
7368
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
7369
    /* v0.3n: D */
7370
    return;
7371
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
7372
    swap_atoms (a1, a2);
7373
  if (!strcmp (a2_el, a1_el))
7374
    {
7375
      if (hetbond_count (*a1) > hetbond_count (*a2))
7376
        swap_atoms (a1, a2);
7377
    }
7378
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el))
7379
    {
7380
      if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O "))
7381
        {
7382
          if (!strcmp (a1_el, "O "))
7383
            swap_atoms (a1, a2);
7384
        }
7385
    }
7386
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el))
7387
    {
7388
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
7389
          atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
7390
        swap_atoms (a1, a2);
7391
    }
7392
}
7393
 
7394
 
7395
static void
7396
chk_imine (a_ref, a_view)
7397
     int a_ref, a_view;
7398
{
7399
  /* a_ref = C, a_view = N */
7400
  int i;
7401
  neighbor_rec nb;
7402
  str2 nb_el;
7403
  int a_het, a_c;
7404
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
7405
  int FORLIM;
7406
 
7407
  /* v0.3k */
7408
  if (atom[a_view - 1].neighbor_count == 1)
7409
    {
7410
      if (atom[a_ref - 1].arom == false)
7411
        fg[fg_imine - 1] = true;
7412
      return;
7413
    }
7414
  memset (nb, 0, sizeof (neighbor_rec));
7415
  get_neighbors (nb, a_view);
7416
  if (atom[a_view - 1].neighbor_count <= 1)
7417
    return;
7418
  FORLIM = atom[a_view - 1].neighbor_count;
7419
  for (i = 0; i < FORLIM; i++)
7420
    {
7421
      if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype ==
7422
                               'S'))
7423
        {
7424
          strcpy (nb_el, atom[nb[i] - 1].element);
7425
          if (!strcmp (nb_el, "C "))
7426
            {
7427
              a_c = nb[i];
7428
              c_count++;
7429
            }
7430
          if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N "))
7431
            {
7432
              a_het = nb[i];
7433
              het_count++;
7434
            }
7435
          if ((!strcmp (nb_el, "O ")
7436
               && atom[nb[i] - 1].neighbor_count ==
7437
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
7438
            /* v0.3k */
7439
            o_count++;
7440
        }
7441
      if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype ==
7442
                               'D'))
7443
        {                       /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
7444
          strcpy (nb_el, atom[nb[i] - 1].element);
7445
          if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")
7446
              || !strcmp (nb_el, "S "))
7447
            {
7448
              a_het = nb[i];    /* v0.3m */
7449
              het_count++;
7450
            }
7451
          if ((!strcmp (nb_el, "O ")
7452
               && atom[nb[i] - 1].neighbor_count ==
7453
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
7454
            /* v0.3k */
7455
            o_count++;
7456
        }
7457
    }
7458
  if (c_count == 1)
7459
    {
7460
      if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
7461
           is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
7462
          && atom[a_ref - 1].arom == false && het_count == 0)
7463
        /* v0.3k */
7464
        fg[fg_imine - 1] = true;
7465
    }
7466
  if (het_count == 1)
7467
    {
7468
      strcpy (nb_el, atom[a_het - 1].element);
7469
      if (!strcmp (nb_el, "O "))
7470
        {
7471
          if (is_hydroxy (a_view, a_het))
7472
            fg[fg_oxime - 1] = true;
7473
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
7474
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
7475
            fg[fg_oxime_ether - 1] = true;
7476
        }
7477
      if (!strcmp (nb_el, "N "))
7478
        {
7479
          if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
7480
              is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,
7481
                                                                    a_het) |
7482
              is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
7483
            fg[fg_hydrazone - 1] = true;
7484
          else
7485
            {
7486
              memset (nb, 0, sizeof (neighbor_rec));
7487
              get_neighbors (nb, a_het);
7488
              if (atom[a_het - 1].neighbor_count > 1)
7489
                {
7490
                  FORLIM = atom[a_het - 1].neighbor_count;
7491
                  for (i = 0; i < FORLIM; i++)
7492
                    {
7493
                      if (nb[i] != a_view)
7494
                        {
7495
                          if (is_carbamoyl (a_het, nb[i]))
7496
                            fg[fg_semicarbazone - 1] = true;
7497
                          if (is_thiocarbamoyl (a_het, nb[i]))
7498
                            fg[fg_thiosemicarbazone - 1] = true;
7499
                        }
7500
                    }
7501
                }
7502
            }
7503
        }
7504
    }                           /* v0.3k: nitro groups in "azi" form */
7505
  /* check for semicarbazone or thiosemicarbazone */
7506
  if (het_count == 2 && o_count == 2)
7507
    fg[fg_nitro_compound - 1] = true;
7508
}
7509
 
7510
 
7511
static void
7512
chk_carbonyl_deriv (a_view, a_ref)
7513
     int a_view, a_ref;
7514
{
7515
  /* a_view = C */
7516
  int i;
7517
  neighbor_rec nb;
7518
  str2 nb_el;
7519
  int c_count = 0, cn_count = 0;
7520
  char bt;                      /* new in v0.3b */
7521
  int n_db = 0;                 /* new in v0.3b */
7522
  int FORLIM;
7523
 
7524
  memset (nb, 0, sizeof (neighbor_rec));
7525
  get_neighbors (nb, a_view);
7526
  FORLIM = atom[a_view - 1].neighbor_count;
7527
  /* new in v0.3b */
7528
  for (i = 0; i < FORLIM; i++)
7529
    {
7530
      bt = bond[get_bond (a_view, nb[i]) - 1].btype;
7531
      if (bt == 'S')
7532
        {
7533
          strcpy (nb_el, atom[nb[i] - 1].element);
7534
          if (!strcmp (nb_el, "C "))
7535
            {
7536
              if (is_cyano_c (nb[i]))
7537
                cn_count++;
7538
              else
7539
                c_count++;
7540
            }
7541
        }
7542
      else
7543
        {
7544
          if (bt == 'D')
7545
            n_db++;
7546
        }
7547
    }
7548
  /* new in v0.3b */
7549
  if (is_oxo_C (a_view))
7550
    {
7551
      fg[fg_carbonyl - 1] = true;
7552
      if (c_count + cn_count < 2)
7553
        {                       /* new in v0.3b (detection of ketenes) */
7554
          if (n_db <= 1)
7555
            fg[fg_aldehyde - 1] = true;
7556
          else
7557
            fg[fg_ketene - 1] = true;
7558
        }
7559
      if (c_count == 2)
7560
        {
7561
          if (atom[a_view - 1].arom)
7562
            fg[fg_oxohetarene - 1] = true;
7563
          else
7564
            fg[fg_ketone - 1] = true;
7565
        }
7566
      if (cn_count > 0)
7567
        fg[fg_acyl_cyanide - 1] = true;
7568
    }
7569
  if (is_thioxo_C (a_view))
7570
    {
7571
      fg[fg_thiocarbonyl - 1] = true;
7572
      if (c_count < 2)
7573
        fg[fg_thioaldehyde - 1] = true;
7574
      if (c_count == 2)
7575
        {
7576
          if (atom[a_view - 1].arom)
7577
            fg[fg_thioxohetarene - 1] = true;
7578
          else
7579
            fg[fg_thioketone - 1] = true;
7580
        }
7581
    }
7582
  if (is_imino_C (a_view))
7583
    chk_imine (a_view, a_ref);
7584
}
7585
 
7586
 
7587
static void
7588
chk_carboxyl_deriv (a_view, a_ref)
7589
     int a_view, a_ref;
7590
{
7591
  int i;
7592
  neighbor_rec nb;
7593
  str2 nb_el;
7594
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 7595
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 7596
 
7597
  memset (nb, 0, sizeof (neighbor_rec));
7598
  get_neighbors (nb, a_view);
7599
  FORLIM = atom[a_view - 1].neighbor_count;
7600
  for (i = 0; i < FORLIM; i++)
7601
    {
7602
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
7603
        {
7604
          strcpy (nb_el, atom[nb[i] - 1].element);
7605
          if (strcmp (nb_el, "C "))
7606
            {
7607
              if (!strcmp (nb_el, "O "))
7608
                {
7609
                  o_count++;
7610
                  a_o = nb[i];
7611
                }
7612
              if (!strcmp (nb_el, "N "))
7613
                {
7614
                  n_count++;
7615
                  a_n = nb[i];
7616
                }
7617
              if (!strcmp (nb_el, "S "))
7618
                {
7619
                  s_count++;
7620
                  a_s = nb[i];
7621
                }
7622
            }
7623
        }
7624
    }
7625
  if (is_oxo_C (a_view))
7626
    {
7627
      if (o_count == 1)
7628
        {                       /* anhydride is checked somewhere else */
7629
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7630
            fg[fg_carboxylic_acid_deriv - 1] = true;
7631
          if (is_hydroxy (a_view, a_o))
7632
            {
7633
              if (atom[a_o - 1].formal_charge == 0)
7634
                fg[fg_carboxylic_acid - 1] = true;
7635
              if (atom[a_o - 1].formal_charge == -1)
7636
                fg[fg_carboxylic_acid_salt - 1] = true;
7637
            }
7638
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
7639
              is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o))
7640
            {
7641
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
7642
                fg[fg_carboxylic_acid_ester - 1] = true;
7643
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0)
7644
                {
7645
                  if (bond[get_bond (a_view, a_o) - 1].arom == true)
7646
                    {
7647
                      /*fg[fg_lactone_heteroarom] := true else fg[fg_lactone] := true; */
7648
                      fg[fg_oxohetarene - 1] = true;
7649
                    }
7650
                  else
7651
                    fg[fg_lactone - 1] = true;
7652
                }
7653
            }
7654
        }
7655
      if (n_count == 1)
7656
        {
7657
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7658
            fg[fg_carboxylic_acid_deriv - 1] = true;
7659
          else
7660
            {
7661
              /*fg[fg_lactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
7662
              fg[fg_oxohetarene - 1] = true;
7663
            }
7664
          if (is_amino (a_view, a_n)
7665
              || (!strcmp (atom[a_n - 1].atype, "NAM")
7666
                  && atom[a_n - 1].neighbor_count == 1))
7667
            {
7668
              fg[fg_carboxylic_acid_amide - 1] = true;
7669
              fg[fg_carboxylic_acid_prim_amide - 1] = true;
7670
            }
7671
          /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
7672
          if (is_C_monosubst_amino (a_view, a_n) &
7673
              (!is_subst_acylamino (a_view, a_n)))
7674
            {                   /* v0.3j */
7675
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7676
                fg[fg_carboxylic_acid_amide - 1] = true;
7677
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7678
                fg[fg_carboxylic_acid_sec_amide - 1] = true;
7679
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7680
                {
7681
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7682
                    {
7683
                      /*fg[fg_lactam_heteroarom]    := true else  */
7684
                      fg[fg_oxohetarene - 1] = true;
7685
                    }
7686
                  else
7687
                    fg[fg_lactam - 1] = true;
7688
                }
7689
            }
7690
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
7691
          /*   (is_diarylamino(a_view,a_n)) then  */
7692
          if (is_C_disubst_amino (a_view, a_n) &
7693
              (!is_subst_acylamino (a_view, a_n)))
7694
            {                   /* v0.3j */
7695
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7696
                fg[fg_carboxylic_acid_amide - 1] = true;
7697
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7698
                fg[fg_carboxylic_acid_tert_amide - 1] = true;
7699
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7700
                {
7701
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7702
                    {
7703
                      /*fg[fg_lactam_heteroarom]    := true else  */
7704
                      fg[fg_oxohetarene - 1] = true;
7705
                    }
7706
                  else
7707
                    fg[fg_lactam - 1] = true;
7708
                }
7709
            }
7710
          if (is_hydroxylamino (a_view, a_n))
7711
            fg[fg_hydroxamic_acid - 1] = true;
7712
          if (is_hydrazino (a_view, a_n))
7713
            fg[fg_carboxylic_acid_hydrazide - 1] = true;
7714
          if (is_azido (a_view, a_n))
7715
            fg[fg_carboxylic_acid_azide - 1] = true;
7716
        }
7717
      if (s_count == 1)
7718
        {                       /* anhydride is checked somewhere else */
7719
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7720
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7721
          if (is_sulfanyl (a_view, a_s))
7722
            fg[fg_thiocarboxylic_acid - 1] = true;
7723
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7724
            {
7725
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7726
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7727
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0)
7728
                {
7729
                  if (bond[get_bond (a_view, a_s) - 1].arom == true)
7730
                    {
7731
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7732
                      fg[fg_oxohetarene - 1] = true;
7733
                    }
7734
                  else
7735
                    fg[fg_thiolactone - 1] = true;
7736
                }
7737
            }
7738
        }
7739
    }                           /* end Oxo-C */
7740
  if (is_thioxo_C (a_view))
7741
    {
7742
      /* fg[fg_thiocarboxylic_acid_deriv]  := true; */
7743
      if (o_count == 1)
7744
        {                       /* anhydride is checked somewhere else */
7745
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7746
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7747
          if (is_hydroxy (a_view, a_o))
7748
            fg[fg_thiocarboxylic_acid - 1] = true;      /* fixed in v0.3c */
7749
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o))
7750
            {
7751
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7752
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7753
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0)
7754
                {
7755
                  if (bond[get_bond (a_view, a_o) - 1].arom == true)
7756
                    {
7757
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7758
                      fg[fg_thioxohetarene - 1] = true;
7759
                    }
7760
                  else
7761
                    fg[fg_thiolactone - 1] = true;
7762
                }
7763
            }
7764
        }
7765
      if (n_count == 1)
7766
        {
7767
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7768
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7769
          else
7770
            {
7771
              /*fg[fg_thiolactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
7772
              fg[fg_thioxohetarene - 1] = true;
7773
            }
7774
          /* catches also pyridazines, 1,2,3-triazines, etc. */
7775
          if (is_amino (a_view, a_n))
7776
            {
7777
              fg[fg_thiocarboxylic_acid_amide - 1] = true;
7778
              /* fg[fg_thiocarboxylic_acid_prim_amide] := true; */
7779
            }
7780
          /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
7781
          if (is_C_monosubst_amino (a_view, a_n) &
7782
              (!is_subst_acylamino (a_view, a_n)))
7783
            {                   /* v0.3j */
7784
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7785
                fg[fg_thiocarboxylic_acid_amide - 1] = true;
7786
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := true; */
7787
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7788
                {
7789
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7790
                    {
7791
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
7792
                      fg[fg_thioxohetarene - 1] = true;
7793
                    }
7794
                  else
7795
                    fg[fg_thiolactam - 1] = true;
7796
                }
7797
            }
7798
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
7799
          /*   (is_diarylamino(a_view,a_n)) then  */
7800
          if (is_C_disubst_amino (a_view, a_n) &
7801
              (!is_subst_acylamino (a_view, a_n)))
7802
            {                   /* v0.3j */
7803
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7804
                fg[fg_thiocarboxylic_acid_amide - 1] = true;
7805
              /*fg[fg_thiocarboxylic_acid_tert_amide] := true; */
7806
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7807
                {
7808
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7809
                    {
7810
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
7811
                      fg[fg_thioxohetarene - 1] = true;
7812
                    }
7813
                  else
7814
                    fg[fg_thiolactam - 1] = true;
7815
                }
7816
            }
7817
        }
7818
      if (s_count == 1)
7819
        {                       /* anhydride is checked somewhere else */
7820
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7821
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7822
          if (is_sulfanyl (a_view, a_s))
7823
            fg[fg_thiocarboxylic_acid - 1] = true;
7824
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7825
            {
7826
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7827
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7828
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0)
7829
                {
7830
                  if (bond[get_bond (a_view, a_s) - 1].arom == true)
7831
                    {
7832
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7833
                      fg[fg_thioxohetarene - 1] = true;
7834
                    }
7835
                  else
7836
                    fg[fg_thiolactone - 1] = true;
7837
                }
7838
            }
7839
        }
7840
    }                           /* end Thioxo-C */
7841
  if (is_true_imino_C (a_view))
7842
    {
7843
      if (o_count == 1)
7844
        {
7845
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7846
            fg[fg_carboxylic_acid_deriv - 1] = true;
7847
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o))
7848
            {
7849
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
7850
                fg[fg_imido_ester - 1] = true;
7851
            }
7852
        }
7853
      if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == false))
7854
        {
7855
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7856
            fg[fg_carboxylic_acid_deriv - 1] = true;
7857
          if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7858
            {
7859
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7860
                fg[fg_carboxylic_acid_deriv - 1] = true;
7861
              fg[fg_carboxylic_acid_amidine - 1] = true;
7862
            }
7863
          if (is_hydrazino (a_view, a_n))
7864
            {
7865
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7866
                fg[fg_carboxylic_acid_amidrazone - 1] = true;
7867
            }
7868
        }
7869
      if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == true))
7870
        /* catches also pyridazines, 1,2,3-triazines, etc. */
7871
        fg[fg_iminohetarene - 1] = true;
7872
      if (s_count == 1)
7873
        {
7874
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7875
            fg[fg_carboxylic_acid_deriv - 1] = true;
7876
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7877
            {
7878
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7879
                fg[fg_imido_thioester - 1] = true;
7880
            }
7881
        }
7882
    }
7883
  if (is_hydroximino_C (a_view))
7884
    {
7885
      if (bond[get_bond (a_view, a_n) - 1].arom == false)
7886
        fg[fg_carboxylic_acid_deriv - 1] = true;
7887
      if (o_count == 1)
7888
        {
7889
          if (is_hydroxy (a_view, a_o))
7890
            fg[fg_hydroxamic_acid - 1] = true;
7891
        }
7892
    }
7893
  if (!is_hydrazono_C (a_view))
7894
    return;
7895
  if (bond[get_bond (a_view, a_n) - 1].arom == false)
7896
    fg[fg_carboxylic_acid_deriv - 1] = true;
7897
  if (n_count == 1)
7898
    {
7899
      if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7900
        fg[fg_carboxylic_acid_amidrazone - 1] = true;
7901
    }
7902
}
7903
 
7904
 
7905
static void
7906
chk_co2_sp2 (a_view, a_ref)
7907
     int a_view, a_ref;
7908
{
7909
  int i;
7910
  neighbor_rec nb;
7911
  str2 nb_el;
7912
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
7913
    s_count = 0, sr_count = 0;
7914
  int FORLIM;
7915
 
7916
  memset (nb, 0, sizeof (neighbor_rec));
7917
  get_neighbors (nb, a_view);
7918
  FORLIM = atom[a_view - 1].neighbor_count;
7919
  for (i = 0; i < FORLIM; i++)
7920
    {
7921
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
7922
        {
7923
          strcpy (nb_el, atom[nb[i] - 1].element);
7924
          if (strcmp (nb_el, "C "))
7925
            {
7926
              if (!strcmp (nb_el, "O "))
7927
                {
7928
                  o_count++;
7929
                  if (is_alkoxy (a_view, nb[i]) |
7930
                      is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,
7931
                                                                   nb[i]))
7932
                    /* v0.3j */
7933
                    or_count++;
7934
                }
7935
              if (!strcmp (nb_el, "N "))
7936
                {
7937
                  n_count++;
7938
                  if (is_hydrazino (a_view, nb[i]))
7939
                    nn_count++;
7940
                  if (is_subst_hydrazino (a_view, nb[i]))       /* more general... */
7941
                    nnx_count++;
7942
                }
7943
              if (!strcmp (nb_el, "S "))
7944
                {
7945
                  s_count++;
7946
                  if (is_alkylsulfanyl (a_view, nb[i]) |
7947
                      is_arylsulfanyl (a_view, nb[i]))
7948
                    sr_count++;
7949
                }
7950
            }
7951
        }
7952
    }
7953
  if (is_oxo_C (a_view))
7954
    {
7955
      if (o_count == 2)
7956
        {
7957
          fg[fg_carbonic_acid_deriv - 1] = true;
7958
          if (or_count == 1)
7959
            fg[fg_carbonic_acid_monoester - 1] = true;
7960
          if (or_count == 2)
7961
            fg[fg_carbonic_acid_diester - 1] = true;
7962
        }
7963
      if (o_count == 1 && s_count == 1)
7964
        {
7965
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7966
          if (or_count + sr_count == 1)
7967
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7968
          if (or_count + sr_count == 2)
7969
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7970
        }
7971
      if (s_count == 2)
7972
        {
7973
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7974
          if (sr_count == 1)
7975
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7976
          if (sr_count == 2)
7977
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7978
        }
7979
      if (o_count == 1 && n_count == 1)
7980
        {
7981
          fg[fg_carbamic_acid_deriv - 1] = true;
7982
          if (or_count == 0)
7983
            fg[fg_carbamic_acid - 1] = true;
7984
          if (or_count == 1)
7985
            fg[fg_carbamic_acid_ester - 1] = true;
7986
        }
7987
      if (s_count == 1 && n_count == 1)
7988
        {
7989
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
7990
          if (sr_count == 0)
7991
            fg[fg_thiocarbamic_acid - 1] = true;
7992
          if (sr_count == 1)
7993
            fg[fg_thiocarbamic_acid_ester - 1] = true;
7994
        }
7995
      if (n_count == 2)
7996
        {
7997
          if (nn_count == 1)
7998
            fg[fg_semicarbazide - 1] = true;
7999
          else
8000
            {
8001
              if (nnx_count == 0)       /* excludes semicarbazones */
8002
                fg[fg_urea - 1] = true;
8003
            }
8004
        }
8005
    }                           /* end Oxo-C */
8006
  if (is_thioxo_C (a_view))
8007
    {
8008
      if (o_count == 2)
8009
        {
8010
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8011
          if (or_count == 1)
8012
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8013
          if (or_count == 2)
8014
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8015
        }
8016
      if (o_count == 1 && s_count == 1)
8017
        {
8018
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8019
          if (or_count + sr_count == 1)
8020
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8021
          if (or_count + sr_count == 2)
8022
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8023
        }
8024
      if (s_count == 2)
8025
        {
8026
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8027
          if (sr_count == 1)
8028
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8029
          if (sr_count == 2)
8030
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8031
        }
8032
      if (o_count == 1 && n_count == 1)
8033
        {
8034
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
8035
          if (or_count == 0)
8036
            fg[fg_thiocarbamic_acid - 1] = true;
8037
          if (or_count == 1)
8038
            fg[fg_thiocarbamic_acid_ester - 1] = true;
8039
        }
8040
      if (s_count == 1 && n_count == 1)
8041
        {
8042
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
8043
          if (sr_count == 0)
8044
            fg[fg_thiocarbamic_acid - 1] = true;
8045
          if (sr_count == 1)
8046
            fg[fg_thiocarbamic_acid_ester - 1] = true;
8047
        }
8048
      if (n_count == 2)
8049
        {
8050
          if (nn_count == 1)
8051
            fg[fg_thiosemicarbazide - 1] = true;
8052
          else
8053
            {
8054
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
8055
                fg[fg_thiourea - 1] = true;
8056
            }
8057
        }
8058
    }                           /* end Thioxo-C */
8059
  if (!
8060
      (is_true_imino_C (a_view) &
8061
       (bond[get_bond (a_view, a_ref) - 1].arom == false)))
8062
    {
8063
      return;
8064
    }                           /* end Imino-C */
8065
  if (o_count == 1 && n_count == 1)
8066
    fg[fg_isourea - 1] = true;
8067
  if (s_count == 1 && n_count == 1)
8068
    fg[fg_isothiourea - 1] = true;
8069
  if (n_count == 2)
8070
    fg[fg_guanidine - 1] = true;
8071
}
8072
 
8073
 
8074
static void
8075
chk_co2_sp (a_view, a_ref)
8076
     int a_view, a_ref;
8077
{
8078
  int i;
8079
  neighbor_rec nb;
8080
  str2 nb_el;
8081
  int o_count = 0, n_count = 0, s_count = 0;
8082
  int FORLIM;
8083
 
8084
  memset (nb, 0, sizeof (neighbor_rec));
8085
  get_neighbors (nb, a_view);
8086
  FORLIM = atom[a_view - 1].neighbor_count;
8087
  for (i = 0; i < FORLIM; i++)
8088
    {
8089
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')
8090
        {
8091
          strcpy (nb_el, atom[nb[i] - 1].element);
8092
          if (strcmp (nb_el, "C "))
8093
            {
8094
              if (!strcmp (nb_el, "O "))
8095
                o_count++;
8096
              if (!strcmp (nb_el, "N "))
8097
                n_count++;
8098
              if (!strcmp (nb_el, "S "))
8099
                s_count++;
8100
            }
8101
        }
8102
    }
8103
  if (o_count + s_count == 2)   /* new in v0.3b */
8104
    fg[fg_co2_deriv - 1] = true;
8105
  if (o_count == 1 && n_count == 1)
8106
    fg[fg_isocyanate - 1] = true;
8107
  if (s_count == 1 && n_count == 1)
8108
    fg[fg_isothiocyanate - 1] = true;
8109
  if (n_count == 2)
8110
    fg[fg_carbodiimide - 1] = true;
8111
}
8112
 
8113
 
8114
static void
8115
chk_triple (a1, a2)
8116
     int a1, a2;
8117
{
8118
  str2 a1_el, a2_el;
8119
 
8120
  strcpy (a1_el, atom[a1 - 1].element);
8121
  strcpy (a2_el, atom[a2 - 1].element);
8122
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &
8123
      (bond[get_bond (a1, a2) - 1].arom == false))
8124
    fg[fg_alkyne - 1] = true;
8125
  if (is_nitrile (a1, a2))
8126
    fg[fg_nitrile - 1] = true;
8127
  if (is_isonitrile (a1, a2))
8128
    fg[fg_isonitrile - 1] = true;
8129
  if (is_cyanate (a1, a2))
8130
    fg[fg_cyanate - 1] = true;
8131
  if (is_thiocyanate (a1, a2))
8132
    fg[fg_thiocyanate - 1] = true;
8133
}
8134
 
8135
 
8136
static void
8137
chk_ccx (a_view, a_ref)
8138
     int a_view, a_ref;
8139
{
8140
  int i;
8141
  neighbor_rec nb;
8142
  int oh_count = 0, or_count = 0, n_count = 0;
8143
  int FORLIM;
8144
 
8145
  memset (nb, 0, sizeof (neighbor_rec));
8146
  get_neighbors (nb, a_ref);
8147
  FORLIM = atom[a_ref - 1].neighbor_count;
8148
  for (i = 0; i < FORLIM; i++)
8149
    {
8150
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
8151
        {
8152
          if (is_hydroxy (a_ref, nb[i]))
8153
            oh_count++;
8154
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8155
              is_siloxy (a_ref, nb[i]))
8156
            or_count++;
8157
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8158
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8159
            n_count++;
8160
        }
8161
    }
8162
  if (oh_count == 1)
8163
    fg[fg_enol - 1] = true;
8164
  if (or_count == 1)
8165
    fg[fg_enolether - 1] = true;
8166
  if (n_count == 1)
8167
    fg[fg_enamine - 1] = true;
8168
  /* new in v0.2f   (regard anything else as an alkene) */
8169
  if (oh_count + or_count + n_count == 0)
8170
    fg[fg_alkene - 1] = true;
8171
}
8172
 
8173
 
8174
static void
8175
chk_xccx (a_view, a_ref)
8176
     int a_view, a_ref;
8177
{
8178
  int i;
8179
  neighbor_rec nb;
8180
  int oh_count = 0, or_count = 0, n_count = 0;
8181
  int FORLIM;
8182
 
8183
  memset (nb, 0, sizeof (neighbor_rec));
8184
  get_neighbors (nb, a_view);
8185
  FORLIM = atom[a_view - 1].neighbor_count;
8186
  for (i = 0; i < FORLIM; i++)
8187
    {
8188
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
8189
        {
8190
          if (is_hydroxy (a_view, nb[i]))
8191
            oh_count++;
8192
          if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
8193
              is_siloxy (a_view, nb[i]))
8194
            or_count++;
8195
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8196
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8197
            n_count++;
8198
        }
8199
    }
8200
  memset (nb, 0, sizeof (neighbor_rec));
8201
  get_neighbors (nb, a_ref);
8202
  FORLIM = atom[a_ref - 1].neighbor_count;
8203
  for (i = 0; i < FORLIM; i++)
8204
    {
8205
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
8206
        {
8207
          if (is_hydroxy (a_ref, nb[i]))
8208
            oh_count++;
8209
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8210
              is_siloxy (a_ref, nb[i]))
8211
            or_count++;
8212
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8213
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8214
            n_count++;
8215
        }
8216
    }
8217
  if (oh_count == 2)
8218
    fg[fg_enediol - 1] = true;
8219
  /* new in v0.2f   (regard anything else as an alkene) */
8220
  if (oh_count + or_count + n_count == 0)
8221
    fg[fg_alkene - 1] = true;
8222
}
8223
 
8224
 
8225
static void
8226
chk_n_o_dbl (a1, a2)
8227
     int a1, a2;
8228
{
8229
  int i;
8230
  neighbor_rec nb;
8231
  str2 nb_el;
8232
  int or_count = 0, n_count = 0, c_count = 0;
8233
  int b;                        /* v0.3j */
8234
  int het_count = 0;            /* v0.3k */
8235
  char bt;                      /* v0.3k */
8236
  float bo_sum = 0.0;           /* v0.3k */
8237
  int FORLIM;
8238
 
8239
  memset (nb, 0, sizeof (neighbor_rec));
8240
  get_neighbors (nb, a1);
8241
  FORLIM = atom[a1 - 1].neighbor_count;
8242
  /* v0.3k */
8243
  /* v0.3k */
8244
  for (i = 0; i < FORLIM; i++)
8245
    {
8246
      if (nb[i] != a2)
8247
        {
8248
          b = get_bond (a1, nb[i]);     /* v0.3j */
8249
          strcpy (nb_el, atom[nb[i] - 1].element);
8250
          bt = bond[b - 1].btype;       /* v0.3k */
8251
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
8252
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
8253
              && strcmp (nb_el, "LP") && bond[b - 1].arom == false)
8254
            /* added 'D ' in v0.3n */
8255
            het_count++;
8256
          /* v0.3k: ignore hetero atoms */
8257
          /* in aromatic rings like isoxazole  */
8258
          if (bt == 'S')
8259
            bo_sum += 1.0;
8260
          if (bt == 'D')
8261
            bo_sum += 2.0;
8262
          if (bt == 'A')
8263
            bo_sum += 1.5;
8264
          if (!strcmp (nb_el, "O "))
8265
            or_count++;
8266
          if (!strcmp (nb_el, "N "))
8267
            n_count++;
8268
          if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')        /* v0.3k */
8269
            c_count++;
8270
          /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
8271
        }
8272
    }
8273
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2)
8274
    {                           /* excludes nitro etc. */
8275
      if (or_count == 1)
8276
        fg[fg_nitrite - 1] = true;
8277
      if (c_count == 1)
8278
        fg[fg_nitroso_compound - 1] = true;
8279
      if (n_count == 1)         /* instead of nitrosamine  v0.3j */
8280
        fg[fg_nitroso_compound - 1] = true;
8281
      /*if (n_count = 1) then fg[fg_nitrosamine]   := true;  (* still missing */
8282
    }
8283
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
8284
  /*  begin */
8285
  /*    fg[fg_n_oxide] := true; */
8286
  /*  end; */
8287
  /* new approach in v0.3k */
8288
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
8289
    fg[fg_n_oxide - 1] = true;
8290
}
8291
 
8292
 
8293
static void
8294
chk_sulfoxide (a1, a2)
8295
     int a1, a2;
8296
{
8297
  int i;
8298
  neighbor_rec nb;
8299
  str2 nb_el;
8300
  int o_count = 0, c_count = 0;
8301
  int FORLIM;
8302
 
8303
  memset (nb, 0, sizeof (neighbor_rec));
8304
  get_neighbors (nb, a1);
8305
  FORLIM = atom[a1 - 1].neighbor_count;
8306
  for (i = 0; i < FORLIM; i++)
8307
    {
8308
      strcpy (nb_el, atom[nb[i] - 1].element);
8309
      if (!strcmp (nb_el, "O "))
8310
        o_count++;
8311
      if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
8312
        c_count++;
8313
    }
8314
  if (o_count == 1 && c_count == 2)
8315
    fg[fg_sulfoxide - 1] = true;
8316
}
8317
 
8318
 
8319
static void
8320
chk_double (a1, a2)
8321
     int a1, a2;
8322
{
8323
  str2 a1_el, a2_el;
8324
 
8325
  strcpy (a1_el, atom[a1 - 1].element);
8326
  strcpy (a2_el, atom[a2 - 1].element);
8327
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &
8328
      (bond[get_bond (a1, a2) - 1].arom == false))
8329
    {
8330
      if (hetbond_count (a1) == 2)
8331
        chk_carbonyl_deriv (a1, a2);
8332
      if (hetbond_count (a1) == 3)
8333
        chk_carboxyl_deriv (a1, a2);
8334
      if (hetbond_count (a1) == 4)
8335
        {
8336
          if (!strcmp (atom[a1 - 1].atype, "C2 "))
8337
            chk_co2_sp2 (a1, a2);
8338
          if (!strcmp (atom[a1 - 1].atype, "C1 "))
8339
            chk_co2_sp (a1, a2);
8340
        }
8341
    }                           /* end C=X */
8342
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
8343
       && !strcmp (atom[a2 - 1].atype,
8344
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == false))
8345
    {
8346
      if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
8347
        fg[fg_ketene_acetal_deriv - 1] = true;
8348
      if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
8349
        chk_ccx (a1, a2);
8350
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8351
        chk_xccx (a1, a2);
8352
      if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
8353
          atom[a1 - 1].arom == false && atom[a2 - 1].arom == false)
8354
        fg[fg_alkene - 1] = true;
8355
    }
8356
  if (((!strcmp (a1_el, "N ")
8357
        && !strcmp (a2_el,
8358
                    "N ")) && (hetbond_count (a1) ==
8359
                               2) && (hetbond_count (a2) ==
8360
                                      2) && (bond[get_bond (a1, a2) -
8361
                                                  1].arom == false))
8362
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
8363
    fg[fg_azo_compound - 1] = true;
8364
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
8365
    chk_n_o_dbl (a1, a2);
8366
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
8367
    chk_sulfoxide (a1, a2);
8368
}
8369
 
8370
 
8371
static void
8372
chk_c_hal (a1, a2)
8373
     int a1, a2;
8374
{
8375
  str2 a2_el;
8376
 
8377
  strcpy (a2_el, atom[a2 - 1].element);
8378
  fg[fg_halogen_deriv - 1] = true;
8379
  if (atom[a1 - 1].arom)
8380
    {
8381
      fg[fg_aryl_halide - 1] = true;
8382
      if (!strcmp (a2_el, "F "))
8383
        fg[fg_aryl_fluoride - 1] = true;
8384
      if (!strcmp (a2_el, "CL"))
8385
        fg[fg_aryl_chloride - 1] = true;
8386
      if (!strcmp (a2_el, "BR"))
8387
        fg[fg_aryl_bromide - 1] = true;
8388
      if (!strcmp (a2_el, "I "))
8389
        fg[fg_aryl_iodide - 1] = true;
8390
      return;
8391
    }
8392
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2))
8393
    {                           /* alkyl halides */
8394
      fg[fg_alkyl_halide - 1] = true;
8395
      if (!strcmp (a2_el, "F "))
8396
        fg[fg_alkyl_fluoride - 1] = true;
8397
      if (!strcmp (a2_el, "CL"))
8398
        fg[fg_alkyl_chloride - 1] = true;
8399
      if (!strcmp (a2_el, "BR"))
8400
        fg[fg_alkyl_bromide - 1] = true;
8401
      if (!strcmp (a2_el, "I "))
8402
        fg[fg_alkyl_iodide - 1] = true;
8403
    }
8404
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3))
8405
    {                           /* acyl halides and related compounds */
8406
      if (is_oxo_C (a1))
8407
        {
8408
          fg[fg_acyl_halide - 1] = true;
8409
          if (!strcmp (a2_el, "F "))
8410
            fg[fg_acyl_fluoride - 1] = true;
8411
          if (!strcmp (a2_el, "CL"))
8412
            fg[fg_acyl_chloride - 1] = true;
8413
          if (!strcmp (a2_el, "BR"))
8414
            fg[fg_acyl_bromide - 1] = true;
8415
          if (!strcmp (a2_el, "I "))
8416
            fg[fg_acyl_iodide - 1] = true;
8417
        }
8418
      if (is_thioxo_C (a1))
8419
        fg[fg_thiocarboxylic_acid_deriv - 1] = true;
8420
      if (is_imino_C (a1))
8421
        fg[fg_imidoyl_halide - 1] = true;
8422
    }
8423
  if (!
8424
      ((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
8425
       && (hetbond_count (a1) == 4)))
8426
    /* chloroformates etc. */
8427
    return;
8428
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
8429
  fg[fg_co2_deriv - 1] = true;
8430
  if (is_oxo_C (a1))
8431
    {
8432
      fg[fg_carbonic_acid_deriv - 1] = true;
8433
      if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
8434
        fg[fg_carbonic_acid_ester_halide - 1] = true;
8435
      if (is_carbamoyl (a2, a1))
8436
        {
8437
          fg[fg_carbamic_acid_deriv - 1] = true;
8438
          fg[fg_carbamic_acid_halide - 1] = true;
8439
        }
8440
    }
8441
  if (!is_thioxo_C (a1))
8442
    return;
8443
  fg[fg_thiocarbonic_acid_deriv - 1] = true;
8444
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
8445
    fg[fg_thiocarbonic_acid_ester_halide - 1] = true;
8446
  if (is_thiocarbamoyl (a2, a1))
8447
    {
8448
      fg[fg_thiocarbamic_acid_deriv - 1] = true;
8449
      fg[fg_thiocarbamic_acid_halide - 1] = true;
8450
      /* end of non-aromatic halogen compounds */
8451
    }
8452
}
8453
 
8454
 
8455
static void
8456
chk_c_o (a1, a2)
8457
     int a1, a2;
8458
{
8459
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
8460
  if (bond[get_bond (a1, a2) - 1].arom == true)
8461
    return;
8462
  if (is_true_alkyl (a2, a1) && is_hydroxy (a1, a2))
8463
    {
8464
      fg[fg_hydroxy - 1] = true;
8465
      fg[fg_alcohol - 1] = true;
8466
      if (atom[a1 - 1].neighbor_count <= 2)
8467
        fg[fg_prim_alcohol - 1] = true;
8468
      if (atom[a1 - 1].neighbor_count == 3)
8469
        fg[fg_sec_alcohol - 1] = true;
8470
      if (atom[a1 - 1].neighbor_count == 4)
8471
        fg[fg_tert_alcohol - 1] = true;
8472
    }
8473
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2))
8474
    {
8475
      fg[fg_hydroxy - 1] = true;
8476
      fg[fg_phenol - 1] = true;
8477
    }
8478
  if (is_true_alkyl (a2, a1) && is_true_alkoxy (a1, a2))
8479
    {
8480
      fg[fg_ether - 1] = true;
8481
      fg[fg_dialkylether - 1] = true;
8482
    }
8483
  if ((is_true_alkyl (a2, a1) && is_aryloxy (a1, a2)) |
8484
      (is_aryl (a2, a1) && is_true_alkoxy (a1, a2)))
8485
    {
8486
      fg[fg_ether - 1] = true;
8487
      fg[fg_alkylarylether - 1] = true;
8488
    }
8489
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2))
8490
    {
8491
      fg[fg_ether - 1] = true;
8492
      fg[fg_diarylether - 1] = true;
8493
    }
8494
  if ((is_true_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2))
8495
    {
8496
      fg[fg_ether - 1] = true;
8497
      ether_generic = true;
8498
    }
8499
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2))
8500
    {
8501
      fg[fg_hydroxy - 1] = true;
8502
      hydroxy_generic = true;
8503
    }
8504
 
8505
}
8506
 
8507
 
8508
static void
8509
chk_c_s (a1, a2)
8510
     int a1, a2;
8511
{
8512
  int i;
8513
  neighbor_rec nb;
8514
  str2 nb_el;
8515
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
8516
    hal_count = 0;
8517
  int FORLIM;
8518
 
8519
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
8520
  if (bond[get_bond (a1, a2) - 1].arom == true)
8521
    return;
8522
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2))
8523
    {
8524
      fg[fg_thiol - 1] = true;
8525
      fg[fg_alkylthiol - 1] = true;
8526
    }
8527
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2))
8528
    {
8529
      fg[fg_thiol - 1] = true;
8530
      fg[fg_arylthiol - 1] = true;
8531
    }
8532
  if (is_true_alkyl (a2, a1) && is_true_alkylsulfanyl (a1, a2))
8533
    fg[fg_thioether - 1] = true;
8534
  if ((is_true_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) |
8535
      (is_aryl (a2, a1) && is_true_alkylsulfanyl (a1, a2)))
8536
    fg[fg_thioether - 1] = true;
8537
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
8538
    fg[fg_thioether - 1] = true;
8539
  /* check for sulfinic/sulfenic acid derivatives */
8540
  memset (nb, 0, sizeof (neighbor_rec));
8541
  get_neighbors (nb, a2);
8542
  FORLIM = atom[a2 - 1].neighbor_count;
8543
  for (i = 0; i < FORLIM; i++)
8544
    {
8545
      strcpy (nb_el, atom[nb[i] - 1].element);
8546
      if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
8547
        c_count++;
8548
      if (is_hydroxy (a2, nb[i]))
8549
        oh_count++;
8550
      if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
8551
        or_count++;
8552
      if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
8553
        n_count++;
8554
      if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
8555
          !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
8556
        hal_count++;
8557
      if (!strcmp (nb_el, "O "))
8558
        o_count++;
8559
    }
8560
  if (c_count != 1)
8561
    return;
8562
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1)
8563
    {                           /* sulfinic acid && derivs */
8564
      fg[fg_sulfinic_acid_deriv - 1] = true;
8565
      if (oh_count == 1)
8566
        fg[fg_sulfinic_acid - 1] = true;
8567
      if (or_count == 1)
8568
        fg[fg_sulfinic_acid_ester - 1] = true;
8569
      if (hal_count == 1)
8570
        fg[fg_sulfinic_acid_halide - 1] = true;
8571
      if (n_count == 1)
8572
        fg[fg_sulfinic_acid_amide - 1] = true;
8573
    }
8574
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
8575
    /* sulfenic acid && derivs */
8576
    return;
8577
 
8578
  fg[fg_sulfenic_acid_deriv - 1] = true;
8579
  if (oh_count == 1)
8580
    fg[fg_sulfenic_acid - 1] = true;
8581
  if (or_count == 1)
8582
    fg[fg_sulfenic_acid_ester - 1] = true;
8583
  if (hal_count == 1)
8584
    fg[fg_sulfenic_acid_halide - 1] = true;
8585
  if (n_count == 1)
8586
    fg[fg_sulfenic_acid_amide - 1] = true;
8587
}
8588
 
8589
 
8590
static void
8591
chk_c_n (a1, a2)
8592
     int a1, a2;
8593
{
8594
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
8595
  if (atom[a2 - 1].arom == true)
8596
    return;
8597
  if (is_true_alkyl (a2, a1) && is_amino (a1, a2))
8598
    {
8599
      fg[fg_amine - 1] = true;
8600
      fg[fg_prim_amine - 1] = true;
8601
      fg[fg_prim_aliph_amine - 1] = true;
8602
    }
8603
  if (is_aryl (a2, a1) && is_amino (a1, a2))
8604
    {
8605
      fg[fg_amine - 1] = true;
8606
      fg[fg_prim_amine - 1] = true;
8607
      fg[fg_prim_arom_amine - 1] = true;
8608
    }
8609
  if (is_true_alkyl (a2, a1) && is_true_alkylamino (a1, a2))
8610
    {
8611
      fg[fg_amine - 1] = true;
8612
      fg[fg_sec_amine - 1] = true;
8613
      fg[fg_sec_aliph_amine - 1] = true;
8614
    }
8615
  if (is_aryl (a2, a1) && is_true_alkylamino (a1, a2))
8616
    {
8617
      fg[fg_amine - 1] = true;
8618
      fg[fg_sec_amine - 1] = true;
8619
      fg[fg_sec_mixed_amine - 1] = true;
8620
    }
8621
  if (is_aryl (a2, a1) && is_arylamino (a1, a2))
8622
    {
8623
      fg[fg_amine - 1] = true;
8624
      fg[fg_sec_amine - 1] = true;
8625
      fg[fg_sec_arom_amine - 1] = true;
8626
    }
8627
  if (is_true_alkyl (a2, a1) && is_true_dialkylamino (a1, a2))
8628
    {
8629
      fg[fg_amine - 1] = true;
8630
      fg[fg_tert_amine - 1] = true;
8631
      fg[fg_tert_aliph_amine - 1] = true;
8632
    }
8633
  if ((is_true_alkyl (a2, a1) && is_diarylamino (a1, a2)) |
8634
      (is_aryl (a2, a1) && is_true_dialkylamino (a1, a2)))
8635
    {
8636
      fg[fg_amine - 1] = true;
8637
      fg[fg_tert_amine - 1] = true;
8638
      fg[fg_tert_mixed_amine - 1] = true;
8639
    }
8640
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2))
8641
    {
8642
      fg[fg_amine - 1] = true;
8643
      fg[fg_tert_amine - 1] = true;
8644
      fg[fg_tert_arom_amine - 1] = true;
8645
    }
8646
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8647
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2,
8648
                                                                          a1)
8649
                                                             == false))
8650
    /* v0.3k */
8651
    fg[fg_hydroxylamine - 1] = true;
8652
  /* v0.3k */
8653
  /* v0.3k  */
8654
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) |
8655
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
8656
    fg[fg_hydrazine - 1] = true;
8657
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8658
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
8659
    /* v0.3k */
8660
    fg[fg_azide - 1] = true;
8661
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8662
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
8663
    /* v0.3k */
8664
    fg[fg_diazonium_salt - 1] = true;
8665
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8666
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
8667
    /* v0.3k */
8668
    fg[fg_nitro_compound - 1] = true;
8669
  if (is_alkynyl (a2, a1) &
8670
      (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
8671
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2)))))
8672
    {
8673
      fg[fg_amine - 1] = true;
8674
      amine_generic = true;
8675
    }
8676
}
8677
 
8678
 
8679
static void
8680
chk_c_c (a1, a2)
8681
     int a1, a2;
8682
{
8683
  int i;
8684
  neighbor_rec nb;
8685
  int oh_count, nhr_count, FORLIM;
8686
 
8687
  /* ignore aromatic rings */
8688
  if (atom[a2 - 1].arom == true)
8689
    return;
8690
  /*check for 1,2-diols and 1,2-aminoalcoholes */
8691
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
8692
      && !strcmp (atom[a2 - 1].atype, "C3 "))
8693
    {
8694
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8695
        {
8696
          oh_count = 0;
8697
          nhr_count = 0;
8698
          memset (nb, 0, sizeof (neighbor_rec));
8699
          get_neighbors (nb, a1);
8700
          FORLIM = atom[a1 - 1].neighbor_count;
8701
          for (i = 0; i < FORLIM; i++)
8702
            {
8703
              if (nb[i] != a2)
8704
                {
8705
                  if (is_hydroxy (a1, nb[i]))
8706
                    oh_count++;
8707
                  if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
8708
                      is_arylamino (a1, nb[i]))
8709
                    nhr_count++;
8710
                }
8711
            }
8712
          memset (nb, 0, sizeof (neighbor_rec));
8713
          get_neighbors (nb, a2);
8714
          FORLIM = atom[a2 - 1].neighbor_count;
8715
          for (i = 0; i < FORLIM; i++)
8716
            {
8717
              if (nb[i] != a1)
8718
                {
8719
                  if (is_hydroxy (a2, nb[i]))
8720
                    oh_count++;
8721
                  if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
8722
                      is_arylamino (a2, nb[i]))
8723
                    nhr_count++;
8724
                }
8725
            }
8726
          if (oh_count == 2)
8727
            fg[fg_1_2_diol - 1] = true;
8728
          if (oh_count == 1 && nhr_count == 1)
8729
            fg[fg_1_2_aminoalcohol - 1] = true;
8730
        }
8731
    }
8732
  /* check for alpha-aminoacids and alpha-hydroxyacids */
8733
  if (strcmp (atom[a1 - 1].atype, "C3 ")
8734
      || strcmp (atom[a2 - 1].atype, "C2 "))
8735
    return;
8736
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
8737
    return;
8738
  oh_count = 0;
8739
  nhr_count = 0;
8740
  memset (nb, 0, sizeof (neighbor_rec));
8741
  get_neighbors (nb, a1);
8742
  FORLIM = atom[a1 - 1].neighbor_count;
8743
  for (i = 0; i < FORLIM; i++)
8744
    {
8745
      if (nb[i] != a2)
8746
        {
8747
          if (is_hydroxy (a1, nb[i]))
8748
            oh_count++;
8749
          if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
8750
              is_arylamino (a1, nb[i]))
8751
            nhr_count++;
8752
        }
8753
    }
8754
  memset (nb, 0, sizeof (neighbor_rec));
8755
  get_neighbors (nb, a2);
8756
  FORLIM = atom[a2 - 1].neighbor_count;
8757
  for (i = 0; i < FORLIM; i++)
8758
    {
8759
      if (nb[i] != a1)
8760
        {
8761
          if (is_hydroxy (a2, nb[i]))
8762
            oh_count++;
8763
        }
8764
    }
8765
  if ((oh_count == 2) && is_oxo_C (a2))
8766
    fg[fg_alpha_hydroxyacid - 1] = true;
8767
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
8768
    fg[fg_alpha_aminoacid - 1] = true;
8769
}
8770
 
8771
 
8772
static void
8773
chk_x_y_single (a_view, a_ref)
8774
     int a_view, a_ref;
8775
{
8776
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
8777
      !strcmp (atom[a_ref - 1].atype, "O3 "))
8778
    {
8779
      if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
8780
        fg[fg_hydroperoxide - 1] = true;
8781
      if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
8782
           is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,
8783
                                                     a_ref) |
8784
                                          is_aryloxy (a_view,
8785
                                                      a_ref) |
8786
                                          is_siloxy (a_view, a_ref)))
8787
        fg[fg_peroxide - 1] = true;
8788
    }                           /* still missing: peracid */
8789
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
8790
      !strcmp (atom[a_ref - 1].atype, "S3 "))
8791
    {
8792
      if (atom[a_view - 1].neighbor_count == 2 &&
8793
          atom[a_ref - 1].neighbor_count == 2)
8794
        fg[fg_disulfide - 1] = true;
8795
    }
8796
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
8797
       !strcmp (atom[a_ref - 1].element,
8798
                "N ")) && (hetbond_count (a_view) ==
8799
                           1) && (hetbond_count (a_ref) == 1))
8800
    {
8801
      /*if ((is_amino(a_ref,a_view)) or  */
8802
      /*    (is_subst_amino(a_ref,a_view)) or */
8803
      /*    (is_acylamino(a_ref,a_view))) and */
8804
      /*   ((is_amino(a_view,a_ref)) or  */
8805
      /*    (is_subst_amino(a_view,a_ref)) or */
8806
      /*    (is_acylamino(a_ref,a_view))) then  */
8807
      if (bond[get_bond (a_view, a_ref) - 1].arom == false)
8808
        fg[fg_hydrazine - 1] = true;
8809
    }
8810
  if (!strcmp (atom[a_view - 1].element, "N ") &&
8811
      !strcmp (atom[a_ref - 1].atype, "O3 "))
8812
    {                           /* bond is in "opposite" direction */
8813
      if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &
8814
          is_nitro (a_ref, a_view))
8815
        fg[fg_nitrate - 1] = true;
8816
      if ((is_nitro (a_ref, a_view) == false
8817
           && atom[a_view - 1].arom == false) && (is_amino (a_ref,
8818
                                                            a_view) |
8819
                                                  is_subst_amino (a_ref,
8820
                                                                  a_view)) &
8821
          (is_acylamino (a_ref, a_view) == false))
8822
        fg[fg_hydroxylamine - 1] = true;        /* new in v0.3c */
8823
    }
8824
  if (!strcmp (atom[a_view - 1].element, "S ") &&
8825
      !strcmp (atom[a_ref - 1].element, "O "))
8826
    chk_sulfoxide (a_view, a_ref);
8827
}
8828
 
8829
 
8830
static void
8831
chk_single (a1, a2)
8832
     int a1, a2;
8833
{
8834
  str2 a1_el, a2_el;
8835
 
8836
  strcpy (a1_el, atom[a1 - 1].element);
8837
  strcpy (a2_el, atom[a2 - 1].element);
8838
  if (!strcmp (a1_el, "C ") &&
8839
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
8840
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
8841
    chk_c_hal (a1, a2);
8842
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
8843
    chk_c_o (a1, a2);
8844
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
8845
    chk_c_s (a1, a2);
8846
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
8847
    chk_c_n (a1, a2);
8848
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) ==
8849
                                                            false))
8850
    {
8851
      fg[fg_organometallic - 1] = true;
8852
      if (!strcmp (a2_el, "LI"))
8853
        fg[fg_organolithium - 1] = true;
8854
      if (!strcmp (a2_el, "MG"))
8855
        fg[fg_organomagnesium - 1] = true;
8856
    }
8857
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
8858
    chk_c_c (a1, a2);
8859
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
8860
    chk_x_y_single (a1, a2);
8861
}
8862
 
8863
 
8864
static void
8865
chk_carbonyl_deriv_sp3 (a_ref)
8866
     int a_ref;
8867
{
8868
  int i;
8869
  neighbor_rec nb;
8870
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
8871
  int FORLIM;
8872
 
8873
  memset (nb, 0, sizeof (neighbor_rec));
8874
  get_neighbors (nb, a_ref);
8875
  FORLIM = atom[a_ref - 1].neighbor_count;
8876
  for (i = 0; i < FORLIM; i++)
8877
    {
8878
      if (is_hydroxy (a_ref, nb[i]))
8879
        oh_count++;
8880
      if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8881
          is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
8882
        or_count++;
8883
      if (is_sulfanyl (a_ref, nb[i]))
8884
        sh_count++;
8885
      if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
8886
          is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref,
8887
                                                                   nb[i]))
8888
        sr_count++;
8889
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8890
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
8891
        n_count++;
8892
    }
8893
  if (oh_count == 2)
8894
    fg[fg_carbonyl_hydrate - 1] = true;
8895
  if (oh_count == 1 && or_count == 1)
8896
    fg[fg_hemiacetal - 1] = true;
8897
  if (or_count == 2)
8898
    fg[fg_acetal - 1] = true;
8899
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
8900
    fg[fg_hemiaminal - 1] = true;
8901
  if (n_count == 2)
8902
    fg[fg_aminal - 1] = true;
8903
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
8904
    fg[fg_thiohemiaminal - 1] = true;
8905
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
8906
    fg[fg_thioacetal - 1] = true;
8907
}
8908
 
8909
 
8910
static void
8911
chk_carboxyl_deriv_sp3 (a_ref)
8912
     int a_ref;
8913
{
8914
  int i;
8915
  neighbor_rec nb;
8916
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
8917
  int electroneg_count = 0;     /* new in v0.3j */
8918
  int hal_count = 0;
8919
  str2 nb_el;
8920
  int FORLIM;
8921
 
8922
  memset (nb, 0, sizeof (neighbor_rec));
8923
  get_neighbors (nb, a_ref);
8924
  FORLIM = atom[a_ref - 1].neighbor_count;
8925
  for (i = 0; i < FORLIM; i++)
8926
    {
8927
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3j */
8928
      if (is_electroneg (nb_el))
8929
        electroneg_count++;
8930
      if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
8931
          !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
8932
          || !strcmp (nb_el, "AT"))
8933
        hal_count++;
8934
      if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8935
          is_siloxy (a_ref, nb[i]))
8936
        or_count++;
8937
      if (is_hydroxy (a_ref, nb[i]))    /* new in v0.3c    */
8938
        oh_count++;
8939
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8940
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
8941
        n_count++;
8942
    }
8943
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := true;  (* until v0.3i */
8944
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
8945
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
8946
  if (or_count == 3)
8947
    fg[fg_carboxylic_acid_orthoester - 1] = true;
8948
  if (or_count == 2 && n_count == 1)
8949
    fg[fg_carboxylic_acid_amide_acetal - 1] = true;
8950
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
8951
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
8952
}
8953
 
8954
 
8955
static void
8956
chk_anhydride (a_ref)
8957
     int a_ref;
8958
{
8959
  int i;
8960
  neighbor_rec nb;
8961
  int acyl_count = 0;
8962
  int FORLIM;
8963
 
8964
  memset (nb, 0, sizeof (neighbor_rec));
8965
  get_neighbors (nb, a_ref);
8966
  FORLIM = atom[a_ref - 1].neighbor_count;
8967
  for (i = 0; i < FORLIM; i++)
8968
    {
8969
      if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
8970
        acyl_count++;
8971
    }
8972
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 "))
8973
    {
8974
      fg[fg_carboxylic_acid_deriv - 1] = true;
8975
      fg[fg_carboxylic_acid_anhydride - 1] = true;
8976
    }
8977
}
8978
 
8979
 
8980
static void
8981
chk_imide (a_ref)
8982
     int a_ref;
8983
{
8984
  int i;
8985
  neighbor_rec nb;
8986
  int acyl_count = 0;
8987
  int FORLIM;
8988
 
8989
  memset (nb, 0, sizeof (neighbor_rec));
8990
  get_neighbors (nb, a_ref);
8991
  FORLIM = atom[a_ref - 1].neighbor_count;
8992
  for (i = 0; i < FORLIM; i++)
8993
    {
8994
      if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))    /* v0.3j */
8995
        acyl_count++;
8996
    }
8997
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
8998
    /* v0.3j: accept also N-acyl-imides */
8999
    return;
9000
  fg[fg_carboxylic_acid_deriv - 1] = true;
9001
  fg[fg_carboxylic_acid_imide - 1] = true;
9002
  if (atom[a_ref - 1].neighbor_count == 2)
9003
    fg[fg_carboxylic_acid_unsubst_imide - 1] = true;
9004
  if (atom[a_ref - 1].neighbor_count == 3)
9005
    fg[fg_carboxylic_acid_subst_imide - 1] = true;
9006
}
9007
 
9008
 
9009
static void
9010
chk_12diphenol (a_view, a_ref)
9011
     int a_view, a_ref;
9012
{
9013
  int i;
9014
  neighbor_rec nb;
9015
  int oh_count = 0;
9016
  int FORLIM;
9017
 
9018
  memset (nb, 0, sizeof (neighbor_rec));
9019
  get_neighbors (nb, a_view);
9020
  FORLIM = atom[a_view - 1].neighbor_count;
9021
  for (i = 0; i < FORLIM; i++)
9022
    {
9023
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
9024
        {
9025
          if (is_hydroxy (a_view, nb[i]))
9026
            oh_count++;
9027
        }
9028
    }
9029
  memset (nb, 0, sizeof (neighbor_rec));
9030
  get_neighbors (nb, a_ref);
9031
  FORLIM = atom[a_ref - 1].neighbor_count;
9032
  for (i = 0; i < FORLIM; i++)
9033
    {
9034
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
9035
        {
9036
          if (is_hydroxy (a_ref, nb[i]))
9037
            oh_count++;
9038
        }
9039
    }
9040
  if (oh_count == 2)
9041
    fg[fg_1_2_diphenol - 1] = true;
9042
}
9043
 
9044
 
9045
static void
9046
chk_arom_fg (a1, a2)
9047
     int a1, a2;
9048
{
9049
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
9050
    chk_12diphenol (a1, a2);
9051
}
9052
 
9053
 
9054
static boolean
9055
is_arene (r_id)
9056
     int r_id;
9057
{
9058
  int i, j;
9059
  boolean r = true;
9060
  ringpath_type testring;
9061
  int ring_size, a_prev, a_ref;
9062
 
9063
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
9064
  if (r_id < 1 || r_id > n_rings)
9065
    return false;
9066
  memset (testring, 0, sizeof (ringpath_type));
9067
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9068
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9069
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9070
    testring[j] = ring[r_id - 1][j];
9071
  /*ring_size := path_length(testring); */
9072
  if (ring_size <= 2)
9073
    return false;
9074
  a_prev = testring[ring_size - 1];
9075
  for (i = 0; i < ring_size; i++)
9076
    {
9077
      a_ref = testring[i];
9078
      if (bond[get_bond (a_prev, a_ref) - 1].arom == false)
9079
        r = false;
9080
      a_prev = a_ref;
9081
    }
9082
  return r;
9083
}
9084
 
9085
 
9086
static boolean
9087
is_heterocycle (r_id)
9088
     int r_id;
9089
{
9090
  int i, j;
9091
  boolean r = false;
9092
  ringpath_type testring;
9093
  int ring_size, a_ref;
9094
 
9095
  if (r_id < 1 || r_id > n_rings)
9096
    return false;
9097
  memset (testring, 0, sizeof (ringpath_type));
9098
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9099
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9100
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9101
    testring[j] = ring[r_id - 1][j];
9102
  /*ring_size := path_length(testring); */
9103
  if (ring_size <= 2)
9104
    return false;
9105
  for (i = 0; i < ring_size; i++)
9106
    {
9107
      a_ref = testring[i];
9108
      if (strcmp (atom[a_ref - 1].element, "C "))
9109
        r = true;
9110
    }
9111
  return r;
9112
}
9113
 
9114
 
9115
static void
9116
chk_oxo_thioxo_imino_hetarene (r_id)
9117
     int r_id;
9118
{
9119
  int i, j;
9120
  ringpath_type testring;
9121
  int ring_size, a_ref;
9122
 
9123
  if (r_id < 1 || r_id > n_rings)
9124
    return;
9125
  memset (testring, 0, sizeof (ringpath_type));
9126
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9127
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9128
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9129
    testring[j] = ring[r_id - 1][j];
9130
  /*ring_size := path_length(testring); */
9131
  /*if (is_arene(r_id)) and (odd(ring_size) = false) then */
9132
  if (!is_arene (r_id))         /* v0.3j */
9133
    return;
9134
  for (i = 0; i < ring_size; i++)
9135
    {
9136
      a_ref = testring[i];
9137
      if (is_oxo_C (a_ref))
9138
        fg[fg_oxohetarene - 1] = true;
9139
      if (is_thioxo_C (a_ref))
9140
        fg[fg_thioxohetarene - 1] = true;
9141
      if (is_true_exocyclic_imino_C (a_ref, r_id))      /* v0.3j */
9142
        fg[fg_iminohetarene - 1] = true;
9143
    }
9144
}
9145
 
9146
 
9147
static void
9148
chk_ion (a_ref)
9149
     int a_ref;
9150
{
9151
  int i;
9152
  neighbor_rec nb;
9153
  int charge, FORLIM;
9154
 
9155
  memset (nb, 0, sizeof (neighbor_rec));
9156
  get_neighbors (nb, a_ref);
9157
  charge = atom[a_ref - 1].formal_charge;
9158
  if (charge == 0)
9159
    /* check if charge is neutralized by an adjacent opposite charge */
9160
    return;
9161
  FORLIM = atom[a_ref - 1].neighbor_count;
9162
  for (i = 0; i < FORLIM; i++)
9163
    charge += atom[nb[i] - 1].formal_charge;
9164
  if (charge > 0)
9165
    fg[fg_cation - 1] = true;
9166
  if (charge < 0)
9167
    fg[fg_anion - 1] = true;
9168
}
9169
 
9170
 
9171
static void
9172
chk_functionalgroups ()
9173
{
9174
  int i, a1, a2;
9175
  char bt;
9176
  int pos_chg = 0, neg_chg = 0;
9177
  int FORLIM;
9178
 
9179
  if (n_atoms < 1 || n_bonds < 1)
9180
    return;
9181
  FORLIM = n_atoms;
9182
  for (i = 1; i <= FORLIM; i++)
9183
    {                           /* a few groups are best discovered in the atom list */
9184
      if (!strcmp (atom[i - 1].atype, "SO2"))
9185
        chk_so2_deriv (i);
9186
      /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := true;  (* do another check in the bond list!! */
9187
      if (!strcmp (atom[i - 1].element, "P "))
9188
        chk_p_deriv (i);
9189
      if (!strcmp (atom[i - 1].element, "B "))
9190
        chk_b_deriv (i);
9191
      if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
9192
        chk_ammon (i);
9193
      if ((strcmp (atom[i - 1].atype, "C3 ") == 0)
9194
          && (hetbond_count (i) == 2))
9195
        chk_carbonyl_deriv_sp3 (i);
9196
      if ((strcmp (atom[i - 1].atype, "C3 ") == 0)
9197
          && (hetbond_count (i) == 3))
9198
        chk_carboxyl_deriv_sp3 (i);
9199
      if (!strcmp (atom[i - 1].atype, "O3 ")
9200
          && atom[i - 1].neighbor_count == 2)
9201
        chk_anhydride (i);
9202
      if ((!strcmp (atom[i - 1].atype, "N3 ")
9203
           || !strcmp (atom[i - 1].atype, "NAM"))
9204
          && atom[i - 1].neighbor_count >= 2)
9205
        chk_imide (i);
9206
      if (atom[i - 1].formal_charge > 0)
9207
        pos_chg += atom[i - 1].formal_charge;
9208
      if (atom[i - 1].formal_charge < 0)
9209
        neg_chg += atom[i - 1].formal_charge;
9210
      chk_ion (i);
9211
    }
9212
  FORLIM = n_bonds;
9213
  for (i = 0; i < FORLIM; i++)
9214
    {                           /* most groups are best discovered in the bond list */
9215
      a1 = bond[i].a1;
9216
      a2 = bond[i].a2;
9217
      bt = bond[i].btype;
9218
      if (atom[a1 - 1].heavy && atom[a2 - 1].heavy)
9219
        {
9220
          orient_bond (&a1, &a2);
9221
          if (bt == 'T')
9222
            chk_triple (a1, a2);
9223
          if (bt == 'D')
9224
            chk_double (a1, a2);
9225
          if (bt == 'S')
9226
            chk_single (a1, a2);
9227
          if (bond[i].arom)
9228
            chk_arom_fg (a1, a2);
9229
        }
9230
    }
9231
  if (n_rings > 0)
9232
    {
9233
      FORLIM = n_rings;
9234
      for (i = 1; i <= FORLIM; i++)
9235
        {
9236
          chk_oxo_thioxo_imino_hetarene (i);
9237
          if (is_arene (i))
9238
            fg[fg_aromatic - 1] = true;
9239
          if (is_heterocycle (i))
9240
            fg[fg_heterocycle - 1] = true;
9241
        }
9242
    }
9243
  if (pos_chg + neg_chg > 0)
9244
    fg[fg_cation - 1] = true;
9245
  if (pos_chg + neg_chg < 0)
9246
    fg[fg_anion - 1] = true;
9247
}
9248
 
9249
 
9250
static void
9251
write_fg_text ()
9252
{
9253
  if (fg[fg_cation - 1])
9254
    printf ("cation\n");
9255
  if (fg[fg_anion - 1])
9256
    printf ("anion\n");
9257
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
9258
  if (fg[fg_aldehyde - 1])
9259
    printf ("aldehyde\n");
9260
  if (fg[fg_ketone - 1])
9261
    printf ("ketone\n");
9262
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
9263
  if (fg[fg_thioaldehyde - 1])
9264
    printf ("thioaldehyde\n");
9265
  if (fg[fg_thioketone - 1])
9266
    printf ("thioketone\n");
9267
  if (fg[fg_imine - 1])
9268
    printf ("imine\n");
9269
  if (fg[fg_hydrazone - 1])
9270
    printf ("hydrazone\n");
9271
  if (fg[fg_semicarbazone - 1])
9272
    printf ("semicarbazone\n");
9273
  if (fg[fg_thiosemicarbazone - 1])
9274
    printf ("thiosemicarbazone\n");
9275
  if (fg[fg_oxime - 1])
9276
    printf ("oxime\n");
9277
  if (fg[fg_oxime_ether - 1])
9278
    printf ("oxime ether\n");
9279
  if (fg[fg_ketene - 1])
9280
    printf ("ketene\n");
9281
  if (fg[fg_ketene_acetal_deriv - 1])
9282
    printf ("ketene acetal or derivative\n");
9283
  if (fg[fg_carbonyl_hydrate - 1])
9284
    printf ("carbonyl hydrate\n");
9285
  if (fg[fg_hemiacetal - 1])
9286
    printf ("hemiacetal\n");
9287
  if (fg[fg_acetal - 1])
9288
    printf ("acetal\n");
9289
  if (fg[fg_hemiaminal - 1])
9290
    printf ("hemiaminal\n");
9291
  if (fg[fg_aminal - 1])
9292
    printf ("aminal\n");
9293
  if (fg[fg_thiohemiaminal - 1])
9294
    printf ("hemithioaminal\n");
9295
  if (fg[fg_thioacetal - 1])
9296
    printf ("thioacetal\n");
9297
  if (fg[fg_enamine - 1])
9298
    printf ("enamine\n");
9299
  if (fg[fg_enol - 1])
9300
    printf ("enol\n");
9301
  if (fg[fg_enolether - 1])
9302
    printf ("enol ether\n");
9303
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9304
    printf ("hydroxy compound\n");
9305
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
9306
  if (fg[fg_prim_alcohol - 1])
9307
    printf ("primary alcohol\n");
9308
  if (fg[fg_sec_alcohol - 1])
9309
    printf ("secondary alcohol\n");
9310
  if (fg[fg_tert_alcohol - 1])
9311
    printf ("tertiary alcohol\n");
9312
  if (fg[fg_1_2_diol - 1])
9313
    printf ("1,2-diol\n");
9314
  if (fg[fg_1_2_aminoalcohol - 1])
9315
    printf ("1,2-aminoalcohol\n");
9316
  if (fg[fg_phenol - 1])
9317
    printf ("phenol or hydroxyhetarene\n");
9318
  if (fg[fg_1_2_diphenol - 1])
9319
    printf ("1,2-diphenol\n");
9320
  if (fg[fg_enediol - 1])
9321
    printf ("enediol\n");
9322
  if (fg[fg_ether - 1] && ether_generic)
9323
    printf ("ether\n");
9324
  if (fg[fg_dialkylether - 1])
9325
    printf ("dialkyl ether\n");
9326
  if (fg[fg_alkylarylether - 1])
9327
    printf ("alkyl aryl ether \n");
9328
  if (fg[fg_diarylether - 1])
9329
    printf ("diaryl ether\n");
9330
  if (fg[fg_thioether - 1])
9331
    printf ("thioether\n");
9332
  if (fg[fg_disulfide - 1])
9333
    printf ("disulfide\n");
9334
  if (fg[fg_peroxide - 1])
9335
    printf ("peroxide\n");
9336
  if (fg[fg_hydroperoxide - 1])
9337
    printf ("hydroperoxide \n");
9338
  if (fg[fg_hydrazine - 1])
9339
    printf ("hydrazine derivative\n");
9340
  if (fg[fg_hydroxylamine - 1])
9341
    printf ("hydroxylamine\n");
9342
  if (fg[fg_amine - 1] && amine_generic)
9343
    printf ("amine\n");
9344
  if (fg[fg_prim_amine - 1])
9345
    printf ("primary amine\n");
9346
  if (fg[fg_prim_aliph_amine - 1])
9347
    printf ("primary aliphatic amine (alkylamine)\n");
9348
  if (fg[fg_prim_arom_amine - 1])
9349
    printf ("primary aromatic amine\n");
9350
  if (fg[fg_sec_amine - 1])
9351
    printf ("secondary amine\n");
9352
  if (fg[fg_sec_aliph_amine - 1])
9353
    printf ("secondary aliphatic amine (dialkylamine)\n");
9354
  if (fg[fg_sec_mixed_amine - 1])
9355
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
9356
  if (fg[fg_sec_arom_amine - 1])
9357
    printf ("secondary aromatic amine (diarylamine)\n");
9358
  if (fg[fg_tert_amine - 1])
9359
    printf ("tertiary amine\n");
9360
  if (fg[fg_tert_aliph_amine - 1])
9361
    printf ("tertiary aliphatic amine (trialkylamine)\n");
9362
  if (fg[fg_tert_mixed_amine - 1])
9363
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
9364
  if (fg[fg_tert_arom_amine - 1])
9365
    printf ("tertiary aromatic amine (triarylamine)\n");
9366
  if (fg[fg_quart_ammonium - 1])
9367
    printf ("quaternary ammonium salt\n");
9368
  if (fg[fg_n_oxide - 1])
9369
    printf ("N-oxide\n");
9370
  /* new in v0.2f */
9371
  if (fg[fg_halogen_deriv - 1])
9372
    {
9373
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
9374
          !fg[fg_acyl_halide - 1])
9375
        printf ("halogen derivative\n");
9376
    }
9377
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
9378
  if (fg[fg_alkyl_fluoride - 1])
9379
    printf ("alkyl fluoride\n");
9380
  if (fg[fg_alkyl_chloride - 1])
9381
    printf ("alkyl chloride\n");
9382
  if (fg[fg_alkyl_bromide - 1])
9383
    printf ("alkyl bromide\n");
9384
  if (fg[fg_alkyl_iodide - 1])
9385
    printf ("alkyl iodide\n");
9386
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
9387
  if (fg[fg_aryl_fluoride - 1])
9388
    printf ("aryl fluoride\n");
9389
  if (fg[fg_aryl_chloride - 1])
9390
    printf ("aryl chloride\n");
9391
  if (fg[fg_aryl_bromide - 1])
9392
    printf ("aryl bromide\n");
9393
  if (fg[fg_aryl_iodide - 1])
9394
    printf ("aryl iodide\n");
9395
  if (fg[fg_organometallic - 1])
9396
    printf ("organometallic compound\n");
9397
  if (fg[fg_organolithium - 1])
9398
    printf ("organolithium compound\n");
9399
  if (fg[fg_organomagnesium - 1])
9400
    printf ("organomagnesium compound\n");
9401
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
9402
  if (fg[fg_carboxylic_acid - 1])
9403
    printf ("carboxylic acid\n");
9404
  if (fg[fg_carboxylic_acid_salt - 1])
9405
    printf ("carboxylic acid salt\n");
9406
  if (fg[fg_carboxylic_acid_ester - 1])
9407
    printf ("carboxylic acid ester\n");
9408
  if (fg[fg_lactone - 1])
9409
    printf ("lactone\n");
9410
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
9411
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9412
    printf ("primary carboxylic acid amide\n");
9413
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9414
    printf ("secondary carboxylic acid amide\n");
9415
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9416
    printf ("tertiary carboxylic acid amide\n");
9417
  if (fg[fg_lactam - 1])
9418
    printf ("lactam\n");
9419
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9420
    printf ("carboxylic acid hydrazide\n");
9421
  if (fg[fg_carboxylic_acid_azide - 1])
9422
    printf ("carboxylic acid azide\n");
9423
  if (fg[fg_hydroxamic_acid - 1])
9424
    printf ("hydroxamic acid\n");
9425
  if (fg[fg_carboxylic_acid_amidine - 1])
9426
    printf ("carboxylic acid amidine\n");
9427
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9428
    printf ("carboxylic acid amidrazone\n");
9429
  if (fg[fg_nitrile - 1])
9430
    printf ("carbonitrile\n");
9431
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
9432
  if (fg[fg_acyl_fluoride - 1])
9433
    printf ("acyl fluoride\n");
9434
  if (fg[fg_acyl_chloride - 1])
9435
    printf ("acyl chloride\n");
9436
  if (fg[fg_acyl_bromide - 1])
9437
    printf ("acyl bromide\n");
9438
  if (fg[fg_acyl_iodide - 1])
9439
    printf ("acyl iodide\n");
9440
  if (fg[fg_acyl_cyanide - 1])
9441
    printf ("acyl cyanide\n");
9442
  if (fg[fg_imido_ester - 1])
9443
    printf ("imido ester\n");
9444
  if (fg[fg_imidoyl_halide - 1])
9445
    printf ("imidoyl halide\n");
9446
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
9447
  if (fg[fg_thiocarboxylic_acid - 1])
9448
    printf ("thiocarboxylic acid\n");
9449
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9450
    printf ("thiocarboxylic acid ester\n");
9451
  if (fg[fg_thiolactone - 1])
9452
    printf ("thiolactone\n");
9453
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9454
    printf ("thiocarboxylic acid amide\n");
9455
  if (fg[fg_thiolactam - 1])
9456
    printf ("thiolactam\n");
9457
  if (fg[fg_imido_thioester - 1])
9458
    printf ("imidothioester\n");
9459
  if (fg[fg_oxohetarene - 1])
9460
    printf ("oxo(het)arene\n");
9461
  if (fg[fg_thioxohetarene - 1])
9462
    printf ("thioxo(het)arene\n");
9463
  if (fg[fg_iminohetarene - 1])
9464
    printf ("imino(het)arene\n");
9465
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9466
    printf ("orthocarboxylic acid derivative\n");
9467
  if (fg[fg_carboxylic_acid_orthoester - 1])
9468
    printf ("orthoester\n");
9469
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9470
    printf ("amide acetal\n");
9471
  if (fg[fg_carboxylic_acid_anhydride - 1])
9472
    printf ("carboxylic acid anhydride\n");
9473
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
9474
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9475
    printf ("carboxylic acid imide, N-unsubstituted\n");
9476
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9477
    printf ("carboxylic acid imide, N-substituted\n");
9478
  if (fg[fg_co2_deriv - 1])
9479
    printf ("CO2 derivative (general)\n");
9480
  if (fg[fg_carbonic_acid_deriv - 1] &&
9481
      !(fg[fg_carbonic_acid_monoester - 1]
9482
        || fg[fg_carbonic_acid_diester - 1]
9483
        || fg[fg_carbonic_acid_ester_halide - 1]))
9484
    /* changed in v0.3c */
9485
    printf ("carbonic acid derivative\n");
9486
  if (fg[fg_carbonic_acid_monoester - 1])
9487
    printf ("carbonic acid monoester\n");
9488
  if (fg[fg_carbonic_acid_diester - 1])
9489
    printf ("carbonic acid diester\n");
9490
  if (fg[fg_carbonic_acid_ester_halide - 1])
9491
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
9492
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9493
    printf ("thiocarbonic acid derivative\n");
9494
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9495
    printf ("thiocarbonic acid monoester\n");
9496
  if (fg[fg_thiocarbonic_acid_diester - 1])
9497
    printf ("thiocarbonic acid diester\n");
9498
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9499
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
9500
  if (fg[fg_carbamic_acid_deriv - 1]
9501
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
9502
           || fg[fg_carbamic_acid_halide - 1]))
9503
    /* changed in v0.3c */
9504
    printf ("carbamic acid derivative\n");
9505
  if (fg[fg_carbamic_acid - 1])
9506
    printf ("carbamic acid\n");
9507
  if (fg[fg_carbamic_acid_ester - 1])
9508
    printf ("carbamic acid ester (urethane)\n");
9509
  if (fg[fg_carbamic_acid_halide - 1])
9510
    printf ("carbamic acid halide (haloformic acid amide)\n");
9511
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
9512
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
9513
        || fg[fg_thiocarbamic_acid_halide - 1]))
9514
    /* changed in v0.3c */
9515
    printf ("thiocarbamic acid derivative\n");
9516
  if (fg[fg_thiocarbamic_acid - 1])
9517
    printf ("thiocarbamic acid\n");
9518
  if (fg[fg_thiocarbamic_acid_ester - 1])
9519
    printf ("thiocarbamic acid ester\n");
9520
  if (fg[fg_thiocarbamic_acid_halide - 1])
9521
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
9522
  if (fg[fg_urea - 1])
9523
    printf ("urea\n");
9524
  if (fg[fg_isourea - 1])
9525
    printf ("isourea\n");
9526
  if (fg[fg_thiourea - 1])
9527
    printf ("thiourea\n");
9528
  if (fg[fg_isothiourea - 1])
9529
    printf ("isothiourea\n");
9530
  if (fg[fg_guanidine - 1])
9531
    printf ("guanidine\n");
9532
  if (fg[fg_semicarbazide - 1])
9533
    printf ("semicarbazide\n");
9534
  if (fg[fg_thiosemicarbazide - 1])
9535
    printf ("thiosemicarbazide\n");
9536
  if (fg[fg_azide - 1])
9537
    printf ("azide\n");
9538
  if (fg[fg_azo_compound - 1])
9539
    printf ("azo compound\n");
9540
  if (fg[fg_diazonium_salt - 1])
9541
    printf ("diazonium salt\n");
9542
  if (fg[fg_isonitrile - 1])
9543
    printf ("isonitrile\n");
9544
  if (fg[fg_cyanate - 1])
9545
    printf ("cyanate\n");
9546
  if (fg[fg_isocyanate - 1])
9547
    printf ("isocyanate\n");
9548
  if (fg[fg_thiocyanate - 1])
9549
    printf ("thiocyanate\n");
9550
  if (fg[fg_isothiocyanate - 1])
9551
    printf ("isothiocyanate\n");
9552
  if (fg[fg_carbodiimide - 1])
9553
    printf ("carbodiimide\n");
9554
  if (fg[fg_nitroso_compound - 1])
9555
    printf ("nitroso compound\n");
9556
  if (fg[fg_nitro_compound - 1])
9557
    printf ("nitro compound\n");
9558
  if (fg[fg_nitrite - 1])
9559
    printf ("nitrite\n");
9560
  if (fg[fg_nitrate - 1])
9561
    printf ("nitrate\n");
9562
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
9563
  if (fg[fg_sulfuric_acid - 1])
9564
    printf ("sulfuric acid\n");
9565
  if (fg[fg_sulfuric_acid_monoester - 1])
9566
    printf ("sulfuric acid monoester\n");
9567
  if (fg[fg_sulfuric_acid_diester - 1])
9568
    printf ("sulfuric acid diester\n");
9569
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9570
    printf ("sulfuric acid amide ester\n");
9571
  if (fg[fg_sulfuric_acid_amide - 1])
9572
    printf ("sulfuric acid amide\n");
9573
  if (fg[fg_sulfuric_acid_diamide - 1])
9574
    printf ("sulfuric acid diamide\n");
9575
  if (fg[fg_sulfuryl_halide - 1])
9576
    printf ("sulfuryl halide\n");
9577
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
9578
  if (fg[fg_sulfonic_acid - 1])
9579
    printf ("sulfonic acid\n");
9580
  if (fg[fg_sulfonic_acid_ester - 1])
9581
    printf ("sulfonic acid ester\n");
9582
  if (fg[fg_sulfonamide - 1])
9583
    printf ("sulfonamide\n");
9584
  if (fg[fg_sulfonyl_halide - 1])
9585
    printf ("sulfonyl halide\n");
9586
  if (fg[fg_sulfone - 1])
9587
    printf ("sulfone\n");
9588
  if (fg[fg_sulfoxide - 1])
9589
    printf ("sulfoxide\n");
9590
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
9591
  if (fg[fg_sulfinic_acid - 1])
9592
    printf ("sulfinic acid\n");
9593
  if (fg[fg_sulfinic_acid_ester - 1])
9594
    printf ("sulfinic acid ester\n");
9595
  if (fg[fg_sulfinic_acid_halide - 1])
9596
    printf ("sulfinic acid halide\n");
9597
  if (fg[fg_sulfinic_acid_amide - 1])
9598
    printf ("sulfinic acid amide\n");
9599
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
9600
  if (fg[fg_sulfenic_acid - 1])
9601
    printf ("sulfenic acid\n");
9602
  if (fg[fg_sulfenic_acid_ester - 1])
9603
    printf ("sulfenic acid ester\n");
9604
  if (fg[fg_sulfenic_acid_halide - 1])
9605
    printf ("sulfenic acid halide\n");
9606
  if (fg[fg_sulfenic_acid_amide - 1])
9607
    printf ("sulfenic acid amide\n");
9608
  if (fg[fg_thiol - 1])
9609
    printf ("thiol (sulfanyl compound)\n");
9610
  if (fg[fg_alkylthiol - 1])
9611
    printf ("alkylthiol\n");
9612
  if (fg[fg_arylthiol - 1])
9613
    printf ("arylthiol\n");
9614
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
9615
  if (fg[fg_phosphoric_acid - 1])
9616
    printf ("phosphoric acid\n");
9617
  if (fg[fg_phosphoric_acid_ester - 1])
9618
    printf ("phosphoric acid ester\n");
9619
  if (fg[fg_phosphoric_acid_halide - 1])
9620
    printf ("phosphoric acid halide\n");
9621
  if (fg[fg_phosphoric_acid_amide - 1])
9622
    printf ("phosphoric acid amide\n");
9623
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
9624
  if (fg[fg_thiophosphoric_acid - 1])
9625
    printf ("thiophosphoric acid\n");
9626
  if (fg[fg_thiophosphoric_acid_ester - 1])
9627
    printf ("thiophosphoric acid ester\n");
9628
  if (fg[fg_thiophosphoric_acid_halide - 1])
9629
    printf ("thiophosphoric acid halide\n");
9630
  if (fg[fg_thiophosphoric_acid_amide - 1])
9631
    printf ("thiophosphoric acid amide\n");
9632
  if (fg[fg_phosphonic_acid_deriv - 1])
9633
    printf ("phosphonic acid derivative \n");
9634
  if (fg[fg_phosphonic_acid - 1])
9635
    printf ("phosphonic acid\n");
9636
  if (fg[fg_phosphonic_acid_ester - 1])
9637
    printf ("phosphonic acid ester\n");
9638
  if (fg[fg_phosphine - 1])
9639
    printf ("phosphine\n");
9640
  if (fg[fg_phosphinoxide - 1])
9641
    printf ("phosphine oxide\n");
9642
  if (fg[fg_boronic_acid_deriv - 1])
9643
    printf ("boronic acid derivative\n");
9644
  if (fg[fg_boronic_acid - 1])
9645
    printf ("boronic acid\n");
9646
  if (fg[fg_boronic_acid_ester - 1])
9647
    printf ("boronic acid ester\n");
9648
  if (fg[fg_alkene - 1])
9649
    printf ("alkene\n");
9650
  if (fg[fg_alkyne - 1])
9651
    printf ("alkyne\n");
9652
  if (fg[fg_aromatic - 1])
9653
    printf ("aromatic compound\n");
9654
  if (fg[fg_heterocycle - 1])
9655
    printf ("heterocyclic compound\n");
9656
  if (fg[fg_alpha_aminoacid - 1])
9657
    printf ("alpha-aminoacid\n");
9658
  if (fg[fg_alpha_hydroxyacid - 1])
9659
    printf ("alpha-hydroxyacid\n");
9660
}
9661
 
9662
 
9663
static void
9664
write_fg_text_de ()
9665
{
9666
  if (fg[fg_cation - 1])
9667
    printf ("Kation\n");
9668
  if (fg[fg_anion - 1])
9669
    printf ("Anion\n");
9670
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
9671
  if (fg[fg_aldehyde - 1])
9672
    printf ("Aldehyd\n");
9673
  if (fg[fg_ketone - 1])
9674
    printf ("Keton\n");
9675
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
9676
  if (fg[fg_thioaldehyde - 1])
9677
    printf ("Thioaldehyd\n");
9678
  if (fg[fg_thioketone - 1])
9679
    printf ("Thioketon\n");
9680
  if (fg[fg_imine - 1])
9681
    printf ("Imin\n");
9682
  if (fg[fg_hydrazone - 1])
9683
    printf ("Hydrazon\n");
9684
  if (fg[fg_semicarbazone - 1])
9685
    printf ("Semicarbazon\n");
9686
  if (fg[fg_thiosemicarbazone - 1])
9687
    printf ("Thiosemicarbazon\n");
9688
  if (fg[fg_oxime - 1])
9689
    printf ("Oxim\n");
9690
  if (fg[fg_oxime_ether - 1])
9691
    printf ("Oximether\n");
9692
  if (fg[fg_ketene - 1])
9693
    printf ("Keten\n");
9694
  if (fg[fg_ketene_acetal_deriv - 1])
9695
    printf ("Keten-Acetal oder Derivat\n");
9696
  if (fg[fg_carbonyl_hydrate - 1])
9697
    printf ("Carbonyl-Hydrat\n");
9698
  if (fg[fg_hemiacetal - 1])
9699
    printf ("Halbacetal\n");
9700
  if (fg[fg_acetal - 1])
9701
    printf ("Acetal\n");
9702
  if (fg[fg_hemiaminal - 1])
9703
    printf ("Halbaminal\n");
9704
  if (fg[fg_aminal - 1])
9705
    printf ("Aminal\n");
9706
  if (fg[fg_thiohemiaminal - 1])
9707
    printf ("Thiohalbaminal\n");
9708
  if (fg[fg_thioacetal - 1])
9709
    printf ("Thioacetal\n");
9710
  if (fg[fg_enamine - 1])
9711
    printf ("Enamin\n");
9712
  if (fg[fg_enol - 1])
9713
    printf ("Enol\n");
9714
  if (fg[fg_enolether - 1])
9715
    printf ("Enolether\n");
9716
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9717
    printf ("Hydroxy-Verbindung\n");
9718
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
9719
  if (fg[fg_prim_alcohol - 1])
9720
    printf ("prim\344rer Alkohol\n");
9721
/* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
9722
  if (fg[fg_sec_alcohol - 1])
9723
    printf ("sekund\344rer Alkohol\n");
9724
/* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
9725
  if (fg[fg_tert_alcohol - 1])
9726
    printf ("terti\344rer Alkohol\n");
9727
/* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
9728
  if (fg[fg_1_2_diol - 1])
9729
    printf ("1,2-Diol\n");
9730
  if (fg[fg_1_2_aminoalcohol - 1])
9731
    printf ("1,2-Aminoalkohol\n");
9732
  if (fg[fg_phenol - 1])
9733
    printf ("Phenol oder Hydroxyhetaren\n");
9734
  if (fg[fg_1_2_diphenol - 1])
9735
    printf ("1,2-Diphenol\n");
9736
  if (fg[fg_enediol - 1])
9737
    printf ("Endiol\n");
9738
  if (fg[fg_ether - 1] && ether_generic)
9739
    printf ("Ether\n");
9740
  if (fg[fg_dialkylether - 1])
9741
    printf ("Dialkylether\n");
9742
  if (fg[fg_alkylarylether - 1])
9743
    printf ("Alkylarylether \n");
9744
  if (fg[fg_diarylether - 1])
9745
    printf ("Diarylether\n");
9746
  if (fg[fg_thioether - 1])
9747
    printf ("Thioether\n");
9748
  if (fg[fg_disulfide - 1])
9749
    printf ("Disulfid\n");
9750
  if (fg[fg_peroxide - 1])
9751
    printf ("Peroxid\n");
9752
  if (fg[fg_hydroperoxide - 1])
9753
    printf ("Hydroperoxid\n");
9754
  if (fg[fg_hydrazine - 1])
9755
    printf ("Hydrazin-Derivat\n");
9756
  if (fg[fg_hydroxylamine - 1])
9757
    printf ("Hydroxylamin\n");
9758
  if (fg[fg_amine - 1] && amine_generic)
9759
    printf ("Amin\n");
9760
  if (fg[fg_prim_amine - 1])
9761
    printf ("prim\344res Amin\n");
9762
/* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
9763
  if (fg[fg_prim_aliph_amine - 1])
9764
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
9765
/* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
9766
  if (fg[fg_prim_arom_amine - 1])
9767
    printf ("prim\344res aromatisches Amin\n");
9768
/* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
9769
  if (fg[fg_sec_amine - 1])
9770
    printf ("sekund\344res Amin\n");
9771
/* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
9772
  if (fg[fg_sec_aliph_amine - 1])
9773
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
9774
/* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
9775
  if (fg[fg_sec_mixed_amine - 1])
9776
    printf
9777
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
9778
/* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
9779
  if (fg[fg_sec_arom_amine - 1])
9780
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
9781
/* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
9782
  if (fg[fg_tert_amine - 1])
9783
    printf ("terti\344res Amin\n");
9784
/* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
9785
  if (fg[fg_tert_aliph_amine - 1])
9786
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
9787
/* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
9788
  if (fg[fg_tert_mixed_amine - 1])
9789
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
9790
/* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
9791
  if (fg[fg_tert_arom_amine - 1])
9792
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
9793
/* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
9794
  if (fg[fg_quart_ammonium - 1])
9795
    printf ("quart\344res Ammoniumsalz\n");
9796
/* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
9797
  if (fg[fg_n_oxide - 1])
9798
    printf ("N-Oxid\n");
9799
  /* new in v0.2f */
9800
  if (fg[fg_halogen_deriv - 1])
9801
    {
9802
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
9803
          !fg[fg_acyl_halide - 1])
9804
        printf ("Halogenverbindung\n");
9805
    }
9806
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
9807
  if (fg[fg_alkyl_fluoride - 1])
9808
    printf ("Alkylfluorid\n");
9809
  if (fg[fg_alkyl_chloride - 1])
9810
    printf ("Alkylchlorid\n");
9811
  if (fg[fg_alkyl_bromide - 1])
9812
    printf ("Alkylbromid\n");
9813
  if (fg[fg_alkyl_iodide - 1])
9814
    printf ("Alkyliodid\n");
9815
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
9816
  if (fg[fg_aryl_fluoride - 1])
9817
    printf ("Arylfluorid\n");
9818
  if (fg[fg_aryl_chloride - 1])
9819
    printf ("Arylchlorid\n");
9820
  if (fg[fg_aryl_bromide - 1])
9821
    printf ("Arylbromid\n");
9822
  if (fg[fg_aryl_iodide - 1])
9823
    printf ("Aryliodid\n");
9824
  if (fg[fg_organometallic - 1])
9825
    printf ("Organometall-Verbindung\n");
9826
  if (fg[fg_organolithium - 1])
9827
    printf ("Organolithium-Verbindung\n");
9828
  if (fg[fg_organomagnesium - 1])
9829
    printf ("Organomagnesium-Verbindung\n");
9830
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
9831
  if (fg[fg_carboxylic_acid - 1])
9832
    printf ("Carbons\344ure\n");
9833
/* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
9834
  if (fg[fg_carboxylic_acid_salt - 1])
9835
    printf ("Carbons\344uresalz\n");
9836
/* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
9837
  if (fg[fg_carboxylic_acid_ester - 1])
9838
    printf ("Carbons\344ureester\n");
9839
/* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
9840
  if (fg[fg_lactone - 1])
9841
    printf ("Lacton\n");
9842
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
9843
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9844
    printf ("prim\344res Carbons\344ureamid\n");
9845
/* p2c: checkmol.pas, line 7340:
9846
 * Note: characters >= 128 encountered [281] */
9847
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9848
    printf ("sekund\344res Carbons\344ureamid\n");
9849
/* p2c: checkmol.pas, line 7341:
9850
 * Note: characters >= 128 encountered [281] */
9851
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9852
    printf ("terti\344res Carbons\344ureamid\n");
9853
/* p2c: checkmol.pas, line 7342:
9854
 * Note: characters >= 128 encountered [281] */
9855
  if (fg[fg_lactam - 1])
9856
    printf ("Lactam\n");
9857
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9858
    printf ("Carbons\344urehydrazid\n");
9859
/* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
9860
  if (fg[fg_carboxylic_acid_azide - 1])
9861
    printf ("Carbons\344ureazid\n");
9862
/* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
9863
  if (fg[fg_hydroxamic_acid - 1])
9864
    printf ("Hydroxams\344ure\n");
9865
/* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
9866
  if (fg[fg_carboxylic_acid_amidine - 1])
9867
    printf ("Carbons\344ureamidin\n");
9868
/* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
9869
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9870
    printf ("Carbons\344ureamidrazon\n");
9871
/* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
9872
  if (fg[fg_nitrile - 1])
9873
    printf ("Carbonitril\n");
9874
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
9875
  if (fg[fg_acyl_fluoride - 1])
9876
    printf ("Acylfluorid\n");
9877
  if (fg[fg_acyl_chloride - 1])
9878
    printf ("Acylchlorid\n");
9879
  if (fg[fg_acyl_bromide - 1])
9880
    printf ("Acylbromid\n");
9881
  if (fg[fg_acyl_iodide - 1])
9882
    printf ("Acyliodid\n");
9883
  if (fg[fg_acyl_cyanide - 1])
9884
    printf ("Acylcyanid\n");
9885
  if (fg[fg_imido_ester - 1])
9886
    printf ("Imidoester\n");
9887
  if (fg[fg_imidoyl_halide - 1])
9888
    printf ("Imidoylhalogenid\n");
9889
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
9890
  if (fg[fg_thiocarboxylic_acid - 1])
9891
    printf ("Thiocarbons\344ure\n");
9892
/* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
9893
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9894
    printf ("Thiocarbons\344ureester\n");
9895
/* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
9896
  if (fg[fg_thiolactone - 1])
9897
    printf ("Thiolacton\n");
9898
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9899
    printf ("Thiocarbons\344ureamid\n");
9900
/* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
9901
  if (fg[fg_thiolactam - 1])
9902
    printf ("Thiolactam\n");
9903
  if (fg[fg_imido_thioester - 1])
9904
    printf ("Imidothioester\n");
9905
  if (fg[fg_oxohetarene - 1])
9906
    printf ("Oxo(het)aren\n");
9907
  if (fg[fg_thioxohetarene - 1])
9908
    printf ("Thioxo(het)aren\n");
9909
  if (fg[fg_iminohetarene - 1])
9910
    printf ("Imino(het)aren\n");
9911
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9912
    printf ("Orthocarbons\344ure-Derivat\n");
9913
/* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
9914
  if (fg[fg_carboxylic_acid_orthoester - 1])
9915
    printf ("Orthoester\n");
9916
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9917
    printf ("Amidacetal\n");
9918
  if (fg[fg_carboxylic_acid_anhydride - 1])
9919
    printf ("Carbons\344ureanhydrid\n");
9920
/* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
9921
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
9922
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9923
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
9924
/* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
9925
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9926
    printf ("Carbons\344ureimid, N-substituiert\n");
9927
/* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
9928
  if (fg[fg_co2_deriv - 1])
9929
    printf ("CO2-Derivat (allgemein)\n");
9930
  if (fg[fg_carbonic_acid_deriv - 1] &&
9931
      !(fg[fg_carbonic_acid_monoester - 1]
9932
        || fg[fg_carbonic_acid_diester - 1]
9933
        || fg[fg_carbonic_acid_ester_halide - 1]))
9934
    /* changed in v0.3c */
9935
    printf ("Kohlens\344ure-Derivat\n");
9936
/* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
9937
  if (fg[fg_carbonic_acid_monoester - 1])
9938
    printf ("Kohlens\344uremonoester\n");
9939
/* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
9940
  if (fg[fg_carbonic_acid_diester - 1])
9941
    printf ("Kohlens\344urediester\n");
9942
/* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
9943
  if (fg[fg_carbonic_acid_ester_halide - 1])
9944
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
9945
/* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
9946
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9947
    printf ("Thiokohlens\344ure-Derivat\n");
9948
/* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
9949
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9950
    printf ("Thiokohlens\344uremonoester\n");
9951
/* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
9952
  if (fg[fg_thiocarbonic_acid_diester - 1])
9953
    printf ("Thiokohlens\344urediester\n");
9954
/* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
9955
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9956
    printf
9957
      ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
9958
/* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
9959
  if (fg[fg_carbamic_acid_deriv - 1] &&
9960
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
9961
        fg[fg_carbamic_acid_halide - 1]))
9962
    /* changed in v0.3c */
9963
    printf ("Carbamins\344ure-Derivat\n");
9964
/* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
9965
  if (fg[fg_carbamic_acid - 1])
9966
    printf ("Carbamins\344ure\n");
9967
/* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
9968
  if (fg[fg_carbamic_acid_ester - 1])
9969
    printf ("Carbamins\344ureester (Urethan)\n");
9970
/* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
9971
  if (fg[fg_carbamic_acid_halide - 1])
9972
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
9973
/* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
9974
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
9975
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
9976
        || fg[fg_thiocarbamic_acid_halide - 1]))
9977
    /* changed in v0.3c */
9978
    printf ("Thiocarbamins\344ure-Derivat\n");
9979
/* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
9980
  if (fg[fg_thiocarbamic_acid - 1])
9981
    printf ("Thiocarbamins\344ure\n");
9982
/* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
9983
  if (fg[fg_thiocarbamic_acid_ester - 1])
9984
    printf ("Thiocarbamins\344ureester\n");
9985
/* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
9986
  if (fg[fg_thiocarbamic_acid_halide - 1])
9987
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
9988
/* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
9989
  if (fg[fg_urea - 1])
9990
    printf ("Harnstoff\n");
9991
  if (fg[fg_isourea - 1])
9992
    printf ("Isoharnstoff\n");
9993
  if (fg[fg_thiourea - 1])
9994
    printf ("Thioharnstoff\n");
9995
  if (fg[fg_isothiourea - 1])
9996
    printf ("Isothioharnstoff\n");
9997
  if (fg[fg_guanidine - 1])
9998
    printf ("Guanidin\n");
9999
  if (fg[fg_semicarbazide - 1])
10000
    printf ("Semicarbazid\n");
10001
  if (fg[fg_thiosemicarbazide - 1])
10002
    printf ("Thiosemicarbazid\n");
10003
  if (fg[fg_azide - 1])
10004
    printf ("Azid\n");
10005
  if (fg[fg_azo_compound - 1])
10006
    printf ("Azoverbindung\n");
10007
  if (fg[fg_diazonium_salt - 1])
10008
    printf ("Diazoniumsalz\n");
10009
  if (fg[fg_isonitrile - 1])
10010
    printf ("Isonitril\n");
10011
  if (fg[fg_cyanate - 1])
10012
    printf ("Cyanat\n");
10013
  if (fg[fg_isocyanate - 1])
10014
    printf ("Isocyanat\n");
10015
  if (fg[fg_thiocyanate - 1])
10016
    printf ("Thiocyanat\n");
10017
  if (fg[fg_isothiocyanate - 1])
10018
    printf ("Isothiocyanat\n");
10019
  if (fg[fg_carbodiimide - 1])
10020
    printf ("Carbodiimid\n");
10021
  if (fg[fg_nitroso_compound - 1])
10022
    printf ("Nitroso-Verbindung\n");
10023
  if (fg[fg_nitro_compound - 1])
10024
    printf ("Nitro-Verbindung\n");
10025
  if (fg[fg_nitrite - 1])
10026
    printf ("Nitrit\n");
10027
  if (fg[fg_nitrate - 1])
10028
    printf ("Nitrat\n");
10029
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
10030
  if (fg[fg_sulfuric_acid - 1])
10031
    printf ("Schwefels\344ure\n");
10032
/* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
10033
  if (fg[fg_sulfuric_acid_monoester - 1])
10034
    printf ("Schwefels\344uremonoester\n");
10035
/* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
10036
  if (fg[fg_sulfuric_acid_diester - 1])
10037
    printf ("Schwefels\344urediester\n");
10038
/* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
10039
  if (fg[fg_sulfuric_acid_amide_ester - 1])
10040
    printf ("Schwefels\344ureamidester\n");
10041
/* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
10042
  if (fg[fg_sulfuric_acid_amide - 1])
10043
    printf ("Schwefels\344ureamid\n");
10044
/* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
10045
  if (fg[fg_sulfuric_acid_diamide - 1])
10046
    printf ("Schwefels\344urediamid\n");
10047
/* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
10048
  if (fg[fg_sulfuryl_halide - 1])
10049
    printf ("Sulfurylhalogenid\n");
10050
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
10051
  if (fg[fg_sulfonic_acid - 1])
10052
    printf ("Sulfons\344ure\n");
10053
/* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
10054
  if (fg[fg_sulfonic_acid_ester - 1])
10055
    printf ("Sulfons\344ureester\n");
10056
/* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
10057
  if (fg[fg_sulfonamide - 1])
10058
    printf ("Sulfonamid\n");
10059
  if (fg[fg_sulfonyl_halide - 1])
10060
    printf ("Sulfonylhalogenid\n");
10061
  if (fg[fg_sulfone - 1])
10062
    printf ("Sulfon\n");
10063
  if (fg[fg_sulfoxide - 1])
10064
    printf ("Sulfoxid\n");
10065
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
10066
  if (fg[fg_sulfinic_acid - 1])
10067
    printf ("Sulfins\344ure\n");
10068
/* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
10069
  if (fg[fg_sulfinic_acid_ester - 1])
10070
    printf ("Sulfins\344ureester\n");
10071
/* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
10072
  if (fg[fg_sulfinic_acid_halide - 1])
10073
    printf ("Sulfins\344urehalogenid\n");
10074
/* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
10075
  if (fg[fg_sulfinic_acid_amide - 1])
10076
    printf ("Sulfins\344ureamid\n");
10077
/* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
10078
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
10079
  if (fg[fg_sulfenic_acid - 1])
10080
    printf ("Sulfens\344ure\n");
10081
/* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
10082
  if (fg[fg_sulfenic_acid_ester - 1])
10083
    printf ("Sulfens\344ureester\n");
10084
/* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
10085
  if (fg[fg_sulfenic_acid_halide - 1])
10086
    printf ("Sulfens\344urehalogenid\n");
10087
/* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
10088
  if (fg[fg_sulfenic_acid_amide - 1])
10089
    printf ("Sulfens\344ureamid\n");
10090
/* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
10091
  if (fg[fg_thiol - 1])
10092
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
10093
  if (fg[fg_alkylthiol - 1])
10094
    printf ("Alkylthiol\n");
10095
  if (fg[fg_arylthiol - 1])
10096
    printf ("Arylthiol\n");
10097
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
10098
  if (fg[fg_phosphoric_acid - 1])
10099
    printf ("Phosphors\344ure\n");
10100
/* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
10101
  if (fg[fg_phosphoric_acid_ester - 1])
10102
    printf ("Phosphors\344ureester\n");
10103
/* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
10104
  if (fg[fg_phosphoric_acid_halide - 1])
10105
    printf ("Phosphors\344urehalogenid\n");
10106
/* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
10107
  if (fg[fg_phosphoric_acid_amide - 1])
10108
    printf ("Phosphors\344ureamid\n");
10109
/* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
10110
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
10111
  if (fg[fg_thiophosphoric_acid - 1])
10112
    printf ("Thiophosphors\344ure\n");
10113
/* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
10114
  if (fg[fg_thiophosphoric_acid_ester - 1])
10115
    printf ("Thiophosphors\344ureester\n");
10116
/* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
10117
  if (fg[fg_thiophosphoric_acid_halide - 1])
10118
    printf ("Thiophosphors\344urehalogenid\n");
10119
/* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
10120
  if (fg[fg_thiophosphoric_acid_amide - 1])
10121
    printf ("Thiophosphors\344ureamid\n");
10122
/* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
10123
  if (fg[fg_phosphonic_acid_deriv - 1])
10124
    printf ("Phosphons\344ure-Derivat \n");
10125
/* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
10126
  if (fg[fg_phosphonic_acid - 1])
10127
    printf ("Phosphons\344ure\n");
10128
/* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
10129
  if (fg[fg_phosphonic_acid_ester - 1])
10130
    printf ("Phosphons\344ureester\n");
10131
/* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
10132
  if (fg[fg_phosphine - 1])
10133
    printf ("Phosphin\n");
10134
  if (fg[fg_phosphinoxide - 1])
10135
    printf ("Phosphinoxid\n");
10136
  if (fg[fg_boronic_acid_deriv - 1])
10137
    printf ("Borons\344ure-Derivat\n");
10138
/* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
10139
  if (fg[fg_boronic_acid - 1])
10140
    printf ("Borons\344ure\n");
10141
/* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
10142
  if (fg[fg_boronic_acid_ester - 1])
10143
    printf ("Borons\344ureester\n");
10144
/* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
10145
  if (fg[fg_alkene - 1])
10146
    printf ("Alken\n");
10147
  if (fg[fg_alkyne - 1])
10148
    printf ("Alkin\n");
10149
  if (fg[fg_aromatic - 1])
10150
    printf ("aromatische Verbindung\n");
10151
  if (fg[fg_heterocycle - 1])
10152
    printf ("heterocyclische Verbindung\n");
10153
  if (fg[fg_alpha_aminoacid - 1])
10154
    printf ("alpha-Aminos\344ure\n");
10155
/* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
10156
  if (fg[fg_alpha_hydroxyacid - 1])
10157
    printf ("alpha-Hydroxys\344ure\n");
10158
/* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
10159
}
10160
 
10161
 
10162
#define sc              ';'
10163
 
10164
 
10165
static void
10166
write_fg_code ()
10167
{
10168
  if (fg[fg_cation - 1])
10169
    printf ("000000T2%c", sc);
10170
  if (fg[fg_anion - 1])
10171
    printf ("000000T1%c", sc);
10172
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
10173
  if (fg[fg_aldehyde - 1])
10174
    printf ("C2O1H000%c", sc);
10175
  if (fg[fg_ketone - 1])
10176
    printf ("C2O1C000%c", sc);
10177
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
10178
  if (fg[fg_thioaldehyde - 1])
10179
    printf ("C2S1H000%c", sc);
10180
  if (fg[fg_thioketone - 1])
10181
    printf ("C2S1C000%c", sc);
10182
  if (fg[fg_imine - 1])
10183
    printf ("C2N10000%c", sc);
10184
  if (fg[fg_hydrazone - 1])
10185
    printf ("C2N1N000%c", sc);
10186
  if (fg[fg_semicarbazone - 1])
10187
    printf ("C2NNC4ON%c", sc);
10188
  if (fg[fg_thiosemicarbazone - 1])
10189
    printf ("C2NNC4SN%c", sc);
10190
  if (fg[fg_oxime - 1])
10191
    printf ("C2N1OH00%c", sc);
10192
  if (fg[fg_oxime_ether - 1])
10193
    printf ("C2N1OC00%c", sc);
10194
  if (fg[fg_ketene - 1])
10195
    printf ("C3OC0000%c", sc);
10196
  if (fg[fg_ketene_acetal_deriv - 1])
10197
    printf ("C3OCC000%c", sc);
10198
  if (fg[fg_carbonyl_hydrate - 1])
10199
    printf ("C2O2H200%c", sc);
10200
  if (fg[fg_hemiacetal - 1])
10201
    printf ("C2O2HC00%c", sc);
10202
  if (fg[fg_acetal - 1])
10203
    printf ("C2O2CC00%c", sc);
10204
  if (fg[fg_hemiaminal - 1])
10205
    printf ("C2NOHC10%c", sc);
10206
  if (fg[fg_aminal - 1])
10207
    printf ("C2N2CC10%c", sc);
10208
  if (fg[fg_thiohemiaminal - 1])
10209
    printf ("C2NSHC10%c", sc);
10210
  if (fg[fg_thioacetal - 1])
10211
    printf ("C2S2CC00%c", sc);
10212
  if (fg[fg_enamine - 1])
10213
    printf ("C2CNH000%c", sc);
10214
  if (fg[fg_enol - 1])
10215
    printf ("C2COH000%c", sc);
10216
  if (fg[fg_enolether - 1])
10217
    printf ("C2COC000%c", sc);
10218
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
10219
    printf ("O1H00000%c", sc);
10220
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
10221
  if (fg[fg_prim_alcohol - 1])
10222
    printf ("O1H1C000%c", sc);
10223
  if (fg[fg_sec_alcohol - 1])
10224
    printf ("O1H2C000%c", sc);
10225
  if (fg[fg_tert_alcohol - 1])
10226
    printf ("O1H3C000%c", sc);
10227
  if (fg[fg_1_2_diol - 1])
10228
    printf ("O1H0CO1H%c", sc);
10229
  if (fg[fg_1_2_aminoalcohol - 1])
10230
    printf ("O1H0CN1C%c", sc);
10231
  if (fg[fg_phenol - 1])
10232
    printf ("O1H1A000%c", sc);
10233
  if (fg[fg_1_2_diphenol - 1])
10234
    printf ("O1H2A000%c", sc);
10235
  if (fg[fg_enediol - 1])
10236
    printf ("C2COH200%c", sc);
10237
  if (fg[fg_ether - 1] && ether_generic)
10238
    printf ("O1C00000%c", sc);
10239
  if (fg[fg_dialkylether - 1])
10240
    printf ("O1C0CC00%c", sc);
10241
  if (fg[fg_alkylarylether - 1])
10242
    printf ("O1C0CA00%c", sc);
10243
  if (fg[fg_diarylether - 1])
10244
    printf ("O1C0AA00%c", sc);
10245
  if (fg[fg_thioether - 1])
10246
    printf ("S1C00000%c", sc);
10247
  if (fg[fg_disulfide - 1])
10248
    printf ("S1S1C000%c", sc);
10249
  if (fg[fg_peroxide - 1])
10250
    printf ("O1O1C000%c", sc);
10251
  if (fg[fg_hydroperoxide - 1])
10252
    printf ("O1O1H000%c", sc);
10253
  if (fg[fg_hydrazine - 1])
10254
    printf ("N1N10000%c", sc);
10255
  if (fg[fg_hydroxylamine - 1])
10256
    printf ("N1O1H000%c", sc);
10257
  if (fg[fg_amine - 1] && amine_generic)
10258
    printf ("N1C00000%c", sc);
10259
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
10260
  if (fg[fg_prim_aliph_amine - 1])
10261
    printf ("N1C1C000%c", sc);
10262
  if (fg[fg_prim_arom_amine - 1])
10263
    printf ("N1C1A000%c", sc);
10264
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
10265
  if (fg[fg_sec_aliph_amine - 1])
10266
    printf ("N1C2CC00%c", sc);
10267
  if (fg[fg_sec_mixed_amine - 1])
10268
    printf ("N1C2AC00%c", sc);
10269
  if (fg[fg_sec_arom_amine - 1])
10270
    printf ("N1C2AA00%c", sc);
10271
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
10272
  if (fg[fg_tert_aliph_amine - 1])
10273
    printf ("N1C3CC00%c", sc);
10274
  if (fg[fg_tert_mixed_amine - 1])
10275
    printf ("N1C3AC00%c", sc);
10276
  if (fg[fg_tert_arom_amine - 1])
10277
    printf ("N1C3AA00%c", sc);
10278
  if (fg[fg_quart_ammonium - 1])
10279
    printf ("N1C400T2%c", sc);
10280
  if (fg[fg_n_oxide - 1])
10281
    printf ("N0O10000%c", sc);
10282
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
10283
  /* new in v0.2f */
10284
  if (fg[fg_halogen_deriv - 1])
10285
    {
10286
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
10287
          !fg[fg_acyl_halide - 1])
10288
        printf ("XX000000%c", sc);
10289
    }
10290
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
10291
  if (fg[fg_alkyl_fluoride - 1])
10292
    printf ("XF00C000%c", sc);
10293
  if (fg[fg_alkyl_chloride - 1])
10294
    printf ("XC00C000%c", sc);
10295
  if (fg[fg_alkyl_bromide - 1])
10296
    printf ("XB00C000%c", sc);
10297
  if (fg[fg_alkyl_iodide - 1])
10298
    printf ("XI00C000%c", sc);
10299
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
10300
  if (fg[fg_aryl_fluoride - 1])
10301
    printf ("XF00A000%c", sc);
10302
  if (fg[fg_aryl_chloride - 1])
10303
    printf ("XC00A000%c", sc);
10304
  if (fg[fg_aryl_bromide - 1])
10305
    printf ("XB00A000%c", sc);
10306
  if (fg[fg_aryl_iodide - 1])
10307
    printf ("XI00A000%c", sc);
10308
  if (fg[fg_organometallic - 1])
10309
    printf ("000000MX%c", sc);
10310
  if (fg[fg_organolithium - 1])
10311
    printf ("000000ML%c", sc);
10312
  if (fg[fg_organomagnesium - 1])
10313
    printf ("000000MM%c", sc);
10314
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
10315
  if (fg[fg_carboxylic_acid - 1])
10316
    printf ("C3O2H000%c", sc);
10317
  if (fg[fg_carboxylic_acid_salt - 1])
10318
    printf ("C3O200T1%c", sc);
10319
  if (fg[fg_carboxylic_acid_ester - 1])
10320
    printf ("C3O2C000%c", sc);
10321
  if (fg[fg_lactone - 1])
10322
    printf ("C3O2CZ00%c", sc);
10323
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
10324
  if (fg[fg_carboxylic_acid_prim_amide - 1])
10325
    printf ("C3ONC100%c", sc);
10326
  if (fg[fg_carboxylic_acid_sec_amide - 1])
10327
    printf ("C3ONC200%c", sc);
10328
  if (fg[fg_carboxylic_acid_tert_amide - 1])
10329
    printf ("C3ONC300%c", sc);
10330
  if (fg[fg_lactam - 1])
10331
    printf ("C3ONCZ00%c", sc);
10332
  if (fg[fg_carboxylic_acid_hydrazide - 1])
10333
    printf ("C3ONN100%c", sc);
10334
  if (fg[fg_carboxylic_acid_azide - 1])
10335
    printf ("C3ONN200%c", sc);
10336
  if (fg[fg_hydroxamic_acid - 1])
10337
    printf ("C3ONOH00%c", sc);
10338
  if (fg[fg_carboxylic_acid_amidine - 1])
10339
    printf ("C3N2H000%c", sc);
10340
  if (fg[fg_carboxylic_acid_amidrazone - 1])
10341
    printf ("C3NNN100%c", sc);
10342
  if (fg[fg_nitrile - 1])
10343
    printf ("C3N00000%c", sc);
10344
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
10345
  if (fg[fg_acyl_fluoride - 1])
10346
    printf ("C3OXF000%c", sc);
10347
  if (fg[fg_acyl_chloride - 1])
10348
    printf ("C3OXC000%c", sc);
10349
  if (fg[fg_acyl_bromide - 1])
10350
    printf ("C3OXB000%c", sc);
10351
  if (fg[fg_acyl_iodide - 1])
10352
    printf ("C3OXI000%c", sc);
10353
  if (fg[fg_acyl_cyanide - 1])
10354
    printf ("C2OC3N00%c", sc);
10355
  if (fg[fg_imido_ester - 1])
10356
    printf ("C3NOC000%c", sc);
10357
  if (fg[fg_imidoyl_halide - 1])
10358
    printf ("C3NXX000%c", sc);
10359
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
10360
  if (fg[fg_thiocarboxylic_acid - 1])
10361
    printf ("C3SOH000%c", sc);
10362
  if (fg[fg_thiocarboxylic_acid_ester - 1])
10363
    printf ("C3SOC000%c", sc);
10364
  if (fg[fg_thiolactone - 1])
10365
    printf ("C3SOCZ00%c", sc);
10366
  if (fg[fg_thiocarboxylic_acid_amide - 1])
10367
    printf ("C3SNH000%c", sc);
10368
  if (fg[fg_thiolactam - 1])
10369
    printf ("C3SNCZ00%c", sc);
10370
  if (fg[fg_imido_thioester - 1])
10371
    printf ("C3NSC000%c", sc);
10372
  if (fg[fg_oxohetarene - 1])
10373
    printf ("C3ONAZ00%c", sc);
10374
  if (fg[fg_thioxohetarene - 1])
10375
    printf ("C3SNAZ00%c", sc);
10376
  if (fg[fg_iminohetarene - 1])
10377
    printf ("C3NNAZ00%c", sc);
10378
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
10379
    printf ("C3O30000%c", sc);
10380
  if (fg[fg_carboxylic_acid_orthoester - 1])
10381
    printf ("C3O3C000%c", sc);
10382
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
10383
    printf ("C3O3NC00%c", sc);
10384
  if (fg[fg_carboxylic_acid_anhydride - 1])
10385
    printf ("C3O2C3O2%c", sc);
10386
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
10387
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
10388
    printf ("C3ONCH10%c", sc);
10389
  if (fg[fg_carboxylic_acid_subst_imide - 1])
10390
    printf ("C3ONCC10%c", sc);
10391
  if (fg[fg_co2_deriv - 1])
10392
    printf ("C4000000%c", sc);
10393
  if (fg[fg_carbonic_acid_deriv - 1])
10394
    printf ("C4O30000%c", sc);
10395
  if (fg[fg_carbonic_acid_monoester - 1])
10396
    printf ("C4O3C100%c", sc);
10397
  if (fg[fg_carbonic_acid_diester - 1])
10398
    printf ("C4O3C200%c", sc);
10399
  if (fg[fg_carbonic_acid_ester_halide - 1])
10400
    printf ("C4O3CX00%c", sc);
10401
  if (fg[fg_thiocarbonic_acid_deriv - 1])
10402
    printf ("C4SO0000%c", sc);
10403
  if (fg[fg_thiocarbonic_acid_monoester - 1])
10404
    printf ("C4SOC100%c", sc);
10405
  if (fg[fg_thiocarbonic_acid_diester - 1])
10406
    printf ("C4SOC200%c", sc);
10407
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
10408
    printf ("C4SOX_00%c", sc);
10409
  if (fg[fg_carbamic_acid_deriv - 1])
10410
    printf ("C4O2N000%c", sc);
10411
  if (fg[fg_carbamic_acid - 1])
10412
    printf ("C4O2NH00%c", sc);
10413
  if (fg[fg_carbamic_acid_ester - 1])
10414
    printf ("C4O2NC00%c", sc);
10415
  if (fg[fg_carbamic_acid_halide - 1])
10416
    printf ("C4O2NX00%c", sc);
10417
  if (fg[fg_thiocarbamic_acid_deriv - 1])
10418
    printf ("C4SN0000%c", sc);
10419
  if (fg[fg_thiocarbamic_acid - 1])
10420
    printf ("C4SNOH00%c", sc);
10421
  if (fg[fg_thiocarbamic_acid_ester - 1])
10422
    printf ("C4SNOC00%c", sc);
10423
  if (fg[fg_thiocarbamic_acid_halide - 1])
10424
    printf ("C4SNXX00%c", sc);
10425
  if (fg[fg_urea - 1])
10426
    printf ("C4O1N200%c", sc);
10427
  if (fg[fg_isourea - 1])
10428
    printf ("C4N2O100%c", sc);
10429
  if (fg[fg_thiourea - 1])
10430
    printf ("C4S1N200%c", sc);
10431
  if (fg[fg_isothiourea - 1])
10432
    printf ("C4N2S100%c", sc);
10433
  if (fg[fg_guanidine - 1])
10434
    printf ("C4N30000%c", sc);
10435
  if (fg[fg_semicarbazide - 1])
10436
    printf ("C4ON2N00%c", sc);
10437
  if (fg[fg_thiosemicarbazide - 1])
10438
    printf ("C4SN2N00%c", sc);
10439
  if (fg[fg_azide - 1])
10440
    printf ("N4N20000%c", sc);
10441
  if (fg[fg_azo_compound - 1])
10442
    printf ("N2N10000%c", sc);
10443
  if (fg[fg_diazonium_salt - 1])
10444
    printf ("N3N100T2%c", sc);
10445
  if (fg[fg_isonitrile - 1])
10446
    printf ("N3C10000%c", sc);
10447
  if (fg[fg_cyanate - 1])
10448
    printf ("C4NO1000%c", sc);
10449
  if (fg[fg_isocyanate - 1])
10450
    printf ("C4NO2000%c", sc);
10451
  if (fg[fg_thiocyanate - 1])
10452
    printf ("C4NS1000%c", sc);
10453
  if (fg[fg_isothiocyanate - 1])
10454
    printf ("C4NS2000%c", sc);
10455
  if (fg[fg_carbodiimide - 1])
10456
    printf ("C4N20000%c", sc);
10457
  if (fg[fg_nitroso_compound - 1])
10458
    printf ("N2O10000%c", sc);
10459
  if (fg[fg_nitro_compound - 1])
10460
    printf ("N4O20000%c", sc);
10461
  if (fg[fg_nitrite - 1])
10462
    printf ("N3O20000%c", sc);
10463
  if (fg[fg_nitrate - 1])
10464
    printf ("N4O30000%c", sc);
10465
  if (fg[fg_sulfuric_acid_deriv - 1])
10466
    printf ("S6O00000%c", sc);
10467
  if (fg[fg_sulfuric_acid - 1])
10468
    printf ("S6O4H000%c", sc);
10469
  if (fg[fg_sulfuric_acid_monoester - 1])
10470
    printf ("S6O4HC00%c", sc);
10471
  if (fg[fg_sulfuric_acid_diester - 1])
10472
    printf ("S6O4CC00%c", sc);
10473
  if (fg[fg_sulfuric_acid_amide_ester - 1])
10474
    printf ("S6O3NC00%c", sc);
10475
  if (fg[fg_sulfuric_acid_amide - 1])
10476
    printf ("S6O3N100%c", sc);
10477
  if (fg[fg_sulfuric_acid_diamide - 1])
10478
    printf ("S6O2N200%c", sc);
10479
  if (fg[fg_sulfuryl_halide - 1])
10480
    printf ("S6O3XX00%c", sc);
10481
  if (fg[fg_sulfonic_acid_deriv - 1])
10482
    printf ("S5O00000%c", sc);
10483
  if (fg[fg_sulfonic_acid - 1])
10484
    printf ("S5O3H000%c", sc);
10485
  if (fg[fg_sulfonic_acid_ester - 1])
10486
    printf ("S5O3C000%c", sc);
10487
  if (fg[fg_sulfonamide - 1])
10488
    printf ("S5O2N000%c", sc);
10489
  if (fg[fg_sulfonyl_halide - 1])
10490
    printf ("S5O2XX00%c", sc);
10491
  if (fg[fg_sulfone - 1])
10492
    printf ("S4O20000%c", sc);
10493
  if (fg[fg_sulfoxide - 1])
10494
    printf ("S2O10000%c", sc);
10495
  if (fg[fg_sulfinic_acid_deriv - 1])
10496
    printf ("S3O00000%c", sc);
10497
  if (fg[fg_sulfinic_acid - 1])
10498
    printf ("S3O2H000%c", sc);
10499
  if (fg[fg_sulfinic_acid_ester - 1])
10500
    printf ("S3O2C000%c", sc);
10501
  if (fg[fg_sulfinic_acid_halide - 1])
10502
    printf ("S3O1XX00%c", sc);
10503
  if (fg[fg_sulfinic_acid_amide - 1])
10504
    printf ("S3O1N000%c", sc);
10505
  if (fg[fg_sulfenic_acid_deriv - 1])
10506
    printf ("S1O00000%c", sc);
10507
  if (fg[fg_sulfenic_acid - 1])
10508
    printf ("S1O1H000%c", sc);
10509
  if (fg[fg_sulfenic_acid_ester - 1])
10510
    printf ("S1O1C000%c", sc);
10511
  if (fg[fg_sulfenic_acid_halide - 1])
10512
    printf ("S1O0XX00%c", sc);
10513
  if (fg[fg_sulfenic_acid_amide - 1])
10514
    printf ("S1O0N100%c", sc);
10515
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
10516
  if (fg[fg_alkylthiol - 1])
10517
    printf ("S1H1C000%c", sc);
10518
  if (fg[fg_arylthiol - 1])
10519
    printf ("S1H1A000%c", sc);
10520
  if (fg[fg_phosphoric_acid_deriv - 1])
10521
    printf ("P5O0H000%c", sc);
10522
  if (fg[fg_phosphoric_acid - 1])
10523
    printf ("P5O4H200%c", sc);
10524
  if (fg[fg_phosphoric_acid_ester - 1])
10525
    printf ("P5O4HC00%c", sc);
10526
  if (fg[fg_phosphoric_acid_halide - 1])
10527
    printf ("P5O3HX00%c", sc);
10528
  if (fg[fg_phosphoric_acid_amide - 1])
10529
    printf ("P5O3HN00%c", sc);
10530
  if (fg[fg_thiophosphoric_acid_deriv - 1])
10531
    printf ("P5O0S000%c", sc);
10532
  if (fg[fg_thiophosphoric_acid - 1])
10533
    printf ("P5O3SH00%c", sc);
10534
  if (fg[fg_thiophosphoric_acid_ester - 1])
10535
    printf ("P5O3SC00%c", sc);
10536
  if (fg[fg_thiophosphoric_acid_halide - 1])
10537
    printf ("P5O2SX00%c", sc);
10538
  if (fg[fg_thiophosphoric_acid_amide - 1])
10539
    printf ("P5O2SN00%c", sc);
10540
  if (fg[fg_phosphonic_acid_deriv - 1])
10541
    printf ("P4O30000%c", sc);
10542
  if (fg[fg_phosphonic_acid - 1])
10543
    printf ("P4O3H000%c", sc);
10544
  if (fg[fg_phosphonic_acid_ester - 1])
10545
    printf ("P4O3C000%c", sc);
10546
  if (fg[fg_phosphine - 1])
10547
    printf ("P3000000%c", sc);
10548
  if (fg[fg_phosphinoxide - 1])
10549
    printf ("P2O00000%c", sc);
10550
  if (fg[fg_boronic_acid_deriv - 1])
10551
    printf ("B2O20000%c", sc);
10552
  if (fg[fg_boronic_acid - 1])
10553
    printf ("B2O2H000%c", sc);
10554
  if (fg[fg_boronic_acid_ester - 1])
10555
    printf ("B2O2C000%c", sc);
10556
  if (fg[fg_alkene - 1])
10557
    printf ("000C2C00%c", sc);
10558
  if (fg[fg_alkyne - 1])
10559
    printf ("000C3C00%c", sc);
10560
  if (fg[fg_aromatic - 1])
10561
    printf ("0000A000%c", sc);
10562
  if (fg[fg_heterocycle - 1])
10563
    printf ("0000CZ00%c", sc);
10564
  if (fg[fg_alpha_aminoacid - 1])
10565
    printf ("C3O2HN1C%c", sc);
10566
  if (fg[fg_alpha_hydroxyacid - 1])
10567
    printf ("C3O2HO1H%c", sc);
10568
}
10569
 
10570
#undef sc
10571
 
10572
 
10573
static void
10574
write_fg_binary ()
10575
{
10576
  int i, n;
10577
  char o;
10578
 
10579
  for (i = 1; i <= max_fg / 8; i++)
10580
    {
10581
      n = 0;
10582
      if (fg[i * 8 - 1])
10583
        n++;
10584
      if (fg[i * 8 - 2])
10585
        n += 2;
10586
      if (fg[i * 8 - 3])
10587
        n += 4;
10588
      if (fg[i * 8 - 4])
10589
        n += 8;
10590
      if (fg[i * 8 - 5])
10591
        n += 16;
10592
      if (fg[i * 8 - 6])
10593
        n += 32;
10594
      if (fg[i * 8 - 7])
10595
        n += 64;
10596
      if (fg[i * 8 - 8])
10597
        n += 128;
10598
      o = (char) n;
10599
      putchar (o);
10600
    }
10601
}
10602
 
10603
 
10604
static void
10605
write_fg_bitstring ()
10606
{
10607
  int i;
10608
 
10609
  for (i = 0; i < max_fg; i++)
10610
    {
10611
      if (fg[i])
10612
        putchar ('1');
10613
      else
10614
        putchar ('0');
10615
    }
10616
}
10617
 
10618
 
10619
#if 0
10620
static void readinputfile (molfilename) char *molfilename;
10621
     {
10622
     /* new version in v0.2g */
10623
     char rline[256];
10624
     char *TEMP;
10625
 
10626
     molbufindex = 0;
10627
     if (!opt_stdin)
10628
     {
10629
     if (!rfile_is_open)
10630
     {
10631
     assign (rfile, molfilename);
10632
     rewind (rfile);
10633
     rfile_is_open = true;
10634
     }
10635
     /* p2c: checkmol.pas, line 7733: Warning:
10636
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
10637
     *rline = '\0';
10638
     mol_in_queue = false;
10639
     while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
10640
     {
10641
     fgets (rline, 256, rfile);
10642
     TEMP = strchr (rline, '\n');
10643
     if (TEMP != NULL)
10644
     *TEMP = 0;
10645
     /*mol_in_queue := false; */
10646
     if (molbufindex >= max_atoms + max_bonds + 64)
10647
     {
10648
     printf ("Not enough memory for molfile! %12ld\n",
10649
     molbufindex);
10650
     if (rfile != NULL)
10651
     fclose (rfile);
10652
     rfile = NULL;
10653
     _Escape (1);
10654
     }
10655
     molbufindex++;
10656
     strcpy (molbuf[molbufindex - 1], rline);
10657
     if (strpos2 (rline, "$$$$", 1) > 0)
10658
     mol_in_queue = true;
10659
     }
10660
     if (!P_eof (rfile))
10661
     return;
10662
     if (rfile != NULL)
10663
     fclose (rfile);
10664
     rfile = NULL;
10665
     rfile_is_open = false;
10666
     mol_in_queue = false;
10667
     return;
10668
     }
10669
     *rline = '\0';
10670
     mol_in_queue = false;
10671
     while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
10672
     {
10673
     gets (rline);
10674
     if (molbufindex >= max_atoms + max_bonds + 64)
10675
     {
10676
     printf ("Not enough memory!\n");
10677
     _Escape (1);
10678
     }
10679
     molbufindex++;
10680
     strcpy (molbuf[molbufindex - 1], rline);
10681
     if (strpos2 (rline, "$$$$", 1) > 0)
10682
     {
10683
     mol_in_queue = true;
10684
     /* read from standard input
10685
     }
10686
     }
10687
     } */
10688
#endif
10689
 
10690
static void
10691
readinputfile (char *molfilename)
10692
{
10693
  /* new version in v0.2g */
10694
  char rline[256];
10695
  char *TEMP;
10696
 
10697
  molbufindex = 0;
10698
  if (!opt_stdin)
10699
    {
10700
      if (!rfile_is_open)
10701
        {
10702
          rfile = fopen (molfilename, "r");
10703
          rewind (rfile);
10704
          rfile_is_open = true;
10705
        }
10706
/* p2c: checkmol.pas, line 7226: Warning:
10707
 * Don't know how to ASSIGN to a non-explicit file variable [207] */
10708
      *rline = '\0';
10709
      mol_in_queue = false;
10710
      while ((fgets (rline, 256, rfile) != NULL)
10711
             && (strstr (rline, "$$$$") == NULL))
10712
        {
10713
          TEMP = strchr (rline, '\n');
10714
          if (TEMP != NULL)
10715
            *TEMP = 0;
10716
          /*mol_in_queue := false; */
10717
          if (molbufindex >= max_atoms + max_bonds + 64)
10718
            {
10719
              printf ("Not enough memory for molfile! %d\n", molbufindex);
10720
              if (rfile != NULL)
10721
                fclose (rfile);
10722
              rfile = NULL;
10723
              exit (1);
10724
            }
10725
          //molbufindex++;
10726
          strcpy (molbuf[molbufindex++], rline);
10727
          if (strstr (rline, "$$$$") != NULL)
10728
            mol_in_queue = true;
10729
        }
10730
      if (!feof (rfile))
10731
        return;
10732
      if (rfile != NULL)
10733
        fclose (rfile);
10734
      rfile = NULL;
10735
      rfile_is_open = false;
10736
      mol_in_queue = false;
10737
      return;
10738
    }
10739
  *rline = '\0';
10740
  mol_in_queue = false;
10741
  do
10742
    {
10743
      fgets (rline, 256, stdin);
10744
      if (feof (stdin))
10745
        return;
10746
      TEMP = strchr (rline, '\n');
10747
      if (TEMP != NULL)
10748
        *TEMP = '\0';
10749
      if (molbufindex >= max_atoms + max_bonds + 64)
10750
        {
10751
          printf ("Not enough memory!\n");
10752
          exit (1);
10753
        }
10754
      //molbufindex++;
10755
      strcpy (molbuf[molbufindex++], rline);
10756
      if (strstr (rline, "$$$$") != NULL)
10757
        {
10758
          mol_in_queue = true;
10759
          /* read from standard input */
10760
        }
10761
    }
10762
  while (strstr (rline, "$$$$") == NULL);
10763
}
10764
 
10765
#if 0
10766
static void copy_mol_to_needle()
10767
{
10768
  int i, j, FORLIM;
10769
 
10770
  if (n_atoms == 0)
10771
    return;
10772
  /* try */
10773
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10774
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10775
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10776
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10777
  /* except*/
10778
    on e:Eoutofmemory do
10779
      begin
10780
        writeln('Not enough memory');
10781
        halt(4);
10782
      end;
10783
  end;
10784
  ndl_n_atoms = n_atoms;
10785
  ndl_n_bonds = n_bonds;
10786
  ndl_n_rings = n_rings;
10787
  ndl_n_heavyatoms = n_heavyatoms;
10788
  ndl_n_heavybonds = n_heavybonds;
10789
  strcpy(ndl_molname, molname);
10790
  ndl_n_Ctot = n_Ctot;
10791
  ndl_n_Otot = n_Otot;
10792
  ndl_n_Ntot = n_Ntot;
10793
  FORLIM = n_atoms;
10794
  for (i = 0; i < FORLIM; i++) {
10795
    strcpy(ndl_atom[i].element, atom[i].element);
10796
    strcpy(ndl_atom[i].atype, atom[i].atype);
10797
    ndl_atom[i].x = atom[i].x;
10798
    ndl_atom[i].y = atom[i].y;
10799
    ndl_atom[i].z = atom[i].z;
10800
    ndl_atom[i].formal_charge = atom[i].formal_charge;
10801
    ndl_atom[i].real_charge = atom[i].real_charge;
10802
    ndl_atom[i].Hexp = atom[i].Hexp;
10803
    ndl_atom[i].Htot = atom[i].Htot;
10804
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
10805
    ndl_atom[i].ring_count = atom[i].ring_count;
10806
    ndl_atom[i].arom = atom[i].arom;
10807
    ndl_atom[i].stereo_care = atom[i].stereo_care;
10808
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
10809
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
10810
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
10811
                                           }
10812
                                           if (n_bonds > 0) {
10813
                                           FORLIM = n_bonds;
10814
                                           for (i = 0; i < FORLIM; i++) {
10815
                                           ndl_bond[i].a1 = bond[i].a1;
10816
                                           ndl_bond[i].a2 = bond[i].a2;
10817
                                           ndl_bond[i].btype = bond[i].btype;
10818
                                           ndl_bond[i].arom = bond[i].arom;
10819
                                           ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
10820
                                           ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
10821
                                           ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
10822
                                           }
10823
                                           }
10824
                                           if (n_rings > 0) {
10825
                                           FORLIM = n_rings;
10826
                                           for (i = 0; i < FORLIM; i++) {
10827
                                           for (j = 0; j < max_ringsize; j++)
10828
                                           ndl_ring[i][j] = ring[i][j];
10829
                                           }
10830
                                           for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10831
                                           ndl_ringprop[i].size = ringprop[i].size;
10832
                                           ndl_ringprop[i].arom = ringprop[i].arom;
10833
                                           ndl_ringprop[i].envelope = ringprop[i].envelope;
10834
                                           }
10835
                                           }
10836
                                           ndl_molstat.n_QA = molstat.n_QA;
10837
                                           ndl_molstat.n_QB = molstat.n_QB;
10838
                                           ndl_molstat.n_chg = molstat.n_chg;
10839
                                           ndl_molstat.n_C1 = molstat.n_C1;
10840
                                           ndl_molstat.n_C2 = molstat.n_C2;
10841
                                           ndl_molstat.n_C = molstat.n_C;
10842
                                           ndl_molstat.n_CHB1p = molstat.n_CHB1p;
10843
                                           ndl_molstat.n_CHB2p = molstat.n_CHB2p;
10844
                                           ndl_molstat.n_CHB3p = molstat.n_CHB3p;
10845
                                           ndl_molstat.n_CHB4 = molstat.n_CHB4;
10846
                                           ndl_molstat.n_O2 = molstat.n_O2;
10847
                                           ndl_molstat.n_O3 = molstat.n_O3;
10848
                                           ndl_molstat.n_N1 = molstat.n_N1;
10849
                                           ndl_molstat.n_N2 = molstat.n_N2;
10850
                                           ndl_molstat.n_N3 = molstat.n_N3;
10851
                                           ndl_molstat.n_S = molstat.n_S;
10852
                                           ndl_molstat.n_SeTe = molstat.n_SeTe;
10853
                                           ndl_molstat.n_F = molstat.n_F;
10854
                                           ndl_molstat.n_Cl = molstat.n_Cl;
10855
                                           ndl_molstat.n_Br = molstat.n_Br;
10856
                                           ndl_molstat.n_I = molstat.n_I;
10857
                                           ndl_molstat.n_P = molstat.n_P;
10858
                                           ndl_molstat.n_B = molstat.n_B;
10859
                                           ndl_molstat.n_Met = molstat.n_Met;
10860
                                           ndl_molstat.n_X = molstat.n_X;
10861
                                           ndl_molstat.n_b1 = molstat.n_b1;
10862
                                           ndl_molstat.n_b2 = molstat.n_b2;
10863
                                           ndl_molstat.n_b3 = molstat.n_b3;
10864
                                           ndl_molstat.n_bar = molstat.n_bar;
10865
                                           ndl_molstat.n_C1O = molstat.n_C1O;
10866
                                           ndl_molstat.n_C2O = molstat.n_C2O;
10867
                                           ndl_molstat.n_CN = molstat.n_CN;
10868
                                           ndl_molstat.n_XY = molstat.n_XY;
10869
                                           ndl_molstat.n_r3 = molstat.n_r3;
10870
                                           ndl_molstat.n_r4 = molstat.n_r4;
10871
                                           ndl_molstat.n_r5 = molstat.n_r5;
10872
                                           ndl_molstat.n_r6 = molstat.n_r6;
10873
                                           ndl_molstat.n_r7 = molstat.n_r7;
10874
                                           ndl_molstat.n_r8 = molstat.n_r8;
10875
                                           ndl_molstat.n_r9 = molstat.n_r9;
10876
                                           ndl_molstat.n_r10 = molstat.n_r10;
10877
                                           ndl_molstat.n_r11 = molstat.n_r11;
10878
                                           ndl_molstat.n_r12 = molstat.n_r12;
10879
                                           ndl_molstat.n_r13p = molstat.n_r13p;
10880
                                           ndl_molstat.n_rN = molstat.n_rN;
10881
                                           ndl_molstat.n_rN1 = molstat.n_rN1;
10882
                                           ndl_molstat.n_rN2 = molstat.n_rN2;
10883
                                           ndl_molstat.n_rN3p = molstat.n_rN3p;
10884
                                           ndl_molstat.n_rO = molstat.n_rO;
10885
                                           ndl_molstat.n_rO1 = molstat.n_rO1;
10886
                                           ndl_molstat.n_rO2p = molstat.n_rO2p;
10887
                                           ndl_molstat.n_rS = molstat.n_rS;
10888
                                           ndl_molstat.n_rX = molstat.n_rX;
10889
                                           ndl_molstat.n_rAr = molstat.n_rAr;
10890
                                           ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
10891
                                           ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
10892
                                           /* p2c: checkmol.pas, line 7875:
10893
                                           * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10894
                                           /*$IFDEF extended_molstat
10895
                                            v0.3m */
10896
                                           ndl_molstat.n_psg01 = molstat.n_psg01;
10897
                                           ndl_molstat.n_psg02 = molstat.n_psg02;
10898
                                           ndl_molstat.n_psg13 = molstat.n_psg13;
10899
                                           ndl_molstat.n_psg14 = molstat.n_psg14;
10900
                                           ndl_molstat.n_psg15 = molstat.n_psg15;
10901
                                           ndl_molstat.n_psg16 = molstat.n_psg16;
10902
                                           ndl_molstat.n_psg17 = molstat.n_psg17;
10903
                                           ndl_molstat.n_psg18 = molstat.n_psg18;
10904
                                           ndl_molstat.n_pstm = molstat.n_pstm;
10905
                                           ndl_molstat.n_psla = molstat.n_psla;
10906
                                           $ENDIF*/
10907
                                           /* make sure some modes can be switched on only by the query file *M*/
10908
                                           /* and not by subsequent haystack file(s) */
10909
                                           if (ez_flag)   /* new in v0.3f */
10910
                                           ez_search = true;
10911
                                           if (chir_flag)   /* new in v0.3f */
10912
                                           rs_search = true;
10913
                                           }
10914
#endif
10915
 
10916
 
10917
static void
10918
copy_mol_to_needle ()
10919
{
10920
  //int i, j, FORLIM;
10921
 
10922
  /*if (n_atoms == 0)
10923
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10924
 
10925
 
10926
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10927
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10928
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10929
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10930
 
10931
 
10932
  ndl_n_atoms = n_atoms;
10933
  ndl_n_bonds = n_bonds;
10934
  ndl_n_rings = n_rings;
10935
  ndl_n_heavyatoms = n_heavyatoms;
10936
  ndl_n_heavybonds = n_heavybonds;
10937
  strcpy (ndl_molname, molname);
10938
  ndl_n_Ctot = n_Ctot;
10939
  ndl_n_Otot = n_Otot;
10940
  ndl_n_Ntot = n_Ntot;
10941
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
10942
 
10943
  if (n_bonds > 0)
10944
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
10945
 
10946
  if (n_rings > 0)
10947
    {
10948
      memcpy (ndl_ring, ring, sizeof (ringlist));
10949
      memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
10950
    }
10951
 
10952
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
10953
 
10954
 
10955
  // make sure some modes can be switched on only by the query file 
10956
  // and not by subsequent haystack file(s) 
10957
  if (ez_flag)                  // new in v0.3f 
10958
    ez_search = true;
10959
 
10960
  if (chir_flag)                // new in v0.3f 
10961
    rs_search = true;
10962
 
10963
  ndl_querymol = found_querymol;        /* 0.3p */
10964
 
10965
}
10966
 
10967
static void
10968
copy_mol_to_tmp ()
10969
{
10970
  //int i, j, FORLIM;
10971
 
10972
  /*if (n_atoms == 0)
10973
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10974
 
10975
 
10976
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10977
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10978
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10979
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10980
 
10981
 
10982
  tmp_n_atoms = n_atoms;
10983
  tmp_n_bonds = n_bonds;
10984
  tmp_n_rings = n_rings;
10985
  tmp_n_heavyatoms = n_heavyatoms;
10986
  tmp_n_heavybonds = n_heavybonds;
10987
  strcpy (tmp_molname, molname);
10988
  tmp_n_Ctot = n_Ctot;
10989
  tmp_n_Otot = n_Otot;
10990
  tmp_n_Ntot = n_Ntot;
10991
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
10992
 
10993
  if (n_bonds > 0)
10994
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
10995
 
10996
  if (n_rings > 0)
10997
    {
10998
      memcpy (tmp_ring, ring, sizeof (ringlist));
10999
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
11000
    }
11001
 
11002
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
11003
 
11004
 
11005
  // make sure some modes can be switched on only by the query file 
11006
  // and not by subsequent haystack file(s) 
11007
  if (ez_flag)                  // new in v0.3f 
11008
    ez_search = true;
11009
 
11010
  if (chir_flag)                // new in v0.3f 
11011
    rs_search = true;
11012
 
11013
  ndl_querymol = found_querymol;        /* 0.3p */
11014
 
11015
}
11016
 
11017
#if 0
11018
static void copy_mol_to_tmp()
11019
{
11020
  int i, j, FORLIM;
11021
 
11022
  if (n_atoms == 0)
11023
    return;
11024
  /* try */
11025
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
11026
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
11027
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
11028
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
11029
  /* except */
11030
    on e:Eoutofmemory do
11031
      begin
11032
        writeln('Not enough memory');
11033
        halt(4);
11034
      end;
11035
  end;
11036
  tmp_n_atoms = n_atoms;
11037
  tmp_n_bonds = n_bonds;
11038
  tmp_n_rings = n_rings;
11039
  tmp_n_heavyatoms = n_heavyatoms;
11040
  tmp_n_heavybonds = n_heavybonds;
11041
  strcpy(tmp_molname, molname);
11042
  tmp_n_Ctot = n_Ctot;
11043
  tmp_n_Otot = n_Otot;
11044
  tmp_n_Ntot = n_Ntot;
11045
  FORLIM = n_atoms;
11046
  for (i = 0; i < FORLIM; i++) {
11047
    strcpy(tmp_atom[i].element, atom[i].element);
11048
    strcpy(tmp_atom[i].atype, atom[i].atype);
11049
    tmp_atom[i].x = atom[i].x;
11050
    tmp_atom[i].y = atom[i].y;
11051
    tmp_atom[i].z = atom[i].z;
11052
    tmp_atom[i].formal_charge = atom[i].formal_charge;
11053
    tmp_atom[i].real_charge = atom[i].real_charge;
11054
    tmp_atom[i].Hexp = atom[i].Hexp;
11055
    tmp_atom[i].Htot = atom[i].Htot;
11056
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
11057
    tmp_atom[i].ring_count = atom[i].ring_count;
11058
    tmp_atom[i].arom = atom[i].arom;
11059
    tmp_atom[i].stereo_care = atom[i].stereo_care;
11060
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
11061
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
11062
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
11063
  }
11064
  if (n_bonds > 0) {
11065
    FORLIM = n_bonds;
11066
    for (i = 0; i < FORLIM; i++) {
11067
      tmp_bond[i].a1 = bond[i].a1;
11068
      tmp_bond[i].a2 = bond[i].a2;
11069
      tmp_bond[i].btype = bond[i].btype;
11070
      tmp_bond[i].arom = bond[i].arom;
11071
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
11072
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
11073
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
11074
    }
11075
  }
11076
  if (n_rings > 0) {
11077
    FORLIM = n_rings;
11078
    for (i = 0; i < FORLIM; i++) {
11079
      for (j = 0; j < max_ringsize; j++)
11080
        tmp_ring[i][j] = ring[i][j];
11081
    }
11082
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
11083
      tmp_ringprop[i].size = ringprop[i].size;
11084
      tmp_ringprop[i].arom = ringprop[i].arom;
11085
      tmp_ringprop[i].envelope = ringprop[i].envelope;
11086
    }
11087
  }
11088
  tmp_molstat.n_QA = molstat.n_QA;
11089
  tmp_molstat.n_QB = molstat.n_QB;
11090
  tmp_molstat.n_chg = molstat.n_chg;
11091
  tmp_molstat.n_C1 = molstat.n_C1;
11092
  tmp_molstat.n_C2 = molstat.n_C2;
11093
  tmp_molstat.n_C = molstat.n_C;
11094
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
11095
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
11096
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
11097
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
11098
  tmp_molstat.n_O2 = molstat.n_O2;
11099
  tmp_molstat.n_O3 = molstat.n_O3;
11100
  tmp_molstat.n_N1 = molstat.n_N1;
11101
  tmp_molstat.n_N2 = molstat.n_N2;
11102
  tmp_molstat.n_N3 = molstat.n_N3;
11103
  tmp_molstat.n_S = molstat.n_S;
11104
  tmp_molstat.n_SeTe = molstat.n_SeTe;
11105
  tmp_molstat.n_F = molstat.n_F;
11106
  tmp_molstat.n_Cl = molstat.n_Cl;
11107
  tmp_molstat.n_Br = molstat.n_Br;
11108
  tmp_molstat.n_I = molstat.n_I;
11109
  tmp_molstat.n_P = molstat.n_P;
11110
  tmp_molstat.n_B = molstat.n_B;
11111
  tmp_molstat.n_Met = molstat.n_Met;
11112
  tmp_molstat.n_X = molstat.n_X;
11113
  tmp_molstat.n_b1 = molstat.n_b1;
11114
  tmp_molstat.n_b2 = molstat.n_b2;
11115
  tmp_molstat.n_b3 = molstat.n_b3;
11116
  tmp_molstat.n_bar = molstat.n_bar;
11117
  tmp_molstat.n_C1O = molstat.n_C1O;
11118
  tmp_molstat.n_C2O = molstat.n_C2O;
11119
  tmp_molstat.n_CN = molstat.n_CN;
11120
  tmp_molstat.n_XY = molstat.n_XY;
11121
  tmp_molstat.n_r3 = molstat.n_r3;
11122
  tmp_molstat.n_r4 = molstat.n_r4;
11123
  tmp_molstat.n_r5 = molstat.n_r5;
11124
  tmp_molstat.n_r6 = molstat.n_r6;
11125
  tmp_molstat.n_r7 = molstat.n_r7;
11126
  tmp_molstat.n_r8 = molstat.n_r8;
11127
  tmp_molstat.n_r9 = molstat.n_r9;
11128
  tmp_molstat.n_r10 = molstat.n_r10;
11129
  tmp_molstat.n_r11 = molstat.n_r11;
11130
  tmp_molstat.n_r12 = molstat.n_r12;
11131
  tmp_molstat.n_r13p = molstat.n_r13p;
11132
  tmp_molstat.n_rN = molstat.n_rN;
11133
  tmp_molstat.n_rN1 = molstat.n_rN1;
11134
  tmp_molstat.n_rN2 = molstat.n_rN2;
11135
  tmp_molstat.n_rN3p = molstat.n_rN3p;
11136
  tmp_molstat.n_rO = molstat.n_rO;
11137
  tmp_molstat.n_rO1 = molstat.n_rO1;
11138
  tmp_molstat.n_rO2p = molstat.n_rO2p;
11139
  tmp_molstat.n_rS = molstat.n_rS;
11140
  tmp_molstat.n_rX = molstat.n_rX;
11141
  tmp_molstat.n_rAr = molstat.n_rAr;
11142
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
11143
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
11144
/* p2c: checkmol.pas, line 8022:
11145
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11146
  /*$IFDEF extended_molstat
11147
   v0.3m
11148
  tmp_molstat.n_psg01 = molstat.n_psg01;
11149
  tmp_molstat.n_psg02 = molstat.n_psg02;
11150
  tmp_molstat.n_psg13 = molstat.n_psg13;
11151
  tmp_molstat.n_psg14 = molstat.n_psg14;
11152
  tmp_molstat.n_psg15 = molstat.n_psg15;
11153
  tmp_molstat.n_psg16 = molstat.n_psg16;
11154
  tmp_molstat.n_psg17 = molstat.n_psg17;
11155
  tmp_molstat.n_psg18 = molstat.n_psg18;
11156
  tmp_molstat.n_pstm = molstat.n_pstm;
11157
  tmp_molstat.n_psla = molstat.n_psla;
11158
  $ENDIF*/
11159
  /* make sure some modes can be switched on only by the query file */
11160
  /* and not by subsequent haystack file(s) */
11161
  if (ez_flag)   /* new in v0.3f */
11162
    ez_search = true;
11163
  if (chir_flag)   /* new in v0.3f */
11164
    rs_search = true;
11165
}
11166
#endif
11167
 
11168
static void
11169
copy_tmp_to_mol ()
11170
{
11171
  //int i, j, FORLIM;
11172
 
11173
  /*if (n_atoms == 0)
11174
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
11175
 
11176
 
11177
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
11178
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
11179
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
11180
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
11181
 
11182
 
11183
  n_atoms = tmp_n_atoms;
11184
  n_bonds = tmp_n_bonds;
11185
  n_rings = tmp_n_rings;
11186
  n_heavyatoms = tmp_n_heavyatoms;
11187
  n_heavybonds = tmp_n_heavybonds;
11188
  strcpy (molname, tmp_molname);
11189
  n_Ctot = tmp_n_Ctot;
11190
  n_Otot = tmp_n_Otot;
11191
  n_Ntot = tmp_n_Ntot;
11192
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
11193
 
11194
  if (tmp_n_bonds > 0)
11195
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
11196
 
11197
  if (tmp_n_rings > 0)
11198
    {
11199
      memcpy (ring, tmp_ring, sizeof (ringlist));
11200
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
11201
    }
11202
 
11203
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
11204
 
11205
 
11206
  // make sure some modes can be switched on only by the query file 
11207
  // and not by subsequent haystack file(s) 
11208
  if (ez_flag)                  // new in v0.3f 
11209
    ez_search = true;
11210
 
11211
  if (chir_flag)                // new in v0.3f 
11212
    rs_search = true;
11213
 
11214
}
11215
 
11216
#if 0
11217
static void copy_tmp_to_mol()
11218
{
11219
  int i, j, FORLIM;
11220
 
11221
  if (tmp_n_atoms == 0)
11222
    return;
11223
  n_atoms = tmp_n_atoms;
11224
  n_bonds = tmp_n_bonds;
11225
  n_rings = tmp_n_rings;
11226
  n_heavyatoms = tmp_n_heavyatoms;
11227
  n_heavybonds = tmp_n_heavybonds;
11228
  strcpy(molname, tmp_molname);
11229
  n_Ctot = tmp_n_Ctot;
11230
  n_Otot = tmp_n_Otot;
11231
  n_Ntot = tmp_n_Ntot;
11232
  /* try */
11233
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
11234
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
11235
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
11236
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
11237
  FORLIM = tmp_n_atoms;
11238
  /* except*/
11239
    on e:Eoutofmemory do
11240
      begin
11241
        writeln('Not enough memory');
11242
        halt(4);
11243
      end;
11244
  end;
11245
  for (i = 0; i < FORLIM; i++) {
11246
    strcpy(atom[i].element, tmp_atom[i].element);
11247
    strcpy(atom[i].atype, tmp_atom[i].atype);
11248
    atom[i].x = tmp_atom[i].x;
11249
    atom[i].y = tmp_atom[i].y;
11250
    atom[i].z = tmp_atom[i].z;
11251
    atom[i].formal_charge = tmp_atom[i].formal_charge;
11252
    atom[i].real_charge = tmp_atom[i].real_charge;
11253
    atom[i].Hexp = tmp_atom[i].Hexp;
11254
    atom[i].Htot = tmp_atom[i].Htot;
11255
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
11256
    atom[i].ring_count = tmp_atom[i].ring_count;
11257
    atom[i].arom = tmp_atom[i].arom;
11258
    atom[i].stereo_care = tmp_atom[i].stereo_care;
11259
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
11260
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
11261
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
11262
  }
11263
  if (tmp_n_bonds > 0) {
11264
    FORLIM = tmp_n_bonds;
11265
    for (i = 0; i < FORLIM; i++) {
11266
      bond[i].a1 = tmp_bond[i].a1;
11267
      bond[i].a2 = tmp_bond[i].a2;
11268
      bond[i].btype = tmp_bond[i].btype;
11269
      bond[i].arom = tmp_bond[i].arom;
11270
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
11271
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
11272
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
11273
    }
11274
  }
11275
  if (tmp_n_rings > 0) {
11276
    FORLIM = tmp_n_rings;
11277
    for (i = 0; i < FORLIM; i++) {
11278
      for (j = 0; j < max_ringsize; j++)
11279
        ring[i][j] = tmp_ring[i][j];
11280
    }
11281
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
11282
      ringprop[i].size = tmp_ringprop[i].size;
11283
      ringprop[i].arom = tmp_ringprop[i].arom;
11284
      ringprop[i].envelope = tmp_ringprop[i].envelope;
11285
    }
11286
  }
11287
  molstat.n_QA = tmp_molstat.n_QA;
11288
  molstat.n_QB = tmp_molstat.n_QB;
11289
  molstat.n_chg = tmp_molstat.n_chg;
11290
  molstat.n_C1 = tmp_molstat.n_C1;
11291
  molstat.n_C2 = tmp_molstat.n_C2;
11292
  molstat.n_C = tmp_molstat.n_C;
11293
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
11294
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
11295
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
11296
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
11297
  molstat.n_O2 = tmp_molstat.n_O2;
11298
  molstat.n_O3 = tmp_molstat.n_O3;
11299
  molstat.n_N1 = tmp_molstat.n_N1;
11300
  molstat.n_N2 = tmp_molstat.n_N2;
11301
  molstat.n_N3 = tmp_molstat.n_N3;
11302
  molstat.n_S = tmp_molstat.n_S;
11303
  molstat.n_SeTe = tmp_molstat.n_SeTe;
11304
  molstat.n_F = tmp_molstat.n_F;
11305
  molstat.n_Cl = tmp_molstat.n_Cl;
11306
  molstat.n_Br = tmp_molstat.n_Br;
11307
  molstat.n_I = tmp_molstat.n_I;
11308
  molstat.n_P = tmp_molstat.n_P;
11309
  molstat.n_B = tmp_molstat.n_B;
11310
  molstat.n_Met = tmp_molstat.n_Met;
11311
  molstat.n_X = tmp_molstat.n_X;
11312
  molstat.n_b1 = tmp_molstat.n_b1;
11313
  molstat.n_b2 = tmp_molstat.n_b2;
11314
  molstat.n_b3 = tmp_molstat.n_b3;
11315
  molstat.n_bar = tmp_molstat.n_bar;
11316
  molstat.n_C1O = tmp_molstat.n_C1O;
11317
  molstat.n_C2O = tmp_molstat.n_C2O;
11318
  molstat.n_CN = tmp_molstat.n_CN;
11319
  molstat.n_XY = tmp_molstat.n_XY;
11320
  molstat.n_r3 = tmp_molstat.n_r3;
11321
  molstat.n_r4 = tmp_molstat.n_r4;
11322
  molstat.n_r5 = tmp_molstat.n_r5;
11323
  molstat.n_r6 = tmp_molstat.n_r6;
11324
  molstat.n_r7 = tmp_molstat.n_r7;
11325
  molstat.n_r8 = tmp_molstat.n_r8;
11326
  molstat.n_r9 = tmp_molstat.n_r9;
11327
  molstat.n_r10 = tmp_molstat.n_r10;
11328
  molstat.n_r11 = tmp_molstat.n_r11;
11329
  molstat.n_r12 = tmp_molstat.n_r12;
11330
  molstat.n_r13p = tmp_molstat.n_r13p;
11331
  molstat.n_rN = tmp_molstat.n_rN;
11332
  molstat.n_rN1 = tmp_molstat.n_rN1;
11333
  molstat.n_rN2 = tmp_molstat.n_rN2;
11334
  molstat.n_rN3p = tmp_molstat.n_rN3p;
11335
  molstat.n_rO = tmp_molstat.n_rO;
11336
  molstat.n_rO1 = tmp_molstat.n_rO1;
11337
  molstat.n_rO2p = tmp_molstat.n_rO2p;
11338
  molstat.n_rS = tmp_molstat.n_rS;
11339
  molstat.n_rX = tmp_molstat.n_rX;
11340
  molstat.n_rAr = tmp_molstat.n_rAr;
11341
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
11342
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
11343
/* p2c: checkmol.pas, line 8169:
11344
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11345
  /*$IFDEF extended_molstat
11346
     molstat.n_psg01 = tmp_molstat.n_psg01;
11347
     molstat.n_psg02 = tmp_molstat.n_psg02;
11348
     molstat.n_psg13 = tmp_molstat.n_psg13;
11349
     molstat.n_psg14 = tmp_molstat.n_psg14;
11350
     molstat.n_psg15 = tmp_molstat.n_psg15;
11351
     molstat.n_psg16 = tmp_molstat.n_psg16;
11352
     molstat.n_psg17 = tmp_molstat.n_psg17;
11353
     molstat.n_psg18 = tmp_molstat.n_psg18;
11354
     molstat.n_pstm = tmp_molstat.n_pstm;
11355
     molstat.n_psla = tmp_molstat.n_psla;
11356
     $ENDIF */
11357
  /* make sure some modes can be switched on only by the query file */
11358
  /* and not by subsequent haystack file(s) */
11359
     if (ez_flag)
11360
     ez_search = true;
11361
     if (chir_flag)
11362
     rs_search = true;
11363
     }
11364
#endif
11365
 
11366
 
11367
 
11368
 
11369
 
11370
static void
11371
get_ringstat (r_id)
11372
     int r_id;
11373
{
11374
  int i, j;
11375
  ringpath_type testring;
11376
  int ring_size, a_ref;
11377
  str2 elem;
11378
  int nN = 0, nO = 0, nS = 0, nX = 0;
11379
 
11380
  if (r_id < 1 || r_id > n_rings)
11381
    return;
11382
  memset (testring, 0, sizeof (ringpath_type));
11383
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
11384
  for (j = 0; j < ring_size; j++)       /* v0.3j */
11385
    testring[j] = ring[r_id - 1][j];
11386
/* p2c: checkmol.pas, line 8238:
11387
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11388
#ifdef reduced_SAR
11389
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != false)
11390
    /* v0.3n: ignore envelope rings */
11391
    return;
11392
#else
11393
  if (ring_size <= 2)
11394
    return;
11395
#endif
11396
  for (i = 0; i < ring_size; i++)
11397
    {
11398
      a_ref = testring[i];
11399
      strcpy (elem, atom[a_ref - 1].element);
11400
      if (strcmp (elem, "C ") && strcmp (elem, "A "))
11401
        {
11402
          nX++;                 /* general heteroatom count */
11403
          if (!strcmp (elem, "N "))
11404
            nN++;
11405
          if (!strcmp (elem, "O "))
11406
            nO++;
11407
          if (!strcmp (elem, "S "))
11408
            nS++;
11409
        }
11410
    }
11411
  if (nN > 0)
11412
    {
11413
      molstat.n_rN++;
11414
      if (nN == 1)
11415
        molstat.n_rN1++;
11416
      if (nN == 2)
11417
        molstat.n_rN2++;
11418
      if (nN > 2)
11419
        molstat.n_rN3p++;
11420
    }
11421
  if (nO > 0)
11422
    {
11423
      molstat.n_rO++;
11424
      if (nO == 1)
11425
        molstat.n_rO1++;
11426
      if (nO == 2)
11427
        molstat.n_rO2p++;
11428
    }
11429
  if (nS > 0)
11430
    molstat.n_rS++;
11431
  if (nX > 0)
11432
    molstat.n_rX++;
11433
  /* general ringsize descriptors; v0.3m */
11434
  switch (ring_size)
11435
    {
11436
 
11437
    case 3:
11438
      molstat.n_r3++;
11439
      break;
11440
 
11441
    case 4:
11442
      molstat.n_r4++;
11443
      break;
11444
 
11445
    case 5:
11446
      molstat.n_r5++;
11447
      break;
11448
 
11449
    case 6:
11450
      molstat.n_r6++;
11451
      break;
11452
 
11453
    case 7:
11454
      molstat.n_r7++;
11455
      break;
11456
 
11457
    case 8:
11458
      molstat.n_r8++;
11459
      break;
11460
 
11461
    case 9:
11462
      molstat.n_r9++;
11463
      break;
11464
 
11465
    case 10:
11466
      molstat.n_r10++;
11467
      break;
11468
 
11469
    case 11:
11470
      molstat.n_r11++;
11471
      break;
11472
 
11473
    case 12:
11474
      molstat.n_r12++;
11475
      break;
11476
 
11477
    default:
11478
      molstat.n_r13p++;
11479
      break;
11480
    }                           /* end v0.3m        */
11481
}
11482
 
11483
 
11484
static void
11485
get_molstat ()
11486
{
11487
  int i;
11488
  str2 elem;
11489
  str3 atype;
11490
  int a1, a2;
11491
  str2 a1el, a2el;
11492
  char btype;
11493
  int hbc;
11494
  int n_b2formal = 0;           /* new in v0.2e */
11495
  int FORLIM;
11496
 
11497
  if (n_atoms == 0)
11498
    return;
11499
  FORLIM = n_atoms;
11500
  for (i = 0; i < FORLIM; i++)
11501
    {
11502
      if (atom[i].heavy)
11503
        {
11504
          strcpy (elem, atom[i].element);
11505
          strcpy (atype, atom[i].atype);
11506
          if (!strcmp (atype, "C1 "))
11507
            molstat.n_C1++;
11508
          if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
11509
            molstat.n_C2++;
11510
          if (!strcmp (elem, "C "))
11511
            molstat.n_C++;
11512
          if (!strcmp (atype, "O2 "))
11513
            molstat.n_O2++;
11514
          if (!strcmp (atype, "O3 "))
11515
            molstat.n_O3++;
11516
          if (!strcmp (atype, "N1 "))
11517
            molstat.n_N1++;
11518
          if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
11519
              (!strcmp (atype, "NAM") && atom[i].arom == true))
11520
            /* v0.3n */
11521
            molstat.n_N2++;
11522
          if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
11523
              !strcmp (atype, "N3+") ||
11524
              (!strcmp (atype, "NAM") && atom[i].arom == false))
11525
            /* v0.3n */
11526
            molstat.n_N3++;
11527
          if (!strcmp (elem, "A "))     /* query atom */
11528
            molstat.n_QA++;
11529
          if (!strcmp (elem, "Q "))     /* query atom */
11530
            molstat.n_QA++;
11531
          if (!strcmp (elem, "X "))     /* query atom */
11532
            molstat.n_QA++;
11533
          if (!strcmp (elem, "S "))
11534
            molstat.n_S++;
11535
          if (!strcmp (elem, "SE"))
11536
            molstat.n_SeTe++;
11537
          if (!strcmp (elem, "TE"))
11538
            molstat.n_SeTe++;
11539
          if (!strcmp (elem, "F "))
11540
            molstat.n_F++;
11541
          if (!strcmp (elem, "CL"))
11542
            molstat.n_Cl++;
11543
          if (!strcmp (elem, "BR"))
11544
            molstat.n_Br++;
11545
          if (!strcmp (elem, "I "))
11546
            molstat.n_I++;
11547
          if (!strcmp (elem, "P "))
11548
            molstat.n_P++;
11549
          if (!strcmp (elem, "B "))
11550
            molstat.n_B++;
11551
          /* check for known metals */
11552
          if (atom[i].metal)    /* v0.3l */
11553
            molstat.n_Met++;
11554
          /* still missing: unknown elements */
11555
 
11556
          /* check number of heteroatom bonds per C atom */
11557
          if (!strcmp (elem, "C "))
11558
            {
11559
              hbc = raw_hetbond_count (i + 1);
11560
              /* new in v0.2j (replaces hetbond_count) */
11561
              if (hbc >= 1)
11562
                molstat.n_CHB1p++;
11563
              if (hbc >= 2)
11564
                molstat.n_CHB2p++;
11565
              if (hbc >= 3)
11566
                molstat.n_CHB3p++;
11567
              if (hbc == 4)
11568
                molstat.n_CHB4++;
11569
            }
11570
          if (atom[i].formal_charge != 0)
11571
            {
11572
              molstat.n_chg++;
11573
              //n_charges++;
11574
            }
11575
          if (atom[i].nucleon_number != 0)
11576
            {
11577
              molstat.n_iso++;
11578
            }
11579
          if (atom[i].radical_type != 0)
11580
            {
11581
              molstat.n_rad++;
11582
            }
11583
          /* check for "other" elements;  v0.3l */
11584
          if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
11585
              && strcmp (elem, "O ") && strcmp (elem, "S ")
11586
              && strcmp (elem, "SE") && strcmp (elem, "TE")
11587
              && strcmp (elem, "P ") && strcmp (elem, "B ")
11588
              && strcmp (elem, "A ") && strcmp (elem, "Q "))
11589
            molstat.n_X++;
11590
          /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
11591
/* p2c: checkmol.pas, line 8353:
11592
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11593
          /*$IFDEF extended_molstat */
11594
          if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
11595
              || !strcmp (elem, "K ") || !strcmp (elem, "RB")
11596
              || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
11597
            molstat.n_psg01++;
11598
          if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
11599
              || !strcmp (elem, "CA") || !strcmp (elem, "SR")
11600
              || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
11601
            molstat.n_psg02++;
11602
          if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
11603
              || !strcmp (elem, "GA") || !strcmp (elem, "IN")
11604
              || !strcmp (elem, "TL"))
11605
            molstat.n_psg13++;
11606
          if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
11607
              || !strcmp (elem, "GE") || !strcmp (elem, "SN")
11608
              || !strcmp (elem, "PB"))
11609
            molstat.n_psg14++;
11610
          if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
11611
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
11612
              || !strcmp (elem, "BI"))
11613
            molstat.n_psg15++;
11614
          if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
11615
              || !strcmp (elem, "SE") || !strcmp (elem, "TE")
11616
              || !strcmp (elem, "PO"))
11617
            molstat.n_psg16++;
11618
          if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
11619
              || !strcmp (elem, "BR") || !strcmp (elem, "I ")
11620
              || !strcmp (elem, "AT"))
11621
            molstat.n_psg17++;
11622
          if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
11623
              || !strcmp (elem, "AR") || !strcmp (elem, "KR")
11624
              || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
11625
            molstat.n_psg18++;
11626
          if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
11627
              || !strcmp (elem, "LU") || !strcmp (elem, "LR")
11628
              || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
11629
              || !strcmp (elem, "HF") || !strcmp (elem, "RF")
11630
              || !strcmp (elem, "V ") || !strcmp (elem, "NB")
11631
              || !strcmp (elem, "TA") || !strcmp (elem, "DB")
11632
              || !strcmp (elem, "CR") || !strcmp (elem, "MO")
11633
              || !strcmp (elem, "W ") || !strcmp (elem, "SG")
11634
              || !strcmp (elem, "MN") || !strcmp (elem, "TC")
11635
              || !strcmp (elem, "RE") || !strcmp (elem, "BH")
11636
              || !strcmp (elem, "FE") || !strcmp (elem, "RU")
11637
              || !strcmp (elem, "OS") || !strcmp (elem, "HS")
11638
              || !strcmp (elem, "CO") || !strcmp (elem, "RH")
11639
              || !strcmp (elem, "IR") || !strcmp (elem, "MT")
11640
              || !strcmp (elem, "NI") || !strcmp (elem, "PD")
11641
              || !strcmp (elem, "PT") || !strcmp (elem, "DS")
11642
              || !strcmp (elem, "CU") || !strcmp (elem, "AG")
11643
              || !strcmp (elem, "AU") || !strcmp (elem, "RG")
11644
              || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
11645
              || !strcmp (elem, "HG"))
11646
/* p2c: checkmol.pas, line 8439:
11647
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
11648
            molstat.n_pstm++;
11649
          if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
11650
              || !strcmp (elem, "PR") || !strcmp (elem, "ND")
11651
              || !strcmp (elem, "PM") || !strcmp (elem, "SM")
11652
              || !strcmp (elem, "EU") || !strcmp (elem, "GD")
11653
              || !strcmp (elem, "TB") || !strcmp (elem, "DY")
11654
              || !strcmp (elem, "HO") || !strcmp (elem, "ER")
11655
              || !strcmp (elem, "TM") || !strcmp (elem, "YB")
11656
              || !strcmp (elem, "AC") || !strcmp (elem, "TH")
11657
              || !strcmp (elem, "PA") || !strcmp (elem, "U ")
11658
              || !strcmp (elem, "NP") || !strcmp (elem, "PU")
11659
              || !strcmp (elem, "AM") || !strcmp (elem, "CM")
11660
              || !strcmp (elem, "BK") || !strcmp (elem, "CF")
11661
              || !strcmp (elem, "ES") || !strcmp (elem, "FM")
11662
              || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
11663
/* p2c: checkmol.pas, line 8439:
11664
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
11665
            molstat.n_psla++;
11666
          /*$ENDIF */
11667
        }                       /* is heavy */
11668
    }                           /* atoms */
11669
  if (n_bonds > 0)
11670
    {
11671
      FORLIM = n_bonds;
11672
      for (i = 0; i < FORLIM; i++)
11673
        {
11674
          a1 = bond[i].a1;
11675
          a2 = bond[i].a2;
11676
          strcpy (a1el, atom[a1 - 1].element);
11677
          strcpy (a2el, atom[a2 - 1].element);
11678
          btype = bond[i].btype;
11679
          if (bond[i].arom)
11680
            molstat.n_bar++;
11681
          else
11682
            {
11683
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
11684
                molstat.n_b1++;
11685
              if (btype == 'D')
11686
                molstat.n_b2++;
11687
              if (btype == 'T')
11688
                molstat.n_b3++;
11689
            }
11690
          /* v0.3n: ignore bonds to (explicit) hydrogens */
11691
          if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
11692
              (!strcmp (a1el, "O ") && !strcmp (a2el, "C ")))
11693
            {
11694
              if (btype == 'S')
11695
                molstat.n_C1O++;
11696
              if (btype == 'D')
11697
                molstat.n_C2O++;
11698
            }
11699
          if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
11700
              (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
11701
            molstat.n_CN++;
11702
          if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
11703
              && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
11704
            molstat.n_XY++;
11705
          /* new in v0.3n: number of bonds belonging to more than one ring */
11706
          if (bond[i].ring_count > 1)
11707
            molstat.n_br2p++;
11708
        }
11709
    }                           /* bonds */
11710
  if (n_rings <= 0)
11711
    {
11712
      return;
11713
    }                           /* rings */
11714
  /* v0.3n */
11715
  n_countablerings = 0;         /* v0.3n */
11716
  FORLIM = n_rings;
11717
  for (i = 1; i <= FORLIM; i++)
11718
    {
11719
      if (ringprop[i - 1].envelope == false)    /* v0.3n */
11720
        n_countablerings++;
11721
      if (is_arene (i) && ringprop[i - 1].envelope == false)
11722
        {                       /* v0.3n: ignore envelope rings */
11723
          molstat.n_rAr++;
11724
          if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == false))
11725
            /* v0.3l */
11726
            molstat.n_rBz++;
11727
        }
11728
      get_ringstat (i);
11729
      if (ringprop[i - 1].arom == true && ringprop[i - 1].envelope == false)
11730
        /* new in v0.3n; replaces assignment below */
11731
        n_b2formal++;
11732
    }
11733
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
11734
  /* in order to allow an isolated double bond in the needle */
11735
  /* to be matched as a ring fragment of an aromatic ring */
11736
  if (n_b2formal > molstat.n_bar / 2)
11737
    n_b2formal = molstat.n_bar / 2;
11738
  molstat.n_b2 += n_b2formal;
11739
}
11740
 
11741
 
11742
static void
11743
fix_ssr_ringcounts ()
11744
{
11745
  /* new in v0.3n */
11746
  /* if SAR -> SSR fallback happens, set some molstat values */
11747
  /* to a maximum (ring counts for various ring sizes); */
11748
  /* this should be necessary only for ring sizes which */
11749
  /* are a) too large for the SSR (depending on ssr_vringsize) */
11750
  /* and b) which are likely to contain "envelope rings" */
11751
  /* (size 6 and above) */
11752
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
11753
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
11754
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
11755
  if (molstat.n_r6 == 0)
11756
    molstat.n_r6 = max_rings;
11757
  if (molstat.n_r7 == 0)
11758
    molstat.n_r7 = max_rings;
11759
  if (molstat.n_r8 == 0)
11760
    molstat.n_r8 = max_rings;
11761
  if (molstat.n_r9 == 0)
11762
    molstat.n_r9 = max_rings;
11763
  if (molstat.n_r10 == 0)
11764
    molstat.n_r10 = max_rings;
11765
  if (molstat.n_r11 == 0)
11766
    molstat.n_r11 = max_rings;
11767
  if (molstat.n_r12 == 0)
11768
    molstat.n_r12 = max_rings;
11769
  if (molstat.n_r13p == 0)
11770
    molstat.n_r13p = max_rings;
11771
}
11772
 
11773
 
11774
 
11775
static void
11776
write_molstat ()
11777
{
11778
  if (auto_ssr)                 /* v0.3n */
11779
    fix_ssr_ringcounts ();
11780
  printf ("n_atoms:%d;", n_heavyatoms);
11781
  /* count only non-H atoms (some molfiles contain explicit H's) */
11782
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
11783
    printf ("n_bonds:%d;", n_heavybonds);
11784
/* p2c: checkmol.pas, line 8471:
11785
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11786
#ifdef REDUCED_SAR
11787
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
11788
    printf ("n_rings:%d;", n_countablerings);
11789
#else
11790
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
11791
    printf ("n_rings:%d;", n_rings);
11792
#endif
11793
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
11794
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
11795
  if (molstat.n_chg > 0)        /* 0.3x */
11796
    printf ("n_chg:%d;", molstat.n_chg);
11797
 
11798
  if (molstat.n_C1 > 0)
11799
    printf ("n_C1:%d;", molstat.n_C1);
11800
  if (molstat.n_C2 > 0)
11801
    printf ("n_C2:%d;", molstat.n_C2);
11802
  /* requirement of a given number of sp3 carbons might be too restrictive, */
11803
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
11804
  if (molstat.n_C > 0)
11805
    printf ("n_C:%d;", molstat.n_C);
11806
  if (molstat.n_CHB1p > 0)
11807
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
11808
  if (molstat.n_CHB2p > 0)
11809
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
11810
  if (molstat.n_CHB3p > 0)
11811
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
11812
  if (molstat.n_CHB4 > 0)
11813
    printf ("n_CHB4:%d;", molstat.n_CHB4);
11814
  if (molstat.n_O2 > 0)
11815
    printf ("n_O2:%d;", molstat.n_O2);
11816
  if (molstat.n_O3 > 0)
11817
    printf ("n_O3:%d;", molstat.n_O3);
11818
  if (molstat.n_N1 > 0)
11819
    printf ("n_N1:%d;", molstat.n_N1);
11820
  if (molstat.n_N2 > 0)
11821
    printf ("n_N2:%d;", molstat.n_N2);
11822
  if (molstat.n_N3 > 0)
11823
    printf ("n_N3:%d;", molstat.n_N3);
11824
  if (molstat.n_S > 0)
11825
    printf ("n_S:%d;", molstat.n_S);
11826
  if (molstat.n_SeTe > 0)
11827
    printf ("n_SeTe:%d;", molstat.n_SeTe);
11828
  if (molstat.n_F > 0)
11829
    printf ("n_F:%d;", molstat.n_F);
11830
  if (molstat.n_Cl > 0)
11831
    printf ("n_Cl:%d;", molstat.n_Cl);
11832
  if (molstat.n_Br > 0)
11833
    printf ("n_Br:%d;", molstat.n_Br);
11834
  if (molstat.n_I > 0)
11835
    printf ("n_I:%d;", molstat.n_I);
11836
  if (molstat.n_P > 0)
11837
    printf ("n_P:%d;", molstat.n_P);
11838
  if (molstat.n_B > 0)
11839
    printf ("n_B:%d;", molstat.n_B);
11840
  if (molstat.n_Met > 0)
11841
    printf ("n_Met:%d;", molstat.n_Met);
11842
  if (molstat.n_X > 0)
11843
    printf ("n_X:%d;", molstat.n_X);
11844
  if (molstat.n_b1 > 0)
11845
    printf ("n_b1:%d;", molstat.n_b1);
11846
  if (molstat.n_b2 > 0)
11847
    printf ("n_b2:%d;", molstat.n_b2);
11848
  if (molstat.n_b3 > 0)
11849
    printf ("n_b3:%d;", molstat.n_b3);
11850
  if (molstat.n_bar > 0)
11851
    printf ("n_bar:%d;", molstat.n_bar);
11852
  if (molstat.n_C1O > 0)
11853
    printf ("n_C1O:%d;", molstat.n_C1O);
11854
  if (molstat.n_C2O > 0)
11855
    printf ("n_C2O:%d;", molstat.n_C2O);
11856
  if (molstat.n_CN > 0)
11857
    printf ("n_CN:%d;", molstat.n_CN);
11858
  if (molstat.n_XY > 0)
11859
    printf ("n_XY:%d;", molstat.n_XY);
11860
  if (molstat.n_r3 > 0)
11861
    printf ("n_r3:%d;", molstat.n_r3);
11862
  if (molstat.n_r4 > 0)
11863
    printf ("n_r4:%d;", molstat.n_r4);
11864
  if (molstat.n_r5 > 0)
11865
    printf ("n_r5:%d;", molstat.n_r5);
11866
  if (molstat.n_r6 > 0)
11867
    printf ("n_r6:%d;", molstat.n_r6);
11868
  if (molstat.n_r7 > 0)
11869
    printf ("n_r7:%d;", molstat.n_r7);
11870
  if (molstat.n_r8 > 0)
11871
    printf ("n_r8:%d;", molstat.n_r8);
11872
  if (molstat.n_r9 > 0)
11873
    printf ("n_r9:%d;", molstat.n_r9);
11874
  if (molstat.n_r10 > 0)
11875
    printf ("n_r10:%d;", molstat.n_r10);
11876
  if (molstat.n_r11 > 0)
11877
    printf ("n_r11:%d;", molstat.n_r11);
11878
  if (molstat.n_r12 > 0)
11879
    printf ("n_r12:%d;", molstat.n_r12);
11880
  if (molstat.n_r13p > 0)
11881
    printf ("n_r13p:%d;", molstat.n_r13p);
11882
  if (molstat.n_rN > 0)
11883
    printf ("n_rN:%d;", molstat.n_rN);
11884
  if (molstat.n_rN1 > 0)
11885
    printf ("n_rN1:%d;", molstat.n_rN1);
11886
  if (molstat.n_rN2 > 0)
11887
    printf ("n_rN2:%d;", molstat.n_rN2);
11888
  if (molstat.n_rN3p > 0)
11889
    printf ("n_rN3p:%d;", molstat.n_rN3p);
11890
  if (molstat.n_rO > 0)
11891
    printf ("n_rO:%d;", molstat.n_rO);
11892
  if (molstat.n_rO1 > 0)
11893
    printf ("n_rO1:%d;", molstat.n_rO1);
11894
  if (molstat.n_rO2p > 0)
11895
    printf ("n_rO2p:%d;", molstat.n_rO2p);
11896
  if (molstat.n_rS > 0)
11897
    printf ("n_rS:%d;", molstat.n_rS);
11898
  if (molstat.n_rX > 0)
11899
    printf ("n_rX:%d;", molstat.n_rX);
11900
  if (molstat.n_rAr > 0)
11901
    printf ("n_rar:%d;", molstat.n_rAr);
11902
/* p2c: checkmol.pas, line 8532:
11903
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11904
  /*$IFDEF extended_molstat */
11905
  if (molstat.n_rBz > 0)
11906
    printf ("n_rbz:%d;", molstat.n_rBz);
11907
  if (molstat.n_br2p > 0)
11908
    printf ("n_br2p:%d;", molstat.n_br2p);
11909
  if (molstat.n_psg01 > 0)
11910
    printf ("n_psg01:%d;", molstat.n_psg01);
11911
  if (molstat.n_psg02 > 0)
11912
    printf ("n_psg02:%d;", molstat.n_psg02);
11913
  if (molstat.n_psg13 > 0)
11914
    printf ("n_psg13:%d;", molstat.n_psg13);
11915
  if (molstat.n_psg14 > 0)
11916
    printf ("n_psg14:%d;", molstat.n_psg14);
11917
  if (molstat.n_psg15 > 0)
11918
    printf ("n_psg15:%d;", molstat.n_psg15);
11919
  if (molstat.n_psg16 > 0)
11920
    printf ("n_psg16:%d;", molstat.n_psg16);
11921
  if (molstat.n_psg17 > 0)
11922
    printf ("n_psg17:%d;", molstat.n_psg17);
11923
  if (molstat.n_psg18 > 0)
11924
    printf ("n_psg18:%d;", molstat.n_psg18);
11925
  if (molstat.n_pstm > 0)
11926
    printf ("n_pstm:%d;", molstat.n_pstm);
11927
  if (molstat.n_psla > 0)
11928
    printf ("n_psla:%d;", molstat.n_psla);
11929
  if (molstat.n_iso > 0)
11930
    printf ("n_iso:%d;", molstat.n_iso);
11931
  if (molstat.n_rad > 0)
11932
    printf ("n_rad:%d;", molstat.n_rad);
11933
  /*$ENDIF */
11934
  putchar ('\n');
11935
}
11936
 
11937
 
11938
static void
11939
write_molstat_X ()
11940
{
11941
  if (auto_ssr)                 /* v0.3n */
11942
    fix_ssr_ringcounts ();
11943
/* p2c: checkmol.pas, line 8556:
11944
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11945
#ifdef REDUCED_SAR
11946
  printf ("%d,", n_heavyatoms);
11947
  printf ("%d,", n_heavybonds);
11948
  printf ("%d,", n_countablerings);
11949
  /* v0.3n: n_rings =?> n_countablerings */
11950
#else
11951
  printf ("%d,", n_heavyatoms);
11952
  printf ("%d,", n_heavybonds);
11953
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
11954
#endif
11955
  printf ("%d,", molstat.n_QA);
11956
  printf ("%d,", molstat.n_QB);
11957
 
11958
  /* 0.3x */
11959
  printf ("%d,", molstat.n_chg);
11960
 
11961
 
11962
  printf ("%d,", molstat.n_C1);
11963
  printf ("%d,", molstat.n_C2);
11964
  printf ("%d,", molstat.n_C);
11965
  printf ("%d,", molstat.n_CHB1p);
11966
  printf ("%d,", molstat.n_CHB2p);
11967
  printf ("%d,", molstat.n_CHB3p);
11968
  printf ("%d,", molstat.n_CHB4);
11969
  printf ("%d,", molstat.n_O2);
11970
  printf ("%d,", molstat.n_O3);
11971
  printf ("%d,", molstat.n_N1);
11972
  printf ("%d,", molstat.n_N2);
11973
  printf ("%d,", molstat.n_N3);
11974
  printf ("%d,", molstat.n_S);
11975
  printf ("%d,", molstat.n_SeTe);
11976
  printf ("%d,", molstat.n_F);
11977
  printf ("%d,", molstat.n_Cl);
11978
  printf ("%d,", molstat.n_Br);
11979
  printf ("%d,", molstat.n_I);
11980
  printf ("%d,", molstat.n_P);
11981
  printf ("%d,", molstat.n_B);
11982
  printf ("%d,", molstat.n_Met);
11983
  printf ("%d,", molstat.n_X);
11984
  printf ("%d,", molstat.n_b1);
11985
  printf ("%d,", molstat.n_b2);
11986
  printf ("%d,", molstat.n_b3);
11987
  printf ("%d,", molstat.n_bar);
11988
  printf ("%d,", molstat.n_C1O);
11989
  printf ("%d,", molstat.n_C2O);
11990
  printf ("%d,", molstat.n_CN);
11991
  printf ("%d,", molstat.n_XY);
11992
  printf ("%d,", molstat.n_r3);
11993
  printf ("%d,", molstat.n_r4);
11994
  printf ("%d,", molstat.n_r5);
11995
  printf ("%d,", molstat.n_r6);
11996
  printf ("%d,", molstat.n_r7);
11997
  printf ("%d,", molstat.n_r8);
11998
  printf ("%d,", molstat.n_r9);
11999
  printf ("%d,", molstat.n_r10);
12000
  printf ("%d,", molstat.n_r11);
12001
  printf ("%d,", molstat.n_r12);
12002
  printf ("%d,", molstat.n_r13p);
12003
  printf ("%d,", molstat.n_rN);
12004
  printf ("%d,", molstat.n_rN1);
12005
  printf ("%d,", molstat.n_rN2);
12006
  printf ("%d,", molstat.n_rN3p);
12007
  printf ("%d,", molstat.n_rO);
12008
  printf ("%d,", molstat.n_rO1);
12009
  printf ("%d,", molstat.n_rO2p);
12010
  printf ("%d,", molstat.n_rS);
12011
  printf ("%d,", molstat.n_rX);
12012
  printf ("%d", molstat.n_rAr);
12013
/* p2c: checkmol.pas, line 8579:
12014
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12015
  /*$IFDEF extended_molstat */
12016
  printf (",%d", molstat.n_rBz);
12017
  printf (",%d", molstat.n_br2p);
12018
  printf (",%d", molstat.n_psg01);
12019
  printf (",%d", molstat.n_psg02);
12020
  printf (",%d", molstat.n_psg13);
12021
  printf (",%d", molstat.n_psg14);
12022
  printf (",%d", molstat.n_psg15);
12023
  printf (",%d", molstat.n_psg16);
12024
  printf (",%d", molstat.n_psg17);
12025
  printf (",%d", molstat.n_psg18);
12026
  printf (",%d", molstat.n_pstm);
12027
  printf (",%d", molstat.n_psla);
12028
  printf (",%d", molstat.n_iso);
12029
  printf (",%d\n", molstat.n_rad);
12030
  /*$ENDIF */
12031
}
12032
 
12033
 
12034
/* routines for substructure matching */
12035
 
12036
 
12037
static int
12038
find_ndl_ref_atom ()
12039
{
6786 kbelabas 12040
  int i;
6785 bpr 12041
  int score = -1, index = 0;
12042
  int n_nb, n_hc, FORLIM;
12043
 
12044
  /* finds a characteristic atom in the needle molecule, */
12045
  /* i.e., one with as many substituents as possible and */
12046
  /* with as many heteroatom substitutents as possible; */
12047
  /* added in v0.2d: make sure that reference atom is a heavy atom */
12048
  /* and not (accidentally) an explicit hydrogen; */
12049
  /* new in v0.3d: special treatment in case of E/Z geometry search */
12050
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
12051
  /* matchpath, regardless where the recursive search starts; */
12052
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
12053
  /* added in v0.3o: needle atom must be "tagged" in order to be */
12054
  /* selected (prevents unconnected fragments from being overlooked) */
12055
  if (ndl_n_atoms == 0)
6786 kbelabas 12056
    return false;
6785 bpr 12057
  if (ez_search && ndl_n_heavyatoms > 2)
12058
    {
12059
      FORLIM = ndl_n_atoms;
12060
      for (i = 1; i <= FORLIM; i++)
12061
        {                       /* ignore sp2-carbons if not aromatic */
12062
          /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = true)) then */
12063
          if (ndl_alkene_C (i) == false && ndl_atom[i - 1].tag)
12064
            {                   /* v0.3o */
12065
              n_nb = ndl_atom[i - 1].neighbor_count;
12066
              n_hc = ndl_hetatom_count (i);
12067
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy)
12068
                {
12069
                  /* v0.3j */
12070
                  index = i;
12071
                  score = n_nb * 11 + n_hc * 7; /* changed in v0.3j */
12072
                }
12073
            }
12074
        }
12075
    }
12076
  /* it is possible that no suitable reference atom has been found here */
12077
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
12078
  if (index == 0)
12079
    {
12080
      ez_search = false;        /* just in case it was true */
12081
      opt_geom = false;         /* just in case it was true */
12082
      FORLIM = ndl_n_atoms;
12083
      for (i = 1; i <= FORLIM; i++)
12084
        {
12085
          n_nb = ndl_atom[i - 1].neighbor_count;
12086
          n_hc = ndl_hetatom_count (i);
12087
          if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
12088
              ndl_atom[i - 1].tag)
12089
            {                   /* v0.3j */
12090
              index = i;
12091
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
12092
            }
12093
          /* v0.3o */
12094
        }
12095
    }
12096
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
12097
  if (index == 0)               /* just to be sure... */
12098
    index++;
12099
  return index;
12100
}
12101
 
12102
 
12103
static void
12104
cv_init ()
12105
{
12106
  /* new in v0.3j */
12107
  int i;
12108
 
12109
  if (cv == NULL)
12110
    return;
12111
  memset (cv, 0, sizeof (connval_type));
12112
 
12113
  for (i = 0; i < ndl_n_atoms; i++)
12114
    cv[i].def = ndl_atom[i].neighbor_count;
12115
}
12116
 
12117
 
12118
static int
12119
cv_count ()
12120
{
12121
  /* new in v0.3j, modified in v0.3m */
12122
  int i, j;
12123
  int cvlist[max_atoms];
12124
  int cvdef;
12125
  boolean isnew;
12126
  int entries = 0;
12127
  int FORLIM;
12128
 
12129
  if (cv == NULL)
12130
    return 0;
12131
  memset (cvlist, 0, sizeof (int) * max_atoms);
12132
  FORLIM = ndl_n_atoms;
12133
  for (i = 0; i < FORLIM; i++)
12134
    {
12135
      if (ndl_atom[i].heavy == true)
12136
        {
12137
          cvdef = cv[i].def;
12138
          isnew = true;
12139
          if (entries > 0)
12140
            {
12141
              for (j = 0; j < entries; j++)
12142
                {
12143
                  if (cvlist[j] == cvdef)
12144
                    isnew = false;
12145
                }
12146
            }
12147
          if (isnew)
12148
            {
12149
              entries++;
12150
              cvlist[entries - 1] = cvdef;
12151
            }
12152
          /* now we have a list of unique connection values */
12153
        }
12154
    }
12155
  return entries;
12156
}
12157
 
12158
 
12159
static int
12160
cv_iterate (n_cv_prev)
12161
     int n_cv_prev;
12162
{
12163
  /* new in v0.3j, modified in v0.3m */
12164
  int Result, i, j;
12165
  neighbor_rec nb;
12166
  int nnb, nsum, n_cv, FORLIM;
12167
 
12168
  if (cv == NULL || ndl_n_atoms == 0)
12169
    return Result;
12170
  FORLIM = ndl_n_atoms;
12171
  /* update the connection values (Morgan algorithm) */
12172
 
12173
  memset (nb, 0, sizeof (neighbor_rec));
12174
 
12175
  for (i = 1; i <= FORLIM; i++)
12176
    {
12177
      if (ndl_atom[i - 1].heavy == true)
12178
        {
12179
          get_ndl_neighbors (nb, i);
12180
          nnb = ndl_atom[i - 1].neighbor_count;
12181
          nsum = 0;
12182
          if (nnb > 0)
12183
            {
12184
              for (j = 0; j < nnb; j++)
12185
                {
12186
                  if (ndl_atom[nb[j] - 1].heavy == true)
12187
                    nsum += cv[nb[j] - 1].def;
12188
                }
12189
            }
12190
          cv[i - 1].tmp = nsum;
12191
        }
12192
    }
12193
  n_cv = cv_count ();
12194
  if (n_cv > n_cv_prev)
12195
    {
12196
      FORLIM = ndl_n_atoms;
12197
      for (i = 0; i < FORLIM; i++)
12198
        cv[i].def = cv[i].tmp;
12199
    }
12200
  return n_cv;
12201
}
12202
 
12203
 
12204
static int
12205
find_ndl_ref_atom_cv ()
12206
{
12207
  /* new in v0.3j, modified in v0.3m */
12208
  int Result, i;
12209
  int res = 1, it = 0;
12210
  int n_cv;
12211
  int n_cv_prev = 0;
12212
  boolean finished = false;
12213
  int cvmax = 0;
12214
  int FORLIM;
12215
 
12216
  if (ndl_n_atoms == 0)
12217
    return 0;
12218
  /* try */
12219
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
12220
  /* except
12221
     on e:Eoutofmemory do
12222
     begin
12223
     res := find_ndl_ref_atom;
12224
     $IFDEF debug
12225
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
12226
     $ENDIF
12227
     end;
12228
     end; */
12229
  cv_init ();
12230
  do
12231
    {
12232
      it++;                     /* iteration counter (a safeguard against infinite loops) */
12233
      n_cv = cv_iterate (n_cv_prev);
12234
      if (n_cv <= n_cv_prev)
12235
        finished = true;
12236
      n_cv_prev = n_cv;
12237
    }
12238
  while (!(finished || it > 10000));
12239
  FORLIM = ndl_n_atoms;
12240
  /* now that we have canonical connection values (Morgan algorithm), */
12241
  /* pick the atom with the highest value */
12242
  /* added in v0.3o: atom must be "tagged" */
12243
  for (i = 1; i <= FORLIM; i++)
12244
    {
12245
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
12246
      if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == false ||
12247
                                       ez_search == false))
12248
          && ndl_atom[i - 1].tag)
12249
        {                       /* v0.3o */
12250
          cvmax = cv[i - 1].def;
12251
          res = i;
12252
        }
12253
    }
12254
  Result = res;
12255
  /* try */
12256
  if (cv != NULL)
12257
    {
12258
      free (cv);
12259
      cv = NULL;
12260
    }
12261
  /* except
12262
     on e:Einvalidpointer do begin end;
12263
     end; */
12264
  return Result;
12265
}
12266
 
12267
 
12268
static boolean
12269
atomtypes_OK_strict (ndl_a, hst_a)
12270
     int ndl_a, hst_a;
12271
{
12272
  /* new in v0.2f */
12273
  str2 ndl_el;
12274
  str3 ndl_atype;
12275
  str2 hst_el;
12276
  str3 hst_atype;
12277
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
12278
  boolean res = false;
12279
 
12280
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
12281
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
12282
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
12283
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
12284
  strcpy (hst_el, atom[hst_a - 1].element);
12285
  strcpy (hst_atype, atom[hst_a - 1].atype);
12286
  hst_nbc = atom[hst_a - 1].neighbor_count;
12287
  hst_Htot = atom[hst_a - 1].Htot;
12288
  /* v0.3o: formal charges must be the same */
12289
 
12290
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12291
    return false;
12292
 
12293
  /* v0.3x: isotope nucleon numbers must be the same */
12294
 
12295
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
12296
    return false;
12297
 
12298
  /* v0.3x: radicals must be the same */
12299
 
12300
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12301
    return false;
12302
 
12303
  if (!strcmp (ndl_atype, hst_atype))
12304
    res = true;
12305
  else
12306
    {
12307
      if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom &&
12308
          atom[hst_a - 1].arom)
12309
        res = true;
12310
      if (ndl_querymol
12311
          && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
12312
        res = true;             /* 0.3 p */
12313
    }
12314
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
12315
    res = true;
12316
  if (!strcmp (ndl_el, "Q "))
12317
    {
12318
      if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
12319
        res = true;
12320
    }
12321
  if (!strcmp (ndl_el, "X "))
12322
    {
12323
      if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
12324
          !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
12325
          || !strcmp (hst_el, "AT"))
12326
        res = true;
12327
    }
12328
  /* if needle atom has more substituents than haystack atom ==> no match */
12329
  if (ndl_nbc > hst_nbc)
12330
    res = false;
12331
  /* check for explicit hydrogens */
12332
  if (ndl_Hexp > hst_Htot)
12333
    res = false;
12334
/* p2c: checkmol.pas, line 8859:
12335
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12336
  /*$IFDEF debug */
12337
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
12338
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
12339
  /*$ENDIF */
12340
  /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
12341
  if (opt_fp)
12342
    {
12343
      if (strcmp (ndl_el, hst_el))
12344
        res = false;
12345
    }
12346
  return res;
12347
}
12348
 
12349
 
12350
static boolean
12351
atomtypes_OK (ndl_a, hst_a)
12352
     int ndl_a, hst_a;
12353
{
12354
  str2 ndl_el, hst_el;
12355
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
12356
  boolean res = false;
12357
 
12358
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
12359
    return false;
12360
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
12361
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
12362
  /* are tolerated (this is a feature, not a bug) */
12363
  if (opt_chg)
12364
    {
12365
      if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12366
        return false;
12367
    }
12368
//  else
12369
//    {
12370
//      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
12371
//        atom[hst_a - 1].formal_charge != 0 &&
12372
//        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12373
//      return false;
12374
//    }
12375
//
12376
//  /* v0.3x: isotopes must be the same */
12377
  if (opt_iso)
12378
    {
12379
      if (ndl_atom[ndl_a - 1].nucleon_number !=
12380
          atom[hst_a - 1].nucleon_number)
12381
        return false;
12382
    }
12383
//  else
12384
//    {
12385
//      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
12386
//        atom[hst_a - 1].nucleon_number != 0 &&
12387
//        ndl_atom[ndl_a - 1].nucleon_number !=
12388
//        atom[hst_a - 1].nucleon_number)
12389
//      return false;
12390
//    }
12391
//
12392
//  /* v0.3x: radicals must be the same */
12393
  if (opt_rad)
12394
    {
12395
      if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12396
        return false;
12397
    }
12398
//  else
12399
//    {
12400
//      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
12401
//        atom[hst_a - 1].radical_type != 0 &&
12402
//        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12403
//      return false;
12404
//    }
12405
 
12406
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
12407
  if (opt_exact && atom[hst_a - 1].tag == true)
12408
    {
12409
/* p2c: checkmol.pas, line 8899:
12410
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12411
      /*$IFDEF debug */
12412
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
12413
      /*$ENDIF */
12414
      return false;
12415
    }
12416
  if (opt_strict)               /* new in v0.2f */
12417
    return (atomtypes_OK_strict (ndl_a, hst_a));
12418
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
12419
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
12420
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
12421
  strcpy (hst_el, atom[hst_a - 1].element);
12422
  hst_nbc = atom[hst_a - 1].neighbor_count;
12423
  hst_Htot = atom[hst_a - 1].Htot;
12424
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
12425
    res = true;
12426
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
12427
    res = true;
12428
  if (!strcmp (ndl_el, "Q "))
12429
    {
12430
      if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
12431
        res = true;
12432
    }
12433
  if (!strcmp (ndl_el, "X "))
12434
    {
12435
      if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
12436
          !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
12437
          || !strcmp (hst_el, "AT"))
12438
        res = true;
12439
    }
12440
  /* v0.3o: in exact mode, check for identical neighbor_count */
12441
  if (opt_exact)
12442
    {
12443
      if (ndl_nbc != hst_nbc)
12444
        {
12445
          res = false;
12446
/* p2c: checkmol.pas, line 8934:
12447
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12448
          /*$IFDEF debug */
12449
          //debugoutput
12450
          //  ("exact match failed: different number of neighbor atoms");
12451
          /*$ENDIF */
12452
        }
12453
    }
12454
  /* if needle atom has more substituents than haystack atom ==> no match */
12455
  if (ndl_nbc > hst_nbc)
12456
    res = false;
12457
  /* check for explicit hydrogens */
12458
  if (ndl_Hexp > hst_Htot)
12459
    res = false;
12460
/* p2c: checkmol.pas, line 8943:
12461
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12462
  /*$IFDEF debug */
12463
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
12464
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
12465
  /*$ENDIF */
12466
  return res;
12467
}
12468
 
12469
 
12470
static boolean
12471
bondtypes_OK_strict (ndl_b, hst_b)
12472
     int ndl_b, hst_b;
12473
{
12474
  boolean ndl_arom, hst_arom;
12475
  char ndl_btype, hst_btype;
12476
  int ndl_rc;                   /* new in v0.3d */
12477
  int hst_rc;                   /* new in v0.3d */
12478
  int ndl_btopo;                /* new in v0.3d */
12479
  boolean res = false;
12480
/* p2c: checkmol.pas, line 8960:
12481
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12482
  /*$IFDEF debug */
12483
  /*char na[256]; char ha[256];*/
12484
  char tstr[256];
12485
 
12486
  /*$ENDIF */
12487
/* p2c: checkmol.pas, line 8966:
12488
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12489
  /*$IFDEF debug */
12490
  *tstr = '\0';                 /* for debugging purposes only */
12491
  /*$ENDIF */
12492
  ndl_arom = ndl_bond[ndl_b - 1].arom;
12493
  ndl_btype = ndl_bond[ndl_b - 1].btype;
12494
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
12495
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
12496
  hst_arom = bond[hst_b - 1].arom;
12497
  hst_btype = bond[hst_b - 1].btype;
12498
  hst_rc = bond[hst_b - 1].ring_count;
12499
/* p2c: checkmol.pas, line 8976:
12500
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12501
  /*$IFDEF debug */
12502
  /*if (ndl_arom)
12503
    strcpy (na, "(ar)");
12504
  else
12505
    *na = '\0';
12506
  if (hst_arom)
12507
    strcpy (ha, "(ar)");
12508
  else
12509
    *ha = '\0';*/
12510
  /*$ENDIF */
12511
  if (ndl_arom == true && hst_arom == true)
12512
    res = true;
12513
  if (ndl_arom == false && hst_arom == false)
12514
    {
12515
      if (ndl_btype == hst_btype)
12516
        res = true;
12517
      if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
12518
        res = true;
12519
      if (ndl_btype == 's' && hst_btype == 'S')
12520
        res = true;
12521
      if (ndl_btype == 'd' && hst_btype == 'D')
12522
        res = true;
12523
    }
12524
  /* a little exception: */
12525
  if (ndl_arom == false && hst_arom == true)
12526
    {
12527
      if (ndl_btype == 'A')
12528
        res = true;
12529
      if (ndl_btype == 's' || ndl_btype == 'd')
12530
        res = true;
12531
      if (ndl_bond[ndl_b - 1].q_arom)
12532
        res = true;             /* 0.3p */
12533
    }
12534
  if (ndl_btype == 'a')
12535
    res = true;
12536
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
12537
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc)
12538
    {
12539
      if (ndl_rc != hst_rc)
12540
        {
12541
          res = false;          /* this excludes further ring annulations as well as */
12542
/* p2c: checkmol.pas, line 9001:
12543
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12544
          /*$IFDEF debug */
12545
          /* open-chains query structures to be found in rings */
12546
          /*
12547
             tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
12548
          /*$ENDIF */
12549
        }
12550
    }
12551
  else
12552
    {
12553
      if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
12554
        {
12555
          res = false;
12556
/* p2c: checkmol.pas, line 9010:
12557
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12558
          /*$IFDEF debug */
12559
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
12560
          /*$ENDIF */
12561
        }
12562
    }
12563
/* p2c: checkmol.pas, line 9015:
12564
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12565
  /*$IFDEF debug */
12566
  /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
12567
     debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
12568
  /*$ENDIF */
12569
  return res;
12570
}
12571
 
12572
 
12573
static boolean
12574
bondtypes_OK (ndl_b, hst_b)
12575
     int ndl_b, hst_b;
12576
{
12577
  boolean ndl_arom, hst_arom;
12578
  char ndl_btype, hst_btype;
12579
  int ndl_rc;                   /* new in v0.3d */
12580
  int hst_rc;                   /* new in v0.3d */
12581
  int ndl_btopo;                /* new in v0.3d */
12582
  boolean res = false;
12583
/* p2c: checkmol.pas, line 9032:
12584
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12585
  /*$IFDEF debug */
12586
  /*char na[256], ha[256];*/
12587
  char tstr[256];
12588
  /*$ENDIF */
12589
  int a1, a2;
12590
  str2 a1_el, a2_el;
12591
 
12592
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
12593
    return false;
12594
  if (opt_strict)               /* new in v0.2f */
12595
    return (bondtypes_OK_strict (ndl_b, hst_b));
12596
/* p2c: checkmol.pas, line 9051:
12597
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12598
  /*$IFDEF debug */
12599
  *tstr = '\0';                 /* for debug purposes only */
12600
  /*$ENDIF */
12601
  ndl_arom = ndl_bond[ndl_b - 1].arom;
12602
  ndl_btype = ndl_bond[ndl_b - 1].btype;
12603
  hst_arom = bond[hst_b - 1].arom;
12604
  hst_btype = bond[hst_b - 1].btype;
12605
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
12606
  hst_rc = bond[hst_b - 1].ring_count;
12607
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
12608
/* p2c: checkmol.pas, line 9061:
12609
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12610
  /*$IFDEF debug */
12611
  //if (ndl_arom)
12612
//    strcpy (na, "(ar)");
12613
//  else
12614
//    *na = '\0';
12615
//  if (hst_arom)
12616
//    strcpy (ha, "(ar)");
12617
//  else
12618
//    *ha = '\0';
12619
  /*$ENDIF */
12620
  if (ndl_arom == true && hst_arom == true)
12621
    res = true;
12622
  if (ndl_arom == false && hst_arom == false)
12623
    {
12624
      if (ndl_btype == hst_btype)
12625
        res = true;
12626
      if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
12627
        res = true;
12628
      if (ndl_btype == 's' && hst_btype == 'S')
12629
        res = true;
12630
      if (ndl_btype == 'd' && hst_btype == 'D')
12631
        res = true;
12632
    }
12633
  /* a little exception: */
12634
  if (ndl_arom == false && hst_arom == true)
12635
    {
12636
      if (ndl_btype == 'A')
12637
        res = true;
12638
      if (ndl_btype == 's' || ndl_btype == 'd')
12639
        res = true;
12640
      if (ndl_btype == 'D')
12641
        {                       /* added in 0.2d: do not accept C=O etc. as C-O/arom */
12642
          a1 = ndl_bond[ndl_b - 1].a1;
12643
          a2 = ndl_bond[ndl_b - 1].a2;
12644
          strcpy (a1_el, ndl_atom[a1 - 1].element);
12645
          strcpy (a2_el, ndl_atom[a2 - 1].element);
12646
          if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
12647
              && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
12648
              && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
12649
              && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
12650
            res = true;
12651
        }
12652
      if (ndl_bond[ndl_b - 1].q_arom)
12653
        res = true;             /* 0.3p */
12654
    }
12655
  if (ndl_btype == 'a')
12656
    res = true;
12657
  /* new in v0.3d: obey topology requirements in query structure */
12658
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any)
12659
    {
12660
  if (ndl_btopo == btopo_ring && hst_rc == 0)
12661
    res = false;
12662
  if (ndl_btopo == btopo_chain && hst_rc > 0)
12663
    res = false;
12664
  if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
12665
    res = false;
12666
  if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
12667
    res = false;
12668
}    
12669
/* p2c: checkmol.pas, line 9098:
12670
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12671
  /*$IFDEF debug */
12672
  /* if res = false then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
12673
  /*$ENDIF */
12674
/* p2c: checkmol.pas, line 9102:
12675
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12676
  /*$IFDEF debug */
12677
  /*
12678
     if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
12679
     debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
12680
  /*$ENDIF */
12681
  return res;
12682
}
12683
 
12684
 
12685
static boolean
12686
matrix_OK (m, ndl_dim, hst_dim)
12687
boolean (*m)[max_neighbors];
12688
     int ndl_dim, hst_dim;
12689
{
12690
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
12691
  boolean mr = false;
12692
  matchmatrix lm;
12693
  int i, ii, j, lndl_dim, lhst_dim;
12694
 
12695
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
12696
      hst_dim > max_neighbors || ndl_dim > hst_dim)
12697
    return false;
12698
  if (ndl_dim == 1)
12699
    {
12700
      for (i = 0; i < hst_dim; i++)
12701
        {
12702
          if (m[0][i])
12703
            mr = true;
12704
        }
12705
      return mr;
12706
    }
12707
  for (i = 1; i <= hst_dim; i++)
12708
    {
12709
      if (m[0][i - 1])
12710
        {
12711
          /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
12712
          memset (lm, false, sizeof (matchmatrix));
12713
          for (j = 2; j <= ndl_dim; j++)
12714
            {
12715
              lhst_dim = 0;
12716
              for (ii = 1; ii <= hst_dim; ii++)
12717
                {
12718
                  if (ii != i)
12719
                    {
12720
                      lhst_dim++;
12721
                      lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
12722
                    }
12723
                }
12724
            }
12725
          lndl_dim = ndl_dim - 1;
12726
          if (matrix_OK (lm, lndl_dim, lhst_dim))
12727
            {                   /* recursive call to matrix_OK */
12728
              return true;
12729
              /* stop any further work immediately */
12730
            }
12731
        }
12732
    }
12733
  return false;
12734
}
12735
 
12736
 
12737
static boolean
12738
is_flat (angle_deg)
12739
     double angle_deg;
12740
{
12741
  /* new in v0.3j */
12742
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
12743
    return false;
12744
  else
12745
    return true;
12746
}
12747
 
12748
 
12749
static boolean
12750
chirality_OK (ndl_cp, hst_cp)
12751
     int *ndl_cp, *hst_cp;
12752
{
12753
  boolean res = true;
12754
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
12755
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
12756
  int level = 0;
12757
  int i;
12758
  boolean up = false, down = false, updown = false;
12759
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
12760
 
12761
  /* fill temporary atom variables */
12762
  ta1 = ndl_cp[0];              /* this is the central atom */
12763
  ta2 = ndl_cp[1];
12764
  ta3 = ndl_cp[2];
12765
  ta4 = ndl_cp[3];
12766
  /* first, get the central atom of the needle */
12767
  np2.x = ndl_atom[ta1 - 1].x;
12768
  np2.y = ndl_atom[ta1 - 1].y;
12769
  np2.z = ndl_atom[ta1 - 1].z;
12770
  /* next, do the same for all 3 substituent atoms */
12771
  np1.x = ndl_atom[ta2 - 1].x;
12772
  np1.y = ndl_atom[ta2 - 1].y;
12773
  np1.z = ndl_atom[ta2 - 1].z;
12774
  np3.x = ndl_atom[ta3 - 1].x;
12775
  np3.y = ndl_atom[ta3 - 1].y;
12776
  np3.z = ndl_atom[ta3 - 1].z;
12777
  np4.x = ndl_atom[ta4 - 1].x;
12778
  np4.y = ndl_atom[ta4 - 1].y;
12779
  np4.z = ndl_atom[ta4 - 1].z;
12780
  /* now check all needle bonds if we should care about up/down bonds */
12781
  if (ndl_n_bonds > 0)
12782
    {
12783
      FORLIM = ndl_n_bonds;
12784
      for (i = 0; i < FORLIM; i++)
12785
        {
12786
          if (ndl_bond[i].stereo == bstereo_up ||
12787
              ndl_bond[i].stereo == bstereo_down)
12788
            {
12789
              ba1 = ndl_bond[i].a1;
12790
              ba2 = ndl_bond[i].a2;
12791
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up)
12792
                {
12793
                  up = true;
12794
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12795
                    {
12796
                      updown = true;
12797
                      if (ba2 == ta2)
12798
                        np1.z += 0.8;
12799
                      if (ba2 == ta3)
12800
                        np3.z += 0.8;
12801
                      if (ba2 == ta4)
12802
                        np4.z += 0.8;
12803
                    }
12804
                  else
12805
                    level++;
12806
                }
12807
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down)
12808
                {
12809
                  down = true;
12810
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12811
                    {
12812
                      updown = true;
12813
                      if (ba2 == ta2)
12814
                        np1.z -= 0.8;
12815
                      if (ba2 == ta3)
12816
                        np3.z -= 0.8;
12817
                      if (ba2 == ta4)
12818
                        np4.z -= 0.8;
12819
                    }
12820
                  else
12821
                    level--;
12822
                }
12823
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up)
12824
                {
12825
                  down = true;
12826
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12827
                    {
12828
                      updown = true;
12829
                      if (ba1 == ta2)
12830
                        np1.z -= 0.8;
12831
                      if (ba1 == ta3)
12832
                        np3.z -= 0.8;
12833
                      if (ba1 == ta4)
12834
                        np4.z -= 0.8;
12835
                    }
12836
                  else
12837
                    level--;
12838
                }
12839
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down)
12840
                {
12841
                  up = true;
12842
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12843
                    {
12844
                      updown = true;
12845
                      if (ba1 == ta2)
12846
                        np1.z += 0.8;
12847
                      if (ba1 == ta3)
12848
                        np3.z += 0.8;
12849
                      if (ba1 == ta4)
12850
                        np4.z += 0.8;
12851
                    }
12852
                  else
12853
                    level++;
12854
                }
12855
            }
12856
        }                       /* for i ... */
12857
      if (updown == false && level != 0)
12858
        {
12859
          if (level > 0)
12860
            np2.z += 0.3;
12861
          if (level < 0)
12862
            np2.z -= 0.3;
12863
        }
12864
      else
12865
        {
12866
          if (up)
12867
            np2.z += 0.1;
12868
          if (down)
12869
            np2.z -= 0.1;
12870
        }
12871
    }
12872
  /* fill temporary atom variables again */
12873
  ta1 = hst_cp[0];
12874
  ta2 = hst_cp[1];
12875
  ta3 = hst_cp[2];
12876
  ta4 = hst_cp[3];
12877
  /* then, get the central atom of the haystack */
12878
  hp2.x = atom[ta1 - 1].x;
12879
  hp2.y = atom[ta1 - 1].y;
12880
  hp2.z = atom[ta1 - 1].z;
12881
  /* next, do the same for all 3 substituent atoms */
12882
  hp1.x = atom[ta2 - 1].x;
12883
  hp1.y = atom[ta2 - 1].y;
12884
  hp1.z = atom[ta2 - 1].z;
12885
  hp3.x = atom[ta3 - 1].x;
12886
  hp3.y = atom[ta3 - 1].y;
12887
  hp3.z = atom[ta3 - 1].z;
12888
  hp4.x = atom[ta4 - 1].x;
12889
  hp4.y = atom[ta4 - 1].y;
12890
  hp4.z = atom[ta4 - 1].z;
12891
  /* now check all haystack bonds if we should care about up/down bonds */
12892
  level = 0;
12893
  updown = false;
12894
  up = false;
12895
  down = false;
12896
  if (n_bonds > 0)
12897
    {
12898
      FORLIM = n_bonds;
12899
      for (i = 0; i < FORLIM; i++)
12900
        {
12901
          if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down)
12902
            {
12903
              ba1 = bond[i].a1;
12904
              ba2 = bond[i].a2;
12905
              if (ba1 == ta1 && bond[i].stereo == bstereo_up)
12906
                {
12907
                  up = true;
12908
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12909
                    {
12910
                      updown = true;
12911
                      if (ba2 == ta2)
12912
                        hp1.z += 0.8;
12913
                      if (ba2 == ta3)
12914
                        hp3.z += 0.8;
12915
                      if (ba2 == ta4)
12916
                        hp4.z += 0.8;
12917
                    }
12918
                  else
12919
                    level++;
12920
                }
12921
              if (ba1 == ta1 && bond[i].stereo == bstereo_down)
12922
                {
12923
                  down = true;
12924
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12925
                    {
12926
                      updown = true;
12927
                      if (ba2 == ta2)
12928
                        hp1.z -= 0.8;
12929
                      if (ba2 == ta3)
12930
                        hp3.z -= 0.8;
12931
                      if (ba2 == ta4)
12932
                        hp4.z -= 0.8;
12933
                    }
12934
                  else
12935
                    level--;
12936
                }
12937
              if (ba2 == ta1 && bond[i].stereo == bstereo_up)
12938
                {
12939
                  down = true;
12940
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12941
                    {
12942
                      updown = true;
12943
                      if (ba1 == ta2)
12944
                        hp1.z -= 0.8;
12945
                      if (ba1 == ta3)
12946
                        hp3.z -= 0.8;
12947
                      if (ba1 == ta4)
12948
                        hp4.z -= 0.8;
12949
                    }
12950
                  else
12951
                    level--;
12952
                }
12953
              if (ba2 == ta1 && bond[i].stereo == bstereo_down)
12954
                {
12955
                  up = true;
12956
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12957
                    {
12958
                      updown = true;
12959
                      if (ba1 == ta2)
12960
                        hp1.z += 0.8;
12961
                      if (ba1 == ta3)
12962
                        hp3.z += 0.8;
12963
                      if (ba1 == ta4)
12964
                        hp4.z += 0.8;
12965
                    }
12966
                  else
12967
                    level++;
12968
                }
12969
            }
12970
        }                       /* for i ... */
12971
      if (updown == false && level != 0)
12972
        {
12973
          if (level > 0)
12974
            hp2.z += 0.3;
12975
          if (level < 0)
12976
            hp2.z -= 0.3;
12977
        }
12978
      else
12979
        {
12980
          if (up)
12981
            hp2.z += 0.1;
12982
          if (down)
12983
            hp2.z -= 0.1;
12984
        }
12985
    }
12986
  /* get the pseudo-torsion angles */
12987
  ndl_ct = ctorsion (np1, np2, np3, np4);
12988
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
12989
  ndl_ct_deg = radtodeg (ndl_ct);
12990
  hst_ct_deg = radtodeg (hst_ct);
12991
  /* now do a plausibility check and finally check the sense */
12992
  /* (clockwise or counterclockwise) */
12993
  /*
12994
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
12995
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
12996
     (ndl_ct_deg * hst_ct_deg < 0) then res := false;
12997
   */
12998
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
12999
      ndl_ct_deg * hst_ct_deg < 0)
13000
    res = false;
13001
  if (rs_strict)
13002
    {
13003
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) |
13004
           (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
13005
          ndl_ct_deg * hst_ct_deg < 0)
13006
        res = false;
13007
    }
13008
  return res;
13009
}
13010
 
13011
 
13012
static boolean
13013
ndl_maybe_chiral (na)
13014
     int na;
13015
{
13016
  /* new in v0.3h */
13017
  boolean res = false;
13018
  str2 el;
13019
  str3 at;
13020
  int n_nb;
13021
 
13022
  strcpy (el, ndl_atom[na - 1].element);
13023
  strcpy (at, ndl_atom[na - 1].atype);
13024
  n_nb = ndl_atom[na - 1].neighbor_count;
13025
  if (!strcmp (at, "C3 ") && n_nb > 2)
13026
    res = true;
13027
  if (!strcmp (el, "N "))
13028
    {
13029
      if (!strcmp (at, "N3+") && n_nb == 4)
13030
        res = true;
13031
    }
13032
  if (!strcmp (el, "S "))
13033
    {                           /* sulfoxide */
13034
      if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
13035
        res = true;
13036
    }
13037
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
13038
    return res;
13039
  if (n_nb > 3)                 /* are we missing something here? */
13040
    res = true;
13041
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
13042
    res = false;
13043
  return res;
13044
}
13045
 
13046
 
13047
static boolean
13048
is_matching (ndl_xmp, hst_xmp)
13049
     int *ndl_xmp, *hst_xmp;
13050
{
13051
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
13052
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
13053
  int next_ndl_a, next_hst_a;
13054
  neighbor_rec ndl_nb, hst_nb;
13055
  matchmatrix mm;
13056
  int ndl_mp_len, hst_mp_len;
13057
  matchpath_type ndl_mp, hst_mp;
13058
  boolean emptyline, res, ndl_cis, hst_cis;
13059
  int na1, na2, na3, na4;       /* v0.3d */
13060
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
13061
  int prev_ndl_b;
13062
  int prev_hst_b;
13063
  p_3d p1, p2, p3, p4;
13064
  /*hst_torsion, ndl_torsion : double; */
13065
  chirpath_type ncp, hcp;
13066
  int n_hits, n_singlehits;
13067
/* p2c: checkmol.pas, line 9433:
13068
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13069
  /*$IFDEF debug */
13070
  //char tmpstr[256];
13071
 
13072
  /*$ENDIF */
13073
  /* initialize local matchpath variables */
13074
  //memset (ndl_mp, 0, sizeof (matchpath_type));
13075
  //memset (hst_mp, 0, sizeof (matchpath_type));
13076
  /* copy content of external variables into local ones */
13077
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
13078
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
13079
 
13080
  /*for (i = 0; i < max_matchpath_length; i++)
13081
     {
13082
     ndl_mp[i] = ndl_xmp[i];
13083
     hst_mp[i] = hst_xmp[i];
13084
     } */
13085
 
13086
 
13087
  ndl_mp_len = matchpath_length (ndl_mp);
13088
  hst_mp_len = matchpath_length (hst_mp);
13089
  if (ndl_mp_len != hst_mp_len)
13090
    {
13091
      /* this should never happen.... */
13092
/* p2c: checkmol.pas, line 9451:
13093
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13094
      /*$IFDEF debug */
13095
      //debugoutput ("needle and haystack matchpaths are of different length");
13096
      /*$ENDIF */
13097
      return false;
13098
    }
13099
  ndl_a = ndl_mp[ndl_mp_len - 1];
13100
  hst_a = hst_mp[hst_mp_len - 1];
13101
  ndl_atom[ndl_a - 1].tag = false;
13102
  /* new in v0.3o: mark the last needle atom as "visited" */
13103
  if (ndl_mp_len > 1)
13104
    {
13105
      prev_ndl_a = ndl_mp[ndl_mp_len - 2];
13106
      prev_hst_a = hst_mp[hst_mp_len - 2];
13107
    }
13108
  /* if geometry checking is on, check it here */
13109
  if (ez_search == true && ndl_mp_len > 3)
13110
    {
13111
      na1 = ndl_mp[ndl_mp_len - 1];
13112
      na2 = ndl_mp[ndl_mp_len - 2];
13113
      na3 = ndl_mp[ndl_mp_len - 3];
13114
      na4 = ndl_mp[ndl_mp_len - 4];
13115
      ha1 = hst_mp[hst_mp_len - 1];
13116
      ha2 = hst_mp[hst_mp_len - 2];
13117
      ha3 = hst_mp[hst_mp_len - 3];
13118
      ha4 = hst_mp[hst_mp_len - 4];
13119
      prev_ndl_b = get_ndl_bond (na2, na3);
13120
      prev_hst_b = get_bond (ha2, ha3);
13121
      if (ndl_bond[prev_ndl_b - 1].btype == 'D' &&
13122
          bond[prev_hst_b - 1].arom == false
13123
          && (ndl_bond[prev_ndl_b - 1].stereo !=
13124
              bstereo_double_either && bond[prev_hst_b - 1].stereo !=
13125
              bstereo_double_either)
13126
          /* 0.3x always match if needle and/or haystack bond is double_either */
13127
          &&
13128
          (!strcmp (atom[ha2 - 1].element, "C ")
13129
           || !strcmp (atom[ha2 - 1].element, "N "))
13130
          && (!strcmp (atom[ha3 - 1].element, "C ")
13131
              || !strcmp (atom[ha3 - 1].element, "N ")))
13132
        {                       /* v0.3g; check C=C, C=N, N=N bonds */
13133
          p1.x = atom[ha1 - 1].x;
13134
          p1.y = atom[ha1 - 1].y;
13135
          p1.z = atom[ha1 - 1].z;
13136
          p2.x = atom[ha2 - 1].x;
13137
          p2.y = atom[ha2 - 1].y;
13138
          p2.z = atom[ha2 - 1].z;
13139
          p3.x = atom[ha3 - 1].x;
13140
          p3.y = atom[ha3 - 1].y;
13141
          p3.z = atom[ha3 - 1].z;
13142
          p4.x = atom[ha4 - 1].x;
13143
          p4.y = atom[ha4 - 1].y;
13144
          p4.z = atom[ha4 - 1].z;
13145
          hst_cis = is_cis (p1, p2, p3, p4);
13146
          /*hst_torsion := torsion(p1,p2,p3,p4); */
13147
          p1.x = ndl_atom[na1 - 1].x;
13148
          p1.y = ndl_atom[na1 - 1].y;
13149
          p1.z = ndl_atom[na1 - 1].z;
13150
          p2.x = ndl_atom[na2 - 1].x;
13151
          p2.y = ndl_atom[na2 - 1].y;
13152
          p2.z = ndl_atom[na2 - 1].z;
13153
          p3.x = ndl_atom[na3 - 1].x;
13154
          p3.y = ndl_atom[na3 - 1].y;
13155
          p3.z = ndl_atom[na3 - 1].z;
13156
          p4.x = ndl_atom[na4 - 1].x;
13157
          p4.y = ndl_atom[na4 - 1].y;
13158
          p4.z = ndl_atom[na4 - 1].z;
13159
          /*ndl_torsion := torsion(p1,p2,p3,p4); */
13160
          ndl_cis = is_cis (p1, p2, p3, p4);
13161
          if (ndl_cis != hst_cis)
13162
            {
13163
/* p2c: checkmol.pas, line 9501:
13164
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13165
              /*$IFDEF debug */
13166
              //debugoutput ("E/Z geometry mismatch");
13167
              /*$ENDIF */
13168
              return false;
13169
            }
13170
        }
13171
    }                           /* end of E/Z geometry check */
13172
  /* check whatever can be checked as early as now: */
13173
  /* e.g. different elements or more substituents on needle atom than on haystack */
13174
  if (!atomtypes_OK (ndl_a, hst_a))
13175
    return false;
13176
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
13177
  if (atom[hst_a - 1].neighbor_count == 0 &&
13178
      ndl_atom[ndl_a - 1].neighbor_count == 0)
13179
    {
13180
      if (!atomtypes_OK (ndl_a, hst_a))
13181
        return false;
13182
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
13183
      atom[hst_a - 1].tag = true;
13184
      return true;
13185
    }
13186
  /* and other possibilities: */
13187
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
13188
  hst_b = get_bond (prev_hst_a, hst_a);
13189
/* p2c: checkmol.pas, line 9529:
13190
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13191
  /*$IFDEF debug */
13192
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
13193
  /*$ENDIF */
13194
  if (ndl_b > 0 && hst_b > 0)
13195
    {
13196
      /* do a quick check if bond types match */
13197
      if (!bondtypes_OK (ndl_b, hst_b))
13198
        {
13199
/* p2c: checkmol.pas, line 9537:
13200
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13201
          /*$IFDEF debug */
13202
          /*
13203
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
13204
          /*$ENDIF */
13205
          return false;
13206
        }
13207
    }
13208
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
13209
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a,
13210
                                                                 hst_a) &&
13211
      bondtypes_OK (ndl_b, hst_b))
13212
    {
13213
      return true;
13214
/* p2c: checkmol.pas, line 9549:
13215
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13216
      /*$IFDEF debug */
13217
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
13218
      /*$ENDIF */
13219
    }
13220
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
13221
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
13222
      (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp)))
13223
    {
13224
      return false;
13225
/* p2c: checkmol.pas, line 9559:
13226
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13227
      /*$IFDEF debug */
13228
      /*
13229
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
13230
         {$ENDIF */
13231
    }
13232
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
13233
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
13234
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp)))
13235
    {
13236
      if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
13237
          atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b))
13238
        {
13239
          /* 1st chirality check */
13240
          if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
13241
                                                       ndl_atom[ndl_a -
13242
                                                                1].
13243
                                                       stereo_care)) &&
13244
                ndl_maybe_chiral (ndl_a)))
13245
            {                   /* new in v0.3h */
13246
              return true;
13247
            }                   /* end of 1st chirality check */
13248
          na1 = ndl_a;          /* the (potential) chiral center (v0.3f) */
13249
          na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
13250
          na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
13251
          na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
13252
          ha1 = hst_a;
13253
          ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
13254
          ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
13255
          ha4 = hst_mp[matchpath_length (hst_mp) - 2];
13256
          memset (ncp, 0, sizeof (chirpath_type));
13257
          memset (hcp, 0, sizeof (chirpath_type));
13258
          ncp[0] = na1;
13259
          ncp[1] = na2;
13260
          ncp[2] = na3;
13261
          ncp[3] = na4;
13262
          hcp[0] = ha1;
13263
          hcp[1] = ha2;
13264
          hcp[2] = ha3;
13265
          hcp[3] = ha4;
13266
          if (!chirality_OK (ncp, hcp))
13267
            {
13268
/* p2c: checkmol.pas, line 9589:
13269
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13270
              /*$IFDEF debug */
13271
              //debugoutput ("chirality check failed at ring junction");
13272
              /*$ENDIF */
13273
              return false;
13274
            }
13275
/* p2c: checkmol.pas, line 9596:
13276
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13277
          /*$IFDEF debug */
13278
          //debugoutput ("chirality check succeeded at ring junction");
13279
          /*$ENDIF */
13280
          return true;
13281
/* p2c: checkmol.pas, line 9602:
13282
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13283
          /*$IFDEF debug */
13284
          /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
13285
          /*$ENDIF */
13286
        }
13287
      else
13288
        {
13289
          return false;
13290
/* p2c: checkmol.pas, line 9609:
13291
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13292
          /*$IFDEF debug */
13293
          /*
13294
             debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
13295
          /*$ENDIF */
13296
        }
13297
    }
13298
  /* in all other cases, do the hard work: */
13299
  /* first, get all heavy-atom neighbors of needle and haystack; */
13300
  /* at the beginning of the search, this means all neighbors, then it means */
13301
  /* all but the previous atom (where we came from) */
13302
  memset (ndl_nb, 0, sizeof (neighbor_rec));
13303
  memset (hst_nb, 0, sizeof (neighbor_rec));
13304
 
13305
  if (matchpath_length (ndl_mp) == 1)
13306
    {
13307
      ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
13308
      n_nb = atom[hst_a - 1].neighbor_count;
13309
      get_ndl_neighbors (ndl_nb, ndl_a);
13310
      get_neighbors (hst_nb, hst_a);
13311
    }
13312
  else
13313
    {
13314
      ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
13315
      n_nb = atom[hst_a - 1].neighbor_count - 1;
13316
      get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
13317
      get_nextneighbors (hst_nb, hst_a, prev_hst_a);
13318
    }
13319
  /* v0.3o: mark all neighbor atoms as "visited" */
13320
  for (i = 0; i < ndl_n_nb; i++)
13321
    ndl_atom[ndl_nb[i] - 1].tag = false;
13322
  /* now that the neighbor-arrays are filled, get all */
13323
  /* combinations of matches recursively; */
13324
  /* first, initialize the match matrix */
13325
  memset (mm, false, sizeof (matchmatrix));     /* new in v0.2i */
13326
  /* make sure there are not too many neighbors (max. max_neighbors)   */
13327
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors)
13328
    {                           /* updated in v0.2i */
13329
/* p2c: checkmol.pas, line 9644:
13330
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13331
      /*$IFDEF debug */
13332
      //debugoutput ("too many neighbors - exiting");
13333
      /*$ENDIF */
13334
      return false;
13335
    }
13336
  /* check if matchpath is not already filled up */
13337
  if (matchpath_length (ndl_mp) == max_matchpath_length)
13338
    {
13339
/* p2c: checkmol.pas, line 9653:
13340
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13341
      /*$IFDEF debug */
13342
      //debugoutput ("matchpath too int - exiting");
13343
      /*$ENDIF */
13344
      return false;
13345
    }
13346
  /* next, check which chain of the needle matches which chain of the haystack  */
13347
  for (i = 0; i < ndl_n_nb; i++)
13348
    {
13349
      emptyline = true;
13350
      next_ndl_a = ndl_nb[i];
13351
      for (j = 0; j < n_nb; j++)
13352
        {
13353
          next_hst_a = hst_nb[j];
13354
          ndl_mp[ndl_mp_len] = next_ndl_a;
13355
          hst_mp[hst_mp_len] = next_hst_a;
13356
          if (is_matching (ndl_mp, hst_mp))
13357
            {                   /* recursive function call */
13358
 
13359
              if (max_match_recursion_depth != 0
13360
                  && ++recursion_depth > max_match_recursion_depth)
13361
                {
13362
#ifndef MAKE_SHARED_LIBRARY
13363
                  if (opt_verbose)
13364
#endif
13365
                    printf
13366
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
13367
                       max_match_recursion_depth);
13368
                  //n_rings = max_rings;
13369
                  return true;
13370
                }
13371
 
13372
              mm[i][j] = true;
13373
              emptyline = false;
13374
            }
13375
        }
13376
      /* if a needle substituent does not match any of the haystack substituents, */
13377
      /* stop any further work immediately */
13378
      if (emptyline)
13379
        return false;
13380
    }
13381
  /* finally, check the content of the matrix */
13382
  res = matrix_OK (mm, ndl_n_nb, n_nb);
13383
  /* optional: chirality check */
13384
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) &&
13385
        ndl_maybe_chiral (ndl_a)))
13386
    return res;
13387
  /* first, we have to clean up the match matrix in order to remove */
13388
  /* "impossible" multiple matches (new in v0.3h) */
13389
  for (i = 1; i <= 3; i++)
13390
    {
13391
      for (j = 1; j <= max_neighbors; j++)
13392
        {                       /* haystack dimension */
13393
          n_hits = 0;
13394
          l = 0;
13395
          for (k = 1; k <= max_neighbors; k++)
13396
            {                   /* needle dimension */
13397
              if (mm[k - 1][j - 1])
13398
                {
13399
                  n_hits++;
13400
                  l = k;
13401
                }
13402
            }
13403
          if (n_hits == 1)
13404
            {                   /* a unique match ==> kick out any other match at this pos. */
13405
              for (m = 1; m <= max_neighbors; m++)
13406
                {
13407
                  if (m != j)
13408
                    mm[l - 1][m - 1] = false;
13409
                }
13410
            }
13411
        }
13412
    }
13413
  /* end of match matrix clean-up */
13414
  if (prev_ndl_a > 0)
13415
    {
13416
      n_singlehits = 1;
13417
      ncp[1] = prev_ndl_a;
13418
      hcp[1] = prev_hst_a;
13419
    }
13420
  else
13421
    n_singlehits = 0;
13422
  ncp[0] = ndl_a;
13423
  hcp[0] = hst_a;
13424
  i = 0;
13425
  l = 0;
13426
  while (n_singlehits < 3 && i < 4)
13427
    {
13428
      i++;
13429
      n_hits = 0;
13430
      for (k = 1; k <= n_nb; k++)
13431
        {
13432
          if (mm[i - 1][k - 1])
13433
            {
13434
              n_hits++;
13435
              l = k;
13436
            }
13437
        }
13438
      if (n_hits == 1)
13439
        {
13440
          n_singlehits++;
13441
          ncp[n_singlehits] = ndl_nb[i - 1];
13442
          hcp[n_singlehits] = hst_nb[l - 1];
13443
        }
13444
    }
13445
  if (n_singlehits != 3)
13446
    return res;
13447
  if (!chirality_OK (ncp, hcp))
13448
    {
13449
/* p2c: checkmol.pas, line 9749:
13450
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13451
      /*$IFDEF debug */
13452
      //debugoutput ("chirality check failed");
13453
      /*$ENDIF */
13454
      res = false;
13455
    }
13456
  else
13457
    {
13458
/* p2c: checkmol.pas, line 9755:
13459
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13460
      /*$IFDEF debug */
13461
      //debugoutput ("chirality check OK");
13462
      /*$ENDIF */
13463
    }
13464
  return res;
13465
/* p2c: checkmol.pas, line 9762:
13466
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13467
  /*$IFDEF debug */
13468
  /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
13469
     debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
13470
  /*$ENDIF */
13471
}
13472
 
13473
 
13474
static boolean
13475
quick_match ()
13476
{
13477
  /* added in v0.2c */
13478
  int i;
13479
  boolean res = true;
13480
 /* str3 ndl_atype;*/
13481
  str2 ndl_el;                  /* v0.3l */
13482
  int ndl_chg;                  /* v0.3l */
13483
  int ndl_rad;                  /* v0.3x */
13484
  int ndl_iso;                  /* v0.3x */
13485
 
13486
 
13487
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
13488
    /* v0.3f, v0.3m, v0.3o */
13489
    return false;
13490
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
13491
      ndl_n_bonds > n_bonds)
13492
    {                           /* just to be sure... */
13493
/* p2c: checkmol.pas, line 9786:
13494
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13495
      /*$IFDEF debug */
13496
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
13497
      //debugoutput (" ==> quick_match failed");
13498
      /*$ENDIF */
13499
      return false;
13500
    }
13501
 
13502
  if (ndl_n_heavyatoms > 1)
13503
    {
13504
      for (i = 0; i < ndl_n_atoms; i++)
13505
        {
13506
          /*if atom^[i].atype <> ndl_atom^[i].atype then res := false;    (* changed in */
13507
          if (strcmp (atom[i].element, ndl_atom[i].element))    /* v0.2k */
13508
            return false;
13509
          //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
13510
          //res = false;
13511
 
13512
 
13513
          if (opt_chg)
13514
            {
13515
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
13516
                return false;
13517
            }
13518
/*  else
13519
    {
13520
      if (ndl_atom[i].formal_charge != 0 &&
13521
          atom[i].formal_charge != 0 &&
13522
          ndl_atom[i].formal_charge != atom[i].formal_charge)
13523
        return false;
13524
    } */
13525
 
13526
          /* v0.3x: isotopes must be the same */
13527
          if (opt_iso)
13528
            {
13529
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
13530
                return false;
13531
            }
13532
/*  else
13533
    {
13534
      if (ndl_atom[i].nucleon_number != 0 &&
13535
          atom[i].nucleon_number != 0 &&
13536
          ndl_atom[i].nucleon_number !=
13537
          atom[i].nucleon_number)
13538
        return false;
13539
    }*/
13540
 
13541
          /* v0.3x: radicals must be the same */
13542
          if (opt_rad)
13543
            {
13544
              if (ndl_atom[i].radical_type != atom[i].radical_type)
13545
                return false;
13546
            }
13547
/*  else
13548
    {
13549
      if (ndl_atom[i].radical_type != 0 &&
13550
          atom[i].radical_type != 0 &&
13551
          ndl_atom[i].radical_type != atom[i].radical_type)
13552
        return false;
13553
    }*/
13554
 
13555
        }
13556
/* p2c: checkmol.pas, line 9798:
13557
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13558
      /*$IFDEF debug */
13559
      //if (res)
13560
      //debugoutput (" ==> quick_match: atoms OK");
13561
      //else
13562
      //  debugoutput (" ==> quick_match: atoms not OK");
13563
      /*$ENDIF */
13564
      if (ndl_n_bonds > 0)
13565
        {
13566
 
13567
          for (i = 0; i < ndl_n_bonds; i++)
13568
            {
13569
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
13570
                  || ndl_bond[i].btype != bond[i].btype)
13571
                return false;
13572
            }
13573
        }
13574
/* p2c: checkmol.pas, line 9810:
13575
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13576
      /*$IFDEF debug */
13577
      //if (res)
13578
      //  debugoutput (" ==> quick_match: bonds OK");
13579
      //else
13580
      //  debugoutput (" ==> quick_match: bonds not OK");
13581
      /*$ENDIF */
13582
      /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
13583
    }
13584
  else
13585
    {
13586
 
13587
      /* first, find out the element and atom type of the only heavy atom       */
13588
      for (i = 0; i < ndl_n_atoms; i++)
13589
        {
13590
          if (ndl_atom[i].heavy)
13591
            {
13592
              //strcpy (ndl_atype, ndl_atom[i].atype);
13593
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
13594
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
13595
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
13596
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
13597
            }
13598
        }
13599
 
13600
      for (i = 0; i < n_atoms; i++)
13601
        {                       /* v0.3l, v0.3o */
13602
          if (          //      !strcmp (atom[i].atype, ndl_atype) && 
13603
               !strcmp (atom[i].element, ndl_el))
13604
            {
13605
 
13606
 
13607
              if (opt_chg || opt_strict)
13608
                {
13609
                  if (ndl_chg != atom[i].formal_charge)
13610
                    return false;
13611
                }
13612
 
13613
 
13614
              if (opt_iso || opt_strict)
13615
                {
13616
                  if (ndl_iso != atom[i].nucleon_number)
13617
                    return false;
13618
                }
13619
 
13620
 
13621
 
13622
              if (opt_rad || opt_strict)
13623
                {
13624
                  if (ndl_rad != atom[i].radical_type)
13625
                    return false;
13626
                }
13627
                  return true;
13628
            } else {
13629
                res=false;
13630
            }    
13631
        }
13632
    }
13633
/* p2c: checkmol.pas, line 9828:
13634
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13635
  /*$IFDEF debug */
13636
  //if (res)
13637
  //  debugoutput (" ==> quick_match succeeded");
13638
  //else
13639
  //  debugoutput (" ==> quick_match failed (2)");
13640
  /*$ENDIF */
13641
  return res;
13642
}
13643
 
13644
static void
13645
perform_match ()
13646
{
13647
  int i = 0;
13648
  int j;
13649
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
13650
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
13651
  boolean qm;                   /* v0.3l */
13652
  /* check for NoStruct (0 atoms);  v0.3l */
13653
  if (n_atoms == 0 || ndl_n_atoms == 0)
13654
    {
13655
      matchresult = false;
13656
/* p2c: checkmol.pas, line 9849:
13657
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13658
      /*$IFDEF debug */
13659
      //debugoutput ("NoStruct encountered - aborted match routine");
13660
      /*$ENDIF */
13661
      return;
13662
    }
13663
  /* if we perform an exact match, needle and haystack must have */
13664
  /* the same number of atoms, bonds, and rings */
13665
  if (opt_exact && opt_iso)     /* 0.3x */
13666
    {
13667
      if (n_heavyatoms != ndl_n_heavyatoms
13668
          || n_heavybonds != ndl_n_heavybonds)
13669
        {
13670
          matchresult = false;
13671
/* p2c: checkmol.pas, line 9861:
13672
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13673
          /*$IFDEF debug */
13674
          //debugoutput ("different number of heavy atoms and/or bonds");
13675
          /*$ENDIF */
13676
          //return;
13677
        }
13678
    }
13679
 
13680
  /* have a quick look if needle and haystack are identical molfiles */
13681
  qm = quick_match ();          /* v0.3l */
13682
  if (qm)
13683
    {
13684
      matchresult = true;
13685
      clear_ndl_atom_tags ();   /* v0.3o */
13686
      return;
13687
    }
13688
  /* if we have only one heavy atom and quick_match fails, return "false";  v0.3l */
13689
  if (ndl_n_heavyatoms == 1)
13690
    {
13691
      matchresult = false;
13692
      return;
13693
    }
13694
/* p2c: checkmol.pas, line 9881:
13695
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13696
  /*$IFDEF debug */
13697
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
13698
  /*$ENDIF */
13699
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
13700
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
13701
/* p2c: checkmol.pas, line 9886:
13702
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13703
  /*$IFDEF debug */
13704
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
13705
  /*$ENDIF */
13706
  matchresult = false;
13707
  for (j = 0; j < max_matchpath_length; j++)
13708
    {
13709
      ndl_matchpath[j] = 0;
13710
      hst_matchpath[j] = 0;
13711
    }
13712
  ndl_matchpath[0] = ndl_ref_atom;
13713
  while (i < n_atoms && matchresult == false)
13714
    {
13715
      i++;
13716
      n_nb = atom[i - 1].neighbor_count;
13717
      n_hc = hetatom_count (i);
13718
      if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc)
13719
        {
13720
/* p2c: checkmol.pas, line 9904:
13721
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13722
          /*$IFDEF debug */
13723
          /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
13724
          /*$ENDIF */
13725
 
13726
          recursion_depth = 0;
13727
          hst_matchpath[0] = i;
13728
          matchresult = is_matching (ndl_matchpath, hst_matchpath);
13729
/* p2c: checkmol.pas, line 9909:
13730
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13731
          /*$IFDEF debug */
13732
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
13733
          /*$ENDIF */
13734
          if (matchresult)      /* v0.3o; mark this fragment as matched */
13735
            atom[i - 1].tag = true;
13736
        }
13737
    }
13738
}
13739
 
13740
 
13741
static void
13742
clear_rings ()
13743
{
13744
  int i, FORLIM;
13745
  n_rings = 0;
13746
  memset (ring, 0, sizeof (ringlist));
13747
  for (i = 0; i < max_rings; i++)
13748
    {                           /* new in v0.3 */
13749
      ringprop[i].size = 0;
13750
      ringprop[i].arom = false;
13751
      ringprop[i].envelope = false;
13752
    }
13753
  if (n_atoms > 0)
13754
    {
13755
      FORLIM = n_atoms;
13756
      for (i = 0; i < FORLIM; i++)
13757
        atom[i].ring_count = 0;
13758
    }
13759
  if (n_bonds > 0)
13760
    {
13761
      FORLIM = n_bonds;
13762
      for (i = 0; i < FORLIM; i++)
13763
        bond[i].ring_count = 0;
13764
    }
13765
}
13766
 
13767
 
13768
static int
13769
ring_lastpos (s)
13770
     int *s;
13771
{
13772
  int i, rc;
13773
  int rlp = 0;
13774
  int FORLIM;
13775
  if (n_rings <= 0)
13776
    return rlp;
13777
  FORLIM = n_rings;
13778
  for (i = 1; i <= FORLIM; i++)
13779
    {
13780
      rc = ringcompare (s, ring[i - 1]);
13781
      if (rc_identical (rc))
13782
        rlp = i;
13783
    }
13784
  return rlp;
13785
}
13786
 
13787
 
13788
static void
13789
remove_redundant_rings ()
13790
{
13791
  int i, j, k, rlp;
13792
  ringpath_type tmp_path;
13793
  int FORLIM, FORLIM1;
13794
  if (n_rings < 2)
13795
    return;
13796
  FORLIM = n_rings;
13797
  for (i = 1; i < FORLIM; i++)
13798
    {
13799
      memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
13800
      rlp = ring_lastpos (tmp_path);
13801
      while (rlp > i)
13802
        {
13803
          FORLIM1 = n_rings;
13804
/* p2c: checkmol.pas, line 9970:
13805
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13806
          /*$IFDEF debug */
13807
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
13808
          /*$ENDIF */
13809
          for (j = rlp; j < FORLIM1; j++)
13810
            {
13811
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
13812
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
13813
              ringprop[j - 1].arom = ringprop[j].arom;
13814
              ringprop[j - 1].envelope = ringprop[j].envelope;
13815
            }
13816
          for (k = 0; k < max_ringsize; k++)
13817
            ring[n_rings - 1][k] = 0;
13818
          n_rings--;
13819
          rlp = ring_lastpos (tmp_path);
13820
        }
13821
    }
13822
}
13823
 
13824
 
13825
static int
13826
count_aromatic_rings ()
13827
{
13828
  int i;
13829
  int n = 0;
13830
  int FORLIM;
13831
  if (n_rings <= 0)
13832
    return n;
13833
  FORLIM = n_rings;
13834
  for (i = 0; i < FORLIM; i++)
13835
    {
13836
      if (ringprop[i].arom)
13837
        n++;
13838
    }
13839
  return n;
13840
}
13841
 
13842
 
13843
static void
13844
chk_envelopes ()
13845
{
13846
  /* new in v0.3d */
13847
  /* checks if a ring completely contains one or more other rings */
13848
  int a, i, j, k, l, pl, pli;
13849
  boolean found_atom, found_all_atoms, found_ring;
13850
  int FORLIM;
13851
  if (n_rings < 2)
13852
    return;
13853
  FORLIM = n_rings;
13854
  for (i = 1; i < FORLIM; i++)
13855
    {
13856
      found_ring = false;
13857
      j = 0;
13858
      pli = ringprop[i].size;   /* path_length(ring^[i]); */
13859
      while (j < i && found_ring == false)
13860
        {
13861
          j++;
13862
          found_all_atoms = true;
13863
          pl = ringprop[j - 1].size;    /* path_length(ring^[j]); */
13864
          for (k = 0; k < pl; k++)
13865
            {
13866
              found_atom = false;
13867
              a = ring[j - 1][k];
13868
              for (l = 0; l < pli; l++)
13869
                {
13870
                  if (ring[i][l] == a)
13871
                    found_atom = true;
13872
                }
13873
              if (found_atom == false)
13874
                found_all_atoms = false;
13875
            }
13876
          if (found_all_atoms)
13877
            found_ring = true;
13878
        }
13879
      if (found_ring)
13880
        ringprop[i].envelope = true;
13881
    }
13882
}
13883
 
13884
 
13885
static void
13886
update_ringcount ()
13887
{
13888
  int i, j, a1, a2, b, pl, FORLIM;
13889
  if (n_rings <= 0)
13890
    return;
13891
  chk_envelopes ();
13892
  FORLIM = n_rings;
13893
  for (i = 0; i < FORLIM; i++)
13894
    {
13895
      if (ringprop[i].envelope == false)
13896
        {
13897
          pl = ringprop[i].size;        /* path_length(ring^[i]);  (* v0.3d */
13898
          a2 = ring[i][pl - 1];
13899
          for (j = 0; j < pl; j++)
13900
            {
13901
              a1 = ring[i][j];
13902
              atom[a1 - 1].ring_count++;
13903
              b = get_bond (a1, a2);
13904
              bond[b - 1].ring_count++;
13905
              a2 = a1;
13906
            }
13907
        }
13908
    }
13909
}
13910
 
13911
 
13912
static boolean
13913
normalize_ionic_bonds ()
13914
{
13915
  /* v0.3k */
13916
  /* changed from a procedure into a function in v0.3m */
13917
  int i, a1, a2, fc1, fc2;
13918
  char bt;
13919
  boolean res = false;          /* v0.3m */
13920
  int FORLIM;
13921
  /* v0.3m */
13922
  if (n_bonds == 0)
13923
    return false;
13924
  FORLIM = n_bonds;
13925
  for (i = 0; i < FORLIM; i++)
13926
    {
13927
      a1 = bond[i].a1;
13928
      a2 = bond[i].a2;
13929
      bt = bond[i].btype;
13930
      fc1 = atom[a1 - 1].formal_charge;
13931
      fc2 = atom[a2 - 1].formal_charge;
13932
      if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D'))
13933
        {
13934
          atom[a1 - 1].formal_charge = 0;
13935
          atom[a2 - 1].formal_charge = 0;
13936
          if (!strcmp (atom[a1 - 1].atype, "N3+"))      /* v0.3m */
13937
            strcpy (atom[a1 - 1].atype, "N3 ");
13938
          if (!strcmp (atom[a2 - 1].atype, "N3+"))      /* v0.3m */
13939
            strcpy (atom[a2 - 1].atype, "N3 ");
13940
          if (bt == 'D')
13941
            bond[i].btype = 'T';
13942
          if (bt == 'S')
13943
            bond[i].btype = 'D';
13944
          res = true;           /* v0.3m */
13945
        }
13946
    }
13947
  return res;                   /* v0.3m (return true if any change was made */
13948
}
13949
 
13950
#if 0
13951
static void
13952
chk_wildcard_rings ()           // new in v0.3p
13953
// checks if there are any wildcard atom types or bond types
13954
// in a ring of the needle; if yes ==> set the q_arom flag in the
13955
// atom and bond record of all ring members in order to perform the 
13956
// match a bit more generously
13957
{
13958
 
13959
  int i, j, rs;
13960
  int a1, a2, b;
13961
  boolean wcr;
13962
  str3 at;
13963
  char bt;
13964
 
13965
  if (ndl_querymol == false)
13966
    return;
13967
  if (ndl_n_rings == 0)
13968
    return;
13969
  // now look for any not-yet-aromatic rings which contain a wildcard
13970
  for (i = 0; i < ndl_n_rings; i++)
13971
    {
13972
      wcr = false;
13973
      if (ndl_ringprop[i].arom == false)
13974
        {
13975
          rs = ndl_ringprop[i].size;
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
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
13984
                wcr = true;
13985
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
13986
                wcr = true;
13987
              a2 = a1;
13988
            }
13989
          if (wcr)
13990
            {                   // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
13991
              // {$IFDEF debug}
13992
              // debugoutput('wildcard ring found');
13993
              // {$ENDIF}
13994
              a2 = ndl_ring[i][rs];
13995
              for (j = 0; j < rs; j++)
13996
                {
13997
                  a1 = ndl_ring[i][j];
13998
                  b = get_ndl_bond (a1, a2);
13999
                  strcpy (at, ndl_atom[a1].atype);
14000
                  bt = ndl_bond[b].btype;
14001
                  ndl_atom[a1].q_arom = true;
14002
                  ndl_bond[b].q_arom = true;
14003
                  a2 = a1;
14004
                }
14005
            }
14006
        }
14007
    }
14008
  // and now undo this flagging for all rings which contain no wildcard
14009
  for (i = 0; i < ndl_n_rings; i++)
14010
    {
14011
      wcr = false;
14012
      rs = ndl_ringprop[i].size;
14013
      a2 = ndl_ring[i][rs];
14014
      for (j = 0; j < rs; j++)
14015
        {
14016
          a1 = ndl_ring[i][j];
14017
          b = get_ndl_bond (a1, a2);
14018
          strcpy (at, ndl_atom[a1].atype);
14019
          bt = ndl_bond[b].btype;
14020
          if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
14021
            wcr = true;
14022
          if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
14023
            wcr = true;
14024
          a2 = a1;
14025
        }
14026
      if (!wcr)
14027
        {                       // if yes, unflag all atoms and bonds in this ring
14028
          a2 = ndl_ring[i][rs];
14029
          for (j = 0; j < rs; j++)
14030
            {
14031
              a1 = ndl_ring[i][j];
14032
              b = get_ndl_bond (a1, a2);
14033
              strcpy (at, ndl_atom[a1].atype);
14034
              bt = ndl_bond[b].btype;
14035
              ndl_atom[a1].q_arom = false;
14036
              ndl_bond[b].q_arom = false;
14037
              a2 = a1;
14038
            }
14039
        }
14040
    }
14041
  // some further refinement would be necessary here in order to unflag everything
14042
  // which contains a wildcard but which definitely cannot be aromatic
14043
}
14044
#endif
14045
 
14046
#ifndef MAKE_SHARED_LIBRARY
14047
 
14048
int
14049
main (int argc, char *argv[])
14050
{                               /* main routine */
14051
  char STR1[256], STR6[256];
14052
  int FORLIM;
14053
  /* progmode = pmMatchMol */
14054
  rfile = NULL;
14055
  strcpy (progname, argv[0]);
14056
  strncpy (STR1, progname, 253);
14057
  if (strstr (STR1, "matchmol") != NULL)
14058
    progmode = pmMatchMol;
14059
  else
14060
    {
14061
      strncpy (STR6, progname, 253);
14062
      if (strstr (STR6, "checkmol") == NULL)
14063
        {
14064
          printf ("THOU SHALLST NOT RENAME ME!\n");
14065
          exit (9);
14066
        }
14067
      progmode = pmCheckMol;
14068
    }
14069
  if (argc == 1)
14070
    {
14071
      show_usage ();
14072
      exit (1);
14073
    }
14074
  init_globals ();
14075
  init_molstat (&molstat);
14076
  parse_args (argc, argv);
14077
  if (ringsearch_mode == rs_sar)
14078
    max_vringsize = max_ringsize;
14079
  else
14080
    max_vringsize = ssr_vringsize;
14081
  /* v0.3n (was: 10) */
14082
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14083
  if (progmode == pmMatchMol)
14084
    {
14085
      left_trim (ndl_molfilename);
14086
      left_trim (molfilename);
14087
      if ((*molfilename == '\0' || *ndl_molfilename == '\0'
14088
           || argc < 3) && !opt_stdin)
14089
        {
14090
 
14091
          show_usage ();
14092
          exit (2);             /* new in v0.2k */
14093
        }
14094
      if (!(file_exists (ndl_molfilename)) && !opt_stdin)
14095
        {                       /*not  fileexists(ndl_molfilename) REPLACE!!! */
14096
                                   printf("2");
14097
                                   /* p2c: checkmol.pas, line 10128:
14098
                                   * Warning: Expected an expression, found a ')' [227] */
14099
          if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
14100
            show_usage ();
14101
          else
14102
            printf ("file %s not found!\n", ndl_molfilename);
14103
          /* new in v0.2k */
14104
          exit (2);
14105
        }
14106
    }
14107
 
14108
  if (!(file_exists (molfilename)) && !opt_stdin)
14109
    {                           /*not  fileexists(ndl_molfilename) REPLACE!!! */
14110
/* p2c: checkmol.pas, line 10128:
14111
 * Warning: Expected an expression, found a ')' [227] */
14112
 
14113
      if (strlen (molfilename) > 1 && molfilename[0] == '-')
14114
        show_usage ();
14115
      else
14116
        printf ("file %s not found!\n", molfilename);
14117
      /* new in v0.2k */
14118
      exit (2);
14119
    }
14120
 
14121
  /* read the first molecule and process it; if we are in "matchmol" mode, */
14122
  /* this is the "needle" */
14123
  if (progmode == pmMatchMol)
14124
    readinputfile (ndl_molfilename);
14125
  else
14126
    readinputfile (molfilename);
14127
  li = 1;                       /* initialize line pointer for input buffer */
14128
  get_filetype (filetype, ndl_molfilename);
14129
  if (!strcmp (filetype, "unknown"))
14130
    {
14131
      printf ("unknown query file format!\n");
14132
      if (!opt_verbose)
14133
        exit (3);
14134
      printf ("===========================================\n");
14135
      FORLIM = molbufindex;
14136
      for (i = 1; i <= FORLIM; i++)
14137
        puts (molbuf[i - 1]);
14138
      exit (3);
14139
    }
14140
  mol_OK = true;                /* added in v0.2i */
14141
  if (!strcmp (filetype, "alchemy"))
14142
    read_molfile (ndl_molfilename);
14143
  if (!strcmp (filetype, "sybyl"))
14144
    read_mol2file (ndl_molfilename);
14145
  if (!strcmp (filetype, "mdl"))
14146
    read_MDLmolfile (ndl_molfilename);
14147
  count_neighbors ();
14148
  if (!mol_OK || n_atoms < 1)
14149
    {                           /* v0.3g; check if this is a valid query structure */
14150
      printf ("invalid molecule\n");
14151
      exit (3);
14152
    }
14153
  if (!found_arominfo || progmode == pmCheckMol)
14154
    {                           /* added in v0.2b/0.2c */
14155
/* p2c: checkmol.pas, line 10172:
14156
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14157
      /*$IFDEF debug
14158
         if (!found_arominfo)
14159
         debugoutput
14160
         ("no aromaticity information found - checking myself...");
14161
         else
14162
         debugoutput ("performing full aromaticity check");
14163
         // new in v0.3d
14164
      $ENDIF */
14165
      chk_ringbonds ();
14166
      if (ringsearch_mode == rs_ssr)
14167
        remove_redundant_rings ();
14168
      if (n_rings >= max_rings)
14169
        {
14170
          if (opt_verbose)
14171
            printf
14172
              ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14173
               max_rings);
14174
          ringsearch_mode = rs_ssr;
14175
          auto_ssr = true;      /* v0.3n */
14176
          clear_rings ();
14177
          max_vringsize = ssr_vringsize;        /* v0.3n (was: 10) */
14178
          chk_ringbonds ();
14179
          remove_redundant_rings ();
14180
        }
14181
      update_ringcount ();
14182
      /* new in v0.3k: if output is a molfile, leave the original */
14183
      /* representation of N-oxides, S-oxides, nitro groups, etc. */
14184
      /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
14185
      if (!opt_xmdlout)         /* v0.3k */
14186
        normalize_ionic_bonds ();
14187
      update_atypes ();
14188
      update_Htotal ();         /* added in v0.3 */
14189
      chk_arom ();
14190
      if (ringsearch_mode == rs_ssr)
14191
        {                       /* new in v0.3 */
14192
          do
14193
            {
14194
              prev_n_ar = count_aromatic_rings ();
14195
              chk_arom ();
14196
              n_ar = count_aromatic_rings ();
14197
            }
14198
          while (prev_n_ar - n_ar != 0);
14199
        }
14200
    }
14201
  else
14202
    {                           /* v0.3k */
14203
/* p2c: checkmol.pas, line 10206:
14204
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14205
      /*$IFDEF debug
14206
         debugoutput ("found aromaticity information in input file");
14207
         $ENDIF */
14208
      if (!opt_xmdlout)
14209
        normalize_ionic_bonds ();
14210
      update_atypes ();         /* added in v0.2f */
14211
      update_Htotal ();         /* end v0.2b snippet */
14212
    }
14213
  if (progmode == pmCheckMol)
14214
    {
14215
      if (opt_verbose)
14216
        write_mol ();
14217
      get_molstat ();
14218
      if (opt_molstat)
14219
        {
14220
          if (opt_molstat_X)
14221
            write_molstat_X ();
14222
          else
14223
            write_molstat ();
14224
        }
14225
      else
14226
        {
14227
          if (found_querymol)
14228
            {
14229
              printf ("input structure contains query atom or query bond!\n");
14230
              exit (1);
14231
            }
14232
          chk_functionalgroups ();
14233
          if (opt_none)
14234
            opt_text = true;
14235
          if (opt_text)
14236
            write_fg_text ();
14237
          if (opt_text_de)
14238
            write_fg_text_de ();
14239
          if (opt_code)
14240
            write_fg_code ();
14241
          if (opt_bin)
14242
            write_fg_binary ();
14243
          if (opt_bitstring)
14244
            write_fg_bitstring ();
14245
          if (opt_xmdlout)
14246
            write_MDLmolfile ();
14247
        }
14248
      /*if opt_verbose   then write_mol; */
14249
      zap_molecule ();
14250
    }
14251
  else
14252
    {
14253
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14254
      if (!opt_fp)
14255
        {                       /* v0.3m */
14256
          copy_mol_to_needle ();
14257
          //chk_wildcard_rings (); /* 0.3p */
14258
          set_ndl_atom_tags (); /* v0.3o */
14259
          if (opt_verbose)
14260
            write_needle_mol ();
14261
          if (rs_strict)        /* v0.3j */
14262
            ndl_ref_atom = find_ndl_ref_atom_cv ();
14263
          else
14264
            ndl_ref_atom = find_ndl_ref_atom ();
14265
        }
14266
      else
14267
        {
14268
          copy_mol_to_tmp ();   /* v0.3m */
14269
          if (opt_verbose)
14270
            printf ("1st molecule stored in buffer: %s\n", tmp_molname);
14271
        }
14272
      /* next, read the "haystack" file and process it */
14273
      li = 1;
14274
      mol_count = 0;
14275
      fpdecimal = 0;            /* v0.3m */
14276
      fpindex = 0;              /* v0.3m */
14277
      do
14278
        {
14279
          /* new in v0.3i: reset ringsearch_mode to its initial value */
14280
          /* for each new molecule */
14281
          ringsearch_mode = opt_rs;
14282
          if (ringsearch_mode == rs_sar)
14283
            max_vringsize = max_ringsize;
14284
          else
14285
            max_vringsize = ssr_vringsize;
14286
          /* v0.3n (was: 10) */
14287
          readinputfile (molfilename);
14288
          li = 1;
14289
          get_filetype (filetype, molfilename);
14290
          if (strcmp (filetype, "unknown"))
14291
            {
14292
              found_arominfo = false;   /* added in v0.2b */
14293
              mol_OK = true;    /* added in v0.2i */
14294
              if (!strcmp (filetype, "alchemy"))
14295
                read_molfile (molfilename);
14296
              if (!strcmp (filetype, "sybyl"))
14297
                read_mol2file (molfilename);
14298
              if (!strcmp (filetype, "mdl"))
14299
                read_MDLmolfile (molfilename);
14300
              mol_count++;
14301
              fpindex++;
14302
              count_neighbors ();
14303
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14304
              if (!mol_OK || (n_atoms < 1
14305
                  && !(opt_fp && fpformat == fpf_decimal)))
14306
                printf ("%i:F\n", mol_count);
14307
              else
14308
                {
14309
                  if (opt_exact
14310
                      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14311
                          || n_Ntot != ndl_n_Ntot))
14312
                    {           /* new in v0.3g */
14313
                      if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
14314
                        printf ("%i:F\n", mol_count);
14315
                    }
14316
                  else
14317
                    {
14318
                      if (!found_arominfo || (opt_strict && tmfmismatch))
14319
                        {       /* added in v0.3m */
14320
/* p2c: checkmol.pas, line 10294:
14321
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14322
                          /*$IFDEF debug
14323
                             debugoutput
14324
                             ("no aromaticity information found (or tweak mismatch) - checking myself...");
14325
                            *$ENDIF */
14326
                          chk_ringbonds ();
14327
                          if (ringsearch_mode == rs_ssr)
14328
                            remove_redundant_rings ();
14329
                          if (n_rings == max_rings)
14330
                            {
14331
                              if (opt_verbose)
14332
                                printf
14333
                                  ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14334
                                   max_rings);
14335
                              ringsearch_mode = rs_ssr;
14336
                              clear_rings ();
14337
                              max_vringsize = ssr_vringsize;    /* v0.3n (was: 10) */
14338
                              chk_ringbonds ();
14339
                              remove_redundant_rings ();
14340
                            }
14341
                          update_ringcount ();
14342
                          update_atypes ();
14343
                          update_Htotal ();     /* added in v0.3 */
14344
                          chk_arom ();
14345
                          if (ringsearch_mode == rs_ssr)
14346
                            {   /* new in v0.3 */
14347
                              do
14348
                                {
14349
                                  prev_n_ar = count_aromatic_rings ();
14350
                                  chk_arom ();
14351
                                  n_ar = count_aromatic_rings ();
14352
                                }
14353
                              while (prev_n_ar - n_ar != 0);
14354
                            }
14355
                        }
14356
                      else
14357
                        {       /* added in v0.2f */
14358
/* p2c: checkmol.pas, line 10322:
14359
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14360
                          /*$IFDEF debug
14361
                             debugoutput
14362
                             ("found aromaticity information in input file");
14363
                             $ENDIF */
14364
                          if (opt_strict)
14365
                            update_atypes ();
14366
                          update_Htotal ();
14367
                        }
14368
                      init_molstat (&ndl_molstat);
14369
                      if (normalize_ionic_bonds ())
14370
                        /* new in v0.3k, modified in v0.3m */
14371
                        update_atypes ();
14372
                      if (opt_verbose && !opt_fp)
14373
                        write_mol ();
14374
                      /* if in "fingerprint mode", exchange needle and haystack */
14375
                      if (opt_fp)
14376
                        {       /* v0.3m */
14377
                          zap_needle ();
14378
                          copy_mol_to_needle ();
14379
                          //chk_wildcard_rings (); /* 0.3p */
14380
                          zap_molecule ();
14381
                          copy_tmp_to_mol ();
14382
                          if (opt_verbose)
14383
                            write_needle_mol ();
14384
                          if (rs_strict)        /* v0.3j */
14385
                            ndl_ref_atom = find_ndl_ref_atom_cv ();
14386
                          else
14387
                            ndl_ref_atom = find_ndl_ref_atom ();
14388
                          if (opt_verbose)
14389
                            write_mol ();
14390
                        }       /* v0.3m */
14391
                      /* now that we have both molecules, perform the comparison */
14392
                      /* v0.3o: takes care of disconnected fragment... */
14393
                      clear_atom_tags ();
14394
                      set_ndl_atom_tags ();
14395
                      matchsummary = true;
14396
                      perform_match ();
14397
                      matchsummary = matchresult;
14398
                      if (count_tagged_ndl_heavyatoms () > 0
14399
                          && matchsummary == true)
14400
                        {
14401
                          do
14402
                            {
14403
                              if (rs_strict)
14404
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
14405
                              else
14406
                                ndl_ref_atom = find_ndl_ref_atom ();
14407
                              perform_match ();
14408
                              if (matchresult == false)
14409
                                matchsummary = false;
14410
                            }
14411
                          while (count_tagged_ndl_heavyatoms () != 0 &&
14412
                                 matchsummary != false);
14413
                        }
14414
                      /* end of disconnected-fragment matching (v0.3o) */
14415
                      if (matchsummary == true)
14416
                        {       /* v0.3o */
14417
                          if (opt_molout)
14418
                            {
14419
                              FORLIM = molbufindex;
14420
                              for (i = 1; i <= FORLIM; i++)
14421
                                puts (molbuf[i - 1]);
14422
                            }
14423
                          else
14424
                            {
14425
                              if (!opt_fp)      /* inttostr(mol_count) REPLACE!!!, */
14426
                                printf ("%i:T\n", mol_count);
14427
                              else
14428
                                {
14429
                                  if (ndl_n_heavyatoms == n_heavyatoms &&
14430
                                      ndl_n_heavybonds == n_heavybonds)
14431
                                    fp_exacthit = true;
14432
                                  else
14433
                                    fp_exacthit = false;
14434
                                  if (fp_exacthit)
14435
                                    fp_exactblock = true;
14436
                                  if (fpformat == fpf_boolean)
14437
                                    {
14438
                                      if (fp_exacthit)  /* inttostr(mol_count), REPACE!!! */
14439
                                        printf ("%i:TX\n", mol_count);
14440
                                      else
14441
                                        printf ("%i:T\n", mol_count);
14442
                                    }
14443
                                  /* inttostr(mol_count), REPLACE!!! */
14444
                                  if (fpformat == fpf_decimal)
14445
                                    {
14446
                                      fpincrement = 1;
14447
                                      FORLIM = fpindex;
14448
                                      for (i = 1; i <= FORLIM; i++)
14449
                                        fpincrement <<= 1;
14450
                                      fpdecimal += fpincrement;
14451
                                    }
14452
                                }
14453
                            }
14454
                        }
14455
                      else
14456
                        {
14457
                          if (!
14458
                              (opt_molout || (opt_fp
14459
                               && fpformat == fpf_decimal)))
14460
                            /* inttostr(mol_count), REPLACE!!! */
14461
                            printf ("%i:F\n", mol_count);
14462
                        }
14463
                      if (opt_fp && fpformat == fpf_decimal
14464
                          && fpindex == fp_blocksize)
14465
                        {
14466
                          if (fp_exactblock)
14467
                            fpdecimal++;
6786 kbelabas 14468
                          printf ("%lld\n", fpdecimal);
6785 bpr 14469
                          fpindex = 0;
14470
                          fpdecimal = 0;
14471
                          fp_exactblock = false;
14472
                        }
14473
                      zap_molecule ();
14474
                      molbufindex = 0;
14475
                    }
14476
                }
14477
            }
14478
          else
14479
            {
14480
              /* v0.3l */
14481
              /* mol_OK */
14482
              printf ("%i:unknown file format\n", mol_count);
14483
            }
14484
        }
14485
      while (mol_in_queue != false);
14486
      /* if filetype <> 'unknown' */
14487
      if (opt_fp && fpformat == fpf_decimal && fpindex > 0)
14488
        {
14489
          if (fp_exactblock)
14490
            fpdecimal++;
6786 kbelabas 14491
          printf ("%lld\n", fpdecimal);
6785 bpr 14492
        }
14493
      zap_needle ();
14494
      if (rfile_is_open)
14495
        {                       /* new in v0.2g */
14496
          if (rfile != NULL)
14497
            fclose (rfile);
14498
          rfile = NULL;
14499
        }
14500
    }
14501
  if (rfile != NULL)
14502
    fclose (rfile);
14503
  exit (0);
14504
}
14505
 
14506
#else
14507
 
14508
static void
14509
init_globals_dll (void)
14510
{
14511
 
14512
//printf("init_globals_dll\n");
14513
 
14514
  int i;
14515
  opt_verbose = false;
14516
  opt_debug = false;
14517
  opt_stdin = false;
14518
  opt_text = false;
14519
  opt_code = false;
14520
  opt_bin = false;
14521
  opt_bitstring = false;
14522
  opt_molout = false;
14523
  opt_molstat = false;
14524
  opt_molstat_X = false;
14525
  opt_xmdlout = false;
14526
  opt_fp = false;               /* new in v0.3m */
14527
  /*cm_mdlmolfile   := false; */
14528
  found_arominfo = false;
14529
  found_querymol = false;
14530
  ndl_querymol = false;
14531
  opt_rs = rs_sar;              /* v0.3i */
14532
  ringsearch_mode = opt_rs;
14533
  rfile_is_open = false;        /* new in v0.2g */
14534
  ez_flag = false;              /* new in v0.3f */
14535
  chir_flag = false;            /* new in v0.3f */
14536
  n_Ctot = 0;
14537
  n_Otot = 0;
14538
  n_Ntot = 0;                   /* new in v0.3g */
14539
  //for (i = 0; i < max_fg; i++)
14540
  //  fg[i] = false;
14541
  memset (fg, 0, sizeof (fglist));
14542
 
14543
  if (!yet_initialized)
14544
    {
14545
      molbuf = (void *) safe_malloc (sizeof (molbuftype));
14546
      opt_exact = false;
14547
      opt_strict = false;       /* new in v0.2f */
14548
      opt_metalrings = false;   /* new in v0.3 */
14549
      opt_geom = false;         /* new in v0.3d */
14550
      opt_chiral = false;       /* new in v0.3f */
14551
      opt_iso = false;          /* new in v0.3x */
14552
      opt_chg = false;          /* new in v0.3x */
14553
      opt_rad = false;          /* new in v0.3x */
14554
      ez_search = false;        /* new in v0.3d */
14555
      rs_search = false;        /* new in v0.3f */
14556
      rs_strict = false;        /* new in v0.3j */
14557
      ndl_n_Ctot = 0;
14558
      ndl_n_Otot = 0;
14559
      ndl_n_Ntot = 0;           /* new in v0.3g */
14560
      yet_initialized = true;
14561
    }
14562
 
14563
  ether_generic = false;        /* v0.3j */
14564
  amine_generic = false;        /* v0.3j */
14565
  hydroxy_generic = false;      /* v0.3j */
14566
  fpformat = fpf_decimal;       /* v0.3m */
14567
  fpindex = 0;                  /* v0.3m */
14568
  fp_exacthit = false;          /* v0.3m */
14569
  fp_exactblock = false;        /* v0.3m */
14570
  tmfcode = 0;                  /* v0.3m */
14571
  tmfmismatch = false;          /* v0.3m */
14572
  auto_ssr = false;
14573
  recursion_depth = 0;
14574
}
14575
 
14576
static void
14577
mm_init_mol (void)
14578
{
14579
 
14580
//printf("mm_init_mol\n");
14581
  init_globals_dll ();
14582
  init_molstat (&molstat);
14583
  if (opt_rs_dll == RPA_DEFAULT)
14584
    {
14585
      ringsearch_mode = opt_rs;
14586
      //printf("DEFAULT: %i\n",ringsearch_mode);
14587
    }
14588
  else
14589
    {
14590
      ringsearch_mode = opt_rs_dll;
14591
    }
14592
  //printf("RPA: %i\n",ringsearch_mode);
14593
 
14594
  if (ringsearch_mode == rs_sar)
14595
    {
14596
      max_vringsize = max_ringsize;
14597
    }
14598
  else
14599
    {
14600
      max_vringsize = ssr_vringsize;
14601
    }
14602
  zap_molecule ();
14603
  molbufindex = 0;
14604
  mol_count = 0;
14605
//printf("mm_init_mol\n");
14606
}
14607
 
14608
static void
14609
mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
14610
{
14611
//printf("mm_elab_mol\n");
14612
 
14613
  li = 1;                       // initialize line pointer for input buffer
14614
  get_filetype (filetype, ndl_molfilename);
14615
  if (strcmp (filetype, "unknown") == 0)
14616
    {
14617
      //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
14618
      exit (3);
14619
    }
14620
 
14621
  if (checkmol_mode == true)
14622
    progmode = pmCheckMol;
14623
  else
14624
    progmode = pmMatchMol;
14625
  if (strcmp (filetype, "alchemy") == 0)
14626
    read_molfile (ndl_molfilename);
14627
  if (strcmp (filetype, "sybyl") == 0)
14628
    read_mol2file (ndl_molfilename);
14629
  if (strcmp (filetype, "mdl") == 0)
14630
    read_MDLmolfile (ndl_molfilename);
14631
  if (checkmol_mode)
14632
    {
14633
      if (found_querymol)
14634
        {
14635
          printf
14636
            ("Warning: Input structure contains query atom or query bond.\n");
14637
        }
14638
    }
14639
 
14640
  count_neighbors ();
14641
  if (!found_arominfo || checkmol_mode || opt_strict)
14642
    {
14643
      //printf("No arom found or checkmol mode\n");
14644
      chk_ringbonds ();
14645
      if (ringsearch_mode == rs_ssr)
14646
        remove_redundant_rings ();
14647
      if (n_rings >= max_rings)
14648
        {
14649
 
14650
          printf
14651
            ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14652
             max_rings);
14653
          ringsearch_mode = rs_ssr;
14654
          auto_ssr = true;
14655
          clear_rings ();
14656
          max_vringsize = ssr_vringsize;
14657
          chk_ringbonds ();
14658
          remove_redundant_rings ();
14659
        }
14660
 
14661
      update_ringcount ();
14662
      if (normalize_ionic_bnds) /* v0.3k */
14663
        normalize_ionic_bonds ();
14664
      update_atypes ();
14665
      update_Htotal ();
14666
      chk_arom ();
14667
      if (ringsearch_mode == rs_ssr)
14668
        {                       /* new in v0.3 */
14669
          do
14670
            {
14671
              prev_n_ar = count_aromatic_rings ();
14672
              chk_arom ();
14673
              n_ar = count_aromatic_rings ();
14674
            }
14675
          while (prev_n_ar - n_ar != 0);
14676
        }
14677
    }
14678
  else
14679
    {
14680
      if (normalize_ionic_bnds) /* v0.3k  */
14681
        normalize_ionic_bonds ();
14682
      //if (opt_strict)
14683
      update_atypes ();
14684
      update_Htotal ();
14685
    }
14686
 
14687
 
14688
 
14689
//printf("mm_elab_mol\n");
14690
}
14691
 
14692
DLLEXPORT void
14693
mm_set_current_mol_as_query (void)
14694
{
14695
//printf("mm_set_current_mol_as_query\n");
14696
  zap_needle ();
14697
//mm_ElabMol;
14698
  copy_mol_to_needle ();
14699
  //chk_wildcard_rings (); /* 0.3p */
14700
  set_ndl_atom_tags ();         /* v0.3o */
14701
  if (opt_geom)                 /* v0.3d */
14702
    ez_search = true;
14703
  else if (!ez_flag && ez_search)
14704
    ez_search = false;          //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14705
  if (opt_chiral)
14706
    {                           /* v0.3f */
14707
      rs_search = true;
14708
 
14709
      //printf("%i\n",rs_search);
14710
    }
14711
  else if (!chir_flag && rs_search)
14712
    {
14713
      rs_search = false;        //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14714
      //printf("%i\n",rs_search);
14715
    }
14716
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
14717
    rs_strict = true;
14718
  else
14719
    rs_strict = false;
14720
  /* if (rs_strict)              // v0.3j
14721
     ndl_ref_atom = find_ndl_ref_atom_cv ();
14722
     //ndl_ref_atom = find_ndl_ref_atom ();
14723
     else
14724
     ndl_ref_atom = find_ndl_ref_atom (); */
14725
 
14726
 
14727
 
14728
  molbufindex = 0;
14729
  mol_count = 0;
14730
/*printf("mm_set_current_mol_as_query\n");*/
14731
}
14732
 
14733
DLLEXPORT int
14734
mm_get_rings (void)
14735
{
14736
  return n_rings;
14737
}
14738
 
14739
DLLEXPORT void
14740
xm_version (char *buffer)
14741
{
14742
  buffer[0] = '\0';
14743
  strncpy (buffer, version, 255);
14744
}
14745
 
14746
DLLEXPORT int
14747
mm_get_atom_ring (int atom_number)
14748
{
14749
 
14750
  int i, j, a1, pl;
14751
  int ret = 0;
14752
  a1 = atom[atom_number].ring_count;
14753
  if (n_rings > 0)
14754
    {
14755
      for (i = 1; i < n_rings; i++)
14756
        {
14757
 
14758
          pl = path_length (ring[i]);
14759
//          a2 := ring^[i,pl];
14760
          for (j = 1; j < pl; j++)
14761
            {
14762
 
14763
              a1 = ring[i][j];
14764
              if (atom_number == a1)
14765
                ret = i;
14766
//
14767
//              inc(atom^[a1].ring_count);
14768
//              b := get_bond(a1,a2);
14769
//              inc(bond^[b].ring_count);
14770
//              a2 := a1;
14771
            }
14772
        }
14773
    }
14774
  return ret;
14775
}
14776
 
14777
static void
14778
mm_read_input_line (char *st)
14779
{
14780
//printf("mm_read_input_line_in\n");
14781
//var
14782
//yyy:pchar;
14783
 
14784
  mol_in_queue = false;
14785
  if (molbufindex < (max_atoms + max_bonds + slack))
14786
    {
14787
 
14788
//yyy:=Pchar(IntToStr(molbufindex));
14789
//messagebox (0,yyy,'',0);
14790
//printf("%i\n",molbufindex);
14791
//printf("B:%s\n",st);
14792
      strcpy (molbuf[molbufindex++], st);
14793
//printf("%x %x\n",&molbuf,molbuf);
14794
//printf("%s\n",molbuf[molbufindex-1]);
14795
      //  molbufindex++;
14796
    }
14797
  else
14798
    {
14799
      //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
14800
      printf ("Not enough memory for molfile! %i\n", molbufindex);
14801
      exit (1);
14802
    }
14803
//printf("mm_read_input_line_out\n");
14804
}
14805
 
14806
 
14807
static void
14808
mm_set_mol_dll (const char *st, boolean checkmol_mode,
14809
                boolean normalize_ionic_bnds)
14810
{
14811
//printf("mm_set_mol\n");
14812
//printf("%s\n",st);
14813
  char bb;
14814
  char aa;
14815
  int i;
14816
  int k;
14817
  int J;
14818
  int spt = 0;
14819
  char tt[256];
14820
  char bb10 = '\n';
14821
  char bb13 = '\r';
14822
  char bb0 = '\0';
14823
  int lenst;
14824
//char d[256];
14825
  lenst = strlen (st);
14826
//tt=(char*)safe_malloc(256*sizeof(char));
14827
  tt[0] = '\0';
14828
//messagebox(0,st,'',0);
14829
  mm_init_mol ();
14830
  for (i = spt; i < lenst; i++)
14831
    {
14832
      bb = st[i];
14833
      if ((bb == bb10) || (i == lenst))
14834
        {
14835
          J = 0;
14836
          // d:='';
14837
          for (k = spt; k < i; k++)
14838
            {
14839
 
14840
              aa = st[k];
14841
              if ((aa != bb10) && (aa != bb13))
14842
                {
14843
                  //d:=d+aa;
14844
                  tt[J] = aa;
14845
                  J++;
14846
                }
14847
            }
14848
          tt[J] = bb0;
14849
          spt = i;
14850
          //messagebox (0,tt,tt,0);
14851
//printf("A:%s\n",tt);
14852
          mm_read_input_line (tt);
14853
        }
14854
    }
14855
//free(tt);
14856
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
14857
//printf("mm_set_mol\n");
14858
}
14859
 
14860
DLLEXPORT void
14861
cm_set_mol (const char *st, int normalize_ionic_bnds)
14862
{
14863
  mm_set_mol_dll (st, true, (normalize_ionic_bnds != FEATURE_OFF));
14864
}
14865
 
14866
DLLEXPORT void
14867
mm_set_mol (const char *st)
14868
{
14869
  mm_set_mol_dll (st, false, true);
14870
}
14871
 
14872
DLLEXPORT void
14873
xm_set_strict_typing (int strict_typing)
14874
{
14875
  if (!yet_initialized)
14876
    init_globals_dll ();
14877
  opt_strict = (strict_typing != FEATURE_OFF);
14878
  //opt_strict=false; //This never worked right and is harmful
14879
}
14880
 
14881
DLLEXPORT void
14882
mm_set_r_s_check (int r_s_check)
14883
{
14884
  if (!yet_initialized)
14885
    init_globals_dll ();
14886
  opt_chiral = (r_s_check != FEATURE_OFF);
14887
}
14888
 
14889
DLLEXPORT void
14890
mm_set_e_z_check (int e_z_check)
14891
{
14892
  if (!yet_initialized)
14893
    init_globals_dll ();
14894
  opt_geom = (e_z_check != FEATURE_OFF);
14895
}
14896
 
14897
DLLEXPORT void
14898
mm_set_chg_check (int chg_check)
14899
{
14900
  if (!yet_initialized)
14901
    init_globals_dll ();
14902
  opt_chg = (chg_check != FEATURE_OFF);
14903
}
14904
 
14905
DLLEXPORT void
14906
mm_set_iso_check (int iso_check)
14907
{
14908
  if (!yet_initialized)
14909
    init_globals_dll ();
14910
  opt_iso = (iso_check != FEATURE_OFF);
14911
}
14912
 
14913
DLLEXPORT void
14914
mm_set_rad_check (int rad_check)
14915
{
14916
  if (!yet_initialized)
14917
    init_globals_dll ();
14918
  opt_rad = (rad_check != FEATURE_OFF);
14919
}
14920
 
14921
DLLEXPORT void
14922
mm_set_exact_match (int exact)
14923
{
14924
  if (!yet_initialized)
14925
    init_globals_dll ();
14926
  opt_exact = (exact != FEATURE_OFF);
14927
}
14928
 
14929
DLLEXPORT int
14930
mm_match ()
14931
{
14932
  mol_count = 1;
14933
//     mm_ElabMol;
14934
/*printf("%i\n",opt_exact);
14935
printf("%i\n",n_Ctot);
14936
printf("%i\n",ndl_n_Ctot);
14937
printf("%i\n",n_Otot);
14938
printf("%i\n",ndl_n_Otot);
14939
printf("%i\n",n_Ntot);
14940
printf("%i\n",ndl_n_Ntot);*/
14941
  if (opt_exact
14942
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14943
          || n_Ntot != ndl_n_Ntot))
14944
    return 0;
14945
  init_molstat (&ndl_molstat);
14946
  //perform_match ();
14947
  //---------------------------------------------------- 0.3o
14948
  if (rs_strict)                /* v0.3j */
14949
    ndl_ref_atom = find_ndl_ref_atom_cv ();
14950
  //ndl_ref_atom = find_ndl_ref_atom ();
14951
  else
14952
    ndl_ref_atom = find_ndl_ref_atom ();
14953
  clear_atom_tags ();
14954
  set_ndl_atom_tags ();
14955
  matchsummary = true;
14956
  perform_match ();
14957
  matchsummary = matchresult;
14958
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true)
14959
    {
14960
      do
14961
        {
14962
          if (rs_strict)
14963
            ndl_ref_atom = find_ndl_ref_atom_cv ();
14964
          else
14965
            ndl_ref_atom = find_ndl_ref_atom ();
14966
          perform_match ();
14967
          if (matchresult == false)
14968
            matchsummary = false;
14969
        }
14970
      while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
14971
    }
14972
 
14973
  //-----------------------------------------------------
14974
 
14975
  //mol_count = 0;
14976
 
14977
  //molbufindex = 0;
14978
 
14979
  //return matchresult ? 1 : 0;
14980
 
14981
  return matchsummary ? 1 : 0;
14982
}
14983
 
14984
//-------------------------
14985
 
14986
DLLEXPORT void
14987
xm_set_ring_perception_algorithm (int algo)
14988
{
14989
  switch (algo)
14990
    {
14991
    case RPA_SAR:
14992
      opt_rs_dll = rs_sar;
14993
      break;
14994
    case RPA_SSR:
14995
      opt_rs_dll = rs_ssr;
14996
      break;
14997
    default:
14998
      opt_rs_dll = RPA_DEFAULT;
14999
      break;
15000
    }
15001
  //printf("RPA_SET: %i\n",opt_rs_dll);
15002
}
15003
 
15004
static void
15005
write_molstat_X_dll (char *out_buffer)
15006
{
15007
  char tmp_buf[256];
15008
  out_buffer[0] = '\0';
15009
  if (auto_ssr)                 /* v0.3n */
15010
    fix_ssr_ringcounts ();
15011
  sprintf (tmp_buf, "%d,", n_heavyatoms);
15012
  strcat (out_buffer, tmp_buf);
15013
  sprintf (tmp_buf, "%d,", n_heavybonds);
15014
  strcat (out_buffer, tmp_buf);
15015
#ifdef REDUCED_SAR
15016
  sprintf (tmp_buf, "%d,", n_countablerings);
15017
  strcat (out_buffer, tmp_buf);
15018
#else
15019
  sprintf (tmp_buf, "%d,", n_rings);
15020
  strcat (out_buffer, tmp_buf);
15021
#endif
15022
  sprintf (tmp_buf, "%d,", molstat.n_QA);
15023
  strcat (out_buffer, tmp_buf);
15024
  sprintf (tmp_buf, "%d,", molstat.n_QB);
15025
  strcat (out_buffer, tmp_buf);
15026
  //if (opt_chg)
15027
//    {                         /* 0.3x */
15028
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
15029
//    }
15030
//  else
15031
//    {
15032
  sprintf (tmp_buf, "%d,", molstat.n_chg);
15033
  //   }
15034
  strcat (out_buffer, tmp_buf);
15035
  sprintf (tmp_buf, "%d,", molstat.n_C1);
15036
  strcat (out_buffer, tmp_buf);
15037
  sprintf (tmp_buf, "%d,", molstat.n_C2);
15038
  strcat (out_buffer, tmp_buf);
15039
  sprintf (tmp_buf, "%d,", molstat.n_C);
15040
  strcat (out_buffer, tmp_buf);
15041
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
15042
  strcat (out_buffer, tmp_buf);
15043
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
15044
  strcat (out_buffer, tmp_buf);
15045
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
15046
  strcat (out_buffer, tmp_buf);
15047
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
15048
  strcat (out_buffer, tmp_buf);
15049
  sprintf (tmp_buf, "%d,", molstat.n_O2);
15050
  strcat (out_buffer, tmp_buf);
15051
  sprintf (tmp_buf, "%d,", molstat.n_O3);
15052
  strcat (out_buffer, tmp_buf);
15053
  sprintf (tmp_buf, "%d,", molstat.n_N1);
15054
  strcat (out_buffer, tmp_buf);
15055
  sprintf (tmp_buf, "%d,", molstat.n_N2);
15056
  strcat (out_buffer, tmp_buf);
15057
  sprintf (tmp_buf, "%d,", molstat.n_N3);
15058
  strcat (out_buffer, tmp_buf);
15059
  sprintf (tmp_buf, "%d,", molstat.n_S);
15060
  strcat (out_buffer, tmp_buf);
15061
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
15062
  strcat (out_buffer, tmp_buf);
15063
  sprintf (tmp_buf, "%d,", molstat.n_F);
15064
  strcat (out_buffer, tmp_buf);
15065
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
15066
  strcat (out_buffer, tmp_buf);
15067
  sprintf (tmp_buf, "%d,", molstat.n_Br);
15068
  strcat (out_buffer, tmp_buf);
15069
  sprintf (tmp_buf, "%d,", molstat.n_I);
15070
  strcat (out_buffer, tmp_buf);
15071
  sprintf (tmp_buf, "%d,", molstat.n_P);
15072
  strcat (out_buffer, tmp_buf);
15073
  sprintf (tmp_buf, "%d,", molstat.n_B);
15074
  strcat (out_buffer, tmp_buf);
15075
  sprintf (tmp_buf, "%d,", molstat.n_Met);
15076
  strcat (out_buffer, tmp_buf);
15077
  sprintf (tmp_buf, "%d,", molstat.n_X);
15078
  strcat (out_buffer, tmp_buf);
15079
  sprintf (tmp_buf, "%d,", molstat.n_b1);
15080
  strcat (out_buffer, tmp_buf);
15081
  sprintf (tmp_buf, "%d,", molstat.n_b2);
15082
  strcat (out_buffer, tmp_buf);
15083
  sprintf (tmp_buf, "%d,", molstat.n_b3);
15084
  strcat (out_buffer, tmp_buf);
15085
  sprintf (tmp_buf, "%d,", molstat.n_bar);
15086
  strcat (out_buffer, tmp_buf);
15087
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
15088
  strcat (out_buffer, tmp_buf);
15089
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
15090
  strcat (out_buffer, tmp_buf);
15091
  sprintf (tmp_buf, "%d,", molstat.n_CN);
15092
  strcat (out_buffer, tmp_buf);
15093
  sprintf (tmp_buf, "%d,", molstat.n_XY);
15094
  strcat (out_buffer, tmp_buf);
15095
  sprintf (tmp_buf, "%d,", molstat.n_r3);
15096
  strcat (out_buffer, tmp_buf);
15097
  sprintf (tmp_buf, "%d,", molstat.n_r4);
15098
  strcat (out_buffer, tmp_buf);
15099
  sprintf (tmp_buf, "%d,", molstat.n_r5);
15100
  strcat (out_buffer, tmp_buf);
15101
  sprintf (tmp_buf, "%d,", molstat.n_r6);
15102
  strcat (out_buffer, tmp_buf);
15103
  sprintf (tmp_buf, "%d,", molstat.n_r7);
15104
  strcat (out_buffer, tmp_buf);
15105
  sprintf (tmp_buf, "%d,", molstat.n_r8);
15106
  strcat (out_buffer, tmp_buf);
15107
  sprintf (tmp_buf, "%d,", molstat.n_r9);
15108
  strcat (out_buffer, tmp_buf);
15109
  sprintf (tmp_buf, "%d,", molstat.n_r10);
15110
  strcat (out_buffer, tmp_buf);
15111
  sprintf (tmp_buf, "%d,", molstat.n_r11);
15112
  strcat (out_buffer, tmp_buf);
15113
  sprintf (tmp_buf, "%d,", molstat.n_r12);
15114
  strcat (out_buffer, tmp_buf);
15115
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
15116
  strcat (out_buffer, tmp_buf);
15117
  sprintf (tmp_buf, "%d,", molstat.n_rN);
15118
  strcat (out_buffer, tmp_buf);
15119
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
15120
  strcat (out_buffer, tmp_buf);
15121
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
15122
  strcat (out_buffer, tmp_buf);
15123
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
15124
  strcat (out_buffer, tmp_buf);
15125
  sprintf (tmp_buf, "%d,", molstat.n_rO);
15126
  strcat (out_buffer, tmp_buf);
15127
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
15128
  strcat (out_buffer, tmp_buf);
15129
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
15130
  strcat (out_buffer, tmp_buf);
15131
  sprintf (tmp_buf, "%d,", molstat.n_rS);
15132
  strcat (out_buffer, tmp_buf);
15133
  sprintf (tmp_buf, "%d,", molstat.n_rX);
15134
  strcat (out_buffer, tmp_buf);
15135
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
15136
  strcat (out_buffer, tmp_buf);
15137
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
15138
  strcat (out_buffer, tmp_buf);
15139
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
15140
  strcat (out_buffer, tmp_buf);
15141
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
15142
  strcat (out_buffer, tmp_buf);
15143
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
15144
  strcat (out_buffer, tmp_buf);
15145
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
15146
  strcat (out_buffer, tmp_buf);
15147
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
15148
  strcat (out_buffer, tmp_buf);
15149
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
15150
  strcat (out_buffer, tmp_buf);
15151
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
15152
  strcat (out_buffer, tmp_buf);
15153
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
15154
  strcat (out_buffer, tmp_buf);
15155
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
15156
  strcat (out_buffer, tmp_buf);
15157
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
15158
  strcat (out_buffer, tmp_buf);
15159
  sprintf (tmp_buf, "%d,", molstat.n_psla);
15160
  strcat (out_buffer, tmp_buf);
15161
  sprintf (tmp_buf, "%d,", molstat.n_iso);
15162
  strcat (out_buffer, tmp_buf);
15163
  sprintf (tmp_buf, "%d", molstat.n_rad);
15164
  strcat (out_buffer, tmp_buf);
15165
}
15166
 
15167
static void
15168
write_molstat_dll (char *out_buffer, int mode)
15169
{
15170
  char tmp_buf[256];
15171
  char *sep1;
15172
  char *sep2;
15173
  switch (mode)
15174
    {
15175
    case 1:
15176
      sep1 = "=";
15177
      sep2 = " AND ";
15178
      break;
15179
    case 2:
15180
      sep1 = "<=";
15181
      sep2 = " AND ";
15182
      break;
15183
    default:
15184
      sep1 = ":";
15185
      sep2 = ";";
15186
      break;
15187
    }
15188
 
15189
 
15190
 
15191
  out_buffer[0] = '\0';
15192
 
15193
  if (auto_ssr)                 /* v0.3n */
15194
    fix_ssr_ringcounts ();
15195
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
15196
  strcat (out_buffer, tmp_buf);
15197
  if (n_bonds > 0)
15198
    {
15199
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
15200
      strcat (out_buffer, tmp_buf);
15201
    }
15202
 
15203
#ifdef REDUCED_SAR
15204
  if (n_rings > 0)
15205
    {
15206
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
15207
      strcat (out_buffer, tmp_buf);
15208
    }
15209
#else
15210
  if (n_rings > 0)
15211
    {
15212
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
15213
      strcat (out_buffer, tmp_buf);
15214
    }
15215
#endif
15216
 
15217
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */
15218
    {
15219
      sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
15220
      strcat (out_buffer, tmp_buf);
15221
    }
15222
  if (molstat.n_C1 > 0)
15223
    {
15224
      sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
15225
      strcat (out_buffer, tmp_buf);
15226
    }
15227
  if (molstat.n_C2 > 0)
15228
    {
15229
      sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
15230
      strcat (out_buffer, tmp_buf);
15231
    }
15232
 
15233
 
15234
  if (molstat.n_C > 0)
15235
    {
15236
      sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
15237
      strcat (out_buffer, tmp_buf);
15238
    }
15239
  if (molstat.n_CHB1p > 0)
15240
    {
15241
      sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
15242
      strcat (out_buffer, tmp_buf);
15243
    }
15244
  if (molstat.n_CHB2p > 0)
15245
    {
15246
      sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
15247
      strcat (out_buffer, tmp_buf);
15248
    }
15249
  if (molstat.n_CHB3p > 0)
15250
    {
15251
      sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
15252
      strcat (out_buffer, tmp_buf);
15253
    }
15254
  if (molstat.n_CHB4 > 0)
15255
    {
15256
      sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
15257
      strcat (out_buffer, tmp_buf);
15258
    }
15259
  if (molstat.n_O2 > 0)
15260
    {
15261
      sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
15262
      strcat (out_buffer, tmp_buf);
15263
    }
15264
  if (molstat.n_O3 > 0)
15265
    {
15266
      sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
15267
      strcat (out_buffer, tmp_buf);
15268
    }
15269
  if (molstat.n_N1 > 0)
15270
    {
15271
      sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
15272
      strcat (out_buffer, tmp_buf);
15273
    }
15274
  if (molstat.n_N2 > 0)
15275
    {
15276
      sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
15277
      strcat (out_buffer, tmp_buf);
15278
    }
15279
  if (molstat.n_N3 > 0)
15280
    {
15281
      sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
15282
      strcat (out_buffer, tmp_buf);
15283
    }
15284
  if (molstat.n_S > 0)
15285
    {
15286
      sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
15287
      strcat (out_buffer, tmp_buf);
15288
    }
15289
  if (molstat.n_SeTe > 0)
15290
    {
15291
      sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
15292
      strcat (out_buffer, tmp_buf);
15293
    }
15294
  if (molstat.n_F > 0)
15295
    {
15296
      sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
15297
      strcat (out_buffer, tmp_buf);
15298
    }
15299
  if (molstat.n_Cl > 0)
15300
    {
15301
      sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
15302
      strcat (out_buffer, tmp_buf);
15303
    }
15304
  if (molstat.n_Br > 0)
15305
    {
15306
      sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
15307
      strcat (out_buffer, tmp_buf);
15308
    }
15309
  if (molstat.n_I > 0)
15310
    {
15311
      sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
15312
      strcat (out_buffer, tmp_buf);
15313
    }
15314
  if (molstat.n_P > 0)
15315
    {
15316
      sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
15317
      strcat (out_buffer, tmp_buf);
15318
    }
15319
  if (molstat.n_B > 0)
15320
    {
15321
      sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
15322
      strcat (out_buffer, tmp_buf);
15323
    }
15324
  if (molstat.n_Met > 0)
15325
    {
15326
      sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
15327
      strcat (out_buffer, tmp_buf);
15328
    }
15329
  if (molstat.n_X > 0)
15330
    {
15331
      sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
15332
      strcat (out_buffer, tmp_buf);
15333
    }
15334
  if (molstat.n_b1 > 0)
15335
    {
15336
      sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
15337
      strcat (out_buffer, tmp_buf);
15338
    }
15339
  if (molstat.n_b2 > 0)
15340
    {
15341
      sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
15342
      strcat (out_buffer, tmp_buf);
15343
    }
15344
  if (molstat.n_b3 > 0)
15345
    {
15346
      sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
15347
      strcat (out_buffer, tmp_buf);
15348
    }
15349
  if (molstat.n_bar > 0)
15350
    {
15351
      sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
15352
      strcat (out_buffer, tmp_buf);
15353
    }
15354
  if (molstat.n_C1O > 0)
15355
    {
15356
      sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
15357
      strcat (out_buffer, tmp_buf);
15358
    }
15359
  if (molstat.n_C2O > 0)
15360
    {
15361
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
15362
      strcat (out_buffer, tmp_buf);
15363
    }
15364
  if (molstat.n_CN > 0)
15365
    {
15366
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
15367
      strcat (out_buffer, tmp_buf);
15368
    }
15369
  if (molstat.n_XY > 0)
15370
    {
15371
      sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
15372
      strcat (out_buffer, tmp_buf);
15373
    }
15374
  if (molstat.n_r3 > 0)
15375
    {
15376
      sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
15377
      strcat (out_buffer, tmp_buf);
15378
    }
15379
  if (molstat.n_r4 > 0)
15380
    {
15381
      sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
15382
      strcat (out_buffer, tmp_buf);
15383
    }
15384
  if (molstat.n_r5 > 0)
15385
    {
15386
      sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
15387
      strcat (out_buffer, tmp_buf);
15388
    }
15389
  if (molstat.n_r6 > 0)
15390
    {
15391
      sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
15392
      strcat (out_buffer, tmp_buf);
15393
    }
15394
  if (molstat.n_r7 > 0)
15395
    {
15396
      sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
15397
      strcat (out_buffer, tmp_buf);
15398
    }
15399
  if (molstat.n_r8 > 0)
15400
    {
15401
      sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
15402
      strcat (out_buffer, tmp_buf);
15403
    }
15404
  if (molstat.n_r9 > 0)
15405
    {
15406
      sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
15407
      strcat (out_buffer, tmp_buf);
15408
    }
15409
  if (molstat.n_r10 > 0)
15410
    {
15411
      sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
15412
      strcat (out_buffer, tmp_buf);
15413
    }
15414
  if (molstat.n_r11 > 0)
15415
    {
15416
      sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
15417
      strcat (out_buffer, tmp_buf);
15418
    }
15419
  if (molstat.n_r12 > 0)
15420
    {
15421
      sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
15422
      strcat (out_buffer, tmp_buf);
15423
    }
15424
  if (molstat.n_r13p > 0)
15425
    {
15426
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
15427
      strcat (out_buffer, tmp_buf);
15428
    }
15429
  if (molstat.n_rN > 0)
15430
    {
15431
      sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
15432
      strcat (out_buffer, tmp_buf);
15433
    }
15434
  if (molstat.n_rN1 > 0)
15435
    {
15436
      sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
15437
      strcat (out_buffer, tmp_buf);
15438
    }
15439
  if (molstat.n_rN2 > 0)
15440
    {
15441
      sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
15442
      strcat (out_buffer, tmp_buf);
15443
    }
15444
  if (molstat.n_rN3p > 0)
15445
    {
15446
      sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
15447
      strcat (out_buffer, tmp_buf);
15448
    }
15449
  if (molstat.n_rO > 0)
15450
    {
15451
      sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
15452
      strcat (out_buffer, tmp_buf);
15453
    }
15454
  if (molstat.n_rO1 > 0)
15455
    {
15456
      sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
15457
      strcat (out_buffer, tmp_buf);
15458
    }
15459
  if (molstat.n_rO2p > 0)
15460
    {
15461
      sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
15462
      strcat (out_buffer, tmp_buf);
15463
    }
15464
  if (molstat.n_rS > 0)
15465
    {
15466
      sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
15467
      strcat (out_buffer, tmp_buf);
15468
    }
15469
  if (molstat.n_rX > 0)
15470
    {
15471
      sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
15472
      strcat (out_buffer, tmp_buf);
15473
    }
15474
  if (molstat.n_rAr > 0)
15475
    {
15476
      sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
15477
      strcat (out_buffer, tmp_buf);
15478
    }
15479
 
15480
  if (molstat.n_rBz > 0)
15481
    {
15482
      sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
15483
      strcat (out_buffer, tmp_buf);
15484
    }
15485
 
15486
  if (molstat.n_br2p > 0)
15487
    {
15488
      sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
15489
      strcat (out_buffer, tmp_buf);
15490
    }
15491
 
15492
  if (molstat.n_psg01 > 0)
15493
    {
15494
      sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
15495
      strcat (out_buffer, tmp_buf);
15496
    }
15497
 
15498
  if (molstat.n_psg02 > 0)
15499
    {
15500
      sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
15501
      strcat (out_buffer, tmp_buf);
15502
    }
15503
 
15504
  if (molstat.n_psg13 > 0)
15505
    {
15506
      sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
15507
      strcat (out_buffer, tmp_buf);
15508
    }
15509
 
15510
  if (molstat.n_psg14 > 0)
15511
    {
15512
      sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
15513
      strcat (out_buffer, tmp_buf);
15514
    }
15515
 
15516
  if (molstat.n_psg15 > 0)
15517
    {
15518
      sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
15519
      strcat (out_buffer, tmp_buf);
15520
    }
15521
 
15522
  if (molstat.n_psg16 > 0)
15523
    {
15524
      sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
15525
      strcat (out_buffer, tmp_buf);
15526
    }
15527
 
15528
  if (molstat.n_psg17 > 0)
15529
    {
15530
      sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
15531
      strcat (out_buffer, tmp_buf);
15532
    }
15533
 
15534
  if (molstat.n_psg18 > 0)
15535
    {
15536
      sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
15537
      strcat (out_buffer, tmp_buf);
15538
    }
15539
 
15540
  if (molstat.n_pstm > 0)
15541
    {
15542
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
15543
      strcat (out_buffer, tmp_buf);
15544
    }
15545
 
15546
  if (molstat.n_psla > 0)
15547
    {
15548
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
15549
      strcat (out_buffer, tmp_buf);
15550
    }
15551
 
15552
  if (opt_iso && molstat.n_iso > 0)
15553
    {
15554
      sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
15555
      strcat (out_buffer, tmp_buf);
15556
    }
15557
 
15558
  if (opt_rad && molstat.n_rad > 0)
15559
    {
15560
      sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
15561
      strcat (out_buffer, tmp_buf);
15562
    }
15563
}
15564
 
15565
static void
15566
write_fg_code_dll (char *out_buffer)
15567
{
15568
  char tmp_buf[256];
15569
  out_buffer[0] = '\0';
15570
  if (fg[fg_cation - 1])
15571
    {
15572
      sprintf (tmp_buf, "000000T2;");
15573
      strcat (out_buffer, tmp_buf);
15574
    }
15575
  if (fg[fg_anion - 1])
15576
    {
15577
      sprintf (tmp_buf, "000000T1;");
15578
      strcat (out_buffer, tmp_buf);
15579
    }
15580
 
15581
  if (fg[fg_aldehyde - 1])
15582
    {
15583
      sprintf (tmp_buf, "C2O1H000;");
15584
      strcat (out_buffer, tmp_buf);
15585
    }
15586
  if (fg[fg_ketone - 1])
15587
    {
15588
      sprintf (tmp_buf, "C2O1C000;");
15589
      strcat (out_buffer, tmp_buf);
15590
    }
15591
 
15592
  if (fg[fg_thioaldehyde - 1])
15593
    {
15594
      sprintf (tmp_buf, "C2S1H000;");
15595
      strcat (out_buffer, tmp_buf);
15596
    }
15597
  if (fg[fg_thioketone - 1])
15598
    {
15599
      sprintf (tmp_buf, "C2S1C000;");
15600
      strcat (out_buffer, tmp_buf);
15601
    }
15602
  if (fg[fg_imine - 1])
15603
    {
15604
      sprintf (tmp_buf, "C2N10000;");
15605
      strcat (out_buffer, tmp_buf);
15606
    }
15607
  if (fg[fg_hydrazone - 1])
15608
    {
15609
      sprintf (tmp_buf, "C2N1N000;");
15610
      strcat (out_buffer, tmp_buf);
15611
    }
15612
  if (fg[fg_semicarbazone - 1])
15613
    {
15614
      sprintf (tmp_buf, "C2NNC4ON;");
15615
      strcat (out_buffer, tmp_buf);
15616
    }
15617
  if (fg[fg_thiosemicarbazone - 1])
15618
    {
15619
      sprintf (tmp_buf, "C2NNC4SN;");
15620
      strcat (out_buffer, tmp_buf);
15621
    }
15622
  if (fg[fg_oxime - 1])
15623
    {
15624
      sprintf (tmp_buf, "C2N1OH00;");
15625
      strcat (out_buffer, tmp_buf);
15626
    }
15627
  if (fg[fg_oxime_ether - 1])
15628
    {
15629
      sprintf (tmp_buf, "C2N1OC00;");
15630
      strcat (out_buffer, tmp_buf);
15631
    }
15632
  if (fg[fg_ketene - 1])
15633
    {
15634
      sprintf (tmp_buf, "C3OC0000;");
15635
      strcat (out_buffer, tmp_buf);
15636
    }
15637
  if (fg[fg_ketene_acetal_deriv - 1])
15638
    {
15639
      sprintf (tmp_buf, "C3OCC000;");
15640
      strcat (out_buffer, tmp_buf);
15641
    }
15642
  if (fg[fg_carbonyl_hydrate - 1])
15643
    {
15644
      sprintf (tmp_buf, "C2O2H200;");
15645
      strcat (out_buffer, tmp_buf);
15646
    }
15647
  if (fg[fg_hemiacetal - 1])
15648
    {
15649
      sprintf (tmp_buf, "C2O2HC00;");
15650
      strcat (out_buffer, tmp_buf);
15651
    }
15652
  if (fg[fg_acetal - 1])
15653
    {
15654
      sprintf (tmp_buf, "C2O2CC00;");
15655
      strcat (out_buffer, tmp_buf);
15656
    }
15657
  if (fg[fg_hemiaminal - 1])
15658
    {
15659
      sprintf (tmp_buf, "C2NOHC10;");
15660
      strcat (out_buffer, tmp_buf);
15661
    }
15662
  if (fg[fg_aminal - 1])
15663
    {
15664
      sprintf (tmp_buf, "C2N2CC10;");
15665
      strcat (out_buffer, tmp_buf);
15666
    }
15667
  if (fg[fg_thiohemiaminal - 1])
15668
    {
15669
      sprintf (tmp_buf, "C2NSHC10;");
15670
      strcat (out_buffer, tmp_buf);
15671
    }
15672
  if (fg[fg_thioacetal - 1])
15673
    {
15674
      sprintf (tmp_buf, "C2S2CC00;");
15675
      strcat (out_buffer, tmp_buf);
15676
    }
15677
  if (fg[fg_enamine - 1])
15678
    {
15679
      sprintf (tmp_buf, "C2CNH000;");
15680
      strcat (out_buffer, tmp_buf);
15681
    }
15682
  if (fg[fg_enol - 1])
15683
    {
15684
      sprintf (tmp_buf, "C2COH000;");
15685
      strcat (out_buffer, tmp_buf);
15686
    }
15687
  if (fg[fg_enolether - 1])
15688
    {
15689
      sprintf (tmp_buf, "C2COC000;");
15690
      strcat (out_buffer, tmp_buf);
15691
    }
15692
 
15693
 
15694
  if (fg[fg_prim_alcohol - 1])
15695
    {
15696
      sprintf (tmp_buf, "O1H1C000;");
15697
      strcat (out_buffer, tmp_buf);
15698
    }
15699
  if (fg[fg_sec_alcohol - 1])
15700
    {
15701
      sprintf (tmp_buf, "O1H2C000;");
15702
      strcat (out_buffer, tmp_buf);
15703
    }
15704
  if (fg[fg_tert_alcohol - 1])
15705
    {
15706
      sprintf (tmp_buf, "O1H3C000;");
15707
      strcat (out_buffer, tmp_buf);
15708
    }
15709
  if (fg[fg_1_2_diol - 1])
15710
    {
15711
      sprintf (tmp_buf, "O1H0CO1H;");
15712
      strcat (out_buffer, tmp_buf);
15713
    }
15714
  if (fg[fg_1_2_aminoalcohol - 1])
15715
    {
15716
      sprintf (tmp_buf, "O1H0CN1C;");
15717
      strcat (out_buffer, tmp_buf);
15718
    }
15719
  if (fg[fg_phenol - 1])
15720
    {
15721
      sprintf (tmp_buf, "O1H1A000;");
15722
      strcat (out_buffer, tmp_buf);
15723
    }
15724
  if (fg[fg_1_2_diphenol - 1])
15725
    {
15726
      sprintf (tmp_buf, "O1H2A000;");
15727
      strcat (out_buffer, tmp_buf);
15728
    }
15729
  if (fg[fg_enediol - 1])
15730
    {
15731
      sprintf (tmp_buf, "C2COH200;");
15732
      strcat (out_buffer, tmp_buf);
15733
    }
15734
 
15735
  if (fg[fg_dialkylether - 1])
15736
    {
15737
      sprintf (tmp_buf, "O1C0CC00;");
15738
      strcat (out_buffer, tmp_buf);
15739
    }
15740
  if (fg[fg_alkylarylether - 1])
15741
    {
15742
      sprintf (tmp_buf, "O1C0CA00;");
15743
      strcat (out_buffer, tmp_buf);
15744
    }
15745
  if (fg[fg_diarylether - 1])
15746
    {
15747
      sprintf (tmp_buf, "O1C0AA00;");
15748
      strcat (out_buffer, tmp_buf);
15749
    }
15750
  if (fg[fg_thioether - 1])
15751
    {
15752
      sprintf (tmp_buf, "S1C00000;");
15753
      strcat (out_buffer, tmp_buf);
15754
    }
15755
  if (fg[fg_disulfide - 1])
15756
    {
15757
      sprintf (tmp_buf, "S1S1C000;");
15758
      strcat (out_buffer, tmp_buf);
15759
    }
15760
  if (fg[fg_peroxide - 1])
15761
    {
15762
      sprintf (tmp_buf, "O1O1C000;");
15763
      strcat (out_buffer, tmp_buf);
15764
    }
15765
  if (fg[fg_hydroperoxide - 1])
15766
    {
15767
      sprintf (tmp_buf, "O1O1H000;");
15768
      strcat (out_buffer, tmp_buf);
15769
    }
15770
  if (fg[fg_hydrazine - 1])
15771
    {
15772
      sprintf (tmp_buf, "N1N10000;");
15773
      strcat (out_buffer, tmp_buf);
15774
    }
15775
  if (fg[fg_hydroxylamine - 1])
15776
    {
15777
      sprintf (tmp_buf, "N1O1H000;");
15778
      strcat (out_buffer, tmp_buf);
15779
    }
15780
 
15781
 
15782
  if (fg[fg_prim_aliph_amine - 1])
15783
    {
15784
      sprintf (tmp_buf, "N1C1C000;");
15785
      strcat (out_buffer, tmp_buf);
15786
    }
15787
  if (fg[fg_prim_arom_amine - 1])
15788
    {
15789
      sprintf (tmp_buf, "N1C1A000;");
15790
      strcat (out_buffer, tmp_buf);
15791
    }
15792
 
15793
  if (fg[fg_sec_aliph_amine - 1])
15794
    {
15795
      sprintf (tmp_buf, "N1C2CC00;");
15796
      strcat (out_buffer, tmp_buf);
15797
    }
15798
  if (fg[fg_sec_mixed_amine - 1])
15799
    {
15800
      sprintf (tmp_buf, "N1C2AC00;");
15801
      strcat (out_buffer, tmp_buf);
15802
    }
15803
  if (fg[fg_sec_arom_amine - 1])
15804
    {
15805
      sprintf (tmp_buf, "N1C2AA00;");
15806
      strcat (out_buffer, tmp_buf);
15807
    }
15808
 
15809
  if (fg[fg_tert_aliph_amine - 1])
15810
    {
15811
      sprintf (tmp_buf, "N1C3CC00;");
15812
      strcat (out_buffer, tmp_buf);
15813
    }
15814
  if (fg[fg_tert_mixed_amine - 1])
15815
    {
15816
      sprintf (tmp_buf, "N1C3AC00;");
15817
      strcat (out_buffer, tmp_buf);
15818
    }
15819
  if (fg[fg_tert_arom_amine - 1])
15820
    {
15821
      sprintf (tmp_buf, "N1C3AA00;");
15822
      strcat (out_buffer, tmp_buf);
15823
    }
15824
  if (fg[fg_quart_ammonium - 1])
15825
    {
15826
      sprintf (tmp_buf, "N1C400T2;");
15827
      strcat (out_buffer, tmp_buf);
15828
    }
15829
  if (fg[fg_n_oxide - 1])
15830
    {
15831
      sprintf (tmp_buf, "N0O10000;");
15832
      strcat (out_buffer, tmp_buf);
15833
    }
15834
 
15835
 
15836
  if (fg[fg_halogen_deriv - 1])
15837
    {
15838
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
15839
          !fg[fg_acyl_halide - 1])
15840
        {
15841
          sprintf (tmp_buf, "XX000000;");
15842
          strcat (out_buffer, tmp_buf);
15843
        }
15844
    }
15845
 
15846
  if (fg[fg_alkyl_fluoride - 1])
15847
    {
15848
      sprintf (tmp_buf, "XF00C000;");
15849
      strcat (out_buffer, tmp_buf);
15850
    }
15851
  if (fg[fg_alkyl_chloride - 1])
15852
    {
15853
      sprintf (tmp_buf, "XC00C000;");
15854
      strcat (out_buffer, tmp_buf);
15855
    }
15856
  if (fg[fg_alkyl_bromide - 1])
15857
    {
15858
      sprintf (tmp_buf, "XB00C000;");
15859
      strcat (out_buffer, tmp_buf);
15860
    }
15861
  if (fg[fg_alkyl_iodide - 1])
15862
    {
15863
      sprintf (tmp_buf, "XI00C000;");
15864
      strcat (out_buffer, tmp_buf);
15865
    }
15866
 
15867
  if (fg[fg_aryl_fluoride - 1])
15868
    {
15869
      sprintf (tmp_buf, "XF00A000;");
15870
      strcat (out_buffer, tmp_buf);
15871
    }
15872
  if (fg[fg_aryl_chloride - 1])
15873
    {
15874
      sprintf (tmp_buf, "XC00A000;");
15875
      strcat (out_buffer, tmp_buf);
15876
    }
15877
  if (fg[fg_aryl_bromide - 1])
15878
    {
15879
      sprintf (tmp_buf, "XB00A000;");
15880
      strcat (out_buffer, tmp_buf);
15881
    }
15882
  if (fg[fg_aryl_iodide - 1])
15883
    {
15884
      sprintf (tmp_buf, "XI00A000;");
15885
      strcat (out_buffer, tmp_buf);
15886
    }
15887
  if (fg[fg_organometallic - 1])
15888
    {
15889
      sprintf (tmp_buf, "000000MX;");
15890
      strcat (out_buffer, tmp_buf);
15891
    }
15892
  if (fg[fg_organolithium - 1])
15893
    {
15894
      sprintf (tmp_buf, "000000ML;");
15895
      strcat (out_buffer, tmp_buf);
15896
    }
15897
  if (fg[fg_organomagnesium - 1])
15898
    {
15899
      sprintf (tmp_buf, "000000MM;");
15900
      strcat (out_buffer, tmp_buf);
15901
    }
15902
 
15903
  if (fg[fg_carboxylic_acid - 1])
15904
    {
15905
      sprintf (tmp_buf, "C3O2H000;");
15906
      strcat (out_buffer, tmp_buf);
15907
    }
15908
  if (fg[fg_carboxylic_acid_salt - 1])
15909
    {
15910
      sprintf (tmp_buf, "C3O200T1;");
15911
      strcat (out_buffer, tmp_buf);
15912
    }
15913
  if (fg[fg_carboxylic_acid_ester - 1])
15914
    {
15915
      sprintf (tmp_buf, "C3O2C000;");
15916
      strcat (out_buffer, tmp_buf);
15917
    }
15918
  if (fg[fg_lactone - 1])
15919
    {
15920
      sprintf (tmp_buf, "C3O2CZ00;");
15921
      strcat (out_buffer, tmp_buf);
15922
    }
15923
 
15924
  if (fg[fg_carboxylic_acid_prim_amide - 1])
15925
    {
15926
      sprintf (tmp_buf, "C3ONC100;");
15927
      strcat (out_buffer, tmp_buf);
15928
    }
15929
  if (fg[fg_carboxylic_acid_sec_amide - 1])
15930
    {
15931
      sprintf (tmp_buf, "C3ONC200;");
15932
      strcat (out_buffer, tmp_buf);
15933
    }
15934
  if (fg[fg_carboxylic_acid_tert_amide - 1])
15935
    {
15936
      sprintf (tmp_buf, "C3ONC300;");
15937
      strcat (out_buffer, tmp_buf);
15938
    }
15939
  if (fg[fg_lactam - 1])
15940
    {
15941
      sprintf (tmp_buf, "C3ONCZ00;");
15942
      strcat (out_buffer, tmp_buf);
15943
    }
15944
  if (fg[fg_carboxylic_acid_hydrazide - 1])
15945
    {
15946
      sprintf (tmp_buf, "C3ONN100;");
15947
      strcat (out_buffer, tmp_buf);
15948
    }
15949
  if (fg[fg_carboxylic_acid_azide - 1])
15950
    {
15951
      sprintf (tmp_buf, "C3ONN200;");
15952
      strcat (out_buffer, tmp_buf);
15953
    }
15954
  if (fg[fg_hydroxamic_acid - 1])
15955
    {
15956
      sprintf (tmp_buf, "C3ONOH00;");
15957
      strcat (out_buffer, tmp_buf);
15958
    }
15959
  if (fg[fg_carboxylic_acid_amidine - 1])
15960
    {
15961
      sprintf (tmp_buf, "C3N2H000;");
15962
      strcat (out_buffer, tmp_buf);
15963
    }
15964
  if (fg[fg_carboxylic_acid_amidrazone - 1])
15965
    {
15966
      sprintf (tmp_buf, "C3NNN100;");
15967
      strcat (out_buffer, tmp_buf);
15968
    }
15969
  if (fg[fg_nitrile - 1])
15970
    {
15971
      sprintf (tmp_buf, "C3N00000;");
15972
      strcat (out_buffer, tmp_buf);
15973
    }
15974
 
15975
  if (fg[fg_acyl_fluoride - 1])
15976
    {
15977
      sprintf (tmp_buf, "C3OXF000;");
15978
      strcat (out_buffer, tmp_buf);
15979
    }
15980
  if (fg[fg_acyl_chloride - 1])
15981
    {
15982
      sprintf (tmp_buf, "C3OXC000;");
15983
      strcat (out_buffer, tmp_buf);
15984
    }
15985
  if (fg[fg_acyl_bromide - 1])
15986
    {
15987
      sprintf (tmp_buf, "C3OXB000;");
15988
      strcat (out_buffer, tmp_buf);
15989
    }
15990
  if (fg[fg_acyl_iodide - 1])
15991
    {
15992
      sprintf (tmp_buf, "C3OXI000;");
15993
      strcat (out_buffer, tmp_buf);
15994
    }
15995
  if (fg[fg_acyl_cyanide - 1])
15996
    {
15997
      sprintf (tmp_buf, "C2OC3N00;");
15998
      strcat (out_buffer, tmp_buf);
15999
    }
16000
  if (fg[fg_imido_ester - 1])
16001
    {
16002
      sprintf (tmp_buf, "C3NOC000;");
16003
      strcat (out_buffer, tmp_buf);
16004
    }
16005
  if (fg[fg_imidoyl_halide - 1])
16006
    {
16007
      sprintf (tmp_buf, "C3NXX000;");
16008
      strcat (out_buffer, tmp_buf);
16009
    }
16010
 
16011
  if (fg[fg_thiocarboxylic_acid - 1])
16012
    {
16013
      sprintf (tmp_buf, "C3SOH000;");
16014
      strcat (out_buffer, tmp_buf);
16015
    }
16016
  if (fg[fg_thiocarboxylic_acid_ester - 1])
16017
    {
16018
      sprintf (tmp_buf, "C3SOC000;");
16019
      strcat (out_buffer, tmp_buf);
16020
    }
16021
  if (fg[fg_thiolactone - 1])
16022
    {
16023
      sprintf (tmp_buf, "C3SOCZ00;");
16024
      strcat (out_buffer, tmp_buf);
16025
    }
16026
  if (fg[fg_thiocarboxylic_acid_amide - 1])
16027
    {
16028
      sprintf (tmp_buf, "C3SNH000;");
16029
      strcat (out_buffer, tmp_buf);
16030
    }
16031
  if (fg[fg_thiolactam - 1])
16032
    {
16033
      sprintf (tmp_buf, "C3SNCZ00;");
16034
      strcat (out_buffer, tmp_buf);
16035
    }
16036
  if (fg[fg_imido_thioester - 1])
16037
    {
16038
      sprintf (tmp_buf, "C3NSC000;");
16039
      strcat (out_buffer, tmp_buf);
16040
    }
16041
  if (fg[fg_oxohetarene - 1])
16042
    {
16043
      sprintf (tmp_buf, "C3ONAZ00;");
16044
      strcat (out_buffer, tmp_buf);
16045
    }
16046
  if (fg[fg_thioxohetarene - 1])
16047
    {
16048
      sprintf (tmp_buf, "C3SNAZ00;");
16049
      strcat (out_buffer, tmp_buf);
16050
    }
16051
  if (fg[fg_iminohetarene - 1])
16052
    {
16053
      sprintf (tmp_buf, "C3NNAZ00;");
16054
      strcat (out_buffer, tmp_buf);
16055
    }
16056
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
16057
    {
16058
      sprintf (tmp_buf, "C3O30000;");
16059
      strcat (out_buffer, tmp_buf);
16060
    }
16061
  if (fg[fg_carboxylic_acid_orthoester - 1])
16062
    {
16063
      sprintf (tmp_buf, "C3O3C000;");
16064
      strcat (out_buffer, tmp_buf);
16065
    }
16066
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
16067
    {
16068
      sprintf (tmp_buf, "C3O3NC00;");
16069
      strcat (out_buffer, tmp_buf);
16070
    }
16071
  if (fg[fg_carboxylic_acid_anhydride - 1])
16072
    {
16073
      sprintf (tmp_buf, "C3O2C3O2;");
16074
      strcat (out_buffer, tmp_buf);
16075
    }
16076
 
16077
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
16078
    {
16079
      sprintf (tmp_buf, "C3ONCH10;");
16080
      strcat (out_buffer, tmp_buf);
16081
    }
16082
  if (fg[fg_carboxylic_acid_subst_imide - 1])
16083
    {
16084
      sprintf (tmp_buf, "C3ONCC10;");
16085
      strcat (out_buffer, tmp_buf);
16086
    }
16087
  if (fg[fg_co2_deriv - 1])
16088
    {
16089
      sprintf (tmp_buf, "C4000000;");
16090
      strcat (out_buffer, tmp_buf);
16091
    }
16092
  if (fg[fg_carbonic_acid_deriv - 1])
16093
    {
16094
      sprintf (tmp_buf, "C4O30000;");
16095
      strcat (out_buffer, tmp_buf);
16096
    }
16097
  if (fg[fg_carbonic_acid_monoester - 1])
16098
    {
16099
      sprintf (tmp_buf, "C4O3C100;");
16100
      strcat (out_buffer, tmp_buf);
16101
    }
16102
  if (fg[fg_carbonic_acid_diester - 1])
16103
    {
16104
      sprintf (tmp_buf, "C4O3C200;");
16105
      strcat (out_buffer, tmp_buf);
16106
    }
16107
  if (fg[fg_carbonic_acid_ester_halide - 1])
16108
    {
16109
      sprintf (tmp_buf, "C4O3CX00;");
16110
      strcat (out_buffer, tmp_buf);
16111
    }
16112
  if (fg[fg_thiocarbonic_acid_deriv - 1])
16113
    {
16114
      sprintf (tmp_buf, "C4SO0000;");
16115
      strcat (out_buffer, tmp_buf);
16116
    }
16117
  if (fg[fg_thiocarbonic_acid_monoester - 1])
16118
    {
16119
      sprintf (tmp_buf, "C4SOC100;");
16120
      strcat (out_buffer, tmp_buf);
16121
    }
16122
  if (fg[fg_thiocarbonic_acid_diester - 1])
16123
    {
16124
      sprintf (tmp_buf, "C4SOC200;");
16125
      strcat (out_buffer, tmp_buf);
16126
    }
16127
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
16128
    {
16129
      sprintf (tmp_buf, "C4SOX_00;");
16130
      strcat (out_buffer, tmp_buf);
16131
    }
16132
  if (fg[fg_carbamic_acid_deriv - 1])
16133
    {
16134
      sprintf (tmp_buf, "C4O2N000;");
16135
      strcat (out_buffer, tmp_buf);
16136
    }
16137
  if (fg[fg_carbamic_acid - 1])
16138
    {
16139
      sprintf (tmp_buf, "C4O2NH00;");
16140
      strcat (out_buffer, tmp_buf);
16141
    }
16142
  if (fg[fg_carbamic_acid_ester - 1])
16143
    {
16144
      sprintf (tmp_buf, "C4O2NC00;");
16145
      strcat (out_buffer, tmp_buf);
16146
    }
16147
  if (fg[fg_carbamic_acid_halide - 1])
16148
    {
16149
      sprintf (tmp_buf, "C4O2NX00;");
16150
      strcat (out_buffer, tmp_buf);
16151
    }
16152
  if (fg[fg_thiocarbamic_acid_deriv - 1])
16153
    {
16154
      sprintf (tmp_buf, "C4SN0000;");
16155
      strcat (out_buffer, tmp_buf);
16156
    }
16157
  if (fg[fg_thiocarbamic_acid - 1])
16158
    {
16159
      sprintf (tmp_buf, "C4SNOH00;");
16160
      strcat (out_buffer, tmp_buf);
16161
    }
16162
  if (fg[fg_thiocarbamic_acid_ester - 1])
16163
    {
16164
      sprintf (tmp_buf, "C4SNOC00;");
16165
      strcat (out_buffer, tmp_buf);
16166
    }
16167
  if (fg[fg_thiocarbamic_acid_halide - 1])
16168
    {
16169
      sprintf (tmp_buf, "C4SNXX00;");
16170
      strcat (out_buffer, tmp_buf);
16171
    }
16172
  if (fg[fg_urea - 1])
16173
    {
16174
      sprintf (tmp_buf, "C4O1N200;");
16175
      strcat (out_buffer, tmp_buf);
16176
    }
16177
  if (fg[fg_isourea - 1])
16178
    {
16179
      sprintf (tmp_buf, "C4N2O100;");
16180
      strcat (out_buffer, tmp_buf);
16181
    }
16182
  if (fg[fg_thiourea - 1])
16183
    {
16184
      sprintf (tmp_buf, "C4S1N200;");
16185
      strcat (out_buffer, tmp_buf);
16186
    }
16187
  if (fg[fg_isothiourea - 1])
16188
    {
16189
      sprintf (tmp_buf, "C4N2S100;");
16190
      strcat (out_buffer, tmp_buf);
16191
    }
16192
  if (fg[fg_guanidine - 1])
16193
    {
16194
      sprintf (tmp_buf, "C4N30000;");
16195
      strcat (out_buffer, tmp_buf);
16196
    }
16197
  if (fg[fg_semicarbazide - 1])
16198
    {
16199
      sprintf (tmp_buf, "C4ON2N00;");
16200
      strcat (out_buffer, tmp_buf);
16201
    }
16202
  if (fg[fg_thiosemicarbazide - 1])
16203
    {
16204
      sprintf (tmp_buf, "C4SN2N00;");
16205
      strcat (out_buffer, tmp_buf);
16206
    }
16207
  if (fg[fg_azide - 1])
16208
    {
16209
      sprintf (tmp_buf, "N4N20000;");
16210
      strcat (out_buffer, tmp_buf);
16211
    }
16212
  if (fg[fg_azo_compound - 1])
16213
    {
16214
      sprintf (tmp_buf, "N2N10000;");
16215
      strcat (out_buffer, tmp_buf);
16216
    }
16217
  if (fg[fg_diazonium_salt - 1])
16218
    {
16219
      sprintf (tmp_buf, "N3N100T2;");
16220
      strcat (out_buffer, tmp_buf);
16221
    }
16222
  if (fg[fg_isonitrile - 1])
16223
    {
16224
      sprintf (tmp_buf, "N3C10000;");
16225
      strcat (out_buffer, tmp_buf);
16226
    }
16227
  if (fg[fg_cyanate - 1])
16228
    {
16229
      sprintf (tmp_buf, "C4NO1000;");
16230
      strcat (out_buffer, tmp_buf);
16231
    }
16232
  if (fg[fg_isocyanate - 1])
16233
    {
16234
      sprintf (tmp_buf, "C4NO2000;");
16235
      strcat (out_buffer, tmp_buf);
16236
    }
16237
  if (fg[fg_thiocyanate - 1])
16238
    {
16239
      sprintf (tmp_buf, "C4NS1000;");
16240
      strcat (out_buffer, tmp_buf);
16241
    }
16242
  if (fg[fg_isothiocyanate - 1])
16243
    {
16244
      sprintf (tmp_buf, "C4NS2000;");
16245
      strcat (out_buffer, tmp_buf);
16246
    }
16247
  if (fg[fg_carbodiimide - 1])
16248
    {
16249
      sprintf (tmp_buf, "C4N20000;");
16250
      strcat (out_buffer, tmp_buf);
16251
    }
16252
  if (fg[fg_nitroso_compound - 1])
16253
    {
16254
      sprintf (tmp_buf, "N2O10000;");
16255
      strcat (out_buffer, tmp_buf);
16256
    }
16257
  if (fg[fg_nitro_compound - 1])
16258
    {
16259
      sprintf (tmp_buf, "N4O20000;");
16260
      strcat (out_buffer, tmp_buf);
16261
    }
16262
  if (fg[fg_nitrite - 1])
16263
    {
16264
      sprintf (tmp_buf, "N3O20000;");
16265
      strcat (out_buffer, tmp_buf);
16266
    }
16267
  if (fg[fg_nitrate - 1])
16268
    {
16269
      sprintf (tmp_buf, "N4O30000;");
16270
      strcat (out_buffer, tmp_buf);
16271
    }
16272
  if (fg[fg_sulfuric_acid_deriv - 1])
16273
    {
16274
      sprintf (tmp_buf, "S6O00000;");
16275
      strcat (out_buffer, tmp_buf);
16276
    }
16277
  if (fg[fg_sulfuric_acid - 1])
16278
    {
16279
      sprintf (tmp_buf, "S6O4H000;");
16280
      strcat (out_buffer, tmp_buf);
16281
    }
16282
  if (fg[fg_sulfuric_acid_monoester - 1])
16283
    {
16284
      sprintf (tmp_buf, "S6O4HC00;");
16285
      strcat (out_buffer, tmp_buf);
16286
    }
16287
  if (fg[fg_sulfuric_acid_diester - 1])
16288
    {
16289
      sprintf (tmp_buf, "S6O4CC00;");
16290
      strcat (out_buffer, tmp_buf);
16291
    }
16292
  if (fg[fg_sulfuric_acid_amide_ester - 1])
16293
    {
16294
      sprintf (tmp_buf, "S6O3NC00;");
16295
      strcat (out_buffer, tmp_buf);
16296
    }
16297
  if (fg[fg_sulfuric_acid_amide - 1])
16298
    {
16299
      sprintf (tmp_buf, "S6O3N100;");
16300
      strcat (out_buffer, tmp_buf);
16301
    }
16302
  if (fg[fg_sulfuric_acid_diamide - 1])
16303
    {
16304
      sprintf (tmp_buf, "S6O2N200;");
16305
      strcat (out_buffer, tmp_buf);
16306
    }
16307
  if (fg[fg_sulfuryl_halide - 1])
16308
    {
16309
      sprintf (tmp_buf, "S6O3XX00;");
16310
      strcat (out_buffer, tmp_buf);
16311
    }
16312
  if (fg[fg_sulfonic_acid_deriv - 1])
16313
    {
16314
      sprintf (tmp_buf, "S5O00000;");
16315
      strcat (out_buffer, tmp_buf);
16316
    }
16317
  if (fg[fg_sulfonic_acid - 1])
16318
    {
16319
      sprintf (tmp_buf, "S5O3H000;");
16320
      strcat (out_buffer, tmp_buf);
16321
    }
16322
  if (fg[fg_sulfonic_acid_ester - 1])
16323
    {
16324
      sprintf (tmp_buf, "S5O3C000;");
16325
      strcat (out_buffer, tmp_buf);
16326
    }
16327
  if (fg[fg_sulfonamide - 1])
16328
    {
16329
      sprintf (tmp_buf, "S5O2N000;");
16330
      strcat (out_buffer, tmp_buf);
16331
    }
16332
  if (fg[fg_sulfonyl_halide - 1])
16333
    {
16334
      sprintf (tmp_buf, "S5O2XX00;");
16335
      strcat (out_buffer, tmp_buf);
16336
    }
16337
  if (fg[fg_sulfone - 1])
16338
    {
16339
      sprintf (tmp_buf, "S4O20000;");
16340
      strcat (out_buffer, tmp_buf);
16341
    }
16342
  if (fg[fg_sulfoxide - 1])
16343
    {
16344
      sprintf (tmp_buf, "S2O10000;");
16345
      strcat (out_buffer, tmp_buf);
16346
    }
16347
  if (fg[fg_sulfinic_acid_deriv - 1])
16348
    {
16349
      sprintf (tmp_buf, "S3O00000;");
16350
      strcat (out_buffer, tmp_buf);
16351
    }
16352
  if (fg[fg_sulfinic_acid - 1])
16353
    {
16354
      sprintf (tmp_buf, "S3O2H000;");
16355
      strcat (out_buffer, tmp_buf);
16356
    }
16357
  if (fg[fg_sulfinic_acid_ester - 1])
16358
    {
16359
      sprintf (tmp_buf, "S3O2C000;");
16360
      strcat (out_buffer, tmp_buf);
16361
    }
16362
  if (fg[fg_sulfinic_acid_halide - 1])
16363
    {
16364
      sprintf (tmp_buf, "S3O1XX00;");
16365
      strcat (out_buffer, tmp_buf);
16366
    }
16367
  if (fg[fg_sulfinic_acid_amide - 1])
16368
    {
16369
      sprintf (tmp_buf, "S3O1N000;");
16370
      strcat (out_buffer, tmp_buf);
16371
    }
16372
  if (fg[fg_sulfenic_acid_deriv - 1])
16373
    {
16374
      sprintf (tmp_buf, "S1O00000;");
16375
      strcat (out_buffer, tmp_buf);
16376
    }
16377
  if (fg[fg_sulfenic_acid - 1])
16378
    {
16379
      sprintf (tmp_buf, "S1O1H000;");
16380
      strcat (out_buffer, tmp_buf);
16381
    }
16382
  if (fg[fg_sulfenic_acid_ester - 1])
16383
    {
16384
      sprintf (tmp_buf, "S1O1C000;");
16385
      strcat (out_buffer, tmp_buf);
16386
    }
16387
  if (fg[fg_sulfenic_acid_halide - 1])
16388
    {
16389
      sprintf (tmp_buf, "S1O0XX00;");
16390
      strcat (out_buffer, tmp_buf);
16391
    }
16392
  if (fg[fg_sulfenic_acid_amide - 1])
16393
    {
16394
      sprintf (tmp_buf, "S1O0N100;");
16395
      strcat (out_buffer, tmp_buf);
16396
    }
16397
 
16398
  if (fg[fg_alkylthiol - 1])
16399
    {
16400
      sprintf (tmp_buf, "S1H1C000;");
16401
      strcat (out_buffer, tmp_buf);
16402
    }
16403
  if (fg[fg_arylthiol - 1])
16404
    {
16405
      sprintf (tmp_buf, "S1H1A000;");
16406
      strcat (out_buffer, tmp_buf);
16407
    }
16408
  if (fg[fg_phosphoric_acid_deriv - 1])
16409
    {
16410
      sprintf (tmp_buf, "P5O0H000;");
16411
      strcat (out_buffer, tmp_buf);
16412
    }
16413
  if (fg[fg_phosphoric_acid - 1])
16414
    {
16415
      sprintf (tmp_buf, "P5O4H200;");
16416
      strcat (out_buffer, tmp_buf);
16417
    }
16418
  if (fg[fg_phosphoric_acid_ester - 1])
16419
    {
16420
      sprintf (tmp_buf, "P5O4HC00;");
16421
      strcat (out_buffer, tmp_buf);
16422
    }
16423
  if (fg[fg_phosphoric_acid_halide - 1])
16424
    {
16425
      sprintf (tmp_buf, "P5O3HX00;");
16426
      strcat (out_buffer, tmp_buf);
16427
    }
16428
  if (fg[fg_phosphoric_acid_amide - 1])
16429
    {
16430
      sprintf (tmp_buf, "P5O3HN00;");
16431
      strcat (out_buffer, tmp_buf);
16432
    }
16433
  if (fg[fg_thiophosphoric_acid_deriv - 1])
16434
    {
16435
      sprintf (tmp_buf, "P5O0S000;");
16436
      strcat (out_buffer, tmp_buf);
16437
    }
16438
  if (fg[fg_thiophosphoric_acid - 1])
16439
    {
16440
      sprintf (tmp_buf, "P5O3SH00;");
16441
      strcat (out_buffer, tmp_buf);
16442
    }
16443
  if (fg[fg_thiophosphoric_acid_ester - 1])
16444
    {
16445
      sprintf (tmp_buf, "P5O3SC00;");
16446
      strcat (out_buffer, tmp_buf);
16447
    }
16448
  if (fg[fg_thiophosphoric_acid_halide - 1])
16449
    {
16450
      sprintf (tmp_buf, "P5O2SX00;");
16451
      strcat (out_buffer, tmp_buf);
16452
    }
16453
  if (fg[fg_thiophosphoric_acid_amide - 1])
16454
    {
16455
      sprintf (tmp_buf, "P5O2SN00;");
16456
      strcat (out_buffer, tmp_buf);
16457
    }
16458
  if (fg[fg_phosphonic_acid_deriv - 1])
16459
    {
16460
      sprintf (tmp_buf, "P4O30000;");
16461
      strcat (out_buffer, tmp_buf);
16462
    }
16463
  if (fg[fg_phosphonic_acid - 1])
16464
    {
16465
      sprintf (tmp_buf, "P4O3H000;");
16466
      strcat (out_buffer, tmp_buf);
16467
    }
16468
  if (fg[fg_phosphonic_acid_ester - 1])
16469
    {
16470
      sprintf (tmp_buf, "P4O3C000;");
16471
      strcat (out_buffer, tmp_buf);
16472
    }
16473
  if (fg[fg_phosphine - 1])
16474
    {
16475
      sprintf (tmp_buf, "P3000000;");
16476
      strcat (out_buffer, tmp_buf);
16477
    }
16478
  if (fg[fg_phosphinoxide - 1])
16479
    {
16480
      sprintf (tmp_buf, "P2O00000;");
16481
      strcat (out_buffer, tmp_buf);
16482
    }
16483
  if (fg[fg_boronic_acid_deriv - 1])
16484
    {
16485
      sprintf (tmp_buf, "B2O20000;");
16486
      strcat (out_buffer, tmp_buf);
16487
    }
16488
  if (fg[fg_boronic_acid - 1])
16489
    {
16490
      sprintf (tmp_buf, "B2O2H000;");
16491
      strcat (out_buffer, tmp_buf);
16492
    }
16493
  if (fg[fg_boronic_acid_ester - 1])
16494
    {
16495
      sprintf (tmp_buf, "B2O2C000;");
16496
      strcat (out_buffer, tmp_buf);
16497
    }
16498
  if (fg[fg_alkene - 1])
16499
    {
16500
      sprintf (tmp_buf, "000C2C00;");
16501
      strcat (out_buffer, tmp_buf);
16502
    }
16503
  if (fg[fg_alkyne - 1])
16504
    {
16505
      sprintf (tmp_buf, "000C3C00;");
16506
      strcat (out_buffer, tmp_buf);
16507
    }
16508
  if (fg[fg_aromatic - 1])
16509
    {
16510
      sprintf (tmp_buf, "0000A000;");
16511
      strcat (out_buffer, tmp_buf);
16512
    }
16513
  if (fg[fg_heterocycle - 1])
16514
    {
16515
      sprintf (tmp_buf, "0000CZ00;");
16516
      strcat (out_buffer, tmp_buf);
16517
    }
16518
  if (fg[fg_alpha_aminoacid - 1])
16519
    {
16520
      sprintf (tmp_buf, "C3O2HN1C;");
16521
      strcat (out_buffer, tmp_buf);
16522
    }
16523
  if (fg[fg_alpha_hydroxyacid - 1])
16524
    {
16525
      sprintf (tmp_buf, "C3O2HO1H;");
16526
      strcat (out_buffer, tmp_buf);
16527
    }
16528
}
16529
 
16530
/*static void mm_elab_molstat(void)
16531
{
16532
                count_neighbors();
16533
//      init_molstat(&molstat);
16534
        if (!found_arominfo) {
16535
    chk_ringbonds();
16536
    if (ringsearch_mode == rs_ssr)
16537
      remove_redundant_rings();
16538
    if (n_rings == max_rings) {
16539
      if (opt_verbose)
16540
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
16541
      ringsearch_mode = rs_ssr;
16542
      clear_rings();
16543
      max_vringsize = 10;
16544
      chk_ringbonds();
16545
      remove_redundant_rings();
16546
    }
16547
 
16548
    update_ringcount();
16549
    update_atypes();
16550
    update_Htotal();
16551
    chk_arom();
16552
 
16553
    if (ringsearch_mode == rs_ssr) {
16554
      do {
16555
        prev_n_ar = count_aromatic_rings();
16556
        chk_arom();
16557
        n_ar = count_aromatic_rings();
16558
      } while (prev_n_ar - n_ar != 0);
16559
    }
16560
        } else {
16561
 update_atypes();
16562
    update_Htotal();  
16563
 
16564
        }
16565
 
16566
 // get_molstat();
16567
}*/
16568
 
16569
DLLEXPORT void
16570
cm_molstat_X (char *buf)
16571
{
16572
  init_molstat (&molstat);
16573
//mm_elab_molstat();
16574
  get_molstat ();
16575
  write_molstat_X_dll (buf);
16576
}
16577
 
16578
DLLEXPORT void
16579
cm_molstat (char *buf)
16580
{
16581
  init_molstat (&molstat);
16582
//mm_elab_molstat();
16583
  get_molstat ();
16584
  write_molstat_dll (buf, 0);
16585
}
16586
 
16587
DLLEXPORT void
16588
cm_molstat_sql_exact (char *buf)
16589
{
16590
  init_molstat (&molstat);
16591
//mm_elab_molstat();
16592
  get_molstat ();
16593
  write_molstat_dll (buf, 1);
16594
}
16595
 
16596
DLLEXPORT void
16597
cm_molstat_sql_substruct (char *buf)
16598
{
16599
  init_molstat (&molstat);
16600
//mm_elab_molstat();
16601
  get_molstat ();
16602
  write_molstat_dll (buf, 2);
16603
}
16604
 
16605
DLLEXPORT void
16606
cm_fg_codes (char *buf)
16607
{
16608
//mm_elab_molstat();
16609
  chk_functionalgroups ();
16610
  write_fg_code_dll (buf);
16611
}
16612
 
16613
static void
16614
write_MDLmolfile_dll (char *out_buffer)
16615
{
16616
  int i;
16617
  char tmpstr[256];
16618
  char wline[256];
16619
  int a_chg;
16620
  int a_iso;
16621
  int a_rad;
16622
  char tmflabel[256];           /* v0.3m */
16623
  char STR1[256], STR7[256];
16624
  int FORLIM;
16625
  *out_buffer = '\0';
16626
  *tmpstr = '\0';
16627
  *wline = '\0';
16628
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
16629
  while (strlen (tmflabel) < 2) /* v0.3m */
16630
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
16631
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
16632
  if (strlen (molname) > 80)
16633
    sprintf (molname, "%.80s", strcpy (STR1, molname));
16634
  strncat (out_buffer, molname, 80);
16635
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
16636
  if (ringsearch_mode == rs_sar)        /* v0.3m */
16637
    strcat (wline, ":r0");
16638
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
16639
    strcat (wline, ":r1");
16640
  if (opt_metalrings)
16641
    strcat (wline, ":m1");
16642
  else
16643
    strcat (wline, ":m0");
16644
  /* v0.3m */
16645
  sprintf (tmpstr, "\n%s\n", molcomment);
16646
  strcat (wline, tmpstr);
16647
  sprintf (tmpstr, "%d", n_atoms);
16648
  lblank (3L, tmpstr);
16649
  strcat (wline, tmpstr);
16650
  /* first 3 digits: number of atoms */
16651
  sprintf (tmpstr, "%d", n_bonds);
16652
  lblank (3L, tmpstr);
16653
  strcat (wline, tmpstr);
16654
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
16655
  strcpy (tmpstr, "  0");
16656
  strcat (wline, tmpstr);
16657
  /* next 3 digits: number of atom lists (not used by us) */
16658
/* p2c: checkmol.pas, line 2388:
16659
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
16660
#ifdef REDUCED_SAR
16661
  sprintf (tmpstr, "%d", n_countablerings);
16662
  /* v0.3n; changed n_rings into n_countablerings */
16663
#else
16664
  sprintf (tmpstr, "%d", n_rings);
16665
#endif
16666
  lblank (3L, tmpstr);
16667
  strcat (wline, tmpstr);
16668
  /* officially "obsolete", we use it for the number of rings */
16669
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
16670
  if (chir_flag)
16671
    strcat (wline, "1");
16672
  else
16673
    strcat (wline, "0");
16674
  /* v0.3n */
16675
  strcat (wline, "               999 V2000\n");
16676
  /* v0.3n (adjust string length) */
16677
  strcat (out_buffer, wline);
16678
  FORLIM = n_atoms;
16679
  for (i = 0; i < FORLIM; i++)
16680
    {
16681
      *wline = '\0';
16682
      *tmpstr = '\0';
16683
      sprintf (tmpstr, "%1.4f", atom[i].x);
16684
      lblank (10L, tmpstr);
16685
      strcat (wline, tmpstr);
16686
      sprintf (tmpstr, "%1.4f", atom[i].y);
16687
      lblank (10L, tmpstr);
16688
      strcat (wline, tmpstr);
16689
      sprintf (tmpstr, "%1.4f", atom[i].z);
16690
      lblank (10L, tmpstr);
16691
      strcat (wline, tmpstr);
16692
      strcpy (tmpstr, atom[i].element);
16693
      /* tmpstr := lowercase(tmpstr); REPLACE!!! */
16694
      //tmpstr[0] = toupper (tmpstr[0]);
16695
      all_lowercase (tmpstr);
16696
      tmpstr[0] = toupper (tmpstr[0]);
16697
      /*wline := wline + ' '+atom^[i].element+' '; */
16698
      sprintf (wline + strlen (wline), " %s ", tmpstr);
16699
      strcat (wline, " 0");     /* mass difference (isotopes) */
16700
      /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
16701
      if (atom[i].arom)
16702
        strcpy (tmpstr, " 00");
16703
      else
16704
        strcpy (tmpstr, "  0");
16705
      strcat (wline, tmpstr);
16706
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
16707
      strcat (out_buffer, wline);
16708
    }
16709
  FORLIM = n_bonds;
16710
  for (i = 0; i < FORLIM; i++)
16711
    {
16712
      *wline = '\0';
16713
      *tmpstr = '\0';
16714
      sprintf (tmpstr, "%d", bond[i].a1);
16715
      lblank (3L, tmpstr);
16716
      strcat (wline, tmpstr);
16717
      sprintf (tmpstr, "%d", bond[i].a2);
16718
      lblank (3L, tmpstr);
16719
      strcat (wline, tmpstr);
16720
      if (bond[i].btype == 'S')
16721
        strcpy (tmpstr, "  1");
16722
      if (bond[i].btype == 'D')
16723
        strcpy (tmpstr, "  2");
16724
      if (bond[i].btype == 'T')
16725
        strcpy (tmpstr, "  3");
16726
      if (bond[i].btype == 'A')
16727
        strcpy (tmpstr, "  4");
16728
      if (bond[i].btype == 'l')
16729
        strcpy (tmpstr, "  5");
16730
      if (bond[i].btype == 's')
16731
        strcpy (tmpstr, "  6");
16732
      if (bond[i].btype == 'd')
16733
        strcpy (tmpstr, "  7");
16734
      if (bond[i].btype == 'a')
16735
        strcpy (tmpstr, "  8");
16736
      /* now encode our own aromaticity information */
16737
      if (bond[i].arom)
16738
        tmpstr[1] = '0';
16739
      strcat (wline, tmpstr);   /* next, encode bond stereo property (v0.3f) */
16740
      /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
16741
      /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
16742
      /*    wline := wline + '  0'; */
16743
      /* restore original value from MDL molfile (v0.3n) */
16744
      /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
16745
      *tmpstr = '\0';
16746
      sprintf (tmpstr, "%i", bond[i].mdl_stereo);
16747
      strcat (wline, "  ");
16748
      strcat (wline, tmpstr);
16749
      *tmpstr = '\0';
16750
      /* now encode the ring_count of this bond (using a field which officially is "not used") */
16751
      /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
16752
      sprintf (tmpstr, "%i", bond[i].ring_count);
16753
      while (strlen (tmpstr) < 3)
16754
        sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
16755
      sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
16756
      strcat (out_buffer, wline);
16757
    }
16758
  FORLIM = n_atoms;
16759
  for (i = 1; i <= FORLIM; i++)
16760
    {
16761
      a_chg = atom[i - 1].formal_charge;
16762
      if (a_chg != 0)
16763
        {
16764
          strcpy (wline, "M  CHG  1 ");
16765
          sprintf (tmpstr, "%d", i);
16766
          lblank (3L, tmpstr);
16767
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16768
          sprintf (tmpstr, "%d", a_chg);
16769
          lblank (3L, tmpstr);
16770
          strcat (wline, tmpstr);
16771
          strcat (out_buffer, wline);
16772
          strcat (out_buffer, "\n");
16773
        }
16774
    }
16775
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
16776
    {
16777
      a_iso = atom[i - 1].nucleon_number;
16778
      if (a_iso != 0)
16779
        {
16780
          strcpy (wline, "M  ISO  1 ");
16781
          sprintf (tmpstr, "%d", i);
16782
          lblank (3L, tmpstr);
16783
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16784
          sprintf (tmpstr, "%d", a_iso);
16785
          lblank (3L, tmpstr);
16786
          strcat (wline, tmpstr);
16787
          strcat (out_buffer, wline);
16788
          strcat (out_buffer, "\n");
16789
        }
16790
    }
16791
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
16792
    {
16793
      a_rad = atom[i - 1].radical_type;
16794
      if (a_rad != 0)
16795
        {
16796
          strcpy (wline, "M  RAD  1 ");
16797
          sprintf (tmpstr, "%d", i);
16798
          lblank (3L, tmpstr);
16799
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16800
          sprintf (tmpstr, "%d", a_rad);
16801
          lblank (3L, tmpstr);
16802
          strcat (wline, tmpstr);
16803
          strcat (out_buffer, wline);
16804
          strcat (out_buffer, "\n");
16805
        }
16806
    }
16807
  strcat (out_buffer, "M  END\n");
16808
}
16809
 
16810
DLLEXPORT void
16811
cm_tweak_molfile (char *buf)
16812
{
16813
//chk_functionalgroups();
16814
  write_MDLmolfile_dll (buf);
16815
}
16816
#endif