Subversion Repositories wimsdev

Rev

Rev 6787 | Rev 6789 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6785 bpr 1
/*
2
   Modified to run w/o p2c libraries
3
   2007 Ernst-Georg Schmid
4
   Modified to run as shared library
5
   2007 Ernst-Georg Schmid
6
   pgchem@tuschehund.de
7
 
8
   compile with gcc without optimizations (except -march= -mcpu=) or it gets SLOWER!
9
 
10
   THIS VERSION HAS extended_molstat SWITCHED ON BY DEFAULT!
11
 
12
   This file is part of the xchem::tigress project.
13
 
14
   --- DUAL LICENSING ---
15
 
16
   If checkmol.c aka. pgchem::barsoi is compiled as a library, it is released under the terms of the
17
   lesser GNU General Public License. For the executable, the original GPL
18
   licensing applies!
19
 
20
   This program is free software; you can redistribute it and/or modify
21
   it under the terms of the lesser GNU General Public License as published by
22
   the Free Software Foundation version 2.1 of the License.
23
 
24
   This program is distributed in the hope that it will be useful,
25
   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
   lesser GNU General Public License for more details.
28
 
29
   --- DUAL LICENSING ---
30
 
31
   ORIGINAL HEADER:
32
 
33
checkmol/matchmol
34
Norbert Haider, University of Vienna, 2003-2007
35
norbert.haider@univie.ac.at
36
 
37
This software is published under the terms of the GNU General Public
38
License (GPL, see below). For a detailed description of this license,
39
see http://www.gnu.org/copyleft/gpl.html
40
 
41
If invoked as "checkmol", this program reads 2D and 3D molecular structure
42
files in various formats (Tripos Alchemy "mol", Tripos SYBYL "mol2", MDL "mol")
43
and describes the molecule either by its functional groups or by a set of
44
descriptors useful for database pre-screening (number of rings, sp2-hybridized
45
carbons, aromatic bonds, etc.; see definition of molstat_rec).
46
 
47
If invoked as "matchmol", the program reads two individual 2D or 3D molecular
48
structure files in various formats (see above) and checks if the first molecule
49
(the "needle") is a substructure of the second one (the "haystack").
50
"Haystack" can also be a MDL SD-file (containing multiple MOL files);
51
if invoked with "-" as file argument, both "needle" and "haystack" are
52
read as an SD-file from standard input, assuming the first entry in
53
the SDF to be the "needle"; output: entry number + ":F" (false) or ":T" (true)
54
 
55
 
56
Compile with fpc (Free Pascal, see http://www.freepascal.org), using
57
the -Sd or -S2 option (Delphi mode; IMPORTANT!)
58
 
59
example for compilation (with optimization) and installation:
60
 
61
fpc checkmol.pas -S2 -Xs -OG -Or -O2u -Op1
62
 
63
as "root", do the following:
64
 
65
cp checkmol /usr/local/bin
66
cd /usr/local/bin
67
ln checkmol matchmol
68
 
69
 
70
Version history
71
 
72
v0.1   extends "chkmol" utility (N. Haider, 2002), adds matching functionality;
73
 
74
v0.1a  minor bugfixes:
75
       stop ring search when max_rings is reached (function is_ringpath);
76
       fixed upper/lowercase of element symbol in MDL molfile output;
77
       added debug output for checkmol (-D option)
78
 
79
v0.2   added functionality to switch ring search from SAR (set of all rings) to
80
       SSR (set of small rings; see below) if number of rings exceeds max_rings
81
       (1024), e.g. with Buckminster-fullerenes (thanks to E.-G. Schmid for a hint);
82
       added -r command-line option to force ring search into SSR mode;
83
       as SSR, we regard the set of all rings with max. 10 ring members, and in
84
       which no ring is completely contained in another one
85
 
86
v0.2a  fixed a bug in function is_ringpath which could cause SAR ring search to
87
       overlook a few rings (e.g., the six 8-membered rings in cubane)
88
 
89
v0.2b  fixed unequal treatment of needle and haystack structures with respect
90
       to aromaticity check (trusting input file vs. full check)
91
 
92
v0.2c  modified the changes of v0.2b so that they affect only "matchmol" mode;
93
       added quick_match function
94
 
95
v0.2d  refined function bondtypes_OK so that it does not accept C=O fragments
96
       (and C=S, C=Se, C=Te) as equivalent to aromatic C-O (C-S, C-Se, C-Te);
97
       fixed function find_ndl_ref_atom to use only heavy atoms as "needle"
98
       reference atoms for atom-to-atom match; update function quick_match to
99
       handle queries with only one heavy atom (thanks to A. Barozza for a hint)
100
 
101
v0.2e  modified procedure get_molstat: adds 1 formal double bond for each aromatic
102
       ring to the "fingerprint" in order to allow an isolated double bond in the
103
       needle to be matched as a fragment of an aromatic ring
104
       ATTENTION: "fingerprints" (molecular statistics) generated with a previous
105
       version of checkmol(-x and -X option) must be updated for structure/
106
       substructure database searching with matchmaol.
107
 
108
v0.2f  modified procedures chk_ccx, chk_xccx, write_fg_text, write_fg_text_de,
109
       write_fg_code in order to report halogen derivatives other than alkyl halides,
110
       aryl halides and acyl halides (e.g., vinyl halides) and C=C compounds other
111
       than "true" alkenes, enols, enediols, enamines, etc. (e.g. vinyl halides);
112
       added "strict mode" (option -s) for matching: this uses a more thorough
113
       comparison of atom types and bond types (new functions atomtypes_OK_strict,
114
       bondtypes_OK_strict, several minor modifications in other subroutines).
115
 
116
v0.2g  changed procedure readinputfile (+ minor changes in main routine) in
117
       order to read very large SD input files without "not enough memory" error
118
       (the previous version attempted to read the entire SD file into a buffer,
119
       the new version reads only one molecule at once);
120
       fixed a minor bug in read_mol2file which led to undefined bond types;
121
       added definition of "debug" option as a compiler flag.
122
 
123
v0.2h  fixed a small bug which caused program hangs with (e.g.) some metal
124
       complexes: this was solved just by increasing the number of possible
125
       neighbor atoms from 8 to 16 (now defined in the constant max_neighbors).
126
 
127
v0.2i  introduced some more plausibility checking (number of directly connected
128
       atoms), result stored in variable mol_OK (set in count_neighbors);
129
       completely rewrote function matrix_OK which now can handle up to
130
       max_neighbors substituents per atom (previous versions were limited to
131
       4 substituents; larger numbers are required e.g. for ferrocenes and
132
       similar compounds).
133
 
134
v0.2j  new function raw_hetbond_count: ignores bond order (in contrast to function
135
       hetbond_count), this is better suitable for molecular statistics.
136
       ATTENTION: previously generated "fingerprints" in databases must be updated!
137
       improved recognition of non-conformant SD files (with missing "M  END" line)
138
 
139
v0.2k  changed quick_match routine to compare atom types only by element in
140
       order to avoid (rare) cases of non-matching identical input files;
141
       slightly changed error message for non-existant input files
142
 
143
v0.3   changed function update_Htotal in order to distinguish between 3-valent
144
       and 5-valent phosphorus (thanks to H. Feldman for this suggestion);
145
       added a table (array ringprop) to store ring sizes and aromaticity for
146
       faster lookup; changed aromaticity detection (chk_arom) to be fully
147
       independent of Kekule structures in condensed ring systems; changed add_ring
148
       to store new rings in ascending order (with respect to ring size): this
149
       will cause the aromaticity detection to start with smaller rings;
150
       added additional calls to chk_arom when in SSR ring search mode (to ensure
151
       that all aromatic rings are found); speeded up function is_newring;
152
       added option "-M": this restores the behavior of previous versions,
153
       i.e. metal atoms will be accepted as ring members (which costs a lot
154
       of performance for coordinate compounds like ferrocenes but gives
155
       only little useful information); when used in databases: use the _same_
156
       mode ("-M" or not) _both_ for checkmol (creation of fingerprints) and matchmol;
157
       fixed ugly linebreaks in show_usage;
158
 
159
v0.3a  fixed a bug in read_charges (which was introduced in the v0.3 code cleanup)
160
 
161
v0.3b  fixed recognition of ketenes, CO2, CS2, CSO, phosphines, boronic esters
162
 
163
v0.3c  fixed recognition of hydrazines, hydroxylamines, thiocarboxylic acids,
164
       orthocarboxylic acids; slightly changed textual output for a few functional
165
       groups
166
 
167
v0.3d  added bond topology feature ("any", "ring", "chain", as defined by MDL specs,
168
       plus "always_any", "excess-ringcount", "exact-ringcount") to bond properties
169
       and implemented its use for substructure searches, either as specified in the
170
       query MDL molfile or by using "strict" mode; added ring_count property to
171
       "bonds" section of Checkmol-tweaked molfiles (using an unused field in the MDL
172
       molfile specs);
173
       added option for E/Z isomer search, either globally (-g option) or per
174
       double bond: bstereo_xyz property, encoded either by a leading "0" in the
175
       bond block of a checkmol-tweaked molfile or by using the "stereo care" flag
176
       as defined in the MDL file specs (both atoms of a double bond must carry
177
       this flag)
178
 
179
v0.3e  fixed wrong position of "stereo care" flag expected in input molfile;
180
 
181
v0.3f  added option for enantiospecific search (R/S isomer search); this can be
182
       turned on either globally (-G option or using the "chiral" flag in the
183
       "counts line" of the query MDL molfile) or per atom (using - or abusing -
184
       the "stereo care" flag); enantiomers are compared using the 3D coordinates
185
       of the substituents at a chiral center, so we do not have to rely on the
186
       presence of correct "up" and "down" bond types in the candidate structures;
187
       nevertheless, "pseudo-3D" structures (i.e. flat 2D structures with "up"
188
       and "down" bond notation) can be also used, even in mixed mode both as
189
       query structure and candidate structure; added support for "up" and "down"
190
       bond notation in MDL molfile output (if -m option is used and these bond
191
       types were present in the input file); refined function find_ndl_ref_atom;
192
       fixed Alchemy atom type misinterpretation (upper/lower case mismatch);
193
 
194
v0.3g  minor fixes: recognition of sp2 nitrogen in N=N structures (function
195
       update_atypes); extended E/Z geometry check to C=N and N=N bonds; accelerated
196
       exact search by initial comparison of C,O,N counts; added meaningful error
197
       message for input structures with 0 (zero) atoms;
198
 
199
v0.3h  added a match matrix clean-up step to function is_matching in order to
200
       remove "impossible" multiple matches prior to chirality check; added
201
       function ndl_maybe_chiral as a plausibility check; added support for other
202
       atoms than carbon as chiral centers; changed function is_cis from a
203
       distance-based cis/trans check into a torsion-based check;
204
 
205
v0.3i  minor fixes in functions max_neighbors and chk_ammon;
206
       revert ringsearch_mode to its original value for each new molecule
207
       (main routine)
208
 
209
v0.3j  various improvements in checkmol: added alkenyl (vinyl) and alkynyl
210
       residues as possible substituents for amides, esters, ethers, etc.;
211
       extended recognition of orthocarboxylic acid derivatives; refined
212
       recognition of oxohetarenes and iminohetareenes, ureas, nitroso
213
       compounds; fixed reading of "old-style" charges from MDL files;
214
       refined aromaticity check; fixed a bug in procedure chk_arom and
215
       renamed function is_exocyclic_methylene_C into
216
       find_exocyclic_methylene_C; added assignment of pointers to "nil"
217
       after calling "freemem" in procedure zap_molecule and zap_needle;
218
       matchmol: refined selection of needle reference atom; added "strict
219
       chirality check" mode (if -x -s and -G options are used): returns
220
       "false" if a chiral or pseudochiral atom is matched against its
221
       counterpart with undefined or "flat" geometry; added an alternative
222
       selection mechanism for the needle reference atom, based on the
223
       Morgan algorithm;
224
 
225
v0.3k  improved matching of nitro compounds (ionic vs. non-ionic
226
       representation); some finetuning in recognition of N-oxides,
227
       hydroxylamines, etc.; modified get_molstat in order to ignore
228
       charges in nitro groups, N-oxides, sulfoxides, azides, etc. in
229
       ionic representation; added function normalize_ionic_bonds;
230
       fixed a bug in is_alkenyl; fixed a bug (introduced in v0.3j) in
231
       the treatment of "old-style" MDL charges;
232
 
233
v0.3l  minor adjustments in quick_match (for unknown atom types,
234
       opposite charges); some performance improvements, e.g. in function
235
       path_pos, reduced extensive calls to is_heavyatom and is_metal
236
       by extending atom_rec with boolean fields 'heavy' and 'metal'
237
       (thanks to E.-G.Schmid); added molstat field n_rBz (number of
238
       benzene rings; deactivated by default); added -l command-line
239
       option to checkmol (lists all molstat codes with a short
240
       explanation); added graceful handling of NoStruct (i.e.,
241
       zero-atom) molecules
242
 
243
v0.3m  minor bug fixes (chk_imine), let normalize_ionic_bonds return "true"
244
       if some bond-order change was made; fixed incorrect implementation
245
       of the Morgan algorithm (thanks to H.Feldman), fixed is_matching in
246
       order to prevent wrong matches of larger rings on smaller ones; count
247
       halogens also as type "X" in molstat (as before v0.3l); added some more
248
       molstat descriptors for most elements (deactivated by default; for
249
       activation, uncomment the definition of "extended_molstat", see below);
250
       added support for the generation of binary fingerprints with output
251
       either as boolean values (-f option) or as decimal values (-F option),
252
       fingerprint patterns are supplied by the user (in SDF format, max. 62
253
       structures per file); added a version check ("tweaklevel",
254
       ringsearch_mode, opt_metalrings) for "tweaked" MDL molfiles
255
 
256
v0.3n  increased max_vringsize in SSR mode from 10 to 12 (now defined in
257
       ssr_vringsize); optionally changed ring statistics to ignore envelope
258
       rings (which completely contain another ring, "reduced SAR") in order to
259
       make molstat in SAR and SSR mode more compatible) - disabled by default;
260
       introduced a new molstat descriptor: n_br2p (number of bonds which
261
       belong to two or more rings); changed n_b1 counter to ignore bonds to
262
       explicit hydrogens; added procedure fix_ssr_ringcounts
263
       (see comment in the code); added bond property mdl_stereo for preservation
264
       of original value; slightly changed "get_molstat" and "update_atypes" in
265
       order to consolidate atom type for various N atoms; remember "chiral" flag
266
       status in molfile output (-m); modified chk_arom in order to accept rings
267
       as aromatic if all bonds are of type 'A'; several minor bug fixes
268
 
269
v0.3o  minor changes in update_atypes (nitrogen); changed the matching
270
       algorithm in order to take care of disconnected molecular graphs
271
       (e.g., salts); refined matching of atoms with formal charges
272
 
273
 
274
Credits:
275
 
276
Rami Jbara (rami_jbara@hotmail.com) designed the 8-character functional
277
group codes.
278
 
279
I am also very grateful to Ernst-Georg Schmid (Bayer Business Services,
280
Leverkusen/Germany) and to Howard Feldman (The Blueprint Initiative,
281
Toronto/Canada) for numerous bug reports and suggestions for improvements.
282
 
283
 
284
 
285
===============================================================================
286
DISCLAIMER
287
This program is free software; you can redistribute it and/or
288
modify it under the terms of the GNU General Public License
289
as published by the Free Software Foundation; either version 2
290
of the License, or (at your option) any later version.
291
 
292
This program is distributed in the hope that it will be useful,
293
but WITHOUT ANY WARRANTY; without even the implied warranty of
294
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
295
GNU General Public License for more details.
296
 
297
You should have received a copy of the GNU General Public License
298
along with this program; if not, write to the Free Software Foundation,
299
Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
300
===============================================================================
301
*/
302
 
303
/* $DEFINE debug                    uncomment if desired */
304
/* $DEFINE extended_molstat         uncomment if desired */
305
/* $DEFINE reduced_SAR              uncomment if desired */
306
 
307
/* uses
308
  SYSUTILS, MATH; */
309
 
310
#include <stdlib.h>
311
#include <stdio.h>
312
#include <math.h>
313
#include <string.h>
314
#include <ctype.h>
315
#include <sys/types.h>
316
#include <sys/stat.h>
317
#include "safemem.h"
318
#ifdef MAKE_SHARED_LIBRARY
319
#include "barsoi.h"
320
#endif
321
 
322
#ifdef MAKE_SHARED_LIBRARY
323
#define version         "0.3p C (pgchem::barsoi)"
324
#else
325
#define version         "0.3p C"
326
#endif
327
 
328
#undef REDUCED_SAR
329
 
330
/* How many recursions before aborting is_ringpath and reverting to SSR */
331
#define max_ringpath_recursion_depth   500000
332
 
333
/* How many recursions before aborting is_match and reverting to non-exhaustive match */
334
#define max_match_recursion_depth   500000
335
 
336
#define tweaklevel      2
337
    /* v0.3m; accept tweaks in MDL molfiles only if same level */
338
#define max_atoms       1024
339
#define max_bonds       1024
340
#define slack           8192
341
#define max_ringsize    128
342
#define max_rings       1024
343
#define max_fg          256
344
#define max_neighbors   16      /* new in v0.2h */
345
 
346
#define TAB             '\t'
347
 
348
#define max_matchpath_length  256
349
#define pmCheckMol      1001
350
#define pmMatchMol      1002
351
 
352
#define rs_sar          2001    /* ring search mode: SAR = set of all rings */
353
#define rs_ssr          2002
354
    /*                   SSR = set of small rings */
355
 
356
#define btopo_any       0       /* bond topology, new in v0.3d */
357
#define btopo_ring      1
358
#define btopo_chain     2
359
#define btopo_always_any  3     /* even in "strict mode" */
360
#define btopo_excess_rc  4
361
/* bond in candidate must be included in _more_ rings than
362
                        the matching bond in the query ==> specific search for
363
                        annulated systems */
364
#define btopo_exact_rc  5
365
    /* bond in query and candidate must have same ring count */
366
 
367
#define bstereo_any     0
368
    /* new in v0.3d, any E/Z isomer matches (for double bonds) */
369
#define bstereo_xyz     1
370
    /* E/Z match is checked by using XYZ coordinates of the atoms */
371
#define bstereo_up      11      /* new in v0.3f, flags for single bonds */
372
#define bstereo_down    16
373
#define bstereo_either    14    /* 0.3x */
374
#define bstereo_double_either    13     /* 0.3x */
375
 
376
#define fpf_boolean     3001
377
    /* v0.3m; format for fingerprint output (n:T, n:F) */
378
#define fpf_decimal     3002
379
    /* v0.3m; format for fingerprint output as decimal value of bitstring */
380
#define fp_blocksize    62
381
    /* v0.3m; 1 bit may be used for sign (e.g. by PHP), 1 bit for "exact hit" */
382
#define ssr_vringsize   12      /* v0.3n; max. ring size in SSR mode */
383
 
384
/* Definitions for functional groups: */
385
#define fg_cation       1
386
#define fg_anion        2
387
#define fg_carbonyl     3
388
#define fg_aldehyde     4
389
#define fg_ketone       5
390
#define fg_thiocarbonyl  6
391
#define fg_thioaldehyde  7
392
#define fg_thioketone   8
393
#define fg_imine        9
394
#define fg_hydrazone    10
395
#define fg_semicarbazone  11
396
#define fg_thiosemicarbazone  12
397
#define fg_oxime        13
398
#define fg_oxime_ether  14
399
#define fg_ketene       15
400
#define fg_ketene_acetal_deriv  16
401
#define fg_carbonyl_hydrate  17
402
#define fg_hemiacetal   18
403
#define fg_acetal       19
404
#define fg_hemiaminal   20
405
#define fg_aminal       21
406
#define fg_thiohemiaminal  22
407
#define fg_thioacetal   23
408
#define fg_enamine      24
409
#define fg_enol         25
410
#define fg_enolether    26
411
#define fg_hydroxy      27
412
#define fg_alcohol      28
413
#define fg_prim_alcohol  29
414
#define fg_sec_alcohol  30
415
#define fg_tert_alcohol  31
416
#define fg_1_2_diol     32
417
#define fg_1_2_aminoalcohol  33
418
#define fg_phenol       34
419
#define fg_1_2_diphenol  35
420
#define fg_enediol      36
421
#define fg_ether        37
422
#define fg_dialkylether  38
423
#define fg_alkylarylether  39
424
#define fg_diarylether  40
425
#define fg_thioether    41
426
#define fg_disulfide    42
427
#define fg_peroxide     43
428
#define fg_hydroperoxide  44
429
#define fg_hydrazine    45
430
#define fg_hydroxylamine  46
431
#define fg_amine        47
432
#define fg_prim_amine   48
433
#define fg_prim_aliph_amine  49
434
#define fg_prim_arom_amine  50
435
#define fg_sec_amine    51
436
#define fg_sec_aliph_amine  52
437
#define fg_sec_mixed_amine  53
438
#define fg_sec_arom_amine  54
439
#define fg_tert_amine   55
440
#define fg_tert_aliph_amine  56
441
#define fg_tert_mixed_amine  57
442
#define fg_tert_arom_amine  58
443
#define fg_quart_ammonium  59
444
#define fg_n_oxide      60
445
#define fg_halogen_deriv  61
446
#define fg_alkyl_halide  62
447
#define fg_alkyl_fluoride  63
448
#define fg_alkyl_chloride  64
449
#define fg_alkyl_bromide  65
450
#define fg_alkyl_iodide  66
451
#define fg_aryl_halide  67
452
#define fg_aryl_fluoride  68
453
#define fg_aryl_chloride  69
454
#define fg_aryl_bromide  70
455
#define fg_aryl_iodide  71
456
#define fg_organometallic  72
457
#define fg_organolithium  73
458
#define fg_organomagnesium  74
459
#define fg_carboxylic_acid_deriv  75
460
#define fg_carboxylic_acid  76
461
#define fg_carboxylic_acid_salt  77
462
#define fg_carboxylic_acid_ester  78
463
#define fg_lactone      79
464
#define fg_carboxylic_acid_amide  80
465
#define fg_carboxylic_acid_prim_amide  81
466
#define fg_carboxylic_acid_sec_amide  82
467
#define fg_carboxylic_acid_tert_amide  83
468
#define fg_lactam       84
469
#define fg_carboxylic_acid_hydrazide  85
470
#define fg_carboxylic_acid_azide  86
471
#define fg_hydroxamic_acid  87
472
#define fg_carboxylic_acid_amidine  88
473
#define fg_carboxylic_acid_amidrazone  89
474
#define fg_nitrile      90
475
#define fg_acyl_halide  91
476
#define fg_acyl_fluoride  92
477
#define fg_acyl_chloride  93
478
#define fg_acyl_bromide  94
479
#define fg_acyl_iodide  95
480
#define fg_acyl_cyanide  96
481
#define fg_imido_ester  97
482
#define fg_imidoyl_halide  98
483
#define fg_thiocarboxylic_acid_deriv  99
484
#define fg_thiocarboxylic_acid  100
485
#define fg_thiocarboxylic_acid_ester  101
486
#define fg_thiolactone  102
487
#define fg_thiocarboxylic_acid_amide  103
488
#define fg_thiolactam   104
489
#define fg_imido_thioester  105
490
#define fg_oxohetarene  106
491
#define fg_thioxohetarene  107
492
#define fg_iminohetarene  108
493
#define fg_orthocarboxylic_acid_deriv  109
494
#define fg_carboxylic_acid_orthoester  110
495
#define fg_carboxylic_acid_amide_acetal  111
496
#define fg_carboxylic_acid_anhydride  112
497
#define fg_carboxylic_acid_imide  113
498
#define fg_carboxylic_acid_unsubst_imide  114
499
#define fg_carboxylic_acid_subst_imide  115
500
#define fg_co2_deriv    116
501
#define fg_carbonic_acid_deriv  117
502
#define fg_carbonic_acid_monoester  118
503
#define fg_carbonic_acid_diester  119
504
#define fg_carbonic_acid_ester_halide  120
505
#define fg_thiocarbonic_acid_deriv  121
506
#define fg_thiocarbonic_acid_monoester  122
507
#define fg_thiocarbonic_acid_diester  123
508
#define fg_thiocarbonic_acid_ester_halide  124
509
#define fg_carbamic_acid_deriv  125
510
#define fg_carbamic_acid  126
511
#define fg_carbamic_acid_ester  127
512
#define fg_carbamic_acid_halide  128
513
#define fg_thiocarbamic_acid_deriv  129
514
#define fg_thiocarbamic_acid  130
515
#define fg_thiocarbamic_acid_ester  131
516
#define fg_thiocarbamic_acid_halide  132
517
#define fg_urea         133
518
#define fg_isourea      134
519
#define fg_thiourea     135
520
#define fg_isothiourea  136
521
#define fg_guanidine    137
522
#define fg_semicarbazide  138
523
#define fg_thiosemicarbazide  139
524
#define fg_azide        140
525
#define fg_azo_compound  141
526
#define fg_diazonium_salt  142
527
#define fg_isonitrile   143
528
#define fg_cyanate      144
529
#define fg_isocyanate   145
530
#define fg_thiocyanate  146
531
#define fg_isothiocyanate  147
532
#define fg_carbodiimide  148
533
#define fg_nitroso_compound  149
534
#define fg_nitro_compound  150
535
#define fg_nitrite      151
536
#define fg_nitrate      152
537
#define fg_sulfuric_acid_deriv  153
538
#define fg_sulfuric_acid  154
539
#define fg_sulfuric_acid_monoester  155
540
#define fg_sulfuric_acid_diester  156
541
#define fg_sulfuric_acid_amide_ester  157
542
#define fg_sulfuric_acid_amide  158
543
#define fg_sulfuric_acid_diamide  159
544
#define fg_sulfuryl_halide  160
545
#define fg_sulfonic_acid_deriv  161
546
#define fg_sulfonic_acid  162
547
#define fg_sulfonic_acid_ester  163
548
#define fg_sulfonamide  164
549
#define fg_sulfonyl_halide  165
550
#define fg_sulfone      166
551
#define fg_sulfoxide    167
552
#define fg_sulfinic_acid_deriv  168
553
#define fg_sulfinic_acid  169
554
#define fg_sulfinic_acid_ester  170
555
#define fg_sulfinic_acid_halide  171
556
#define fg_sulfinic_acid_amide  172
557
#define fg_sulfenic_acid_deriv  173
558
#define fg_sulfenic_acid  174
559
#define fg_sulfenic_acid_ester  175
560
#define fg_sulfenic_acid_halide  176
561
#define fg_sulfenic_acid_amide  177
562
#define fg_thiol        178
563
#define fg_alkylthiol   179
564
#define fg_arylthiol    180
565
#define fg_phosphoric_acid_deriv  181
566
#define fg_phosphoric_acid  182
567
#define fg_phosphoric_acid_ester  183
568
#define fg_phosphoric_acid_halide  184
569
#define fg_phosphoric_acid_amide  185
570
#define fg_thiophosphoric_acid_deriv  186
571
#define fg_thiophosphoric_acid  187
572
#define fg_thiophosphoric_acid_ester  188
573
#define fg_thiophosphoric_acid_halide  189
574
#define fg_thiophosphoric_acid_amide  190
575
#define fg_phosphonic_acid_deriv  191
576
#define fg_phosphonic_acid  192
577
#define fg_phosphonic_acid_ester  193
578
#define fg_phosphine    194
579
#define fg_phosphinoxide  195
580
#define fg_boronic_acid_deriv  196
581
#define fg_boronic_acid  197
582
#define fg_boronic_acid_ester  198
583
#define fg_alkene       199
584
#define fg_alkyne       200
585
#define fg_aromatic     201
586
#define fg_heterocycle  202
587
#define fg_alpha_aminoacid  203
588
#define fg_alpha_hydroxyacid  204
589
 
590
typedef enum
591
{ false = 0, true } boolean;
592
 
593
 
594
typedef char str2[3];
595
 
596
typedef char str3[4];
597
 
598
typedef char str4[5];
599
 
600
typedef char str5[6];
601
 
602
typedef char str8[9];
603
 
604
typedef struct atom_rec
605
{
606
  str2 element;
607
  str3 atype;
608
  float x, y, z;
609
  int formal_charge;
610
  float real_charge;
611
  int Hexp;                     /* explicit H count */
612
  int Htot;                     /* total H count */
613
  int neighbor_count, ring_count;
614
  boolean arom, stereo_care;    /* new in v0.3d */
615
  boolean q_arom;               // v0.3p potentially aromatic in a query structure
616
  boolean heavy;                /* new in v0.3l */
617
  boolean metal;                /* new in v0.3l */
618
  int nvalences;                /* new in v0.3m */
619
  boolean tag;                  /* new in v0.3o */
620
  int nucleon_number;           /* 0.3.x */
621
  int radical_type;             /* 0.3.x */
622
} atom_rec;
623
 
624
typedef struct bond_rec
625
{
626
  int a1, a2;
627
  char btype;
628
  int ring_count;
629
  boolean arom;
630
  boolean q_arom;               // v0.3p potentially aromatic in a query structure
631
  int topo;                     /* new in v0.3d, see MDL file description */
632
  int stereo;                   /* new in v0.3d */
633
  int mdl_stereo;               /* new in v0.3n */
634
} bond_rec;
635
 
636
typedef int ringpath_type[max_ringsize];
637
typedef int matchpath_type[max_matchpath_length];
638
 
639
typedef atom_rec atomlist[max_atoms];
640
typedef bond_rec bondlist[max_bonds];
641
typedef ringpath_type ringlist[max_rings];
642
typedef int neighbor_rec[max_neighbors];        /* new in v0.2h */
643
typedef boolean fglist[max_fg];
644
 
645
typedef char molbuftype[max_atoms + max_bonds + slack][256];
646
 
647
typedef boolean matchmatrix[max_neighbors][max_neighbors];
648
    /* new in v0.2i */
649
 
650
typedef struct molstat_rec
651
{
652
  int n_QA, n_QB, n_chg;        /* number of query atoms, query bonds, charges */
653
  int n_C1, n_C2, n_C;
654
  /* number of sp, sp2 hybridized, and total no. of carbons */
655
  int n_CHB1p, n_CHB2p, n_CHB3p, n_CHB4;
656
  /* number of C atoms with at least 1, 2, 3 hetero bonds */
657
  int n_O2, n_O3;               /* number of sp2 and sp3 oxygens */
658
  int n_N1, n_N2, n_N3;         /* number of sp, sp2, and sp3 nitrogens */
659
  int n_S, n_SeTe;
660
  /* number of sulfur atoms and selenium or tellurium atoms */
661
  int n_F, n_Cl, n_Br, n_I;
662
  /* number of fluorine, chlorine, bromine, iodine atoms */
663
  int n_P, n_B;                 /* number of phosphorus and boron atoms */
664
  int n_Met, n_X;
665
  /* number of metal and "other" atoms (not listed elsewhere); v0.3l */
666
  int n_b1, n_b2, n_b3, n_bar;
667
  /* number single, double, triple, and aromatic bonds */
668
  int n_C1O, n_C2O, n_CN, n_XY;
669
  /* number of C-O single bonds, C=O double bonds, CN bonds (any type), hetero/hetero bonds */
670
  int n_r3, n_r4, n_r5, n_r6, n_r7, n_r8;
671
  /* number of 3-, 4-, 5-, 6-, 7-, and 8-membered rings */
672
  int n_r9, n_r10, n_r11, n_r12, n_r13p;
673
  /* number of 9-, 10-, 11-, 12-, and 13plus-membered rings */
674
  int n_rN, n_rN1, n_rN2, n_rN3p;
675
  /* number of rings containing N (any number), 1 N, 2 N, and 3 N or more */
676
  int n_rO, n_rO1, n_rO2p;
677
  /* number of rings containing O (any number), 1 O, and 2 O or more */
678
  int n_rS, n_rX, n_rAr, n_rBz;
679
  /* number of rings containing S (any number), any heteroatom (any number),  */
680
  /* number of aromatic rings, number of benzene rings */
681
  int n_br2p;                   /* number of bonds belonging to more than one ring (v0.3n) */
682
/* p2c: checkmol.pas, line 590:
683
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
684
  /*$IFDEF extended_molstat */
685
  int n_psg01, n_psg02, n_psg13, n_psg14;
686
  /* number of atoms belonging to elements of group 1, 2, etc.  */
687
  int n_psg15, n_psg16, n_psg17, n_psg18;
688
  /* number of atoms belonging to elements of group 15, 16, etc.  */
689
  int n_pstm, n_psla;
690
  /* number of transition metals, lanthanides/actinides */
691
  int n_iso, n_rad;
692
  /* number of isotopes, radicals */
693
  /*$ENDIF */
694
} molstat_rec;
695
 
696
typedef struct ringprop_rec
697
{
698
  /* new in v0.3 */
699
  int size;
700
  boolean arom, envelope;
701
} ringprop_rec;
702
 
703
typedef ringprop_rec ringprop_type[max_rings];
704
 
705
typedef struct p_3d
706
{
707
  /* new in v0.3d */
708
  double x, y, z;
709
} p_3d;
710
 
711
typedef int chirpath_type[4];   /* new in v0.3f */
712
 
713
#ifdef MAKE_SHARED_LIBRARY
714
static boolean yet_initialized = false;
715
#endif
716
 
717
typedef struct connval_rec
718
{
719
  /* new in v0.3j */
720
  int def;                      /* better as longint for large molecules? */
721
  int tmp;
722
} connval_rec;
723
 
724
typedef connval_rec connval_type[max_atoms];    /* new in v0.3j  */
725
 
726
 
727
static int progmode;
728
static char progname[256];
729
 
730
#ifndef MAKE_SHARED_LIBRARY
731
static int i;                   /* general purpose index */
732
#endif
733
 
734
static int li;
735
static boolean opt_none, opt_verbose, opt_text, opt_text_de, opt_code,
736
  opt_bin, opt_bitstring, opt_stdin, opt_exact, opt_debug,
737
  opt_molout, opt_molstat, opt_molstat_X, opt_xmdlout, opt_strict;
738
    /* new in v0.2f */
739
static boolean opt_metalrings;  /* new in v0.3 */
740
static boolean opt_geom;        /* new in v0.3d */
741
static boolean opt_chiral;      /* new in v0.3f */
742
static boolean opt_iso;         /* new in v0.3x */
743
static boolean opt_chg;         /* new in v0.3x */
744
static boolean opt_rad;         /* new in v0.3x */
745
static int opt_rs;              /* new in v0.3i */
746
 
747
#ifdef MAKE_SHARED_LIBRARY
748
static int opt_rs_dll = RPA_DEFAULT;
749
#endif
750
 
751
static boolean opt_fp;          /* new in v0.3m */
752
static int fpformat;            /* new in v0.3m */
753
static char filetype[256];
754
/*molfile : text; */
755
static char molfilename[256];
756
static char ndl_molfilename[256];
757
static char molname[256];
758
static char ndl_molname[256];
759
static char tmp_molname[256];   /* v0.3m */
760
static char molcomment[256];
761
static int n_atoms, n_bonds, n_rings;
762
    /* the number of rings we determined ourselves */
763
static int n_countablerings;
764
    /* v0.3n; number of rings which are not envelope rings */
765
static int n_cmrings;
766
    /* the number of rings we read from a (CheckMol-tweaked) MDL molfile */
767
//static int n_charges;         /* number of charges */
768
static int n_heavyatoms, n_heavybonds, ndl_n_atoms, ndl_n_bonds, ndl_n_rings,
769
  ndl_n_heavyatoms, ndl_n_heavybonds;
770
/*cm_mdlmolfile  : boolean; */
771
static boolean found_arominfo, found_querymol, ndl_querymol;
772
static int tmp_n_atoms;         /* v0.3m */
773
static int tmp_n_bonds;         /* v0.3m */
774
static int tmp_n_rings;         /* v0.3m */
775
static int tmp_n_heavyatoms;    /* v0.3m */
776
static int tmp_n_heavybonds;    /* v0.3m */
777
 
778
static atom_rec *atom;
779
static bond_rec *bond;
780
static ringpath_type *ring;
781
static ringprop_rec *ringprop;  /* new in v0.3 */
782
 
783
static atom_rec *ndl_atom;
784
static bond_rec *ndl_bond;
785
static ringpath_type *ndl_ring;
786
static ringprop_rec *ndl_ringprop;      /* new in v0.3 */
787
static int ndl_ref_atom;        /* since v0.3j as a global variable */
788
static atom_rec *tmp_atom;      /* v0.3m */
789
static bond_rec *tmp_bond;      /* v0.3m */
790
static ringpath_type *tmp_ring; /* v0.3m */
791
static ringprop_rec *tmp_ringprop;      /* v0.3m */
792
 
793
static boolean matchresult, matchsummary;       /* v0.3o */
794
static matchpath_type ndl_matchpath, hst_matchpath;
795
 
796
static fglist fg;
797
static str4 atomtype;
798
static str3 newatomtype;
799
 
800
static char (*molbuf)[256];
801
static int molbufindex;
802
 
803
static boolean mol_in_queue;
804
static int mol_count;
805
 
806
static molstat_rec molstat, ndl_molstat, tmp_molstat;   /* v0.3m */
807
 
808
static int ringsearch_mode, max_vringsize;      /* for SSR ring search */
809
 
810
static FILE *rfile;
811
static boolean rfile_is_open, mol_OK;   /* new in v0.2i */
812
 
813
static int n_ar;                /* new in v0.3 */
814
static int prev_n_ar;           /* new in v0.3 */
815
static boolean ez_search;       /* new in v0.3d */
816
static boolean rs_search;       /* new in v0.3f */
817
static boolean ez_flag;         /* new in v0.3f */
818
static boolean chir_flag;       /* new in v0.3f */
819
static boolean rs_strict;       /* new in v0.3j */
820
 
821
static int n_Ctot, n_Otot, n_Ntot;      /* new in v0.3g */
822
static int ndl_n_Ctot, ndl_n_Otot, ndl_n_Ntot;  /* new in v0.3g */
823
static int tmp_n_Ctot, tmp_n_Otot, tmp_n_Ntot;  /* new in v0.3m */
824
static boolean ether_generic;   /* v0.3j */
825
static boolean amine_generic;   /* v0.3j   */
826
static boolean hydroxy_generic; /* v0.3j */
827
static connval_rec *cv;         /* new in v0.3j */
828
static long long fpdecimal;     /* v0.3m */
829
static long long fpincrement;
830
static int fpindex;
831
static boolean fp_exacthit, fp_exactblock;
832
static int tmfcode;
833
    /* v0.3m; version number for tweaked MDL molfiles (tweaklevel) */
834
static boolean tmfmismatch;
835
    /* v0.3m; rely on tweaked MDL molfiles only if same level */
836
static boolean auto_ssr;
837
    /* v0.3n; indicates that SAR -> SSR fallback has happened */
838
static int recursion_depth;
839
    /* ====================emulated pascal functions============================ */
840
 
841
static boolean
842
file_exists (const char *fileName)
843
{
844
  struct stat filestat;
845
 
846
  return stat (fileName, &filestat) == 0 ? true : false;
847
}
848
 
849
static void
850
lblank (int cols, char *nstr)
851
{
852
  /* inserts leading blanks up to a given number of total characters */
853
  char STR1[256];
854
 
855
  if (strlen (nstr) >= cols)
856
    return;
857
  while (strlen (nstr) < cols)
858
    sprintf (nstr, " %s", strcpy (STR1, nstr));
859
}
860
 
861
static inline double
862
radtodeg (double rads)
863
{
864
  return (180.0 / M_PI) * rads;
865
}
866
 
867
static void
868
strdelete (char *s, int pos, int len)
869
{
870
  int slen;
871
 
872
  if (--pos < 0)
873
    return;
874
  slen = strlen (s) - pos;
875
  if (slen <= 0)
876
    return;
877
  s += pos;
878
  if (slen <= len)
879
    {
880
      *s = 0;
881
      return;
882
    }
883
  while ((*s = s[len]))
884
    s++;
885
}
886
 
887
static int
888
strpos2 (char *s, char *pat, int pos)
889
{
890
  char *cp, ch;
891
  int slen;
892
 
893
  if (--pos < 0)
894
    return 0;
895
  slen = strlen (s) - pos;
896
  cp = s + pos;
897
  if (!(ch = *pat++))
898
    return 0;
899
  pos = strlen (pat);
900
  slen -= pos;
901
  while (--slen >= 0)
902
    {
903
      if (*cp++ == ch && !strncmp (cp, pat, pos))
904
        return cp - s;
905
    }
906
  return 0;
907
}
908
 
909
static char *
910
strsub (char *ret, char *s, int pos, int len)
911
{
912
  char *s2;
913
 
914
  if (--pos < 0 || len <= 0)
915
    {
916
      *ret = 0;
917
      return ret;
918
    }
919
  while (pos > 0)
920
    {
921
      if (!*s++)
922
        {
923
          *ret = 0;
924
          return ret;
925
        }
926
      pos--;
927
    }
928
  s2 = ret;
929
  while (--len >= 0)
930
    {
931
      if (!(*s2++ = *s++))
932
        return ret;
933
    }
934
  *s2 = 0;
935
  return ret;
936
}
937
 
938
 
939
/*============================= auxiliary functions & procedures */
940
 
941
inline static void
942
all_lowercase (char *astring)
943
{
944
  int i;
945
  int l = strlen (astring);
946
 
947
  for (i = 0; i < l; i++)
948
    {
949
      astring[i] = tolower (astring[i]);
950
    }
951
}
952
 
953
static void
954
init_globals ()
955
{
956
  /*int i;*/
957
 
958
  opt_verbose = false;
959
  opt_debug = false;
960
  opt_exact = false;
961
  opt_stdin = false;
962
  opt_text = false;
963
  opt_code = false;
964
  opt_bin = false;
965
  opt_bitstring = false;
966
  opt_molout = false;
967
  opt_molstat = false;
968
  opt_molstat_X = false;
969
  opt_xmdlout = false;
970
  opt_strict = false;           /* new in v0.2f */
971
  opt_metalrings = false;       /* new in v0.3 */
972
  opt_geom = false;             /* new in v0.3d */
973
  opt_chiral = false;           /* new in v0.3f */
974
  opt_fp = false;               /* new in v0.3m */
975
  opt_iso = false;              /* new in v0.3x */
976
  opt_chg = false;              /* new in v0.3x */
977
  opt_rad = false;              /* new in v0.3x */
978
  /*cm_mdlmolfile   := false; */
979
  found_arominfo = false;
980
  found_querymol = false;
981
  ndl_querymol = false;
982
  opt_rs = rs_sar;              /* v0.3i */
983
  /*ringsearch_mode := rs_sar; */
984
  rfile_is_open = false;        /* new in v0.2g */
985
  ez_search = false;            /* new in v0.3d */
986
  rs_search = false;            /* new in v0.3f */
987
  ez_flag = false;              /* new in v0.3f */
988
  chir_flag = false;            /* new in v0.3f */
989
  rs_strict = false;            /* new in v0.3j */
990
  n_Ctot = 0;
991
  n_Otot = 0;
992
  n_Ntot = 0;                   /* new in v0.3g */
993
  ndl_n_Ctot = 0;
994
  ndl_n_Otot = 0;
995
  ndl_n_Ntot = 0;               /* new in v0.3g */
996
  //for (i = 0; i < max_fg; i++)
997
  //  fg[i] = false;
998
  memset (fg, 0, sizeof (fglist));
999
  /*try */
1000
  molbuf = safe_malloc (sizeof (molbuftype));
1001
  /*except
1002
     on e:Eoutofmemory do
1003
     begin
1004
     writeln('Not enough memory');
1005
     halt(4);
1006
     end;
1007
     end; */
1008
  ether_generic = false;        /* v0.3j */
1009
  amine_generic = false;        /* v0.3j */
1010
  hydroxy_generic = false;      /* v0.3j */
1011
  fpformat = fpf_decimal;       /* v0.3m */
1012
  fpindex = 0;                  /* v0.3m */
1013
  fp_exacthit = false;          /* v0.3m */
1014
  fp_exactblock = false;        /* v0.3m */
1015
  tmfcode = 0;                  /* v0.3m */
1016
  tmfmismatch = false;          /* v0.3m */
1017
  auto_ssr = false;             /* v0.3n */
1018
  recursion_depth = 0;
1019
}
1020
 
1021
 
1022
static inline void
1023
init_molstat (mstat)
1024
     molstat_rec *mstat;
1025
{
1026
  /*
1027
     with mstat do
1028
     begin
1029
     n_QA := 0; n_QB := 0; n_chg := 0;
1030
     n_C1 := 0; n_C2 := 0; n_C  := 0;
1031
     n_CHB1p := 0; n_CHB2p := 0; n_CHB3p := 0; n_CHB4 := 0;
1032
     n_O2 := 0; n_O3  := 0;
1033
     n_N1 := 0; n_N2 := 0; n_N3 := 0;
1034
     n_S := 0; n_SeTe := 0;
1035
     n_F := 0; n_Cl := 0; n_Br := 0; n_I := 0;
1036
     n_P := 0; n_B := 0;
1037
     n_Met := 0; n_X := 0;
1038
     n_b1 := 0; n_b2 := 0; n_b3 := 0; n_bar := 0;
1039
     n_C1O := 0; n_C2O := 0; n_CN := 0; n_XY := 0;
1040
     n_r3 := 0; n_r4 := 0; n_r5 := 0; n_r6 := 0; n_r7 := 0;
1041
     n_r8 := 0; n_r9 := 0; n_r10 := 0; n_r11 := 0; n_r12 := 0; n_r13p := 0;
1042
     n_rN := 0; n_rN1 := 0; n_rN2 := 0; n_rN3p := 0;
1043
     n_rO := 0; n_rO1 := 0; n_rO2p := 0;
1044
     n_rS := 0; n_rX := 0;
1045
     n_rAr := 0; n_rBz := 0; n_br2p := 0;
1046
     end;
1047
   */
1048
  memset (mstat, 0, sizeof (molstat_rec));      /* v0.3k */
1049
}
1050
 
1051
 
1052
#if 0
1053
static void
1054
debugoutput (dstr)
1055
     char *dstr;
1056
{
1057
  if (opt_debug)
1058
    printf ("%s\n", dstr);
1059
}
1060
#endif
1061
 
1062
static void
1063
left_trim (trimstr)
1064
     char *trimstr;
1065
{
1066
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1067
    strdelete (trimstr, 1, 1);
1068
}
1069
 
1070
 
1071
static int
1072
left_int (trimstr)
1073
     char *trimstr;
1074
{
1075
  char numstr[256];
1076
  char auxstr[256];
1077
  int auxint = 0;
1078
  char STR1[256];
1079
 
1080
  strcpy (numstr, "-+0123456789");
1081
  *auxstr = '\0';
1082
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1083
    strdelete (trimstr, 1, 1);
1084
  while ((*trimstr != '\0') &&
1085
         (strpos2 (numstr, (sprintf (STR1, "%c", trimstr[0]), STR1), 1) > 0))
1086
    {
1087
      sprintf (auxstr + strlen (auxstr), "%c", trimstr[0]);
1088
      strdelete (trimstr, 1, 1);
1089
    }
1090
  return auxint;
1091
}
1092
 
1093
static int
1094
path_pos (int id, int *a_path)
1095
{
1096
  int i = 0;
1097
 
1098
  for (i = 0; i < max_ringsize; i++)
1099
    {
1100
      if (*(a_path++) == id)
1101
        {
1102
          return ++i;
1103
        }
1104
    }
1105
  return 0;
1106
}
1107
 
1108
static int
1109
path_length (int *a_path)
1110
{
1111
  if ((a_path[max_ringsize - 1] != 0) && (path_pos (0, a_path) == 0))
1112
    return max_ringsize;
1113
  else
1114
    return (path_pos (0, a_path) - 1);
1115
}
1116
 
1117
static int
1118
get_bond (int ba1, int ba2)
1119
{
1120
  int i;
1121
  int b_id = 0;
1122
  int FORLIM;
1123
 
1124
  if (n_bonds <= 0)
1125
    return b_id;
1126
  FORLIM = n_bonds;
1127
  for (i = 1; i <= FORLIM; i++)
1128
    {
1129
      if ((bond[i - 1].a1 == ba1 && bond[i - 1].a2 == ba2) ||
1130
          (bond[i - 1].a1 == ba2 && bond[i - 1].a2 == ba1))
1131
        b_id = i;
1132
    }
1133
  return b_id;
1134
}
1135
 
1136
static void
1137
clear_atom_tags ()
1138
{
1139
  int i, FORLIM;
1140
 
1141
  if (n_atoms > 0)
1142
    {
1143
      FORLIM = n_atoms;
1144
      for (i = 0; i < FORLIM; i++)
1145
        atom[i].tag = false;
1146
    }
1147
}
1148
 
1149
#if 0
1150
static void
1151
set_atom_tags ()
1152
{
1153
  int i, FORLIM;
1154
 
1155
  if (n_atoms > 0)
1156
    {
1157
      FORLIM = n_atoms;
1158
      for (i = 0; i < FORLIM; i++)
1159
        atom[i].tag = true;
1160
    }
1161
}
1162
#endif
1163
static void
1164
order_ringpath (int *r_path)
1165
{
1166
  /* order should be: array starts with atom of lowest number, followed by neighbor atom with lower number */
1167
  int i, pl, a_ref, a_left, a_right, a_tmp;
1168
 
1169
  pl = path_length (r_path);
1170
  if (pl < 3)
1171
    return;
1172
  a_ref = n_atoms;
1173
  /* start with highest possible value for an atom number */
1174
  for (i = 0; i < pl; i++)
1175
    {
1176
      if (r_path[i] < a_ref)    /* find the minimum value ==> reference atom */
1177
        a_ref = r_path[i];
1178
    }
1179
  if (a_ref < 1)                /* just to be sure */
1180
    return;
1181
  if (path_pos (a_ref, r_path) < pl)
1182
    a_right = r_path[path_pos (a_ref, r_path)];
1183
  else
1184
    a_right = r_path[0];
1185
  if (path_pos (a_ref, r_path) > 1)
1186
    a_left = r_path[path_pos (a_ref, r_path) - 2];
1187
  else
1188
    a_left = r_path[pl - 1];
1189
  if (a_right == a_left)        /* should never happen */
1190
    return;
1191
  if (a_right < a_left)
1192
    {
1193
      /* correct ring numbering direction, only shift of the reference atom to the left end required */
1194
      while (path_pos (a_ref, r_path) > 1)
1195
        {
1196
          a_tmp = r_path[0];
1197
          for (i = 1; i < pl; i++)
1198
            r_path[i - 1] = r_path[i];
1199
          r_path[pl - 1] = a_tmp;
1200
        }
1201
      return;
1202
    }
1203
  while (path_pos (a_ref, r_path) < pl)
1204
    {
1205
      /* step one: create "mirrored" ring path with reference atom at right end */
1206
      a_tmp = r_path[pl - 1];
1207
      for (i = pl; i >= 2; i--)
1208
        r_path[i - 1] = r_path[i - 2];
1209
      r_path[0] = a_tmp;
1210
    }
1211
  for (i = 1; i <= pl / 2; i++)
1212
    {                           /* one more mirroring */
1213
      a_tmp = r_path[i - 1];
1214
      r_path[i - 1] = r_path[pl - i];
1215
      r_path[pl - i] = a_tmp;
1216
      /* wrong ring numbering direction, two steps required */
1217
    }
1218
}
1219
 
1220
static void
1221
clear_ndl_atom_tags ()
1222
{
1223
  int i;
1224
 
1225
  if (ndl_n_atoms > 0)
1226
    {
1227
 
1228
      for (i = 0; i < ndl_n_atoms; i++)
1229
        ndl_atom[i].tag = false;
1230
    }
1231
}
1232
 
1233
 
1234
static void
1235
set_ndl_atom_tags ()
1236
{
1237
  int i;
1238
 
1239
  if (ndl_n_atoms > 0)
1240
    {
1241
 
1242
      for (i = 0; i < ndl_n_atoms; i++)
1243
        ndl_atom[i].tag = true;
1244
    }
1245
}
1246
 
1247
 
1248
static int
1249
count_tagged_ndl_heavyatoms ()
1250
{
1251
  int i;
1252
  int n = 0;
1253
 
1254
  if (ndl_n_atoms < 1)
1255
    return n;
1256
 
1257
  for (i = 0; i < ndl_n_atoms; i++)
1258
    {
1259
      if (ndl_atom[i].heavy && ndl_atom[i].tag)
1260
        n++;
1261
    }
1262
  return n;
1263
}
1264
 
1265
 
1266
 
1267
/*============================= geometry functions ========================== */
1268
 
1269
static double
1270
dist3d (p1, p2)
1271
     p_3d p1, p2;
1272
{
1273
  double res, TEMP, TEMP1, TEMP2;
1274
 
1275
  TEMP = p1.x - p2.x;
1276
  TEMP1 = p1.y - p2.y;
1277
  TEMP2 = p1.z - p2.z;
1278
  res = sqrt (TEMP * TEMP + TEMP1 * TEMP1 + TEMP2 * TEMP2);
1279
  return res;
1280
}
1281
 
1282
 
1283
/*
1284
function is_cis(p1,p2,p3,p4:p_3d):boolean;  (* new in v0.3d
1285
var                         (* just a simple, distance-based estimation
1286
  total_dist  : double;     (* instead of calculating the dihedral angle
1287
  direct_dist : double;
1288
  res         : boolean;
1289
begin
1290
  res := false;
1291
  total_dist  := dist3d(p1,p2) + dist3d(p2,p3) + dist3d(p3,p4);
1292
  direct_dist := dist3d(p1,p4);
1293
  if (direct_dist < 0.78 * total_dist) then res := true;  (* cutoff value of 0.78 was
1294
  is_cis := res;                                          (* experimentally determined
1295
end;
1296
*/
1297
/* function is_cis was replaced by a new one in v0.3h */
1298
 
1299
 
1300
static p_3d
1301
subtract_3d (p1, p2)
1302
     p_3d p1, p2;
1303
{
1304
  p_3d p;
1305
 
1306
  p.x = p1.x - p2.x;
1307
  p.y = p1.y - p2.y;
1308
  p.z = p1.z - p2.z;
1309
  return p;
1310
}
1311
 
1312
 
1313
static p_3d
1314
add_3d (p1, p2)
1315
     p_3d p1, p2;
1316
{
1317
  p_3d p;
1318
 
1319
  p.x = p1.x + p2.x;
1320
  p.y = p1.y + p2.y;
1321
  p.z = p1.z + p2.z;
1322
  return p;
1323
}
1324
 
1325
#if 0
1326
static void
1327
vec2origin (p1, p2)
1328
     p_3d *p1, *p2;
1329
{
1330
  p_3d p;
1331
 
1332
  p = subtract_3d (*p2, *p1);
1333
  *p2 = p;
1334
  p1->x = 0.0;
1335
  p1->y = 0.0;
1336
  p1->z = 0.0;
1337
}
1338
#endif
1339
 
1340
static double
1341
scalar_prod (p1, p2, p3)
1342
     p_3d p1, p2, p3;
1343
{
1344
  p_3d p;
1345
  double res;
1346
 
1347
  p = subtract_3d (p2, p1);
1348
  p2 = p;
1349
  p = subtract_3d (p3, p1);
1350
  p3 = p;
1351
  p1.x = 0.0;
1352
  p1.y = 0.0;
1353
  p1.z = 0.0;
1354
  res = p2.x * p3.x + p2.y * p3.y + p2.z * p3.z;
1355
  return res;
1356
}
1357
 
1358
 
1359
static p_3d
1360
cross_prod (p1, p2, p3)
1361
     p_3d p1, p2, p3;
1362
{
1363
  p_3d p, orig_p1;
1364
 
1365
  orig_p1 = p1;
1366
  p = subtract_3d (p2, p1);
1367
  p2 = p;
1368
  p = subtract_3d (p3, p1);
1369
  p3 = p;
1370
  p.x = p2.y * p3.z - p2.z * p3.y;
1371
  p.y = p2.z * p3.x - p2.x * p3.z;
1372
  p.z = p2.x * p3.y - p2.y * p3.x;
1373
  return (add_3d (orig_p1, p));
1374
}
1375
 
1376
 
1377
static double
1378
angle_3d (p1, p2, p3)
1379
     p_3d p1, p2, p3;
1380
{
1381
  p_3d lp1, lp2, lp3, p;
1382
  double res = 0.0;
1383
  double magn_1, magn_2, cos_phi;
1384
 
1385
  lp1 = p1;
1386
  lp2 = p2;
1387
  lp3 = p3;
1388
  p = subtract_3d (lp2, lp1);
1389
  lp2 = p;
1390
  p = subtract_3d (lp3, lp1);
1391
  lp3 = p;
1392
  lp1.x = 0.0;
1393
  lp1.y = 0.0;
1394
  lp1.z = 0.0;
1395
  magn_1 = dist3d (lp1, lp2);
1396
  magn_2 = dist3d (lp1, lp3);
1397
  if (magn_1 * magn_2 == 0)     /* emergency exit */
1398
    return M_PI;
1399
  cos_phi = scalar_prod (lp1, lp2, lp3) / (magn_1 * magn_2);
1400
  if (cos_phi < -1)
1401
    cos_phi = -1.0;
1402
  if (cos_phi > 1)
1403
    cos_phi = 1.0;
1404
  res = acos (cos_phi);
1405
  return res;
1406
}
1407
 
1408
 
1409
static double
1410
torsion (p1, p2, p3, p4)
1411
     p_3d p1, p2, p3, p4;
1412
{
1413
  p_3d lp1, lp2, lp3, lp4, d1, c1, c2;
1414
  double res;
1415
  p_3d c1xc2, c2xc1;
1416
  double dist1, dist2, sign;
1417
 
1418
  /* copy everything into local variables */
1419
  lp1 = p1;
1420
  lp2 = p2;
1421
  lp3 = p3;
1422
  lp4 = p4;
1423
  /* get the vector between the two central atoms */
1424
  d1 = subtract_3d (p3, p2);
1425
  /* shift the first atom parallel to be attached to p3 instead of p2 */
1426
  lp1 = add_3d (p1, d1);
1427
  /* now get the cross product vectors */
1428
  c1 = cross_prod (lp3, lp2, lp1);
1429
  c2 = cross_prod (lp3, lp2, lp4);
1430
  res = angle_3d (p3, c1, c2);
1431
  /*now check if it is clockwise or anticlockwise: */
1432
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1433
  c1xc2 = cross_prod (lp3, c1, c2);
1434
  c2xc1 = cross_prod (lp3, c2, c1);
1435
  /*next, get the distances from these points to our refernce point lp2 */
1436
  dist1 = dist3d (lp2, c1xc2);
1437
  dist2 = dist3d (lp2, c2xc1);
1438
  if (dist1 <= dist2)
1439
    sign = 1.0;
1440
  else
1441
    sign = -1.0;
1442
  return (sign * res);
1443
}
1444
 
1445
 
1446
static double
1447
ctorsion (p1, p2, p3, p4)
1448
     p_3d p1, p2, p3, p4;
1449
{
1450
  /* calculates "pseudo-torsion" defined by atoms 3 and 4, being both */
1451
  /* attached to atom 2, with respect to axis of atoms 1 and 2 */
1452
  p_3d lp1, lp2, lp3, lp4;
1453
  /*d1 : p_3d; */
1454
  p_3d c1, c2;
1455
  double res;
1456
  p_3d c1xc2, c2xc1;
1457
  double dist1, dist2, sign;
1458
 
1459
  /* copy everything into local variables */
1460
  lp1 = p1;
1461
  lp2 = p2;
1462
  lp3 = p3;
1463
  lp4 = p4;
1464
  /* get the cross product vectors */
1465
  c1 = cross_prod (lp2, lp1, lp3);
1466
  c2 = cross_prod (lp2, lp1, lp4);
1467
  res = angle_3d (p2, c1, c2);
1468
  /*now check if it is clockwise or anticlockwise: */
1469
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1470
  c1xc2 = cross_prod (lp2, c1, c2);
1471
  c2xc1 = cross_prod (lp2, c2, c1);
1472
  /*next, get the distances from these points to our refernce point lp1 */
1473
  dist1 = dist3d (lp1, c1xc2);
1474
  dist2 = dist3d (lp1, c2xc1);
1475
  if (dist1 <= dist2)
1476
    sign = 1.0;
1477
  else
1478
    sign = -1.0;
1479
  return (sign * res);
1480
}
1481
 
1482
 
1483
static boolean
1484
is_cis (p1, p2, p3, p4)
1485
     p_3d p1, p2, p3, p4;
1486
{
1487
  /* new in v0.3h, uses the dihedral angle */
1488
  double phi;
1489
  boolean res = false;
1490
 
1491
  phi = torsion (p1, p2, p3, p4);
1492
  if (fabs (phi) < M_PI / 2)
1493
    res = true;
1494
  return res;
1495
}
1496
 
1497
 
1498
/*====================== end of geometry functions ========================== */
1499
 
1500
static void
1501
show_usage ()
1502
{
1503
  if (progmode == pmMatchMol)
1504
    {
1505
      printf
1506
        ("matchmol version %s  N. Haider, University of Vienna, 2003-2007\n",
1507
         version);
1508
      printf ("Usage: matchmol [options] <needle> <haystack>\n");
1509
      printf
1510
        (" where <needle> and <haystack> are the two molecules to compare\n");
1511
      printf
1512
        (" (supported formats: MDL *.mol or *.sdf, Alchemy *.mol, Sybyl *.mol2)\n");
1513
      printf (" options can be:\n");
1514
      printf ("    -v  verbose output\n");
1515
      printf ("    -x  exact match\n");
1516
      printf
1517
        ("    -s  strict comparison of atom and bond types (including ring check)\n");
1518
      /* new in v0.2f, v0.3d */
1519
      printf ("    -r  force SSR (set of small rings) ring search mode\n");
1520
      printf
1521
        ("    -m  write matching molecule as MDL molfile to standard output\n");
1522
      printf
1523
        ("        (default output: record number + \":T\" for hit  or \":F\" for miss\n");
1524
      printf ("    -M  accept metal atoms as ring members\n");
1525
      printf ("    -g  check geometry of double bonds (E/Z)\n");
1526
      printf ("    -G  check geometry of chiral centers (R/S)\n");
1527
      printf ("    -a  check charges strict\n");        /* 0.3x */
1528
      printf ("    -i  check isotopes strict\n");       /* 0.3x */
1529
      printf ("    -d  check radicals strict\n");       /* 0.3x */
1530
      printf
1531
        ("    -f  fingerprint mode (1 haystack, multiple needles) with boolean output\n");
1532
      printf
1533
        ("    -F  fingerprint mode (1 haystack, multiple needles) with decimal output\n");
1534
      return;
1535
    }
1536
  printf ("checkmol version %s  N. Haider, University of Vienna, 2003-2007\n",
1537
          version);
1538
  printf ("Usage: checkmol [options] <filename>\n");
1539
  printf (" where options can be:\n");
1540
  printf
1541
    ("    -l  print a list of fingerprint codes + explanation and exit\n");
1542
  printf ("    -v  verbose output\n");
1543
  printf ("    -r  force SSR (set of small rings) ring search mode\n");
1544
  printf ("    -M  accept metal atoms as ring members\n");
1545
  printf ("  and one of the following:\n");
1546
  printf
1547
    ("    -e  english text (common name of functional group; default)\n");
1548
  printf ("    -d  german text (common name of functional group)\n");
1549
  printf ("    -c  code (acronym-like code for functional group)\n");
1550
  printf
1551
    ("    -b  binary (a bitstring representing absence or presence of each group)\n");
1552
  printf
1553
    ("    -s  the ASCII representation of the above bitstring, i.e. 0s and 1s)\n");
1554
  printf
1555
    ("    -x  print molecular statistics (number of various atom types, bond types,\n");
1556
  printf ("        ring sizes, etc.\n");
1557
  printf
1558
    ("    -X  same as above, listing all records (even if 0) as comma-separated list\n");
1559
  printf ("    -a  count charges in fingerprint\n");    /* 0.3x */
1560
  printf
1561
    ("    -m  write MDL molfile (with special encoding for aromatic atoms/bonds)\n");
1562
  printf (" options can be combined like -vc\n");
1563
  printf (" <filename> specifies any file in the formats supported\n");
1564
  printf
1565
    (" (MDL *.mol, Alchemy *.mol, Sybyl *.mol2), the filename \"-\" (without quotes)\n");
1566
  printf (" specifies standard input\n");
1567
  /* the "debug" option (-D) remains undocumented */
1568
}
1569
 
1570
 
1571
static void
1572
list_molstat_codes ()
1573
{
1574
  printf ("n_atoms:     number of heavy atoms\n");
1575
  printf ("n_bonds:     number of bonds between non-H atoms\n");
1576
  printf ("n_rings:     number of rings\n");
1577
  printf ("n_QA:        number of query atoms\n");
1578
  printf ("n_QB:        number of query bonds\n");
1579
  printf ("n_chg:       number of charges\n");
1580
  printf ("n_C1:        number of sp-hybridized carbon atoms\n");
1581
  printf ("n_C2:        number of sp2-hybridized carbon atoms\n");
1582
  printf ("n_C:         total number of carbon atoms\n");
1583
  printf
1584
    ("n_CHB1p:     number of carbon atoms with at least 1 bond to a hetero atom\n");
1585
  printf
1586
    ("n_CHB2p:     number of carbon atoms with at least 2 bonds to a hetero atom\n");
1587
  printf
1588
    ("n_CHB3p:     number of carbon atoms with at least 3 bonds to a hetero atom\n");
1589
  printf
1590
    ("n_CHB4:      number of carbon atoms with 4 bonds to a hetero atom\n");
1591
  printf ("n_O2:        number of sp2-hybridized oxygen atoms\n");
1592
  printf ("n_O3:        number of sp3-hybridized oxygen atoms\n");
1593
  printf ("n_N1:        number of sp-hybridized nitrogen atoms\n");
1594
  printf ("n_N2:        number of sp2-hybridized nitrogen atoms\n");
1595
  printf ("n_N3:        number of sp3-hybridized nitrogen atoms\n");
1596
  printf ("n_S:         number of sulfur atoms\n");
1597
  printf ("n_SeTe:      total number of selenium and tellurium atoms\n");
1598
  printf ("n_F:         number of fluorine atoms\n");
1599
  printf ("n_Cl:        number of chlorine atoms\n");
1600
  printf ("n_Br:        number of bromine atoms\n");
1601
  printf ("n_I:         number of iodine atoms\n");
1602
  printf ("n_P:         number of phosphorus atoms\n");
1603
  printf ("n_B:         number of boron atoms\n");
1604
  printf ("n_Met:       total number of metal atoms\n");
1605
  printf
1606
    ("n_X:         total number of \"other\" atoms (not listed above) and halogens\n");
1607
  printf ("n_b1:        number of single bonds\n");
1608
  printf ("n_b2:        number of double bonds\n");
1609
  printf ("n_b3:        number of triple bonds\n");
1610
  printf ("n_bar:       number of aromatic bonds\n");
1611
  printf ("n_C1O:       number of C-O single bonds\n");
1612
  printf ("n_C2O:       number of C=O double bonds\n");
1613
  printf ("n_CN:        number of C/N bonds (any type)\n");
1614
  printf ("n_XY:        number of heteroatom/heteroatom bonds (any type)\n");
1615
  printf ("n_r3:        number of 3-membered rings\n");
1616
  printf ("n_r4:        number of 4-membered rings\n");
1617
  printf ("n_r5:        number of 5-membered rings\n");
1618
  printf ("n_r6:        number of 6-membered rings\n");
1619
  printf ("n_r7:        number of 7-membered rings\n");
1620
  printf ("n_r8:        number of 8-membered rings\n");
1621
  printf ("n_r9:        number of 9-membered rings\n");
1622
  printf ("n_r10:       number of 10-membered rings\n");
1623
  printf ("n_r11:       number of 11-membered rings\n");
1624
  printf ("n_r12:       number of 12-membered rings\n");
1625
  printf ("n_r13p:      number of 13-membered or larger rings\n");
1626
  printf ("n_rN:        number of rings containing nitrogen (any number)\n");
1627
  printf ("n_rN1:       number of rings containing 1 nitrogen atom\n");
1628
  printf ("n_rN2:       number of rings containing 2 nitrogen atoms\n");
1629
  printf
1630
    ("n_rN3p:      number of rings containing 3 or more nitrogen atoms\n");
1631
  printf ("n_rO:        number of rings containing oxygen (any number)\n");
1632
  printf ("n_rO1:       number of rings containing 1 oxygen atom\n");
1633
  printf ("n_rO2p:      number of rings containing 2 or more oxygen atoms\n");
1634
  printf ("n_rS:        number of rings containing sulfur (any number)\n");
1635
  printf ("n_rX:        number of heterocycles (any type)\n");
1636
  printf ("n_rar:       number of aromatic rings (any type)\n");
1637
/* p2c: checkmol.pas, line 1207:
1638
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1639
  /*$IFDEF extended_molstat */
1640
  printf ("n_rbz:       number of benzene rings\n");
1641
  printf ("n_br2p:      number of bonds belonging to two or more rings\n");
1642
  printf
1643
    ("n_psg01:     number of atoms belonging to group 1 of the periodic system\n");
1644
  printf
1645
    ("n_psg02:     number of atoms belonging to group 2 of the periodic system\n");
1646
  printf
1647
    ("n_psg13:     number of atoms belonging to group 13 of the periodic system\n");
1648
  printf
1649
    ("n_psg14:     number of atoms belonging to group 14 of the periodic system\n");
1650
  printf
1651
    ("n_psg15:     number of atoms belonging to group 15 of the periodic system\n");
1652
  printf
1653
    ("n_psg16:     number of atoms belonging to group 16 of the periodic system\n");
1654
  printf
1655
    ("n_psg17:     number of atoms belonging to group 17 of the periodic system\n");
1656
  printf
1657
    ("n_psg18:     number of atoms belonging to group 18 of the periodic system\n");
1658
  printf
1659
    ("n_pstm:      number of atoms belonging to the transition metals\n");
1660
  printf
1661
    ("n_psla:      number of atoms belonging to the lanthanides or actinides\n");
1662
  printf ("n_iso:      number of isotopes\n");
1663
  printf ("n_rad:      number of radicals\n");
1664
  /*$ENDIF */
1665
}
1666
 
1667
 
1668
#if 0
1669
static void parse_args()
1670
{
1671
  int p;
1672
  char parstr[256];
1673
  char tmpstr[256];
1674
  int l;
1675
 
1676
  *tmpstr = '\0';
1677
  opt_none = true;
1678
  if (progmode == pmCheckMol) {
1679
    for (p = 1; p < P_argc; p++) {
1680
      strcpy(parstr, P_argv[p]);
1681
      if (!strcmp(parstr, "-l")) {   /* new in v0.3l */
1682
        list_molstat_codes();
1683
        _Escape(0);
1684
      }
1685
      if (p < P_argc - 1) {
1686
        if (strpos2(parstr, "-", 1) == 1 && p < P_argc - 1) {
1687
          strcpy(tmpstr, P_argv[p]);
1688
          left_trim(tmpstr);
1689
          l = 0;
1690
          if (strpos2(tmpstr, "v", 1) > 0)
1691
            l++;
1692
          if (strpos2(tmpstr, "D", 1) > 0)
1693
            l++;
1694
          if (strpos2(tmpstr, "r", 1) > 0)
1695
            l++;
1696
          if (strpos2(tmpstr, "M", 1) > 0)   /* new in v0.3 */
1697
            l++;
1698
          if (strlen(tmpstr) > l + 2) {
1699
            show_usage();
1700
            _Escape(1);
1701
          }
1702
          opt_none = false;
1703
          if (strpos2(tmpstr, "M", 1) > 0)
1704
            opt_metalrings = true;
1705
          if (strpos2(tmpstr, "v", 1) > 0)
1706
            opt_verbose = true;
1707
/* p2c: checkmol.pas, line 1261:
1708
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1709
          /*$IFDEF debug
1710
          if (strpos2(tmpstr, "D", 1) > 0)
1711
            opt_debug = true;
1712
          $ENDIF*/
1713
          if (strpos2(tmpstr, "e", 1) > 0)
1714
            opt_text = true;
1715
          else {
1716
            if (strpos2(tmpstr, "d", 1) > 0)
1717
              opt_text_de = true;
1718
            else {
1719
              if (strpos2(tmpstr, "c", 1) > 0)
1720
                opt_code = true;
1721
              else {
1722
                if (strpos2(tmpstr, "b", 1) > 0)
1723
                  opt_bin = true;
1724
                else {
1725
                  if (strpos2(tmpstr, "s", 1) > 0)
1726
                    opt_bitstring = true;
1727
                }
1728
              }
1729
            }
1730
            if (strpos2(tmpstr, "x", 1) > 0)
1731
              opt_molstat = true;
1732
            if (strpos2(tmpstr, "r", 1) > 0)
1733
              opt_rs = rs_ssr;
1734
            if (strpos2(tmpstr, "X", 1) > 0) {
1735
              opt_molstat = true;
1736
              opt_molstat_X = true;
1737
            }
1738
            if (strpos2(tmpstr, "m", 1) > 0) {
1739
              opt_text = false;
1740
              opt_text_de = false;
1741
              opt_bin = false;
1742
              opt_bitstring = false;
1743
              opt_code = false;
1744
              opt_molstat = false;
1745
              opt_xmdlout = true;
1746
            }
1747
          }
1748
          strcpy(molfilename, tmpstr);
1749
        }
1750
      } else {
1751
        if (strpos2(parstr, "-", 1) == 1) {
1752
          if (strlen(parstr) > 1) {
1753
            show_usage();
1754
            _Escape(1);
1755
          }
1756
          opt_stdin = true;
1757
        } else {
1758
          opt_stdin = false;
1759
          strcpy(molfilename, parstr);
1760
        }
1761
      }
1762
    }
1763
    if (opt_text == false && opt_text_de == false && opt_code == false &&
1764
        opt_bin == false && opt_bitstring == false && opt_molstat == false &&
1765
        opt_molstat_X == false && opt_xmdlout == false)
1766
      opt_none = true;
1767
  }
1768
  if (progmode == pmMatchMol) {
1769
    *ndl_molfilename = '\0';
1770
    *molfilename = '\0';
1771
    for (p = 1; p < P_argc; p++) {
1772
      strcpy(parstr, P_argv[p]);
1773
      if (p == 1) {
1774
        if (strpos2(parstr, "-", 1) == 1) {
1775
          if (strpos2(parstr, "v", 1) > 1)
1776
            opt_verbose = true;
1777
/* p2c: checkmol.pas, line 1329:
1778
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1779
          /*$IFDEF debug
1780
             if (strpos2(parstr, "D", 1) > 1)
1781
             opt_debug = true;
1782
             $ENDIF*/
1783
             if (strpos2(parstr, "x", 1) > 1)
1784
             opt_exact = true;
1785
             if (strpos2(parstr, "s", 1) > 1)   /* new in v0.2f */
1786
             opt_strict = true;
1787
             if (strpos2(parstr, "m", 1) > 1)
1788
             opt_molout = true;
1789
             if (strpos2(parstr, "r", 1) > 1)
1790
             opt_rs = rs_ssr;
1791
             if (strpos2(parstr, "M", 1) > 0)   /* new in v0.3 */
1792
             opt_metalrings = true;
1793
             if (strpos2(parstr, "g", 1) > 0)   /* new in v0.3d */
1794
             opt_geom = true;
1795
             if (strpos2(parstr, "G", 1) > 0)   /* new in v0.3f */
1796
             opt_chiral = true;
1797
             if (strpos2(parstr, "f", 1) > 0) {   /* new in v0.3m */
1798
             opt_fp = true;
1799
             fpformat = fpf_boolean;
1800
             }
1801
             if (strpos2(parstr, "F", 1) > 0) {   /* new in v0.3m */
1802
             opt_fp = true;
1803
             fpformat = fpf_decimal;
1804
             }
1805
             if (strpos2(parstr, "h", 1) > 1) {
1806
             show_usage();
1807
             _Escape(0);
1808
             }
1809
             } else
1810
             strcpy(ndl_molfilename, parstr);
1811
             }
1812
             if (p == P_argc - 2) {
1813
             if (strpos2(parstr, "-", 1) != 1)
1814
             strcpy(ndl_molfilename, parstr);
1815
             }
1816
             if (p == P_argc - 1) {
1817
             if (strcmp(parstr, "-"))
1818
             strcpy(molfilename, parstr);
1819
             else
1820
             opt_stdin = true;
1821
             }
1822
             }
1823
             if (opt_geom)   /* v0.3d */
1824
             ez_search = true;
1825
             if (opt_chiral)   /* v0.3f */
1826
             rs_search = true;
1827
             if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1828
             /* new in v0.3j, v0.3m */
1829
             rs_strict = true;
1830
             if (opt_fp) {   /* v0.3m */
1831
             opt_molout = false;
1832
             opt_exact = false;
1833
             }
1834
             }  /* progmode = pmMatchMol */
1835
             ringsearch_mode = opt_rs;   /* v0.3i */
1836
             }
1837
#endif
1838
 
1839
static void
1840
parse_args (int argc, char *argv[])
1841
{
1842
  short p;
1843
  char parstr[256];
1844
  char tmpstr[256];
1845
  short l;
1846
 
1847
  *tmpstr = '\0';
1848
  opt_none = true;
1849
  *molfilename = '\0';
1850
  *ndl_molfilename = '\0';
1851
  if (progmode == pmCheckMol)
1852
    {
1853
      for (p = 1; p <= argc - 1; p++)
1854
        {
1855
          strcpy (parstr, argv[p]);
1856
          if (!strcmp (parstr, "-l"))
1857
            {                   /* new in v0.3l */
1858
              list_molstat_codes ();
1859
              exit (0);
1860
            }
1861
          if (p < argc - 1)
1862
            {
1863
              if (strpos2 (parstr, "-", 1) == 1 && p < argc - 1)
1864
                {
1865
                  strcpy (tmpstr, argv[p]);
1866
                  left_trim (tmpstr);
1867
                  l = 0;
1868
                  if (strpos2 (tmpstr, "v", 1) > 0)
1869
                    l++;
1870
                  if (strpos2 (tmpstr, "D", 1) > 0)
1871
                    l++;
1872
                  if (strpos2 (tmpstr, "r", 1) > 0)
1873
                    l++;
1874
                  /*if (strpos2 (tmpstr, "a", 1) > 0)   // 0.3x
1875
                     l++; */
1876
                  if (strpos2 (tmpstr, "M", 1) > 0)     /* new in v0.3 */
1877
                    l++;
1878
                  if (strlen (tmpstr) > l + 2)
1879
                    {
1880
                      show_usage ();
1881
                      exit (1);
1882
                    }
1883
                  opt_none = false;
1884
                  if (strpos2 (tmpstr, "M", 1) > 0)
1885
                    opt_metalrings = true;
1886
                  if (strpos2 (tmpstr, "v", 1) > 0)
1887
                    opt_verbose = true;
1888
                  /*{$IFDEF debug
1889
                     if pos('D',tmpstr)>0 then opt_debug       := true;
1890
                     {$ENDIF */
1891
                  if (strpos2 (tmpstr, "e", 1) > 0)
1892
                    opt_text = true;
1893
                  else
1894
                    {
1895
                      if (strpos2 (tmpstr, "d", 1) > 0)
1896
                        opt_text_de = true;
1897
                      else
1898
                        {
1899
                          if (strpos2 (tmpstr, "c", 1) > 0)
1900
                            opt_code = true;
1901
                          else
1902
                            {
1903
                              if (strpos2 (tmpstr, "b", 1) > 0)
1904
                                opt_bin = true;
1905
                              else
1906
                                {
1907
                                  if (strpos2 (tmpstr, "s", 1) > 0)
1908
                                    opt_bitstring = true;
1909
                                }
1910
                            }
1911
                        }
1912
                      if (strpos2 (tmpstr, "x", 1) > 0)
1913
                        opt_molstat = true;
1914
                      if (strpos2 (tmpstr, "r", 1) > 0)
1915
                        opt_rs = rs_ssr;
1916
                      /* if (strpos2 (tmpstr, "a", 1) > 0)
1917
                         opt_chg = true; */ /* 0.3x  */
1918
                      if (strpos2 (tmpstr, "X", 1) > 0)
1919
                        {
1920
                          opt_molstat = true;
1921
                          opt_molstat_X = true;
1922
                        }
1923
                      if (strpos2 (tmpstr, "m", 1) > 0)
1924
                        {
1925
                          opt_text = false;
1926
                          opt_text_de = false;
1927
                          opt_bin = false;
1928
                          opt_bitstring = false;
1929
                          opt_code = false;
1930
                          opt_molstat = false;
1931
                          opt_xmdlout = true;
1932
                        }
1933
                    }
1934
                  strcpy (molfilename, tmpstr);
1935
                }
1936
            }
1937
          else
1938
            {
1939
              if (strpos2 (parstr, "-", 1) == 1)
1940
                {
1941
                  if (strlen (parstr) > 1)
1942
                    {
1943
                      show_usage ();
1944
                      exit (1);
1945
                    }
1946
                  opt_stdin = true;
1947
                }
1948
              else
1949
                {
1950
                  opt_stdin = false;
1951
                  strcpy (molfilename, parstr);
1952
                }
1953
            }
1954
        }
1955
      if (opt_text == false && opt_text_de == false && opt_code == false &&
1956
          opt_bin == false && opt_bitstring == false && opt_molstat == false
1957
          && opt_molstat_X == false && opt_xmdlout == false
1958
          && opt_chg == false)
1959
        opt_none = true;        /* 0.3x */
1960
    }
1961
  if (progmode == pmMatchMol)
1962
    {
1963
 
1964
      for (p = 1; p <= argc - 1; p++)
1965
        {
1966
          strcpy (parstr, argv[p]);
1967
          if (p == 1)
1968
            {
1969
              if (strpos2 (parstr, "-", 1) == 1)
1970
                {
1971
                  if (strpos2 (parstr, "v", 1) > 1)
1972
                    opt_verbose = true;
1973
                  /*{$IFDEF debug
1974
                     if pos('D',parstr)>1 then opt_debug       := true;
1975
                     {$ENDIF */
1976
                  if (strpos2 (parstr, "x", 1) > 1)
1977
                    opt_exact = true;
1978
                  if (strpos2 (parstr, "s", 1) > 1)     /* new in v0.2f */
1979
                    opt_strict = true;
1980
                  if (strpos2 (parstr, "m", 1) > 1)
1981
                    opt_molout = true;
1982
                  if (strpos2 (parstr, "r", 1) > 1)
1983
                    opt_rs = rs_ssr;
1984
                  if (strpos2 (parstr, "a", 1) > 0)
1985
                    opt_chg = true;     /* 0.3x */
1986
                  if (strpos2 (parstr, "i", 1) > 0)
1987
                    opt_iso = true;     /* 0.3x */
1988
                  if (strpos2 (parstr, "d", 1) > 0)
1989
                    opt_rad = true;     /* 0.3x */
1990
                  if (strpos2 (parstr, "M", 1) > 0)     /* new in v0.3 */
1991
                    opt_metalrings = true;
1992
                  if (strpos2 (parstr, "g", 1) > 0)     /* new in v0.3d */
1993
                    opt_geom = true;
1994
                  if (strpos2 (parstr, "G", 1) > 0)     /* new in v0.3f */
1995
                    opt_chiral = true;
1996
                  if (strpos2 (parstr, "f", 1) > 0)
1997
                    {           /* new in v0.3m */
1998
                      opt_fp = true;
1999
                      fpformat = fpf_boolean;
2000
                    }
2001
                  if (strpos2 (parstr, "F", 1) > 0)
2002
                    {           /* new in v0.3m */
2003
                      opt_fp = true;
2004
                      fpformat = fpf_decimal;
2005
                    }
2006
                  if (strpos2 (parstr, "h", 1) > 1)
2007
                    {
2008
                      show_usage ();
2009
                      exit (0);
2010
                    }
2011
                }
2012
              else
2013
                strcpy (ndl_molfilename, parstr);
2014
            }
2015
          if (p == argc - 2)
2016
            {
2017
              if (strpos2 (parstr, "-", 1) != 1)
2018
                strcpy (ndl_molfilename, parstr);
2019
            }
2020
          if (p == argc - 1)
2021
            {
2022
              if (strcmp (parstr, "-"))
2023
                strcpy (molfilename, parstr);
2024
              else
2025
                opt_stdin = true;
2026
            }
2027
        }
2028
      if (opt_geom)             /* v0.3d */
2029
        ez_search = true;
2030
      if (opt_chiral)           /* v0.3f */
2031
        rs_search = true;
2032
      if (opt_chiral && opt_strict && (opt_exact || opt_fp))
2033
        /* new in v0.3j, v0.3m  */
2034
        rs_strict = true;
2035
      if (opt_fp)
2036
        {                       /* v0.3m */
2037
          opt_molout = false;
2038
          opt_exact = false;
2039
        }
2040
    }                           /* progmode = pmMatchMol */
2041
  ringsearch_mode = opt_rs;     /* v0.3i */
2042
}
2043
 
2044
/*============== input-related functions & procedures ===================== */
2045
 
2046
static char *
2047
get_filetype (Result, f)
2048
     char *Result;
2049
     char *f;
2050
{
2051
  char rline[256];
2052
  char auxstr[256];
2053
  int i;
2054
  boolean mdl1 = false;
2055
  int ri;
2056
  int sepcount = 0;
2057
  char STR1[256], STR6[256], STR7[256];
2058
 
2059
  strcpy (auxstr, "unknown");
2060
  i = li;
2061
  ri = li - 1;
2062
  while (ri < molbufindex && sepcount < 1)
2063
    {
2064
      ri++;
2065
      strcpy (rline, molbuf[ri - 1]);
2066
      if (strpos2 (rline, "$$$$", 1) > 0)
2067
        sepcount++;
2068
      if ((i == li) && (strcmp (strsub (STR1, rline, 7, 5), "ATOMS") == 0) &&
2069
          (strcmp (strsub (STR6, rline, 20, 5), "BONDS") == 0) &&
2070
          (strcmp (strsub (STR7, rline, 33, 7), "CHARGES") == 0))
2071
        strcpy (auxstr, "alchemy");
2072
      if ((i == li + 3) && (strcmp (strsub (STR1, rline, 35, 5), "V2000") ==
2073
                            0))
2074
        /* and (copy(rline,31,3)='999') */
2075
        mdl1 = true;
2076
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 6), "-ISIS-") ==
2077
                            0))
2078
        mdl1 = true;
2079
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "WLViewer") ==
2080
                            0))
2081
        mdl1 = true;
2082
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CheckMol") ==
2083
                            0))
2084
        mdl1 = true;
2085
      if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CATALYST") ==
2086
                            0))
2087
        {
2088
          mdl1 = true;
2089
          strcpy (auxstr, "mdl");
2090
        }
2091
      if (strpos2 (rline, "M  END", 1) == 1 || mdl1)
2092
        strcpy (auxstr, "mdl");
2093
      if (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) > 0)
2094
        strcpy (auxstr, "sybyl");
2095
      i++;
2096
    }
2097
  /* new in v0.2j: try to identify non-conformant SD-files */
2098
  if (!strcmp (auxstr, "unknown") && sepcount > 0)
2099
    strcpy (auxstr, "mdl");
2100
  return strcpy (Result, auxstr);
2101
}
2102
 
2103
 
2104
static void
2105
zap_molecule ()
2106
{
2107
  /* try */
2108
  if (atom != NULL)
2109
    {
2110
      free (atom);
2111
      atom = NULL;              /* added in v0.3j */
2112
    }
2113
  if (bond != NULL)
2114
    {
2115
      free (bond);
2116
      bond = NULL;              /* added in v0.3j */
2117
    }
2118
  if (ring != NULL)
2119
    {
2120
      free (ring);
2121
      ring = NULL;              /* added in v0.3j */
2122
    }
2123
  if (ringprop != NULL)
2124
    {
2125
      free (ringprop);
2126
      ringprop = NULL;          /* added in v0.3j */
2127
    }
2128
  /* except
2129
     on e:Einvalidpointer do begin end;
2130
     end; */
2131
  n_atoms = 0;
2132
  n_bonds = 0;
2133
  n_rings = 0;
2134
}
2135
 
2136
 
2137
static void
2138
zap_needle ()
2139
{
2140
  /* try */
2141
  if (ndl_atom != NULL)
2142
    {
2143
      free (ndl_atom);
2144
      ndl_atom = NULL;          /* added in v0.3j */
2145
    }
2146
  if (ndl_bond != NULL)
2147
    {
2148
      free (ndl_bond);
2149
      ndl_bond = NULL;          /* added in v0.3j */
2150
    }
2151
  if (ndl_ring != NULL)
2152
    {
2153
      free (ndl_ring);
2154
      ndl_ring = NULL;          /* added in v0.3j */
2155
    }
2156
  if (ndl_ringprop != NULL)
2157
    {
2158
      free (ndl_ringprop);      /* fixed in v0.3g */
2159
      ndl_ringprop = NULL;      /* added in v0.3j */
2160
    }
2161
  /* except
2162
     on e:Einvalidpointer do begin end;
2163
     end; */
2164
  ndl_n_atoms = 0;
2165
  ndl_n_bonds = 0;
2166
  ndl_n_rings = 0;
2167
}
2168
 
2169
#if 0
2170
static void
2171
zap_tmp ()
2172
{
2173
  /* try */
2174
  if (tmp_atom != NULL)
2175
    {
2176
      free (tmp_atom);
2177
      tmp_atom = NULL;          /* added in v0.3j */
2178
    }
2179
  if (tmp_bond != NULL)
2180
    {
2181
      free (tmp_bond);
2182
      tmp_bond = NULL;          /* added in v0.3j */
2183
    }
2184
  if (tmp_ring != NULL)
2185
    {
2186
      free (tmp_ring);
2187
      tmp_ring = NULL;          /* added in v0.3j */
2188
    }
2189
  if (tmp_ringprop != NULL)
2190
    {
2191
      free (tmp_ringprop);      /* fixed in v0.3g */
2192
      tmp_ringprop = NULL;      /* added in v0.3j */
2193
    }
2194
  /* except
2195
     on e:Einvalidpointer do begin end;
2196
     end; */
2197
  tmp_n_atoms = 0;
2198
  tmp_n_bonds = 0;
2199
  tmp_n_rings = 0;
2200
}
2201
#endif
2202
 
2203
static boolean
2204
is_heavyatom (id)
2205
     int id;
2206
{
2207
  str2 el;
2208
 
2209
  strcpy (el, atom[id - 1].element);
2210
 
2211
  if (!strcmp (el, "DU") || !strcmp (el, "LP"))
2212
    return false;
2213
  /*if (progmode == pmCheckMol && !strcmp (el, "H ")
2214
     && atom[id - 1].nucleon_number < 2)
2215
     return false;               0.3x  */
2216
  if (!strcmp (el, "H "))       /* 0.3 p */
2217
    {
2218
      if (progmode == pmMatchMol && !opt_iso)
2219
        {
2220
          return false;
2221
        }
2222
      else
2223
        {
2224
          if (atom[id - 1].nucleon_number < 2)
2225
            return false;
2226
        }
2227
    }
2228
  return true;
2229
}
2230
 
2231
 
2232
static boolean
2233
ndl_alkene_C (ba)
2234
     int ba;
2235
{
2236
  /* new in v0.3f */
2237
  boolean res = false;
2238
  int i, ba2, FORLIM;
2239
 
2240
  if (ndl_n_atoms <= 0 || ndl_n_bonds <= 0)
2241
    return false;
2242
  FORLIM = ndl_n_bonds;
2243
  for (i = 0; i < FORLIM; i++)
2244
    {
2245
      if (ndl_bond[i].a1 == ba || ndl_bond[i].a2 == ba)
2246
        {
2247
          if (ndl_bond[i].a1 == ba)
2248
            ba2 = ndl_bond[i].a2;
2249
          else
2250
            ba2 = ndl_bond[i].a1;
2251
          if (!strcmp (ndl_atom[ba - 1].atype, "C2 ") &&
2252
              !strcmp (ndl_atom[ba2 - 1].atype, "C2 ")
2253
              && ndl_bond[i].btype == 'D' && ndl_bond[i].arom == false)
2254
            res = true;
2255
        }
2256
    }
2257
  return res;
2258
}
2259
 
2260
 
2261
static boolean
2262
is_metal (id)
2263
     int id;
2264
{
2265
  boolean r = false;
2266
  str2 el;
2267
 
2268
  strcpy (el, atom[id - 1].element);
2269
  if (!strcmp (el, "LI") || !strcmp (el, "NA") || !strcmp (el, "K ") ||
2270
      !strcmp (el, "RB") || !strcmp (el, "CS") || !strcmp (el, "BE") ||
2271
      !strcmp (el, "MG") || !strcmp (el, "CA") || !strcmp (el, "SR") ||
2272
      !strcmp (el, "BA") || !strcmp (el, "TI") || !strcmp (el, "ZR") ||
2273
      !strcmp (el, "CR") || !strcmp (el, "MO") || !strcmp (el, "MN") ||
2274
      !strcmp (el, "FE") || !strcmp (el, "CO") || !strcmp (el, "NI") ||
2275
      !strcmp (el, "PD") || !strcmp (el, "PT") || !strcmp (el, "SN") ||
2276
      !strcmp (el, "CU") || !strcmp (el, "AG") || !strcmp (el, "AU") ||
2277
      !strcmp (el, "ZN") || !strcmp (el, "CD") || !strcmp (el, "HG") ||
2278
      !strcmp (el, "AL") || !strcmp (el, "SN") || !strcmp (el, "PB") ||
2279
      !strcmp (el, "SB") || !strcmp (el, "BI"))
2280
/* p2c: checkmol.pas, line 1577:
2281
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 1686 [251] */
2282
    /* etc. etc. */
2283
    r = true;
2284
  return r;
2285
}
2286
 
2287
 
2288
static int
2289
get_nvalences (a_el)
2290
     char *a_el;
2291
{
2292
  /* changed name and position in v0.3m */
2293
  /* preliminary version; should be extended to element/atomtype */
2294
  int res = 1;
2295
 
2296
  if (!strcmp (a_el, "H "))
2297
    res = 1;
2298
  /*if (!strcmp (a_el, "D "))   // v0.3n
2299
     res = 1; */
2300
  if (!strcmp (a_el, "C "))
2301
    res = 4;
2302
  if (!strcmp (a_el, "N "))
2303
    res = 3;
2304
  if (!strcmp (a_el, "O "))
2305
    res = 2;
2306
  if (!strcmp (a_el, "S "))
2307
    res = 2;
2308
  if (!strcmp (a_el, "SE"))
2309
    res = 2;
2310
  if (!strcmp (a_el, "TE"))
2311
    res = 2;
2312
  if (!strcmp (a_el, "P "))
2313
    res = 3;
2314
  if (!strcmp (a_el, "F "))
2315
    res = 1;
2316
  if (!strcmp (a_el, "CL"))
2317
    res = 1;
2318
  if (!strcmp (a_el, "BR"))
2319
    res = 1;
2320
  if (!strcmp (a_el, "I "))
2321
    res = 1;
2322
  if (!strcmp (a_el, "AT"))
2323
    res = 1;
2324
  if (!strcmp (a_el, "B "))
2325
    res = 3;
2326
  if (!strcmp (a_el, "LI"))
2327
    res = 1;
2328
  if (!strcmp (a_el, "NA"))
2329
    res = 1;
2330
  if (!strcmp (a_el, "K "))
2331
    res = 1;
2332
  if (!strcmp (a_el, "CA"))
2333
    res = 2;
2334
  if (!strcmp (a_el, "SR"))
2335
    res = 2;
2336
  if (!strcmp (a_el, "MG"))
2337
    res = 2;
2338
  if (!strcmp (a_el, "FE"))
2339
    res = 3;
2340
  if (!strcmp (a_el, "MN"))
2341
    res = 2;
2342
  if (!strcmp (a_el, "HG"))
2343
    res = 2;
2344
  if (!strcmp (a_el, "SI"))
2345
    res = 4;
2346
  if (!strcmp (a_el, "SN"))
2347
    res = 4;
2348
  if (!strcmp (a_el, "ZN"))
2349
    res = 2;
2350
  if (!strcmp (a_el, "CU"))
2351
    res = 2;
2352
  if (!strcmp (a_el, "A "))
2353
    res = 4;
2354
  if (!strcmp (a_el, "Q "))
2355
    res = 4;
2356
  return res;
2357
}
2358
 
2359
 
2360
static char *
2361
convert_type (Result, oldtype)
2362
     char *Result;
2363
     char *oldtype;
2364
{
2365
  int i;
2366
  str3 newtype;
2367
 
2368
  sprintf (newtype, "%.3s", oldtype);
2369
  for (i = 0; i <= 2; i++)
2370
    newtype[i] = toupper (newtype[i]);
2371
  if (newtype[0] == '~')
2372
    strcpy (newtype, "VAL");
2373
  if (newtype[0] == '*')
2374
    strcpy (newtype, "STR");
2375
  return strcpy (Result, newtype);
2376
}
2377
 
2378
 
2379
static char *
2380
convert_sybtype (Result, oldtype)
2381
     char *Result;
2382
     char *oldtype;
2383
{
2384
  str3 newtype;
2385
 
2386
  /*  NewType := Copy(OldType,1,3); */
2387
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2388
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2389
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2390
  strcpy (newtype, "DU ");
2391
  if (!strcmp (oldtype, "H    "))
2392
    strcpy (newtype, "H  ");
2393
  if (!strcmp (oldtype, "C.ar "))
2394
    strcpy (newtype, "CAR");
2395
  if (!strcmp (oldtype, "C.2  "))
2396
    strcpy (newtype, "C2 ");
2397
  if (!strcmp (oldtype, "C.3  "))
2398
    strcpy (newtype, "C3 ");
2399
  if (!strcmp (oldtype, "C.1  "))
2400
    strcpy (newtype, "C1 ");
2401
  if (!strcmp (oldtype, "O.2  "))
2402
    strcpy (newtype, "O2 ");
2403
  if (!strcmp (oldtype, "O.3  "))
2404
    strcpy (newtype, "O3 ");
2405
  if (!strcmp (oldtype, "O.co2"))
2406
    strcpy (newtype, "O2 ");
2407
  if (!strcmp (oldtype, "O.spc"))
2408
    strcpy (newtype, "O3 ");
2409
  if (!strcmp (oldtype, "O.t3p"))
2410
    strcpy (newtype, "O3 ");
2411
  if (!strcmp (oldtype, "N.1  "))
2412
    strcpy (newtype, "N1 ");
2413
  if (!strcmp (oldtype, "N.2  "))
2414
    strcpy (newtype, "N2 ");
2415
  if (!strcmp (oldtype, "N.3  "))
2416
    strcpy (newtype, "N3 ");
2417
  if (!strcmp (oldtype, "N.pl3"))
2418
    strcpy (newtype, "NPL");
2419
  if (!strcmp (oldtype, "N.4  "))
2420
    strcpy (newtype, "N3+");
2421
  if (!strcmp (oldtype, "N.am "))
2422
    strcpy (newtype, "NAM");
2423
  if (!strcmp (oldtype, "N.ar "))
2424
    strcpy (newtype, "NAR");
2425
  if (!strcmp (oldtype, "F    "))
2426
    strcpy (newtype, "F  ");
2427
  if (!strcmp (oldtype, "Cl   "))
2428
    strcpy (newtype, "CL ");
2429
  if (!strcmp (oldtype, "Br   "))
2430
    strcpy (newtype, "BR ");
2431
  if (!strcmp (oldtype, "I    "))
2432
    strcpy (newtype, "I  ");
2433
  if (!strcmp (oldtype, "Al   "))
2434
    strcpy (newtype, "AL ");
2435
  if (!strcmp (oldtype, "ANY  "))
2436
    strcpy (newtype, "A  ");
2437
  if (!strcmp (oldtype, "Ca   "))
2438
    strcpy (newtype, "CA ");
2439
  if (!strcmp (oldtype, "Du   "))
2440
    strcpy (newtype, "DU ");
2441
  if (!strcmp (oldtype, "Du.C "))
2442
    strcpy (newtype, "DU ");
2443
  if (!strcmp (oldtype, "H.spc"))
2444
    strcpy (newtype, "H  ");
2445
  if (!strcmp (oldtype, "H.t3p"))
2446
    strcpy (newtype, "H  ");
2447
  if (!strcmp (oldtype, "HAL  "))
2448
    strcpy (newtype, "Cl ");
2449
  if (!strcmp (oldtype, "HET  "))
2450
    strcpy (newtype, "Q  ");
2451
  if (!strcmp (oldtype, "HEV  "))
2452
    strcpy (newtype, "DU ");
2453
  if (!strcmp (oldtype, "K    "))
2454
    strcpy (newtype, "K  ");
2455
  if (!strcmp (oldtype, "Li   "))
2456
    strcpy (newtype, "LI ");
2457
  if (!strcmp (oldtype, "LP   "))
2458
    strcpy (newtype, "LP ");
2459
  if (!strcmp (oldtype, "Na   "))
2460
    strcpy (newtype, "NA ");
2461
  if (!strcmp (oldtype, "P.3  "))
2462
    strcpy (newtype, "P3 ");
2463
  if (!strcmp (oldtype, "S.2  "))
2464
    strcpy (newtype, "S2 ");
2465
  if (!strcmp (oldtype, "S.3  "))
2466
    strcpy (newtype, "S3 ");
2467
  if (!strcmp (oldtype, "S.o  "))
2468
    strcpy (newtype, "SO ");
2469
  if (!strcmp (oldtype, "S.o2 "))
2470
    strcpy (newtype, "SO2");
2471
  if (!strcmp (oldtype, "Si   "))
2472
    strcpy (newtype, "SI ");
2473
  if (!strcmp (oldtype, "P.4  "))
2474
    strcpy (newtype, "P4 ");
2475
  return strcpy (Result, newtype);
2476
}
2477
 
2478
 
2479
static char *
2480
convert_MDLtype (Result, oldtype)
2481
     char *Result, *oldtype;
2482
{
2483
  str3 newtype;
2484
 
2485
  /*  NewType := Copy(OldType,1,3); */
2486
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2487
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2488
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2489
  strcpy (newtype, "DU ");
2490
  if (!strcmp (oldtype, "H  "))
2491
    strcpy (newtype, "H  ");
2492
  if (!strcmp (oldtype, "C  "))
2493
    strcpy (newtype, "C3 ");
2494
  if (!strcmp (oldtype, "O  "))
2495
    strcpy (newtype, "O2 ");
2496
  if (!strcmp (oldtype, "N  "))
2497
    strcpy (newtype, "N3 ");
2498
  if (!strcmp (oldtype, "F  "))
2499
    strcpy (newtype, "F  ");
2500
  if (!strcmp (oldtype, "Cl "))
2501
    strcpy (newtype, "CL ");
2502
  if (!strcmp (oldtype, "Br "))
2503
    strcpy (newtype, "BR ");
2504
  if (!strcmp (oldtype, "I  "))
2505
    strcpy (newtype, "I  ");
2506
  if (!strcmp (oldtype, "Al "))
2507
    strcpy (newtype, "AL ");
2508
  if (!strcmp (oldtype, "ANY"))
2509
    strcpy (newtype, "A  ");
2510
  if (!strcmp (oldtype, "Ca "))
2511
    strcpy (newtype, "CA ");
2512
  if (!strcmp (oldtype, "Du "))
2513
    strcpy (newtype, "DU ");
2514
  if (!strcmp (oldtype, "K  "))
2515
    strcpy (newtype, "K  ");
2516
  if (!strcmp (oldtype, "Li "))
2517
    strcpy (newtype, "LI ");
2518
  if (!strcmp (oldtype, "LP "))
2519
    strcpy (newtype, "LP ");
2520
  if (!strcmp (oldtype, "Na "))
2521
    strcpy (newtype, "NA ");
2522
  if (!strcmp (oldtype, "P  "))
2523
    strcpy (newtype, "P3 ");
2524
  if (!strcmp (oldtype, "S  "))
2525
    strcpy (newtype, "S3 ");
2526
  if (!strcmp (oldtype, "Si "))
2527
    strcpy (newtype, "SI ");
2528
  if (!strcmp (oldtype, "P  "))
2529
    strcpy (newtype, "P4 ");
2530
  if (!strcmp (oldtype, "A  "))
2531
    strcpy (newtype, "A  ");
2532
  if (!strcmp (oldtype, "Q  "))
2533
    strcpy (newtype, "Q  ");
2534
  return strcpy (Result, newtype);
2535
}
2536
 
2537
 
2538
static char *
2539
get_element (Result, oldtype)
2540
     char *Result;
2541
     char *oldtype;
2542
{
2543
  char elemstr[256];
2544
 
2545
  if (!strcmp (oldtype, "H   "))
2546
    strcpy (elemstr, "H ");
2547
  /* if (!strcmp (oldtype, "D   "))  // v0.3n
2548
     strcpy (elemstr, "D "); */
2549
  if (!strcmp (oldtype, "CAR "))
2550
    strcpy (elemstr, "C ");
2551
  if (!strcmp (oldtype, "C2  "))
2552
    strcpy (elemstr, "C ");
2553
  if (!strcmp (oldtype, "C3  "))
2554
    strcpy (elemstr, "C ");
2555
  if (!strcmp (oldtype, "C1  "))
2556
    strcpy (elemstr, "C ");
2557
  if (!strcmp (oldtype, "O2  "))
2558
    strcpy (elemstr, "O ");
2559
  if (!strcmp (oldtype, "O3  "))
2560
    strcpy (elemstr, "O ");
2561
  if (!strcmp (oldtype, "O2  "))
2562
    strcpy (elemstr, "O ");
2563
  if (!strcmp (oldtype, "O3  "))
2564
    strcpy (elemstr, "O ");
2565
  if (!strcmp (oldtype, "O3  "))
2566
    strcpy (elemstr, "O ");
2567
  if (!strcmp (oldtype, "N1  "))
2568
    strcpy (elemstr, "N ");
2569
  if (!strcmp (oldtype, "N2  "))
2570
    strcpy (elemstr, "N ");
2571
  if (!strcmp (oldtype, "N3  "))
2572
    strcpy (elemstr, "N ");
2573
  if (!strcmp (oldtype, "NPL "))
2574
    strcpy (elemstr, "N ");
2575
  if (!strcmp (oldtype, "N3+ "))
2576
    strcpy (elemstr, "N ");
2577
  if (!strcmp (oldtype, "NAM "))
2578
    strcpy (elemstr, "N ");
2579
  if (!strcmp (oldtype, "NAR "))
2580
    strcpy (elemstr, "N ");
2581
  if (!strcmp (oldtype, "F   "))
2582
    strcpy (elemstr, "F ");
2583
  if (!strcmp (oldtype, "CL  "))
2584
    strcpy (elemstr, "CL");
2585
  if (!strcmp (oldtype, "BR  "))
2586
    strcpy (elemstr, "BR");
2587
  if (!strcmp (oldtype, "I   "))
2588
    strcpy (elemstr, "I ");
2589
  if (!strcmp (oldtype, "AT  "))
2590
    strcpy (elemstr, "AT");
2591
  if (!strcmp (oldtype, "AL  "))
2592
    strcpy (elemstr, "AL");
2593
  if (!strcmp (oldtype, "DU  "))
2594
    strcpy (elemstr, "DU");
2595
  if (!strcmp (oldtype, "CA  "))
2596
    strcpy (elemstr, "CA");
2597
  if (!strcmp (oldtype, "DU  "))
2598
    strcpy (elemstr, "DU");
2599
  if (!strcmp (oldtype, "Cl  "))
2600
    strcpy (elemstr, "CL");
2601
  if (!strcmp (oldtype, "K   "))
2602
    strcpy (elemstr, "K ");
2603
  if (!strcmp (oldtype, "LI  "))
2604
    strcpy (elemstr, "LI");
2605
  if (!strcmp (oldtype, "LP  "))
2606
    strcpy (elemstr, "LP");
2607
  if (!strcmp (oldtype, "NA  "))
2608
    strcpy (elemstr, "NA");
2609
  if (!strcmp (oldtype, "P3  "))
2610
    strcpy (elemstr, "P ");
2611
  if (!strcmp (oldtype, "S2  "))
2612
    strcpy (elemstr, "S ");
2613
  if (!strcmp (oldtype, "S3  "))
2614
    strcpy (elemstr, "S ");
2615
  if (!strcmp (oldtype, "SO  "))
2616
    strcpy (elemstr, "S ");
2617
  if (!strcmp (oldtype, "SO2 "))
2618
    strcpy (elemstr, "S ");
2619
  if (!strcmp (oldtype, "SI  "))
2620
    strcpy (elemstr, "SI");
2621
  if (!strcmp (oldtype, "P4  "))
2622
    strcpy (elemstr, "P ");
2623
  if (!strcmp (oldtype, "A   "))
2624
    strcpy (elemstr, "A ");
2625
  if (!strcmp (oldtype, "Q   "))
2626
    strcpy (elemstr, "Q ");
2627
  return strcpy (Result, elemstr);
2628
}
2629
 
2630
 
2631
static char *
2632
get_sybelement (Result, oldtype)
2633
     char *Result;
2634
     char *oldtype;
2635
{
2636
  int i;
2637
  str2 elemstr;
2638
 
2639
  if (strpos2 (oldtype, ".", 1) < 2)
2640
    sprintf (elemstr, "%.2s", oldtype);
2641
  else
2642
    {
2643
      sprintf (elemstr, "%.*s", strpos2 (oldtype, ".", 1) - 1, oldtype);
2644
      if (strlen (elemstr) < 2)
2645
        strcat (elemstr, " ");
2646
    }
2647
  for (i = 0; i <= 1; i++)
2648
    elemstr[i] = toupper (elemstr[i]);
2649
  return strcpy (Result, elemstr);
2650
}
2651
 
2652
 
2653
static char *
2654
get_MDLelement (Result, oldtype)
2655
     char *Result;
2656
     char *oldtype;
2657
{
2658
  int i;
2659
  str2 elemstr;
2660
 
2661
  sprintf (elemstr, "%.2s", oldtype);
2662
  for (i = 0; i <= 1; i++)
2663
    elemstr[i] = toupper (elemstr[i]);
2664
  if (elemstr[0] == '~')
2665
    strcpy (elemstr, "??");
2666
  if (elemstr[0] == '*')
2667
    strcpy (elemstr, "??");
2668
  return strcpy (Result, elemstr);
2669
}
2670
 
2671
static void
2672
read_molfile (mfilename)
2673
     char *mfilename;
2674
{
2675
  /* reads ALCHEMY mol files */
6787 kbelabas 2676
  int n;
6785 bpr 2677
  char rline[256], tmpstr[256];
2678
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2679
  float xval, yval, zval, chgval;
2680
  char a1str[256], a2str[256], elemstr[256];
2681
  int a1val, a2val, ri;
2682
  char STR1[256];
2683
  int FORLIM;
2684
  atom_rec *WITH;
2685
  bond_rec *WITH1;
2686
 
2687
  if (n_atoms > 0)
2688
    zap_molecule ();
2689
  ri = li;
2690
  strcpy (rline, molbuf[ri - 1]);
2691
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2692
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2693
  strsub (tmpstr, rline, 14, 5);
6787 kbelabas 2694
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2695
  strsub (molname, rline, 42, (int) (strlen (rline) - 42L));
2696
  /* try */
2697
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2698
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2699
  ring = safe_calloc (1, sizeof (ringlist));
2700
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2701
  /* except
2702
     on e:Eoutofmemory do
2703
     begin
2704
     writeln('Not enough memory');
2705
     halt(4);
2706
     end;
2707
     end; */
2708
  n_heavyatoms = 0;
2709
  n_heavybonds = 0;
2710
  n_Ctot = 0;                   /* v0.3g */
2711
  n_Otot = 0;                   /* v0.3g */
2712
  n_Ntot = 0;                   /* v0.3g */
2713
  FORLIM = n_atoms;
2714
  for (n = 1; n <= FORLIM; n++)
2715
    {
2716
      ri++;
2717
      strcpy (rline, molbuf[ri - 1]);
2718
      strsub (atomtype, rline, 7, 4);
2719
      sprintf (STR1, "%c", toupper (*atomtype));
2720
      strcpy (atomtype, STR1);  /* fixed in v0.3f */
2721
      get_element (elemstr, atomtype);
2722
      if (!strcmp (elemstr, "C "))
2723
        n_Ctot++;
2724
      if (!strcmp (elemstr, "O "))
2725
        n_Otot++;
2726
      if (!strcmp (elemstr, "N "))
2727
        n_Ntot++;
2728
      convert_type (newatomtype, atomtype);
2729
      strsub (xstr, rline, 14, 7);
2730
      strsub (ystr, rline, 23, 7);
2731
      strsub (zstr, rline, 32, 7);
2732
      strsub (chgstr, rline, 43, 7);
6787 kbelabas 2733
      (void)sscanf (xstr, "%g", &xval);
2734
      (void)sscanf (ystr, "%g", &yval);
2735
      (void)sscanf (zstr, "%g", &zval);
2736
      (void)sscanf (chgstr, "%g", &chgval);
6785 bpr 2737
      WITH = &atom[n - 1];
2738
      strcpy (WITH->element, elemstr);
2739
      strcpy (WITH->atype, newatomtype);
2740
      WITH->x = xval;
2741
      WITH->y = yval;
2742
      WITH->z = zval;
2743
      WITH->real_charge = chgval;
2744
      if (is_heavyatom (n))
2745
        {
2746
          n_heavyatoms++;
2747
          WITH->heavy = true;
2748
          if (is_metal (n))
2749
            WITH->metal = true;
2750
        }
2751
      WITH->nvalences = get_nvalences (WITH->element);  /* v0.3m   */
2752
    }
2753
  /*
2754
     with atom^[n] do
2755
     begin
2756
     x := 0; y := 0; z := 0;  (* v0.3g
2757
     formal_charge  := 0;
2758
     real_charge    := 0;
2759
     Hexp           := 0;
2760
     Htot           := 0;
2761
     neighbor_count := 0;
2762
     ring_count     := 0;
2763
     arom           := false;
2764
     stereo_care    := false;
2765
     heavy          := false;
2766
     metal          := false;
2767
     tag            := false;
2768
     end;
2769
   */
2770
  FORLIM = n_bonds;
2771
  for (n = 0; n < FORLIM; n++)
2772
    {
2773
      ri++;
2774
      strcpy (rline, molbuf[ri - 1]);
2775
      strsub (a1str, rline, 9, 3);
2776
      strsub (a2str, rline, 15, 3);
6787 kbelabas 2777
      (void)sscanf(a1str, "%d", &a1val);
2778
      (void)sscanf(a2str, "%d", &a2val);
6785 bpr 2779
      WITH1 = &bond[n];
2780
      WITH1->a1 = a1val;
2781
      WITH1->a2 = a2val;
2782
      WITH1->btype = rline[19];
2783
      WITH1->ring_count = 0;
2784
      WITH1->arom = false;
2785
      WITH1->topo = btopo_any;
2786
      WITH1->stereo = bstereo_any;
2787
      WITH1->mdl_stereo = 0;    /* v0.3n */
2788
      if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2789
        n_heavybonds++;
2790
    }
2791
  memset (ring, 0, sizeof (ringlist));
2792
  for (n = 0; n < max_rings; n++)
2793
    {                           /* new in v0.3 */
2794
      ringprop[n].size = 0;
2795
      ringprop[n].arom = false;
2796
      ringprop[n].envelope = false;
2797
    }
2798
  li = ri + 1;
2799
}
2800
 
2801
 
2802
static void
2803
read_mol2file (mfilename)
2804
     char *mfilename;
2805
{
2806
  /* reads SYBYL mol2 files */
2807
  int n, code;
2808
  char sybatomtype[6];
2809
  char tmpstr[256], rline[256];
2810
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2811
  float xval, yval, zval, chgval;
2812
  char a1str[256], a2str[256], elemstr[256];
2813
  int a1val, a2val, ri, FORLIM;
2814
  atom_rec *WITH;
2815
  bond_rec *WITH1;
2816
 
2817
  if (n_atoms > 0)
2818
    zap_molecule ();
2819
  *rline = '\0';
2820
  ri = li - 1;
2821
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) == 0))
2822
    {
2823
      ri++;
2824
      strcpy (rline, molbuf[ri - 1]);
2825
    }
2826
  if (ri < molbufindex)
2827
    {
2828
      ri++;
2829
      strcpy (molname, molbuf[ri - 1]);
2830
    }
2831
  if (ri < molbufindex)
2832
    {
2833
      ri++;
2834
      strcpy (rline, molbuf[ri - 1]);
2835
    }
2836
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2837
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2838
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2839
  strsub (tmpstr, rline, 7, 5);
6787 kbelabas 2840
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2841
  /* try */
2842
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
2843
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2844
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2845
  ring = safe_calloc (1, sizeof (ringlist));
2846
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2847
  /* except
2848
     on e:Eoutofmemory do
2849
     begin
2850
     writeln('Not enough memory');
2851
     halt(4);
2852
     end;
2853
     end; */
2854
  n_heavyatoms = 0;
2855
  n_heavybonds = 0;
2856
  n_Ctot = 0;                   /* v0.3g */
2857
  n_Otot = 0;                   /* v0.3g */
2858
  n_Ntot = 0;                   /* v0.3g */
2859
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>ATOM", 1) == 0))
2860
    {
2861
      ri++;
2862
      strcpy (rline, molbuf[ri - 1]);
2863
    }
2864
  FORLIM = n_atoms;
2865
  for (n = 1; n <= FORLIM; n++)
2866
    {
2867
      /*
2868
         with atom^[n] do
2869
         begin
2870
         x := 0; y := 0; z := 0;  (* v0.3g
2871
         formal_charge  := 0;
2872
         real_charge    := 0;
2873
         Hexp           := 0;
2874
         Htot           := 0;
2875
         neighbor_count := 0;
2876
         ring_count     := 0;
2877
         arom           := false;
2878
         stereo_care    := false;
2879
         heavy          := false;
2880
         metal          := false;
2881
         tag            := false;
2882
         end;
2883
       */
2884
      if (ri < molbufindex)
2885
        {
2886
          ri++;
2887
          strcpy (rline, molbuf[ri - 1]);
2888
        }
2889
      strsub (sybatomtype, rline, 48, 5);
2890
      get_sybelement (elemstr, sybatomtype);
2891
      if (!strcmp (elemstr, "C "))
2892
        n_Ctot++;
2893
      if (!strcmp (elemstr, "O "))
2894
        n_Otot++;
2895
      if (!strcmp (elemstr, "N "))
2896
        n_Ntot++;
2897
      convert_sybtype (newatomtype, sybatomtype);
2898
      strsub (xstr, rline, 18, 9);
2899
      strsub (ystr, rline, 28, 9);
2900
      strsub (zstr, rline, 38, 9);
2901
      strsub (chgstr, rline, 70, 9);
6787 kbelabas 2902
      (void)sscanf (xstr, "%g", &xval);
2903
      (void)sscanf (ystr, "%g", &yval);
2904
      (void)sscanf (zstr, "%g", &zval);
2905
      (void)sscanf (chgstr, "%g", &chgval);
6785 bpr 2906
      WITH = &atom[n - 1];
2907
      strcpy (WITH->element, elemstr);
2908
      strcpy (WITH->atype, newatomtype);
2909
      WITH->x = xval;
2910
      WITH->y = yval;
2911
      WITH->z = zval;
2912
      WITH->real_charge = chgval;
2913
      if (is_heavyatom (n))
2914
        {
2915
          n_heavyatoms++;
2916
          WITH->heavy = true;
2917
          if (is_metal (n))
2918
            WITH->metal = true;
2919
        }
2920
      WITH->nvalences = get_nvalences (WITH->element);  /* v0.3m   */
2921
    }
2922
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>BOND", 1) == 0))
2923
    {
2924
      ri++;
2925
      strcpy (rline, molbuf[ri - 1]);
2926
    }
2927
  FORLIM = n_bonds;
2928
  for (n = 0; n < FORLIM; n++)
2929
    {
2930
      if (ri < molbufindex)
2931
        {
2932
          ri++;
2933
          strcpy (rline, molbuf[ri - 1]);
2934
        }
2935
      strsub (a1str, rline, 9, 3);
2936
      strsub (a2str, rline, 14, 3);
2937
      code = (sscanf (a1str, "%d", &a1val) == 0);
2938
      if (code != 0)
2939
        printf ("%s\007\n", rline);
2940
      code = (sscanf (a2str, "%d", &a2val) == 0);
2941
      if (code != 0)
2942
        printf ("%s\007\n", rline);
2943
      WITH1 = &bond[n];
2944
      WITH1->a1 = a1val;
2945
      WITH1->a2 = a2val;
2946
      if (rline[17] == '1')
2947
        WITH1->btype = 'S';
2948
      if (rline[17] == '2')
2949
        WITH1->btype = 'D';
2950
      if (rline[17] == '3')
2951
        WITH1->btype = 'T';
2952
      if (rline[17] == 'a')
2953
        WITH1->btype = 'A';
2954
      WITH1->ring_count = 0;
2955
      WITH1->arom = false;
2956
      WITH1->topo = btopo_any;
2957
      WITH1->stereo = bstereo_any;
2958
      WITH1->mdl_stereo = 0;    /* v0.3n */
2959
      if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2960
        n_heavybonds++;
2961
    }
2962
  memset (ring, 0, sizeof (ringlist));
2963
  for (n = 0; n < max_rings; n++)
2964
    {                           /* new in v0.3 */
2965
      ringprop[n].size = 0;
2966
      ringprop[n].arom = false;
2967
      ringprop[n].envelope = false;
2968
    }
2969
  li = ri + 1;
2970
}
2971
 
2972
 
2973
static void
2974
read_charges (chgstring_)
2975
     char *chgstring_;
2976
{
2977
  char chgstring[256];
2978
  int a_id, a_chg;
2979
  /* int n_chrg;*/
2980
 
2981
  /* typical example: a molecule with 2 cations + 1 anion */
2982
  /* M  CHG  3   8   1  10   1  11  -1 */
2983
  strcpy (chgstring, chgstring_);
2984
  if (strpos2 (chgstring, "M  CHG", 1) <= 0)
2985
    return;
2986
  strdelete (chgstring, 1, 6);
2987
  left_trim (chgstring);
2988
 /* n_chrg = left_int (chgstring);*/
2989
  /* this assignment must be kept also in non-debug mode! */
2990
/* p2c: checkmol.pas, line 2077:
2991
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
2992
  /*$IFDEF debug */
2993
  /*if (n_chrg == 0)
2994
     debugoutput ("strange... M  CHG present, but no charges found"); */
2995
  /*$ENDIF */
2996
  while (*chgstring != '\0')
2997
    {
2998
      a_id = left_int (chgstring);
2999
      a_chg = left_int (chgstring);
3000
      if (a_id != 0 && a_chg != 0)
3001
        atom[a_id - 1].formal_charge = a_chg;
3002
      //printf ("CHG %i %i\n", a_id, a_chg);
3003
    }
3004
}
3005
 
3006
static void
3007
read_isotopes (char *isotopestring_)
3008
{
3009
  char isotopestring[256];
3010
  int a_id, a_nucleon_number;
3011
  /* int n_isotopes;*/
3012
 
3013
  /* typical example: a molecule with 2 cations + 1 anion */
3014
  /* M  CHG  3   8   1  10   1  11  -1 */
3015
  strcpy (isotopestring, isotopestring_);
3016
  if (strpos2 (isotopestring, "M  ISO", 1) <= 0)
3017
    return;
3018
  strdelete (isotopestring, 1, 6);
3019
  left_trim (isotopestring);
3020
  /*n_isotopes = left_int (isotopestring);*/
3021
  /* this assignment must be kept also in non-debug mode! */
3022
/* p2c: checkmol.pas, line 2077:
3023
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3024
  /*$IFDEF debug */
3025
  /*if (n_chrg == 0)
3026
     debugoutput ("strange... M  CHG present, but no charges found"); */
3027
  /*$ENDIF */
3028
  while (*isotopestring != '\0')
3029
    {
3030
      a_id = left_int (isotopestring);
3031
      a_nucleon_number = left_int (isotopestring);
3032
      if (a_id != 0 && a_nucleon_number != 0)
3033
        {
3034
          atom[a_id - 1].nucleon_number = a_nucleon_number;
3035
          if (!strcmp (atom[a_id - 1].element, "H "))
3036
            {
3037
              atom[a_id - 1].heavy = true;
3038
              n_heavyatoms++;
3039
              strcpy (atom[a_id - 1].atype, "DU ");
3040
            }
3041
        }
3042
      //printf ("ISO %i %i\n", a_id, a_nucleon_number);
3043
    }
3044
}
3045
 
3046
static void
3047
read_radicals (radstring_)
3048
     char *radstring_;
3049
{
3050
  char radstring[256];
6788 kbelabas 3051
  int a_id, a_rad;
6785 bpr 3052
 
3053
  /* typical example: a molecule with 2 cations + 1 anion */
3054
  /* M  CHG  3   8   1  10   1  11  -1 */
3055
  strcpy (radstring, radstring_);
3056
  if (strpos2 (radstring, "M  RAD", 1) <= 0)
3057
    return;
3058
  strdelete (radstring, 1, 6);
3059
  left_trim (radstring);
6788 kbelabas 3060
  (void)left_int (radstring);
6785 bpr 3061
  /* this assignment must be kept also in non-debug mode! */
3062
/* p2c: checkmol.pas, line 2077:
3063
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3064
  /*$IFDEF debug */
3065
  /*if (n_chrg == 0)
3066
     debugoutput ("strange... M  CHG present, but no charges found"); */
3067
  /*$ENDIF */
3068
  while (*radstring != '\0')
3069
    {
3070
      a_id = left_int (radstring);
3071
      a_rad = left_int (radstring);
3072
      if (a_id != 0 && a_rad != 0)
3073
        atom[a_id - 1].radical_type = a_rad;
3074
      //printf ("RAD %i %i\n", a_id, a_rad);
3075
    }
3076
}
3077
 
3078
 
3079
static void
3080
read_MDLmolfile (char *mfilename)
3081
{
3082
  /* reads MDL mol files */
3083
  int n, v, tmp_n_atoms, tmp_n_bonds, code;     /* v0.3l */
3084
  char rline[256], tmpstr[256];
3085
  char xstr[256], ystr[256], zstr[256], chgstr[256];
3086
  float xval, yval, zval, chgval;
3087
  char a1str[256], a2str[256], elemstr[256];
3088
  int a1val, a2val, ri, rc, bt, bs;
3089
  int sepcount = 0;
3090
  int i;                        /* v0.3j */
3091
  boolean clearcharges = true;  /* v0.3j */
3092
  char STR1[256];
3093
/*  int FORLIM;*/
3094
  atom_rec *WITH;
3095
  bond_rec *WITH1;
3096
 
3097
  /* v0.3j */
3098
  if (n_atoms > 0)
3099
    zap_molecule ();
3100
  /*cm_mdlmolfile := false; */
3101
  *rline = '\0';
3102
  ri = li;
3103
  strcpy (molname, molbuf[ri - 1]);     /* line 1 */
3104
  if (ri < molbufindex)         /* line 2 */
3105
    ri++;
3106
  strcpy (rline, molbuf[ri - 1]);
3107
  if (strpos2 (rline, "CheckMol", 1) == 3)
3108
    {
3109
      /*cm_mdlmolfile := true; */
3110
      found_arominfo = true;
3111
      tmfcode = 1;              /* v0.3m (begin) */
3112
      code = 0;
3113
      if ((strlen (rline) >= 39) && (strpos2 (rline, "TMF", 1) == 35))
3114
        {                       /* v0.3m; encoding of tweaklevel */
3115
          strsub (tmpstr, rline, 38, 2);
3116
          code = (sscanf (tmpstr, "%d", &tmfcode) == 0);
3117
        }
3118
      if (code != 0 || tmfcode != tweaklevel)
3119
        tmfmismatch = true;
3120
      else
3121
        tmfmismatch = false;
3122
      if ((strpos2 (rline, ":r0", 1) >= 40 && ringsearch_mode != rs_sar) |
3123
          (strpos2 (rline, ":r1", 1) >= 40 && ringsearch_mode != rs_ssr))
3124
        tmfmismatch = true;
3125
      if ((strpos2 (rline, ":m0", 1) >= 40 && opt_metalrings == true) |
3126
          (strpos2 (rline, ":m1", 1) >= 40 && opt_metalrings == false))
3127
        tmfmismatch = true;
3128
/* p2c: checkmol.pas, line 2128:
3129
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3130
      /*$IFDEF debug */
3131
      //if (tmfmismatch)
3132
      //printf ("\"tweaked\" molfile: version mismatch!\n");
3133
      // else
3134
      //printf ("\"tweaked\" molfile: version OK");
3135
    }
3136
  /*$ENDIF */
3137
  /* v0.3m (end) */
3138
  if (ri < molbufindex)         /* line 3 */
3139
    ri++;
3140
  strcpy (rline, molbuf[ri - 1]);
3141
  strcpy (molcomment, rline);
3142
  if (ri < molbufindex)         /* line 4 */
3143
    ri++;
3144
  strcpy (rline, molbuf[ri - 1]);
3145
  sprintf (tmpstr, "%.3s", rline);
6787 kbelabas 3146
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 3147
  strsub (tmpstr, rline, 4, 3);
6787 kbelabas 3148
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 3149
  strsub (tmpstr, rline, 10, 3);
3150
  /* if it is a CheckMol-tweaked molfile, this is the number of rings */
3151
  n_cmrings = 0;
3152
  code = (sscanf (tmpstr, "%d", &n_cmrings) == 0);
3153
  if (code != 0)
3154
    n_cmrings = 0;
3155
  /* do some range checking for n_atoms, n_bonds; new in v0.3l */
3156
  tmp_n_atoms = n_atoms;
3157
  if (n_atoms > max_atoms)
3158
    n_atoms = max_atoms;
3159
  if (n_atoms < 0)
3160
    n_atoms = 0;
3161
  tmp_n_bonds = n_bonds;
3162
  if (n_bonds > max_bonds)
3163
    n_bonds = max_bonds;
3164
  if (n_bonds < 0)
3165
    n_bonds = 0;
3166
  if (n_atoms == 0
3167
#ifndef MAKE_SHARED_LIBRARY
3168
      && opt_verbose
3169
#endif
3170
    )
3171
    {                           /* v0.3l */
3172
      printf ("WARNING: Possible NoStruct read!\n");
3173
      printf ("NoStructs are proprietary, obsolete and dangerous.\n");
3174
    }
3175
  /* try */
3176
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
3177
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
3178
  /* this would be only one safe_calloc() in C;  v0.3l */
3179
  ring = safe_calloc (1, sizeof (ringlist));
3180
  ringprop = safe_calloc (1, sizeof (ringprop_type));
3181
  /* except
3182
     on e:Eoutofmemory do
3183
     begin
3184
     writeln('Not enough memory');
3185
     (* close(molfile);
3186
     halt(4);
3187
     exit;
3188
     end;
3189
     end; */
3190
  /* check for the chirality flag */
3191
  if (strlen (rline) > 14 && rline[14] == '1')  /* new in v0.3f */
3192
    chir_flag = true;
3193
  n_heavyatoms = 0;
3194
  n_heavybonds = 0;
3195
  n_Ctot = 0;                   /* v0.3g */
3196
  n_Otot = 0;                   /* v0.3g */
3197
  n_Ntot = 0;                   /* v0.3g */
3198
  if (n_atoms > 0)
3199
    {                           /* v0.3l */
3200
      for (n = 1; n <= tmp_n_atoms; n++)
3201
        {
3202
          if (n <= max_atoms)
3203
            v = n;
3204
          else
3205
            v = max_atoms;
3206
          /* just for safety; v0.3l */
3207
          /*
3208
             with atom^[v] do
3209
             begin
3210
             x := 0; y := 0; z := 0;  (* v0.3g
3211
             formal_charge  := 0;
3212
             real_charge    := 0;
3213
             Hexp           := 0;
3214
             Htot           := 0;
3215
             neighbor_count := 0;
3216
             ring_count     := 0;
3217
             arom           := false;
3218
             stereo_care    := false;
3219
             metal          := false;
3220
             heavy          := false;
3221
             tag            := false;
3222
             end;
3223
           */
3224
          /* replaced by fillchar() after getmem() (see above); v0.3l */
3225
          ri++;
3226
          strcpy (rline, molbuf[ri - 1]);
3227
          strsub (atomtype, rline, 32, 3);
3228
          get_MDLelement (elemstr, atomtype);
3229
          if (!strcmp (elemstr, "C "))
3230
            n_Ctot++;
3231
          if (!strcmp (elemstr, "O "))
3232
            n_Otot++;
3233
          if (!strcmp (elemstr, "N "))
3234
            n_Ntot++;
3235
 
3236
          convert_MDLtype (newatomtype, atomtype);
3237
          strsub (xstr, rline, 1, 10);  /* fixed in v0.3k (was: 2,9 etc.) */
3238
          strsub (ystr, rline, 11, 10);
3239
          strsub (zstr, rline, 21, 10);
3240
          /*chgstr := '0'; */
3241
          strsub (chgstr, rline, 37, 3);        /* new in v0.3j */
6787 kbelabas 3242
          (void)sscanf (chgstr, "%f", &chgval);
6785 bpr 3243
          if (chgval != 0)
3244
            {
3245
              if (chgval >= 1 && chgval <= 7)
3246
                chgval = 4.0 - chgval;
3247
              else
3248
                {
3249
                  chgval = 0.0;
3250
                }
3251
            }                   /* end (v0.3j) */
6787 kbelabas 3252
          (void)sscanf (xstr, "%f", &xval);
3253
          (void)sscanf (ystr, "%f", &yval);
3254
          (void)sscanf (zstr, "%f", &zval);
6785 bpr 3255
          /* v0.3k: removed superfluous val(chgstr,chgval,code) */
3256
          WITH = &atom[v - 1];
3257
          strcpy (WITH->element, elemstr);
3258
          if (!strcmp (elemstr, "A ") || !strcmp (elemstr, "Q ") ||
3259
              !strcmp (elemstr, "X "))
3260
            /* 'X ' added in v0.3n */
3261
            found_querymol = true;
3262
 
3263
          strcpy (WITH->atype, newatomtype);
3264
 
3265
 
3266
          if (!strcmp (elemstr, "D "))
3267
            {
3268
              strcpy (WITH->element, "H ");
3269
              WITH->nucleon_number = 2;
3270
            }                   /* 0.3x */
3271
          if (!strcmp (elemstr, "T "))
3272
            {
3273
              strcpy (WITH->element, "H ");
3274
              WITH->nucleon_number = 3;
3275
            }                   /* 0.3x */
3276
 
3277
 
3278
 
3279
          WITH->x = xval;
3280
          WITH->y = yval;
3281
          WITH->z = zval;
3282
          WITH->formal_charge = (long) floor (chgval + 0.5);
3283
          WITH->real_charge = 0.0;      /* v0.3j */
3284
          /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3285
          if (strlen (rline) > 37 && rline[37] == '0')
3286
            {
3287
              WITH->arom = true;
3288
              found_arominfo = true;
3289
            }
3290
          /* new in v0.3d: read stereo care flag */
3291
          if (strlen (rline) > 47 && rline[47] == '1')
3292
            WITH->stereo_care = true;
3293
          if (is_heavyatom (n))
3294
            {
3295
              n_heavyatoms++;
3296
              WITH->heavy = true;
3297
              if (is_metal (n))
3298
                WITH->metal = true;
3299
            }
3300
          WITH->nvalences = get_nvalences (WITH->element);
3301
          /* v0.3m                 */
3302
        }
3303
    }                           /* if (n_atoms > 0)... */
3304
  if (n_bonds > 0)
3305
    {                           /* v0.3l */
3306
      for (n = 1; n <= tmp_n_bonds; n++)
3307
        {
3308
          if (n <= max_bonds)
3309
            v = n;
3310
          else
3311
            v = max_bonds;
3312
          /* just for safety; v0.3l */
3313
          ri++;
3314
          strcpy (rline, molbuf[ri - 1]);
3315
          sprintf (a1str, "%.3s", rline);
3316
          strsub (a2str, rline, 4, 3);
3317
          code = (sscanf (a1str, "%d", &a1val) == 0);
3318
          if (code != 0)        /* v0.3l */
3319
            a1val = 1;
3320
          code = (sscanf (a2str, "%d", &a2val) == 0);
3321
          if (code != 0)        /* v0.3l */
3322
            a2val = 1;
3323
          WITH1 = &bond[v - 1];
3324
          WITH1->a1 = a1val;
3325
          WITH1->a2 = a2val;
3326
          if (rline[8] == '1')  /* single */
3327
            WITH1->btype = 'S';
3328
          if (rline[8] == '2')  /* double */
3329
            WITH1->btype = 'D';
3330
          if (rline[8] == '3')  /* triple */
3331
            WITH1->btype = 'T';
3332
          if (rline[8] == '4')  /* aromatic */
3333
            WITH1->btype = 'A';
3334
          if (rline[8] == '5')  /* single or double */
3335
            WITH1->btype = 'l';
3336
          if (rline[8] == '6')  /* single or aromatic */
3337
            WITH1->btype = 's';
3338
          if (rline[8] == '7')  /* double or aromatic */
3339
            WITH1->btype = 'd';
3340
          if (rline[8] == '8')  /* any */
3341
            WITH1->btype = 'a';
3342
          sprintf (STR1, "%c", WITH1->btype);
3343
          if (strpos2 ("lsda", STR1, 1) > 0)
3344
            found_querymol = true;
3345
          WITH1->arom = false;
3346
          WITH1->q_arom = false;        /* 0.3p */
3347
          /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3348
          if (WITH1->btype == 'A' || rline[7] == '0')
3349
            {
3350
              WITH1->arom = true;
3351
              if (rline[7] == '0')
3352
                found_arominfo = true;
3353
            }
3354
          strsub (tmpstr, rline, 13, 3);
3355
          /* new in v0.3d: read ring_count from tweaked molfile */
3356
          code = (sscanf (tmpstr, "%d", &rc) == 0);
3357
          if (code != 0 || rc < 0 || progmode == pmCheckMol || tmfmismatch)
3358
            WITH1->ring_count = 0;
3359
          else
3360
            WITH1->ring_count = rc;
3361
          /* v0.3n: added tmfmismatch check */
3362
          strsub (tmpstr, rline, 16, 3);        /* new in v0.3d: read bond topology; */
3363
          code = (sscanf (tmpstr, "%d", &bt) == 0);
3364
          /* extended features are encoded by leading zero */
3365
          if (code != 0 || (unsigned long) bt > 2)
3366
            WITH1->topo = btopo_any;
3367
          else
3368
            {
3369
              if (tmpstr[1] == '0')
3370
                WITH1->topo = bt + 3;
3371
              else
3372
                WITH1->topo = bt;
3373
            }
3374
          /* v0.3n changed >5 into >2 */
3375
          /* new in v0.3d: add stereo property from MDL "stereo care" flag in atom block */
3376
          WITH1->stereo = bstereo_any;
3377
          if (WITH1->btype == 'D')
3378
            {
3379
              if (atom[WITH1->a1 - 1].stereo_care
3380
                  && atom[WITH1->a2 - 1].stereo_care)
3381
                {               /* this is the MDL-conformant encoding, */
3382
                  WITH1->stereo = bstereo_xyz;  /* for an alternative see below */
3383
                  ez_flag = true;       /* v0.3f */
3384
                }
3385
              else
3386
                {               /* this extended feature is encoded by a leading zero */
3387
                  strsub (tmpstr, rline, 10, 3);
3388
                  /* new in v0.3d: read bond stereo specification; */
3389
                  code = (sscanf (tmpstr, "%d", &bs) == 0);
3390
                  WITH1->mdl_stereo = bs;       /* v0.3n */
3391
                  if (code != 0 || bs <= 0 || bs > 2)
3392
                    WITH1->stereo = bstereo_any;
3393
                  else
3394
                    WITH1->stereo = bstereo_xyz;
3395
                  if (tmpstr[1] == '0')
3396
                    WITH1->stereo = bstereo_xyz;
3397
                }
3398
            }
3399
          /*if stereo <> bstereo_any then ez_search := true; */
3400
          if (WITH1->stereo != bstereo_any)     /* changed in v0.3f */
3401
            ez_flag = true;
3402
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '1')
3403
            WITH1->stereo = bstereo_up;
3404
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '6')
3405
            WITH1->stereo = bstereo_down;
3406
          if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '4')
3407
            WITH1->stereo = bstereo_either;     /* 0.3x */
3408
          if (WITH1->btype == 'D' && strlen (rline) > 11 && rline[11] == '3')
3409
            WITH1->stereo = bstereo_double_either;      /* 0.3x */
3410
          strsub (tmpstr, rline, 10, 3);
3411
          /* new in v0.3n: save original bond stereo specification; */
6787 kbelabas 3412
          (void)sscanf (tmpstr, "%d", &bs);
6785 bpr 3413
          /* v0.3n */
3414
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3415
          WITH1->mdl_stereo = bs;       /* v0.3n */
3416
          if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
3417
            n_heavybonds++;
3418
        }
3419
    }                           /* if (n_bonds > 0)... */
3420
  while (ri < molbufindex && sepcount < 1)
3421
    {
3422
      ri++;
3423
      strcpy (rline, molbuf[ri - 1]);
3424
      if (strpos2 (rline, "M  CHG", 1) > 0)
3425
        {                       /* new in v0.3j */
3426
          if (clearcharges)
3427
            {                   /* "M  CHG" supersedes all "old-style" charge values */
3428
 
3429
              for (i = 0; i < n_atoms; i++)
3430
                atom[i].formal_charge = 0;
3431
            }
3432
          read_charges (rline);
3433
          clearcharges = false;
3434
          /* subsequent "M  CHG" lines must not clear previous values */
3435
        }
3436
 
3437
      if (strpos2 (rline, "M  ISO", 1) > 0)
3438
        read_isotopes (rline);  /* 0.3x */
3439
 
3440
      if (strpos2 (rline, "M  RAD", 1) > 0)
3441
        read_radicals (rline);  /* 0.3x */
3442
 
3443
      if (strpos2 (rline, "$$$$", 1) > 0)
3444
        {
3445
          sepcount++;
3446
          if (molbufindex > ri + 2)     /* we assume this is an SDF file */
3447
            mol_in_queue = true;
3448
        }
3449
    }
3450
  memset (ring, 0, sizeof (ringlist));
3451
  for (n = 0; n < max_rings; n++)
3452
    {                           /* new in v0.3 */
3453
      ringprop[n].size = 0;
3454
      ringprop[n].arom = false;
3455
      ringprop[n].envelope = false;
3456
    }
3457
  li = ri + 1;
3458
}
3459
 
3460
 
3461
 
3462
static void
3463
write_MDLmolfile ()
3464
{
3465
  int i;
3466
  char tmpstr[256];
3467
  char wline[256];
3468
  int a_chg;
3469
  int a_iso;
3470
  int a_rad;
3471
  char tmflabel[256];           /* v0.3m */
3472
  char STR1[256];
3473
  /*char STR7[256];*/
3474
  int FORLIM;
3475
 
3476
  sprintf (tmflabel, "%d", (int) tweaklevel);   /* v0.3m */
3477
  while (strlen (tmflabel) < 2) /* v0.3m */
3478
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
3479
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
3480
  if (strlen (molname) > 80)
3481
    sprintf (molname, "%.80s", strcpy (STR1, molname));
3482
  puts (molname);
3483
  printf ("  CheckMol                        %s", tmflabel);    /* v0.3m */
3484
  if (ringsearch_mode == rs_sar)        /* v0.3m */
3485
    printf (":r0");
3486
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
3487
    printf (":r1");
3488
  if (opt_metalrings)
3489
    printf (":m1");
3490
  else
3491
    printf (":m0");
3492
  /* v0.3m */
3493
  printf ("\n%s\n", molcomment);
3494
  *wline = '\0';
3495
  *tmpstr = '\0';
3496
  sprintf (tmpstr, "%d", n_atoms);
3497
  lblank (3L, tmpstr);
3498
  strcat (wline, tmpstr);
3499
  *tmpstr = '\0';               /* first 3 digits: number of atoms */
3500
  sprintf (tmpstr, "%d", n_bonds);
3501
  lblank (3L, tmpstr);
3502
  strcat (wline, tmpstr);
3503
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
3504
  strcpy (tmpstr, "  0");
3505
  strcat (wline, tmpstr);
3506
  *tmpstr = '\0';               /* next 3 digits: number of atom lists (not used by us) */
3507
/* p2c: checkmol.pas, line 2388:
3508
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3509
#ifdef REDUCED_SAR
3510
  sprintf (tmpstr, "%d", n_countablerings);
3511
  /* v0.3n; changed n_rings into n_countablerings */
3512
#else
3513
  sprintf (tmpstr, "%d", n_rings);
3514
#endif
3515
  lblank (3L, tmpstr);
3516
  strcat (wline, tmpstr);
3517
  *tmpstr = '\0';
3518
  /* officially "obsolete", we use it for the number of rings */
3519
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
3520
  if (chir_flag)
3521
    strcat (wline, "1");
3522
  else
3523
    strcat (wline, "0");
3524
  /* v0.3n */
3525
  strcat (wline, "               999 V2000");
3526
  /* v0.3n (adjust string length) */
3527
  puts (wline);
3528
  FORLIM = n_atoms;
3529
  for (i = 0; i < FORLIM; i++)
3530
    {
3531
      *wline = '\0';
3532
      sprintf (tmpstr, "%1.4f", atom[i].x);
3533
      lblank (10L, tmpstr);
3534
      strcat (wline, tmpstr);
3535
      sprintf (tmpstr, "%1.4f", atom[i].y);
3536
      lblank (10L, tmpstr);
3537
      strcat (wline, tmpstr);
3538
      sprintf (tmpstr, "%1.4f", atom[i].z);
3539
      lblank (10L, tmpstr);
3540
      strcat (wline, tmpstr);
3541
      strcpy (tmpstr, atom[i].element);
3542
      /* tmpstr := lowercase(tmpstr); REPLACE!!! */
3543
      //tmpstr[0] = toupper (tmpstr[0]);
3544
      all_lowercase (tmpstr);
3545
      tmpstr[0] = toupper (tmpstr[0]);
3546
      /*wline := wline + ' '+atom^[i].element+' '; */
3547
      sprintf (wline + strlen (wline), " %s ", tmpstr);
3548
      strcat (wline, " 0");     /* mass difference (isotopes) */
3549
      /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
3550
      if (atom[i].arom)
3551
        strcpy (tmpstr, " 00");
3552
      else
3553
        strcpy (tmpstr, "  0");
3554
      strcat (wline, tmpstr);
3555
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0");
3556
      puts (wline);
3557
    }
3558
  FORLIM = n_bonds;
3559
  for (i = 0; i < FORLIM; i++)
3560
    {
3561
      *wline = '\0';
3562
      sprintf (tmpstr, "%d", bond[i].a1);
3563
      lblank (3L, tmpstr);
3564
      strcat (wline, tmpstr);
3565
      sprintf (tmpstr, "%d", bond[i].a2);
3566
      lblank (3L, tmpstr);
3567
      strcat (wline, tmpstr);
3568
      if (bond[i].btype == 'S')
3569
        strcpy (tmpstr, "  1");
3570
      if (bond[i].btype == 'D')
3571
        strcpy (tmpstr, "  2");
3572
      if (bond[i].btype == 'T')
3573
        strcpy (tmpstr, "  3");
3574
      if (bond[i].btype == 'A')
3575
        strcpy (tmpstr, "  4");
3576
      if (bond[i].btype == 'l')
3577
        strcpy (tmpstr, "  5");
3578
      if (bond[i].btype == 's')
3579
        strcpy (tmpstr, "  6");
3580
      if (bond[i].btype == 'd')
3581
        strcpy (tmpstr, "  7");
3582
      if (bond[i].btype == 'a')
3583
        strcpy (tmpstr, "  8");
3584
      /* now encode our own aromaticity information */
3585
      if (bond[i].arom)
3586
        tmpstr[1] = '0';
3587
      strcat (wline, tmpstr);   /* next, encode bond stereo property (v0.3f) */
3588
      /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
3589
      /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
3590
      /*    wline := wline + '  0'; */
3591
      /* restore original value from MDL molfile (v0.3n) */
3592
      /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
3593
      *tmpstr = '\0';
3594
      sprintf (tmpstr, "%i", bond[i].mdl_stereo);
3595
      strcat (wline, "  ");
3596
      strcat (wline, tmpstr);
3597
      *tmpstr = '\0';
3598
      /* now encode the ring_count of this bond (using a field which officially is "not used") */
3599
      /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
3600
      sprintf (tmpstr, "%i", bond[i].ring_count);
3601
      while (strlen (tmpstr) < 3)
3602
        sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
3603
      sprintf (wline + strlen (wline), "%s  0  0", tmpstr);
3604
      puts (wline);
3605
    }
3606
  FORLIM = n_atoms;
3607
  for (i = 1; i <= FORLIM; i++)
3608
    {
3609
      a_chg = atom[i - 1].formal_charge;
3610
      if (a_chg != 0)
3611
        {
3612
          strcpy (wline, "M  CHG  1 ");
3613
          sprintf (tmpstr, "%d", i);
3614
          lblank (3L, tmpstr);
3615
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3616
          sprintf (tmpstr, "%d", a_chg);
3617
          lblank (3L, tmpstr);
3618
          strcat (wline, tmpstr);
3619
          puts (wline);
3620
        }
3621
    }
3622
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
3623
    {
3624
      a_iso = atom[i - 1].nucleon_number;
3625
      if (a_iso != 0)
3626
        {
3627
          strcpy (wline, "M  ISO  1 ");
3628
          sprintf (tmpstr, "%d", i);
3629
          lblank (3L, tmpstr);
3630
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3631
          sprintf (tmpstr, "%d", a_iso);
3632
          lblank (3L, tmpstr);
3633
          strcat (wline, tmpstr);
3634
          puts (wline);
3635
        }
3636
    }
3637
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
3638
    {
3639
      a_rad = atom[i - 1].radical_type;
3640
      if (a_rad != 0)
3641
        {
3642
          strcpy (wline, "M  RAD  1 ");
3643
          sprintf (tmpstr, "%d", i);
3644
          lblank (3L, tmpstr);
3645
          sprintf (wline + strlen (wline), "%s ", tmpstr);
3646
          sprintf (tmpstr, "%d", a_rad);
3647
          lblank (3L, tmpstr);
3648
          strcat (wline, tmpstr);
3649
          puts (wline);
3650
        }
3651
    }
3652
  printf ("M  END\n");
3653
}
3654
 
3655
 
3656
/*============= chemical processing functions && procedures ============ */
3657
 
3658
static boolean
3659
is_electroneg (a_el)
3660
     char *a_el;
3661
{
3662
  /* new in v0.3j */
3663
  boolean res = false;
3664
 
3665
  if (!strcmp (a_el, "N "))
3666
    res = true;
3667
  if (!strcmp (a_el, "P "))
3668
    res = true;
3669
  if (!strcmp (a_el, "O "))
3670
    res = true;
3671
  if (!strcmp (a_el, "S "))
3672
    res = true;
3673
  if (!strcmp (a_el, "SE"))
3674
    res = true;
3675
  if (!strcmp (a_el, "TE"))
3676
    res = true;
3677
  if (!strcmp (a_el, "F "))
3678
    res = true;
3679
  if (!strcmp (a_el, "CL"))
3680
    res = true;
3681
  if (!strcmp (a_el, "BR"))
3682
    res = true;
3683
  if (!strcmp (a_el, "I "))
3684
    res = true;
3685
  if (!strcmp (a_el, "AT"))
3686
    res = true;
3687
  return res;
3688
}
3689
 
3690
 
3691
static void
3692
count_neighbors ()
3693
{
3694
  /* counts heavy-atom neighbors and explicit hydrogens */
3695
  int i, FORLIM;
3696
 
3697
  if (n_atoms < 1 || n_bonds < 1)
3698
    return;
3699
  FORLIM = n_bonds;
3700
  for (i = 0; i < FORLIM; i++)
3701
    {
3702
      if (atom[bond[i].a1 - 1].heavy)
3703
        atom[bond[i].a2 - 1].neighbor_count++;
3704
      if (atom[bond[i].a2 - 1].heavy)
3705
        atom[bond[i].a1 - 1].neighbor_count++;
3706
      if (!strcmp (atom[bond[i].a1 - 1].element, "H "))
3707
        atom[bond[i].a2 - 1].Hexp++;
3708
      if (!strcmp (atom[bond[i].a2 - 1].element, "H "))
3709
        atom[bond[i].a1 - 1].Hexp++;
3710
      /* plausibility check (new in v02.i) */
3711
      if (atom[bond[i].a1 - 1].neighbor_count > max_neighbors ||
3712
          atom[bond[i].a2 - 1].neighbor_count > max_neighbors)
3713
        {
3714
          mol_OK = false;
3715
          /*writeln('invalid molecule!'); */
3716
        }
3717
    }
3718
}
3719
 
3720
 
3721
static void
3722
get_neighbors (Result, id)
3723
     int *Result;
3724
     int id;
3725
{
6786 kbelabas 3726
  int i;
6785 bpr 3727
  //neighbor_rec nb_tmp;
3728
  int nb_count = 0;
3729
  //int FORLIM = n_bonds;
3730
 
3731
  //memset (Result, 0, sizeof (neighbor_rec));
3732
 
6786 kbelabas 3733
  for (i = 0; i < n_bonds; i++)
6785 bpr 3734
    {
3735
      if (bond[i].a1 == id && atom[bond[i].a2 - 1].heavy
3736
          && nb_count < max_neighbors)
3737
        {
3738
          Result[nb_count++] = bond[i].a2;
3739
        }
3740
      if (bond[i].a2 == id && atom[bond[i].a1 - 1].heavy
3741
          && nb_count < max_neighbors)
3742
        {
3743
          Result[nb_count++] = bond[i].a1;
3744
        }
3745
    }
3746
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3747
}
3748
 
3749
 
3750
static void
3751
get_ndl_neighbors (int *Result, int id)
3752
{
3753
  int i;
3754
  //neighbor_rec nb_tmp;
3755
  int nb_count = 0;
3756
  /* v0.3i: use max_neighbors instead of a fixed value of 8 */
3757
  //int FORLIM = ndl_n_bonds;
3758
 
3759
  //memset (nb_tmp, 0, sizeof (neighbor_rec));
3760
 
3761
  for (i = 0; i < ndl_n_bonds; i++)
3762
    {
3763
      if (ndl_bond[i].a1 == id && nb_count < max_neighbors &&
3764
          ndl_atom[ndl_bond[i].a2 - 1].heavy)
3765
        {
3766
          nb_count++;
3767
          Result[nb_count - 1] = ndl_bond[i].a2;
3768
        }
3769
      if (ndl_bond[i].a2 == id && nb_count < max_neighbors &&
3770
          ndl_atom[ndl_bond[i].a1 - 1].heavy)
3771
        {
3772
          nb_count++;
3773
          Result[nb_count - 1] = ndl_bond[i].a1;
3774
        }
3775
    }
3776
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3777
}
3778
 
3779
 
3780
static int *
3781
get_nextneighbors (int *Result, int id, int prev_id)
3782
{
3783
  int i;
3784
  neighbor_rec nb_tmp;
3785
  int nb_count = 0;
3786
  int FORLIM;
3787
 
3788
  /* gets all neighbors except prev_id (usually the atom where we came from */
3789
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3790
  FORLIM = n_bonds;
3791
  for (i = 0; i < FORLIM; i++)
3792
    {
3793
      if (bond[i].a1 == id && bond[i].a2 != prev_id &&
3794
          nb_count < max_neighbors && atom[bond[i].a2 - 1].heavy)
3795
        {
3796
          nb_count++;
3797
          nb_tmp[nb_count - 1] = bond[i].a2;
3798
        }
3799
      if (bond[i].a2 == id && bond[i].a1 != prev_id &&
3800
          nb_count < max_neighbors && atom[bond[i].a1 - 1].heavy)
3801
        {
3802
          nb_count++;
3803
          nb_tmp[nb_count - 1] = bond[i].a1;
3804
        }
3805
    }
3806
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3807
}
3808
 
3809
 
3810
static int *
3811
get_ndl_nextneighbors (int *Result, int id, int prev_id)
3812
{
3813
  int i;
3814
  neighbor_rec nb_tmp;
3815
  int nb_count = 0;
3816
  int FORLIM;
3817
 
3818
  /* gets all neighbors except prev_id (usually the atom where we came from */
3819
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3820
  FORLIM = ndl_n_bonds;
3821
  for (i = 0; i < FORLIM; i++)
3822
    {
3823
      if (ndl_bond[i].a1 == id && ndl_bond[i].a2 != prev_id &&
3824
          nb_count < max_neighbors && ndl_atom[ndl_bond[i].a2 - 1].heavy)
3825
        {
3826
          nb_count++;
3827
          nb_tmp[nb_count - 1] = ndl_bond[i].a2;
3828
        }
3829
      if (ndl_bond[i].a2 == id && ndl_bond[i].a1 != prev_id &&
3830
          nb_count < max_neighbors && ndl_atom[ndl_bond[i].a1 - 1].heavy)
3831
        {
3832
          nb_count++;
3833
          nb_tmp[nb_count - 1] = ndl_bond[i].a1;
3834
        }
3835
    }
3836
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3837
}
3838
 
3839
#if 0
3840
static int path_pos (id, a_path) int id;
3841
     int *a_path;
3842
     {
3843
     /* new version in v0.3l */
3844
     int i;
3845
     int pp = 0;
3846
 
3847
     for (i = 1; i <= max_ringsize; i++)
3848
     {
3849
     if (a_path[i - 1] == id)
3850
     {
3851
     pp = i;
3852
     /* p2c: checkmol.pas, line 2620:
3853
     * Warning: Expected a '(', found a semicolon [227]  */
3854
     /* p2c: checkmol.pas, line 2620:
3855
     * Warning: Expected an expression, found a semicolon [227] */
3856
     fflush (0);
3857
     P_ioresult = 0;
3858
     }
3859
     }
3860
     return pp;
3861
     }
3862
#endif
3863
 
3864
static int
3865
matchpath_pos (int id, int *a_path)
3866
{
3867
  int i;
3868
  int pp = 0;
3869
 
3870
  for (i = max_matchpath_length; i >= 1; i--)
3871
    {
3872
      if (a_path[i - 1] == id)
3873
        pp = i;
3874
    }
3875
  return pp;
3876
}
3877
 
3878
 
3879
static int
3880
matchpath_length (int *a_path)
3881
{
3882
  if (a_path[max_matchpath_length - 1] != 0)
3883
    return max_matchpath_length;
3884
  else
3885
    return (matchpath_pos (0L, a_path) - 1);
3886
}
3887
 
3888
static int
3889
get_ndl_bond (int ba1, int ba2)
3890
{
3891
  int i;
3892
  int b_id = 0;
3893
  int FORLIM;
3894
 
3895
  if (ndl_n_bonds <= 0)
3896
    return b_id;
3897
  FORLIM = ndl_n_bonds;
3898
  for (i = 1; i <= FORLIM; i++)
3899
    {
3900
      if ((ndl_bond[i - 1].a1 == ba1 && ndl_bond[i - 1].a2 == ba2) ||
3901
          (ndl_bond[i - 1].a1 == ba2 && ndl_bond[i - 1].a2 == ba1))
3902
        b_id = i;
3903
    }
3904
  return b_id;
3905
}
3906
 
3907
static int
3908
ringcompare (int *rp1, int *rp2)
3909
{
3910
  int i, j;
3911
  int rc = 0;
3912
  int rs1, rs2;
3913
  int n_common = 0;
3914
  int max_cra;
3915
 
3916
  rs1 = path_length (rp1);
3917
  rs2 = path_length (rp2);
3918
  if (rs1 < rs2)
3919
    max_cra = rs1;
3920
  else
3921
    max_cra = rs2;
3922
  for (i = 0; i < rs1; i++)
3923
    {
3924
      for (j = 0; j < rs2; j++)
3925
        {
3926
          if (rp1[i] == rp2[j])
3927
            n_common++;
3928
        }
3929
    }
3930
  if (rs1 == rs2 && n_common == max_cra)
3931
    {
3932
      rc = 0;
3933
      return rc;
3934
    }
3935
  if (n_common == 0)
3936
    rc += 8;
3937
  if (n_common < max_cra)
3938
    {
3939
      rc += 4;
3940
      return rc;
3941
    }
3942
  if (rs1 < rs2)
3943
    rc++;
3944
  else
3945
    rc += 2;
3946
  return rc;
3947
}
3948
 
3949
 
3950
static boolean
3951
rc_identical (int rc_int)
3952
{
3953
  if (rc_int == 0)
3954
    return true;
3955
  else
3956
    return false;
3957
}
3958
 
3959
 
3960
static boolean
3961
rc_1in2 (int rc_int)
3962
{
3963
  if (rc_int & 1)
3964
    return true;
3965
  else
3966
    return false;
3967
}
3968
 
3969
 
3970
static boolean
3971
rc_2in1 (int rc_int)
3972
{
3973
  rc_int /= 2;
3974
  if (rc_int & 1)
3975
    return true;
3976
  else
3977
    return false;
3978
}
3979
 
3980
 
3981
#if 0
3982
static boolean
3983
rc_different (int rc_int)
3984
{
3985
  rc_int /= 4;
3986
  if (rc_int & 1)
3987
    return true;
3988
  else
3989
    return false;
3990
}
3991
#endif
3992
#if 0
3993
static boolean
3994
rc_independent (int rc_int)
3995
{
3996
  rc_int /= 8;
3997
  if (rc_int & 1)
3998
    return true;
3999
  else
4000
    return false;
4001
}
4002
#endif
4003
 
4004
static boolean
4005
is_newring (int *n_path)
4006
{
4007
  int i, j;
4008
  boolean nr = true;
4009
  boolean same_ring;
4010
  ringpath_type tmp_path;
4011
  int rc_result;
4012
  boolean found_ring;
4013
  int pl;                       /* new in v0.3 */
4014
  int FORLIM;
4015
 
4016
  pl = path_length (n_path);    /* new in v0.3 */
4017
  if (n_rings <= 0)
4018
    return true;
4019
  switch (ringsearch_mode)
4020
    {
4021
 
4022
    case rs_sar:
4023
      found_ring = false;
4024
      i = 0;
4025
      while (i < n_rings && !found_ring)
4026
        {
4027
          i++;
4028
          if (pl != ringprop[i - 1].size)       /* compare only rings of same size */
4029
            continue;
4030
          same_ring = true;
4031
          for (j = 0; j < max_ringsize; j++)
4032
            {
4033
              if (ring[i - 1][j] != n_path[j])
4034
                same_ring = false;
4035
            }
4036
          if (same_ring)
4037
            {
4038
              nr = false;
4039
              found_ring = true;
4040
            }
4041
        }
4042
      break;
4043
 
4044
    case rs_ssr:
4045
      FORLIM = n_rings;
4046
      for (i = 0; i < FORLIM; i++)
4047
        {
4048
          for (j = 0; j < max_ringsize; j++)
4049
            tmp_path[j] = ring[i][j];
4050
          rc_result = ringcompare (n_path, tmp_path);
4051
          if (rc_identical (rc_result))
4052
            nr = false;
4053
          if (rc_1in2 (rc_result))
4054
            {
4055
              /* exchange existing ring by smaller one */
4056
              for (j = 0; j < max_ringsize; j++)
4057
                ring[i][j] = n_path[j];
4058
              /* update ring property record (new in v0.3) */
4059
              ringprop[i].size = pl;
4060
              nr = false;
4061
/* p2c: checkmol.pas, line 2841:
4062
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4063
              /*$IFDEF debug */
4064
              /* debugoutput('replacing ring '+inttostr(i)+' by smaller one (ringsize: '+inttostr(path_length(n_path))+')'); */
4065
              /*$ENDIF */
4066
            }
4067
          if (rc_2in1 (rc_result))
4068
            {
4069
              /* new ring contains existing one, but is larger ==> discard */
4070
              nr = false;
4071
            }
4072
        }
4073
      break;
4074
    }
4075
  return nr;
4076
}
4077
 
4078
 
4079
static void
4080
add_ring (int *n_path)
4081
{
4082
  /* new in v0.3: store rings in an ordered way (with ascending ring size) */
4083
  int i;
4084
  int j = 0;
4085
  int k, s, pl;
4086
/* p2c: checkmol.pas, line 2862:
4087
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4088
  /*$IFDEF debug */
4089
  /*char dstr[256];*/
4090
  int FORLIM;
4091
 
4092
  /*$ENDIF */
4093
  pl = path_length (n_path);
4094
 
4095
  if (pl < 1)
4096
    return;
4097
 
4098
  if (n_rings >= max_rings)
4099
    {
4100
 
4101
/* p2c: checkmol.pas, line 2906:
4102
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4103
      /*$IFDEF debug
4104
         debugoutput ("max_rings exceeded!");
4105
         $ENDIF */
4106
      return;
4107
    }
4108
  n_rings++;
4109
 
4110
/* p2c: checkmol.pas, line 2871:
4111
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4112
  /*$IFDEF debug */
4113
  /* dstr := '';
4114
     for j := 1 to pl do dstr := dstr + inttostr((n_path[j])) + ' ';
4115
     debugoutput('adding ring '+inttostr(n_rings)+':  '+dstr); */
4116
  /*$ENDIF */
4117
  if (n_rings > 1)
4118
    {
4119
      FORLIM = n_rings;
4120
      for (i = 1; i < FORLIM; i++)
4121
        {
4122
          s = ringprop[i - 1].size;
4123
          if (pl >= s)
4124
            j = i;
4125
        }
4126
    }
4127
  j++;                          /* the next position is ours */
4128
  if (j < n_rings)
4129
    {                           /* push up the remaining rings by one position */
4130
      for (k = n_rings; k > j; k--)
4131
        {
4132
          ringprop[k - 1].size = ringprop[k - 2].size;
4133
          /*ringprop^[k].arom := ringprop^[(k-1)].arom; */
4134
          for (i = 0; i < max_ringsize; i++)
4135
            ring[k - 1][i] = ring[k - 2][i];
4136
        }
4137
    }
4138
  ringprop[j - 1].size = pl;
4139
  for (i = 0; i < max_ringsize; i++)
4140
    {
4141
      ring[j - 1][i] = n_path[i];
4142
      /*inc(atom^[(n_path[i])].ring_count); */
4143
    }
4144
}
4145
 
4146
 
4147
#if 0
4148
 static boolean is_ringpath (s_path) int *s_path;
4149
     {
4150
     boolean Result;
4151
     int i, j;
4152
     neighbor_rec nb;
4153
     boolean rp = false;
4154
     boolean new_atom;
4155
     int a_last, pl;
4156
     ringpath_type l_path;
4157
     int FORLIM;
4158
 
4159
     /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4160
     memset (nb, 0, sizeof (neighbor_rec));
4161
     memset (l_path, 0, sizeof (ringpath_type));
4162
     pl = path_length (s_path);
4163
     if (pl < 1)
4164
     {
4165
     /* p2c: checkmol.pas, line 2928:
4166
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4167
     /*$IFDEF debug
4168
     debugoutput ("Oops! Got zero-length s_path!");
4169
     $ENDIF */
4170
     return Result;
4171
     }
4172
     for (i = 0; i < pl; i++)
4173
     l_path[i] = s_path[i];
4174
     /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
4175
     if (opt_metalrings == false)
4176
     {
4177
     if (atom[l_path[pl - 1] - 1].metal)
4178
     {
4179
     /* p2c: checkmol.pas, line 2942:
4180
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4181
     /*$IFDEF debug
4182
     debugoutput ("skipping metal in ring search");
4183
     $ENDIF */
4184
     return false;
4185
     }
4186
     }
4187
     /* check if ring is already closed */
4188
     if (pl > 2 && l_path[pl - 1] == l_path[0])
4189
     {
4190
     l_path[pl - 1] = 0;        /* remove last entry (redundant!) */
4191
     order_ringpath (l_path);
4192
     if (is_newring (l_path))
4193
     {
4194
     if (n_rings >= max_rings)
4195
     {
4196
     /* p2c: checkmol.pas, line 2958:
4197
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4198
     /*$IFDEF debug
4199
     debugoutput ("maximum number of rings exceeded!");
4200
     $ENDIF */
4201
     return false;
4202
     }
4203
     add_ring (l_path);
4204
     }
4205
     /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4206
     return true;
4207
     }
4208
     /* any other case: ring is not (yet) closed */
4209
     a_last = l_path[pl - 1];
4210
     get_neighbors (nb, a_last);
4211
     if (atom[a_last - 1].neighbor_count <= 1)
4212
     return false;
4213
     if (n_rings >= max_rings)
4214
     /* added in v0.2: check if max_rings is reached **/
4215
     {                          /* if ring is not closed, continue searching */
4216
     return false;
4217
     }
4218
     FORLIM = atom[a_last - 1].neighbor_count;
4219
     for (i = 0; i < FORLIM; i++)
4220
     {
4221
     new_atom = true;
4222
     for (j = 1; j < pl; j++)
4223
     {
4224
     if (nb[i] == l_path[j])
4225
     {                    /* v0.3k */
4226
     new_atom = false;
4227
     /* p2c: checkmol.pas, line 2982:
4228
     * Warning: Expected a '(', found a semicolon [227] */
4229
     /* p2c: checkmol.pas, line 2982:
4230
     * Warning: Expected an expression, found a semicolon [227] */
4231
     fflush (0);
4232
     P_ioresult = 0;      /* v0.3k */
4233
     }
4234
     }
4235
     /* added in v0.1a: check if max_rings not yet reached */
4236
     /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
4237
     if (new_atom && pl < max_vringsize && n_rings < max_rings)
4238
     {
4239
     l_path[pl] = nb[i];
4240
     if (pl < max_ringsize - 1)   /* just to be sure */
4241
     l_path[pl + 1] = 0;
4242
     if (is_ringpath (l_path))
4243
     rp = true;
4244
     }
4245
     }
4246
     return rp;
4247
     }
4248
#endif
4249
 
4250
static boolean
4251
is_ringpath (int *s_path)
4252
{
4253
  int i, j;
4254
  neighbor_rec nb;
4255
  boolean rp = false;
4256
  boolean new_atom;
4257
  int a_last, pl;
4258
  ringpath_type l_path;
4259
  int FORLIM, pl_prev, pl_next, max_ringsize_dec;
4260
 
4261
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4262
  memset ((void *) nb, 0, sizeof (neighbor_rec));
4263
  memset ((void *) l_path, 0, sizeof (ringpath_type));
4264
  pl = path_length (s_path);
4265
  if (pl < 1)
4266
    {
4267
/* p2c: checkmol.pas, line 2524:
4268
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4269
 
4270
      return false;
4271
    }
4272
 
4273
  pl_prev = pl - 1;
4274
  //memcpy (l_path, s_path, sizeof (ringpath_type));
4275
  memcpy (l_path, s_path, pl * sizeof (int));
4276
 
4277
  /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
4278
  if (opt_metalrings == false)
4279
    {
4280
      if (atom[l_path[pl_prev] - 1].metal)
4281
        {
4282
/* p2c: checkmol.pas, line 2538:
4283
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4284
          return false;
4285
        }
4286
    }
4287
  /* check if ring is already closed */
4288
  if (pl > 2 && l_path[pl_prev] == l_path[0])
4289
    {
4290
      l_path[pl_prev] = 0;      /* remove last entry (redundant!) */
4291
      order_ringpath (l_path);
4292
      if (is_newring (l_path))
4293
        {
4294
          if (n_rings >= max_rings)
4295
            {
4296
/* p2c: checkmol.pas, line 2554:
4297
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
4298
 
4299
              return false;
4300
            }
4301
          add_ring (l_path);
4302
        }
4303
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4304
      return true;
4305
    }
4306
  /* any other case: ring is not (yet) closed */
4307
  a_last = l_path[pl_prev];
4308
  get_neighbors (nb, a_last);
4309
  if (atom[a_last - 1].neighbor_count <= 1)
4310
    return false;
4311
  if (n_rings >= max_rings)
4312
    /* added in v0.2: check if max_rings is reached */
4313
    {                           /* if ring is not closed, continue searching */
4314
      return false;
4315
    }
4316
  FORLIM = atom[a_last - 1].neighbor_count;
4317
  pl_next = pl + 1;
4318
  max_ringsize_dec = max_ringsize - 1;
4319
  for (i = 0; i < FORLIM; i++)
4320
    {
4321
      new_atom = true;
4322
      for (j = 1; j < pl; j++)
4323
        {
4324
          if (nb[i] == l_path[j])
4325
            {
4326
              new_atom = false;
4327
              break;
4328
            }
4329
        }
4330
      /* added in v0.1a: check if max_rings not yet reached */
4331
      /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
4332
      if (new_atom && pl < max_vringsize && n_rings < max_rings)
4333
        {
4334
          l_path[pl] = nb[i];
4335
          if (pl < max_ringsize_dec)    /* just to be sure */
4336
            l_path[pl_next] = 0;
4337
 
4338
          if (max_ringpath_recursion_depth != 0
4339
              && ++recursion_depth > max_ringpath_recursion_depth)
4340
            {
4341
#ifndef MAKE_SHARED_LIBRARY
4342
              if (opt_verbose)
4343
#endif
4344
                printf
4345
                  ("Warning: max. number of ringpath recursions (%i) reached\n",
4346
                   max_ringpath_recursion_depth);
4347
              n_rings = max_rings;
4348
              return false;
4349
            }
4350
 
4351
          /*printf("%i\n",recursion_depth);
4352
          fflush(stdout);*/
4353
 
4354
          if (is_ringpath (l_path))
4355
            rp = true;
4356
          /*return true;*/
4357
        }
4358
    }
4359
  return rp;
4360
}
4361
 
4362
static boolean
4363
is_ringbond (int b_id)
4364
{
4365
  int i, ra1, ra2;
4366
  neighbor_rec nb;
4367
  ringpath_type search_path;
4368
  boolean rb = false;
4369
  int FORLIM;
4370
 
4371
  recursion_depth = 0;
4372
 
4373
  ra1 = bond[b_id - 1].a1;
4374
  ra2 = bond[b_id - 1].a2;
4375
  memset (nb, 0, sizeof (neighbor_rec));
4376
  memset (search_path, 0, sizeof (ringpath_type));
4377
  get_neighbors (nb, ra2);
4378
  if (atom[ra2 - 1].neighbor_count <= 1 || atom[ra1 - 1].neighbor_count <= 1)
4379
    return false;
4380
  search_path[0] = ra1;
4381
  search_path[1] = ra2;
4382
  FORLIM = atom[ra2 - 1].neighbor_count;
4383
  for (i = 0; i < FORLIM; i++)
4384
    {
4385
      if (nb[i] != ra1 && atom[nb[i] - 1].heavy)
4386
        {
4387
          search_path[2] = nb[i];
4388
          if (is_ringpath (search_path))
4389
            rb = true;
4390
          //return true;
4391
        }
4392
    }
4393
  return rb;
4394
}
4395
 
4396
 
4397
static void
4398
chk_ringbonds ()
4399
{
4400
  int i, a1rc, a2rc;
4401
 
4402
  if (n_bonds < 1)
4403
    return;
4404
 
4405
  for (i = 0; i < n_bonds; i++)
4406
    {
4407
      a1rc = atom[bond[i].a1 - 1].ring_count;
4408
      a2rc = atom[bond[i].a2 - 1].ring_count;
4409
      if (n_rings == 0 || (a1rc < n_rings && a2rc < n_rings))
4410
        {
4411
          is_ringbond (i + 1);
4412
          /*inc(bond^[i].ring_count); */
4413
        }
4414
    }
4415
}
4416
 
4417
 
4418
/* v0.3d: moved procedure update_ringcount a bit down */
4419
 
4420
 
4421
static int
4422
raw_hetbond_count (int a)
4423
{
4424
  /* new in v0.2j, ignores bond order */
4425
  int i;
4426
  neighbor_rec nb;
4427
  str2 nb_el;
4428
  int hbc = 0;
4429
  int FORLIM;
4430
 
4431
  if (a <= 0 || a > n_atoms)
4432
    return hbc;
4433
  memset (nb, 0, sizeof (neighbor_rec));
4434
  get_neighbors (nb, a);
4435
  if (atom[a - 1].neighbor_count <= 0)
4436
    return hbc;
4437
  FORLIM = atom[a - 1].neighbor_count;
4438
  for (i = 0; i < FORLIM; i++)
4439
    {
4440
      strcpy (nb_el, atom[nb[i] - 1].element);
4441
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /* &&  strcmp (nb_el, "D ") */
4442
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4443
        /* added 'D ' in v0.3n */
4444
        hbc++;
4445
    }
4446
  return hbc;
4447
}
4448
 
4449
 
4450
static int
4451
hetbond_count (int a)
4452
{
4453
  int i;
4454
  neighbor_rec nb;
4455
  str2 nb_el;
4456
  float hbc = 0.0;
4457
  int FORLIM;
4458
 
4459
  if (a <= 0 || a > n_atoms)
4460
    return ((int) floor (hbc + 0.5));
4461
  memset (nb, 0, sizeof (neighbor_rec));
4462
  get_neighbors (nb, a);
4463
  if (atom[a - 1].neighbor_count <= 0)
4464
    return ((int) floor (hbc + 0.5));
4465
  FORLIM = atom[a - 1].neighbor_count;
4466
  for (i = 0; i < FORLIM; i++)
4467
    {
4468
      strcpy (nb_el, atom[nb[i] - 1].element);
4469
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /*&& strcmp (nb_el, "D ") */
4470
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4471
        {                       /* added 'D ' in v0.3n */
4472
          if (bond[get_bond (a, nb[i]) - 1].btype == 'S')
4473
            hbc += 1.0;
4474
          if (bond[get_bond (a, nb[i]) - 1].btype == 'A')
4475
            hbc += 1.5;
4476
          if (bond[get_bond (a, nb[i]) - 1].btype == 'D')
4477
            hbc += 2.0;
4478
          if (bond[get_bond (a, nb[i]) - 1].btype == 'T')
4479
            hbc += 3.0;
4480
        }
4481
    }
4482
  return ((int) floor (hbc + 0.5));
4483
}
4484
 
4485
 
4486
static int
4487
hetatom_count (int a)
4488
{
4489
  int i;
4490
  neighbor_rec nb;
4491
  str2 nb_el;
4492
  int hac = 0;
4493
  int FORLIM;
4494
 
4495
  if (a <= 0 || a > n_atoms)
4496
    return hac;
4497
  memset (nb, 0, sizeof (neighbor_rec));
4498
  get_neighbors (nb, a);
4499
  if (atom[a - 1].neighbor_count <= 0)
4500
    return hac;
4501
  FORLIM = atom[a - 1].neighbor_count;
4502
  for (i = 0; i < FORLIM; i++)
4503
    {
4504
      strcpy (nb_el, atom[nb[i] - 1].element);
4505
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4506
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4507
          && strcmp (nb_el, "DU"))
4508
        /* added 'D ' in v0.3n */
4509
        hac++;
4510
    }
4511
  return hac;
4512
}
4513
 
4514
#if 0
4515
static int
4516
ndl_hetbond_count (int a)
4517
{
4518
  int i;
4519
  neighbor_rec nb;
4520
  str2 nb_el;
4521
  float hbc = 0.0;
4522
  int FORLIM;
4523
 
4524
  if (a <= 0 || a > n_atoms)
4525
    return ((int) floor (hbc + 0.5));
4526
  memset (nb, 0, sizeof (neighbor_rec));
4527
  get_ndl_neighbors (nb, a);
4528
  if (ndl_atom[a - 1].neighbor_count <= 0)
4529
    return ((int) floor (hbc + 0.5));
4530
  FORLIM = ndl_atom[a - 1].neighbor_count;
4531
  for (i = 0; i < FORLIM; i++)
4532
    {
4533
      strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4534
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4535
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4536
          && strcmp (nb_el, "DU"))
4537
        {                       /* added 'D ' in v0.3n */
4538
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'S')
4539
            hbc += 1.0;
4540
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'A')
4541
            hbc += 1.5;
4542
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'D')
4543
            hbc += 2.0;
4544
          if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'T')
4545
            hbc += 3.0;
4546
        }
4547
    }
4548
  return ((int) floor (hbc + 0.5));
4549
}
4550
#endif
4551
 
4552
static int
4553
ndl_hetatom_count (int a)
4554
{
4555
  int i;
4556
  neighbor_rec nb;
4557
  str2 nb_el;
4558
  int hac = 0;
4559
  int FORLIM;
4560
 
4561
  if (a <= 0 || a > ndl_n_atoms)
4562
    return hac;
4563
  memset (nb, 0, sizeof (neighbor_rec));
4564
  get_ndl_neighbors (nb, a);
4565
  if (ndl_atom[a - 1].neighbor_count <= 0)
4566
    return hac;
4567
  FORLIM = ndl_atom[a - 1].neighbor_count;
4568
  for (i = 0; i < FORLIM; i++)
4569
    {                           /* note: query atoms like 'A' should be present only in the needle */
4570
      strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4571
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")  /*&&  strcmp (nb_el, "D ") */
4572
          && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4573
        /* added 'D ' in v0.3n */
4574
        hac++;
4575
    }
4576
  return hac;
4577
}
4578
 
4579
 
4580
static boolean
4581
is_oxo_C (int id)
4582
{
4583
  int i;
4584
  boolean r = false;
4585
  neighbor_rec nb;
4586
  int FORLIM;
4587
 
4588
  memset (nb, 0, sizeof (neighbor_rec));
4589
  if (id < 1 || id > n_atoms)
6786 kbelabas 4590
    return false;
6785 bpr 4591
  get_neighbors (nb, id);
4592
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4593
    return false;
4594
  FORLIM = atom[id - 1].neighbor_count;
4595
  for (i = 0; i < FORLIM; i++)
4596
    {
4597
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4598
          !strcmp (atom[nb[i] - 1].element, "O "))
4599
        /* no N, amidines are different... */
4600
        r = true;
4601
      /* or
4602
         (atom^[(nb[i])].element = 'S ')  or
4603
         (atom^[(nb[i])].element = 'SE') */
4604
    }
4605
  return r;
4606
}
4607
 
4608
 
4609
static boolean
4610
is_thioxo_C (int id)
4611
{
4612
  int i;
4613
  boolean r = false;
4614
  neighbor_rec nb;
4615
  int FORLIM;
4616
 
4617
  memset (nb, 0, sizeof (neighbor_rec));
4618
  if (id < 1 || id > n_atoms)
6786 kbelabas 4619
    return false;
6785 bpr 4620
  get_neighbors (nb, id);
4621
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4622
    return false;
4623
  FORLIM = atom[id - 1].neighbor_count;
4624
  for (i = 0; i < FORLIM; i++)
4625
    {
4626
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4627
          (!strcmp (atom[nb[i] - 1].element, "S ") ||
4628
           !strcmp (atom[nb[i] - 1].element, "SE")))
4629
        /* no N, amidines are different... */
4630
        r = true;
4631
    }
4632
  return r;
4633
}
4634
 
4635
 
4636
static boolean
4637
is_imino_C (int id)
4638
{
4639
  int i;
4640
  boolean r = false;
4641
  neighbor_rec nb;
4642
  int FORLIM;
4643
 
4644
  memset (nb, 0, sizeof (neighbor_rec));
4645
  if (id < 1 || id > n_atoms)
6786 kbelabas 4646
    return false;
6785 bpr 4647
  get_neighbors (nb, id);
4648
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4649
    return false;
4650
  FORLIM = atom[id - 1].neighbor_count;
4651
  for (i = 0; i < FORLIM; i++)
4652
    {
4653
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4654
          !strcmp (atom[nb[i] - 1].element, "N "))
4655
        r = true;
4656
    }
4657
  return r;
4658
}
4659
 
4660
 
4661
static boolean
4662
is_true_imino_C (int id)
4663
{
4664
  int i;
4665
  boolean r = true;
4666
  neighbor_rec nb;
4667
  str2 nb_el;
4668
  int a_n = 0;
4669
  int b;                        /* v0.3j */
4670
  int FORLIM;
4671
 
4672
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4673
  memset (nb, 0, sizeof (neighbor_rec));
4674
  if (id < 1 || id > n_atoms)
6786 kbelabas 4675
    return false;
6785 bpr 4676
  get_neighbors (nb, id);
4677
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4678
    return false;
4679
  FORLIM = atom[id - 1].neighbor_count;
4680
  for (i = 0; i < FORLIM; i++)
4681
    {
4682
      b = get_bond (id, nb[i]); /* v0.3j */
4683
      if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4684
          !strcmp (atom[nb[i] - 1].element, "N "))
4685
        /* v0.3j */
4686
        a_n = nb[i];
4687
    }
4688
  if (a_n <= 0)
4689
    return false;
4690
  memset (nb, 0, sizeof (neighbor_rec));
4691
  get_neighbors (nb, a_n);
4692
  FORLIM = atom[a_n - 1].neighbor_count;
4693
  for (i = 0; i < FORLIM; i++)
4694
    {
4695
      strcpy (nb_el, atom[nb[i] - 1].element);
4696
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4697
          /*&&  strcmp (nb_el, "D ") */ )
4698
        /* v0.3n: D */
4699
        r = false;
4700
    }
4701
  return r;
4702
}
4703
 
4704
 
4705
static boolean
4706
is_true_exocyclic_imino_C (int id, int r_id)
4707
{
4708
  /* v0.3j */
4709
  boolean Result;
4710
  int i, j;
4711
  boolean r = false;
4712
  neighbor_rec nb;
4713
  ringpath_type testring;
4714
  int ring_size, b, FORLIM;
4715
 
4716
  memset (nb, 0, sizeof (neighbor_rec));
4717
  if (id < 1 || id > n_atoms)
4718
    return Result;
4719
  get_neighbors (nb, id);
4720
  memset (testring, 0, sizeof (ringpath_type));
4721
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4722
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4723
    testring[j] = ring[r_id - 1][j];
4724
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4725
    return false;
4726
  FORLIM = atom[id - 1].neighbor_count;
4727
  for (i = 0; i < FORLIM; i++)
4728
    {
4729
      b = get_bond (id, nb[i]);
4730
      if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4731
          !strcmp (atom[nb[i] - 1].element, "N "))
4732
        {
4733
          r = true;
4734
          for (j = 0; j < ring_size; j++)
4735
            {
4736
              if (nb[i] == ring[r_id - 1][j])
4737
                r = false;
4738
            }
4739
        }
4740
    }
4741
  return r;
4742
}
4743
 
4744
 
4745
static boolean
4746
is_exocyclic_imino_C (int id, int r_id)
4747
{
4748
  boolean Result;
4749
  int i, j;
4750
  boolean r = false;
4751
  neighbor_rec nb;
4752
  ringpath_type testring;
4753
  int ring_size, FORLIM;
4754
 
4755
  memset (nb, 0, sizeof (neighbor_rec));
4756
  if (id < 1 || id > n_atoms)
4757
    return Result;
4758
  get_neighbors (nb, id);
4759
  memset (testring, 0, sizeof (ringpath_type));
4760
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4761
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4762
    testring[j] = ring[r_id - 1][j];
4763
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4764
    return false;
4765
  FORLIM = atom[id - 1].neighbor_count;
4766
  for (i = 0; i < FORLIM; i++)
4767
    {
4768
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4769
          !strcmp (atom[nb[i] - 1].element, "N "))
4770
        {
4771
          r = true;
4772
          for (j = 0; j < ring_size; j++)
4773
            {
4774
              if (nb[i] == ring[r_id - 1][j])
4775
                r = false;
4776
            }
4777
        }
4778
    }
4779
  return r;
4780
}
4781
 
4782
 
4783
static int
4784
find_exocyclic_methylene_C (int id, int r_id)
4785
{
4786
  /* renamed and rewritten in v0.3j */
4787
  int i, j;
4788
  int r = 0;
4789
  neighbor_rec nb;
4790
  ringpath_type testring;
4791
  int ring_size, FORLIM;
4792
 
4793
  memset (nb, 0, sizeof (neighbor_rec));
4794
  if (id < 1 || id > n_atoms)
4795
    return 0;
4796
  get_neighbors (nb, id);
4797
  memset (testring, 0, sizeof (ringpath_type));
4798
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4799
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4800
    testring[j] = ring[r_id - 1][j];
4801
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4802
    return r;
4803
  FORLIM = atom[id - 1].neighbor_count;
4804
  for (i = 0; i < FORLIM; i++)
4805
    {
4806
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4807
          !strcmp (atom[nb[i] - 1].element, "C "))
4808
        {
4809
          r = nb[i];
4810
          for (j = 0; j < ring_size; j++)
4811
            {
4812
              if (nb[i] == ring[r_id - 1][j])
4813
                r = 0;
4814
            }
4815
        }
4816
    }
4817
  return r;
4818
}
4819
 
4820
 
4821
static boolean
4822
is_hydroxy (int a_view, int a_ref)
4823
{
4824
  boolean r = false;
4825
 
4826
  if (atom[a_view - 1].
4827
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4828
    {
4829
      if (!strcmp (atom[a_ref - 1].atype, "O3 ") &&
4830
          atom[a_ref - 1].neighbor_count == 1)
4831
        r = true;
4832
    }
4833
  return r;
4834
}
4835
 
4836
 
4837
static boolean
4838
is_sulfanyl (int a_view, int a_ref)
4839
{
4840
  boolean r = false;
4841
 
4842
  if (atom[a_view - 1].
4843
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4844
    {
4845
      if (!strcmp (atom[a_ref - 1].atype, "S3 ") &&
4846
          atom[a_ref - 1].neighbor_count == 1)
4847
        r = true;
4848
    }
4849
  return r;
4850
}
4851
 
4852
 
4853
static boolean
4854
is_amino (int a_view, int a_ref)
4855
{
4856
  boolean r = false;
4857
 
4858
  if (atom[a_view - 1].
4859
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4860
    {
4861
      if ((!strcmp (atom[a_ref - 1].atype, "N3 ") ||
4862
           !strcmp (atom[a_ref - 1].atype, "N3+")) &&
4863
          atom[a_ref - 1].neighbor_count == 1)
4864
        r = true;
4865
    }
4866
  return r;
4867
}
4868
 
4869
 
4870
static boolean
4871
is_alkyl (int a_view, int a_ref)
4872
{
4873
  int i;
4874
  boolean r = false;
4875
  neighbor_rec nb;
4876
  str2 nb_el;
4877
  int het_count = 0;
4878
  int FORLIM;
4879
 
4880
  memset (nb, 0, sizeof (neighbor_rec));
4881
  if (!
4882
      (atom[a_view - 1].
4883
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4884
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4885
      || atom[a_ref - 1].arom != false)
4886
    return false;
4887
  get_nextneighbors (nb, a_ref, a_view);
4888
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4889
  for (i = 0; i <= FORLIM; i++)
4890
    {
4891
      strcpy (nb_el, atom[nb[i] - 1].element);
4892
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4893
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4894
          && strcmp (nb_el, "LP"))
4895
        /* added 'D ' in v0.3n */
4896
        het_count++;
4897
    }
4898
  if (het_count <= 1)           /* we consider (e.g.) alkoxyalkyl groups as alkyl */
4899
    r = true;
4900
  return r;
4901
}
4902
 
4903
 
4904
static boolean
4905
is_true_alkyl (int a_view, int a_ref)
4906
{
4907
  int i;
4908
  boolean r = false;
4909
  neighbor_rec nb;
4910
  str2 nb_el;
4911
  int het_count = 0;
4912
  int FORLIM;
4913
 
4914
  memset (nb, 0, sizeof (neighbor_rec));
4915
  if (!
4916
      (atom[a_view - 1].
4917
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4918
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4919
      || atom[a_ref - 1].arom != false)
4920
    return false;
4921
  get_nextneighbors (nb, a_ref, a_view);
4922
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4923
  for (i = 0; i <= FORLIM; i++)
4924
    {
4925
      strcpy (nb_el, atom[nb[i] - 1].element);
4926
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4927
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
4928
        /* added 'D ' in v0.3n */
4929
        het_count++;
4930
    }
4931
  if (het_count == 0)           /* */
4932
    r = true;
4933
  return r;
4934
}
4935
 
4936
 
4937
static boolean
4938
is_alkenyl (int a_view, int a_ref)
4939
{
4940
  /* new in v0.3j */
4941
  int i;
4942
  boolean r = false;
4943
  neighbor_rec nb;
4944
  str2 nb_el;
4945
  str3 nb_at;
4946
  int c2_count = 0, het_count = 0;
4947
  int FORLIM;
4948
 
4949
  memset (nb, 0, sizeof (neighbor_rec));
4950
  if (!
4951
      (atom[a_view - 1].
4952
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4953
      || strcmp (atom[a_ref - 1].atype, "C2 ")
4954
      || atom[a_ref - 1].arom != false)
4955
    {
4956
      return false;
4957
    }                           /* v0.3k: changed c2_count = 1 into c2_count >= 1 */
4958
  get_nextneighbors (nb, a_ref, a_view);
4959
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4960
  for (i = 0; i <= FORLIM; i++)
4961
    {
4962
      strcpy (nb_el, atom[nb[i] - 1].element);
4963
      strcpy (nb_at, atom[nb[i] - 1].atype);
4964
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4965
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4966
          && strcmp (nb_el, "LP"))
4967
        /* added 'D ' in v0.3n */
4968
        het_count++;
4969
      if (!strcmp (nb_at, "C2 "))
4970
        c2_count++;
4971
    }
4972
  if (c2_count >= 1 && het_count <= 1)
4973
    /* we consider (e.g.) alkoxyalkenyl groups as alkenyl */
4974
    r = true;
4975
  return r;
4976
}
4977
 
4978
 
4979
static boolean
4980
is_alkynyl (int a_view, int a_ref)
4981
{
4982
  /* new in v0.3j */
4983
  int i;
4984
  boolean r = false;
4985
  neighbor_rec nb;
4986
  str3 nb_at;
4987
  int c1_count = 0;
4988
  int FORLIM;
4989
 
4990
  memset (nb, 0, sizeof (neighbor_rec));
4991
  if (!
4992
      (atom[a_view - 1].
4993
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4994
      || strcmp (atom[a_ref - 1].atype, "C1 ")
4995
      || atom[a_ref - 1].arom != false)
4996
    return false;
4997
  get_nextneighbors (nb, a_ref, a_view);
4998
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
4999
  for (i = 0; i <= FORLIM; i++)
5000
    {
5001
      strcpy (nb_at, atom[nb[i] - 1].atype);
5002
      if (!strcmp (nb_at, "C1 "))
5003
        c1_count++;
5004
    }
5005
  if (c1_count == 1)
5006
    r = true;
5007
  return r;
5008
}
5009
 
5010
 
5011
static boolean
5012
is_aryl (int a_view, int a_ref)
5013
{
5014
  boolean r = false;
5015
 
5016
  if ((atom[a_view - 1].
5017
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
5018
      && !strcmp (atom[a_ref - 1].element, "C ")
5019
      && atom[a_ref - 1].arom == true)
5020
    r = true;
5021
  return r;
5022
}
5023
 
5024
 
5025
static boolean
5026
is_alkoxy (int a_view, int a_ref)
5027
{
5028
  boolean r = false;
5029
  neighbor_rec nb;
5030
 
5031
  memset (nb, 0, sizeof (neighbor_rec));
5032
  if (!
5033
      (atom[a_view - 1].
5034
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5035
    return false;
5036
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5037
      || atom[a_ref - 1].neighbor_count != 2)
5038
    return false;
5039
  get_nextneighbors (nb, a_ref, a_view);
5040
  if (is_alkyl (a_ref, nb[0]))
5041
    r = true;
5042
  return r;
5043
}
5044
 
5045
 
5046
static boolean
5047
is_siloxy (int a_view, int a_ref)
5048
{
5049
  boolean r = false;
5050
  neighbor_rec nb;
5051
 
5052
  memset (nb, 0, sizeof (neighbor_rec));
5053
  if (!
5054
      (atom[a_view - 1].
5055
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5056
    return false;
5057
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5058
      || atom[a_ref - 1].neighbor_count != 2)
5059
    return false;
5060
  get_nextneighbors (nb, a_ref, a_view);
5061
  if (!strcmp (atom[nb[0] - 1].element, "SI"))
5062
    r = true;
5063
  return r;
5064
}
5065
 
5066
 
5067
static boolean
5068
is_true_alkoxy (int a_view, int a_ref)
5069
{
5070
  boolean r = false;
5071
  neighbor_rec nb;
5072
 
5073
  memset (nb, 0, sizeof (neighbor_rec));
5074
  if (!
5075
      (atom[a_view - 1].
5076
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5077
    return false;
5078
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5079
      || atom[a_ref - 1].neighbor_count != 2)
5080
    return false;
5081
  get_nextneighbors (nb, a_ref, a_view);
5082
  if (is_true_alkyl (a_ref, nb[0]))
5083
    r = true;
5084
  return r;
5085
}
5086
 
5087
 
5088
static boolean
5089
is_aryloxy (int a_view, int a_ref)
5090
{
5091
  boolean r = false;
5092
  neighbor_rec nb;
5093
 
5094
  memset (nb, 0, sizeof (neighbor_rec));
5095
  if (!
5096
      (atom[a_view - 1].
5097
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5098
    return false;
5099
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5100
      || atom[a_ref - 1].neighbor_count != 2)
5101
    return false;
5102
  get_nextneighbors (nb, a_ref, a_view);
5103
  if (is_aryl (a_ref, nb[0]))
5104
    r = true;
5105
  return r;
5106
}
5107
 
5108
 
5109
static boolean
5110
is_alkenyloxy (int a_view, int a_ref)
5111
{
5112
  /* v0.3j */
5113
  boolean r = false;
5114
  neighbor_rec nb;
5115
 
5116
  memset (nb, 0, sizeof (neighbor_rec));
5117
  if (!
5118
      (atom[a_view - 1].
5119
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5120
    return false;
5121
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5122
      || atom[a_ref - 1].neighbor_count != 2)
5123
    return false;
5124
  get_nextneighbors (nb, a_ref, a_view);
5125
  if (is_alkenyl (a_ref, nb[0]))
5126
    r = true;
5127
  return r;
5128
}
5129
 
5130
 
5131
static boolean
5132
is_alkynyloxy (int a_view, int a_ref)
5133
{
5134
  /* v0.3j */
5135
  boolean r = false;
5136
  neighbor_rec nb;
5137
 
5138
  memset (nb, 0, sizeof (neighbor_rec));
5139
  if (!
5140
      (atom[a_view - 1].
5141
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5142
    return false;
5143
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
5144
      || atom[a_ref - 1].neighbor_count != 2)
5145
    return false;
5146
  get_nextneighbors (nb, a_ref, a_view);
5147
  if (is_alkynyl (a_ref, nb[0]))
5148
    r = true;
5149
  return r;
5150
}
5151
 
5152
 
5153
static boolean
5154
is_alkylsulfanyl (int a_view, int a_ref)
5155
{
5156
  boolean r = false;
5157
  neighbor_rec nb;
5158
 
5159
  memset (nb, 0, sizeof (neighbor_rec));
5160
  if (!
5161
      (atom[a_view - 1].
5162
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5163
    return false;
5164
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5165
      || atom[a_ref - 1].neighbor_count != 2)
5166
    return false;
5167
  get_nextneighbors (nb, a_ref, a_view);
5168
  if (is_alkyl (a_ref, nb[0]))
5169
    r = true;
5170
  return r;
5171
}
5172
 
5173
 
5174
static boolean
5175
is_true_alkylsulfanyl (int a_view, int a_ref)
5176
{
5177
  boolean r = false;
5178
  neighbor_rec nb;
5179
 
5180
  memset (nb, 0, sizeof (neighbor_rec));
5181
  if (!
5182
      (atom[a_view - 1].
5183
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5184
    return false;
5185
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5186
      || atom[a_ref - 1].neighbor_count != 2)
5187
    return false;
5188
  get_nextneighbors (nb, a_ref, a_view);
5189
  if (is_true_alkyl (a_ref, nb[0]))
5190
    r = true;
5191
  return r;
5192
}
5193
 
5194
 
5195
static boolean
5196
is_arylsulfanyl (int a_view, int a_ref)
5197
{
5198
  boolean r = false;
5199
  neighbor_rec nb;
5200
 
5201
  memset (nb, 0, sizeof (neighbor_rec));
5202
  if (!
5203
      (atom[a_view - 1].
5204
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5205
    return false;
5206
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5207
      || atom[a_ref - 1].neighbor_count != 2)
5208
    return false;
5209
  get_nextneighbors (nb, a_ref, a_view);
5210
  if (is_aryl (a_ref, nb[0]))
5211
    r = true;
5212
  return r;
5213
}
5214
 
5215
 
5216
static boolean
5217
is_alkenylsulfanyl (a_view, a_ref)
5218
     int a_view, a_ref;
5219
{
5220
  /* v0.3j */
5221
  boolean r = false;
5222
  neighbor_rec nb;
5223
 
5224
  memset (nb, 0, sizeof (neighbor_rec));
5225
  if (!
5226
      (atom[a_view - 1].
5227
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5228
    return false;
5229
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5230
      || atom[a_ref - 1].neighbor_count != 2)
5231
    return false;
5232
  get_nextneighbors (nb, a_ref, a_view);
5233
  if (is_alkenyl (a_ref, nb[0]))
5234
    r = true;
5235
  return r;
5236
}
5237
 
5238
 
5239
static boolean
5240
is_alkynylsulfanyl (a_view, a_ref)
5241
     int a_view, a_ref;
5242
{
5243
  /* v0.3j */
5244
  boolean r = false;
5245
  neighbor_rec nb;
5246
 
5247
  memset (nb, 0, sizeof (neighbor_rec));
5248
  if (!
5249
      (atom[a_view - 1].
5250
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5251
    return false;
5252
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
5253
      || atom[a_ref - 1].neighbor_count != 2)
5254
    return false;
5255
  get_nextneighbors (nb, a_ref, a_view);
5256
  if (is_alkynyl (a_ref, nb[0]))
5257
    r = true;
5258
  return r;
5259
}
5260
 
5261
 
5262
static boolean
5263
is_alkylamino (a_view, a_ref)
5264
     int a_view, a_ref;
5265
{
5266
  boolean r = false;
5267
  neighbor_rec nb;
5268
  int alkyl_count = 0;
5269
 
5270
  memset (nb, 0, sizeof (neighbor_rec));
5271
  if (!
5272
      (atom[a_view - 1].
5273
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5274
    return false;
5275
  if (strcmp (atom[a_ref - 1].element, "N ")
5276
      || atom[a_ref - 1].neighbor_count != 2)
5277
    return false;
5278
  get_nextneighbors (nb, a_ref, a_view);
5279
  if (is_alkyl (a_ref, nb[0]))
5280
    alkyl_count++;
5281
  if (alkyl_count == 1)
5282
    r = true;
5283
  return r;
5284
}
5285
 
5286
 
5287
static boolean
5288
is_dialkylamino (a_view, a_ref)
5289
     int a_view, a_ref;
5290
{
5291
  int i;
5292
  boolean r = false;
5293
  neighbor_rec nb;
5294
  int alkyl_count = 0;
5295
 
5296
  memset (nb, 0, sizeof (neighbor_rec));
5297
  if (!
5298
      (atom[a_view - 1].
5299
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5300
    return false;
5301
  if (strcmp (atom[a_ref - 1].element, "N ")
5302
      || atom[a_ref - 1].neighbor_count != 3)
5303
    return false;
5304
  get_nextneighbors (nb, a_ref, a_view);
5305
  for (i = 0; i <= 1; i++)
5306
    {
5307
      if (is_alkyl (a_ref, nb[i]))
5308
        alkyl_count++;
5309
    }
5310
  if (alkyl_count == 2)
5311
    r = true;
5312
  return r;
5313
}
5314
 
5315
 
5316
static boolean
5317
is_arylamino (a_view, a_ref)
5318
     int a_view, a_ref;
5319
{
5320
  boolean r = false;
5321
  neighbor_rec nb;
5322
  int aryl_count = 0;
5323
 
5324
  memset (nb, 0, sizeof (neighbor_rec));
5325
  if (!
5326
      (atom[a_view - 1].
5327
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5328
    return false;
5329
  if (strcmp (atom[a_ref - 1].element, "N ")
5330
      || atom[a_ref - 1].neighbor_count != 2)
5331
    return false;
5332
  get_nextneighbors (nb, a_ref, a_view);
5333
  if (is_aryl (a_ref, nb[0]))
5334
    aryl_count++;
5335
  if (aryl_count == 1)
5336
    r = true;
5337
  return r;
5338
}
5339
 
5340
 
5341
static boolean
5342
is_diarylamino (a_view, a_ref)
5343
     int a_view, a_ref;
5344
{
5345
  int i;
5346
  boolean r = false;
5347
  neighbor_rec nb;
5348
  int aryl_count = 0;
5349
 
5350
  memset (nb, 0, sizeof (neighbor_rec));
5351
  if (!
5352
      (atom[a_view - 1].
5353
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5354
    return false;
5355
  if (strcmp (atom[a_ref - 1].element, "N ")
5356
      || atom[a_ref - 1].neighbor_count != 3)
5357
    return false;
5358
  get_nextneighbors (nb, a_ref, a_view);
5359
  for (i = 0; i <= 1; i++)
5360
    {
5361
      if (is_aryl (a_ref, nb[i]))
5362
        aryl_count++;
5363
    }
5364
  if (aryl_count == 2)
5365
    r = true;
5366
  return r;
5367
}
5368
 
5369
 
5370
static boolean
5371
is_alkylarylamino (a_view, a_ref)
5372
     int a_view, a_ref;
5373
{
5374
  int i;
5375
  boolean r = false;
5376
  neighbor_rec nb;
5377
  int alkyl_count = 0, aryl_count = 0;
5378
 
5379
  memset (nb, 0, sizeof (neighbor_rec));
5380
  if (!
5381
      (atom[a_view - 1].
5382
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5383
    return false;
5384
  if (strcmp (atom[a_ref - 1].element, "N ")
5385
      || atom[a_ref - 1].neighbor_count != 3)
5386
    return false;
5387
  get_nextneighbors (nb, a_ref, a_view);
5388
  for (i = 0; i <= 1; i++)
5389
    {
5390
      if (is_alkyl (a_ref, nb[i]))
5391
        alkyl_count++;
5392
      if (is_aryl (a_ref, nb[i]))
5393
        aryl_count++;
5394
    }
5395
  if (alkyl_count == 1 && aryl_count == 1)
5396
    r = true;
5397
  return r;
5398
}
5399
 
5400
 
5401
static boolean
5402
is_C_monosubst_amino (a_view, a_ref)
5403
     int a_view, a_ref;
5404
{
5405
  /* new in v0.3j */
5406
  boolean r = false;
5407
  neighbor_rec nb;
5408
  int c_count = 0;
5409
 
5410
  memset (nb, 0, sizeof (neighbor_rec));
5411
  if (!
5412
      (atom[a_view - 1].
5413
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5414
    return false;
5415
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5416
      && strcmp (atom[a_ref - 1].atype, "NAM"))
5417
      || atom[a_ref - 1].neighbor_count != 2)
5418
    return false;
5419
  get_nextneighbors (nb, a_ref, a_view);
5420
  if (!strcmp (atom[nb[0] - 1].element, "C "))
5421
    c_count++;
5422
  if (c_count == 1)
5423
    r = true;
5424
  return r;
5425
}
5426
 
5427
 
5428
static boolean
5429
is_C_disubst_amino (a_view, a_ref)
5430
     int a_view, a_ref;
5431
{
5432
  /* new in v0.3j */
5433
  int i;
5434
  boolean r = false;
5435
  neighbor_rec nb;
5436
  int b;
5437
  int c_count = 0;
5438
 
5439
  b = get_bond (a_view, a_ref);
5440
  memset (nb, 0, sizeof (neighbor_rec));
5441
  if (!(atom[a_view - 1].heavy && bond[b - 1].btype == 'S' &&
5442
        bond[b - 1].arom == false))
5443
    return false;
5444
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5445
      && strcmp (atom[a_ref - 1].atype, "NAM"))
5446
      || atom[a_ref - 1].neighbor_count != 3)
5447
    return false;
5448
  get_nextneighbors (nb, a_ref, a_view);
5449
  for (i = 0; i <= 1; i++)
5450
    {
5451
      if (!strcmp (atom[nb[i] - 1].element, "C "))
5452
        c_count++;
5453
    }
5454
  if (c_count == 2)
5455
    r = true;
5456
  return r;
5457
}
5458
 
5459
 
5460
static boolean
5461
is_subst_amino (a_view, a_ref)
5462
     int a_view, a_ref;
5463
{
5464
  boolean r = false;
5465
 
5466
  if (is_amino (a_view, a_ref) || is_alkylamino (a_view, a_ref) |
5467
      is_arylamino (a_view, a_ref) || is_dialkylamino (a_view, a_ref) |
5468
      is_alkylarylamino (a_view, a_ref) || is_diarylamino (a_view, a_ref))
5469
    r = true;
5470
  return r;
5471
}
5472
 
5473
 
5474
static boolean
5475
is_true_alkylamino (a_view, a_ref)
5476
     int a_view, a_ref;
5477
{
5478
  boolean r = false;
5479
  neighbor_rec nb;
5480
  int alkyl_count = 0;
5481
 
5482
  memset (nb, 0, sizeof (neighbor_rec));
5483
  if (!
5484
      (atom[a_view - 1].
5485
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5486
    return false;
5487
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5488
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5489
      || atom[a_ref - 1].neighbor_count != 2)
5490
    return false;
5491
  get_nextneighbors (nb, a_ref, a_view);
5492
  if (is_true_alkyl (a_ref, nb[0]))
5493
    alkyl_count++;
5494
  if (alkyl_count == 1)
5495
    r = true;
5496
  return r;
5497
}
5498
 
5499
 
5500
static boolean
5501
is_true_dialkylamino (a_view, a_ref)
5502
     int a_view, a_ref;
5503
{
5504
  int i;
5505
  boolean r = false;
5506
  neighbor_rec nb;
5507
  int alkyl_count = 0;
5508
 
5509
  memset (nb, 0, sizeof (neighbor_rec));
5510
  if (!
5511
      (atom[a_view - 1].
5512
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5513
    return false;
5514
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5515
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5516
      || atom[a_ref - 1].neighbor_count != 3)
5517
    return false;
5518
  get_nextneighbors (nb, a_ref, a_view);
5519
  for (i = 0; i <= 1; i++)
5520
    {
5521
      if (is_true_alkyl (a_ref, nb[i]))
5522
        alkyl_count++;
5523
    }
5524
  if (alkyl_count == 2)
5525
    r = true;
5526
  return r;
5527
}
5528
 
5529
#if 0
5530
static boolean
5531
is_true_alkylarylamino (a_view, a_ref)
5532
     int a_view, a_ref;
5533
{
5534
  int i;
5535
  boolean r = false;
5536
  neighbor_rec nb;
5537
  int alkyl_count = 0, aryl_count = 0;
5538
 
5539
  memset (nb, 0, sizeof (neighbor_rec));
5540
  if (!
5541
      (atom[a_view - 1].
5542
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5543
    return false;
5544
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5545
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5546
      || atom[a_ref - 1].neighbor_count != 3)
5547
    return false;
5548
  get_nextneighbors (nb, a_ref, a_view);
5549
  for (i = 0; i <= 1; i++)
5550
    {
5551
      if (is_true_alkyl (a_ref, nb[i]))
5552
        alkyl_count++;
5553
      if (is_aryl (a_ref, nb[i]))
5554
        aryl_count++;
5555
    }
5556
  if (alkyl_count == 1 && aryl_count == 1)
5557
    r = true;
5558
  return r;
5559
}
5560
#endif
5561
 
5562
static boolean
5563
is_hydroxylamino (a_view, a_ref)
5564
     int a_view, a_ref;
5565
{
5566
  int i;
5567
  boolean r = false;
5568
  neighbor_rec nb;
5569
  int oh_count = 0, het_count = 0;      /* v0.3k */
5570
  str2 nb_el;                   /* v0.3k */
5571
  int FORLIM;
5572
 
5573
  memset (nb, 0, sizeof (neighbor_rec));
5574
  if (!
5575
      (atom[a_view - 1].
5576
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5577
    return false;
5578
  if (strcmp (atom[a_ref - 1].element, "N ")
5579
      || atom[a_ref - 1].neighbor_count < 2)
5580
    /* v0.3c */
5581
    return false;
5582
  get_nextneighbors (nb, a_ref, a_view);
5583
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
5584
  for (i = 0; i <= FORLIM; i++)
5585
    {                           /* v0.3c */
5586
      if (is_hydroxy (a_ref, nb[i]))
5587
        oh_count++;
5588
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3k */
5589
      if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
5590
          /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
5591
          && strcmp (nb_el, "LP"))
5592
        /* v0.3k */
5593
        het_count++;
5594
      /* v0.3n: D */
5595
    }
5596
  if (oh_count == 1 && het_count == 1)
5597
    r = true;
5598
  return r;
5599
}
5600
 
5601
 
5602
static boolean
5603
is_nitro (a_view, a_ref)
5604
     int a_view, a_ref;
5605
{
5606
  int i;
5607
  boolean r = false;
5608
  neighbor_rec nb;
5609
  int o_count = 0, bond_count = 0;
5610
 
5611
  memset (nb, 0, sizeof (neighbor_rec));
5612
  if (!
5613
      (atom[a_view - 1].
5614
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5615
    return false;
5616
  if (strcmp (atom[a_ref - 1].element, "N ")
5617
      || atom[a_ref - 1].neighbor_count != 3)
5618
    return false;
5619
  get_nextneighbors (nb, a_ref, a_view);
5620
  for (i = 0; i <= 1; i++)
5621
    {
5622
      if (!strcmp (atom[nb[i] - 1].element, "O "))
5623
        o_count++;
5624
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
5625
        bond_count++;
5626
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
5627
        bond_count += 2;
5628
    }
5629
  if (o_count == 2 && bond_count >= 3)
5630
    r = true;
5631
  return r;
5632
}
5633
 
5634
 
5635
static boolean
5636
is_azido (a_view, a_ref)
5637
     int a_view, a_ref;
5638
{
5639
  boolean r = false;
5640
  neighbor_rec nb;
5641
  int bond_count = 0, n1 = 0, n2 = 0, n3 = 0;
5642
 
5643
  if (!
5644
      (atom[a_view - 1].
5645
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5646
    return false;
5647
  if (strcmp (atom[a_ref - 1].element, "N ")
5648
      || atom[a_ref - 1].neighbor_count != 2)
5649
    return false;
5650
  n1 = a_ref;
5651
  memset (nb, 0, sizeof (neighbor_rec));
5652
  get_nextneighbors (nb, n1, a_view);
5653
  if (!strcmp (atom[nb[0] - 1].element, "N "))
5654
    {
5655
      n2 = nb[0];
5656
      if (bond[get_bond (n1, n2) - 1].btype == 'S')
5657
        bond_count++;
5658
      if (bond[get_bond (n1, n2) - 1].btype == 'D')
5659
        bond_count += 2;
5660
      if (bond[get_bond (n1, n2) - 1].btype == 'T')
5661
        bond_count += 3;
5662
    }
5663
  if (n2 > 0 && atom[n2 - 1].neighbor_count == 2)
5664
    {
5665
      memset (nb, 0, sizeof (neighbor_rec));
5666
      get_nextneighbors (nb, n2, n1);
5667
      if (!strcmp (atom[nb[0] - 1].element, "N "))
5668
        {
5669
          n3 = nb[0];
5670
          if (bond[get_bond (n2, n3) - 1].btype == 'S')
5671
            bond_count++;
5672
          if (bond[get_bond (n2, n3) - 1].btype == 'D')
5673
            bond_count += 2;
5674
          if (bond[get_bond (n2, n3) - 1].btype == 'T')
5675
            bond_count += 3;
5676
        }
5677
    }
5678
  if (n1 > 0 && n2 > 0 && n3 > 0 && atom[n3 - 1].neighbor_count == 1 &&
5679
      bond_count > 3)
5680
    r = true;
5681
  return r;
5682
}
5683
 
5684
 
5685
static boolean
5686
is_diazonium (a_view, a_ref)
5687
     int a_view, a_ref;
5688
{
5689
  boolean r = false;
5690
  neighbor_rec nb;
5691
  int bond_count = 0, chg_count = 0, n1 = 0, n2 = 0;
5692
 
5693
  if (!
5694
      (atom[a_view - 1].
5695
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5696
    return false;
5697
  if (strcmp (atom[a_ref - 1].element, "N ")
5698
      || atom[a_ref - 1].neighbor_count != 2)
5699
    return false;
5700
  n1 = a_ref;
5701
  chg_count = atom[n1 - 1].formal_charge;
5702
  memset (nb, 0, sizeof (neighbor_rec));
5703
  get_nextneighbors (nb, n1, a_view);
5704
  if (!strcmp (atom[nb[0] - 1].element, "N "))
5705
    {
5706
      n2 = nb[0];
5707
      chg_count += atom[n2 - 1].formal_charge;
5708
      if (bond[get_bond (n1, n2) - 1].btype == 'S')
5709
        bond_count++;
5710
      if (bond[get_bond (n1, n2) - 1].btype == 'D')
5711
        bond_count += 2;
5712
      if (bond[get_bond (n1, n2) - 1].btype == 'T')
5713
        bond_count += 3;
5714
    }
5715
  if (n1 > 0 && n2 > 0 && atom[n2 - 1].neighbor_count == 1
5716
      && bond_count >= 2 && chg_count > 0)
5717
    r = true;
5718
  return r;
5719
}
5720
 
5721
 
5722
static boolean
5723
is_hydroximino_C (id)
5724
     int id;
5725
{
5726
  boolean Result;
5727
  int i;
5728
  boolean r = false;
5729
  neighbor_rec nb;
5730
  int a_het = 0;
5731
  int FORLIM;
5732
 
5733
  memset (nb, 0, sizeof (neighbor_rec));
5734
  if (id < 1 || id > n_atoms)
5735
    return Result;
5736
  get_neighbors (nb, id);
5737
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5738
    return false;
5739
  FORLIM = atom[id - 1].neighbor_count;
5740
  for (i = 0; i < FORLIM; i++)
5741
    {
5742
      if ((bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5743
           !strcmp (atom[nb[i] - 1].element,
5744
                    "N ")) && (hetbond_count (nb[i]) == 3))
5745
        a_het = nb[i];
5746
    }
5747
  if (a_het <= 0)
5748
    return false;
5749
  memset (nb, 0, sizeof (neighbor_rec));
5750
  get_neighbors (nb, a_het);
5751
  if (strcmp (atom[a_het - 1].element, "N ")
5752
      || atom[a_het - 1].neighbor_count <= 0)
5753
    return false;
5754
  FORLIM = atom[a_het - 1].neighbor_count;
5755
  for (i = 0; i < FORLIM; i++)
5756
    {
5757
      if (is_hydroxy (a_het, nb[i]))
5758
        r = true;
5759
    }
5760
  return r;
5761
}
5762
 
5763
 
5764
static boolean
5765
is_hydrazono_C (id)
5766
     int id;
5767
{
5768
  boolean Result;
5769
  int i;
5770
  boolean r = false;
5771
  neighbor_rec nb;
5772
  int a_het = 0;
5773
  int FORLIM;
5774
 
5775
  memset (nb, 0, sizeof (neighbor_rec));
5776
  if (id < 1 || id > n_atoms)
5777
    return Result;
5778
  get_neighbors (nb, id);
5779
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5780
    return false;
5781
  FORLIM = atom[id - 1].neighbor_count;
5782
  for (i = 0; i < FORLIM; i++)
5783
    {
5784
      if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5785
          !strcmp (atom[nb[i] - 1].element, "N "))
5786
        {
5787
          /* and
5788
             (hetbond_count(nb[i]) = 3)  */
5789
          a_het = nb[i];
5790
        }
5791
    }
5792
  if (a_het <= 0)
5793
    return false;
5794
  memset (nb, 0, sizeof (neighbor_rec));
5795
  get_neighbors (nb, a_het);
5796
  if (strcmp (atom[a_het - 1].element, "N ")
5797
      || atom[a_het - 1].neighbor_count <= 0)
5798
    return false;
5799
  FORLIM = atom[a_het - 1].neighbor_count;
5800
  for (i = 0; i < FORLIM; i++)
5801
    {
5802
      if (is_amino (a_het, nb[i]) || is_alkylamino (a_het, nb[i]) |
5803
          is_alkylarylamino (a_het, nb[i]) || is_arylamino (a_het, nb[i]) |
5804
          is_dialkylamino (a_het, nb[i]) || is_diarylamino (a_het, nb[i]))
5805
        r = true;
5806
    }
5807
  return r;
5808
}
5809
 
5810
 
5811
static boolean
5812
is_alkoxycarbonyl (a_view, a_ref)
5813
     int a_view, a_ref;
5814
{
5815
  int i;
5816
  boolean r = false;
5817
  neighbor_rec nb;
5818
 
5819
  memset (nb, 0, sizeof (neighbor_rec));
5820
  if (!
5821
      (atom[a_view - 1].
5822
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5823
    return false;
5824
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5825
    return false;
5826
  get_nextneighbors (nb, a_ref, a_view);
5827
  for (i = 0; i <= 1; i++)
5828
    {
5829
      if (is_alkoxy (a_ref, nb[i]))
5830
        r = true;
5831
    }
5832
  return r;
5833
}
5834
 
5835
 
5836
static boolean
5837
is_aryloxycarbonyl (a_view, a_ref)
5838
     int a_view, a_ref;
5839
{
5840
  int i;
5841
  boolean r = false;
5842
  neighbor_rec nb;
5843
 
5844
  memset (nb, 0, sizeof (neighbor_rec));
5845
  if (!
5846
      (atom[a_view - 1].
5847
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5848
    return false;
5849
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5850
    return false;
5851
  get_nextneighbors (nb, a_ref, a_view);
5852
  for (i = 0; i <= 1; i++)
5853
    {
5854
      if (is_aryloxy (a_ref, nb[i]))
5855
        r = true;
5856
    }
5857
  return r;
5858
}
5859
 
5860
 
5861
static boolean
5862
is_carbamoyl (a_view, a_ref)
5863
     int a_view, a_ref;
5864
{
5865
  int i;
5866
  boolean r = false;
5867
  neighbor_rec nb;
5868
 
5869
  memset (nb, 0, sizeof (neighbor_rec));
5870
  if (!
5871
      (atom[a_view - 1].
5872
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5873
    return false;
5874
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5875
    return false;
5876
  get_nextneighbors (nb, a_ref, a_view);
5877
  for (i = 0; i <= 1; i++)
5878
    {
5879
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5880
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
5881
        r = true;
5882
    }
5883
  return r;
5884
}
5885
 
5886
 
5887
static boolean
5888
is_alkoxythiocarbonyl (a_view, a_ref)
5889
     int a_view, a_ref;
5890
{
5891
  int i;
5892
  boolean r = false;
5893
  neighbor_rec nb;
5894
 
5895
  memset (nb, 0, sizeof (neighbor_rec));
5896
  if (!
5897
      (atom[a_view - 1].
5898
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5899
    return false;
5900
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5901
    return false;
5902
  get_nextneighbors (nb, a_ref, a_view);
5903
  for (i = 0; i <= 1; i++)
5904
    {
5905
      if (is_alkoxy (a_ref, nb[i]))
5906
        r = true;
5907
    }
5908
  return r;
5909
}
5910
 
5911
 
5912
static boolean
5913
is_aryloxythiocarbonyl (a_view, a_ref)
5914
     int a_view, a_ref;
5915
{
5916
  int i;
5917
  boolean r = false;
5918
  neighbor_rec nb;
5919
 
5920
  memset (nb, 0, sizeof (neighbor_rec));
5921
  if (!
5922
      (atom[a_view - 1].
5923
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5924
    return false;
5925
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5926
    return false;
5927
  get_nextneighbors (nb, a_ref, a_view);
5928
  for (i = 0; i <= 1; i++)
5929
    {
5930
      if (is_aryloxy (a_ref, nb[i]))
5931
        r = true;
5932
    }
5933
  return r;
5934
}
5935
 
5936
 
5937
static boolean
5938
is_thiocarbamoyl (a_view, a_ref)
5939
     int a_view, a_ref;
5940
{
5941
  int i;
5942
  boolean r = false;
5943
  neighbor_rec nb;
5944
 
5945
  memset (nb, 0, sizeof (neighbor_rec));
5946
  if (!
5947
      (atom[a_view - 1].
5948
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5949
    return false;
5950
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5951
    return false;
5952
  get_nextneighbors (nb, a_ref, a_view);
5953
  for (i = 0; i <= 1; i++)
5954
    {
5955
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5956
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
5957
        r = true;
5958
    }
5959
  return r;
5960
}
5961
 
5962
 
5963
static boolean
5964
is_alkanoyl (a_view, a_ref)
5965
     int a_view, a_ref;
5966
{
5967
  int i;
5968
  boolean r = false;
5969
  neighbor_rec nb;
5970
 
5971
  memset (nb, 0, sizeof (neighbor_rec));
5972
  if (!
5973
      (atom[a_view - 1].
5974
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5975
    return false;
5976
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5977
    return false;
5978
  get_nextneighbors (nb, a_ref, a_view);
5979
  for (i = 0; i <= 1; i++)
5980
    {
5981
      if (is_alkyl (a_ref, nb[i]))
5982
        r = true;
5983
    }
5984
  return r;
5985
}
5986
 
5987
 
5988
static boolean
5989
is_aroyl (a_view, a_ref)
5990
     int a_view, a_ref;
5991
{
5992
  int i;
5993
  boolean r = false;
5994
  neighbor_rec nb;
5995
 
5996
  memset (nb, 0, sizeof (neighbor_rec));
5997
  if (!
5998
      (atom[a_view - 1].
5999
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6000
    return false;
6001
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
6002
    return false;
6003
  get_nextneighbors (nb, a_ref, a_view);
6004
  for (i = 0; i <= 1; i++)
6005
    {
6006
      if (is_aryl (a_ref, nb[i]))
6007
        r = true;
6008
    }
6009
  return r;
6010
}
6011
 
6012
 
6013
static boolean
6014
is_acyl (a_view, a_ref)
6015
     int a_view, a_ref;
6016
{
6017
  boolean r = false;
6018
 
6019
  if (is_alkanoyl (a_view, a_ref) || is_aroyl (a_view, a_ref))
6020
    r = true;
6021
  return r;
6022
}
6023
 
6024
 
6025
static boolean
6026
is_acyl_gen (a_view, a_ref)
6027
     int a_view, a_ref;
6028
{
6029
  /* new in v0.3j */
6030
  boolean r = false;
6031
 
6032
  if (is_oxo_C (a_ref))
6033
    r = true;
6034
  return r;
6035
}
6036
 
6037
 
6038
static boolean
6039
is_acylamino (a_view, a_ref)
6040
     int a_view, a_ref;
6041
{
6042
  boolean r = false;
6043
  neighbor_rec nb;
6044
  int acyl_count = 0;
6045
 
6046
  memset (nb, 0, sizeof (neighbor_rec));
6047
  if (!
6048
      (atom[a_view - 1].
6049
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6050
    return false;
6051
  if (strcmp (atom[a_ref - 1].element, "N ")
6052
      || atom[a_ref - 1].neighbor_count != 2)
6053
    return false;
6054
  get_nextneighbors (nb, a_ref, a_view);
6055
  if (is_acyl (a_ref, nb[0]))
6056
    acyl_count++;
6057
  if (acyl_count == 1)
6058
    r = true;
6059
  return r;
6060
}
6061
 
6062
 
6063
static boolean
6064
is_subst_acylamino (a_view, a_ref)
6065
     int a_view, a_ref;
6066
{
6067
  /* may be substituted _or_ unsubstituted acylamino group! */
6068
  int i;
6069
  boolean r = false;
6070
  neighbor_rec nb;
6071
  int acyl_count = 0;
6072
  int FORLIM;
6073
 
6074
  memset (nb, 0, sizeof (neighbor_rec));
6075
  if (!
6076
      (atom[a_view - 1].
6077
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6078
    return false;
6079
  if (strcmp (atom[a_ref - 1].element, "N ")
6080
      || atom[a_ref - 1].neighbor_count < 2)
6081
    return false;
6082
  get_nextneighbors (nb, a_ref, a_view);
6083
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6084
  for (i = 0; i <= FORLIM; i++)
6085
    {
6086
      if (is_acyl_gen (a_ref, nb[i]))   /* v0.3j */
6087
        acyl_count++;
6088
    }
6089
  if (acyl_count > 0)
6090
    r = true;
6091
  return r;
6092
}
6093
 
6094
 
6095
static boolean
6096
is_hydrazino (a_view, a_ref)
6097
     int a_view, a_ref;
6098
{
6099
  int i;
6100
  boolean r = false;
6101
  neighbor_rec nb;
6102
  int nr_count = 0;
6103
  int FORLIM;
6104
 
6105
  memset (nb, 0, sizeof (neighbor_rec));
6106
  if (!
6107
      (atom[a_view - 1].
6108
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6109
    return false;
6110
  if (strcmp (atom[a_ref - 1].element, "N ")
6111
      || atom[a_ref - 1].neighbor_count < 2)
6112
    return false;
6113
  get_nextneighbors (nb, a_ref, a_view);
6114
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6115
  for (i = 0; i <= FORLIM; i++)
6116
    {                           /* fixed in v0.3c */
6117
      if (is_amino (a_ref, nb[i]) || is_subst_amino (a_ref, nb[i]))
6118
        nr_count++;
6119
    }
6120
  if (nr_count == 1)
6121
    r = true;
6122
  return r;
6123
}
6124
 
6125
 
6126
static boolean
6127
is_nitroso (a_view, a_ref)
6128
     int a_view, a_ref;
6129
{
6130
  /* new in v0.3j */
6131
  boolean r = false;
6132
  neighbor_rec nb;
6133
  int o_count = 0;
6134
  int a2;
6135
 
6136
  memset (nb, 0, sizeof (neighbor_rec));
6137
  if (!
6138
      (atom[a_view - 1].
6139
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6140
    return false;
6141
  if (strcmp (atom[a_ref - 1].element, "N ")
6142
      || atom[a_ref - 1].neighbor_count != 2)
6143
    return false;
6144
  get_nextneighbors (nb, a_ref, a_view);
6145
  a2 = nb[0];
6146
  if ((strcmp (atom[a2 - 1].element, "O ") == 0) &
6147
      (bond[get_bond (a_ref, a2) - 1].btype == 'D'))
6148
    o_count++;
6149
  if (o_count == 1)
6150
    r = true;
6151
  return r;
6152
}
6153
 
6154
 
6155
static boolean
6156
is_subst_hydrazino (a_view, a_ref)
6157
     int a_view, a_ref;
6158
{
6159
  int i;
6160
  boolean r = false;
6161
  neighbor_rec nb;
6162
  int nr_count = 0;
6163
  int a2, FORLIM;
6164
 
6165
  memset (nb, 0, sizeof (neighbor_rec));
6166
  if (!
6167
      (atom[a_view - 1].
6168
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6169
    return false;
6170
  if (strcmp (atom[a_ref - 1].element, "N ")
6171
      || atom[a_ref - 1].neighbor_count < 2)
6172
    return false;
6173
  get_nextneighbors (nb, a_ref, a_view);
6174
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
6175
  for (i = 0; i <= FORLIM; i++)
6176
    {
6177
      a2 = nb[i];
6178
      if ((strcmp (atom[a2 - 1].element, "N ") ==
6179
           0) && (!is_nitroso (a_ref, a2)))
6180
        /* v0.3j */
6181
        nr_count++;
6182
    }
6183
  if (nr_count == 1)
6184
    r = true;
6185
  return r;
6186
}
6187
 
6188
 
6189
static boolean
6190
is_cyano (a_view, a_ref)
6191
     int a_view, a_ref;
6192
{
6193
  boolean r = false;
6194
 
6195
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
6196
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6197
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
6198
      atom[a_ref - 1].neighbor_count == 1)
6199
    r = true;
6200
  return r;
6201
}
6202
 
6203
 
6204
static boolean
6205
is_cyano_c (a_ref)
6206
     int a_ref;
6207
{
6208
  int i;
6209
  boolean r = false;
6210
  neighbor_rec nb;
6211
  int FORLIM;
6212
 
6213
  memset (nb, 0, sizeof (neighbor_rec));
6214
  if (strcmp (atom[a_ref - 1].atype, "C1 ")
6215
      || atom[a_ref - 1].neighbor_count <= 0)
6216
    return false;
6217
  get_neighbors (nb, a_ref);
6218
  FORLIM = atom[a_ref - 1].neighbor_count;
6219
  for (i = 0; i < FORLIM; i++)
6220
    {
6221
      if (is_cyano (a_ref, nb[i]))
6222
        r = true;
6223
    }
6224
  return r;
6225
}
6226
 
6227
 
6228
static boolean
6229
is_nitrile (a_view, a_ref)
6230
     int a_view, a_ref;
6231
{
6232
  boolean r = false;
6233
  neighbor_rec nb;
6234
  str2 nb_el;
6235
 
6236
  if (!is_cyano (a_view, a_ref))
6237
    return false;
6238
  if (atom[a_view - 1].neighbor_count == 1
6239
      && atom[a_view - 1].formal_charge == 0)
6240
    return true;
6241
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6242
  get_nextneighbors (nb, a_view, a_ref);
6243
  strcpy (nb_el, atom[nb[0] - 1].element);
6244
  if (!strcmp (nb_el, "C ")
6245
      || !strcmp (nb_el, "H ") /*|| !strcmp (nb_el, "D ") */ )
6246
    /* v0.3n: D */
6247
    r = true;
6248
  /* HCN is also a nitrile! */
6249
  return r;
6250
}
6251
 
6252
 
6253
static boolean
6254
is_isonitrile (a_view, a_ref)
6255
     int a_view, a_ref;
6256
{
6257
  /* only recognized with CN triple bond! */
6258
  boolean r = false;
6259
 
6260
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
6261
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6262
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
6263
      atom[a_ref - 1].neighbor_count == 2
6264
      && atom[a_view - 1].neighbor_count == 1)
6265
    r = true;
6266
  return r;
6267
}
6268
 
6269
 
6270
static boolean
6271
is_cyanate (a_view, a_ref)
6272
     int a_view, a_ref;
6273
{
6274
  boolean r = false;
6275
  neighbor_rec nb;
6276
 
6277
  if (!is_cyano (a_view, a_ref))
6278
    return false;
6279
  if (atom[a_view - 1].neighbor_count != 2)
6280
    return false;
6281
  get_nextneighbors (nb, a_view, a_ref);
6282
  if (is_alkoxy (a_view, nb[0]) || is_aryloxy (a_view, nb[0]))
6283
    r = true;
6284
  return r;
6285
}
6286
 
6287
 
6288
static boolean
6289
is_thiocyanate (a_view, a_ref)
6290
     int a_view, a_ref;
6291
{
6292
  boolean r = false;
6293
  neighbor_rec nb;
6294
 
6295
  if (!is_cyano (a_view, a_ref))
6296
    return false;
6297
  if (atom[a_view - 1].neighbor_count != 2)
6298
    return false;
6299
  get_nextneighbors (nb, a_view, a_ref);
6300
  if (is_alkylsulfanyl (a_view, nb[0]) || is_arylsulfanyl (a_view, nb[0]))
6301
    r = true;
6302
  return r;
6303
}
6304
 
6305
 
6306
static void
6307
update_Htotal ()
6308
{
6309
  int i, j, b_id;
6310
  neighbor_rec nb;
6311
  int single_count, double_count, triple_count, arom_count, total_bonds,
6312
    Htotal, nval;
6313
  /* new in v0.3 */
6314
  boolean diazon = false;       /* new in v0.3j */
6315
  neighbor_rec nb2;             /* new in v0.3j */
6316
  int a1, a2, a3;               /* new in v0.3j */
6317
  int FORLIM, FORLIM1;
6318
 
6319
  if (n_atoms < 1)
6320
    return;
6321
  memset (nb, 0, sizeof (neighbor_rec));
6322
  FORLIM = n_atoms;
6323
  for (i = 1; i <= FORLIM; i++)
6324
    {
6325
      single_count = 0;
6326
      double_count = 0;
6327
      triple_count = 0;
6328
      arom_count = 0;
6329
      total_bonds = 0;
6330
      Htotal = 0;
6331
      get_neighbors (nb, i);
6332
      if (atom[i - 1].neighbor_count > 0)
6333
        {
6334
          /* count single, double, triple, and aromatic bonds to all neighbor atoms */
6335
          FORLIM1 = atom[i - 1].neighbor_count;
6336
          for (j = 0; j < FORLIM1; j++)
6337
            {
6338
              b_id = get_bond (i, nb[j]);
6339
              if (b_id > 0)
6340
                {
6341
                  if (bond[b_id - 1].btype == 'S')
6342
                    single_count++;
6343
                  if (bond[b_id - 1].btype == 'D')
6344
                    double_count++;
6345
                  if (bond[b_id - 1].btype == 'T')
6346
                    triple_count++;
6347
                  if (bond[b_id - 1].btype == 'A')
6348
                    arom_count++;
6349
                }
6350
            }
6351
          /*check for diazonium salts */
6352
          a1 = i;
6353
          a2 = nb[0];
6354
          if (!strcmp (atom[a1 - 1].element, "N ") &&
6355
              !strcmp (atom[a2 - 1].element, "N "))
6356
            {
6357
              if (atom[a2 - 1].neighbor_count == 2)
6358
                {
6359
                  get_nextneighbors (nb2, a2, a1);
6360
                  a3 = nb2[0];
6361
                  if ((strcmp (atom[a3 - 1].element, "C ") ==
6362
                       0) && is_diazonium (a3, a2))
6363
                    diazon = true;
6364
                }
6365
            }
6366
        }
6367
      total_bonds = single_count + double_count * 2 + triple_count * 3 +
6368
        (int) (1.5 * arom_count);
6369
      /* calculate number of total hydrogens per atom */
6370
      /*nval := nvalences(atom^[i].element);    (* new in v0.3 */
6371
      nval = atom[i - 1].nvalences;     /* new in v0.3m */
6372
      if (!strcmp (atom[i - 1].element, "P "))
6373
        {
6374
          if (total_bonds - atom[i - 1].formal_charge > 3)      /* refined in v0.3n */
6375
            nval = 5;
6376
        }                       /*  */
6377
      if (!strcmp (atom[i - 1].element, "S "))
6378
        {                       /* v0.3h */
6379
          if (total_bonds > 2 && atom[i - 1].formal_charge < 1)
6380
            /* updated in v0.3j */
6381
            nval = 4;
6382
          if (total_bonds > 4)  /* this will need some refinement... */
6383
            nval = 6;
6384
        }                       /*  */
6385
      Htotal = nval - total_bonds + atom[i - 1].formal_charge;
6386
      if (diazon)               /* v0.3j */
6387
        Htotal = 0;
6388
      if (Htotal < 0)           /* e.g., N in nitro group */
6389
        Htotal = 0;
6390
      atom[i - 1].Htot = Htotal;
6391
      if (atom[i - 1].Hexp > atom[i - 1].Htot)  /* v0.3n; just to be sure... */
6392
        atom[i - 1].Htot = atom[i - 1].Hexp;
6393
    }
6394
}
6395
 
6396
 
6397
static void
6398
update_atypes ()
6399
{
6400
  int i, j, b_id;
6401
  neighbor_rec nb;
6402
  int single_count, double_count, triple_count, arom_count, acyl_count,
6403
    C_count, O_count, total_bonds, NdO_count, NdC_count, Htotal, FORLIM,
6404
    FORLIM1;
6405
 
6406
  if (n_atoms < 1)
6407
    return;
6408
  memset (nb, 0, sizeof (neighbor_rec));
6409
  FORLIM = n_atoms;
6410
  for (i = 0; i < FORLIM; i++)
6411
    {
6412
      single_count = 0;
6413
      double_count = 0;
6414
      triple_count = 0;
6415
      arom_count = 0;
6416
      total_bonds = 0;
6417
      acyl_count = 0;
6418
      C_count = 0;
6419
      O_count = 0;
6420
      NdO_count = 0;
6421
      NdC_count = 0;
6422
      Htotal = 0;
6423
      get_neighbors (nb, i + 1);
6424
      if (atom[i].neighbor_count > 0)
6425
        {
6426
          /* count single, double, triple, and aromatic bonds to all neighbor atoms */
6427
          FORLIM1 = atom[i].neighbor_count;
6428
          for (j = 0; j < FORLIM1; j++)
6429
            {
6430
              if (is_oxo_C (nb[j]) || is_thioxo_C (nb[j]))
6431
                acyl_count++;
6432
              if (!strcmp (atom[nb[j] - 1].element, "C "))
6433
                C_count++;
6434
              if (!strcmp (atom[nb[j] - 1].element, "O "))
6435
                O_count++;
6436
              b_id = get_bond (i + 1, nb[j]);
6437
              if (b_id > 0)
6438
                {
6439
                  if (bond[b_id - 1].btype == 'S')
6440
                    single_count++;
6441
                  if (bond[b_id - 1].btype == 'D')
6442
                    double_count++;
6443
                  if (bond[b_id - 1].btype == 'T')
6444
                    triple_count++;
6445
                  if (bond[b_id - 1].btype == 'A')
6446
                    /* v0.3n: special treatment for acyclic bonds */
6447
                    {           /* flagged as "aromatic" (in query structures) */
6448
                      if (bond[b_id - 1].ring_count > 0)
6449
                        arom_count++;
6450
                      else
6451
                        double_count++;
6452
                    }
6453
                  if ((!strcmp (atom[i].element, "N ") &&
6454
                       !strcmp (atom[nb[j] - 1].element, "O ")) ||
6455
                      (!strcmp (atom[i].element, "O ") &&
6456
                       !strcmp (atom[nb[j] - 1].element, "N ")))
6457
                    {
6458
                      /* check if it is an N-oxide drawn with a double bond ==> should be N3 */
6459
                      if (bond[b_id - 1].btype == 'D')
6460
                        NdO_count++;
6461
                    }
6462
                  if ((!strcmp (atom[i].element, "N ") &&
6463
                       !strcmp (atom[nb[j] - 1].element, "C ")) ||
6464
                      (!strcmp (atom[i].element, "C ") &&
6465
                       !strcmp (atom[nb[j] - 1].element, "N ")))
6466
                    {
6467
                      if (bond[b_id - 1].btype == 'D')
6468
                        NdC_count++;
6469
                    }
6470
                }
6471
            }
6472
          total_bonds = single_count + double_count * 2 + triple_count * 3 +
6473
            (int) (1.5 * arom_count);
6474
          /* calculate number of total hydrogens per atom */
6475
          /*Htotal := nvalences(atom^[i].element) - total_bonds + atom^[i].formal_charge; */
6476
          Htotal = atom[i].nvalences - total_bonds + atom[i].formal_charge;
6477
          if (Htotal < 0)       /* e.g., N in nitro group */
6478
            Htotal = 0;
6479
          atom[i].Htot = Htotal;
6480
          /* refine atom types, based on bond types */
6481
          if (!strcmp (atom[i].element, "C "))
6482
            {
6483
              if (arom_count > 1)
6484
                strcpy (atom[i].atype, "CAR");
6485
              if (triple_count == 1 || double_count == 2)
6486
                strcpy (atom[i].atype, "C1 ");
6487
              if (double_count == 1)
6488
                strcpy (atom[i].atype, "C2 ");
6489
              if (triple_count == 0 && double_count == 0 && arom_count < 2)
6490
                strcpy (atom[i].atype, "C3 ");
6491
            }
6492
          if (!strcmp (atom[i].element, "O "))
6493
            {
6494
              if (double_count == 1)
6495
                strcpy (atom[i].atype, "O2 ");
6496
              if (double_count == 0)
6497
                strcpy (atom[i].atype, "O3 ");
6498
            }
6499
          if (!strcmp (atom[i].element, "N "))
6500
            {
6501
              if (total_bonds > 3)
6502
                {
6503
                  if (O_count == 0)
6504
                    {
6505
                      if (single_count > 3 ||
6506
                          (single_count == 2 && double_count == 1
6507
                          && C_count >= 2))
6508
                        atom[i].formal_charge = 1;
6509
                    }
6510
                  else
6511
                    {
6512
                      if (O_count == 1 && atom[i].formal_charge == 0)   /* v0.3m */
6513
                        strcpy (atom[i].atype, "N3 ");
6514
                      if (O_count == 2 && atom[i].formal_charge == 0)
6515
                        {
6516
                          if (atom[i].neighbor_count > 2)       /* nitro v0.3o */
6517
                            strcpy (atom[i].atype, "N2 ");
6518
                          if (atom[i].neighbor_count == 2)      /* NO2   v0.3o */
6519
                            strcpy (atom[i].atype, "N1 ");
6520
                        }
6521
                      /* the rest is left empty, so far.... */
6522
                    }
6523
                }
6524
              /* could be an N-oxide -> should be found elsewhere  */
6525
              if (triple_count == 1 ||
6526
                  (double_count == 2 && atom[i].neighbor_count == 2))
6527
                /* v0.3n */
6528
                strcpy (atom[i].atype, "N1 ");
6529
              if (double_count == 1)
6530
                {
6531
                  /*if NdC_count > 0 then atom^[i].atype := 'N2 '; */
6532
                  if (NdC_count == 0 && NdO_count > 0 && C_count >= 2)
6533
                    strcpy (atom[i].atype, "N3 ");
6534
                  /* N-oxide is N3 except in hetarene etc. */
6535
                  else
6536
                    strcpy (atom[i].atype, "N2 ");
6537
                }
6538
              /* fallback, added in v0.3g  */
6539
              if (arom_count > 1 || atom[i].arom == true)       /* v0.3n */
6540
                strcpy (atom[i].atype, "NAR");
6541
              if (triple_count == 0 && double_count == 0)
6542
                {
6543
                  if (atom[i].formal_charge == 0)
6544
                    {
6545
                      if (acyl_count == 0)
6546
                        strcpy (atom[i].atype, "N3 ");
6547
                      if (acyl_count > 0)
6548
                        strcpy (atom[i].atype, "NAM");
6549
                    }
6550
                  if (atom[i].formal_charge == 1)
6551
                    strcpy (atom[i].atype, "N3+");
6552
                }
6553
            }
6554
          if (!strcmp (atom[i].element, "P "))
6555
            {
6556
              if (single_count > 4)
6557
                strcpy (atom[i].atype, "P4 ");
6558
              if (single_count <= 4 && double_count == 0)
6559
                strcpy (atom[i].atype, "P3 ");
6560
              if (double_count == 2)
6561
                strcpy (atom[i].atype, "P3D");
6562
            }
6563
          if (!strcmp (atom[i].element, "S "))
6564
            {
6565
              if (double_count == 1 && single_count == 0)
6566
                strcpy (atom[i].atype, "S2 ");
6567
              if (double_count == 0)
6568
                strcpy (atom[i].atype, "S3 ");
6569
              if (double_count == 1 && single_count > 0)
6570
                strcpy (atom[i].atype, "SO ");
6571
              if (double_count == 2 && single_count > 0)
6572
                strcpy (atom[i].atype, "SO2");
6573
            }
6574
          /* further atom types should go here */
6575
        }
6576
    }
6577
}
6578
 
6579
 
6580
static void
6581
chk_arom ()
6582
{
6583
  int i, j, pi_count, ring_size, b, a1, a2;     /* v0.3n */
6584
  ringpath_type testring;
6585
  int a_ref, a_prev, a_next, b_bk, b_fw, b_exo;
6586
  char bt_bk, bt_fw;
6587
  boolean ar_bk, ar_fw, ar_exo; /* new in v0.3 */
6588
  boolean conj_intr, ko, aromatic, aromatic_bt; /* v0.3n */
6589
  int n_db, n_sb, n_ar;
6590
  boolean cumul;
6591
  int exo_mC;                   /* v0.3j */
6592
  int arom_pi_diff;             /* v0.3j */
6593
  int FORLIM;
6594
 
6595
  if (n_rings < 1)
6596
    return;
6597
  FORLIM = n_rings;
6598
  /* first, do a very quick check for benzene, pyridine, etc. */
6599
  for (i = 0; i < FORLIM; i++)
6600
    {
6601
      ring_size = ringprop[i].size;
6602
      if (ring_size == 6)
6603
        {
6604
          memset (testring, 0, sizeof (ringpath_type));
6605
          for (j = 0; j < ring_size; j++)
6606
            testring[j] = ring[i][j];
6607
          cumul = false;
6608
          n_sb = 0;
6609
          n_db = 0;
6610
          n_ar = 0;
6611
          a_prev = testring[ring_size - 1];
6612
          for (j = 1; j <= ring_size; j++)
6613
            {
6614
              a_ref = testring[j - 1];
6615
              if (j < ring_size)
6616
                a_next = testring[j];
6617
              else
6618
                a_next = testring[0];
6619
              b_bk = get_bond (a_prev, a_ref);
6620
              b_fw = get_bond (a_ref, a_next);
6621
              bt_bk = bond[b_bk - 1].btype;
6622
              bt_fw = bond[b_fw - 1].btype;
6623
              if (bt_fw == 'S')
6624
                n_sb++;
6625
              if (bt_fw == 'D')
6626
                n_db++;
6627
              if (bt_fw == 'A')
6628
                n_ar++;
6629
              if (bt_fw != 'A' && bt_bk == bt_fw)
6630
                cumul = true;
6631
              a_prev = a_ref;
6632
            }
6633
          if (n_ar == 6 || (n_sb == 3 && n_db == 3 && cumul == false))
6634
            {                   /* this ring is aromatic */
6635
              a_prev = testring[ring_size - 1];
6636
              for (j = 0; j < ring_size; j++)
6637
                {
6638
                  a_ref = testring[j];
6639
                  b_bk = get_bond (a_prev, a_ref);
6640
                  bond[b_bk - 1].arom = true;
6641
                  a_prev = a_ref;
6642
                }
6643
              ringprop[i].arom = true;
6644
            }
6645
        }
6646
    }
6647
  FORLIM = n_rings;
6648
  for (i = 1; i <= FORLIM; i++)
6649
    {
6650
      if (ringprop[i - 1].arom == false)
6651
        {
6652
          /* do the hard work only for those rings which are not yet flagged aromatic */
6653
          memset (testring, 0, sizeof (ringpath_type));
6654
          ring_size = ringprop[i - 1].size;     /* v0.3j */
6655
          for (j = 0; j < ring_size; j++)       /* v0.3j */
6656
            testring[j] = ring[i - 1][j];
6657
          pi_count = 0;
6658
          arom_pi_diff = 0;     /* v0.3j */
6659
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6660
          ko = false;
6661
          a_prev = testring[ring_size - 1];
6662
          for (j = 1; j <= ring_size; j++)
6663
            {
6664
              a_ref = testring[j - 1];
6665
              if (j < ring_size)
6666
                a_next = testring[j];
6667
              else
6668
                a_next = testring[0];
6669
              b_bk = get_bond (a_prev, a_ref);
6670
              b_fw = get_bond (a_ref, a_next);
6671
              bt_bk = bond[b_bk - 1].btype;
6672
              bt_fw = bond[b_fw - 1].btype;
6673
              ar_bk = bond[b_bk - 1].arom;
6674
              ar_fw = bond[b_fw - 1].arom;
6675
              if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == false
6676
                  && ar_fw == false)
6677
                {
6678
                  /* first, assume the worst case (interrupted conjugation) */
6679
                  conj_intr = true;
6680
                  /* conjugation can be restored by hetero atoms */
6681
                  if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6682
                      !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6683
                      !strcmp (atom[a_ref - 1].element, "N ") ||
6684
                      !strcmp (atom[a_ref - 1].element, "SE"))
6685
                    {
6686
                      conj_intr = false;
6687
                      pi_count += 2;    /* lone pair adds for 2 pi electrons */
6688
                    }
6689
                  /* conjugation can be restored by a formal charge at a methylene group */
6690
                  if (!strcmp (atom[a_ref - 1].element, "C ") &&
6691
                      atom[a_ref - 1].formal_charge != 0)
6692
                    {
6693
                      conj_intr = false;
6694
                      pi_count -= atom[a_ref - 1].formal_charge;
6695
                      /* neg. charge increases pi_count! */
6696
                    }
6697
                  /* conjugation can be restored by carbonyl groups etc. */
6698
                  if (is_oxo_C (a_ref) || is_thioxo_C (a_ref) |
6699
                      is_exocyclic_imino_C (a_ref, i))
6700
                    conj_intr = false;
6701
                  /* conjugation can be restored by exocyclic C=C double bond, */
6702
                  /* adds 2 pi electrons to 5-membered rings, not to 7-membered rings (CAUTION!) */
6703
                  /* apply only to non-aromatic exocyclic C=C bonds */
6704
                  exo_mC = find_exocyclic_methylene_C (a_ref, i);       /* v0.3j */
6705
                  if (exo_mC > 0 && (ring_size & 1))
6706
                    {           /* v0.3j */
6707
                      b_exo = get_bond (a_ref, exo_mC); /* v0.3j  */
6708
                      ar_exo = bond[b_exo - 1].arom;
6709
                      if (((ring_size - 1) & 3) == 0)
6710
                        {       /* 5-membered rings and related */
6711
                          conj_intr = false;
6712
                          pi_count += 2;
6713
                        }
6714
                      else
6715
                        {
6716
                          if (!ar_exo)
6717
                            conj_intr = false;
6718
                        }
6719
                    }
6720
                  /* 7-membered rings and related */
6721
                  /* if conjugation is still interrupted ==> knock-out */
6722
                  if (conj_intr)
6723
                    ko = true;
6724
                }
6725
              else
6726
                {
6727
                  if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == true
6728
                      && ar_fw == true)
6729
                    {
6730
                      if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6731
                          !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6732
                          !strcmp (atom[a_ref - 1].element, "N ") ||
6733
                          !strcmp (atom[a_ref - 1].element, "SE"))
6734
                        pi_count += 2;  /* lone pair adds for 2 pi electrons */
6735
                      if (!strcmp (atom[a_ref - 1].element, "C ") &&
6736
                          atom[a_ref - 1].formal_charge != 0)
6737
                        pi_count -= atom[a_ref - 1].formal_charge;
6738
                      /* neg. charge increases pi_count! */
6739
                      exo_mC = find_exocyclic_methylene_C (a_ref, i);   /* v0.3j */
6740
                      if (exo_mC > 0 && (ring_size & 1))
6741
                        {       /* v0.3j */
6742
                          b_exo = get_bond (a_ref, exo_mC);     /* v0.3j */
6743
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6744
                          if (((ring_size - 1) & 3) == 0)
6745
                            /* 5-membered rings and related */
6746
                            pi_count += 2;
6747
                        }
6748
                    }
6749
                  else
6750
                    {
6751
                      pi_count++;       /* v0.3j; adjustment for bridgehead N: see below */
6752
                      if (bt_bk == 'S' && bt_fw == 'S' &&
6753
                          ((ar_bk == true && ar_fw == false) ||
6754
                           (ar_bk == false && ar_fw == true)))
6755
                        {
6756
                          /* v0.3j; if a bridgehead N were not aromatic, it could  */
6757
                          /* contribute 2 pi electrons --> try also this variant */
6758
                          /* (example: CAS 32278-54-9) */
6759
                          if (!strcmp (atom[a_ref - 1].element, "N "))
6760
                            {
6761
                              arom_pi_diff++;
6762
                              /* any other case: increase pi count by one electron */
6763
                            }
6764
                        }
6765
                    }
6766
                }
6767
              /* last command: */
6768
              a_prev = a_ref;
6769
            }                   /* for j := 1 to ring_size */
6770
          /* now we can draw our conclusion */
6771
          /*if not ((ko) or (odd(pi_count))) then */
6772
          if (!ko)
6773
            /* v0.3j; odd pi_count might be compensated by arom_pi_diff */
6774
            {                   /* apply Hueckel's rule */
6775
              if (labs (ring_size - pi_count) < 2 &&
6776
                  (((pi_count - 2) & 3) == 0 ||
6777
                   ((pi_count + arom_pi_diff - 2) & 3) == 0))
6778
                {
6779
                  /* this ring is aromatic */
6780
                  ringprop[i - 1].arom = true;
6781
                  /* now mark _all_ bonds in the ring as aromatic */
6782
                  a_prev = testring[ring_size - 1];
6783
                  for (j = 0; j < ring_size; j++)
6784
                    {
6785
                      a_ref = testring[j];
6786
                      bond[get_bond (a_prev, a_ref) - 1].arom = true;
6787
                      a_prev = a_ref;
6788
                    }
6789
                }
6790
            }
6791
        }
6792
    }                           /* (for i := 1 to n_rings) */
6793
  FORLIM = n_bonds;
6794
  /* finally, mark all involved atoms as aromatic */
6795
  for (i = 0; i < FORLIM; i++)
6796
    {
6797
      if (bond[i].arom)
6798
        {
6799
          a1 = bond[i].a1;      /* v0.3n */
6800
          a2 = bond[i].a2;      /* v0.3n */
6801
          atom[a1 - 1].arom = true;
6802
          atom[a2 - 1].arom = true;
6803
          /* v0.3n: update atom types if applicable (C and N) */
6804
          if (!strcmp (atom[a1 - 1].element, "C "))
6805
            strcpy (atom[a1 - 1].atype, "CAR");
6806
          if (!strcmp (atom[a2 - 1].element, "C "))
6807
            strcpy (atom[a2 - 1].atype, "CAR");
6808
          if (!strcmp (atom[a1 - 1].element, "N "))
6809
            strcpy (atom[a1 - 1].atype, "NAR");
6810
          if (!strcmp (atom[a2 - 1].element, "N "))
6811
            strcpy (atom[a2 - 1].atype, "NAR");
6812
        }
6813
    }
6814
  FORLIM = n_rings;
6815
  /* update aromaticity information in ringprop */
6816
  /* new in v0.3n: accept rings as aromatic if all bonds are of type 'A' */
6817
  for (i = 0; i < FORLIM; i++)
6818
    {
6819
      memcpy (testring, ring[i], sizeof (ringpath_type));
6820
      /*ring_size := path_length(testring); */
6821
      ring_size = ringprop[i].size;     /* v0.3j */
6822
      aromatic = true;
6823
      aromatic_bt = true;       /* v0.3n */
6824
      a_prev = testring[ring_size - 1];
6825
      for (j = 0; j < ring_size; j++)
6826
        {
6827
          a_ref = testring[j];
6828
          b = get_bond (a_prev, a_ref); /* v0.3n */
6829
          if (!bond[b - 1].arom)
6830
            aromatic = false;
6831
          if (bond[b - 1].btype != 'A') /* v0.3n */
6832
            aromatic_bt = false;
6833
          a_prev = a_ref;
6834
        }
6835
      if (aromatic_bt && !aromatic)
6836
        {                       /* v0.3n: update aromaticity flag */
6837
          a_prev = testring[ring_size - 1];
6838
          for (j = 0; j < ring_size; j++)
6839
            {
6840
              a_ref = testring[j];
6841
              b = get_bond (a_prev, a_ref);
6842
              bond[b - 1].arom = true;
6843
              if (!strcmp (atom[a_ref - 1].element, "C "))
6844
                strcpy (atom[a_ref - 1].atype, "CAR");
6845
              if (!strcmp (atom[a_ref - 1].element, "N "))
6846
                strcpy (atom[a_ref - 1].atype, "NAR");
6847
              a_prev = a_ref;
6848
            }
6849
          aromatic = true;
6850
        }                       /* end v0.3n block   */
6851
      if (aromatic)
6852
        ringprop[i].arom = true;
6853
      else
6854
        ringprop[i].arom = false;
6855
    }
6856
}
6857
 
6858
 
6859
static void
6860
write_mol ()
6861
{
6862
  int i, j;
6863
  ringpath_type testring;
6864
  int ring_size, FORLIM;
6865
 
6866
  /*aromatic : boolean; */
6867
  /*a_prev, a_ref : integer; */
6868
  if (progmode == pmCheckMol)
6869
    printf ("Molecule name: %s\n", molname);
6870
  else
6871
    printf ("Molecule name (haystack): %s\n", molname);
6872
  printf ("atoms: %d  bonds: %d  rings: %d\n", n_atoms, n_bonds, n_rings);
6873
  if (n_atoms < 1)
6874
    return;
6875
  if (n_bonds < 1)
6876
    return;
6877
  FORLIM = n_atoms;
6878
  for (i = 1; i <= FORLIM; i++)
6879
    {
6880
      if (i < 10)
6881
        putchar (' ');
6882
      if (i < 100)
6883
        putchar (' ');
6884
      if (i < 1000)
6885
        putchar (' ');
6886
      printf ("%d %s %s %f %f ",
6887
              i, atom[i - 1].element, atom[i - 1].atype, atom[i - 1].x,
6888
              atom[i - 1].y);
6889
      printf ("%f", atom[i - 1].z);
6890
      printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6891
              atom[i - 1].neighbor_count, atom[i - 1].Hexp, atom[i - 1].Htot);
6892
      if (atom[i - 1].formal_charge != 0)
6786 kbelabas 6893
        printf ("  charge: %d", atom[i - 1].formal_charge);
6785 bpr 6894
      putchar ('\n');
6895
    }
6896
  FORLIM = n_bonds;
6897
  for (i = 1; i <= FORLIM; i++)
6898
    {
6899
      if (i < 10)
6900
        putchar (' ');
6901
      if (i < 100)
6902
        putchar (' ');
6903
      if (i < 1000)
6904
        putchar (' ');
6905
      printf ("%d %d %d %c",
6906
              i, bond[i - 1].a1, bond[i - 1].a2, bond[i - 1].btype);
6907
      if (bond[i - 1].ring_count > 0)
6908
        printf (", contained in %d ring(s)", bond[i - 1].ring_count);
6909
      if (bond[i - 1].arom)
6910
        printf (" (aromatic) ");
6911
      putchar ('\n');
6912
    }
6913
  if (n_rings <= 0)
6914
    return;
6915
  FORLIM = n_rings;
6916
  for (i = 0; i < FORLIM; i++)
6917
    {
6918
      printf ("ring %d: ", i + 1);
6919
      /*aromatic := true; */
6920
      memset (testring, 0, sizeof (ringpath_type));
6921
      ring_size = ringprop[i].size;     /* v0.3j */
6922
      /*for j := 1 to max_ringsize do if ring^[i,j] > 0 then testring[j] := ring^[i,j]; */
6923
      for (j = 0; j < ring_size; j++)   /* v0.3j */
6924
        testring[j] = ring[i][j];
6925
      /*ring_size := path_length(testring); */
6926
      /*a_prev := testring[ring_size]; */
6927
      for (j = 0; j < ring_size; j++)
6928
        {
6929
          printf ("%d ", testring[j]);
6930
          /*a_ref := testring[j]; */
6931
          /*if (not bond^[get_bond(a_prev,a_ref)].arom) then aromatic := false; */
6932
          /*a_prev := a_ref; */
6933
        }
6934
      /*if aromatic then write(' (aromatic)'); */
6935
      if (ringprop[i].arom)
6936
        printf (" (aromatic)");
6937
      if (ringprop[i].envelope)
6938
        printf (" (env)");
6939
      putchar ('\n');
6940
    }
6941
}
6942
 
6943
 
6944
static void
6945
write_needle_mol ()
6946
{
6947
  int i, j;
6948
  ringpath_type testring;
6949
  int ring_size;
6950
  boolean aromatic;
6951
  int a_prev, a_ref, FORLIM;
6952
 
6953
  printf ("Molecule name (needle): %s\n", ndl_molname);
6954
  printf ("atoms: %d  bonds: %d  rings: %d\n",
6955
          ndl_n_atoms, ndl_n_bonds, ndl_n_rings);
6956
  if (ndl_n_atoms < 1)
6957
    return;
6958
  if (ndl_n_bonds < 1)
6959
    return;
6960
  FORLIM = ndl_n_atoms;
6961
  for (i = 1; i <= FORLIM; i++)
6962
    {
6963
      if (i < 10)
6964
        putchar (' ');
6965
      if (i < 100)
6966
        putchar (' ');
6967
      if (i < 1000)
6968
        putchar (' ');
6969
      printf ("%d %s %s %f %f ",
6970
              i, ndl_atom[i - 1].element, ndl_atom[i - 1].atype,
6971
              ndl_atom[i - 1].x, atom[i - 1].y);
6972
      printf ("%f", ndl_atom[i - 1].z);
6973
      printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6974
              ndl_atom[i - 1].neighbor_count, ndl_atom[i - 1].Hexp,
6975
              ndl_atom[i - 1].Htot);
6976
      if (ndl_atom[i - 1].formal_charge != 0)
6977
        printf ("  charge: %d", ndl_atom[i - 1].formal_charge);
6978
      putchar ('\n');
6979
    }
6980
  FORLIM = ndl_n_bonds;
6981
  for (i = 1; i <= FORLIM; i++)
6982
    {
6983
      if (i < 10)
6984
        putchar (' ');
6985
      if (i < 100)
6986
        putchar (' ');
6987
      if (i < 1000)
6988
        putchar (' ');
6989
      printf ("%d %d %d %c",
6990
              i, ndl_bond[i - 1].a1, ndl_bond[i - 1].a2,
6991
              ndl_bond[i - 1].btype);
6992
      if (ndl_bond[i - 1].ring_count > 0)
6993
        printf (", contained in %d ring(s)", ndl_bond[i - 1].ring_count);
6994
      if (ndl_bond[i - 1].arom)
6995
        printf (" (aromatic) ");
6996
      putchar ('\n');
6997
    }
6998
  if (ndl_n_rings <= 0)
6999
    return;
7000
  FORLIM = ndl_n_rings;
7001
  for (i = 0; i < FORLIM; i++)
7002
    {
7003
      aromatic = true;
7004
      memset (testring, 0, sizeof (ringpath_type));
7005
      for (j = 0; j < max_ringsize; j++)
7006
        {
7007
          if (ndl_ring[i][j] > 0)
7008
            testring[j] = ndl_ring[i][j];
7009
        }
7010
      ring_size = path_length (testring);
7011
      printf ("ring %d: ", i + 1);
7012
      a_prev = testring[ring_size - 1];
7013
      for (j = 0; j < ring_size; j++)
7014
        {
7015
          printf ("%d ", testring[j]);
7016
          a_ref = testring[j];
7017
          if (!ndl_bond[get_ndl_bond (a_prev, a_ref) - 1].arom) /* v0.3k */
7018
            aromatic = false;
7019
          a_prev = a_ref;
7020
        }
7021
      if (aromatic)
7022
        printf (" (aromatic)");
7023
      putchar ('\n');
7024
    }
7025
}
7026
 
7027
 
7028
static void
7029
chk_so2_deriv (a_ref)
7030
     int a_ref;
7031
{
7032
  int i;
7033
  neighbor_rec nb;
7034
  str2 nb_el;
7035
  int het_count = 0, o_count = 0, or_count = 0, hal_count = 0, n_count = 0,
7036
    c_count = 0;
7037
  int FORLIM;
7038
 
7039
  memset (nb, 0, sizeof (neighbor_rec));
7040
  if (strcmp (atom[a_ref - 1].atype, "SO2"))
7041
    return;
7042
  get_neighbors (nb, a_ref);
7043
  FORLIM = atom[a_ref - 1].neighbor_count;
7044
  for (i = 0; i < FORLIM; i++)
7045
    {
7046
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7047
        {
7048
          strcpy (nb_el, atom[nb[i] - 1].element);
7049
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7050
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
7051
              && strcmp (nb_el, "LP"))
7052
            /* added 'D ' in v0.3n */
7053
            het_count++;
7054
          if (!strcmp (nb_el, "O "))
7055
            {
7056
              o_count++;
7057
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7058
                or_count++;
7059
            }
7060
          if (!strcmp (nb_el, "N "))
7061
            n_count++;
7062
          if (!strcmp (nb_el, "C "))
7063
            c_count++;
7064
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7065
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7066
              || !strcmp (nb_el, "AT"))
7067
            hal_count++;
7068
        }
7069
    }
7070
  if (het_count == 2)
7071
    {                           /* sulfuric acid derivative */
7072
      fg[fg_sulfuric_acid_deriv - 1] = true;
7073
      if (o_count == 2)
7074
        {
7075
          if (or_count == 0)
7076
            fg[fg_sulfuric_acid - 1] = true;
7077
          if (or_count == 1)
7078
            fg[fg_sulfuric_acid_monoester - 1] = true;
7079
          if (or_count == 2)
7080
            fg[fg_sulfuric_acid_diester - 1] = true;
7081
        }
7082
      if (o_count == 1)
7083
        {
7084
          if (or_count == 1 && n_count == 1)
7085
            fg[fg_sulfuric_acid_amide_ester - 1] = true;
7086
          if (or_count == 0 && n_count == 1)
7087
            fg[fg_sulfuric_acid_amide - 1] = true;
7088
        }
7089
      if (n_count == 2)
7090
        fg[fg_sulfuric_acid_diamide - 1] = true;
7091
      if (hal_count > 0)
7092
        fg[fg_sulfuryl_halide - 1] = true;
7093
    }
7094
  if (het_count == 1 && c_count == 1)
7095
    {                           /* sulfonic acid derivative */
7096
      fg[fg_sulfonic_acid_deriv - 1] = true;
7097
      if (o_count == 1 && or_count == 0)
7098
        fg[fg_sulfonic_acid - 1] = true;
7099
      if (o_count == 1 && or_count == 1)
7100
        fg[fg_sulfonic_acid_ester - 1] = true;
7101
      if (n_count == 1)
7102
        fg[fg_sulfonamide - 1] = true;
7103
      if (hal_count == 1)
7104
        fg[fg_sulfonyl_halide - 1] = true;
7105
    }
7106
  if (het_count == 0 && c_count == 2)   /* sulfone */
7107
    fg[fg_sulfone - 1] = true;
7108
}
7109
 
7110
 
7111
static void
7112
chk_p_deriv (a_ref)
7113
     int a_ref;
7114
{
7115
  int i;
7116
  neighbor_rec nb;
7117
  str2 nb_el, dbl_het;
7118
  int het_count;
7119
  int oh_count = 0, or_count = 0, hal_count = 0, n_count = 0, c_count = 0;
7120
  int FORLIM;
7121
 
7122
  if (strcmp (atom[a_ref - 1].element, "P "))
7123
    return;
7124
  memset (nb, 0, sizeof (neighbor_rec));
7125
  get_neighbors (nb, a_ref);
7126
  *dbl_het = '\0';
7127
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
7128
  FORLIM = atom[a_ref - 1].neighbor_count;
7129
  for (i = 0; i < FORLIM; i++)
7130
    {
7131
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
7132
        strcpy (dbl_het, atom[nb[i] - 1].element);
7133
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7134
        {
7135
          strcpy (nb_el, atom[nb[i] - 1].element);
7136
          if (!strcmp (nb_el, "C "))
7137
            c_count++;
7138
          if (is_hydroxy (a_ref, nb[i]))
7139
            oh_count++;
7140
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7141
            or_count++;
7142
          if (!strcmp (nb_el, "N "))
7143
            n_count++;
7144
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7145
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7146
              || !strcmp (nb_el, "AT"))
7147
            hal_count++;
7148
        }
7149
    }
7150
  het_count = oh_count + or_count + hal_count + n_count;
7151
  if (!strcmp (atom[a_ref - 1].atype, "P3D") ||
7152
      !strcmp (atom[a_ref - 1].atype, "P4 "))
7153
    {
7154
      if (!strcmp (dbl_het, "O "))
7155
        {
7156
          if (c_count == 0)
7157
            {
7158
              fg[fg_phosphoric_acid_deriv - 1] = true;
7159
              if (oh_count == 3)
7160
                fg[fg_phosphoric_acid - 1] = true;
7161
              if (or_count > 0)
7162
                fg[fg_phosphoric_acid_ester - 1] = true;
7163
              if (hal_count > 0)
7164
                fg[fg_phosphoric_acid_halide - 1] = true;
7165
              if (n_count > 0)
7166
                fg[fg_phosphoric_acid_amide - 1] = true;
7167
            }
7168
          if (c_count == 1)
7169
            {
7170
              fg[fg_phosphonic_acid_deriv - 1] = true;
7171
              if (oh_count == 2)
7172
                fg[fg_phosphonic_acid - 1] = true;
7173
              if (or_count > 0)
7174
                fg[fg_phosphonic_acid_ester - 1] = true;
7175
              /*if (hal_count > 0)  then fg[fg_phosphonic_acid_halide] := true;             */
7176
              /*if (n_count > 0)    then fg[fg_phosphonic_acid_amide]  := true; */
7177
            }
7178
          if (c_count == 3)
7179
            fg[fg_phosphinoxide - 1] = true;
7180
        }
7181
      if (!strcmp (dbl_het, "S "))
7182
        {
7183
          if (c_count == 0)
7184
            {
7185
              fg[fg_thiophosphoric_acid_deriv - 1] = true;
7186
              if (oh_count == 3)
7187
                fg[fg_thiophosphoric_acid - 1] = true;
7188
              if (or_count > 0)
7189
                fg[fg_thiophosphoric_acid_ester - 1] = true;
7190
              if (hal_count > 0)
7191
                fg[fg_thiophosphoric_acid_halide - 1] = true;
7192
              if (n_count > 0)
7193
                fg[fg_thiophosphoric_acid_amide - 1] = true;
7194
            }
7195
        }
7196
    }
7197
  /*  if (atom^[a_ref].atype = 'P4 ') then fg[fg_phosphoric_acid_deriv] := true; */
7198
  if (strcmp (atom[a_ref - 1].atype, "P3 "))    /* changed P3D into P3 in v0.3b */
7199
    return;
7200
  if (c_count == 3 && het_count == 0)
7201
    fg[fg_phosphine - 1] = true;
7202
  if (c_count == 3 && oh_count == 1)
7203
    fg[fg_phosphinoxide - 1] = true;
7204
}
7205
 
7206
 
7207
static void
7208
chk_b_deriv (a_ref)
7209
     int a_ref;
7210
{
7211
  int i;
7212
  neighbor_rec nb;
7213
  str2 nb_el;
7214
  int het_count = 0, oh_count = 0, or_count = 0, hal_count = 0, n_count = 0,
7215
    c_count = 0;
7216
  int FORLIM;
7217
 
7218
  if (strcmp (atom[a_ref - 1].element, "B "))
7219
    return;
7220
  memset (nb, 0, sizeof (neighbor_rec));
7221
  get_neighbors (nb, a_ref);
7222
  FORLIM = atom[a_ref - 1].neighbor_count;
7223
  for (i = 0; i < FORLIM; i++)
7224
    {
7225
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
7226
        {
7227
          strcpy (nb_el, atom[nb[i] - 1].element);
7228
          if (!strcmp (nb_el, "C "))
7229
            c_count++;
7230
          else if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  &&
7231
                   strcmp (nb_el, "LP"))
7232
            /* v0.3n: D */
7233
            het_count++;
7234
          if (is_hydroxy (a_ref, nb[i]))
7235
            oh_count++;
7236
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
7237
            /* fixed in v0.3b */
7238
            or_count++;
7239
          if (!strcmp (nb_el, "N "))
7240
            n_count++;
7241
          if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7242
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7243
              || !strcmp (nb_el, "AT"))
7244
            hal_count++;
7245
        }
7246
    }
7247
  het_count = oh_count + or_count + hal_count + n_count;
7248
  /* fixed in v0.3b */
7249
  if (c_count != 1 || het_count != 2)
7250
    return;
7251
  fg[fg_boronic_acid_deriv - 1] = true;
7252
  if (oh_count == 2)
7253
    fg[fg_boronic_acid - 1] = true;
7254
  if (or_count > 0)
7255
    fg[fg_boronic_acid_ester - 1] = true;
7256
}
7257
 
7258
 
7259
static void
7260
chk_ammon (a_ref)
7261
     int a_ref;
7262
{
7263
  int i;
7264
  neighbor_rec nb;
7265
  str2 nb_el;
7266
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
7267
  char bt;                      /* v0.3k */
7268
  float bo_sum = 0.0;
7269
  boolean ha;
7270
  int FORLIM;
7271
 
7272
  memset (nb, 0, sizeof (neighbor_rec));
7273
  if (strcmp (atom[a_ref - 1].atype, "N3+")
7274
      && atom[a_ref - 1].formal_charge == 0)
7275
    return;
7276
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
7277
    return;
7278
  get_neighbors (nb, a_ref);
7279
  FORLIM = atom[a_ref - 1].neighbor_count;
7280
  for (i = 0; i < FORLIM; i++)
7281
    {
7282
      bt = bond[get_bond (a_ref, nb[i]) - 1].btype;     /* v0.3k */
7283
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3k */
7284
      ha = atom[nb[i] - 1].heavy;       /* v0.3k */
7285
      if (bt == 'S')
7286
        {
7287
          if (ha)
7288
            bo_sum += 1.0;
7289
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7290
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
7291
            {                   /* added 'D ' in v0.3n */
7292
              het_count++;
7293
              if (!strcmp (nb_el, "O "))
7294
                {
7295
                  o_count++;
7296
                  if (atom[nb[i] - 1].neighbor_count > 1)
7297
                    or_count++;
7298
                }
7299
            }
7300
          if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
7301
              is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
7302
            /* v0.3k */
7303
            r_count++;
7304
        }
7305
      if (bt == 'D')
7306
        {
7307
          if (ha)
7308
            bo_sum += 2.0;
7309
          if (strcmp (nb_el, "C "))
7310
            {
7311
              het_count += 2;
7312
              if (!strcmp (nb_el, "O "))
7313
                o_count += 2;
7314
            }
7315
          if (!strcmp (nb_el, "C "))
7316
            r_count++;
7317
        }
7318
      if (bt == 'A' && ha)
7319
        bo_sum += 1.5;
7320
    }                           /* v0.3k: corrected end of "for ..." loop */
7321
  if (het_count == 0 && r_count == 4)
7322
    fg[fg_quart_ammonium - 1] = true;
7323
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
7324
    return;
7325
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
7326
    fg[fg_n_oxide - 1] = true;  /* finds only aliphatic N-oxides! */
7327
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
7328
      atom[a_ref - 1].arom == true)
7329
    fg[fg_quart_ammonium - 1] = true;
7330
}
7331
 
7332
 
7333
static void
7334
swap_atoms (a1, a2)
7335
     int *a1, *a2;
7336
{
7337
  int a_tmp;
7338
 
7339
  a_tmp = *a1;
7340
  *a1 = *a2;
7341
  *a2 = a_tmp;
7342
}
7343
 
7344
 
7345
static void
7346
orient_bond (a1, a2)
7347
     int *a1, *a2;
7348
{
7349
  str2 a1_el, a2_el;
7350
 
7351
  strcpy (a1_el, atom[*a1 - 1].element);
7352
  strcpy (a2_el, atom[*a2 - 1].element);
7353
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
7354
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
7355
    /* v0.3n: D */
7356
    return;
7357
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
7358
    swap_atoms (a1, a2);
7359
  if (!strcmp (a2_el, a1_el))
7360
    {
7361
      if (hetbond_count (*a1) > hetbond_count (*a2))
7362
        swap_atoms (a1, a2);
7363
    }
7364
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el))
7365
    {
7366
      if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O "))
7367
        {
7368
          if (!strcmp (a1_el, "O "))
7369
            swap_atoms (a1, a2);
7370
        }
7371
    }
7372
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el))
7373
    {
7374
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
7375
          atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
7376
        swap_atoms (a1, a2);
7377
    }
7378
}
7379
 
7380
 
7381
static void
7382
chk_imine (a_ref, a_view)
7383
     int a_ref, a_view;
7384
{
7385
  /* a_ref = C, a_view = N */
7386
  int i;
7387
  neighbor_rec nb;
7388
  str2 nb_el;
6788 kbelabas 7389
  int a_het = 0, a_c;
6785 bpr 7390
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
7391
  int FORLIM;
7392
 
7393
  /* v0.3k */
7394
  if (atom[a_view - 1].neighbor_count == 1)
7395
    {
7396
      if (atom[a_ref - 1].arom == false)
7397
        fg[fg_imine - 1] = true;
7398
      return;
7399
    }
7400
  memset (nb, 0, sizeof (neighbor_rec));
7401
  get_neighbors (nb, a_view);
7402
  if (atom[a_view - 1].neighbor_count <= 1)
7403
    return;
7404
  FORLIM = atom[a_view - 1].neighbor_count;
7405
  for (i = 0; i < FORLIM; i++)
7406
    {
7407
      if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype ==
7408
                               'S'))
7409
        {
7410
          strcpy (nb_el, atom[nb[i] - 1].element);
7411
          if (!strcmp (nb_el, "C "))
7412
            {
7413
              a_c = nb[i];
7414
              c_count++;
7415
            }
7416
          if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N "))
7417
            {
7418
              a_het = nb[i];
7419
              het_count++;
7420
            }
7421
          if ((!strcmp (nb_el, "O ")
7422
               && atom[nb[i] - 1].neighbor_count ==
7423
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
7424
            /* v0.3k */
7425
            o_count++;
7426
        }
7427
      if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype ==
7428
                               'D'))
7429
        {                       /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
7430
          strcpy (nb_el, atom[nb[i] - 1].element);
7431
          if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")
7432
              || !strcmp (nb_el, "S "))
7433
            {
7434
              a_het = nb[i];    /* v0.3m */
7435
              het_count++;
7436
            }
7437
          if ((!strcmp (nb_el, "O ")
7438
               && atom[nb[i] - 1].neighbor_count ==
7439
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
7440
            /* v0.3k */
7441
            o_count++;
7442
        }
7443
    }
7444
  if (c_count == 1)
7445
    {
7446
      if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
7447
           is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
7448
          && atom[a_ref - 1].arom == false && het_count == 0)
7449
        /* v0.3k */
7450
        fg[fg_imine - 1] = true;
7451
    }
7452
  if (het_count == 1)
7453
    {
7454
      strcpy (nb_el, atom[a_het - 1].element);
7455
      if (!strcmp (nb_el, "O "))
7456
        {
7457
          if (is_hydroxy (a_view, a_het))
7458
            fg[fg_oxime - 1] = true;
7459
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
7460
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
7461
            fg[fg_oxime_ether - 1] = true;
7462
        }
7463
      if (!strcmp (nb_el, "N "))
7464
        {
7465
          if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
7466
              is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,
7467
                                                                    a_het) |
7468
              is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
7469
            fg[fg_hydrazone - 1] = true;
7470
          else
7471
            {
7472
              memset (nb, 0, sizeof (neighbor_rec));
7473
              get_neighbors (nb, a_het);
7474
              if (atom[a_het - 1].neighbor_count > 1)
7475
                {
7476
                  FORLIM = atom[a_het - 1].neighbor_count;
7477
                  for (i = 0; i < FORLIM; i++)
7478
                    {
7479
                      if (nb[i] != a_view)
7480
                        {
7481
                          if (is_carbamoyl (a_het, nb[i]))
7482
                            fg[fg_semicarbazone - 1] = true;
7483
                          if (is_thiocarbamoyl (a_het, nb[i]))
7484
                            fg[fg_thiosemicarbazone - 1] = true;
7485
                        }
7486
                    }
7487
                }
7488
            }
7489
        }
7490
    }                           /* v0.3k: nitro groups in "azi" form */
7491
  /* check for semicarbazone or thiosemicarbazone */
7492
  if (het_count == 2 && o_count == 2)
7493
    fg[fg_nitro_compound - 1] = true;
7494
}
7495
 
7496
 
7497
static void
7498
chk_carbonyl_deriv (a_view, a_ref)
7499
     int a_view, a_ref;
7500
{
7501
  /* a_view = C */
7502
  int i;
7503
  neighbor_rec nb;
7504
  str2 nb_el;
7505
  int c_count = 0, cn_count = 0;
7506
  char bt;                      /* new in v0.3b */
7507
  int n_db = 0;                 /* new in v0.3b */
7508
  int FORLIM;
7509
 
7510
  memset (nb, 0, sizeof (neighbor_rec));
7511
  get_neighbors (nb, a_view);
7512
  FORLIM = atom[a_view - 1].neighbor_count;
7513
  /* new in v0.3b */
7514
  for (i = 0; i < FORLIM; i++)
7515
    {
7516
      bt = bond[get_bond (a_view, nb[i]) - 1].btype;
7517
      if (bt == 'S')
7518
        {
7519
          strcpy (nb_el, atom[nb[i] - 1].element);
7520
          if (!strcmp (nb_el, "C "))
7521
            {
7522
              if (is_cyano_c (nb[i]))
7523
                cn_count++;
7524
              else
7525
                c_count++;
7526
            }
7527
        }
7528
      else
7529
        {
7530
          if (bt == 'D')
7531
            n_db++;
7532
        }
7533
    }
7534
  /* new in v0.3b */
7535
  if (is_oxo_C (a_view))
7536
    {
7537
      fg[fg_carbonyl - 1] = true;
7538
      if (c_count + cn_count < 2)
7539
        {                       /* new in v0.3b (detection of ketenes) */
7540
          if (n_db <= 1)
7541
            fg[fg_aldehyde - 1] = true;
7542
          else
7543
            fg[fg_ketene - 1] = true;
7544
        }
7545
      if (c_count == 2)
7546
        {
7547
          if (atom[a_view - 1].arom)
7548
            fg[fg_oxohetarene - 1] = true;
7549
          else
7550
            fg[fg_ketone - 1] = true;
7551
        }
7552
      if (cn_count > 0)
7553
        fg[fg_acyl_cyanide - 1] = true;
7554
    }
7555
  if (is_thioxo_C (a_view))
7556
    {
7557
      fg[fg_thiocarbonyl - 1] = true;
7558
      if (c_count < 2)
7559
        fg[fg_thioaldehyde - 1] = true;
7560
      if (c_count == 2)
7561
        {
7562
          if (atom[a_view - 1].arom)
7563
            fg[fg_thioxohetarene - 1] = true;
7564
          else
7565
            fg[fg_thioketone - 1] = true;
7566
        }
7567
    }
7568
  if (is_imino_C (a_view))
7569
    chk_imine (a_view, a_ref);
7570
}
7571
 
7572
 
7573
static void
7574
chk_carboxyl_deriv (a_view, a_ref)
7575
     int a_view, a_ref;
7576
{
7577
  int i;
7578
  neighbor_rec nb;
7579
  str2 nb_el;
7580
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 7581
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 7582
 
7583
  memset (nb, 0, sizeof (neighbor_rec));
7584
  get_neighbors (nb, a_view);
7585
  FORLIM = atom[a_view - 1].neighbor_count;
7586
  for (i = 0; i < FORLIM; i++)
7587
    {
7588
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
7589
        {
7590
          strcpy (nb_el, atom[nb[i] - 1].element);
7591
          if (strcmp (nb_el, "C "))
7592
            {
7593
              if (!strcmp (nb_el, "O "))
7594
                {
7595
                  o_count++;
7596
                  a_o = nb[i];
7597
                }
7598
              if (!strcmp (nb_el, "N "))
7599
                {
7600
                  n_count++;
7601
                  a_n = nb[i];
7602
                }
7603
              if (!strcmp (nb_el, "S "))
7604
                {
7605
                  s_count++;
7606
                  a_s = nb[i];
7607
                }
7608
            }
7609
        }
7610
    }
7611
  if (is_oxo_C (a_view))
7612
    {
7613
      if (o_count == 1)
7614
        {                       /* anhydride is checked somewhere else */
7615
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7616
            fg[fg_carboxylic_acid_deriv - 1] = true;
7617
          if (is_hydroxy (a_view, a_o))
7618
            {
7619
              if (atom[a_o - 1].formal_charge == 0)
7620
                fg[fg_carboxylic_acid - 1] = true;
7621
              if (atom[a_o - 1].formal_charge == -1)
7622
                fg[fg_carboxylic_acid_salt - 1] = true;
7623
            }
7624
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
7625
              is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o))
7626
            {
7627
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
7628
                fg[fg_carboxylic_acid_ester - 1] = true;
7629
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0)
7630
                {
7631
                  if (bond[get_bond (a_view, a_o) - 1].arom == true)
7632
                    {
7633
                      /*fg[fg_lactone_heteroarom] := true else fg[fg_lactone] := true; */
7634
                      fg[fg_oxohetarene - 1] = true;
7635
                    }
7636
                  else
7637
                    fg[fg_lactone - 1] = true;
7638
                }
7639
            }
7640
        }
7641
      if (n_count == 1)
7642
        {
7643
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7644
            fg[fg_carboxylic_acid_deriv - 1] = true;
7645
          else
7646
            {
7647
              /*fg[fg_lactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
7648
              fg[fg_oxohetarene - 1] = true;
7649
            }
7650
          if (is_amino (a_view, a_n)
7651
              || (!strcmp (atom[a_n - 1].atype, "NAM")
7652
                  && atom[a_n - 1].neighbor_count == 1))
7653
            {
7654
              fg[fg_carboxylic_acid_amide - 1] = true;
7655
              fg[fg_carboxylic_acid_prim_amide - 1] = true;
7656
            }
7657
          /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
7658
          if (is_C_monosubst_amino (a_view, a_n) &
7659
              (!is_subst_acylamino (a_view, a_n)))
7660
            {                   /* v0.3j */
7661
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7662
                fg[fg_carboxylic_acid_amide - 1] = true;
7663
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7664
                fg[fg_carboxylic_acid_sec_amide - 1] = true;
7665
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7666
                {
7667
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7668
                    {
7669
                      /*fg[fg_lactam_heteroarom]    := true else  */
7670
                      fg[fg_oxohetarene - 1] = true;
7671
                    }
7672
                  else
7673
                    fg[fg_lactam - 1] = true;
7674
                }
7675
            }
7676
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
7677
          /*   (is_diarylamino(a_view,a_n)) then  */
7678
          if (is_C_disubst_amino (a_view, a_n) &
7679
              (!is_subst_acylamino (a_view, a_n)))
7680
            {                   /* v0.3j */
7681
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7682
                fg[fg_carboxylic_acid_amide - 1] = true;
7683
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7684
                fg[fg_carboxylic_acid_tert_amide - 1] = true;
7685
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7686
                {
7687
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7688
                    {
7689
                      /*fg[fg_lactam_heteroarom]    := true else  */
7690
                      fg[fg_oxohetarene - 1] = true;
7691
                    }
7692
                  else
7693
                    fg[fg_lactam - 1] = true;
7694
                }
7695
            }
7696
          if (is_hydroxylamino (a_view, a_n))
7697
            fg[fg_hydroxamic_acid - 1] = true;
7698
          if (is_hydrazino (a_view, a_n))
7699
            fg[fg_carboxylic_acid_hydrazide - 1] = true;
7700
          if (is_azido (a_view, a_n))
7701
            fg[fg_carboxylic_acid_azide - 1] = true;
7702
        }
7703
      if (s_count == 1)
7704
        {                       /* anhydride is checked somewhere else */
7705
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7706
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7707
          if (is_sulfanyl (a_view, a_s))
7708
            fg[fg_thiocarboxylic_acid - 1] = true;
7709
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7710
            {
7711
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7712
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7713
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0)
7714
                {
7715
                  if (bond[get_bond (a_view, a_s) - 1].arom == true)
7716
                    {
7717
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7718
                      fg[fg_oxohetarene - 1] = true;
7719
                    }
7720
                  else
7721
                    fg[fg_thiolactone - 1] = true;
7722
                }
7723
            }
7724
        }
7725
    }                           /* end Oxo-C */
7726
  if (is_thioxo_C (a_view))
7727
    {
7728
      /* fg[fg_thiocarboxylic_acid_deriv]  := true; */
7729
      if (o_count == 1)
7730
        {                       /* anhydride is checked somewhere else */
7731
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7732
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7733
          if (is_hydroxy (a_view, a_o))
7734
            fg[fg_thiocarboxylic_acid - 1] = true;      /* fixed in v0.3c */
7735
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o))
7736
            {
7737
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7738
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7739
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0)
7740
                {
7741
                  if (bond[get_bond (a_view, a_o) - 1].arom == true)
7742
                    {
7743
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7744
                      fg[fg_thioxohetarene - 1] = true;
7745
                    }
7746
                  else
7747
                    fg[fg_thiolactone - 1] = true;
7748
                }
7749
            }
7750
        }
7751
      if (n_count == 1)
7752
        {
7753
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7754
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7755
          else
7756
            {
7757
              /*fg[fg_thiolactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
7758
              fg[fg_thioxohetarene - 1] = true;
7759
            }
7760
          /* catches also pyridazines, 1,2,3-triazines, etc. */
7761
          if (is_amino (a_view, a_n))
7762
            {
7763
              fg[fg_thiocarboxylic_acid_amide - 1] = true;
7764
              /* fg[fg_thiocarboxylic_acid_prim_amide] := true; */
7765
            }
7766
          /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
7767
          if (is_C_monosubst_amino (a_view, a_n) &
7768
              (!is_subst_acylamino (a_view, a_n)))
7769
            {                   /* v0.3j */
7770
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7771
                fg[fg_thiocarboxylic_acid_amide - 1] = true;
7772
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := true; */
7773
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7774
                {
7775
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7776
                    {
7777
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
7778
                      fg[fg_thioxohetarene - 1] = true;
7779
                    }
7780
                  else
7781
                    fg[fg_thiolactam - 1] = true;
7782
                }
7783
            }
7784
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
7785
          /*   (is_diarylamino(a_view,a_n)) then  */
7786
          if (is_C_disubst_amino (a_view, a_n) &
7787
              (!is_subst_acylamino (a_view, a_n)))
7788
            {                   /* v0.3j */
7789
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7790
                fg[fg_thiocarboxylic_acid_amide - 1] = true;
7791
              /*fg[fg_thiocarboxylic_acid_tert_amide] := true; */
7792
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0)
7793
                {
7794
                  if (bond[get_bond (a_view, a_n) - 1].arom == true)
7795
                    {
7796
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
7797
                      fg[fg_thioxohetarene - 1] = true;
7798
                    }
7799
                  else
7800
                    fg[fg_thiolactam - 1] = true;
7801
                }
7802
            }
7803
        }
7804
      if (s_count == 1)
7805
        {                       /* anhydride is checked somewhere else */
7806
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7807
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7808
          if (is_sulfanyl (a_view, a_s))
7809
            fg[fg_thiocarboxylic_acid - 1] = true;
7810
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7811
            {
7812
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7813
                fg[fg_thiocarboxylic_acid_ester - 1] = true;
7814
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0)
7815
                {
7816
                  if (bond[get_bond (a_view, a_s) - 1].arom == true)
7817
                    {
7818
                      /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7819
                      fg[fg_thioxohetarene - 1] = true;
7820
                    }
7821
                  else
7822
                    fg[fg_thiolactone - 1] = true;
7823
                }
7824
            }
7825
        }
7826
    }                           /* end Thioxo-C */
7827
  if (is_true_imino_C (a_view))
7828
    {
7829
      if (o_count == 1)
7830
        {
7831
          if (bond[get_bond (a_view, a_o) - 1].arom == false)
7832
            fg[fg_carboxylic_acid_deriv - 1] = true;
7833
          if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o))
7834
            {
7835
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
7836
                fg[fg_imido_ester - 1] = true;
7837
            }
7838
        }
7839
      if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == false))
7840
        {
7841
          if (bond[get_bond (a_view, a_n) - 1].arom == false)
7842
            fg[fg_carboxylic_acid_deriv - 1] = true;
7843
          if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7844
            {
7845
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7846
                fg[fg_carboxylic_acid_deriv - 1] = true;
7847
              fg[fg_carboxylic_acid_amidine - 1] = true;
7848
            }
7849
          if (is_hydrazino (a_view, a_n))
7850
            {
7851
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
7852
                fg[fg_carboxylic_acid_amidrazone - 1] = true;
7853
            }
7854
        }
7855
      if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == true))
7856
        /* catches also pyridazines, 1,2,3-triazines, etc. */
7857
        fg[fg_iminohetarene - 1] = true;
7858
      if (s_count == 1)
7859
        {
7860
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
7861
            fg[fg_carboxylic_acid_deriv - 1] = true;
7862
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s))
7863
            {
7864
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
7865
                fg[fg_imido_thioester - 1] = true;
7866
            }
7867
        }
7868
    }
7869
  if (is_hydroximino_C (a_view))
7870
    {
7871
      if (bond[get_bond (a_view, a_n) - 1].arom == false)
7872
        fg[fg_carboxylic_acid_deriv - 1] = true;
7873
      if (o_count == 1)
7874
        {
7875
          if (is_hydroxy (a_view, a_o))
7876
            fg[fg_hydroxamic_acid - 1] = true;
7877
        }
7878
    }
7879
  if (!is_hydrazono_C (a_view))
7880
    return;
7881
  if (bond[get_bond (a_view, a_n) - 1].arom == false)
7882
    fg[fg_carboxylic_acid_deriv - 1] = true;
7883
  if (n_count == 1)
7884
    {
7885
      if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7886
        fg[fg_carboxylic_acid_amidrazone - 1] = true;
7887
    }
7888
}
7889
 
7890
 
7891
static void
7892
chk_co2_sp2 (a_view, a_ref)
7893
     int a_view, a_ref;
7894
{
7895
  int i;
7896
  neighbor_rec nb;
7897
  str2 nb_el;
7898
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
7899
    s_count = 0, sr_count = 0;
7900
  int FORLIM;
7901
 
7902
  memset (nb, 0, sizeof (neighbor_rec));
7903
  get_neighbors (nb, a_view);
7904
  FORLIM = atom[a_view - 1].neighbor_count;
7905
  for (i = 0; i < FORLIM; i++)
7906
    {
7907
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
7908
        {
7909
          strcpy (nb_el, atom[nb[i] - 1].element);
7910
          if (strcmp (nb_el, "C "))
7911
            {
7912
              if (!strcmp (nb_el, "O "))
7913
                {
7914
                  o_count++;
7915
                  if (is_alkoxy (a_view, nb[i]) |
7916
                      is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,
7917
                                                                   nb[i]))
7918
                    /* v0.3j */
7919
                    or_count++;
7920
                }
7921
              if (!strcmp (nb_el, "N "))
7922
                {
7923
                  n_count++;
7924
                  if (is_hydrazino (a_view, nb[i]))
7925
                    nn_count++;
7926
                  if (is_subst_hydrazino (a_view, nb[i]))       /* more general... */
7927
                    nnx_count++;
7928
                }
7929
              if (!strcmp (nb_el, "S "))
7930
                {
7931
                  s_count++;
7932
                  if (is_alkylsulfanyl (a_view, nb[i]) |
7933
                      is_arylsulfanyl (a_view, nb[i]))
7934
                    sr_count++;
7935
                }
7936
            }
7937
        }
7938
    }
7939
  if (is_oxo_C (a_view))
7940
    {
7941
      if (o_count == 2)
7942
        {
7943
          fg[fg_carbonic_acid_deriv - 1] = true;
7944
          if (or_count == 1)
7945
            fg[fg_carbonic_acid_monoester - 1] = true;
7946
          if (or_count == 2)
7947
            fg[fg_carbonic_acid_diester - 1] = true;
7948
        }
7949
      if (o_count == 1 && s_count == 1)
7950
        {
7951
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7952
          if (or_count + sr_count == 1)
7953
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7954
          if (or_count + sr_count == 2)
7955
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7956
        }
7957
      if (s_count == 2)
7958
        {
7959
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7960
          if (sr_count == 1)
7961
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7962
          if (sr_count == 2)
7963
            fg[fg_thiocarbonic_acid_diester - 1] = true;
7964
        }
7965
      if (o_count == 1 && n_count == 1)
7966
        {
7967
          fg[fg_carbamic_acid_deriv - 1] = true;
7968
          if (or_count == 0)
7969
            fg[fg_carbamic_acid - 1] = true;
7970
          if (or_count == 1)
7971
            fg[fg_carbamic_acid_ester - 1] = true;
7972
        }
7973
      if (s_count == 1 && n_count == 1)
7974
        {
7975
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
7976
          if (sr_count == 0)
7977
            fg[fg_thiocarbamic_acid - 1] = true;
7978
          if (sr_count == 1)
7979
            fg[fg_thiocarbamic_acid_ester - 1] = true;
7980
        }
7981
      if (n_count == 2)
7982
        {
7983
          if (nn_count == 1)
7984
            fg[fg_semicarbazide - 1] = true;
7985
          else
7986
            {
7987
              if (nnx_count == 0)       /* excludes semicarbazones */
7988
                fg[fg_urea - 1] = true;
7989
            }
7990
        }
7991
    }                           /* end Oxo-C */
7992
  if (is_thioxo_C (a_view))
7993
    {
7994
      if (o_count == 2)
7995
        {
7996
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
7997
          if (or_count == 1)
7998
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
7999
          if (or_count == 2)
8000
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8001
        }
8002
      if (o_count == 1 && s_count == 1)
8003
        {
8004
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8005
          if (or_count + sr_count == 1)
8006
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8007
          if (or_count + sr_count == 2)
8008
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8009
        }
8010
      if (s_count == 2)
8011
        {
8012
          fg[fg_thiocarbonic_acid_deriv - 1] = true;
8013
          if (sr_count == 1)
8014
            fg[fg_thiocarbonic_acid_monoester - 1] = true;
8015
          if (sr_count == 2)
8016
            fg[fg_thiocarbonic_acid_diester - 1] = true;
8017
        }
8018
      if (o_count == 1 && n_count == 1)
8019
        {
8020
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
8021
          if (or_count == 0)
8022
            fg[fg_thiocarbamic_acid - 1] = true;
8023
          if (or_count == 1)
8024
            fg[fg_thiocarbamic_acid_ester - 1] = true;
8025
        }
8026
      if (s_count == 1 && n_count == 1)
8027
        {
8028
          fg[fg_thiocarbamic_acid_deriv - 1] = true;
8029
          if (sr_count == 0)
8030
            fg[fg_thiocarbamic_acid - 1] = true;
8031
          if (sr_count == 1)
8032
            fg[fg_thiocarbamic_acid_ester - 1] = true;
8033
        }
8034
      if (n_count == 2)
8035
        {
8036
          if (nn_count == 1)
8037
            fg[fg_thiosemicarbazide - 1] = true;
8038
          else
8039
            {
8040
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
8041
                fg[fg_thiourea - 1] = true;
8042
            }
8043
        }
8044
    }                           /* end Thioxo-C */
8045
  if (!
8046
      (is_true_imino_C (a_view) &
8047
       (bond[get_bond (a_view, a_ref) - 1].arom == false)))
8048
    {
8049
      return;
8050
    }                           /* end Imino-C */
8051
  if (o_count == 1 && n_count == 1)
8052
    fg[fg_isourea - 1] = true;
8053
  if (s_count == 1 && n_count == 1)
8054
    fg[fg_isothiourea - 1] = true;
8055
  if (n_count == 2)
8056
    fg[fg_guanidine - 1] = true;
8057
}
8058
 
8059
 
8060
static void
8061
chk_co2_sp (a_view, a_ref)
8062
     int a_view, a_ref;
8063
{
8064
  int i;
8065
  neighbor_rec nb;
8066
  str2 nb_el;
8067
  int o_count = 0, n_count = 0, s_count = 0;
8068
  int FORLIM;
8069
 
8070
  memset (nb, 0, sizeof (neighbor_rec));
8071
  get_neighbors (nb, a_view);
8072
  FORLIM = atom[a_view - 1].neighbor_count;
8073
  for (i = 0; i < FORLIM; i++)
8074
    {
8075
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')
8076
        {
8077
          strcpy (nb_el, atom[nb[i] - 1].element);
8078
          if (strcmp (nb_el, "C "))
8079
            {
8080
              if (!strcmp (nb_el, "O "))
8081
                o_count++;
8082
              if (!strcmp (nb_el, "N "))
8083
                n_count++;
8084
              if (!strcmp (nb_el, "S "))
8085
                s_count++;
8086
            }
8087
        }
8088
    }
8089
  if (o_count + s_count == 2)   /* new in v0.3b */
8090
    fg[fg_co2_deriv - 1] = true;
8091
  if (o_count == 1 && n_count == 1)
8092
    fg[fg_isocyanate - 1] = true;
8093
  if (s_count == 1 && n_count == 1)
8094
    fg[fg_isothiocyanate - 1] = true;
8095
  if (n_count == 2)
8096
    fg[fg_carbodiimide - 1] = true;
8097
}
8098
 
8099
 
8100
static void
8101
chk_triple (a1, a2)
8102
     int a1, a2;
8103
{
8104
  str2 a1_el, a2_el;
8105
 
8106
  strcpy (a1_el, atom[a1 - 1].element);
8107
  strcpy (a2_el, atom[a2 - 1].element);
8108
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &
8109
      (bond[get_bond (a1, a2) - 1].arom == false))
8110
    fg[fg_alkyne - 1] = true;
8111
  if (is_nitrile (a1, a2))
8112
    fg[fg_nitrile - 1] = true;
8113
  if (is_isonitrile (a1, a2))
8114
    fg[fg_isonitrile - 1] = true;
8115
  if (is_cyanate (a1, a2))
8116
    fg[fg_cyanate - 1] = true;
8117
  if (is_thiocyanate (a1, a2))
8118
    fg[fg_thiocyanate - 1] = true;
8119
}
8120
 
8121
 
8122
static void
8123
chk_ccx (a_view, a_ref)
8124
     int a_view, a_ref;
8125
{
8126
  int i;
8127
  neighbor_rec nb;
8128
  int oh_count = 0, or_count = 0, n_count = 0;
8129
  int FORLIM;
8130
 
8131
  memset (nb, 0, sizeof (neighbor_rec));
8132
  get_neighbors (nb, a_ref);
8133
  FORLIM = atom[a_ref - 1].neighbor_count;
8134
  for (i = 0; i < FORLIM; i++)
8135
    {
8136
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
8137
        {
8138
          if (is_hydroxy (a_ref, nb[i]))
8139
            oh_count++;
8140
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8141
              is_siloxy (a_ref, nb[i]))
8142
            or_count++;
8143
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8144
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8145
            n_count++;
8146
        }
8147
    }
8148
  if (oh_count == 1)
8149
    fg[fg_enol - 1] = true;
8150
  if (or_count == 1)
8151
    fg[fg_enolether - 1] = true;
8152
  if (n_count == 1)
8153
    fg[fg_enamine - 1] = true;
8154
  /* new in v0.2f   (regard anything else as an alkene) */
8155
  if (oh_count + or_count + n_count == 0)
8156
    fg[fg_alkene - 1] = true;
8157
}
8158
 
8159
 
8160
static void
8161
chk_xccx (a_view, a_ref)
8162
     int a_view, a_ref;
8163
{
8164
  int i;
8165
  neighbor_rec nb;
8166
  int oh_count = 0, or_count = 0, n_count = 0;
8167
  int FORLIM;
8168
 
8169
  memset (nb, 0, sizeof (neighbor_rec));
8170
  get_neighbors (nb, a_view);
8171
  FORLIM = atom[a_view - 1].neighbor_count;
8172
  for (i = 0; i < FORLIM; i++)
8173
    {
8174
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
8175
        {
8176
          if (is_hydroxy (a_view, nb[i]))
8177
            oh_count++;
8178
          if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
8179
              is_siloxy (a_view, nb[i]))
8180
            or_count++;
8181
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8182
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8183
            n_count++;
8184
        }
8185
    }
8186
  memset (nb, 0, sizeof (neighbor_rec));
8187
  get_neighbors (nb, a_ref);
8188
  FORLIM = atom[a_ref - 1].neighbor_count;
8189
  for (i = 0; i < FORLIM; i++)
8190
    {
8191
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
8192
        {
8193
          if (is_hydroxy (a_ref, nb[i]))
8194
            oh_count++;
8195
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8196
              is_siloxy (a_ref, nb[i]))
8197
            or_count++;
8198
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8199
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
8200
            n_count++;
8201
        }
8202
    }
8203
  if (oh_count == 2)
8204
    fg[fg_enediol - 1] = true;
8205
  /* new in v0.2f   (regard anything else as an alkene) */
8206
  if (oh_count + or_count + n_count == 0)
8207
    fg[fg_alkene - 1] = true;
8208
}
8209
 
8210
 
8211
static void
8212
chk_n_o_dbl (a1, a2)
8213
     int a1, a2;
8214
{
8215
  int i;
8216
  neighbor_rec nb;
8217
  str2 nb_el;
8218
  int or_count = 0, n_count = 0, c_count = 0;
8219
  int b;                        /* v0.3j */
8220
  int het_count = 0;            /* v0.3k */
8221
  char bt;                      /* v0.3k */
8222
  float bo_sum = 0.0;           /* v0.3k */
8223
  int FORLIM;
8224
 
8225
  memset (nb, 0, sizeof (neighbor_rec));
8226
  get_neighbors (nb, a1);
8227
  FORLIM = atom[a1 - 1].neighbor_count;
8228
  /* v0.3k */
8229
  /* v0.3k */
8230
  for (i = 0; i < FORLIM; i++)
8231
    {
8232
      if (nb[i] != a2)
8233
        {
8234
          b = get_bond (a1, nb[i]);     /* v0.3j */
8235
          strcpy (nb_el, atom[nb[i] - 1].element);
8236
          bt = bond[b - 1].btype;       /* v0.3k */
8237
          if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
8238
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
8239
              && strcmp (nb_el, "LP") && bond[b - 1].arom == false)
8240
            /* added 'D ' in v0.3n */
8241
            het_count++;
8242
          /* v0.3k: ignore hetero atoms */
8243
          /* in aromatic rings like isoxazole  */
8244
          if (bt == 'S')
8245
            bo_sum += 1.0;
8246
          if (bt == 'D')
8247
            bo_sum += 2.0;
8248
          if (bt == 'A')
8249
            bo_sum += 1.5;
8250
          if (!strcmp (nb_el, "O "))
8251
            or_count++;
8252
          if (!strcmp (nb_el, "N "))
8253
            n_count++;
8254
          if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')        /* v0.3k */
8255
            c_count++;
8256
          /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
8257
        }
8258
    }
8259
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2)
8260
    {                           /* excludes nitro etc. */
8261
      if (or_count == 1)
8262
        fg[fg_nitrite - 1] = true;
8263
      if (c_count == 1)
8264
        fg[fg_nitroso_compound - 1] = true;
8265
      if (n_count == 1)         /* instead of nitrosamine  v0.3j */
8266
        fg[fg_nitroso_compound - 1] = true;
8267
      /*if (n_count = 1) then fg[fg_nitrosamine]   := true;  (* still missing */
8268
    }
8269
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
8270
  /*  begin */
8271
  /*    fg[fg_n_oxide] := true; */
8272
  /*  end; */
8273
  /* new approach in v0.3k */
8274
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
8275
    fg[fg_n_oxide - 1] = true;
8276
}
8277
 
8278
 
8279
static void
8280
chk_sulfoxide (a1, a2)
8281
     int a1, a2;
8282
{
8283
  int i;
8284
  neighbor_rec nb;
8285
  str2 nb_el;
8286
  int o_count = 0, c_count = 0;
8287
  int FORLIM;
8288
 
8289
  memset (nb, 0, sizeof (neighbor_rec));
8290
  get_neighbors (nb, a1);
8291
  FORLIM = atom[a1 - 1].neighbor_count;
8292
  for (i = 0; i < FORLIM; i++)
8293
    {
8294
      strcpy (nb_el, atom[nb[i] - 1].element);
8295
      if (!strcmp (nb_el, "O "))
8296
        o_count++;
8297
      if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
8298
        c_count++;
8299
    }
8300
  if (o_count == 1 && c_count == 2)
8301
    fg[fg_sulfoxide - 1] = true;
8302
}
8303
 
8304
 
8305
static void
8306
chk_double (a1, a2)
8307
     int a1, a2;
8308
{
8309
  str2 a1_el, a2_el;
8310
 
8311
  strcpy (a1_el, atom[a1 - 1].element);
8312
  strcpy (a2_el, atom[a2 - 1].element);
8313
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &
8314
      (bond[get_bond (a1, a2) - 1].arom == false))
8315
    {
8316
      if (hetbond_count (a1) == 2)
8317
        chk_carbonyl_deriv (a1, a2);
8318
      if (hetbond_count (a1) == 3)
8319
        chk_carboxyl_deriv (a1, a2);
8320
      if (hetbond_count (a1) == 4)
8321
        {
8322
          if (!strcmp (atom[a1 - 1].atype, "C2 "))
8323
            chk_co2_sp2 (a1, a2);
8324
          if (!strcmp (atom[a1 - 1].atype, "C1 "))
8325
            chk_co2_sp (a1, a2);
8326
        }
8327
    }                           /* end C=X */
8328
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
8329
       && !strcmp (atom[a2 - 1].atype,
8330
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == false))
8331
    {
8332
      if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
8333
        fg[fg_ketene_acetal_deriv - 1] = true;
8334
      if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
8335
        chk_ccx (a1, a2);
8336
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8337
        chk_xccx (a1, a2);
8338
      if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
8339
          atom[a1 - 1].arom == false && atom[a2 - 1].arom == false)
8340
        fg[fg_alkene - 1] = true;
8341
    }
8342
  if (((!strcmp (a1_el, "N ")
8343
        && !strcmp (a2_el,
8344
                    "N ")) && (hetbond_count (a1) ==
8345
                               2) && (hetbond_count (a2) ==
8346
                                      2) && (bond[get_bond (a1, a2) -
8347
                                                  1].arom == false))
8348
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
8349
    fg[fg_azo_compound - 1] = true;
8350
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
8351
    chk_n_o_dbl (a1, a2);
8352
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
8353
    chk_sulfoxide (a1, a2);
8354
}
8355
 
8356
 
8357
static void
8358
chk_c_hal (a1, a2)
8359
     int a1, a2;
8360
{
8361
  str2 a2_el;
8362
 
8363
  strcpy (a2_el, atom[a2 - 1].element);
8364
  fg[fg_halogen_deriv - 1] = true;
8365
  if (atom[a1 - 1].arom)
8366
    {
8367
      fg[fg_aryl_halide - 1] = true;
8368
      if (!strcmp (a2_el, "F "))
8369
        fg[fg_aryl_fluoride - 1] = true;
8370
      if (!strcmp (a2_el, "CL"))
8371
        fg[fg_aryl_chloride - 1] = true;
8372
      if (!strcmp (a2_el, "BR"))
8373
        fg[fg_aryl_bromide - 1] = true;
8374
      if (!strcmp (a2_el, "I "))
8375
        fg[fg_aryl_iodide - 1] = true;
8376
      return;
8377
    }
8378
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2))
8379
    {                           /* alkyl halides */
8380
      fg[fg_alkyl_halide - 1] = true;
8381
      if (!strcmp (a2_el, "F "))
8382
        fg[fg_alkyl_fluoride - 1] = true;
8383
      if (!strcmp (a2_el, "CL"))
8384
        fg[fg_alkyl_chloride - 1] = true;
8385
      if (!strcmp (a2_el, "BR"))
8386
        fg[fg_alkyl_bromide - 1] = true;
8387
      if (!strcmp (a2_el, "I "))
8388
        fg[fg_alkyl_iodide - 1] = true;
8389
    }
8390
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3))
8391
    {                           /* acyl halides and related compounds */
8392
      if (is_oxo_C (a1))
8393
        {
8394
          fg[fg_acyl_halide - 1] = true;
8395
          if (!strcmp (a2_el, "F "))
8396
            fg[fg_acyl_fluoride - 1] = true;
8397
          if (!strcmp (a2_el, "CL"))
8398
            fg[fg_acyl_chloride - 1] = true;
8399
          if (!strcmp (a2_el, "BR"))
8400
            fg[fg_acyl_bromide - 1] = true;
8401
          if (!strcmp (a2_el, "I "))
8402
            fg[fg_acyl_iodide - 1] = true;
8403
        }
8404
      if (is_thioxo_C (a1))
8405
        fg[fg_thiocarboxylic_acid_deriv - 1] = true;
8406
      if (is_imino_C (a1))
8407
        fg[fg_imidoyl_halide - 1] = true;
8408
    }
8409
  if (!
8410
      ((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
8411
       && (hetbond_count (a1) == 4)))
8412
    /* chloroformates etc. */
8413
    return;
8414
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
8415
  fg[fg_co2_deriv - 1] = true;
8416
  if (is_oxo_C (a1))
8417
    {
8418
      fg[fg_carbonic_acid_deriv - 1] = true;
8419
      if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
8420
        fg[fg_carbonic_acid_ester_halide - 1] = true;
8421
      if (is_carbamoyl (a2, a1))
8422
        {
8423
          fg[fg_carbamic_acid_deriv - 1] = true;
8424
          fg[fg_carbamic_acid_halide - 1] = true;
8425
        }
8426
    }
8427
  if (!is_thioxo_C (a1))
8428
    return;
8429
  fg[fg_thiocarbonic_acid_deriv - 1] = true;
8430
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
8431
    fg[fg_thiocarbonic_acid_ester_halide - 1] = true;
8432
  if (is_thiocarbamoyl (a2, a1))
8433
    {
8434
      fg[fg_thiocarbamic_acid_deriv - 1] = true;
8435
      fg[fg_thiocarbamic_acid_halide - 1] = true;
8436
      /* end of non-aromatic halogen compounds */
8437
    }
8438
}
8439
 
8440
 
8441
static void
8442
chk_c_o (a1, a2)
8443
     int a1, a2;
8444
{
8445
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
8446
  if (bond[get_bond (a1, a2) - 1].arom == true)
8447
    return;
8448
  if (is_true_alkyl (a2, a1) && is_hydroxy (a1, a2))
8449
    {
8450
      fg[fg_hydroxy - 1] = true;
8451
      fg[fg_alcohol - 1] = true;
8452
      if (atom[a1 - 1].neighbor_count <= 2)
8453
        fg[fg_prim_alcohol - 1] = true;
8454
      if (atom[a1 - 1].neighbor_count == 3)
8455
        fg[fg_sec_alcohol - 1] = true;
8456
      if (atom[a1 - 1].neighbor_count == 4)
8457
        fg[fg_tert_alcohol - 1] = true;
8458
    }
8459
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2))
8460
    {
8461
      fg[fg_hydroxy - 1] = true;
8462
      fg[fg_phenol - 1] = true;
8463
    }
8464
  if (is_true_alkyl (a2, a1) && is_true_alkoxy (a1, a2))
8465
    {
8466
      fg[fg_ether - 1] = true;
8467
      fg[fg_dialkylether - 1] = true;
8468
    }
8469
  if ((is_true_alkyl (a2, a1) && is_aryloxy (a1, a2)) |
8470
      (is_aryl (a2, a1) && is_true_alkoxy (a1, a2)))
8471
    {
8472
      fg[fg_ether - 1] = true;
8473
      fg[fg_alkylarylether - 1] = true;
8474
    }
8475
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2))
8476
    {
8477
      fg[fg_ether - 1] = true;
8478
      fg[fg_diarylether - 1] = true;
8479
    }
8480
  if ((is_true_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2))
8481
    {
8482
      fg[fg_ether - 1] = true;
8483
      ether_generic = true;
8484
    }
8485
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2))
8486
    {
8487
      fg[fg_hydroxy - 1] = true;
8488
      hydroxy_generic = true;
8489
    }
8490
 
8491
}
8492
 
8493
 
8494
static void
8495
chk_c_s (a1, a2)
8496
     int a1, a2;
8497
{
8498
  int i;
8499
  neighbor_rec nb;
8500
  str2 nb_el;
8501
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
8502
    hal_count = 0;
8503
  int FORLIM;
8504
 
8505
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
8506
  if (bond[get_bond (a1, a2) - 1].arom == true)
8507
    return;
8508
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2))
8509
    {
8510
      fg[fg_thiol - 1] = true;
8511
      fg[fg_alkylthiol - 1] = true;
8512
    }
8513
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2))
8514
    {
8515
      fg[fg_thiol - 1] = true;
8516
      fg[fg_arylthiol - 1] = true;
8517
    }
8518
  if (is_true_alkyl (a2, a1) && is_true_alkylsulfanyl (a1, a2))
8519
    fg[fg_thioether - 1] = true;
8520
  if ((is_true_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) |
8521
      (is_aryl (a2, a1) && is_true_alkylsulfanyl (a1, a2)))
8522
    fg[fg_thioether - 1] = true;
8523
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
8524
    fg[fg_thioether - 1] = true;
8525
  /* check for sulfinic/sulfenic acid derivatives */
8526
  memset (nb, 0, sizeof (neighbor_rec));
8527
  get_neighbors (nb, a2);
8528
  FORLIM = atom[a2 - 1].neighbor_count;
8529
  for (i = 0; i < FORLIM; i++)
8530
    {
8531
      strcpy (nb_el, atom[nb[i] - 1].element);
8532
      if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
8533
        c_count++;
8534
      if (is_hydroxy (a2, nb[i]))
8535
        oh_count++;
8536
      if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
8537
        or_count++;
8538
      if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
8539
        n_count++;
8540
      if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
8541
          !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
8542
        hal_count++;
8543
      if (!strcmp (nb_el, "O "))
8544
        o_count++;
8545
    }
8546
  if (c_count != 1)
8547
    return;
8548
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1)
8549
    {                           /* sulfinic acid && derivs */
8550
      fg[fg_sulfinic_acid_deriv - 1] = true;
8551
      if (oh_count == 1)
8552
        fg[fg_sulfinic_acid - 1] = true;
8553
      if (or_count == 1)
8554
        fg[fg_sulfinic_acid_ester - 1] = true;
8555
      if (hal_count == 1)
8556
        fg[fg_sulfinic_acid_halide - 1] = true;
8557
      if (n_count == 1)
8558
        fg[fg_sulfinic_acid_amide - 1] = true;
8559
    }
8560
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
8561
    /* sulfenic acid && derivs */
8562
    return;
8563
 
8564
  fg[fg_sulfenic_acid_deriv - 1] = true;
8565
  if (oh_count == 1)
8566
    fg[fg_sulfenic_acid - 1] = true;
8567
  if (or_count == 1)
8568
    fg[fg_sulfenic_acid_ester - 1] = true;
8569
  if (hal_count == 1)
8570
    fg[fg_sulfenic_acid_halide - 1] = true;
8571
  if (n_count == 1)
8572
    fg[fg_sulfenic_acid_amide - 1] = true;
8573
}
8574
 
8575
 
8576
static void
8577
chk_c_n (a1, a2)
8578
     int a1, a2;
8579
{
8580
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
8581
  if (atom[a2 - 1].arom == true)
8582
    return;
8583
  if (is_true_alkyl (a2, a1) && is_amino (a1, a2))
8584
    {
8585
      fg[fg_amine - 1] = true;
8586
      fg[fg_prim_amine - 1] = true;
8587
      fg[fg_prim_aliph_amine - 1] = true;
8588
    }
8589
  if (is_aryl (a2, a1) && is_amino (a1, a2))
8590
    {
8591
      fg[fg_amine - 1] = true;
8592
      fg[fg_prim_amine - 1] = true;
8593
      fg[fg_prim_arom_amine - 1] = true;
8594
    }
8595
  if (is_true_alkyl (a2, a1) && is_true_alkylamino (a1, a2))
8596
    {
8597
      fg[fg_amine - 1] = true;
8598
      fg[fg_sec_amine - 1] = true;
8599
      fg[fg_sec_aliph_amine - 1] = true;
8600
    }
8601
  if (is_aryl (a2, a1) && is_true_alkylamino (a1, a2))
8602
    {
8603
      fg[fg_amine - 1] = true;
8604
      fg[fg_sec_amine - 1] = true;
8605
      fg[fg_sec_mixed_amine - 1] = true;
8606
    }
8607
  if (is_aryl (a2, a1) && is_arylamino (a1, a2))
8608
    {
8609
      fg[fg_amine - 1] = true;
8610
      fg[fg_sec_amine - 1] = true;
8611
      fg[fg_sec_arom_amine - 1] = true;
8612
    }
8613
  if (is_true_alkyl (a2, a1) && is_true_dialkylamino (a1, a2))
8614
    {
8615
      fg[fg_amine - 1] = true;
8616
      fg[fg_tert_amine - 1] = true;
8617
      fg[fg_tert_aliph_amine - 1] = true;
8618
    }
8619
  if ((is_true_alkyl (a2, a1) && is_diarylamino (a1, a2)) |
8620
      (is_aryl (a2, a1) && is_true_dialkylamino (a1, a2)))
8621
    {
8622
      fg[fg_amine - 1] = true;
8623
      fg[fg_tert_amine - 1] = true;
8624
      fg[fg_tert_mixed_amine - 1] = true;
8625
    }
8626
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2))
8627
    {
8628
      fg[fg_amine - 1] = true;
8629
      fg[fg_tert_amine - 1] = true;
8630
      fg[fg_tert_arom_amine - 1] = true;
8631
    }
8632
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8633
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2,
8634
                                                                          a1)
8635
                                                             == false))
8636
    /* v0.3k */
8637
    fg[fg_hydroxylamine - 1] = true;
8638
  /* v0.3k */
8639
  /* v0.3k  */
8640
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) |
8641
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
8642
    fg[fg_hydrazine - 1] = true;
8643
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8644
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
8645
    /* v0.3k */
8646
    fg[fg_azide - 1] = true;
8647
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8648
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
8649
    /* v0.3k */
8650
    fg[fg_diazonium_salt - 1] = true;
8651
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
8652
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
8653
    /* v0.3k */
8654
    fg[fg_nitro_compound - 1] = true;
8655
  if (is_alkynyl (a2, a1) &
8656
      (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
8657
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2)))))
8658
    {
8659
      fg[fg_amine - 1] = true;
8660
      amine_generic = true;
8661
    }
8662
}
8663
 
8664
 
8665
static void
8666
chk_c_c (a1, a2)
8667
     int a1, a2;
8668
{
8669
  int i;
8670
  neighbor_rec nb;
8671
  int oh_count, nhr_count, FORLIM;
8672
 
8673
  /* ignore aromatic rings */
8674
  if (atom[a2 - 1].arom == true)
8675
    return;
8676
  /*check for 1,2-diols and 1,2-aminoalcoholes */
8677
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
8678
      && !strcmp (atom[a2 - 1].atype, "C3 "))
8679
    {
8680
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8681
        {
8682
          oh_count = 0;
8683
          nhr_count = 0;
8684
          memset (nb, 0, sizeof (neighbor_rec));
8685
          get_neighbors (nb, a1);
8686
          FORLIM = atom[a1 - 1].neighbor_count;
8687
          for (i = 0; i < FORLIM; i++)
8688
            {
8689
              if (nb[i] != a2)
8690
                {
8691
                  if (is_hydroxy (a1, nb[i]))
8692
                    oh_count++;
8693
                  if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
8694
                      is_arylamino (a1, nb[i]))
8695
                    nhr_count++;
8696
                }
8697
            }
8698
          memset (nb, 0, sizeof (neighbor_rec));
8699
          get_neighbors (nb, a2);
8700
          FORLIM = atom[a2 - 1].neighbor_count;
8701
          for (i = 0; i < FORLIM; i++)
8702
            {
8703
              if (nb[i] != a1)
8704
                {
8705
                  if (is_hydroxy (a2, nb[i]))
8706
                    oh_count++;
8707
                  if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
8708
                      is_arylamino (a2, nb[i]))
8709
                    nhr_count++;
8710
                }
8711
            }
8712
          if (oh_count == 2)
8713
            fg[fg_1_2_diol - 1] = true;
8714
          if (oh_count == 1 && nhr_count == 1)
8715
            fg[fg_1_2_aminoalcohol - 1] = true;
8716
        }
8717
    }
8718
  /* check for alpha-aminoacids and alpha-hydroxyacids */
8719
  if (strcmp (atom[a1 - 1].atype, "C3 ")
8720
      || strcmp (atom[a2 - 1].atype, "C2 "))
8721
    return;
8722
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
8723
    return;
8724
  oh_count = 0;
8725
  nhr_count = 0;
8726
  memset (nb, 0, sizeof (neighbor_rec));
8727
  get_neighbors (nb, a1);
8728
  FORLIM = atom[a1 - 1].neighbor_count;
8729
  for (i = 0; i < FORLIM; i++)
8730
    {
8731
      if (nb[i] != a2)
8732
        {
8733
          if (is_hydroxy (a1, nb[i]))
8734
            oh_count++;
8735
          if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
8736
              is_arylamino (a1, nb[i]))
8737
            nhr_count++;
8738
        }
8739
    }
8740
  memset (nb, 0, sizeof (neighbor_rec));
8741
  get_neighbors (nb, a2);
8742
  FORLIM = atom[a2 - 1].neighbor_count;
8743
  for (i = 0; i < FORLIM; i++)
8744
    {
8745
      if (nb[i] != a1)
8746
        {
8747
          if (is_hydroxy (a2, nb[i]))
8748
            oh_count++;
8749
        }
8750
    }
8751
  if ((oh_count == 2) && is_oxo_C (a2))
8752
    fg[fg_alpha_hydroxyacid - 1] = true;
8753
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
8754
    fg[fg_alpha_aminoacid - 1] = true;
8755
}
8756
 
8757
 
8758
static void
8759
chk_x_y_single (a_view, a_ref)
8760
     int a_view, a_ref;
8761
{
8762
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
8763
      !strcmp (atom[a_ref - 1].atype, "O3 "))
8764
    {
8765
      if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
8766
        fg[fg_hydroperoxide - 1] = true;
8767
      if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
8768
           is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,
8769
                                                     a_ref) |
8770
                                          is_aryloxy (a_view,
8771
                                                      a_ref) |
8772
                                          is_siloxy (a_view, a_ref)))
8773
        fg[fg_peroxide - 1] = true;
8774
    }                           /* still missing: peracid */
8775
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
8776
      !strcmp (atom[a_ref - 1].atype, "S3 "))
8777
    {
8778
      if (atom[a_view - 1].neighbor_count == 2 &&
8779
          atom[a_ref - 1].neighbor_count == 2)
8780
        fg[fg_disulfide - 1] = true;
8781
    }
8782
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
8783
       !strcmp (atom[a_ref - 1].element,
8784
                "N ")) && (hetbond_count (a_view) ==
8785
                           1) && (hetbond_count (a_ref) == 1))
8786
    {
8787
      /*if ((is_amino(a_ref,a_view)) or  */
8788
      /*    (is_subst_amino(a_ref,a_view)) or */
8789
      /*    (is_acylamino(a_ref,a_view))) and */
8790
      /*   ((is_amino(a_view,a_ref)) or  */
8791
      /*    (is_subst_amino(a_view,a_ref)) or */
8792
      /*    (is_acylamino(a_ref,a_view))) then  */
8793
      if (bond[get_bond (a_view, a_ref) - 1].arom == false)
8794
        fg[fg_hydrazine - 1] = true;
8795
    }
8796
  if (!strcmp (atom[a_view - 1].element, "N ") &&
8797
      !strcmp (atom[a_ref - 1].atype, "O3 "))
8798
    {                           /* bond is in "opposite" direction */
8799
      if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &
8800
          is_nitro (a_ref, a_view))
8801
        fg[fg_nitrate - 1] = true;
8802
      if ((is_nitro (a_ref, a_view) == false
8803
           && atom[a_view - 1].arom == false) && (is_amino (a_ref,
8804
                                                            a_view) |
8805
                                                  is_subst_amino (a_ref,
8806
                                                                  a_view)) &
8807
          (is_acylamino (a_ref, a_view) == false))
8808
        fg[fg_hydroxylamine - 1] = true;        /* new in v0.3c */
8809
    }
8810
  if (!strcmp (atom[a_view - 1].element, "S ") &&
8811
      !strcmp (atom[a_ref - 1].element, "O "))
8812
    chk_sulfoxide (a_view, a_ref);
8813
}
8814
 
8815
 
8816
static void
8817
chk_single (a1, a2)
8818
     int a1, a2;
8819
{
8820
  str2 a1_el, a2_el;
8821
 
8822
  strcpy (a1_el, atom[a1 - 1].element);
8823
  strcpy (a2_el, atom[a2 - 1].element);
8824
  if (!strcmp (a1_el, "C ") &&
8825
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
8826
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
8827
    chk_c_hal (a1, a2);
8828
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
8829
    chk_c_o (a1, a2);
8830
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
8831
    chk_c_s (a1, a2);
8832
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
8833
    chk_c_n (a1, a2);
8834
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) ==
8835
                                                            false))
8836
    {
8837
      fg[fg_organometallic - 1] = true;
8838
      if (!strcmp (a2_el, "LI"))
8839
        fg[fg_organolithium - 1] = true;
8840
      if (!strcmp (a2_el, "MG"))
8841
        fg[fg_organomagnesium - 1] = true;
8842
    }
8843
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
8844
    chk_c_c (a1, a2);
8845
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
8846
    chk_x_y_single (a1, a2);
8847
}
8848
 
8849
 
8850
static void
8851
chk_carbonyl_deriv_sp3 (a_ref)
8852
     int a_ref;
8853
{
8854
  int i;
8855
  neighbor_rec nb;
8856
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
8857
  int FORLIM;
8858
 
8859
  memset (nb, 0, sizeof (neighbor_rec));
8860
  get_neighbors (nb, a_ref);
8861
  FORLIM = atom[a_ref - 1].neighbor_count;
8862
  for (i = 0; i < FORLIM; i++)
8863
    {
8864
      if (is_hydroxy (a_ref, nb[i]))
8865
        oh_count++;
8866
      if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8867
          is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
8868
        or_count++;
8869
      if (is_sulfanyl (a_ref, nb[i]))
8870
        sh_count++;
8871
      if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
8872
          is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref,
8873
                                                                   nb[i]))
8874
        sr_count++;
8875
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8876
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
8877
        n_count++;
8878
    }
8879
  if (oh_count == 2)
8880
    fg[fg_carbonyl_hydrate - 1] = true;
8881
  if (oh_count == 1 && or_count == 1)
8882
    fg[fg_hemiacetal - 1] = true;
8883
  if (or_count == 2)
8884
    fg[fg_acetal - 1] = true;
8885
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
8886
    fg[fg_hemiaminal - 1] = true;
8887
  if (n_count == 2)
8888
    fg[fg_aminal - 1] = true;
8889
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
8890
    fg[fg_thiohemiaminal - 1] = true;
8891
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
8892
    fg[fg_thioacetal - 1] = true;
8893
}
8894
 
8895
 
8896
static void
8897
chk_carboxyl_deriv_sp3 (a_ref)
8898
     int a_ref;
8899
{
8900
  int i;
8901
  neighbor_rec nb;
8902
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
8903
  int electroneg_count = 0;     /* new in v0.3j */
8904
  int hal_count = 0;
8905
  str2 nb_el;
8906
  int FORLIM;
8907
 
8908
  memset (nb, 0, sizeof (neighbor_rec));
8909
  get_neighbors (nb, a_ref);
8910
  FORLIM = atom[a_ref - 1].neighbor_count;
8911
  for (i = 0; i < FORLIM; i++)
8912
    {
8913
      strcpy (nb_el, atom[nb[i] - 1].element);  /* v0.3j */
8914
      if (is_electroneg (nb_el))
8915
        electroneg_count++;
8916
      if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
8917
          !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
8918
          || !strcmp (nb_el, "AT"))
8919
        hal_count++;
8920
      if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
8921
          is_siloxy (a_ref, nb[i]))
8922
        or_count++;
8923
      if (is_hydroxy (a_ref, nb[i]))    /* new in v0.3c    */
8924
        oh_count++;
8925
      if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
8926
          !strcmp (atom[nb[i] - 1].atype, "NAM"))
8927
        n_count++;
8928
    }
8929
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := true;  (* until v0.3i */
8930
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
8931
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
8932
  if (or_count == 3)
8933
    fg[fg_carboxylic_acid_orthoester - 1] = true;
8934
  if (or_count == 2 && n_count == 1)
8935
    fg[fg_carboxylic_acid_amide_acetal - 1] = true;
8936
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
8937
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
8938
}
8939
 
8940
 
8941
static void
8942
chk_anhydride (a_ref)
8943
     int a_ref;
8944
{
8945
  int i;
8946
  neighbor_rec nb;
8947
  int acyl_count = 0;
8948
  int FORLIM;
8949
 
8950
  memset (nb, 0, sizeof (neighbor_rec));
8951
  get_neighbors (nb, a_ref);
8952
  FORLIM = atom[a_ref - 1].neighbor_count;
8953
  for (i = 0; i < FORLIM; i++)
8954
    {
8955
      if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
8956
        acyl_count++;
8957
    }
8958
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 "))
8959
    {
8960
      fg[fg_carboxylic_acid_deriv - 1] = true;
8961
      fg[fg_carboxylic_acid_anhydride - 1] = true;
8962
    }
8963
}
8964
 
8965
 
8966
static void
8967
chk_imide (a_ref)
8968
     int a_ref;
8969
{
8970
  int i;
8971
  neighbor_rec nb;
8972
  int acyl_count = 0;
8973
  int FORLIM;
8974
 
8975
  memset (nb, 0, sizeof (neighbor_rec));
8976
  get_neighbors (nb, a_ref);
8977
  FORLIM = atom[a_ref - 1].neighbor_count;
8978
  for (i = 0; i < FORLIM; i++)
8979
    {
8980
      if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))    /* v0.3j */
8981
        acyl_count++;
8982
    }
8983
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
8984
    /* v0.3j: accept also N-acyl-imides */
8985
    return;
8986
  fg[fg_carboxylic_acid_deriv - 1] = true;
8987
  fg[fg_carboxylic_acid_imide - 1] = true;
8988
  if (atom[a_ref - 1].neighbor_count == 2)
8989
    fg[fg_carboxylic_acid_unsubst_imide - 1] = true;
8990
  if (atom[a_ref - 1].neighbor_count == 3)
8991
    fg[fg_carboxylic_acid_subst_imide - 1] = true;
8992
}
8993
 
8994
 
8995
static void
8996
chk_12diphenol (a_view, a_ref)
8997
     int a_view, a_ref;
8998
{
8999
  int i;
9000
  neighbor_rec nb;
9001
  int oh_count = 0;
9002
  int FORLIM;
9003
 
9004
  memset (nb, 0, sizeof (neighbor_rec));
9005
  get_neighbors (nb, a_view);
9006
  FORLIM = atom[a_view - 1].neighbor_count;
9007
  for (i = 0; i < FORLIM; i++)
9008
    {
9009
      if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')
9010
        {
9011
          if (is_hydroxy (a_view, nb[i]))
9012
            oh_count++;
9013
        }
9014
    }
9015
  memset (nb, 0, sizeof (neighbor_rec));
9016
  get_neighbors (nb, a_ref);
9017
  FORLIM = atom[a_ref - 1].neighbor_count;
9018
  for (i = 0; i < FORLIM; i++)
9019
    {
9020
      if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
9021
        {
9022
          if (is_hydroxy (a_ref, nb[i]))
9023
            oh_count++;
9024
        }
9025
    }
9026
  if (oh_count == 2)
9027
    fg[fg_1_2_diphenol - 1] = true;
9028
}
9029
 
9030
 
9031
static void
9032
chk_arom_fg (a1, a2)
9033
     int a1, a2;
9034
{
9035
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
9036
    chk_12diphenol (a1, a2);
9037
}
9038
 
9039
 
9040
static boolean
9041
is_arene (r_id)
9042
     int r_id;
9043
{
9044
  int i, j;
9045
  boolean r = true;
9046
  ringpath_type testring;
9047
  int ring_size, a_prev, a_ref;
9048
 
9049
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
9050
  if (r_id < 1 || r_id > n_rings)
9051
    return false;
9052
  memset (testring, 0, sizeof (ringpath_type));
9053
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9054
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9055
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9056
    testring[j] = ring[r_id - 1][j];
9057
  /*ring_size := path_length(testring); */
9058
  if (ring_size <= 2)
9059
    return false;
9060
  a_prev = testring[ring_size - 1];
9061
  for (i = 0; i < ring_size; i++)
9062
    {
9063
      a_ref = testring[i];
9064
      if (bond[get_bond (a_prev, a_ref) - 1].arom == false)
9065
        r = false;
9066
      a_prev = a_ref;
9067
    }
9068
  return r;
9069
}
9070
 
9071
 
9072
static boolean
9073
is_heterocycle (r_id)
9074
     int r_id;
9075
{
9076
  int i, j;
9077
  boolean r = false;
9078
  ringpath_type testring;
9079
  int ring_size, a_ref;
9080
 
9081
  if (r_id < 1 || r_id > n_rings)
9082
    return false;
9083
  memset (testring, 0, sizeof (ringpath_type));
9084
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9085
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9086
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9087
    testring[j] = ring[r_id - 1][j];
9088
  /*ring_size := path_length(testring); */
9089
  if (ring_size <= 2)
9090
    return false;
9091
  for (i = 0; i < ring_size; i++)
9092
    {
9093
      a_ref = testring[i];
9094
      if (strcmp (atom[a_ref - 1].element, "C "))
9095
        r = true;
9096
    }
9097
  return r;
9098
}
9099
 
9100
 
9101
static void
9102
chk_oxo_thioxo_imino_hetarene (r_id)
9103
     int r_id;
9104
{
9105
  int i, j;
9106
  ringpath_type testring;
9107
  int ring_size, a_ref;
9108
 
9109
  if (r_id < 1 || r_id > n_rings)
9110
    return;
9111
  memset (testring, 0, sizeof (ringpath_type));
9112
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
9113
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
9114
  for (j = 0; j < ring_size; j++)       /* v0.3j */
9115
    testring[j] = ring[r_id - 1][j];
9116
  /*ring_size := path_length(testring); */
9117
  /*if (is_arene(r_id)) and (odd(ring_size) = false) then */
9118
  if (!is_arene (r_id))         /* v0.3j */
9119
    return;
9120
  for (i = 0; i < ring_size; i++)
9121
    {
9122
      a_ref = testring[i];
9123
      if (is_oxo_C (a_ref))
9124
        fg[fg_oxohetarene - 1] = true;
9125
      if (is_thioxo_C (a_ref))
9126
        fg[fg_thioxohetarene - 1] = true;
9127
      if (is_true_exocyclic_imino_C (a_ref, r_id))      /* v0.3j */
9128
        fg[fg_iminohetarene - 1] = true;
9129
    }
9130
}
9131
 
9132
 
9133
static void
9134
chk_ion (a_ref)
9135
     int a_ref;
9136
{
9137
  int i;
9138
  neighbor_rec nb;
9139
  int charge, FORLIM;
9140
 
9141
  memset (nb, 0, sizeof (neighbor_rec));
9142
  get_neighbors (nb, a_ref);
9143
  charge = atom[a_ref - 1].formal_charge;
9144
  if (charge == 0)
9145
    /* check if charge is neutralized by an adjacent opposite charge */
9146
    return;
9147
  FORLIM = atom[a_ref - 1].neighbor_count;
9148
  for (i = 0; i < FORLIM; i++)
9149
    charge += atom[nb[i] - 1].formal_charge;
9150
  if (charge > 0)
9151
    fg[fg_cation - 1] = true;
9152
  if (charge < 0)
9153
    fg[fg_anion - 1] = true;
9154
}
9155
 
9156
 
9157
static void
9158
chk_functionalgroups ()
9159
{
9160
  int i, a1, a2;
9161
  char bt;
9162
  int pos_chg = 0, neg_chg = 0;
9163
  int FORLIM;
9164
 
9165
  if (n_atoms < 1 || n_bonds < 1)
9166
    return;
9167
  FORLIM = n_atoms;
9168
  for (i = 1; i <= FORLIM; i++)
9169
    {                           /* a few groups are best discovered in the atom list */
9170
      if (!strcmp (atom[i - 1].atype, "SO2"))
9171
        chk_so2_deriv (i);
9172
      /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := true;  (* do another check in the bond list!! */
9173
      if (!strcmp (atom[i - 1].element, "P "))
9174
        chk_p_deriv (i);
9175
      if (!strcmp (atom[i - 1].element, "B "))
9176
        chk_b_deriv (i);
9177
      if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
9178
        chk_ammon (i);
9179
      if ((strcmp (atom[i - 1].atype, "C3 ") == 0)
9180
          && (hetbond_count (i) == 2))
9181
        chk_carbonyl_deriv_sp3 (i);
9182
      if ((strcmp (atom[i - 1].atype, "C3 ") == 0)
9183
          && (hetbond_count (i) == 3))
9184
        chk_carboxyl_deriv_sp3 (i);
9185
      if (!strcmp (atom[i - 1].atype, "O3 ")
9186
          && atom[i - 1].neighbor_count == 2)
9187
        chk_anhydride (i);
9188
      if ((!strcmp (atom[i - 1].atype, "N3 ")
9189
           || !strcmp (atom[i - 1].atype, "NAM"))
9190
          && atom[i - 1].neighbor_count >= 2)
9191
        chk_imide (i);
9192
      if (atom[i - 1].formal_charge > 0)
9193
        pos_chg += atom[i - 1].formal_charge;
9194
      if (atom[i - 1].formal_charge < 0)
9195
        neg_chg += atom[i - 1].formal_charge;
9196
      chk_ion (i);
9197
    }
9198
  FORLIM = n_bonds;
9199
  for (i = 0; i < FORLIM; i++)
9200
    {                           /* most groups are best discovered in the bond list */
9201
      a1 = bond[i].a1;
9202
      a2 = bond[i].a2;
9203
      bt = bond[i].btype;
9204
      if (atom[a1 - 1].heavy && atom[a2 - 1].heavy)
9205
        {
9206
          orient_bond (&a1, &a2);
9207
          if (bt == 'T')
9208
            chk_triple (a1, a2);
9209
          if (bt == 'D')
9210
            chk_double (a1, a2);
9211
          if (bt == 'S')
9212
            chk_single (a1, a2);
9213
          if (bond[i].arom)
9214
            chk_arom_fg (a1, a2);
9215
        }
9216
    }
9217
  if (n_rings > 0)
9218
    {
9219
      FORLIM = n_rings;
9220
      for (i = 1; i <= FORLIM; i++)
9221
        {
9222
          chk_oxo_thioxo_imino_hetarene (i);
9223
          if (is_arene (i))
9224
            fg[fg_aromatic - 1] = true;
9225
          if (is_heterocycle (i))
9226
            fg[fg_heterocycle - 1] = true;
9227
        }
9228
    }
9229
  if (pos_chg + neg_chg > 0)
9230
    fg[fg_cation - 1] = true;
9231
  if (pos_chg + neg_chg < 0)
9232
    fg[fg_anion - 1] = true;
9233
}
9234
 
9235
 
9236
static void
9237
write_fg_text ()
9238
{
9239
  if (fg[fg_cation - 1])
9240
    printf ("cation\n");
9241
  if (fg[fg_anion - 1])
9242
    printf ("anion\n");
9243
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
9244
  if (fg[fg_aldehyde - 1])
9245
    printf ("aldehyde\n");
9246
  if (fg[fg_ketone - 1])
9247
    printf ("ketone\n");
9248
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
9249
  if (fg[fg_thioaldehyde - 1])
9250
    printf ("thioaldehyde\n");
9251
  if (fg[fg_thioketone - 1])
9252
    printf ("thioketone\n");
9253
  if (fg[fg_imine - 1])
9254
    printf ("imine\n");
9255
  if (fg[fg_hydrazone - 1])
9256
    printf ("hydrazone\n");
9257
  if (fg[fg_semicarbazone - 1])
9258
    printf ("semicarbazone\n");
9259
  if (fg[fg_thiosemicarbazone - 1])
9260
    printf ("thiosemicarbazone\n");
9261
  if (fg[fg_oxime - 1])
9262
    printf ("oxime\n");
9263
  if (fg[fg_oxime_ether - 1])
9264
    printf ("oxime ether\n");
9265
  if (fg[fg_ketene - 1])
9266
    printf ("ketene\n");
9267
  if (fg[fg_ketene_acetal_deriv - 1])
9268
    printf ("ketene acetal or derivative\n");
9269
  if (fg[fg_carbonyl_hydrate - 1])
9270
    printf ("carbonyl hydrate\n");
9271
  if (fg[fg_hemiacetal - 1])
9272
    printf ("hemiacetal\n");
9273
  if (fg[fg_acetal - 1])
9274
    printf ("acetal\n");
9275
  if (fg[fg_hemiaminal - 1])
9276
    printf ("hemiaminal\n");
9277
  if (fg[fg_aminal - 1])
9278
    printf ("aminal\n");
9279
  if (fg[fg_thiohemiaminal - 1])
9280
    printf ("hemithioaminal\n");
9281
  if (fg[fg_thioacetal - 1])
9282
    printf ("thioacetal\n");
9283
  if (fg[fg_enamine - 1])
9284
    printf ("enamine\n");
9285
  if (fg[fg_enol - 1])
9286
    printf ("enol\n");
9287
  if (fg[fg_enolether - 1])
9288
    printf ("enol ether\n");
9289
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9290
    printf ("hydroxy compound\n");
9291
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
9292
  if (fg[fg_prim_alcohol - 1])
9293
    printf ("primary alcohol\n");
9294
  if (fg[fg_sec_alcohol - 1])
9295
    printf ("secondary alcohol\n");
9296
  if (fg[fg_tert_alcohol - 1])
9297
    printf ("tertiary alcohol\n");
9298
  if (fg[fg_1_2_diol - 1])
9299
    printf ("1,2-diol\n");
9300
  if (fg[fg_1_2_aminoalcohol - 1])
9301
    printf ("1,2-aminoalcohol\n");
9302
  if (fg[fg_phenol - 1])
9303
    printf ("phenol or hydroxyhetarene\n");
9304
  if (fg[fg_1_2_diphenol - 1])
9305
    printf ("1,2-diphenol\n");
9306
  if (fg[fg_enediol - 1])
9307
    printf ("enediol\n");
9308
  if (fg[fg_ether - 1] && ether_generic)
9309
    printf ("ether\n");
9310
  if (fg[fg_dialkylether - 1])
9311
    printf ("dialkyl ether\n");
9312
  if (fg[fg_alkylarylether - 1])
9313
    printf ("alkyl aryl ether \n");
9314
  if (fg[fg_diarylether - 1])
9315
    printf ("diaryl ether\n");
9316
  if (fg[fg_thioether - 1])
9317
    printf ("thioether\n");
9318
  if (fg[fg_disulfide - 1])
9319
    printf ("disulfide\n");
9320
  if (fg[fg_peroxide - 1])
9321
    printf ("peroxide\n");
9322
  if (fg[fg_hydroperoxide - 1])
9323
    printf ("hydroperoxide \n");
9324
  if (fg[fg_hydrazine - 1])
9325
    printf ("hydrazine derivative\n");
9326
  if (fg[fg_hydroxylamine - 1])
9327
    printf ("hydroxylamine\n");
9328
  if (fg[fg_amine - 1] && amine_generic)
9329
    printf ("amine\n");
9330
  if (fg[fg_prim_amine - 1])
9331
    printf ("primary amine\n");
9332
  if (fg[fg_prim_aliph_amine - 1])
9333
    printf ("primary aliphatic amine (alkylamine)\n");
9334
  if (fg[fg_prim_arom_amine - 1])
9335
    printf ("primary aromatic amine\n");
9336
  if (fg[fg_sec_amine - 1])
9337
    printf ("secondary amine\n");
9338
  if (fg[fg_sec_aliph_amine - 1])
9339
    printf ("secondary aliphatic amine (dialkylamine)\n");
9340
  if (fg[fg_sec_mixed_amine - 1])
9341
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
9342
  if (fg[fg_sec_arom_amine - 1])
9343
    printf ("secondary aromatic amine (diarylamine)\n");
9344
  if (fg[fg_tert_amine - 1])
9345
    printf ("tertiary amine\n");
9346
  if (fg[fg_tert_aliph_amine - 1])
9347
    printf ("tertiary aliphatic amine (trialkylamine)\n");
9348
  if (fg[fg_tert_mixed_amine - 1])
9349
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
9350
  if (fg[fg_tert_arom_amine - 1])
9351
    printf ("tertiary aromatic amine (triarylamine)\n");
9352
  if (fg[fg_quart_ammonium - 1])
9353
    printf ("quaternary ammonium salt\n");
9354
  if (fg[fg_n_oxide - 1])
9355
    printf ("N-oxide\n");
9356
  /* new in v0.2f */
9357
  if (fg[fg_halogen_deriv - 1])
9358
    {
9359
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
9360
          !fg[fg_acyl_halide - 1])
9361
        printf ("halogen derivative\n");
9362
    }
9363
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
9364
  if (fg[fg_alkyl_fluoride - 1])
9365
    printf ("alkyl fluoride\n");
9366
  if (fg[fg_alkyl_chloride - 1])
9367
    printf ("alkyl chloride\n");
9368
  if (fg[fg_alkyl_bromide - 1])
9369
    printf ("alkyl bromide\n");
9370
  if (fg[fg_alkyl_iodide - 1])
9371
    printf ("alkyl iodide\n");
9372
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
9373
  if (fg[fg_aryl_fluoride - 1])
9374
    printf ("aryl fluoride\n");
9375
  if (fg[fg_aryl_chloride - 1])
9376
    printf ("aryl chloride\n");
9377
  if (fg[fg_aryl_bromide - 1])
9378
    printf ("aryl bromide\n");
9379
  if (fg[fg_aryl_iodide - 1])
9380
    printf ("aryl iodide\n");
9381
  if (fg[fg_organometallic - 1])
9382
    printf ("organometallic compound\n");
9383
  if (fg[fg_organolithium - 1])
9384
    printf ("organolithium compound\n");
9385
  if (fg[fg_organomagnesium - 1])
9386
    printf ("organomagnesium compound\n");
9387
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
9388
  if (fg[fg_carboxylic_acid - 1])
9389
    printf ("carboxylic acid\n");
9390
  if (fg[fg_carboxylic_acid_salt - 1])
9391
    printf ("carboxylic acid salt\n");
9392
  if (fg[fg_carboxylic_acid_ester - 1])
9393
    printf ("carboxylic acid ester\n");
9394
  if (fg[fg_lactone - 1])
9395
    printf ("lactone\n");
9396
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
9397
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9398
    printf ("primary carboxylic acid amide\n");
9399
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9400
    printf ("secondary carboxylic acid amide\n");
9401
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9402
    printf ("tertiary carboxylic acid amide\n");
9403
  if (fg[fg_lactam - 1])
9404
    printf ("lactam\n");
9405
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9406
    printf ("carboxylic acid hydrazide\n");
9407
  if (fg[fg_carboxylic_acid_azide - 1])
9408
    printf ("carboxylic acid azide\n");
9409
  if (fg[fg_hydroxamic_acid - 1])
9410
    printf ("hydroxamic acid\n");
9411
  if (fg[fg_carboxylic_acid_amidine - 1])
9412
    printf ("carboxylic acid amidine\n");
9413
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9414
    printf ("carboxylic acid amidrazone\n");
9415
  if (fg[fg_nitrile - 1])
9416
    printf ("carbonitrile\n");
9417
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
9418
  if (fg[fg_acyl_fluoride - 1])
9419
    printf ("acyl fluoride\n");
9420
  if (fg[fg_acyl_chloride - 1])
9421
    printf ("acyl chloride\n");
9422
  if (fg[fg_acyl_bromide - 1])
9423
    printf ("acyl bromide\n");
9424
  if (fg[fg_acyl_iodide - 1])
9425
    printf ("acyl iodide\n");
9426
  if (fg[fg_acyl_cyanide - 1])
9427
    printf ("acyl cyanide\n");
9428
  if (fg[fg_imido_ester - 1])
9429
    printf ("imido ester\n");
9430
  if (fg[fg_imidoyl_halide - 1])
9431
    printf ("imidoyl halide\n");
9432
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
9433
  if (fg[fg_thiocarboxylic_acid - 1])
9434
    printf ("thiocarboxylic acid\n");
9435
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9436
    printf ("thiocarboxylic acid ester\n");
9437
  if (fg[fg_thiolactone - 1])
9438
    printf ("thiolactone\n");
9439
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9440
    printf ("thiocarboxylic acid amide\n");
9441
  if (fg[fg_thiolactam - 1])
9442
    printf ("thiolactam\n");
9443
  if (fg[fg_imido_thioester - 1])
9444
    printf ("imidothioester\n");
9445
  if (fg[fg_oxohetarene - 1])
9446
    printf ("oxo(het)arene\n");
9447
  if (fg[fg_thioxohetarene - 1])
9448
    printf ("thioxo(het)arene\n");
9449
  if (fg[fg_iminohetarene - 1])
9450
    printf ("imino(het)arene\n");
9451
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9452
    printf ("orthocarboxylic acid derivative\n");
9453
  if (fg[fg_carboxylic_acid_orthoester - 1])
9454
    printf ("orthoester\n");
9455
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9456
    printf ("amide acetal\n");
9457
  if (fg[fg_carboxylic_acid_anhydride - 1])
9458
    printf ("carboxylic acid anhydride\n");
9459
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
9460
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9461
    printf ("carboxylic acid imide, N-unsubstituted\n");
9462
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9463
    printf ("carboxylic acid imide, N-substituted\n");
9464
  if (fg[fg_co2_deriv - 1])
9465
    printf ("CO2 derivative (general)\n");
9466
  if (fg[fg_carbonic_acid_deriv - 1] &&
9467
      !(fg[fg_carbonic_acid_monoester - 1]
9468
        || fg[fg_carbonic_acid_diester - 1]
9469
        || fg[fg_carbonic_acid_ester_halide - 1]))
9470
    /* changed in v0.3c */
9471
    printf ("carbonic acid derivative\n");
9472
  if (fg[fg_carbonic_acid_monoester - 1])
9473
    printf ("carbonic acid monoester\n");
9474
  if (fg[fg_carbonic_acid_diester - 1])
9475
    printf ("carbonic acid diester\n");
9476
  if (fg[fg_carbonic_acid_ester_halide - 1])
9477
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
9478
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9479
    printf ("thiocarbonic acid derivative\n");
9480
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9481
    printf ("thiocarbonic acid monoester\n");
9482
  if (fg[fg_thiocarbonic_acid_diester - 1])
9483
    printf ("thiocarbonic acid diester\n");
9484
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9485
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
9486
  if (fg[fg_carbamic_acid_deriv - 1]
9487
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
9488
           || fg[fg_carbamic_acid_halide - 1]))
9489
    /* changed in v0.3c */
9490
    printf ("carbamic acid derivative\n");
9491
  if (fg[fg_carbamic_acid - 1])
9492
    printf ("carbamic acid\n");
9493
  if (fg[fg_carbamic_acid_ester - 1])
9494
    printf ("carbamic acid ester (urethane)\n");
9495
  if (fg[fg_carbamic_acid_halide - 1])
9496
    printf ("carbamic acid halide (haloformic acid amide)\n");
9497
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
9498
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
9499
        || fg[fg_thiocarbamic_acid_halide - 1]))
9500
    /* changed in v0.3c */
9501
    printf ("thiocarbamic acid derivative\n");
9502
  if (fg[fg_thiocarbamic_acid - 1])
9503
    printf ("thiocarbamic acid\n");
9504
  if (fg[fg_thiocarbamic_acid_ester - 1])
9505
    printf ("thiocarbamic acid ester\n");
9506
  if (fg[fg_thiocarbamic_acid_halide - 1])
9507
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
9508
  if (fg[fg_urea - 1])
9509
    printf ("urea\n");
9510
  if (fg[fg_isourea - 1])
9511
    printf ("isourea\n");
9512
  if (fg[fg_thiourea - 1])
9513
    printf ("thiourea\n");
9514
  if (fg[fg_isothiourea - 1])
9515
    printf ("isothiourea\n");
9516
  if (fg[fg_guanidine - 1])
9517
    printf ("guanidine\n");
9518
  if (fg[fg_semicarbazide - 1])
9519
    printf ("semicarbazide\n");
9520
  if (fg[fg_thiosemicarbazide - 1])
9521
    printf ("thiosemicarbazide\n");
9522
  if (fg[fg_azide - 1])
9523
    printf ("azide\n");
9524
  if (fg[fg_azo_compound - 1])
9525
    printf ("azo compound\n");
9526
  if (fg[fg_diazonium_salt - 1])
9527
    printf ("diazonium salt\n");
9528
  if (fg[fg_isonitrile - 1])
9529
    printf ("isonitrile\n");
9530
  if (fg[fg_cyanate - 1])
9531
    printf ("cyanate\n");
9532
  if (fg[fg_isocyanate - 1])
9533
    printf ("isocyanate\n");
9534
  if (fg[fg_thiocyanate - 1])
9535
    printf ("thiocyanate\n");
9536
  if (fg[fg_isothiocyanate - 1])
9537
    printf ("isothiocyanate\n");
9538
  if (fg[fg_carbodiimide - 1])
9539
    printf ("carbodiimide\n");
9540
  if (fg[fg_nitroso_compound - 1])
9541
    printf ("nitroso compound\n");
9542
  if (fg[fg_nitro_compound - 1])
9543
    printf ("nitro compound\n");
9544
  if (fg[fg_nitrite - 1])
9545
    printf ("nitrite\n");
9546
  if (fg[fg_nitrate - 1])
9547
    printf ("nitrate\n");
9548
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
9549
  if (fg[fg_sulfuric_acid - 1])
9550
    printf ("sulfuric acid\n");
9551
  if (fg[fg_sulfuric_acid_monoester - 1])
9552
    printf ("sulfuric acid monoester\n");
9553
  if (fg[fg_sulfuric_acid_diester - 1])
9554
    printf ("sulfuric acid diester\n");
9555
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9556
    printf ("sulfuric acid amide ester\n");
9557
  if (fg[fg_sulfuric_acid_amide - 1])
9558
    printf ("sulfuric acid amide\n");
9559
  if (fg[fg_sulfuric_acid_diamide - 1])
9560
    printf ("sulfuric acid diamide\n");
9561
  if (fg[fg_sulfuryl_halide - 1])
9562
    printf ("sulfuryl halide\n");
9563
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
9564
  if (fg[fg_sulfonic_acid - 1])
9565
    printf ("sulfonic acid\n");
9566
  if (fg[fg_sulfonic_acid_ester - 1])
9567
    printf ("sulfonic acid ester\n");
9568
  if (fg[fg_sulfonamide - 1])
9569
    printf ("sulfonamide\n");
9570
  if (fg[fg_sulfonyl_halide - 1])
9571
    printf ("sulfonyl halide\n");
9572
  if (fg[fg_sulfone - 1])
9573
    printf ("sulfone\n");
9574
  if (fg[fg_sulfoxide - 1])
9575
    printf ("sulfoxide\n");
9576
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
9577
  if (fg[fg_sulfinic_acid - 1])
9578
    printf ("sulfinic acid\n");
9579
  if (fg[fg_sulfinic_acid_ester - 1])
9580
    printf ("sulfinic acid ester\n");
9581
  if (fg[fg_sulfinic_acid_halide - 1])
9582
    printf ("sulfinic acid halide\n");
9583
  if (fg[fg_sulfinic_acid_amide - 1])
9584
    printf ("sulfinic acid amide\n");
9585
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
9586
  if (fg[fg_sulfenic_acid - 1])
9587
    printf ("sulfenic acid\n");
9588
  if (fg[fg_sulfenic_acid_ester - 1])
9589
    printf ("sulfenic acid ester\n");
9590
  if (fg[fg_sulfenic_acid_halide - 1])
9591
    printf ("sulfenic acid halide\n");
9592
  if (fg[fg_sulfenic_acid_amide - 1])
9593
    printf ("sulfenic acid amide\n");
9594
  if (fg[fg_thiol - 1])
9595
    printf ("thiol (sulfanyl compound)\n");
9596
  if (fg[fg_alkylthiol - 1])
9597
    printf ("alkylthiol\n");
9598
  if (fg[fg_arylthiol - 1])
9599
    printf ("arylthiol\n");
9600
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
9601
  if (fg[fg_phosphoric_acid - 1])
9602
    printf ("phosphoric acid\n");
9603
  if (fg[fg_phosphoric_acid_ester - 1])
9604
    printf ("phosphoric acid ester\n");
9605
  if (fg[fg_phosphoric_acid_halide - 1])
9606
    printf ("phosphoric acid halide\n");
9607
  if (fg[fg_phosphoric_acid_amide - 1])
9608
    printf ("phosphoric acid amide\n");
9609
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
9610
  if (fg[fg_thiophosphoric_acid - 1])
9611
    printf ("thiophosphoric acid\n");
9612
  if (fg[fg_thiophosphoric_acid_ester - 1])
9613
    printf ("thiophosphoric acid ester\n");
9614
  if (fg[fg_thiophosphoric_acid_halide - 1])
9615
    printf ("thiophosphoric acid halide\n");
9616
  if (fg[fg_thiophosphoric_acid_amide - 1])
9617
    printf ("thiophosphoric acid amide\n");
9618
  if (fg[fg_phosphonic_acid_deriv - 1])
9619
    printf ("phosphonic acid derivative \n");
9620
  if (fg[fg_phosphonic_acid - 1])
9621
    printf ("phosphonic acid\n");
9622
  if (fg[fg_phosphonic_acid_ester - 1])
9623
    printf ("phosphonic acid ester\n");
9624
  if (fg[fg_phosphine - 1])
9625
    printf ("phosphine\n");
9626
  if (fg[fg_phosphinoxide - 1])
9627
    printf ("phosphine oxide\n");
9628
  if (fg[fg_boronic_acid_deriv - 1])
9629
    printf ("boronic acid derivative\n");
9630
  if (fg[fg_boronic_acid - 1])
9631
    printf ("boronic acid\n");
9632
  if (fg[fg_boronic_acid_ester - 1])
9633
    printf ("boronic acid ester\n");
9634
  if (fg[fg_alkene - 1])
9635
    printf ("alkene\n");
9636
  if (fg[fg_alkyne - 1])
9637
    printf ("alkyne\n");
9638
  if (fg[fg_aromatic - 1])
9639
    printf ("aromatic compound\n");
9640
  if (fg[fg_heterocycle - 1])
9641
    printf ("heterocyclic compound\n");
9642
  if (fg[fg_alpha_aminoacid - 1])
9643
    printf ("alpha-aminoacid\n");
9644
  if (fg[fg_alpha_hydroxyacid - 1])
9645
    printf ("alpha-hydroxyacid\n");
9646
}
9647
 
9648
 
9649
static void
9650
write_fg_text_de ()
9651
{
9652
  if (fg[fg_cation - 1])
9653
    printf ("Kation\n");
9654
  if (fg[fg_anion - 1])
9655
    printf ("Anion\n");
9656
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
9657
  if (fg[fg_aldehyde - 1])
9658
    printf ("Aldehyd\n");
9659
  if (fg[fg_ketone - 1])
9660
    printf ("Keton\n");
9661
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
9662
  if (fg[fg_thioaldehyde - 1])
9663
    printf ("Thioaldehyd\n");
9664
  if (fg[fg_thioketone - 1])
9665
    printf ("Thioketon\n");
9666
  if (fg[fg_imine - 1])
9667
    printf ("Imin\n");
9668
  if (fg[fg_hydrazone - 1])
9669
    printf ("Hydrazon\n");
9670
  if (fg[fg_semicarbazone - 1])
9671
    printf ("Semicarbazon\n");
9672
  if (fg[fg_thiosemicarbazone - 1])
9673
    printf ("Thiosemicarbazon\n");
9674
  if (fg[fg_oxime - 1])
9675
    printf ("Oxim\n");
9676
  if (fg[fg_oxime_ether - 1])
9677
    printf ("Oximether\n");
9678
  if (fg[fg_ketene - 1])
9679
    printf ("Keten\n");
9680
  if (fg[fg_ketene_acetal_deriv - 1])
9681
    printf ("Keten-Acetal oder Derivat\n");
9682
  if (fg[fg_carbonyl_hydrate - 1])
9683
    printf ("Carbonyl-Hydrat\n");
9684
  if (fg[fg_hemiacetal - 1])
9685
    printf ("Halbacetal\n");
9686
  if (fg[fg_acetal - 1])
9687
    printf ("Acetal\n");
9688
  if (fg[fg_hemiaminal - 1])
9689
    printf ("Halbaminal\n");
9690
  if (fg[fg_aminal - 1])
9691
    printf ("Aminal\n");
9692
  if (fg[fg_thiohemiaminal - 1])
9693
    printf ("Thiohalbaminal\n");
9694
  if (fg[fg_thioacetal - 1])
9695
    printf ("Thioacetal\n");
9696
  if (fg[fg_enamine - 1])
9697
    printf ("Enamin\n");
9698
  if (fg[fg_enol - 1])
9699
    printf ("Enol\n");
9700
  if (fg[fg_enolether - 1])
9701
    printf ("Enolether\n");
9702
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9703
    printf ("Hydroxy-Verbindung\n");
9704
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
9705
  if (fg[fg_prim_alcohol - 1])
9706
    printf ("prim\344rer Alkohol\n");
9707
/* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
9708
  if (fg[fg_sec_alcohol - 1])
9709
    printf ("sekund\344rer Alkohol\n");
9710
/* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
9711
  if (fg[fg_tert_alcohol - 1])
9712
    printf ("terti\344rer Alkohol\n");
9713
/* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
9714
  if (fg[fg_1_2_diol - 1])
9715
    printf ("1,2-Diol\n");
9716
  if (fg[fg_1_2_aminoalcohol - 1])
9717
    printf ("1,2-Aminoalkohol\n");
9718
  if (fg[fg_phenol - 1])
9719
    printf ("Phenol oder Hydroxyhetaren\n");
9720
  if (fg[fg_1_2_diphenol - 1])
9721
    printf ("1,2-Diphenol\n");
9722
  if (fg[fg_enediol - 1])
9723
    printf ("Endiol\n");
9724
  if (fg[fg_ether - 1] && ether_generic)
9725
    printf ("Ether\n");
9726
  if (fg[fg_dialkylether - 1])
9727
    printf ("Dialkylether\n");
9728
  if (fg[fg_alkylarylether - 1])
9729
    printf ("Alkylarylether \n");
9730
  if (fg[fg_diarylether - 1])
9731
    printf ("Diarylether\n");
9732
  if (fg[fg_thioether - 1])
9733
    printf ("Thioether\n");
9734
  if (fg[fg_disulfide - 1])
9735
    printf ("Disulfid\n");
9736
  if (fg[fg_peroxide - 1])
9737
    printf ("Peroxid\n");
9738
  if (fg[fg_hydroperoxide - 1])
9739
    printf ("Hydroperoxid\n");
9740
  if (fg[fg_hydrazine - 1])
9741
    printf ("Hydrazin-Derivat\n");
9742
  if (fg[fg_hydroxylamine - 1])
9743
    printf ("Hydroxylamin\n");
9744
  if (fg[fg_amine - 1] && amine_generic)
9745
    printf ("Amin\n");
9746
  if (fg[fg_prim_amine - 1])
9747
    printf ("prim\344res Amin\n");
9748
/* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
9749
  if (fg[fg_prim_aliph_amine - 1])
9750
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
9751
/* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
9752
  if (fg[fg_prim_arom_amine - 1])
9753
    printf ("prim\344res aromatisches Amin\n");
9754
/* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
9755
  if (fg[fg_sec_amine - 1])
9756
    printf ("sekund\344res Amin\n");
9757
/* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
9758
  if (fg[fg_sec_aliph_amine - 1])
9759
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
9760
/* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
9761
  if (fg[fg_sec_mixed_amine - 1])
9762
    printf
9763
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
9764
/* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
9765
  if (fg[fg_sec_arom_amine - 1])
9766
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
9767
/* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
9768
  if (fg[fg_tert_amine - 1])
9769
    printf ("terti\344res Amin\n");
9770
/* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
9771
  if (fg[fg_tert_aliph_amine - 1])
9772
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
9773
/* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
9774
  if (fg[fg_tert_mixed_amine - 1])
9775
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
9776
/* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
9777
  if (fg[fg_tert_arom_amine - 1])
9778
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
9779
/* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
9780
  if (fg[fg_quart_ammonium - 1])
9781
    printf ("quart\344res Ammoniumsalz\n");
9782
/* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
9783
  if (fg[fg_n_oxide - 1])
9784
    printf ("N-Oxid\n");
9785
  /* new in v0.2f */
9786
  if (fg[fg_halogen_deriv - 1])
9787
    {
9788
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
9789
          !fg[fg_acyl_halide - 1])
9790
        printf ("Halogenverbindung\n");
9791
    }
9792
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
9793
  if (fg[fg_alkyl_fluoride - 1])
9794
    printf ("Alkylfluorid\n");
9795
  if (fg[fg_alkyl_chloride - 1])
9796
    printf ("Alkylchlorid\n");
9797
  if (fg[fg_alkyl_bromide - 1])
9798
    printf ("Alkylbromid\n");
9799
  if (fg[fg_alkyl_iodide - 1])
9800
    printf ("Alkyliodid\n");
9801
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
9802
  if (fg[fg_aryl_fluoride - 1])
9803
    printf ("Arylfluorid\n");
9804
  if (fg[fg_aryl_chloride - 1])
9805
    printf ("Arylchlorid\n");
9806
  if (fg[fg_aryl_bromide - 1])
9807
    printf ("Arylbromid\n");
9808
  if (fg[fg_aryl_iodide - 1])
9809
    printf ("Aryliodid\n");
9810
  if (fg[fg_organometallic - 1])
9811
    printf ("Organometall-Verbindung\n");
9812
  if (fg[fg_organolithium - 1])
9813
    printf ("Organolithium-Verbindung\n");
9814
  if (fg[fg_organomagnesium - 1])
9815
    printf ("Organomagnesium-Verbindung\n");
9816
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
9817
  if (fg[fg_carboxylic_acid - 1])
9818
    printf ("Carbons\344ure\n");
9819
/* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
9820
  if (fg[fg_carboxylic_acid_salt - 1])
9821
    printf ("Carbons\344uresalz\n");
9822
/* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
9823
  if (fg[fg_carboxylic_acid_ester - 1])
9824
    printf ("Carbons\344ureester\n");
9825
/* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
9826
  if (fg[fg_lactone - 1])
9827
    printf ("Lacton\n");
9828
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
9829
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9830
    printf ("prim\344res Carbons\344ureamid\n");
9831
/* p2c: checkmol.pas, line 7340:
9832
 * Note: characters >= 128 encountered [281] */
9833
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9834
    printf ("sekund\344res Carbons\344ureamid\n");
9835
/* p2c: checkmol.pas, line 7341:
9836
 * Note: characters >= 128 encountered [281] */
9837
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9838
    printf ("terti\344res Carbons\344ureamid\n");
9839
/* p2c: checkmol.pas, line 7342:
9840
 * Note: characters >= 128 encountered [281] */
9841
  if (fg[fg_lactam - 1])
9842
    printf ("Lactam\n");
9843
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9844
    printf ("Carbons\344urehydrazid\n");
9845
/* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
9846
  if (fg[fg_carboxylic_acid_azide - 1])
9847
    printf ("Carbons\344ureazid\n");
9848
/* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
9849
  if (fg[fg_hydroxamic_acid - 1])
9850
    printf ("Hydroxams\344ure\n");
9851
/* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
9852
  if (fg[fg_carboxylic_acid_amidine - 1])
9853
    printf ("Carbons\344ureamidin\n");
9854
/* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
9855
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9856
    printf ("Carbons\344ureamidrazon\n");
9857
/* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
9858
  if (fg[fg_nitrile - 1])
9859
    printf ("Carbonitril\n");
9860
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
9861
  if (fg[fg_acyl_fluoride - 1])
9862
    printf ("Acylfluorid\n");
9863
  if (fg[fg_acyl_chloride - 1])
9864
    printf ("Acylchlorid\n");
9865
  if (fg[fg_acyl_bromide - 1])
9866
    printf ("Acylbromid\n");
9867
  if (fg[fg_acyl_iodide - 1])
9868
    printf ("Acyliodid\n");
9869
  if (fg[fg_acyl_cyanide - 1])
9870
    printf ("Acylcyanid\n");
9871
  if (fg[fg_imido_ester - 1])
9872
    printf ("Imidoester\n");
9873
  if (fg[fg_imidoyl_halide - 1])
9874
    printf ("Imidoylhalogenid\n");
9875
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
9876
  if (fg[fg_thiocarboxylic_acid - 1])
9877
    printf ("Thiocarbons\344ure\n");
9878
/* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
9879
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9880
    printf ("Thiocarbons\344ureester\n");
9881
/* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
9882
  if (fg[fg_thiolactone - 1])
9883
    printf ("Thiolacton\n");
9884
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9885
    printf ("Thiocarbons\344ureamid\n");
9886
/* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
9887
  if (fg[fg_thiolactam - 1])
9888
    printf ("Thiolactam\n");
9889
  if (fg[fg_imido_thioester - 1])
9890
    printf ("Imidothioester\n");
9891
  if (fg[fg_oxohetarene - 1])
9892
    printf ("Oxo(het)aren\n");
9893
  if (fg[fg_thioxohetarene - 1])
9894
    printf ("Thioxo(het)aren\n");
9895
  if (fg[fg_iminohetarene - 1])
9896
    printf ("Imino(het)aren\n");
9897
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9898
    printf ("Orthocarbons\344ure-Derivat\n");
9899
/* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
9900
  if (fg[fg_carboxylic_acid_orthoester - 1])
9901
    printf ("Orthoester\n");
9902
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9903
    printf ("Amidacetal\n");
9904
  if (fg[fg_carboxylic_acid_anhydride - 1])
9905
    printf ("Carbons\344ureanhydrid\n");
9906
/* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
9907
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
9908
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9909
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
9910
/* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
9911
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9912
    printf ("Carbons\344ureimid, N-substituiert\n");
9913
/* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
9914
  if (fg[fg_co2_deriv - 1])
9915
    printf ("CO2-Derivat (allgemein)\n");
9916
  if (fg[fg_carbonic_acid_deriv - 1] &&
9917
      !(fg[fg_carbonic_acid_monoester - 1]
9918
        || fg[fg_carbonic_acid_diester - 1]
9919
        || fg[fg_carbonic_acid_ester_halide - 1]))
9920
    /* changed in v0.3c */
9921
    printf ("Kohlens\344ure-Derivat\n");
9922
/* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
9923
  if (fg[fg_carbonic_acid_monoester - 1])
9924
    printf ("Kohlens\344uremonoester\n");
9925
/* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
9926
  if (fg[fg_carbonic_acid_diester - 1])
9927
    printf ("Kohlens\344urediester\n");
9928
/* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
9929
  if (fg[fg_carbonic_acid_ester_halide - 1])
9930
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
9931
/* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
9932
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9933
    printf ("Thiokohlens\344ure-Derivat\n");
9934
/* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
9935
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9936
    printf ("Thiokohlens\344uremonoester\n");
9937
/* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
9938
  if (fg[fg_thiocarbonic_acid_diester - 1])
9939
    printf ("Thiokohlens\344urediester\n");
9940
/* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
9941
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9942
    printf
9943
      ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
9944
/* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
9945
  if (fg[fg_carbamic_acid_deriv - 1] &&
9946
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
9947
        fg[fg_carbamic_acid_halide - 1]))
9948
    /* changed in v0.3c */
9949
    printf ("Carbamins\344ure-Derivat\n");
9950
/* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
9951
  if (fg[fg_carbamic_acid - 1])
9952
    printf ("Carbamins\344ure\n");
9953
/* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
9954
  if (fg[fg_carbamic_acid_ester - 1])
9955
    printf ("Carbamins\344ureester (Urethan)\n");
9956
/* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
9957
  if (fg[fg_carbamic_acid_halide - 1])
9958
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
9959
/* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
9960
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
9961
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
9962
        || fg[fg_thiocarbamic_acid_halide - 1]))
9963
    /* changed in v0.3c */
9964
    printf ("Thiocarbamins\344ure-Derivat\n");
9965
/* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
9966
  if (fg[fg_thiocarbamic_acid - 1])
9967
    printf ("Thiocarbamins\344ure\n");
9968
/* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
9969
  if (fg[fg_thiocarbamic_acid_ester - 1])
9970
    printf ("Thiocarbamins\344ureester\n");
9971
/* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
9972
  if (fg[fg_thiocarbamic_acid_halide - 1])
9973
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
9974
/* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
9975
  if (fg[fg_urea - 1])
9976
    printf ("Harnstoff\n");
9977
  if (fg[fg_isourea - 1])
9978
    printf ("Isoharnstoff\n");
9979
  if (fg[fg_thiourea - 1])
9980
    printf ("Thioharnstoff\n");
9981
  if (fg[fg_isothiourea - 1])
9982
    printf ("Isothioharnstoff\n");
9983
  if (fg[fg_guanidine - 1])
9984
    printf ("Guanidin\n");
9985
  if (fg[fg_semicarbazide - 1])
9986
    printf ("Semicarbazid\n");
9987
  if (fg[fg_thiosemicarbazide - 1])
9988
    printf ("Thiosemicarbazid\n");
9989
  if (fg[fg_azide - 1])
9990
    printf ("Azid\n");
9991
  if (fg[fg_azo_compound - 1])
9992
    printf ("Azoverbindung\n");
9993
  if (fg[fg_diazonium_salt - 1])
9994
    printf ("Diazoniumsalz\n");
9995
  if (fg[fg_isonitrile - 1])
9996
    printf ("Isonitril\n");
9997
  if (fg[fg_cyanate - 1])
9998
    printf ("Cyanat\n");
9999
  if (fg[fg_isocyanate - 1])
10000
    printf ("Isocyanat\n");
10001
  if (fg[fg_thiocyanate - 1])
10002
    printf ("Thiocyanat\n");
10003
  if (fg[fg_isothiocyanate - 1])
10004
    printf ("Isothiocyanat\n");
10005
  if (fg[fg_carbodiimide - 1])
10006
    printf ("Carbodiimid\n");
10007
  if (fg[fg_nitroso_compound - 1])
10008
    printf ("Nitroso-Verbindung\n");
10009
  if (fg[fg_nitro_compound - 1])
10010
    printf ("Nitro-Verbindung\n");
10011
  if (fg[fg_nitrite - 1])
10012
    printf ("Nitrit\n");
10013
  if (fg[fg_nitrate - 1])
10014
    printf ("Nitrat\n");
10015
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
10016
  if (fg[fg_sulfuric_acid - 1])
10017
    printf ("Schwefels\344ure\n");
10018
/* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
10019
  if (fg[fg_sulfuric_acid_monoester - 1])
10020
    printf ("Schwefels\344uremonoester\n");
10021
/* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
10022
  if (fg[fg_sulfuric_acid_diester - 1])
10023
    printf ("Schwefels\344urediester\n");
10024
/* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
10025
  if (fg[fg_sulfuric_acid_amide_ester - 1])
10026
    printf ("Schwefels\344ureamidester\n");
10027
/* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
10028
  if (fg[fg_sulfuric_acid_amide - 1])
10029
    printf ("Schwefels\344ureamid\n");
10030
/* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
10031
  if (fg[fg_sulfuric_acid_diamide - 1])
10032
    printf ("Schwefels\344urediamid\n");
10033
/* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
10034
  if (fg[fg_sulfuryl_halide - 1])
10035
    printf ("Sulfurylhalogenid\n");
10036
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
10037
  if (fg[fg_sulfonic_acid - 1])
10038
    printf ("Sulfons\344ure\n");
10039
/* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
10040
  if (fg[fg_sulfonic_acid_ester - 1])
10041
    printf ("Sulfons\344ureester\n");
10042
/* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
10043
  if (fg[fg_sulfonamide - 1])
10044
    printf ("Sulfonamid\n");
10045
  if (fg[fg_sulfonyl_halide - 1])
10046
    printf ("Sulfonylhalogenid\n");
10047
  if (fg[fg_sulfone - 1])
10048
    printf ("Sulfon\n");
10049
  if (fg[fg_sulfoxide - 1])
10050
    printf ("Sulfoxid\n");
10051
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
10052
  if (fg[fg_sulfinic_acid - 1])
10053
    printf ("Sulfins\344ure\n");
10054
/* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
10055
  if (fg[fg_sulfinic_acid_ester - 1])
10056
    printf ("Sulfins\344ureester\n");
10057
/* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
10058
  if (fg[fg_sulfinic_acid_halide - 1])
10059
    printf ("Sulfins\344urehalogenid\n");
10060
/* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
10061
  if (fg[fg_sulfinic_acid_amide - 1])
10062
    printf ("Sulfins\344ureamid\n");
10063
/* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
10064
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
10065
  if (fg[fg_sulfenic_acid - 1])
10066
    printf ("Sulfens\344ure\n");
10067
/* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
10068
  if (fg[fg_sulfenic_acid_ester - 1])
10069
    printf ("Sulfens\344ureester\n");
10070
/* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
10071
  if (fg[fg_sulfenic_acid_halide - 1])
10072
    printf ("Sulfens\344urehalogenid\n");
10073
/* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
10074
  if (fg[fg_sulfenic_acid_amide - 1])
10075
    printf ("Sulfens\344ureamid\n");
10076
/* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
10077
  if (fg[fg_thiol - 1])
10078
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
10079
  if (fg[fg_alkylthiol - 1])
10080
    printf ("Alkylthiol\n");
10081
  if (fg[fg_arylthiol - 1])
10082
    printf ("Arylthiol\n");
10083
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
10084
  if (fg[fg_phosphoric_acid - 1])
10085
    printf ("Phosphors\344ure\n");
10086
/* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
10087
  if (fg[fg_phosphoric_acid_ester - 1])
10088
    printf ("Phosphors\344ureester\n");
10089
/* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
10090
  if (fg[fg_phosphoric_acid_halide - 1])
10091
    printf ("Phosphors\344urehalogenid\n");
10092
/* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
10093
  if (fg[fg_phosphoric_acid_amide - 1])
10094
    printf ("Phosphors\344ureamid\n");
10095
/* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
10096
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
10097
  if (fg[fg_thiophosphoric_acid - 1])
10098
    printf ("Thiophosphors\344ure\n");
10099
/* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
10100
  if (fg[fg_thiophosphoric_acid_ester - 1])
10101
    printf ("Thiophosphors\344ureester\n");
10102
/* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
10103
  if (fg[fg_thiophosphoric_acid_halide - 1])
10104
    printf ("Thiophosphors\344urehalogenid\n");
10105
/* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
10106
  if (fg[fg_thiophosphoric_acid_amide - 1])
10107
    printf ("Thiophosphors\344ureamid\n");
10108
/* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
10109
  if (fg[fg_phosphonic_acid_deriv - 1])
10110
    printf ("Phosphons\344ure-Derivat \n");
10111
/* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
10112
  if (fg[fg_phosphonic_acid - 1])
10113
    printf ("Phosphons\344ure\n");
10114
/* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
10115
  if (fg[fg_phosphonic_acid_ester - 1])
10116
    printf ("Phosphons\344ureester\n");
10117
/* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
10118
  if (fg[fg_phosphine - 1])
10119
    printf ("Phosphin\n");
10120
  if (fg[fg_phosphinoxide - 1])
10121
    printf ("Phosphinoxid\n");
10122
  if (fg[fg_boronic_acid_deriv - 1])
10123
    printf ("Borons\344ure-Derivat\n");
10124
/* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
10125
  if (fg[fg_boronic_acid - 1])
10126
    printf ("Borons\344ure\n");
10127
/* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
10128
  if (fg[fg_boronic_acid_ester - 1])
10129
    printf ("Borons\344ureester\n");
10130
/* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
10131
  if (fg[fg_alkene - 1])
10132
    printf ("Alken\n");
10133
  if (fg[fg_alkyne - 1])
10134
    printf ("Alkin\n");
10135
  if (fg[fg_aromatic - 1])
10136
    printf ("aromatische Verbindung\n");
10137
  if (fg[fg_heterocycle - 1])
10138
    printf ("heterocyclische Verbindung\n");
10139
  if (fg[fg_alpha_aminoacid - 1])
10140
    printf ("alpha-Aminos\344ure\n");
10141
/* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
10142
  if (fg[fg_alpha_hydroxyacid - 1])
10143
    printf ("alpha-Hydroxys\344ure\n");
10144
/* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
10145
}
10146
 
10147
 
10148
#define sc              ';'
10149
 
10150
 
10151
static void
10152
write_fg_code ()
10153
{
10154
  if (fg[fg_cation - 1])
10155
    printf ("000000T2%c", sc);
10156
  if (fg[fg_anion - 1])
10157
    printf ("000000T1%c", sc);
10158
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
10159
  if (fg[fg_aldehyde - 1])
10160
    printf ("C2O1H000%c", sc);
10161
  if (fg[fg_ketone - 1])
10162
    printf ("C2O1C000%c", sc);
10163
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
10164
  if (fg[fg_thioaldehyde - 1])
10165
    printf ("C2S1H000%c", sc);
10166
  if (fg[fg_thioketone - 1])
10167
    printf ("C2S1C000%c", sc);
10168
  if (fg[fg_imine - 1])
10169
    printf ("C2N10000%c", sc);
10170
  if (fg[fg_hydrazone - 1])
10171
    printf ("C2N1N000%c", sc);
10172
  if (fg[fg_semicarbazone - 1])
10173
    printf ("C2NNC4ON%c", sc);
10174
  if (fg[fg_thiosemicarbazone - 1])
10175
    printf ("C2NNC4SN%c", sc);
10176
  if (fg[fg_oxime - 1])
10177
    printf ("C2N1OH00%c", sc);
10178
  if (fg[fg_oxime_ether - 1])
10179
    printf ("C2N1OC00%c", sc);
10180
  if (fg[fg_ketene - 1])
10181
    printf ("C3OC0000%c", sc);
10182
  if (fg[fg_ketene_acetal_deriv - 1])
10183
    printf ("C3OCC000%c", sc);
10184
  if (fg[fg_carbonyl_hydrate - 1])
10185
    printf ("C2O2H200%c", sc);
10186
  if (fg[fg_hemiacetal - 1])
10187
    printf ("C2O2HC00%c", sc);
10188
  if (fg[fg_acetal - 1])
10189
    printf ("C2O2CC00%c", sc);
10190
  if (fg[fg_hemiaminal - 1])
10191
    printf ("C2NOHC10%c", sc);
10192
  if (fg[fg_aminal - 1])
10193
    printf ("C2N2CC10%c", sc);
10194
  if (fg[fg_thiohemiaminal - 1])
10195
    printf ("C2NSHC10%c", sc);
10196
  if (fg[fg_thioacetal - 1])
10197
    printf ("C2S2CC00%c", sc);
10198
  if (fg[fg_enamine - 1])
10199
    printf ("C2CNH000%c", sc);
10200
  if (fg[fg_enol - 1])
10201
    printf ("C2COH000%c", sc);
10202
  if (fg[fg_enolether - 1])
10203
    printf ("C2COC000%c", sc);
10204
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
10205
    printf ("O1H00000%c", sc);
10206
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
10207
  if (fg[fg_prim_alcohol - 1])
10208
    printf ("O1H1C000%c", sc);
10209
  if (fg[fg_sec_alcohol - 1])
10210
    printf ("O1H2C000%c", sc);
10211
  if (fg[fg_tert_alcohol - 1])
10212
    printf ("O1H3C000%c", sc);
10213
  if (fg[fg_1_2_diol - 1])
10214
    printf ("O1H0CO1H%c", sc);
10215
  if (fg[fg_1_2_aminoalcohol - 1])
10216
    printf ("O1H0CN1C%c", sc);
10217
  if (fg[fg_phenol - 1])
10218
    printf ("O1H1A000%c", sc);
10219
  if (fg[fg_1_2_diphenol - 1])
10220
    printf ("O1H2A000%c", sc);
10221
  if (fg[fg_enediol - 1])
10222
    printf ("C2COH200%c", sc);
10223
  if (fg[fg_ether - 1] && ether_generic)
10224
    printf ("O1C00000%c", sc);
10225
  if (fg[fg_dialkylether - 1])
10226
    printf ("O1C0CC00%c", sc);
10227
  if (fg[fg_alkylarylether - 1])
10228
    printf ("O1C0CA00%c", sc);
10229
  if (fg[fg_diarylether - 1])
10230
    printf ("O1C0AA00%c", sc);
10231
  if (fg[fg_thioether - 1])
10232
    printf ("S1C00000%c", sc);
10233
  if (fg[fg_disulfide - 1])
10234
    printf ("S1S1C000%c", sc);
10235
  if (fg[fg_peroxide - 1])
10236
    printf ("O1O1C000%c", sc);
10237
  if (fg[fg_hydroperoxide - 1])
10238
    printf ("O1O1H000%c", sc);
10239
  if (fg[fg_hydrazine - 1])
10240
    printf ("N1N10000%c", sc);
10241
  if (fg[fg_hydroxylamine - 1])
10242
    printf ("N1O1H000%c", sc);
10243
  if (fg[fg_amine - 1] && amine_generic)
10244
    printf ("N1C00000%c", sc);
10245
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
10246
  if (fg[fg_prim_aliph_amine - 1])
10247
    printf ("N1C1C000%c", sc);
10248
  if (fg[fg_prim_arom_amine - 1])
10249
    printf ("N1C1A000%c", sc);
10250
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
10251
  if (fg[fg_sec_aliph_amine - 1])
10252
    printf ("N1C2CC00%c", sc);
10253
  if (fg[fg_sec_mixed_amine - 1])
10254
    printf ("N1C2AC00%c", sc);
10255
  if (fg[fg_sec_arom_amine - 1])
10256
    printf ("N1C2AA00%c", sc);
10257
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
10258
  if (fg[fg_tert_aliph_amine - 1])
10259
    printf ("N1C3CC00%c", sc);
10260
  if (fg[fg_tert_mixed_amine - 1])
10261
    printf ("N1C3AC00%c", sc);
10262
  if (fg[fg_tert_arom_amine - 1])
10263
    printf ("N1C3AA00%c", sc);
10264
  if (fg[fg_quart_ammonium - 1])
10265
    printf ("N1C400T2%c", sc);
10266
  if (fg[fg_n_oxide - 1])
10267
    printf ("N0O10000%c", sc);
10268
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
10269
  /* new in v0.2f */
10270
  if (fg[fg_halogen_deriv - 1])
10271
    {
10272
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
10273
          !fg[fg_acyl_halide - 1])
10274
        printf ("XX000000%c", sc);
10275
    }
10276
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
10277
  if (fg[fg_alkyl_fluoride - 1])
10278
    printf ("XF00C000%c", sc);
10279
  if (fg[fg_alkyl_chloride - 1])
10280
    printf ("XC00C000%c", sc);
10281
  if (fg[fg_alkyl_bromide - 1])
10282
    printf ("XB00C000%c", sc);
10283
  if (fg[fg_alkyl_iodide - 1])
10284
    printf ("XI00C000%c", sc);
10285
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
10286
  if (fg[fg_aryl_fluoride - 1])
10287
    printf ("XF00A000%c", sc);
10288
  if (fg[fg_aryl_chloride - 1])
10289
    printf ("XC00A000%c", sc);
10290
  if (fg[fg_aryl_bromide - 1])
10291
    printf ("XB00A000%c", sc);
10292
  if (fg[fg_aryl_iodide - 1])
10293
    printf ("XI00A000%c", sc);
10294
  if (fg[fg_organometallic - 1])
10295
    printf ("000000MX%c", sc);
10296
  if (fg[fg_organolithium - 1])
10297
    printf ("000000ML%c", sc);
10298
  if (fg[fg_organomagnesium - 1])
10299
    printf ("000000MM%c", sc);
10300
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
10301
  if (fg[fg_carboxylic_acid - 1])
10302
    printf ("C3O2H000%c", sc);
10303
  if (fg[fg_carboxylic_acid_salt - 1])
10304
    printf ("C3O200T1%c", sc);
10305
  if (fg[fg_carboxylic_acid_ester - 1])
10306
    printf ("C3O2C000%c", sc);
10307
  if (fg[fg_lactone - 1])
10308
    printf ("C3O2CZ00%c", sc);
10309
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
10310
  if (fg[fg_carboxylic_acid_prim_amide - 1])
10311
    printf ("C3ONC100%c", sc);
10312
  if (fg[fg_carboxylic_acid_sec_amide - 1])
10313
    printf ("C3ONC200%c", sc);
10314
  if (fg[fg_carboxylic_acid_tert_amide - 1])
10315
    printf ("C3ONC300%c", sc);
10316
  if (fg[fg_lactam - 1])
10317
    printf ("C3ONCZ00%c", sc);
10318
  if (fg[fg_carboxylic_acid_hydrazide - 1])
10319
    printf ("C3ONN100%c", sc);
10320
  if (fg[fg_carboxylic_acid_azide - 1])
10321
    printf ("C3ONN200%c", sc);
10322
  if (fg[fg_hydroxamic_acid - 1])
10323
    printf ("C3ONOH00%c", sc);
10324
  if (fg[fg_carboxylic_acid_amidine - 1])
10325
    printf ("C3N2H000%c", sc);
10326
  if (fg[fg_carboxylic_acid_amidrazone - 1])
10327
    printf ("C3NNN100%c", sc);
10328
  if (fg[fg_nitrile - 1])
10329
    printf ("C3N00000%c", sc);
10330
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
10331
  if (fg[fg_acyl_fluoride - 1])
10332
    printf ("C3OXF000%c", sc);
10333
  if (fg[fg_acyl_chloride - 1])
10334
    printf ("C3OXC000%c", sc);
10335
  if (fg[fg_acyl_bromide - 1])
10336
    printf ("C3OXB000%c", sc);
10337
  if (fg[fg_acyl_iodide - 1])
10338
    printf ("C3OXI000%c", sc);
10339
  if (fg[fg_acyl_cyanide - 1])
10340
    printf ("C2OC3N00%c", sc);
10341
  if (fg[fg_imido_ester - 1])
10342
    printf ("C3NOC000%c", sc);
10343
  if (fg[fg_imidoyl_halide - 1])
10344
    printf ("C3NXX000%c", sc);
10345
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
10346
  if (fg[fg_thiocarboxylic_acid - 1])
10347
    printf ("C3SOH000%c", sc);
10348
  if (fg[fg_thiocarboxylic_acid_ester - 1])
10349
    printf ("C3SOC000%c", sc);
10350
  if (fg[fg_thiolactone - 1])
10351
    printf ("C3SOCZ00%c", sc);
10352
  if (fg[fg_thiocarboxylic_acid_amide - 1])
10353
    printf ("C3SNH000%c", sc);
10354
  if (fg[fg_thiolactam - 1])
10355
    printf ("C3SNCZ00%c", sc);
10356
  if (fg[fg_imido_thioester - 1])
10357
    printf ("C3NSC000%c", sc);
10358
  if (fg[fg_oxohetarene - 1])
10359
    printf ("C3ONAZ00%c", sc);
10360
  if (fg[fg_thioxohetarene - 1])
10361
    printf ("C3SNAZ00%c", sc);
10362
  if (fg[fg_iminohetarene - 1])
10363
    printf ("C3NNAZ00%c", sc);
10364
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
10365
    printf ("C3O30000%c", sc);
10366
  if (fg[fg_carboxylic_acid_orthoester - 1])
10367
    printf ("C3O3C000%c", sc);
10368
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
10369
    printf ("C3O3NC00%c", sc);
10370
  if (fg[fg_carboxylic_acid_anhydride - 1])
10371
    printf ("C3O2C3O2%c", sc);
10372
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
10373
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
10374
    printf ("C3ONCH10%c", sc);
10375
  if (fg[fg_carboxylic_acid_subst_imide - 1])
10376
    printf ("C3ONCC10%c", sc);
10377
  if (fg[fg_co2_deriv - 1])
10378
    printf ("C4000000%c", sc);
10379
  if (fg[fg_carbonic_acid_deriv - 1])
10380
    printf ("C4O30000%c", sc);
10381
  if (fg[fg_carbonic_acid_monoester - 1])
10382
    printf ("C4O3C100%c", sc);
10383
  if (fg[fg_carbonic_acid_diester - 1])
10384
    printf ("C4O3C200%c", sc);
10385
  if (fg[fg_carbonic_acid_ester_halide - 1])
10386
    printf ("C4O3CX00%c", sc);
10387
  if (fg[fg_thiocarbonic_acid_deriv - 1])
10388
    printf ("C4SO0000%c", sc);
10389
  if (fg[fg_thiocarbonic_acid_monoester - 1])
10390
    printf ("C4SOC100%c", sc);
10391
  if (fg[fg_thiocarbonic_acid_diester - 1])
10392
    printf ("C4SOC200%c", sc);
10393
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
10394
    printf ("C4SOX_00%c", sc);
10395
  if (fg[fg_carbamic_acid_deriv - 1])
10396
    printf ("C4O2N000%c", sc);
10397
  if (fg[fg_carbamic_acid - 1])
10398
    printf ("C4O2NH00%c", sc);
10399
  if (fg[fg_carbamic_acid_ester - 1])
10400
    printf ("C4O2NC00%c", sc);
10401
  if (fg[fg_carbamic_acid_halide - 1])
10402
    printf ("C4O2NX00%c", sc);
10403
  if (fg[fg_thiocarbamic_acid_deriv - 1])
10404
    printf ("C4SN0000%c", sc);
10405
  if (fg[fg_thiocarbamic_acid - 1])
10406
    printf ("C4SNOH00%c", sc);
10407
  if (fg[fg_thiocarbamic_acid_ester - 1])
10408
    printf ("C4SNOC00%c", sc);
10409
  if (fg[fg_thiocarbamic_acid_halide - 1])
10410
    printf ("C4SNXX00%c", sc);
10411
  if (fg[fg_urea - 1])
10412
    printf ("C4O1N200%c", sc);
10413
  if (fg[fg_isourea - 1])
10414
    printf ("C4N2O100%c", sc);
10415
  if (fg[fg_thiourea - 1])
10416
    printf ("C4S1N200%c", sc);
10417
  if (fg[fg_isothiourea - 1])
10418
    printf ("C4N2S100%c", sc);
10419
  if (fg[fg_guanidine - 1])
10420
    printf ("C4N30000%c", sc);
10421
  if (fg[fg_semicarbazide - 1])
10422
    printf ("C4ON2N00%c", sc);
10423
  if (fg[fg_thiosemicarbazide - 1])
10424
    printf ("C4SN2N00%c", sc);
10425
  if (fg[fg_azide - 1])
10426
    printf ("N4N20000%c", sc);
10427
  if (fg[fg_azo_compound - 1])
10428
    printf ("N2N10000%c", sc);
10429
  if (fg[fg_diazonium_salt - 1])
10430
    printf ("N3N100T2%c", sc);
10431
  if (fg[fg_isonitrile - 1])
10432
    printf ("N3C10000%c", sc);
10433
  if (fg[fg_cyanate - 1])
10434
    printf ("C4NO1000%c", sc);
10435
  if (fg[fg_isocyanate - 1])
10436
    printf ("C4NO2000%c", sc);
10437
  if (fg[fg_thiocyanate - 1])
10438
    printf ("C4NS1000%c", sc);
10439
  if (fg[fg_isothiocyanate - 1])
10440
    printf ("C4NS2000%c", sc);
10441
  if (fg[fg_carbodiimide - 1])
10442
    printf ("C4N20000%c", sc);
10443
  if (fg[fg_nitroso_compound - 1])
10444
    printf ("N2O10000%c", sc);
10445
  if (fg[fg_nitro_compound - 1])
10446
    printf ("N4O20000%c", sc);
10447
  if (fg[fg_nitrite - 1])
10448
    printf ("N3O20000%c", sc);
10449
  if (fg[fg_nitrate - 1])
10450
    printf ("N4O30000%c", sc);
10451
  if (fg[fg_sulfuric_acid_deriv - 1])
10452
    printf ("S6O00000%c", sc);
10453
  if (fg[fg_sulfuric_acid - 1])
10454
    printf ("S6O4H000%c", sc);
10455
  if (fg[fg_sulfuric_acid_monoester - 1])
10456
    printf ("S6O4HC00%c", sc);
10457
  if (fg[fg_sulfuric_acid_diester - 1])
10458
    printf ("S6O4CC00%c", sc);
10459
  if (fg[fg_sulfuric_acid_amide_ester - 1])
10460
    printf ("S6O3NC00%c", sc);
10461
  if (fg[fg_sulfuric_acid_amide - 1])
10462
    printf ("S6O3N100%c", sc);
10463
  if (fg[fg_sulfuric_acid_diamide - 1])
10464
    printf ("S6O2N200%c", sc);
10465
  if (fg[fg_sulfuryl_halide - 1])
10466
    printf ("S6O3XX00%c", sc);
10467
  if (fg[fg_sulfonic_acid_deriv - 1])
10468
    printf ("S5O00000%c", sc);
10469
  if (fg[fg_sulfonic_acid - 1])
10470
    printf ("S5O3H000%c", sc);
10471
  if (fg[fg_sulfonic_acid_ester - 1])
10472
    printf ("S5O3C000%c", sc);
10473
  if (fg[fg_sulfonamide - 1])
10474
    printf ("S5O2N000%c", sc);
10475
  if (fg[fg_sulfonyl_halide - 1])
10476
    printf ("S5O2XX00%c", sc);
10477
  if (fg[fg_sulfone - 1])
10478
    printf ("S4O20000%c", sc);
10479
  if (fg[fg_sulfoxide - 1])
10480
    printf ("S2O10000%c", sc);
10481
  if (fg[fg_sulfinic_acid_deriv - 1])
10482
    printf ("S3O00000%c", sc);
10483
  if (fg[fg_sulfinic_acid - 1])
10484
    printf ("S3O2H000%c", sc);
10485
  if (fg[fg_sulfinic_acid_ester - 1])
10486
    printf ("S3O2C000%c", sc);
10487
  if (fg[fg_sulfinic_acid_halide - 1])
10488
    printf ("S3O1XX00%c", sc);
10489
  if (fg[fg_sulfinic_acid_amide - 1])
10490
    printf ("S3O1N000%c", sc);
10491
  if (fg[fg_sulfenic_acid_deriv - 1])
10492
    printf ("S1O00000%c", sc);
10493
  if (fg[fg_sulfenic_acid - 1])
10494
    printf ("S1O1H000%c", sc);
10495
  if (fg[fg_sulfenic_acid_ester - 1])
10496
    printf ("S1O1C000%c", sc);
10497
  if (fg[fg_sulfenic_acid_halide - 1])
10498
    printf ("S1O0XX00%c", sc);
10499
  if (fg[fg_sulfenic_acid_amide - 1])
10500
    printf ("S1O0N100%c", sc);
10501
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
10502
  if (fg[fg_alkylthiol - 1])
10503
    printf ("S1H1C000%c", sc);
10504
  if (fg[fg_arylthiol - 1])
10505
    printf ("S1H1A000%c", sc);
10506
  if (fg[fg_phosphoric_acid_deriv - 1])
10507
    printf ("P5O0H000%c", sc);
10508
  if (fg[fg_phosphoric_acid - 1])
10509
    printf ("P5O4H200%c", sc);
10510
  if (fg[fg_phosphoric_acid_ester - 1])
10511
    printf ("P5O4HC00%c", sc);
10512
  if (fg[fg_phosphoric_acid_halide - 1])
10513
    printf ("P5O3HX00%c", sc);
10514
  if (fg[fg_phosphoric_acid_amide - 1])
10515
    printf ("P5O3HN00%c", sc);
10516
  if (fg[fg_thiophosphoric_acid_deriv - 1])
10517
    printf ("P5O0S000%c", sc);
10518
  if (fg[fg_thiophosphoric_acid - 1])
10519
    printf ("P5O3SH00%c", sc);
10520
  if (fg[fg_thiophosphoric_acid_ester - 1])
10521
    printf ("P5O3SC00%c", sc);
10522
  if (fg[fg_thiophosphoric_acid_halide - 1])
10523
    printf ("P5O2SX00%c", sc);
10524
  if (fg[fg_thiophosphoric_acid_amide - 1])
10525
    printf ("P5O2SN00%c", sc);
10526
  if (fg[fg_phosphonic_acid_deriv - 1])
10527
    printf ("P4O30000%c", sc);
10528
  if (fg[fg_phosphonic_acid - 1])
10529
    printf ("P4O3H000%c", sc);
10530
  if (fg[fg_phosphonic_acid_ester - 1])
10531
    printf ("P4O3C000%c", sc);
10532
  if (fg[fg_phosphine - 1])
10533
    printf ("P3000000%c", sc);
10534
  if (fg[fg_phosphinoxide - 1])
10535
    printf ("P2O00000%c", sc);
10536
  if (fg[fg_boronic_acid_deriv - 1])
10537
    printf ("B2O20000%c", sc);
10538
  if (fg[fg_boronic_acid - 1])
10539
    printf ("B2O2H000%c", sc);
10540
  if (fg[fg_boronic_acid_ester - 1])
10541
    printf ("B2O2C000%c", sc);
10542
  if (fg[fg_alkene - 1])
10543
    printf ("000C2C00%c", sc);
10544
  if (fg[fg_alkyne - 1])
10545
    printf ("000C3C00%c", sc);
10546
  if (fg[fg_aromatic - 1])
10547
    printf ("0000A000%c", sc);
10548
  if (fg[fg_heterocycle - 1])
10549
    printf ("0000CZ00%c", sc);
10550
  if (fg[fg_alpha_aminoacid - 1])
10551
    printf ("C3O2HN1C%c", sc);
10552
  if (fg[fg_alpha_hydroxyacid - 1])
10553
    printf ("C3O2HO1H%c", sc);
10554
}
10555
 
10556
#undef sc
10557
 
10558
 
10559
static void
10560
write_fg_binary ()
10561
{
10562
  int i, n;
10563
  char o;
10564
 
10565
  for (i = 1; i <= max_fg / 8; i++)
10566
    {
10567
      n = 0;
10568
      if (fg[i * 8 - 1])
10569
        n++;
10570
      if (fg[i * 8 - 2])
10571
        n += 2;
10572
      if (fg[i * 8 - 3])
10573
        n += 4;
10574
      if (fg[i * 8 - 4])
10575
        n += 8;
10576
      if (fg[i * 8 - 5])
10577
        n += 16;
10578
      if (fg[i * 8 - 6])
10579
        n += 32;
10580
      if (fg[i * 8 - 7])
10581
        n += 64;
10582
      if (fg[i * 8 - 8])
10583
        n += 128;
10584
      o = (char) n;
10585
      putchar (o);
10586
    }
10587
}
10588
 
10589
 
10590
static void
10591
write_fg_bitstring ()
10592
{
10593
  int i;
10594
 
10595
  for (i = 0; i < max_fg; i++)
10596
    {
10597
      if (fg[i])
10598
        putchar ('1');
10599
      else
10600
        putchar ('0');
10601
    }
10602
}
10603
 
10604
 
10605
#if 0
10606
static void readinputfile (molfilename) char *molfilename;
10607
     {
10608
     /* new version in v0.2g */
10609
     char rline[256];
10610
     char *TEMP;
10611
 
10612
     molbufindex = 0;
10613
     if (!opt_stdin)
10614
     {
10615
     if (!rfile_is_open)
10616
     {
10617
     assign (rfile, molfilename);
10618
     rewind (rfile);
10619
     rfile_is_open = true;
10620
     }
10621
     /* p2c: checkmol.pas, line 7733: Warning:
10622
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
10623
     *rline = '\0';
10624
     mol_in_queue = false;
10625
     while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
10626
     {
10627
     fgets (rline, 256, rfile);
10628
     TEMP = strchr (rline, '\n');
10629
     if (TEMP != NULL)
10630
     *TEMP = 0;
10631
     /*mol_in_queue := false; */
10632
     if (molbufindex >= max_atoms + max_bonds + 64)
10633
     {
10634
     printf ("Not enough memory for molfile! %12ld\n",
10635
     molbufindex);
10636
     if (rfile != NULL)
10637
     fclose (rfile);
10638
     rfile = NULL;
10639
     _Escape (1);
10640
     }
10641
     molbufindex++;
10642
     strcpy (molbuf[molbufindex - 1], rline);
10643
     if (strpos2 (rline, "$$$$", 1) > 0)
10644
     mol_in_queue = true;
10645
     }
10646
     if (!P_eof (rfile))
10647
     return;
10648
     if (rfile != NULL)
10649
     fclose (rfile);
10650
     rfile = NULL;
10651
     rfile_is_open = false;
10652
     mol_in_queue = false;
10653
     return;
10654
     }
10655
     *rline = '\0';
10656
     mol_in_queue = false;
10657
     while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
10658
     {
10659
     gets (rline);
10660
     if (molbufindex >= max_atoms + max_bonds + 64)
10661
     {
10662
     printf ("Not enough memory!\n");
10663
     _Escape (1);
10664
     }
10665
     molbufindex++;
10666
     strcpy (molbuf[molbufindex - 1], rline);
10667
     if (strpos2 (rline, "$$$$", 1) > 0)
10668
     {
10669
     mol_in_queue = true;
10670
     /* read from standard input
10671
     }
10672
     }
10673
     } */
10674
#endif
10675
 
10676
static void
10677
readinputfile (char *molfilename)
10678
{
10679
  /* new version in v0.2g */
10680
  char rline[256];
10681
  char *TEMP;
10682
 
10683
  molbufindex = 0;
10684
  if (!opt_stdin)
10685
    {
10686
      if (!rfile_is_open)
10687
        {
10688
          rfile = fopen (molfilename, "r");
10689
          rewind (rfile);
10690
          rfile_is_open = true;
10691
        }
10692
/* p2c: checkmol.pas, line 7226: Warning:
10693
 * Don't know how to ASSIGN to a non-explicit file variable [207] */
10694
      *rline = '\0';
10695
      mol_in_queue = false;
10696
      while ((fgets (rline, 256, rfile) != NULL)
10697
             && (strstr (rline, "$$$$") == NULL))
10698
        {
10699
          TEMP = strchr (rline, '\n');
10700
          if (TEMP != NULL)
10701
            *TEMP = 0;
10702
          /*mol_in_queue := false; */
10703
          if (molbufindex >= max_atoms + max_bonds + 64)
10704
            {
10705
              printf ("Not enough memory for molfile! %d\n", molbufindex);
10706
              if (rfile != NULL)
10707
                fclose (rfile);
10708
              rfile = NULL;
10709
              exit (1);
10710
            }
10711
          //molbufindex++;
10712
          strcpy (molbuf[molbufindex++], rline);
10713
          if (strstr (rline, "$$$$") != NULL)
10714
            mol_in_queue = true;
10715
        }
10716
      if (!feof (rfile))
10717
        return;
10718
      if (rfile != NULL)
10719
        fclose (rfile);
10720
      rfile = NULL;
10721
      rfile_is_open = false;
10722
      mol_in_queue = false;
10723
      return;
10724
    }
10725
  *rline = '\0';
10726
  mol_in_queue = false;
10727
  do
10728
    {
10729
      fgets (rline, 256, stdin);
10730
      if (feof (stdin))
10731
        return;
10732
      TEMP = strchr (rline, '\n');
10733
      if (TEMP != NULL)
10734
        *TEMP = '\0';
10735
      if (molbufindex >= max_atoms + max_bonds + 64)
10736
        {
10737
          printf ("Not enough memory!\n");
10738
          exit (1);
10739
        }
10740
      //molbufindex++;
10741
      strcpy (molbuf[molbufindex++], rline);
10742
      if (strstr (rline, "$$$$") != NULL)
10743
        {
10744
          mol_in_queue = true;
10745
          /* read from standard input */
10746
        }
10747
    }
10748
  while (strstr (rline, "$$$$") == NULL);
10749
}
10750
 
10751
#if 0
10752
static void copy_mol_to_needle()
10753
{
10754
  int i, j, FORLIM;
10755
 
10756
  if (n_atoms == 0)
10757
    return;
10758
  /* try */
10759
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10760
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10761
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10762
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10763
  /* except*/
10764
    on e:Eoutofmemory do
10765
      begin
10766
        writeln('Not enough memory');
10767
        halt(4);
10768
      end;
10769
  end;
10770
  ndl_n_atoms = n_atoms;
10771
  ndl_n_bonds = n_bonds;
10772
  ndl_n_rings = n_rings;
10773
  ndl_n_heavyatoms = n_heavyatoms;
10774
  ndl_n_heavybonds = n_heavybonds;
10775
  strcpy(ndl_molname, molname);
10776
  ndl_n_Ctot = n_Ctot;
10777
  ndl_n_Otot = n_Otot;
10778
  ndl_n_Ntot = n_Ntot;
10779
  FORLIM = n_atoms;
10780
  for (i = 0; i < FORLIM; i++) {
10781
    strcpy(ndl_atom[i].element, atom[i].element);
10782
    strcpy(ndl_atom[i].atype, atom[i].atype);
10783
    ndl_atom[i].x = atom[i].x;
10784
    ndl_atom[i].y = atom[i].y;
10785
    ndl_atom[i].z = atom[i].z;
10786
    ndl_atom[i].formal_charge = atom[i].formal_charge;
10787
    ndl_atom[i].real_charge = atom[i].real_charge;
10788
    ndl_atom[i].Hexp = atom[i].Hexp;
10789
    ndl_atom[i].Htot = atom[i].Htot;
10790
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
10791
    ndl_atom[i].ring_count = atom[i].ring_count;
10792
    ndl_atom[i].arom = atom[i].arom;
10793
    ndl_atom[i].stereo_care = atom[i].stereo_care;
10794
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
10795
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
10796
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
10797
                                           }
10798
                                           if (n_bonds > 0) {
10799
                                           FORLIM = n_bonds;
10800
                                           for (i = 0; i < FORLIM; i++) {
10801
                                           ndl_bond[i].a1 = bond[i].a1;
10802
                                           ndl_bond[i].a2 = bond[i].a2;
10803
                                           ndl_bond[i].btype = bond[i].btype;
10804
                                           ndl_bond[i].arom = bond[i].arom;
10805
                                           ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
10806
                                           ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
10807
                                           ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
10808
                                           }
10809
                                           }
10810
                                           if (n_rings > 0) {
10811
                                           FORLIM = n_rings;
10812
                                           for (i = 0; i < FORLIM; i++) {
10813
                                           for (j = 0; j < max_ringsize; j++)
10814
                                           ndl_ring[i][j] = ring[i][j];
10815
                                           }
10816
                                           for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10817
                                           ndl_ringprop[i].size = ringprop[i].size;
10818
                                           ndl_ringprop[i].arom = ringprop[i].arom;
10819
                                           ndl_ringprop[i].envelope = ringprop[i].envelope;
10820
                                           }
10821
                                           }
10822
                                           ndl_molstat.n_QA = molstat.n_QA;
10823
                                           ndl_molstat.n_QB = molstat.n_QB;
10824
                                           ndl_molstat.n_chg = molstat.n_chg;
10825
                                           ndl_molstat.n_C1 = molstat.n_C1;
10826
                                           ndl_molstat.n_C2 = molstat.n_C2;
10827
                                           ndl_molstat.n_C = molstat.n_C;
10828
                                           ndl_molstat.n_CHB1p = molstat.n_CHB1p;
10829
                                           ndl_molstat.n_CHB2p = molstat.n_CHB2p;
10830
                                           ndl_molstat.n_CHB3p = molstat.n_CHB3p;
10831
                                           ndl_molstat.n_CHB4 = molstat.n_CHB4;
10832
                                           ndl_molstat.n_O2 = molstat.n_O2;
10833
                                           ndl_molstat.n_O3 = molstat.n_O3;
10834
                                           ndl_molstat.n_N1 = molstat.n_N1;
10835
                                           ndl_molstat.n_N2 = molstat.n_N2;
10836
                                           ndl_molstat.n_N3 = molstat.n_N3;
10837
                                           ndl_molstat.n_S = molstat.n_S;
10838
                                           ndl_molstat.n_SeTe = molstat.n_SeTe;
10839
                                           ndl_molstat.n_F = molstat.n_F;
10840
                                           ndl_molstat.n_Cl = molstat.n_Cl;
10841
                                           ndl_molstat.n_Br = molstat.n_Br;
10842
                                           ndl_molstat.n_I = molstat.n_I;
10843
                                           ndl_molstat.n_P = molstat.n_P;
10844
                                           ndl_molstat.n_B = molstat.n_B;
10845
                                           ndl_molstat.n_Met = molstat.n_Met;
10846
                                           ndl_molstat.n_X = molstat.n_X;
10847
                                           ndl_molstat.n_b1 = molstat.n_b1;
10848
                                           ndl_molstat.n_b2 = molstat.n_b2;
10849
                                           ndl_molstat.n_b3 = molstat.n_b3;
10850
                                           ndl_molstat.n_bar = molstat.n_bar;
10851
                                           ndl_molstat.n_C1O = molstat.n_C1O;
10852
                                           ndl_molstat.n_C2O = molstat.n_C2O;
10853
                                           ndl_molstat.n_CN = molstat.n_CN;
10854
                                           ndl_molstat.n_XY = molstat.n_XY;
10855
                                           ndl_molstat.n_r3 = molstat.n_r3;
10856
                                           ndl_molstat.n_r4 = molstat.n_r4;
10857
                                           ndl_molstat.n_r5 = molstat.n_r5;
10858
                                           ndl_molstat.n_r6 = molstat.n_r6;
10859
                                           ndl_molstat.n_r7 = molstat.n_r7;
10860
                                           ndl_molstat.n_r8 = molstat.n_r8;
10861
                                           ndl_molstat.n_r9 = molstat.n_r9;
10862
                                           ndl_molstat.n_r10 = molstat.n_r10;
10863
                                           ndl_molstat.n_r11 = molstat.n_r11;
10864
                                           ndl_molstat.n_r12 = molstat.n_r12;
10865
                                           ndl_molstat.n_r13p = molstat.n_r13p;
10866
                                           ndl_molstat.n_rN = molstat.n_rN;
10867
                                           ndl_molstat.n_rN1 = molstat.n_rN1;
10868
                                           ndl_molstat.n_rN2 = molstat.n_rN2;
10869
                                           ndl_molstat.n_rN3p = molstat.n_rN3p;
10870
                                           ndl_molstat.n_rO = molstat.n_rO;
10871
                                           ndl_molstat.n_rO1 = molstat.n_rO1;
10872
                                           ndl_molstat.n_rO2p = molstat.n_rO2p;
10873
                                           ndl_molstat.n_rS = molstat.n_rS;
10874
                                           ndl_molstat.n_rX = molstat.n_rX;
10875
                                           ndl_molstat.n_rAr = molstat.n_rAr;
10876
                                           ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
10877
                                           ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
10878
                                           /* p2c: checkmol.pas, line 7875:
10879
                                           * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10880
                                           /*$IFDEF extended_molstat
10881
                                            v0.3m */
10882
                                           ndl_molstat.n_psg01 = molstat.n_psg01;
10883
                                           ndl_molstat.n_psg02 = molstat.n_psg02;
10884
                                           ndl_molstat.n_psg13 = molstat.n_psg13;
10885
                                           ndl_molstat.n_psg14 = molstat.n_psg14;
10886
                                           ndl_molstat.n_psg15 = molstat.n_psg15;
10887
                                           ndl_molstat.n_psg16 = molstat.n_psg16;
10888
                                           ndl_molstat.n_psg17 = molstat.n_psg17;
10889
                                           ndl_molstat.n_psg18 = molstat.n_psg18;
10890
                                           ndl_molstat.n_pstm = molstat.n_pstm;
10891
                                           ndl_molstat.n_psla = molstat.n_psla;
10892
                                           $ENDIF*/
10893
                                           /* make sure some modes can be switched on only by the query file *M*/
10894
                                           /* and not by subsequent haystack file(s) */
10895
                                           if (ez_flag)   /* new in v0.3f */
10896
                                           ez_search = true;
10897
                                           if (chir_flag)   /* new in v0.3f */
10898
                                           rs_search = true;
10899
                                           }
10900
#endif
10901
 
10902
 
10903
static void
10904
copy_mol_to_needle ()
10905
{
10906
  //int i, j, FORLIM;
10907
 
10908
  /*if (n_atoms == 0)
10909
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10910
 
10911
 
10912
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10913
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10914
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10915
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10916
 
10917
 
10918
  ndl_n_atoms = n_atoms;
10919
  ndl_n_bonds = n_bonds;
10920
  ndl_n_rings = n_rings;
10921
  ndl_n_heavyatoms = n_heavyatoms;
10922
  ndl_n_heavybonds = n_heavybonds;
10923
  strcpy (ndl_molname, molname);
10924
  ndl_n_Ctot = n_Ctot;
10925
  ndl_n_Otot = n_Otot;
10926
  ndl_n_Ntot = n_Ntot;
10927
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
10928
 
10929
  if (n_bonds > 0)
10930
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
10931
 
10932
  if (n_rings > 0)
10933
    {
10934
      memcpy (ndl_ring, ring, sizeof (ringlist));
10935
      memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
10936
    }
10937
 
10938
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
10939
 
10940
 
10941
  // make sure some modes can be switched on only by the query file 
10942
  // and not by subsequent haystack file(s) 
10943
  if (ez_flag)                  // new in v0.3f 
10944
    ez_search = true;
10945
 
10946
  if (chir_flag)                // new in v0.3f 
10947
    rs_search = true;
10948
 
10949
  ndl_querymol = found_querymol;        /* 0.3p */
10950
 
10951
}
10952
 
10953
static void
10954
copy_mol_to_tmp ()
10955
{
10956
  //int i, j, FORLIM;
10957
 
10958
  /*if (n_atoms == 0)
10959
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10960
 
10961
 
10962
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10963
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10964
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10965
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10966
 
10967
 
10968
  tmp_n_atoms = n_atoms;
10969
  tmp_n_bonds = n_bonds;
10970
  tmp_n_rings = n_rings;
10971
  tmp_n_heavyatoms = n_heavyatoms;
10972
  tmp_n_heavybonds = n_heavybonds;
10973
  strcpy (tmp_molname, molname);
10974
  tmp_n_Ctot = n_Ctot;
10975
  tmp_n_Otot = n_Otot;
10976
  tmp_n_Ntot = n_Ntot;
10977
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
10978
 
10979
  if (n_bonds > 0)
10980
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
10981
 
10982
  if (n_rings > 0)
10983
    {
10984
      memcpy (tmp_ring, ring, sizeof (ringlist));
10985
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
10986
    }
10987
 
10988
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
10989
 
10990
 
10991
  // make sure some modes can be switched on only by the query file 
10992
  // and not by subsequent haystack file(s) 
10993
  if (ez_flag)                  // new in v0.3f 
10994
    ez_search = true;
10995
 
10996
  if (chir_flag)                // new in v0.3f 
10997
    rs_search = true;
10998
 
10999
  ndl_querymol = found_querymol;        /* 0.3p */
11000
 
11001
}
11002
 
11003
#if 0
11004
static void copy_mol_to_tmp()
11005
{
11006
  int i, j, FORLIM;
11007
 
11008
  if (n_atoms == 0)
11009
    return;
11010
  /* try */
11011
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
11012
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
11013
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
11014
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
11015
  /* except */
11016
    on e:Eoutofmemory do
11017
      begin
11018
        writeln('Not enough memory');
11019
        halt(4);
11020
      end;
11021
  end;
11022
  tmp_n_atoms = n_atoms;
11023
  tmp_n_bonds = n_bonds;
11024
  tmp_n_rings = n_rings;
11025
  tmp_n_heavyatoms = n_heavyatoms;
11026
  tmp_n_heavybonds = n_heavybonds;
11027
  strcpy(tmp_molname, molname);
11028
  tmp_n_Ctot = n_Ctot;
11029
  tmp_n_Otot = n_Otot;
11030
  tmp_n_Ntot = n_Ntot;
11031
  FORLIM = n_atoms;
11032
  for (i = 0; i < FORLIM; i++) {
11033
    strcpy(tmp_atom[i].element, atom[i].element);
11034
    strcpy(tmp_atom[i].atype, atom[i].atype);
11035
    tmp_atom[i].x = atom[i].x;
11036
    tmp_atom[i].y = atom[i].y;
11037
    tmp_atom[i].z = atom[i].z;
11038
    tmp_atom[i].formal_charge = atom[i].formal_charge;
11039
    tmp_atom[i].real_charge = atom[i].real_charge;
11040
    tmp_atom[i].Hexp = atom[i].Hexp;
11041
    tmp_atom[i].Htot = atom[i].Htot;
11042
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
11043
    tmp_atom[i].ring_count = atom[i].ring_count;
11044
    tmp_atom[i].arom = atom[i].arom;
11045
    tmp_atom[i].stereo_care = atom[i].stereo_care;
11046
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
11047
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
11048
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
11049
  }
11050
  if (n_bonds > 0) {
11051
    FORLIM = n_bonds;
11052
    for (i = 0; i < FORLIM; i++) {
11053
      tmp_bond[i].a1 = bond[i].a1;
11054
      tmp_bond[i].a2 = bond[i].a2;
11055
      tmp_bond[i].btype = bond[i].btype;
11056
      tmp_bond[i].arom = bond[i].arom;
11057
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
11058
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
11059
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
11060
    }
11061
  }
11062
  if (n_rings > 0) {
11063
    FORLIM = n_rings;
11064
    for (i = 0; i < FORLIM; i++) {
11065
      for (j = 0; j < max_ringsize; j++)
11066
        tmp_ring[i][j] = ring[i][j];
11067
    }
11068
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
11069
      tmp_ringprop[i].size = ringprop[i].size;
11070
      tmp_ringprop[i].arom = ringprop[i].arom;
11071
      tmp_ringprop[i].envelope = ringprop[i].envelope;
11072
    }
11073
  }
11074
  tmp_molstat.n_QA = molstat.n_QA;
11075
  tmp_molstat.n_QB = molstat.n_QB;
11076
  tmp_molstat.n_chg = molstat.n_chg;
11077
  tmp_molstat.n_C1 = molstat.n_C1;
11078
  tmp_molstat.n_C2 = molstat.n_C2;
11079
  tmp_molstat.n_C = molstat.n_C;
11080
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
11081
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
11082
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
11083
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
11084
  tmp_molstat.n_O2 = molstat.n_O2;
11085
  tmp_molstat.n_O3 = molstat.n_O3;
11086
  tmp_molstat.n_N1 = molstat.n_N1;
11087
  tmp_molstat.n_N2 = molstat.n_N2;
11088
  tmp_molstat.n_N3 = molstat.n_N3;
11089
  tmp_molstat.n_S = molstat.n_S;
11090
  tmp_molstat.n_SeTe = molstat.n_SeTe;
11091
  tmp_molstat.n_F = molstat.n_F;
11092
  tmp_molstat.n_Cl = molstat.n_Cl;
11093
  tmp_molstat.n_Br = molstat.n_Br;
11094
  tmp_molstat.n_I = molstat.n_I;
11095
  tmp_molstat.n_P = molstat.n_P;
11096
  tmp_molstat.n_B = molstat.n_B;
11097
  tmp_molstat.n_Met = molstat.n_Met;
11098
  tmp_molstat.n_X = molstat.n_X;
11099
  tmp_molstat.n_b1 = molstat.n_b1;
11100
  tmp_molstat.n_b2 = molstat.n_b2;
11101
  tmp_molstat.n_b3 = molstat.n_b3;
11102
  tmp_molstat.n_bar = molstat.n_bar;
11103
  tmp_molstat.n_C1O = molstat.n_C1O;
11104
  tmp_molstat.n_C2O = molstat.n_C2O;
11105
  tmp_molstat.n_CN = molstat.n_CN;
11106
  tmp_molstat.n_XY = molstat.n_XY;
11107
  tmp_molstat.n_r3 = molstat.n_r3;
11108
  tmp_molstat.n_r4 = molstat.n_r4;
11109
  tmp_molstat.n_r5 = molstat.n_r5;
11110
  tmp_molstat.n_r6 = molstat.n_r6;
11111
  tmp_molstat.n_r7 = molstat.n_r7;
11112
  tmp_molstat.n_r8 = molstat.n_r8;
11113
  tmp_molstat.n_r9 = molstat.n_r9;
11114
  tmp_molstat.n_r10 = molstat.n_r10;
11115
  tmp_molstat.n_r11 = molstat.n_r11;
11116
  tmp_molstat.n_r12 = molstat.n_r12;
11117
  tmp_molstat.n_r13p = molstat.n_r13p;
11118
  tmp_molstat.n_rN = molstat.n_rN;
11119
  tmp_molstat.n_rN1 = molstat.n_rN1;
11120
  tmp_molstat.n_rN2 = molstat.n_rN2;
11121
  tmp_molstat.n_rN3p = molstat.n_rN3p;
11122
  tmp_molstat.n_rO = molstat.n_rO;
11123
  tmp_molstat.n_rO1 = molstat.n_rO1;
11124
  tmp_molstat.n_rO2p = molstat.n_rO2p;
11125
  tmp_molstat.n_rS = molstat.n_rS;
11126
  tmp_molstat.n_rX = molstat.n_rX;
11127
  tmp_molstat.n_rAr = molstat.n_rAr;
11128
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
11129
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
11130
/* p2c: checkmol.pas, line 8022:
11131
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11132
  /*$IFDEF extended_molstat
11133
   v0.3m
11134
  tmp_molstat.n_psg01 = molstat.n_psg01;
11135
  tmp_molstat.n_psg02 = molstat.n_psg02;
11136
  tmp_molstat.n_psg13 = molstat.n_psg13;
11137
  tmp_molstat.n_psg14 = molstat.n_psg14;
11138
  tmp_molstat.n_psg15 = molstat.n_psg15;
11139
  tmp_molstat.n_psg16 = molstat.n_psg16;
11140
  tmp_molstat.n_psg17 = molstat.n_psg17;
11141
  tmp_molstat.n_psg18 = molstat.n_psg18;
11142
  tmp_molstat.n_pstm = molstat.n_pstm;
11143
  tmp_molstat.n_psla = molstat.n_psla;
11144
  $ENDIF*/
11145
  /* make sure some modes can be switched on only by the query file */
11146
  /* and not by subsequent haystack file(s) */
11147
  if (ez_flag)   /* new in v0.3f */
11148
    ez_search = true;
11149
  if (chir_flag)   /* new in v0.3f */
11150
    rs_search = true;
11151
}
11152
#endif
11153
 
11154
static void
11155
copy_tmp_to_mol ()
11156
{
11157
  //int i, j, FORLIM;
11158
 
11159
  /*if (n_atoms == 0)
11160
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
11161
 
11162
 
11163
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
11164
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
11165
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
11166
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
11167
 
11168
 
11169
  n_atoms = tmp_n_atoms;
11170
  n_bonds = tmp_n_bonds;
11171
  n_rings = tmp_n_rings;
11172
  n_heavyatoms = tmp_n_heavyatoms;
11173
  n_heavybonds = tmp_n_heavybonds;
11174
  strcpy (molname, tmp_molname);
11175
  n_Ctot = tmp_n_Ctot;
11176
  n_Otot = tmp_n_Otot;
11177
  n_Ntot = tmp_n_Ntot;
11178
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
11179
 
11180
  if (tmp_n_bonds > 0)
11181
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
11182
 
11183
  if (tmp_n_rings > 0)
11184
    {
11185
      memcpy (ring, tmp_ring, sizeof (ringlist));
11186
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
11187
    }
11188
 
11189
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
11190
 
11191
 
11192
  // make sure some modes can be switched on only by the query file 
11193
  // and not by subsequent haystack file(s) 
11194
  if (ez_flag)                  // new in v0.3f 
11195
    ez_search = true;
11196
 
11197
  if (chir_flag)                // new in v0.3f 
11198
    rs_search = true;
11199
 
11200
}
11201
 
11202
#if 0
11203
static void copy_tmp_to_mol()
11204
{
11205
  int i, j, FORLIM;
11206
 
11207
  if (tmp_n_atoms == 0)
11208
    return;
11209
  n_atoms = tmp_n_atoms;
11210
  n_bonds = tmp_n_bonds;
11211
  n_rings = tmp_n_rings;
11212
  n_heavyatoms = tmp_n_heavyatoms;
11213
  n_heavybonds = tmp_n_heavybonds;
11214
  strcpy(molname, tmp_molname);
11215
  n_Ctot = tmp_n_Ctot;
11216
  n_Otot = tmp_n_Otot;
11217
  n_Ntot = tmp_n_Ntot;
11218
  /* try */
11219
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
11220
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
11221
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
11222
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
11223
  FORLIM = tmp_n_atoms;
11224
  /* except*/
11225
    on e:Eoutofmemory do
11226
      begin
11227
        writeln('Not enough memory');
11228
        halt(4);
11229
      end;
11230
  end;
11231
  for (i = 0; i < FORLIM; i++) {
11232
    strcpy(atom[i].element, tmp_atom[i].element);
11233
    strcpy(atom[i].atype, tmp_atom[i].atype);
11234
    atom[i].x = tmp_atom[i].x;
11235
    atom[i].y = tmp_atom[i].y;
11236
    atom[i].z = tmp_atom[i].z;
11237
    atom[i].formal_charge = tmp_atom[i].formal_charge;
11238
    atom[i].real_charge = tmp_atom[i].real_charge;
11239
    atom[i].Hexp = tmp_atom[i].Hexp;
11240
    atom[i].Htot = tmp_atom[i].Htot;
11241
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
11242
    atom[i].ring_count = tmp_atom[i].ring_count;
11243
    atom[i].arom = tmp_atom[i].arom;
11244
    atom[i].stereo_care = tmp_atom[i].stereo_care;
11245
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
11246
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
11247
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
11248
  }
11249
  if (tmp_n_bonds > 0) {
11250
    FORLIM = tmp_n_bonds;
11251
    for (i = 0; i < FORLIM; i++) {
11252
      bond[i].a1 = tmp_bond[i].a1;
11253
      bond[i].a2 = tmp_bond[i].a2;
11254
      bond[i].btype = tmp_bond[i].btype;
11255
      bond[i].arom = tmp_bond[i].arom;
11256
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
11257
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
11258
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
11259
    }
11260
  }
11261
  if (tmp_n_rings > 0) {
11262
    FORLIM = tmp_n_rings;
11263
    for (i = 0; i < FORLIM; i++) {
11264
      for (j = 0; j < max_ringsize; j++)
11265
        ring[i][j] = tmp_ring[i][j];
11266
    }
11267
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
11268
      ringprop[i].size = tmp_ringprop[i].size;
11269
      ringprop[i].arom = tmp_ringprop[i].arom;
11270
      ringprop[i].envelope = tmp_ringprop[i].envelope;
11271
    }
11272
  }
11273
  molstat.n_QA = tmp_molstat.n_QA;
11274
  molstat.n_QB = tmp_molstat.n_QB;
11275
  molstat.n_chg = tmp_molstat.n_chg;
11276
  molstat.n_C1 = tmp_molstat.n_C1;
11277
  molstat.n_C2 = tmp_molstat.n_C2;
11278
  molstat.n_C = tmp_molstat.n_C;
11279
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
11280
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
11281
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
11282
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
11283
  molstat.n_O2 = tmp_molstat.n_O2;
11284
  molstat.n_O3 = tmp_molstat.n_O3;
11285
  molstat.n_N1 = tmp_molstat.n_N1;
11286
  molstat.n_N2 = tmp_molstat.n_N2;
11287
  molstat.n_N3 = tmp_molstat.n_N3;
11288
  molstat.n_S = tmp_molstat.n_S;
11289
  molstat.n_SeTe = tmp_molstat.n_SeTe;
11290
  molstat.n_F = tmp_molstat.n_F;
11291
  molstat.n_Cl = tmp_molstat.n_Cl;
11292
  molstat.n_Br = tmp_molstat.n_Br;
11293
  molstat.n_I = tmp_molstat.n_I;
11294
  molstat.n_P = tmp_molstat.n_P;
11295
  molstat.n_B = tmp_molstat.n_B;
11296
  molstat.n_Met = tmp_molstat.n_Met;
11297
  molstat.n_X = tmp_molstat.n_X;
11298
  molstat.n_b1 = tmp_molstat.n_b1;
11299
  molstat.n_b2 = tmp_molstat.n_b2;
11300
  molstat.n_b3 = tmp_molstat.n_b3;
11301
  molstat.n_bar = tmp_molstat.n_bar;
11302
  molstat.n_C1O = tmp_molstat.n_C1O;
11303
  molstat.n_C2O = tmp_molstat.n_C2O;
11304
  molstat.n_CN = tmp_molstat.n_CN;
11305
  molstat.n_XY = tmp_molstat.n_XY;
11306
  molstat.n_r3 = tmp_molstat.n_r3;
11307
  molstat.n_r4 = tmp_molstat.n_r4;
11308
  molstat.n_r5 = tmp_molstat.n_r5;
11309
  molstat.n_r6 = tmp_molstat.n_r6;
11310
  molstat.n_r7 = tmp_molstat.n_r7;
11311
  molstat.n_r8 = tmp_molstat.n_r8;
11312
  molstat.n_r9 = tmp_molstat.n_r9;
11313
  molstat.n_r10 = tmp_molstat.n_r10;
11314
  molstat.n_r11 = tmp_molstat.n_r11;
11315
  molstat.n_r12 = tmp_molstat.n_r12;
11316
  molstat.n_r13p = tmp_molstat.n_r13p;
11317
  molstat.n_rN = tmp_molstat.n_rN;
11318
  molstat.n_rN1 = tmp_molstat.n_rN1;
11319
  molstat.n_rN2 = tmp_molstat.n_rN2;
11320
  molstat.n_rN3p = tmp_molstat.n_rN3p;
11321
  molstat.n_rO = tmp_molstat.n_rO;
11322
  molstat.n_rO1 = tmp_molstat.n_rO1;
11323
  molstat.n_rO2p = tmp_molstat.n_rO2p;
11324
  molstat.n_rS = tmp_molstat.n_rS;
11325
  molstat.n_rX = tmp_molstat.n_rX;
11326
  molstat.n_rAr = tmp_molstat.n_rAr;
11327
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
11328
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
11329
/* p2c: checkmol.pas, line 8169:
11330
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11331
  /*$IFDEF extended_molstat
11332
     molstat.n_psg01 = tmp_molstat.n_psg01;
11333
     molstat.n_psg02 = tmp_molstat.n_psg02;
11334
     molstat.n_psg13 = tmp_molstat.n_psg13;
11335
     molstat.n_psg14 = tmp_molstat.n_psg14;
11336
     molstat.n_psg15 = tmp_molstat.n_psg15;
11337
     molstat.n_psg16 = tmp_molstat.n_psg16;
11338
     molstat.n_psg17 = tmp_molstat.n_psg17;
11339
     molstat.n_psg18 = tmp_molstat.n_psg18;
11340
     molstat.n_pstm = tmp_molstat.n_pstm;
11341
     molstat.n_psla = tmp_molstat.n_psla;
11342
     $ENDIF */
11343
  /* make sure some modes can be switched on only by the query file */
11344
  /* and not by subsequent haystack file(s) */
11345
     if (ez_flag)
11346
     ez_search = true;
11347
     if (chir_flag)
11348
     rs_search = true;
11349
     }
11350
#endif
11351
 
11352
 
11353
 
11354
 
11355
 
11356
static void
11357
get_ringstat (r_id)
11358
     int r_id;
11359
{
11360
  int i, j;
11361
  ringpath_type testring;
11362
  int ring_size, a_ref;
11363
  str2 elem;
11364
  int nN = 0, nO = 0, nS = 0, nX = 0;
11365
 
11366
  if (r_id < 1 || r_id > n_rings)
11367
    return;
11368
  memset (testring, 0, sizeof (ringpath_type));
11369
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
11370
  for (j = 0; j < ring_size; j++)       /* v0.3j */
11371
    testring[j] = ring[r_id - 1][j];
11372
/* p2c: checkmol.pas, line 8238:
11373
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11374
#ifdef reduced_SAR
11375
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != false)
11376
    /* v0.3n: ignore envelope rings */
11377
    return;
11378
#else
11379
  if (ring_size <= 2)
11380
    return;
11381
#endif
11382
  for (i = 0; i < ring_size; i++)
11383
    {
11384
      a_ref = testring[i];
11385
      strcpy (elem, atom[a_ref - 1].element);
11386
      if (strcmp (elem, "C ") && strcmp (elem, "A "))
11387
        {
11388
          nX++;                 /* general heteroatom count */
11389
          if (!strcmp (elem, "N "))
11390
            nN++;
11391
          if (!strcmp (elem, "O "))
11392
            nO++;
11393
          if (!strcmp (elem, "S "))
11394
            nS++;
11395
        }
11396
    }
11397
  if (nN > 0)
11398
    {
11399
      molstat.n_rN++;
11400
      if (nN == 1)
11401
        molstat.n_rN1++;
11402
      if (nN == 2)
11403
        molstat.n_rN2++;
11404
      if (nN > 2)
11405
        molstat.n_rN3p++;
11406
    }
11407
  if (nO > 0)
11408
    {
11409
      molstat.n_rO++;
11410
      if (nO == 1)
11411
        molstat.n_rO1++;
11412
      if (nO == 2)
11413
        molstat.n_rO2p++;
11414
    }
11415
  if (nS > 0)
11416
    molstat.n_rS++;
11417
  if (nX > 0)
11418
    molstat.n_rX++;
11419
  /* general ringsize descriptors; v0.3m */
11420
  switch (ring_size)
11421
    {
11422
 
11423
    case 3:
11424
      molstat.n_r3++;
11425
      break;
11426
 
11427
    case 4:
11428
      molstat.n_r4++;
11429
      break;
11430
 
11431
    case 5:
11432
      molstat.n_r5++;
11433
      break;
11434
 
11435
    case 6:
11436
      molstat.n_r6++;
11437
      break;
11438
 
11439
    case 7:
11440
      molstat.n_r7++;
11441
      break;
11442
 
11443
    case 8:
11444
      molstat.n_r8++;
11445
      break;
11446
 
11447
    case 9:
11448
      molstat.n_r9++;
11449
      break;
11450
 
11451
    case 10:
11452
      molstat.n_r10++;
11453
      break;
11454
 
11455
    case 11:
11456
      molstat.n_r11++;
11457
      break;
11458
 
11459
    case 12:
11460
      molstat.n_r12++;
11461
      break;
11462
 
11463
    default:
11464
      molstat.n_r13p++;
11465
      break;
11466
    }                           /* end v0.3m        */
11467
}
11468
 
11469
 
11470
static void
11471
get_molstat ()
11472
{
11473
  int i;
11474
  str2 elem;
11475
  str3 atype;
11476
  int a1, a2;
11477
  str2 a1el, a2el;
11478
  char btype;
11479
  int hbc;
11480
  int n_b2formal = 0;           /* new in v0.2e */
11481
  int FORLIM;
11482
 
11483
  if (n_atoms == 0)
11484
    return;
11485
  FORLIM = n_atoms;
11486
  for (i = 0; i < FORLIM; i++)
11487
    {
11488
      if (atom[i].heavy)
11489
        {
11490
          strcpy (elem, atom[i].element);
11491
          strcpy (atype, atom[i].atype);
11492
          if (!strcmp (atype, "C1 "))
11493
            molstat.n_C1++;
11494
          if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
11495
            molstat.n_C2++;
11496
          if (!strcmp (elem, "C "))
11497
            molstat.n_C++;
11498
          if (!strcmp (atype, "O2 "))
11499
            molstat.n_O2++;
11500
          if (!strcmp (atype, "O3 "))
11501
            molstat.n_O3++;
11502
          if (!strcmp (atype, "N1 "))
11503
            molstat.n_N1++;
11504
          if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
11505
              (!strcmp (atype, "NAM") && atom[i].arom == true))
11506
            /* v0.3n */
11507
            molstat.n_N2++;
11508
          if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
11509
              !strcmp (atype, "N3+") ||
11510
              (!strcmp (atype, "NAM") && atom[i].arom == false))
11511
            /* v0.3n */
11512
            molstat.n_N3++;
11513
          if (!strcmp (elem, "A "))     /* query atom */
11514
            molstat.n_QA++;
11515
          if (!strcmp (elem, "Q "))     /* query atom */
11516
            molstat.n_QA++;
11517
          if (!strcmp (elem, "X "))     /* query atom */
11518
            molstat.n_QA++;
11519
          if (!strcmp (elem, "S "))
11520
            molstat.n_S++;
11521
          if (!strcmp (elem, "SE"))
11522
            molstat.n_SeTe++;
11523
          if (!strcmp (elem, "TE"))
11524
            molstat.n_SeTe++;
11525
          if (!strcmp (elem, "F "))
11526
            molstat.n_F++;
11527
          if (!strcmp (elem, "CL"))
11528
            molstat.n_Cl++;
11529
          if (!strcmp (elem, "BR"))
11530
            molstat.n_Br++;
11531
          if (!strcmp (elem, "I "))
11532
            molstat.n_I++;
11533
          if (!strcmp (elem, "P "))
11534
            molstat.n_P++;
11535
          if (!strcmp (elem, "B "))
11536
            molstat.n_B++;
11537
          /* check for known metals */
11538
          if (atom[i].metal)    /* v0.3l */
11539
            molstat.n_Met++;
11540
          /* still missing: unknown elements */
11541
 
11542
          /* check number of heteroatom bonds per C atom */
11543
          if (!strcmp (elem, "C "))
11544
            {
11545
              hbc = raw_hetbond_count (i + 1);
11546
              /* new in v0.2j (replaces hetbond_count) */
11547
              if (hbc >= 1)
11548
                molstat.n_CHB1p++;
11549
              if (hbc >= 2)
11550
                molstat.n_CHB2p++;
11551
              if (hbc >= 3)
11552
                molstat.n_CHB3p++;
11553
              if (hbc == 4)
11554
                molstat.n_CHB4++;
11555
            }
11556
          if (atom[i].formal_charge != 0)
11557
            {
11558
              molstat.n_chg++;
11559
              //n_charges++;
11560
            }
11561
          if (atom[i].nucleon_number != 0)
11562
            {
11563
              molstat.n_iso++;
11564
            }
11565
          if (atom[i].radical_type != 0)
11566
            {
11567
              molstat.n_rad++;
11568
            }
11569
          /* check for "other" elements;  v0.3l */
11570
          if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
11571
              && strcmp (elem, "O ") && strcmp (elem, "S ")
11572
              && strcmp (elem, "SE") && strcmp (elem, "TE")
11573
              && strcmp (elem, "P ") && strcmp (elem, "B ")
11574
              && strcmp (elem, "A ") && strcmp (elem, "Q "))
11575
            molstat.n_X++;
11576
          /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
11577
/* p2c: checkmol.pas, line 8353:
11578
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11579
          /*$IFDEF extended_molstat */
11580
          if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
11581
              || !strcmp (elem, "K ") || !strcmp (elem, "RB")
11582
              || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
11583
            molstat.n_psg01++;
11584
          if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
11585
              || !strcmp (elem, "CA") || !strcmp (elem, "SR")
11586
              || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
11587
            molstat.n_psg02++;
11588
          if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
11589
              || !strcmp (elem, "GA") || !strcmp (elem, "IN")
11590
              || !strcmp (elem, "TL"))
11591
            molstat.n_psg13++;
11592
          if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
11593
              || !strcmp (elem, "GE") || !strcmp (elem, "SN")
11594
              || !strcmp (elem, "PB"))
11595
            molstat.n_psg14++;
11596
          if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
11597
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
11598
              || !strcmp (elem, "BI"))
11599
            molstat.n_psg15++;
11600
          if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
11601
              || !strcmp (elem, "SE") || !strcmp (elem, "TE")
11602
              || !strcmp (elem, "PO"))
11603
            molstat.n_psg16++;
11604
          if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
11605
              || !strcmp (elem, "BR") || !strcmp (elem, "I ")
11606
              || !strcmp (elem, "AT"))
11607
            molstat.n_psg17++;
11608
          if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
11609
              || !strcmp (elem, "AR") || !strcmp (elem, "KR")
11610
              || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
11611
            molstat.n_psg18++;
11612
          if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
11613
              || !strcmp (elem, "LU") || !strcmp (elem, "LR")
11614
              || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
11615
              || !strcmp (elem, "HF") || !strcmp (elem, "RF")
11616
              || !strcmp (elem, "V ") || !strcmp (elem, "NB")
11617
              || !strcmp (elem, "TA") || !strcmp (elem, "DB")
11618
              || !strcmp (elem, "CR") || !strcmp (elem, "MO")
11619
              || !strcmp (elem, "W ") || !strcmp (elem, "SG")
11620
              || !strcmp (elem, "MN") || !strcmp (elem, "TC")
11621
              || !strcmp (elem, "RE") || !strcmp (elem, "BH")
11622
              || !strcmp (elem, "FE") || !strcmp (elem, "RU")
11623
              || !strcmp (elem, "OS") || !strcmp (elem, "HS")
11624
              || !strcmp (elem, "CO") || !strcmp (elem, "RH")
11625
              || !strcmp (elem, "IR") || !strcmp (elem, "MT")
11626
              || !strcmp (elem, "NI") || !strcmp (elem, "PD")
11627
              || !strcmp (elem, "PT") || !strcmp (elem, "DS")
11628
              || !strcmp (elem, "CU") || !strcmp (elem, "AG")
11629
              || !strcmp (elem, "AU") || !strcmp (elem, "RG")
11630
              || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
11631
              || !strcmp (elem, "HG"))
11632
/* p2c: checkmol.pas, line 8439:
11633
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
11634
            molstat.n_pstm++;
11635
          if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
11636
              || !strcmp (elem, "PR") || !strcmp (elem, "ND")
11637
              || !strcmp (elem, "PM") || !strcmp (elem, "SM")
11638
              || !strcmp (elem, "EU") || !strcmp (elem, "GD")
11639
              || !strcmp (elem, "TB") || !strcmp (elem, "DY")
11640
              || !strcmp (elem, "HO") || !strcmp (elem, "ER")
11641
              || !strcmp (elem, "TM") || !strcmp (elem, "YB")
11642
              || !strcmp (elem, "AC") || !strcmp (elem, "TH")
11643
              || !strcmp (elem, "PA") || !strcmp (elem, "U ")
11644
              || !strcmp (elem, "NP") || !strcmp (elem, "PU")
11645
              || !strcmp (elem, "AM") || !strcmp (elem, "CM")
11646
              || !strcmp (elem, "BK") || !strcmp (elem, "CF")
11647
              || !strcmp (elem, "ES") || !strcmp (elem, "FM")
11648
              || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
11649
/* p2c: checkmol.pas, line 8439:
11650
 * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
11651
            molstat.n_psla++;
11652
          /*$ENDIF */
11653
        }                       /* is heavy */
11654
    }                           /* atoms */
11655
  if (n_bonds > 0)
11656
    {
11657
      FORLIM = n_bonds;
11658
      for (i = 0; i < FORLIM; i++)
11659
        {
11660
          a1 = bond[i].a1;
11661
          a2 = bond[i].a2;
11662
          strcpy (a1el, atom[a1 - 1].element);
11663
          strcpy (a2el, atom[a2 - 1].element);
11664
          btype = bond[i].btype;
11665
          if (bond[i].arom)
11666
            molstat.n_bar++;
11667
          else
11668
            {
11669
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
11670
                molstat.n_b1++;
11671
              if (btype == 'D')
11672
                molstat.n_b2++;
11673
              if (btype == 'T')
11674
                molstat.n_b3++;
11675
            }
11676
          /* v0.3n: ignore bonds to (explicit) hydrogens */
11677
          if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
11678
              (!strcmp (a1el, "O ") && !strcmp (a2el, "C ")))
11679
            {
11680
              if (btype == 'S')
11681
                molstat.n_C1O++;
11682
              if (btype == 'D')
11683
                molstat.n_C2O++;
11684
            }
11685
          if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
11686
              (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
11687
            molstat.n_CN++;
11688
          if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
11689
              && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
11690
            molstat.n_XY++;
11691
          /* new in v0.3n: number of bonds belonging to more than one ring */
11692
          if (bond[i].ring_count > 1)
11693
            molstat.n_br2p++;
11694
        }
11695
    }                           /* bonds */
11696
  if (n_rings <= 0)
11697
    {
11698
      return;
11699
    }                           /* rings */
11700
  /* v0.3n */
11701
  n_countablerings = 0;         /* v0.3n */
11702
  FORLIM = n_rings;
11703
  for (i = 1; i <= FORLIM; i++)
11704
    {
11705
      if (ringprop[i - 1].envelope == false)    /* v0.3n */
11706
        n_countablerings++;
11707
      if (is_arene (i) && ringprop[i - 1].envelope == false)
11708
        {                       /* v0.3n: ignore envelope rings */
11709
          molstat.n_rAr++;
11710
          if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == false))
11711
            /* v0.3l */
11712
            molstat.n_rBz++;
11713
        }
11714
      get_ringstat (i);
11715
      if (ringprop[i - 1].arom == true && ringprop[i - 1].envelope == false)
11716
        /* new in v0.3n; replaces assignment below */
11717
        n_b2formal++;
11718
    }
11719
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
11720
  /* in order to allow an isolated double bond in the needle */
11721
  /* to be matched as a ring fragment of an aromatic ring */
11722
  if (n_b2formal > molstat.n_bar / 2)
11723
    n_b2formal = molstat.n_bar / 2;
11724
  molstat.n_b2 += n_b2formal;
11725
}
11726
 
11727
 
11728
static void
11729
fix_ssr_ringcounts ()
11730
{
11731
  /* new in v0.3n */
11732
  /* if SAR -> SSR fallback happens, set some molstat values */
11733
  /* to a maximum (ring counts for various ring sizes); */
11734
  /* this should be necessary only for ring sizes which */
11735
  /* are a) too large for the SSR (depending on ssr_vringsize) */
11736
  /* and b) which are likely to contain "envelope rings" */
11737
  /* (size 6 and above) */
11738
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
11739
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
11740
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
11741
  if (molstat.n_r6 == 0)
11742
    molstat.n_r6 = max_rings;
11743
  if (molstat.n_r7 == 0)
11744
    molstat.n_r7 = max_rings;
11745
  if (molstat.n_r8 == 0)
11746
    molstat.n_r8 = max_rings;
11747
  if (molstat.n_r9 == 0)
11748
    molstat.n_r9 = max_rings;
11749
  if (molstat.n_r10 == 0)
11750
    molstat.n_r10 = max_rings;
11751
  if (molstat.n_r11 == 0)
11752
    molstat.n_r11 = max_rings;
11753
  if (molstat.n_r12 == 0)
11754
    molstat.n_r12 = max_rings;
11755
  if (molstat.n_r13p == 0)
11756
    molstat.n_r13p = max_rings;
11757
}
11758
 
11759
 
11760
 
11761
static void
11762
write_molstat ()
11763
{
11764
  if (auto_ssr)                 /* v0.3n */
11765
    fix_ssr_ringcounts ();
11766
  printf ("n_atoms:%d;", n_heavyatoms);
11767
  /* count only non-H atoms (some molfiles contain explicit H's) */
11768
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
11769
    printf ("n_bonds:%d;", n_heavybonds);
11770
/* p2c: checkmol.pas, line 8471:
11771
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11772
#ifdef REDUCED_SAR
11773
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
11774
    printf ("n_rings:%d;", n_countablerings);
11775
#else
11776
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
11777
    printf ("n_rings:%d;", n_rings);
11778
#endif
11779
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
11780
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
11781
  if (molstat.n_chg > 0)        /* 0.3x */
11782
    printf ("n_chg:%d;", molstat.n_chg);
11783
 
11784
  if (molstat.n_C1 > 0)
11785
    printf ("n_C1:%d;", molstat.n_C1);
11786
  if (molstat.n_C2 > 0)
11787
    printf ("n_C2:%d;", molstat.n_C2);
11788
  /* requirement of a given number of sp3 carbons might be too restrictive, */
11789
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
11790
  if (molstat.n_C > 0)
11791
    printf ("n_C:%d;", molstat.n_C);
11792
  if (molstat.n_CHB1p > 0)
11793
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
11794
  if (molstat.n_CHB2p > 0)
11795
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
11796
  if (molstat.n_CHB3p > 0)
11797
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
11798
  if (molstat.n_CHB4 > 0)
11799
    printf ("n_CHB4:%d;", molstat.n_CHB4);
11800
  if (molstat.n_O2 > 0)
11801
    printf ("n_O2:%d;", molstat.n_O2);
11802
  if (molstat.n_O3 > 0)
11803
    printf ("n_O3:%d;", molstat.n_O3);
11804
  if (molstat.n_N1 > 0)
11805
    printf ("n_N1:%d;", molstat.n_N1);
11806
  if (molstat.n_N2 > 0)
11807
    printf ("n_N2:%d;", molstat.n_N2);
11808
  if (molstat.n_N3 > 0)
11809
    printf ("n_N3:%d;", molstat.n_N3);
11810
  if (molstat.n_S > 0)
11811
    printf ("n_S:%d;", molstat.n_S);
11812
  if (molstat.n_SeTe > 0)
11813
    printf ("n_SeTe:%d;", molstat.n_SeTe);
11814
  if (molstat.n_F > 0)
11815
    printf ("n_F:%d;", molstat.n_F);
11816
  if (molstat.n_Cl > 0)
11817
    printf ("n_Cl:%d;", molstat.n_Cl);
11818
  if (molstat.n_Br > 0)
11819
    printf ("n_Br:%d;", molstat.n_Br);
11820
  if (molstat.n_I > 0)
11821
    printf ("n_I:%d;", molstat.n_I);
11822
  if (molstat.n_P > 0)
11823
    printf ("n_P:%d;", molstat.n_P);
11824
  if (molstat.n_B > 0)
11825
    printf ("n_B:%d;", molstat.n_B);
11826
  if (molstat.n_Met > 0)
11827
    printf ("n_Met:%d;", molstat.n_Met);
11828
  if (molstat.n_X > 0)
11829
    printf ("n_X:%d;", molstat.n_X);
11830
  if (molstat.n_b1 > 0)
11831
    printf ("n_b1:%d;", molstat.n_b1);
11832
  if (molstat.n_b2 > 0)
11833
    printf ("n_b2:%d;", molstat.n_b2);
11834
  if (molstat.n_b3 > 0)
11835
    printf ("n_b3:%d;", molstat.n_b3);
11836
  if (molstat.n_bar > 0)
11837
    printf ("n_bar:%d;", molstat.n_bar);
11838
  if (molstat.n_C1O > 0)
11839
    printf ("n_C1O:%d;", molstat.n_C1O);
11840
  if (molstat.n_C2O > 0)
11841
    printf ("n_C2O:%d;", molstat.n_C2O);
11842
  if (molstat.n_CN > 0)
11843
    printf ("n_CN:%d;", molstat.n_CN);
11844
  if (molstat.n_XY > 0)
11845
    printf ("n_XY:%d;", molstat.n_XY);
11846
  if (molstat.n_r3 > 0)
11847
    printf ("n_r3:%d;", molstat.n_r3);
11848
  if (molstat.n_r4 > 0)
11849
    printf ("n_r4:%d;", molstat.n_r4);
11850
  if (molstat.n_r5 > 0)
11851
    printf ("n_r5:%d;", molstat.n_r5);
11852
  if (molstat.n_r6 > 0)
11853
    printf ("n_r6:%d;", molstat.n_r6);
11854
  if (molstat.n_r7 > 0)
11855
    printf ("n_r7:%d;", molstat.n_r7);
11856
  if (molstat.n_r8 > 0)
11857
    printf ("n_r8:%d;", molstat.n_r8);
11858
  if (molstat.n_r9 > 0)
11859
    printf ("n_r9:%d;", molstat.n_r9);
11860
  if (molstat.n_r10 > 0)
11861
    printf ("n_r10:%d;", molstat.n_r10);
11862
  if (molstat.n_r11 > 0)
11863
    printf ("n_r11:%d;", molstat.n_r11);
11864
  if (molstat.n_r12 > 0)
11865
    printf ("n_r12:%d;", molstat.n_r12);
11866
  if (molstat.n_r13p > 0)
11867
    printf ("n_r13p:%d;", molstat.n_r13p);
11868
  if (molstat.n_rN > 0)
11869
    printf ("n_rN:%d;", molstat.n_rN);
11870
  if (molstat.n_rN1 > 0)
11871
    printf ("n_rN1:%d;", molstat.n_rN1);
11872
  if (molstat.n_rN2 > 0)
11873
    printf ("n_rN2:%d;", molstat.n_rN2);
11874
  if (molstat.n_rN3p > 0)
11875
    printf ("n_rN3p:%d;", molstat.n_rN3p);
11876
  if (molstat.n_rO > 0)
11877
    printf ("n_rO:%d;", molstat.n_rO);
11878
  if (molstat.n_rO1 > 0)
11879
    printf ("n_rO1:%d;", molstat.n_rO1);
11880
  if (molstat.n_rO2p > 0)
11881
    printf ("n_rO2p:%d;", molstat.n_rO2p);
11882
  if (molstat.n_rS > 0)
11883
    printf ("n_rS:%d;", molstat.n_rS);
11884
  if (molstat.n_rX > 0)
11885
    printf ("n_rX:%d;", molstat.n_rX);
11886
  if (molstat.n_rAr > 0)
11887
    printf ("n_rar:%d;", molstat.n_rAr);
11888
/* p2c: checkmol.pas, line 8532:
11889
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11890
  /*$IFDEF extended_molstat */
11891
  if (molstat.n_rBz > 0)
11892
    printf ("n_rbz:%d;", molstat.n_rBz);
11893
  if (molstat.n_br2p > 0)
11894
    printf ("n_br2p:%d;", molstat.n_br2p);
11895
  if (molstat.n_psg01 > 0)
11896
    printf ("n_psg01:%d;", molstat.n_psg01);
11897
  if (molstat.n_psg02 > 0)
11898
    printf ("n_psg02:%d;", molstat.n_psg02);
11899
  if (molstat.n_psg13 > 0)
11900
    printf ("n_psg13:%d;", molstat.n_psg13);
11901
  if (molstat.n_psg14 > 0)
11902
    printf ("n_psg14:%d;", molstat.n_psg14);
11903
  if (molstat.n_psg15 > 0)
11904
    printf ("n_psg15:%d;", molstat.n_psg15);
11905
  if (molstat.n_psg16 > 0)
11906
    printf ("n_psg16:%d;", molstat.n_psg16);
11907
  if (molstat.n_psg17 > 0)
11908
    printf ("n_psg17:%d;", molstat.n_psg17);
11909
  if (molstat.n_psg18 > 0)
11910
    printf ("n_psg18:%d;", molstat.n_psg18);
11911
  if (molstat.n_pstm > 0)
11912
    printf ("n_pstm:%d;", molstat.n_pstm);
11913
  if (molstat.n_psla > 0)
11914
    printf ("n_psla:%d;", molstat.n_psla);
11915
  if (molstat.n_iso > 0)
11916
    printf ("n_iso:%d;", molstat.n_iso);
11917
  if (molstat.n_rad > 0)
11918
    printf ("n_rad:%d;", molstat.n_rad);
11919
  /*$ENDIF */
11920
  putchar ('\n');
11921
}
11922
 
11923
 
11924
static void
11925
write_molstat_X ()
11926
{
11927
  if (auto_ssr)                 /* v0.3n */
11928
    fix_ssr_ringcounts ();
11929
/* p2c: checkmol.pas, line 8556:
11930
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11931
#ifdef REDUCED_SAR
11932
  printf ("%d,", n_heavyatoms);
11933
  printf ("%d,", n_heavybonds);
11934
  printf ("%d,", n_countablerings);
11935
  /* v0.3n: n_rings =?> n_countablerings */
11936
#else
11937
  printf ("%d,", n_heavyatoms);
11938
  printf ("%d,", n_heavybonds);
11939
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
11940
#endif
11941
  printf ("%d,", molstat.n_QA);
11942
  printf ("%d,", molstat.n_QB);
11943
 
11944
  /* 0.3x */
11945
  printf ("%d,", molstat.n_chg);
11946
 
11947
 
11948
  printf ("%d,", molstat.n_C1);
11949
  printf ("%d,", molstat.n_C2);
11950
  printf ("%d,", molstat.n_C);
11951
  printf ("%d,", molstat.n_CHB1p);
11952
  printf ("%d,", molstat.n_CHB2p);
11953
  printf ("%d,", molstat.n_CHB3p);
11954
  printf ("%d,", molstat.n_CHB4);
11955
  printf ("%d,", molstat.n_O2);
11956
  printf ("%d,", molstat.n_O3);
11957
  printf ("%d,", molstat.n_N1);
11958
  printf ("%d,", molstat.n_N2);
11959
  printf ("%d,", molstat.n_N3);
11960
  printf ("%d,", molstat.n_S);
11961
  printf ("%d,", molstat.n_SeTe);
11962
  printf ("%d,", molstat.n_F);
11963
  printf ("%d,", molstat.n_Cl);
11964
  printf ("%d,", molstat.n_Br);
11965
  printf ("%d,", molstat.n_I);
11966
  printf ("%d,", molstat.n_P);
11967
  printf ("%d,", molstat.n_B);
11968
  printf ("%d,", molstat.n_Met);
11969
  printf ("%d,", molstat.n_X);
11970
  printf ("%d,", molstat.n_b1);
11971
  printf ("%d,", molstat.n_b2);
11972
  printf ("%d,", molstat.n_b3);
11973
  printf ("%d,", molstat.n_bar);
11974
  printf ("%d,", molstat.n_C1O);
11975
  printf ("%d,", molstat.n_C2O);
11976
  printf ("%d,", molstat.n_CN);
11977
  printf ("%d,", molstat.n_XY);
11978
  printf ("%d,", molstat.n_r3);
11979
  printf ("%d,", molstat.n_r4);
11980
  printf ("%d,", molstat.n_r5);
11981
  printf ("%d,", molstat.n_r6);
11982
  printf ("%d,", molstat.n_r7);
11983
  printf ("%d,", molstat.n_r8);
11984
  printf ("%d,", molstat.n_r9);
11985
  printf ("%d,", molstat.n_r10);
11986
  printf ("%d,", molstat.n_r11);
11987
  printf ("%d,", molstat.n_r12);
11988
  printf ("%d,", molstat.n_r13p);
11989
  printf ("%d,", molstat.n_rN);
11990
  printf ("%d,", molstat.n_rN1);
11991
  printf ("%d,", molstat.n_rN2);
11992
  printf ("%d,", molstat.n_rN3p);
11993
  printf ("%d,", molstat.n_rO);
11994
  printf ("%d,", molstat.n_rO1);
11995
  printf ("%d,", molstat.n_rO2p);
11996
  printf ("%d,", molstat.n_rS);
11997
  printf ("%d,", molstat.n_rX);
11998
  printf ("%d", molstat.n_rAr);
11999
/* p2c: checkmol.pas, line 8579:
12000
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12001
  /*$IFDEF extended_molstat */
12002
  printf (",%d", molstat.n_rBz);
12003
  printf (",%d", molstat.n_br2p);
12004
  printf (",%d", molstat.n_psg01);
12005
  printf (",%d", molstat.n_psg02);
12006
  printf (",%d", molstat.n_psg13);
12007
  printf (",%d", molstat.n_psg14);
12008
  printf (",%d", molstat.n_psg15);
12009
  printf (",%d", molstat.n_psg16);
12010
  printf (",%d", molstat.n_psg17);
12011
  printf (",%d", molstat.n_psg18);
12012
  printf (",%d", molstat.n_pstm);
12013
  printf (",%d", molstat.n_psla);
12014
  printf (",%d", molstat.n_iso);
12015
  printf (",%d\n", molstat.n_rad);
12016
  /*$ENDIF */
12017
}
12018
 
12019
 
12020
/* routines for substructure matching */
12021
 
12022
 
12023
static int
12024
find_ndl_ref_atom ()
12025
{
6786 kbelabas 12026
  int i;
6785 bpr 12027
  int score = -1, index = 0;
12028
  int n_nb, n_hc, FORLIM;
12029
 
12030
  /* finds a characteristic atom in the needle molecule, */
12031
  /* i.e., one with as many substituents as possible and */
12032
  /* with as many heteroatom substitutents as possible; */
12033
  /* added in v0.2d: make sure that reference atom is a heavy atom */
12034
  /* and not (accidentally) an explicit hydrogen; */
12035
  /* new in v0.3d: special treatment in case of E/Z geometry search */
12036
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
12037
  /* matchpath, regardless where the recursive search starts; */
12038
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
12039
  /* added in v0.3o: needle atom must be "tagged" in order to be */
12040
  /* selected (prevents unconnected fragments from being overlooked) */
12041
  if (ndl_n_atoms == 0)
6786 kbelabas 12042
    return false;
6785 bpr 12043
  if (ez_search && ndl_n_heavyatoms > 2)
12044
    {
12045
      FORLIM = ndl_n_atoms;
12046
      for (i = 1; i <= FORLIM; i++)
12047
        {                       /* ignore sp2-carbons if not aromatic */
12048
          /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = true)) then */
12049
          if (ndl_alkene_C (i) == false && ndl_atom[i - 1].tag)
12050
            {                   /* v0.3o */
12051
              n_nb = ndl_atom[i - 1].neighbor_count;
12052
              n_hc = ndl_hetatom_count (i);
12053
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy)
12054
                {
12055
                  /* v0.3j */
12056
                  index = i;
12057
                  score = n_nb * 11 + n_hc * 7; /* changed in v0.3j */
12058
                }
12059
            }
12060
        }
12061
    }
12062
  /* it is possible that no suitable reference atom has been found here */
12063
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
12064
  if (index == 0)
12065
    {
12066
      ez_search = false;        /* just in case it was true */
12067
      opt_geom = false;         /* just in case it was true */
12068
      FORLIM = ndl_n_atoms;
12069
      for (i = 1; i <= FORLIM; i++)
12070
        {
12071
          n_nb = ndl_atom[i - 1].neighbor_count;
12072
          n_hc = ndl_hetatom_count (i);
12073
          if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
12074
              ndl_atom[i - 1].tag)
12075
            {                   /* v0.3j */
12076
              index = i;
12077
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
12078
            }
12079
          /* v0.3o */
12080
        }
12081
    }
12082
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
12083
  if (index == 0)               /* just to be sure... */
12084
    index++;
12085
  return index;
12086
}
12087
 
12088
 
12089
static void
12090
cv_init ()
12091
{
12092
  /* new in v0.3j */
12093
  int i;
12094
 
12095
  if (cv == NULL)
12096
    return;
12097
  memset (cv, 0, sizeof (connval_type));
12098
 
12099
  for (i = 0; i < ndl_n_atoms; i++)
12100
    cv[i].def = ndl_atom[i].neighbor_count;
12101
}
12102
 
12103
 
12104
static int
12105
cv_count ()
12106
{
12107
  /* new in v0.3j, modified in v0.3m */
12108
  int i, j;
12109
  int cvlist[max_atoms];
12110
  int cvdef;
12111
  boolean isnew;
12112
  int entries = 0;
12113
  int FORLIM;
12114
 
12115
  if (cv == NULL)
12116
    return 0;
12117
  memset (cvlist, 0, sizeof (int) * max_atoms);
12118
  FORLIM = ndl_n_atoms;
12119
  for (i = 0; i < FORLIM; i++)
12120
    {
12121
      if (ndl_atom[i].heavy == true)
12122
        {
12123
          cvdef = cv[i].def;
12124
          isnew = true;
12125
          if (entries > 0)
12126
            {
12127
              for (j = 0; j < entries; j++)
12128
                {
12129
                  if (cvlist[j] == cvdef)
12130
                    isnew = false;
12131
                }
12132
            }
12133
          if (isnew)
12134
            {
12135
              entries++;
12136
              cvlist[entries - 1] = cvdef;
12137
            }
12138
          /* now we have a list of unique connection values */
12139
        }
12140
    }
12141
  return entries;
12142
}
12143
 
12144
 
12145
static int
12146
cv_iterate (n_cv_prev)
12147
     int n_cv_prev;
12148
{
12149
  /* new in v0.3j, modified in v0.3m */
6788 kbelabas 12150
  int i, j;
6785 bpr 12151
  neighbor_rec nb;
12152
  int nnb, nsum, n_cv, FORLIM;
12153
 
12154
  if (cv == NULL || ndl_n_atoms == 0)
6788 kbelabas 12155
    return false;
6785 bpr 12156
  FORLIM = ndl_n_atoms;
12157
  /* update the connection values (Morgan algorithm) */
12158
 
12159
  memset (nb, 0, sizeof (neighbor_rec));
12160
 
12161
  for (i = 1; i <= FORLIM; i++)
12162
    {
12163
      if (ndl_atom[i - 1].heavy == true)
12164
        {
12165
          get_ndl_neighbors (nb, i);
12166
          nnb = ndl_atom[i - 1].neighbor_count;
12167
          nsum = 0;
12168
          if (nnb > 0)
12169
            {
12170
              for (j = 0; j < nnb; j++)
12171
                {
12172
                  if (ndl_atom[nb[j] - 1].heavy == true)
12173
                    nsum += cv[nb[j] - 1].def;
12174
                }
12175
            }
12176
          cv[i - 1].tmp = nsum;
12177
        }
12178
    }
12179
  n_cv = cv_count ();
12180
  if (n_cv > n_cv_prev)
12181
    {
12182
      FORLIM = ndl_n_atoms;
12183
      for (i = 0; i < FORLIM; i++)
12184
        cv[i].def = cv[i].tmp;
12185
    }
12186
  return n_cv;
12187
}
12188
 
12189
 
12190
static int
12191
find_ndl_ref_atom_cv ()
12192
{
12193
  /* new in v0.3j, modified in v0.3m */
12194
  int Result, i;
12195
  int res = 1, it = 0;
12196
  int n_cv;
12197
  int n_cv_prev = 0;
12198
  boolean finished = false;
12199
  int cvmax = 0;
12200
  int FORLIM;
12201
 
12202
  if (ndl_n_atoms == 0)
12203
    return 0;
12204
  /* try */
12205
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
12206
  /* except
12207
     on e:Eoutofmemory do
12208
     begin
12209
     res := find_ndl_ref_atom;
12210
     $IFDEF debug
12211
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
12212
     $ENDIF
12213
     end;
12214
     end; */
12215
  cv_init ();
12216
  do
12217
    {
12218
      it++;                     /* iteration counter (a safeguard against infinite loops) */
12219
      n_cv = cv_iterate (n_cv_prev);
12220
      if (n_cv <= n_cv_prev)
12221
        finished = true;
12222
      n_cv_prev = n_cv;
12223
    }
12224
  while (!(finished || it > 10000));
12225
  FORLIM = ndl_n_atoms;
12226
  /* now that we have canonical connection values (Morgan algorithm), */
12227
  /* pick the atom with the highest value */
12228
  /* added in v0.3o: atom must be "tagged" */
12229
  for (i = 1; i <= FORLIM; i++)
12230
    {
12231
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
12232
      if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == false ||
12233
                                       ez_search == false))
12234
          && ndl_atom[i - 1].tag)
12235
        {                       /* v0.3o */
12236
          cvmax = cv[i - 1].def;
12237
          res = i;
12238
        }
12239
    }
12240
  Result = res;
12241
  /* try */
12242
  if (cv != NULL)
12243
    {
12244
      free (cv);
12245
      cv = NULL;
12246
    }
12247
  /* except
12248
     on e:Einvalidpointer do begin end;
12249
     end; */
12250
  return Result;
12251
}
12252
 
12253
 
12254
static boolean
12255
atomtypes_OK_strict (ndl_a, hst_a)
12256
     int ndl_a, hst_a;
12257
{
12258
  /* new in v0.2f */
12259
  str2 ndl_el;
12260
  str3 ndl_atype;
12261
  str2 hst_el;
12262
  str3 hst_atype;
12263
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
12264
  boolean res = false;
12265
 
12266
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
12267
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
12268
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
12269
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
12270
  strcpy (hst_el, atom[hst_a - 1].element);
12271
  strcpy (hst_atype, atom[hst_a - 1].atype);
12272
  hst_nbc = atom[hst_a - 1].neighbor_count;
12273
  hst_Htot = atom[hst_a - 1].Htot;
12274
  /* v0.3o: formal charges must be the same */
12275
 
12276
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12277
    return false;
12278
 
12279
  /* v0.3x: isotope nucleon numbers must be the same */
12280
 
12281
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
12282
    return false;
12283
 
12284
  /* v0.3x: radicals must be the same */
12285
 
12286
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12287
    return false;
12288
 
12289
  if (!strcmp (ndl_atype, hst_atype))
12290
    res = true;
12291
  else
12292
    {
12293
      if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom &&
12294
          atom[hst_a - 1].arom)
12295
        res = true;
12296
      if (ndl_querymol
12297
          && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
12298
        res = true;             /* 0.3 p */
12299
    }
12300
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
12301
    res = true;
12302
  if (!strcmp (ndl_el, "Q "))
12303
    {
12304
      if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
12305
        res = true;
12306
    }
12307
  if (!strcmp (ndl_el, "X "))
12308
    {
12309
      if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
12310
          !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
12311
          || !strcmp (hst_el, "AT"))
12312
        res = true;
12313
    }
12314
  /* if needle atom has more substituents than haystack atom ==> no match */
12315
  if (ndl_nbc > hst_nbc)
12316
    res = false;
12317
  /* check for explicit hydrogens */
12318
  if (ndl_Hexp > hst_Htot)
12319
    res = false;
12320
/* p2c: checkmol.pas, line 8859:
12321
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12322
  /*$IFDEF debug */
12323
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
12324
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
12325
  /*$ENDIF */
12326
  /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
12327
  if (opt_fp)
12328
    {
12329
      if (strcmp (ndl_el, hst_el))
12330
        res = false;
12331
    }
12332
  return res;
12333
}
12334
 
12335
 
12336
static boolean
12337
atomtypes_OK (ndl_a, hst_a)
12338
     int ndl_a, hst_a;
12339
{
12340
  str2 ndl_el, hst_el;
12341
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
12342
  boolean res = false;
12343
 
12344
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
12345
    return false;
12346
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
12347
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
12348
  /* are tolerated (this is a feature, not a bug) */
12349
  if (opt_chg)
12350
    {
12351
      if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12352
        return false;
12353
    }
12354
//  else
12355
//    {
12356
//      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
12357
//        atom[hst_a - 1].formal_charge != 0 &&
12358
//        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
12359
//      return false;
12360
//    }
12361
//
12362
//  /* v0.3x: isotopes must be the same */
12363
  if (opt_iso)
12364
    {
12365
      if (ndl_atom[ndl_a - 1].nucleon_number !=
12366
          atom[hst_a - 1].nucleon_number)
12367
        return false;
12368
    }
12369
//  else
12370
//    {
12371
//      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
12372
//        atom[hst_a - 1].nucleon_number != 0 &&
12373
//        ndl_atom[ndl_a - 1].nucleon_number !=
12374
//        atom[hst_a - 1].nucleon_number)
12375
//      return false;
12376
//    }
12377
//
12378
//  /* v0.3x: radicals must be the same */
12379
  if (opt_rad)
12380
    {
12381
      if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12382
        return false;
12383
    }
12384
//  else
12385
//    {
12386
//      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
12387
//        atom[hst_a - 1].radical_type != 0 &&
12388
//        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
12389
//      return false;
12390
//    }
12391
 
12392
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
12393
  if (opt_exact && atom[hst_a - 1].tag == true)
12394
    {
12395
/* p2c: checkmol.pas, line 8899:
12396
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12397
      /*$IFDEF debug */
12398
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
12399
      /*$ENDIF */
12400
      return false;
12401
    }
12402
  if (opt_strict)               /* new in v0.2f */
12403
    return (atomtypes_OK_strict (ndl_a, hst_a));
12404
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
12405
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
12406
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
12407
  strcpy (hst_el, atom[hst_a - 1].element);
12408
  hst_nbc = atom[hst_a - 1].neighbor_count;
12409
  hst_Htot = atom[hst_a - 1].Htot;
12410
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
12411
    res = true;
12412
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
12413
    res = true;
12414
  if (!strcmp (ndl_el, "Q "))
12415
    {
12416
      if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
12417
        res = true;
12418
    }
12419
  if (!strcmp (ndl_el, "X "))
12420
    {
12421
      if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
12422
          !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
12423
          || !strcmp (hst_el, "AT"))
12424
        res = true;
12425
    }
12426
  /* v0.3o: in exact mode, check for identical neighbor_count */
12427
  if (opt_exact)
12428
    {
12429
      if (ndl_nbc != hst_nbc)
12430
        {
12431
          res = false;
12432
/* p2c: checkmol.pas, line 8934:
12433
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12434
          /*$IFDEF debug */
12435
          //debugoutput
12436
          //  ("exact match failed: different number of neighbor atoms");
12437
          /*$ENDIF */
12438
        }
12439
    }
12440
  /* if needle atom has more substituents than haystack atom ==> no match */
12441
  if (ndl_nbc > hst_nbc)
12442
    res = false;
12443
  /* check for explicit hydrogens */
12444
  if (ndl_Hexp > hst_Htot)
12445
    res = false;
12446
/* p2c: checkmol.pas, line 8943:
12447
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12448
  /*$IFDEF debug */
12449
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
12450
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
12451
  /*$ENDIF */
12452
  return res;
12453
}
12454
 
12455
 
12456
static boolean
12457
bondtypes_OK_strict (ndl_b, hst_b)
12458
     int ndl_b, hst_b;
12459
{
12460
  boolean ndl_arom, hst_arom;
12461
  char ndl_btype, hst_btype;
12462
  int ndl_rc;                   /* new in v0.3d */
12463
  int hst_rc;                   /* new in v0.3d */
12464
  int ndl_btopo;                /* new in v0.3d */
12465
  boolean res = false;
12466
/* p2c: checkmol.pas, line 8960:
12467
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12468
  /*$IFDEF debug */
12469
  /*char na[256]; char ha[256];*/
12470
  char tstr[256];
12471
 
12472
  /*$ENDIF */
12473
/* p2c: checkmol.pas, line 8966:
12474
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12475
  /*$IFDEF debug */
12476
  *tstr = '\0';                 /* for debugging purposes only */
12477
  /*$ENDIF */
12478
  ndl_arom = ndl_bond[ndl_b - 1].arom;
12479
  ndl_btype = ndl_bond[ndl_b - 1].btype;
12480
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
12481
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
12482
  hst_arom = bond[hst_b - 1].arom;
12483
  hst_btype = bond[hst_b - 1].btype;
12484
  hst_rc = bond[hst_b - 1].ring_count;
12485
/* p2c: checkmol.pas, line 8976:
12486
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12487
  /*$IFDEF debug */
12488
  /*if (ndl_arom)
12489
    strcpy (na, "(ar)");
12490
  else
12491
    *na = '\0';
12492
  if (hst_arom)
12493
    strcpy (ha, "(ar)");
12494
  else
12495
    *ha = '\0';*/
12496
  /*$ENDIF */
12497
  if (ndl_arom == true && hst_arom == true)
12498
    res = true;
12499
  if (ndl_arom == false && hst_arom == false)
12500
    {
12501
      if (ndl_btype == hst_btype)
12502
        res = true;
12503
      if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
12504
        res = true;
12505
      if (ndl_btype == 's' && hst_btype == 'S')
12506
        res = true;
12507
      if (ndl_btype == 'd' && hst_btype == 'D')
12508
        res = true;
12509
    }
12510
  /* a little exception: */
12511
  if (ndl_arom == false && hst_arom == true)
12512
    {
12513
      if (ndl_btype == 'A')
12514
        res = true;
12515
      if (ndl_btype == 's' || ndl_btype == 'd')
12516
        res = true;
12517
      if (ndl_bond[ndl_b - 1].q_arom)
12518
        res = true;             /* 0.3p */
12519
    }
12520
  if (ndl_btype == 'a')
12521
    res = true;
12522
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
12523
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc)
12524
    {
12525
      if (ndl_rc != hst_rc)
12526
        {
12527
          res = false;          /* this excludes further ring annulations as well as */
12528
/* p2c: checkmol.pas, line 9001:
12529
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12530
          /*$IFDEF debug */
12531
          /* open-chains query structures to be found in rings */
12532
          /*
12533
             tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
12534
          /*$ENDIF */
12535
        }
12536
    }
12537
  else
12538
    {
12539
      if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
12540
        {
12541
          res = false;
12542
/* p2c: checkmol.pas, line 9010:
12543
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12544
          /*$IFDEF debug */
12545
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
12546
          /*$ENDIF */
12547
        }
12548
    }
12549
/* p2c: checkmol.pas, line 9015:
12550
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12551
  /*$IFDEF debug */
12552
  /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
12553
     debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
12554
  /*$ENDIF */
12555
  return res;
12556
}
12557
 
12558
 
12559
static boolean
12560
bondtypes_OK (ndl_b, hst_b)
12561
     int ndl_b, hst_b;
12562
{
12563
  boolean ndl_arom, hst_arom;
12564
  char ndl_btype, hst_btype;
12565
  int ndl_rc;                   /* new in v0.3d */
12566
  int hst_rc;                   /* new in v0.3d */
12567
  int ndl_btopo;                /* new in v0.3d */
12568
  boolean res = false;
12569
/* p2c: checkmol.pas, line 9032:
12570
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12571
  /*$IFDEF debug */
12572
  /*char na[256], ha[256];*/
12573
  char tstr[256];
12574
  /*$ENDIF */
12575
  int a1, a2;
12576
  str2 a1_el, a2_el;
12577
 
12578
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
12579
    return false;
12580
  if (opt_strict)               /* new in v0.2f */
12581
    return (bondtypes_OK_strict (ndl_b, hst_b));
12582
/* p2c: checkmol.pas, line 9051:
12583
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12584
  /*$IFDEF debug */
12585
  *tstr = '\0';                 /* for debug purposes only */
12586
  /*$ENDIF */
12587
  ndl_arom = ndl_bond[ndl_b - 1].arom;
12588
  ndl_btype = ndl_bond[ndl_b - 1].btype;
12589
  hst_arom = bond[hst_b - 1].arom;
12590
  hst_btype = bond[hst_b - 1].btype;
12591
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
12592
  hst_rc = bond[hst_b - 1].ring_count;
12593
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
12594
/* p2c: checkmol.pas, line 9061:
12595
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12596
  /*$IFDEF debug */
12597
  //if (ndl_arom)
12598
//    strcpy (na, "(ar)");
12599
//  else
12600
//    *na = '\0';
12601
//  if (hst_arom)
12602
//    strcpy (ha, "(ar)");
12603
//  else
12604
//    *ha = '\0';
12605
  /*$ENDIF */
12606
  if (ndl_arom == true && hst_arom == true)
12607
    res = true;
12608
  if (ndl_arom == false && hst_arom == false)
12609
    {
12610
      if (ndl_btype == hst_btype)
12611
        res = true;
12612
      if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
12613
        res = true;
12614
      if (ndl_btype == 's' && hst_btype == 'S')
12615
        res = true;
12616
      if (ndl_btype == 'd' && hst_btype == 'D')
12617
        res = true;
12618
    }
12619
  /* a little exception: */
12620
  if (ndl_arom == false && hst_arom == true)
12621
    {
12622
      if (ndl_btype == 'A')
12623
        res = true;
12624
      if (ndl_btype == 's' || ndl_btype == 'd')
12625
        res = true;
12626
      if (ndl_btype == 'D')
12627
        {                       /* added in 0.2d: do not accept C=O etc. as C-O/arom */
12628
          a1 = ndl_bond[ndl_b - 1].a1;
12629
          a2 = ndl_bond[ndl_b - 1].a2;
12630
          strcpy (a1_el, ndl_atom[a1 - 1].element);
12631
          strcpy (a2_el, ndl_atom[a2 - 1].element);
12632
          if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
12633
              && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
12634
              && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
12635
              && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
12636
            res = true;
12637
        }
12638
      if (ndl_bond[ndl_b - 1].q_arom)
12639
        res = true;             /* 0.3p */
12640
    }
12641
  if (ndl_btype == 'a')
12642
    res = true;
12643
  /* new in v0.3d: obey topology requirements in query structure */
12644
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any)
12645
    {
12646
  if (ndl_btopo == btopo_ring && hst_rc == 0)
12647
    res = false;
12648
  if (ndl_btopo == btopo_chain && hst_rc > 0)
12649
    res = false;
12650
  if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
12651
    res = false;
12652
  if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
12653
    res = false;
12654
}    
12655
/* p2c: checkmol.pas, line 9098:
12656
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12657
  /*$IFDEF debug */
12658
  /* if res = false then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
12659
  /*$ENDIF */
12660
/* p2c: checkmol.pas, line 9102:
12661
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12662
  /*$IFDEF debug */
12663
  /*
12664
     if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
12665
     debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
12666
  /*$ENDIF */
12667
  return res;
12668
}
12669
 
12670
 
12671
static boolean
12672
matrix_OK (m, ndl_dim, hst_dim)
12673
boolean (*m)[max_neighbors];
12674
     int ndl_dim, hst_dim;
12675
{
12676
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
12677
  boolean mr = false;
12678
  matchmatrix lm;
12679
  int i, ii, j, lndl_dim, lhst_dim;
12680
 
12681
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
12682
      hst_dim > max_neighbors || ndl_dim > hst_dim)
12683
    return false;
12684
  if (ndl_dim == 1)
12685
    {
12686
      for (i = 0; i < hst_dim; i++)
12687
        {
12688
          if (m[0][i])
12689
            mr = true;
12690
        }
12691
      return mr;
12692
    }
12693
  for (i = 1; i <= hst_dim; i++)
12694
    {
12695
      if (m[0][i - 1])
12696
        {
12697
          /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
12698
          memset (lm, false, sizeof (matchmatrix));
12699
          for (j = 2; j <= ndl_dim; j++)
12700
            {
12701
              lhst_dim = 0;
12702
              for (ii = 1; ii <= hst_dim; ii++)
12703
                {
12704
                  if (ii != i)
12705
                    {
12706
                      lhst_dim++;
12707
                      lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
12708
                    }
12709
                }
12710
            }
12711
          lndl_dim = ndl_dim - 1;
12712
          if (matrix_OK (lm, lndl_dim, lhst_dim))
12713
            {                   /* recursive call to matrix_OK */
12714
              return true;
12715
              /* stop any further work immediately */
12716
            }
12717
        }
12718
    }
12719
  return false;
12720
}
12721
 
12722
 
12723
static boolean
12724
is_flat (angle_deg)
12725
     double angle_deg;
12726
{
12727
  /* new in v0.3j */
12728
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
12729
    return false;
12730
  else
12731
    return true;
12732
}
12733
 
12734
 
12735
static boolean
12736
chirality_OK (ndl_cp, hst_cp)
12737
     int *ndl_cp, *hst_cp;
12738
{
12739
  boolean res = true;
12740
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
12741
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
12742
  int level = 0;
12743
  int i;
12744
  boolean up = false, down = false, updown = false;
12745
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
12746
 
12747
  /* fill temporary atom variables */
12748
  ta1 = ndl_cp[0];              /* this is the central atom */
12749
  ta2 = ndl_cp[1];
12750
  ta3 = ndl_cp[2];
12751
  ta4 = ndl_cp[3];
12752
  /* first, get the central atom of the needle */
12753
  np2.x = ndl_atom[ta1 - 1].x;
12754
  np2.y = ndl_atom[ta1 - 1].y;
12755
  np2.z = ndl_atom[ta1 - 1].z;
12756
  /* next, do the same for all 3 substituent atoms */
12757
  np1.x = ndl_atom[ta2 - 1].x;
12758
  np1.y = ndl_atom[ta2 - 1].y;
12759
  np1.z = ndl_atom[ta2 - 1].z;
12760
  np3.x = ndl_atom[ta3 - 1].x;
12761
  np3.y = ndl_atom[ta3 - 1].y;
12762
  np3.z = ndl_atom[ta3 - 1].z;
12763
  np4.x = ndl_atom[ta4 - 1].x;
12764
  np4.y = ndl_atom[ta4 - 1].y;
12765
  np4.z = ndl_atom[ta4 - 1].z;
12766
  /* now check all needle bonds if we should care about up/down bonds */
12767
  if (ndl_n_bonds > 0)
12768
    {
12769
      FORLIM = ndl_n_bonds;
12770
      for (i = 0; i < FORLIM; i++)
12771
        {
12772
          if (ndl_bond[i].stereo == bstereo_up ||
12773
              ndl_bond[i].stereo == bstereo_down)
12774
            {
12775
              ba1 = ndl_bond[i].a1;
12776
              ba2 = ndl_bond[i].a2;
12777
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up)
12778
                {
12779
                  up = true;
12780
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12781
                    {
12782
                      updown = true;
12783
                      if (ba2 == ta2)
12784
                        np1.z += 0.8;
12785
                      if (ba2 == ta3)
12786
                        np3.z += 0.8;
12787
                      if (ba2 == ta4)
12788
                        np4.z += 0.8;
12789
                    }
12790
                  else
12791
                    level++;
12792
                }
12793
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down)
12794
                {
12795
                  down = true;
12796
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12797
                    {
12798
                      updown = true;
12799
                      if (ba2 == ta2)
12800
                        np1.z -= 0.8;
12801
                      if (ba2 == ta3)
12802
                        np3.z -= 0.8;
12803
                      if (ba2 == ta4)
12804
                        np4.z -= 0.8;
12805
                    }
12806
                  else
12807
                    level--;
12808
                }
12809
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up)
12810
                {
12811
                  down = true;
12812
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12813
                    {
12814
                      updown = true;
12815
                      if (ba1 == ta2)
12816
                        np1.z -= 0.8;
12817
                      if (ba1 == ta3)
12818
                        np3.z -= 0.8;
12819
                      if (ba1 == ta4)
12820
                        np4.z -= 0.8;
12821
                    }
12822
                  else
12823
                    level--;
12824
                }
12825
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down)
12826
                {
12827
                  up = true;
12828
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12829
                    {
12830
                      updown = true;
12831
                      if (ba1 == ta2)
12832
                        np1.z += 0.8;
12833
                      if (ba1 == ta3)
12834
                        np3.z += 0.8;
12835
                      if (ba1 == ta4)
12836
                        np4.z += 0.8;
12837
                    }
12838
                  else
12839
                    level++;
12840
                }
12841
            }
12842
        }                       /* for i ... */
12843
      if (updown == false && level != 0)
12844
        {
12845
          if (level > 0)
12846
            np2.z += 0.3;
12847
          if (level < 0)
12848
            np2.z -= 0.3;
12849
        }
12850
      else
12851
        {
12852
          if (up)
12853
            np2.z += 0.1;
12854
          if (down)
12855
            np2.z -= 0.1;
12856
        }
12857
    }
12858
  /* fill temporary atom variables again */
12859
  ta1 = hst_cp[0];
12860
  ta2 = hst_cp[1];
12861
  ta3 = hst_cp[2];
12862
  ta4 = hst_cp[3];
12863
  /* then, get the central atom of the haystack */
12864
  hp2.x = atom[ta1 - 1].x;
12865
  hp2.y = atom[ta1 - 1].y;
12866
  hp2.z = atom[ta1 - 1].z;
12867
  /* next, do the same for all 3 substituent atoms */
12868
  hp1.x = atom[ta2 - 1].x;
12869
  hp1.y = atom[ta2 - 1].y;
12870
  hp1.z = atom[ta2 - 1].z;
12871
  hp3.x = atom[ta3 - 1].x;
12872
  hp3.y = atom[ta3 - 1].y;
12873
  hp3.z = atom[ta3 - 1].z;
12874
  hp4.x = atom[ta4 - 1].x;
12875
  hp4.y = atom[ta4 - 1].y;
12876
  hp4.z = atom[ta4 - 1].z;
12877
  /* now check all haystack bonds if we should care about up/down bonds */
12878
  level = 0;
12879
  updown = false;
12880
  up = false;
12881
  down = false;
12882
  if (n_bonds > 0)
12883
    {
12884
      FORLIM = n_bonds;
12885
      for (i = 0; i < FORLIM; i++)
12886
        {
12887
          if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down)
12888
            {
12889
              ba1 = bond[i].a1;
12890
              ba2 = bond[i].a2;
12891
              if (ba1 == ta1 && bond[i].stereo == bstereo_up)
12892
                {
12893
                  up = true;
12894
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12895
                    {
12896
                      updown = true;
12897
                      if (ba2 == ta2)
12898
                        hp1.z += 0.8;
12899
                      if (ba2 == ta3)
12900
                        hp3.z += 0.8;
12901
                      if (ba2 == ta4)
12902
                        hp4.z += 0.8;
12903
                    }
12904
                  else
12905
                    level++;
12906
                }
12907
              if (ba1 == ta1 && bond[i].stereo == bstereo_down)
12908
                {
12909
                  down = true;
12910
                  if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4)
12911
                    {
12912
                      updown = true;
12913
                      if (ba2 == ta2)
12914
                        hp1.z -= 0.8;
12915
                      if (ba2 == ta3)
12916
                        hp3.z -= 0.8;
12917
                      if (ba2 == ta4)
12918
                        hp4.z -= 0.8;
12919
                    }
12920
                  else
12921
                    level--;
12922
                }
12923
              if (ba2 == ta1 && bond[i].stereo == bstereo_up)
12924
                {
12925
                  down = true;
12926
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12927
                    {
12928
                      updown = true;
12929
                      if (ba1 == ta2)
12930
                        hp1.z -= 0.8;
12931
                      if (ba1 == ta3)
12932
                        hp3.z -= 0.8;
12933
                      if (ba1 == ta4)
12934
                        hp4.z -= 0.8;
12935
                    }
12936
                  else
12937
                    level--;
12938
                }
12939
              if (ba2 == ta1 && bond[i].stereo == bstereo_down)
12940
                {
12941
                  up = true;
12942
                  if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4)
12943
                    {
12944
                      updown = true;
12945
                      if (ba1 == ta2)
12946
                        hp1.z += 0.8;
12947
                      if (ba1 == ta3)
12948
                        hp3.z += 0.8;
12949
                      if (ba1 == ta4)
12950
                        hp4.z += 0.8;
12951
                    }
12952
                  else
12953
                    level++;
12954
                }
12955
            }
12956
        }                       /* for i ... */
12957
      if (updown == false && level != 0)
12958
        {
12959
          if (level > 0)
12960
            hp2.z += 0.3;
12961
          if (level < 0)
12962
            hp2.z -= 0.3;
12963
        }
12964
      else
12965
        {
12966
          if (up)
12967
            hp2.z += 0.1;
12968
          if (down)
12969
            hp2.z -= 0.1;
12970
        }
12971
    }
12972
  /* get the pseudo-torsion angles */
12973
  ndl_ct = ctorsion (np1, np2, np3, np4);
12974
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
12975
  ndl_ct_deg = radtodeg (ndl_ct);
12976
  hst_ct_deg = radtodeg (hst_ct);
12977
  /* now do a plausibility check and finally check the sense */
12978
  /* (clockwise or counterclockwise) */
12979
  /*
12980
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
12981
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
12982
     (ndl_ct_deg * hst_ct_deg < 0) then res := false;
12983
   */
12984
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
12985
      ndl_ct_deg * hst_ct_deg < 0)
12986
    res = false;
12987
  if (rs_strict)
12988
    {
12989
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) |
12990
           (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
12991
          ndl_ct_deg * hst_ct_deg < 0)
12992
        res = false;
12993
    }
12994
  return res;
12995
}
12996
 
12997
 
12998
static boolean
12999
ndl_maybe_chiral (na)
13000
     int na;
13001
{
13002
  /* new in v0.3h */
13003
  boolean res = false;
13004
  str2 el;
13005
  str3 at;
13006
  int n_nb;
13007
 
13008
  strcpy (el, ndl_atom[na - 1].element);
13009
  strcpy (at, ndl_atom[na - 1].atype);
13010
  n_nb = ndl_atom[na - 1].neighbor_count;
13011
  if (!strcmp (at, "C3 ") && n_nb > 2)
13012
    res = true;
13013
  if (!strcmp (el, "N "))
13014
    {
13015
      if (!strcmp (at, "N3+") && n_nb == 4)
13016
        res = true;
13017
    }
13018
  if (!strcmp (el, "S "))
13019
    {                           /* sulfoxide */
13020
      if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
13021
        res = true;
13022
    }
13023
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
13024
    return res;
13025
  if (n_nb > 3)                 /* are we missing something here? */
13026
    res = true;
13027
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
13028
    res = false;
13029
  return res;
13030
}
13031
 
13032
 
13033
static boolean
13034
is_matching (ndl_xmp, hst_xmp)
13035
     int *ndl_xmp, *hst_xmp;
13036
{
13037
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
13038
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
13039
  int next_ndl_a, next_hst_a;
13040
  neighbor_rec ndl_nb, hst_nb;
13041
  matchmatrix mm;
13042
  int ndl_mp_len, hst_mp_len;
13043
  matchpath_type ndl_mp, hst_mp;
13044
  boolean emptyline, res, ndl_cis, hst_cis;
13045
  int na1, na2, na3, na4;       /* v0.3d */
13046
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
13047
  int prev_ndl_b;
13048
  int prev_hst_b;
13049
  p_3d p1, p2, p3, p4;
13050
  /*hst_torsion, ndl_torsion : double; */
13051
  chirpath_type ncp, hcp;
13052
  int n_hits, n_singlehits;
13053
/* p2c: checkmol.pas, line 9433:
13054
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13055
  /*$IFDEF debug */
13056
  //char tmpstr[256];
13057
 
13058
  /*$ENDIF */
13059
  /* initialize local matchpath variables */
13060
  //memset (ndl_mp, 0, sizeof (matchpath_type));
13061
  //memset (hst_mp, 0, sizeof (matchpath_type));
13062
  /* copy content of external variables into local ones */
13063
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
13064
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
13065
 
13066
  /*for (i = 0; i < max_matchpath_length; i++)
13067
     {
13068
     ndl_mp[i] = ndl_xmp[i];
13069
     hst_mp[i] = hst_xmp[i];
13070
     } */
13071
 
13072
 
13073
  ndl_mp_len = matchpath_length (ndl_mp);
13074
  hst_mp_len = matchpath_length (hst_mp);
13075
  if (ndl_mp_len != hst_mp_len)
13076
    {
13077
      /* this should never happen.... */
13078
/* p2c: checkmol.pas, line 9451:
13079
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13080
      /*$IFDEF debug */
13081
      //debugoutput ("needle and haystack matchpaths are of different length");
13082
      /*$ENDIF */
13083
      return false;
13084
    }
13085
  ndl_a = ndl_mp[ndl_mp_len - 1];
13086
  hst_a = hst_mp[hst_mp_len - 1];
13087
  ndl_atom[ndl_a - 1].tag = false;
13088
  /* new in v0.3o: mark the last needle atom as "visited" */
13089
  if (ndl_mp_len > 1)
13090
    {
13091
      prev_ndl_a = ndl_mp[ndl_mp_len - 2];
13092
      prev_hst_a = hst_mp[hst_mp_len - 2];
13093
    }
13094
  /* if geometry checking is on, check it here */
13095
  if (ez_search == true && ndl_mp_len > 3)
13096
    {
13097
      na1 = ndl_mp[ndl_mp_len - 1];
13098
      na2 = ndl_mp[ndl_mp_len - 2];
13099
      na3 = ndl_mp[ndl_mp_len - 3];
13100
      na4 = ndl_mp[ndl_mp_len - 4];
13101
      ha1 = hst_mp[hst_mp_len - 1];
13102
      ha2 = hst_mp[hst_mp_len - 2];
13103
      ha3 = hst_mp[hst_mp_len - 3];
13104
      ha4 = hst_mp[hst_mp_len - 4];
13105
      prev_ndl_b = get_ndl_bond (na2, na3);
13106
      prev_hst_b = get_bond (ha2, ha3);
13107
      if (ndl_bond[prev_ndl_b - 1].btype == 'D' &&
13108
          bond[prev_hst_b - 1].arom == false
13109
          && (ndl_bond[prev_ndl_b - 1].stereo !=
13110
              bstereo_double_either && bond[prev_hst_b - 1].stereo !=
13111
              bstereo_double_either)
13112
          /* 0.3x always match if needle and/or haystack bond is double_either */
13113
          &&
13114
          (!strcmp (atom[ha2 - 1].element, "C ")
13115
           || !strcmp (atom[ha2 - 1].element, "N "))
13116
          && (!strcmp (atom[ha3 - 1].element, "C ")
13117
              || !strcmp (atom[ha3 - 1].element, "N ")))
13118
        {                       /* v0.3g; check C=C, C=N, N=N bonds */
13119
          p1.x = atom[ha1 - 1].x;
13120
          p1.y = atom[ha1 - 1].y;
13121
          p1.z = atom[ha1 - 1].z;
13122
          p2.x = atom[ha2 - 1].x;
13123
          p2.y = atom[ha2 - 1].y;
13124
          p2.z = atom[ha2 - 1].z;
13125
          p3.x = atom[ha3 - 1].x;
13126
          p3.y = atom[ha3 - 1].y;
13127
          p3.z = atom[ha3 - 1].z;
13128
          p4.x = atom[ha4 - 1].x;
13129
          p4.y = atom[ha4 - 1].y;
13130
          p4.z = atom[ha4 - 1].z;
13131
          hst_cis = is_cis (p1, p2, p3, p4);
13132
          /*hst_torsion := torsion(p1,p2,p3,p4); */
13133
          p1.x = ndl_atom[na1 - 1].x;
13134
          p1.y = ndl_atom[na1 - 1].y;
13135
          p1.z = ndl_atom[na1 - 1].z;
13136
          p2.x = ndl_atom[na2 - 1].x;
13137
          p2.y = ndl_atom[na2 - 1].y;
13138
          p2.z = ndl_atom[na2 - 1].z;
13139
          p3.x = ndl_atom[na3 - 1].x;
13140
          p3.y = ndl_atom[na3 - 1].y;
13141
          p3.z = ndl_atom[na3 - 1].z;
13142
          p4.x = ndl_atom[na4 - 1].x;
13143
          p4.y = ndl_atom[na4 - 1].y;
13144
          p4.z = ndl_atom[na4 - 1].z;
13145
          /*ndl_torsion := torsion(p1,p2,p3,p4); */
13146
          ndl_cis = is_cis (p1, p2, p3, p4);
13147
          if (ndl_cis != hst_cis)
13148
            {
13149
/* p2c: checkmol.pas, line 9501:
13150
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13151
              /*$IFDEF debug */
13152
              //debugoutput ("E/Z geometry mismatch");
13153
              /*$ENDIF */
13154
              return false;
13155
            }
13156
        }
13157
    }                           /* end of E/Z geometry check */
13158
  /* check whatever can be checked as early as now: */
13159
  /* e.g. different elements or more substituents on needle atom than on haystack */
13160
  if (!atomtypes_OK (ndl_a, hst_a))
13161
    return false;
13162
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
13163
  if (atom[hst_a - 1].neighbor_count == 0 &&
13164
      ndl_atom[ndl_a - 1].neighbor_count == 0)
13165
    {
13166
      if (!atomtypes_OK (ndl_a, hst_a))
13167
        return false;
13168
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
13169
      atom[hst_a - 1].tag = true;
13170
      return true;
13171
    }
13172
  /* and other possibilities: */
13173
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
13174
  hst_b = get_bond (prev_hst_a, hst_a);
13175
/* p2c: checkmol.pas, line 9529:
13176
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13177
  /*$IFDEF debug */
13178
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
13179
  /*$ENDIF */
13180
  if (ndl_b > 0 && hst_b > 0)
13181
    {
13182
      /* do a quick check if bond types match */
13183
      if (!bondtypes_OK (ndl_b, hst_b))
13184
        {
13185
/* p2c: checkmol.pas, line 9537:
13186
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13187
          /*$IFDEF debug */
13188
          /*
13189
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
13190
          /*$ENDIF */
13191
          return false;
13192
        }
13193
    }
13194
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
13195
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a,
13196
                                                                 hst_a) &&
13197
      bondtypes_OK (ndl_b, hst_b))
13198
    {
13199
      return true;
13200
/* p2c: checkmol.pas, line 9549:
13201
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13202
      /*$IFDEF debug */
13203
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
13204
      /*$ENDIF */
13205
    }
13206
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
13207
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
13208
      (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp)))
13209
    {
13210
      return false;
13211
/* p2c: checkmol.pas, line 9559:
13212
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13213
      /*$IFDEF debug */
13214
      /*
13215
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
13216
         {$ENDIF */
13217
    }
13218
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
13219
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
13220
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp)))
13221
    {
13222
      if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
13223
          atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b))
13224
        {
13225
          /* 1st chirality check */
13226
          if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
13227
                                                       ndl_atom[ndl_a -
13228
                                                                1].
13229
                                                       stereo_care)) &&
13230
                ndl_maybe_chiral (ndl_a)))
13231
            {                   /* new in v0.3h */
13232
              return true;
13233
            }                   /* end of 1st chirality check */
13234
          na1 = ndl_a;          /* the (potential) chiral center (v0.3f) */
13235
          na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
13236
          na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
13237
          na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
13238
          ha1 = hst_a;
13239
          ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
13240
          ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
13241
          ha4 = hst_mp[matchpath_length (hst_mp) - 2];
13242
          memset (ncp, 0, sizeof (chirpath_type));
13243
          memset (hcp, 0, sizeof (chirpath_type));
13244
          ncp[0] = na1;
13245
          ncp[1] = na2;
13246
          ncp[2] = na3;
13247
          ncp[3] = na4;
13248
          hcp[0] = ha1;
13249
          hcp[1] = ha2;
13250
          hcp[2] = ha3;
13251
          hcp[3] = ha4;
13252
          if (!chirality_OK (ncp, hcp))
13253
            {
13254
/* p2c: checkmol.pas, line 9589:
13255
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13256
              /*$IFDEF debug */
13257
              //debugoutput ("chirality check failed at ring junction");
13258
              /*$ENDIF */
13259
              return false;
13260
            }
13261
/* p2c: checkmol.pas, line 9596:
13262
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13263
          /*$IFDEF debug */
13264
          //debugoutput ("chirality check succeeded at ring junction");
13265
          /*$ENDIF */
13266
          return true;
13267
/* p2c: checkmol.pas, line 9602:
13268
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13269
          /*$IFDEF debug */
13270
          /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
13271
          /*$ENDIF */
13272
        }
13273
      else
13274
        {
13275
          return false;
13276
/* p2c: checkmol.pas, line 9609:
13277
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13278
          /*$IFDEF debug */
13279
          /*
13280
             debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
13281
          /*$ENDIF */
13282
        }
13283
    }
13284
  /* in all other cases, do the hard work: */
13285
  /* first, get all heavy-atom neighbors of needle and haystack; */
13286
  /* at the beginning of the search, this means all neighbors, then it means */
13287
  /* all but the previous atom (where we came from) */
13288
  memset (ndl_nb, 0, sizeof (neighbor_rec));
13289
  memset (hst_nb, 0, sizeof (neighbor_rec));
13290
 
13291
  if (matchpath_length (ndl_mp) == 1)
13292
    {
13293
      ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
13294
      n_nb = atom[hst_a - 1].neighbor_count;
13295
      get_ndl_neighbors (ndl_nb, ndl_a);
13296
      get_neighbors (hst_nb, hst_a);
13297
    }
13298
  else
13299
    {
13300
      ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
13301
      n_nb = atom[hst_a - 1].neighbor_count - 1;
13302
      get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
13303
      get_nextneighbors (hst_nb, hst_a, prev_hst_a);
13304
    }
13305
  /* v0.3o: mark all neighbor atoms as "visited" */
13306
  for (i = 0; i < ndl_n_nb; i++)
13307
    ndl_atom[ndl_nb[i] - 1].tag = false;
13308
  /* now that the neighbor-arrays are filled, get all */
13309
  /* combinations of matches recursively; */
13310
  /* first, initialize the match matrix */
13311
  memset (mm, false, sizeof (matchmatrix));     /* new in v0.2i */
13312
  /* make sure there are not too many neighbors (max. max_neighbors)   */
13313
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors)
13314
    {                           /* updated in v0.2i */
13315
/* p2c: checkmol.pas, line 9644:
13316
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13317
      /*$IFDEF debug */
13318
      //debugoutput ("too many neighbors - exiting");
13319
      /*$ENDIF */
13320
      return false;
13321
    }
13322
  /* check if matchpath is not already filled up */
13323
  if (matchpath_length (ndl_mp) == max_matchpath_length)
13324
    {
13325
/* p2c: checkmol.pas, line 9653:
13326
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13327
      /*$IFDEF debug */
13328
      //debugoutput ("matchpath too int - exiting");
13329
      /*$ENDIF */
13330
      return false;
13331
    }
13332
  /* next, check which chain of the needle matches which chain of the haystack  */
13333
  for (i = 0; i < ndl_n_nb; i++)
13334
    {
13335
      emptyline = true;
13336
      next_ndl_a = ndl_nb[i];
13337
      for (j = 0; j < n_nb; j++)
13338
        {
13339
          next_hst_a = hst_nb[j];
13340
          ndl_mp[ndl_mp_len] = next_ndl_a;
13341
          hst_mp[hst_mp_len] = next_hst_a;
13342
          if (is_matching (ndl_mp, hst_mp))
13343
            {                   /* recursive function call */
13344
 
13345
              if (max_match_recursion_depth != 0
13346
                  && ++recursion_depth > max_match_recursion_depth)
13347
                {
13348
#ifndef MAKE_SHARED_LIBRARY
13349
                  if (opt_verbose)
13350
#endif
13351
                    printf
13352
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
13353
                       max_match_recursion_depth);
13354
                  //n_rings = max_rings;
13355
                  return true;
13356
                }
13357
 
13358
              mm[i][j] = true;
13359
              emptyline = false;
13360
            }
13361
        }
13362
      /* if a needle substituent does not match any of the haystack substituents, */
13363
      /* stop any further work immediately */
13364
      if (emptyline)
13365
        return false;
13366
    }
13367
  /* finally, check the content of the matrix */
13368
  res = matrix_OK (mm, ndl_n_nb, n_nb);
13369
  /* optional: chirality check */
13370
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) &&
13371
        ndl_maybe_chiral (ndl_a)))
13372
    return res;
13373
  /* first, we have to clean up the match matrix in order to remove */
13374
  /* "impossible" multiple matches (new in v0.3h) */
13375
  for (i = 1; i <= 3; i++)
13376
    {
13377
      for (j = 1; j <= max_neighbors; j++)
13378
        {                       /* haystack dimension */
13379
          n_hits = 0;
13380
          l = 0;
13381
          for (k = 1; k <= max_neighbors; k++)
13382
            {                   /* needle dimension */
13383
              if (mm[k - 1][j - 1])
13384
                {
13385
                  n_hits++;
13386
                  l = k;
13387
                }
13388
            }
13389
          if (n_hits == 1)
13390
            {                   /* a unique match ==> kick out any other match at this pos. */
13391
              for (m = 1; m <= max_neighbors; m++)
13392
                {
13393
                  if (m != j)
13394
                    mm[l - 1][m - 1] = false;
13395
                }
13396
            }
13397
        }
13398
    }
13399
  /* end of match matrix clean-up */
13400
  if (prev_ndl_a > 0)
13401
    {
13402
      n_singlehits = 1;
13403
      ncp[1] = prev_ndl_a;
13404
      hcp[1] = prev_hst_a;
13405
    }
13406
  else
13407
    n_singlehits = 0;
13408
  ncp[0] = ndl_a;
13409
  hcp[0] = hst_a;
13410
  i = 0;
13411
  l = 0;
13412
  while (n_singlehits < 3 && i < 4)
13413
    {
13414
      i++;
13415
      n_hits = 0;
13416
      for (k = 1; k <= n_nb; k++)
13417
        {
13418
          if (mm[i - 1][k - 1])
13419
            {
13420
              n_hits++;
13421
              l = k;
13422
            }
13423
        }
13424
      if (n_hits == 1)
13425
        {
13426
          n_singlehits++;
13427
          ncp[n_singlehits] = ndl_nb[i - 1];
13428
          hcp[n_singlehits] = hst_nb[l - 1];
13429
        }
13430
    }
13431
  if (n_singlehits != 3)
13432
    return res;
13433
  if (!chirality_OK (ncp, hcp))
13434
    {
13435
/* p2c: checkmol.pas, line 9749:
13436
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13437
      /*$IFDEF debug */
13438
      //debugoutput ("chirality check failed");
13439
      /*$ENDIF */
13440
      res = false;
13441
    }
13442
  else
13443
    {
13444
/* p2c: checkmol.pas, line 9755:
13445
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13446
      /*$IFDEF debug */
13447
      //debugoutput ("chirality check OK");
13448
      /*$ENDIF */
13449
    }
13450
  return res;
13451
/* p2c: checkmol.pas, line 9762:
13452
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13453
  /*$IFDEF debug */
13454
  /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
13455
     debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
13456
  /*$ENDIF */
13457
}
13458
 
13459
 
13460
static boolean
13461
quick_match ()
13462
{
13463
  /* added in v0.2c */
13464
  int i;
13465
  boolean res = true;
13466
 /* str3 ndl_atype;*/
13467
  str2 ndl_el;                  /* v0.3l */
6788 kbelabas 13468
  int ndl_chg = 0;              /* v0.3l */
13469
  int ndl_rad = 0;              /* v0.3x */
13470
  int ndl_iso = 0;              /* v0.3x */
6785 bpr 13471
 
13472
 
13473
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
13474
    /* v0.3f, v0.3m, v0.3o */
13475
    return false;
13476
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
13477
      ndl_n_bonds > n_bonds)
13478
    {                           /* just to be sure... */
13479
/* p2c: checkmol.pas, line 9786:
13480
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13481
      /*$IFDEF debug */
13482
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
13483
      //debugoutput (" ==> quick_match failed");
13484
      /*$ENDIF */
13485
      return false;
13486
    }
13487
 
13488
  if (ndl_n_heavyatoms > 1)
13489
    {
13490
      for (i = 0; i < ndl_n_atoms; i++)
13491
        {
13492
          /*if atom^[i].atype <> ndl_atom^[i].atype then res := false;    (* changed in */
13493
          if (strcmp (atom[i].element, ndl_atom[i].element))    /* v0.2k */
13494
            return false;
13495
          //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
13496
          //res = false;
13497
 
13498
 
13499
          if (opt_chg)
13500
            {
13501
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
13502
                return false;
13503
            }
13504
/*  else
13505
    {
13506
      if (ndl_atom[i].formal_charge != 0 &&
13507
          atom[i].formal_charge != 0 &&
13508
          ndl_atom[i].formal_charge != atom[i].formal_charge)
13509
        return false;
13510
    } */
13511
 
13512
          /* v0.3x: isotopes must be the same */
13513
          if (opt_iso)
13514
            {
13515
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
13516
                return false;
13517
            }
13518
/*  else
13519
    {
13520
      if (ndl_atom[i].nucleon_number != 0 &&
13521
          atom[i].nucleon_number != 0 &&
13522
          ndl_atom[i].nucleon_number !=
13523
          atom[i].nucleon_number)
13524
        return false;
13525
    }*/
13526
 
13527
          /* v0.3x: radicals must be the same */
13528
          if (opt_rad)
13529
            {
13530
              if (ndl_atom[i].radical_type != atom[i].radical_type)
13531
                return false;
13532
            }
13533
/*  else
13534
    {
13535
      if (ndl_atom[i].radical_type != 0 &&
13536
          atom[i].radical_type != 0 &&
13537
          ndl_atom[i].radical_type != atom[i].radical_type)
13538
        return false;
13539
    }*/
13540
 
13541
        }
13542
/* p2c: checkmol.pas, line 9798:
13543
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13544
      /*$IFDEF debug */
13545
      //if (res)
13546
      //debugoutput (" ==> quick_match: atoms OK");
13547
      //else
13548
      //  debugoutput (" ==> quick_match: atoms not OK");
13549
      /*$ENDIF */
13550
      if (ndl_n_bonds > 0)
13551
        {
13552
 
13553
          for (i = 0; i < ndl_n_bonds; i++)
13554
            {
13555
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
13556
                  || ndl_bond[i].btype != bond[i].btype)
13557
                return false;
13558
            }
13559
        }
13560
/* p2c: checkmol.pas, line 9810:
13561
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13562
      /*$IFDEF debug */
13563
      //if (res)
13564
      //  debugoutput (" ==> quick_match: bonds OK");
13565
      //else
13566
      //  debugoutput (" ==> quick_match: bonds not OK");
13567
      /*$ENDIF */
13568
      /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
13569
    }
13570
  else
13571
    {
13572
 
13573
      /* first, find out the element and atom type of the only heavy atom       */
13574
      for (i = 0; i < ndl_n_atoms; i++)
13575
        {
13576
          if (ndl_atom[i].heavy)
13577
            {
13578
              //strcpy (ndl_atype, ndl_atom[i].atype);
13579
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
13580
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
13581
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
13582
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
13583
            }
13584
        }
13585
 
13586
      for (i = 0; i < n_atoms; i++)
13587
        {                       /* v0.3l, v0.3o */
13588
          if (          //      !strcmp (atom[i].atype, ndl_atype) && 
13589
               !strcmp (atom[i].element, ndl_el))
13590
            {
13591
 
13592
 
13593
              if (opt_chg || opt_strict)
13594
                {
13595
                  if (ndl_chg != atom[i].formal_charge)
13596
                    return false;
13597
                }
13598
 
13599
 
13600
              if (opt_iso || opt_strict)
13601
                {
13602
                  if (ndl_iso != atom[i].nucleon_number)
13603
                    return false;
13604
                }
13605
 
13606
 
13607
 
13608
              if (opt_rad || opt_strict)
13609
                {
13610
                  if (ndl_rad != atom[i].radical_type)
13611
                    return false;
13612
                }
13613
                  return true;
13614
            } else {
13615
                res=false;
13616
            }    
13617
        }
13618
    }
13619
/* p2c: checkmol.pas, line 9828:
13620
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13621
  /*$IFDEF debug */
13622
  //if (res)
13623
  //  debugoutput (" ==> quick_match succeeded");
13624
  //else
13625
  //  debugoutput (" ==> quick_match failed (2)");
13626
  /*$ENDIF */
13627
  return res;
13628
}
13629
 
13630
static void
13631
perform_match ()
13632
{
13633
  int i = 0;
13634
  int j;
13635
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
13636
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
13637
  boolean qm;                   /* v0.3l */
13638
  /* check for NoStruct (0 atoms);  v0.3l */
13639
  if (n_atoms == 0 || ndl_n_atoms == 0)
13640
    {
13641
      matchresult = false;
13642
/* p2c: checkmol.pas, line 9849:
13643
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13644
      /*$IFDEF debug */
13645
      //debugoutput ("NoStruct encountered - aborted match routine");
13646
      /*$ENDIF */
13647
      return;
13648
    }
13649
  /* if we perform an exact match, needle and haystack must have */
13650
  /* the same number of atoms, bonds, and rings */
13651
  if (opt_exact && opt_iso)     /* 0.3x */
13652
    {
13653
      if (n_heavyatoms != ndl_n_heavyatoms
13654
          || n_heavybonds != ndl_n_heavybonds)
13655
        {
13656
          matchresult = false;
13657
/* p2c: checkmol.pas, line 9861:
13658
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13659
          /*$IFDEF debug */
13660
          //debugoutput ("different number of heavy atoms and/or bonds");
13661
          /*$ENDIF */
13662
          //return;
13663
        }
13664
    }
13665
 
13666
  /* have a quick look if needle and haystack are identical molfiles */
13667
  qm = quick_match ();          /* v0.3l */
13668
  if (qm)
13669
    {
13670
      matchresult = true;
13671
      clear_ndl_atom_tags ();   /* v0.3o */
13672
      return;
13673
    }
13674
  /* if we have only one heavy atom and quick_match fails, return "false";  v0.3l */
13675
  if (ndl_n_heavyatoms == 1)
13676
    {
13677
      matchresult = false;
13678
      return;
13679
    }
13680
/* p2c: checkmol.pas, line 9881:
13681
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13682
  /*$IFDEF debug */
13683
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
13684
  /*$ENDIF */
13685
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
13686
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
13687
/* p2c: checkmol.pas, line 9886:
13688
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13689
  /*$IFDEF debug */
13690
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
13691
  /*$ENDIF */
13692
  matchresult = false;
13693
  for (j = 0; j < max_matchpath_length; j++)
13694
    {
13695
      ndl_matchpath[j] = 0;
13696
      hst_matchpath[j] = 0;
13697
    }
13698
  ndl_matchpath[0] = ndl_ref_atom;
13699
  while (i < n_atoms && matchresult == false)
13700
    {
13701
      i++;
13702
      n_nb = atom[i - 1].neighbor_count;
13703
      n_hc = hetatom_count (i);
13704
      if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc)
13705
        {
13706
/* p2c: checkmol.pas, line 9904:
13707
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13708
          /*$IFDEF debug */
13709
          /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
13710
          /*$ENDIF */
13711
 
13712
          recursion_depth = 0;
13713
          hst_matchpath[0] = i;
13714
          matchresult = is_matching (ndl_matchpath, hst_matchpath);
13715
/* p2c: checkmol.pas, line 9909:
13716
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13717
          /*$IFDEF debug */
13718
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
13719
          /*$ENDIF */
13720
          if (matchresult)      /* v0.3o; mark this fragment as matched */
13721
            atom[i - 1].tag = true;
13722
        }
13723
    }
13724
}
13725
 
13726
 
13727
static void
13728
clear_rings ()
13729
{
13730
  int i, FORLIM;
13731
  n_rings = 0;
13732
  memset (ring, 0, sizeof (ringlist));
13733
  for (i = 0; i < max_rings; i++)
13734
    {                           /* new in v0.3 */
13735
      ringprop[i].size = 0;
13736
      ringprop[i].arom = false;
13737
      ringprop[i].envelope = false;
13738
    }
13739
  if (n_atoms > 0)
13740
    {
13741
      FORLIM = n_atoms;
13742
      for (i = 0; i < FORLIM; i++)
13743
        atom[i].ring_count = 0;
13744
    }
13745
  if (n_bonds > 0)
13746
    {
13747
      FORLIM = n_bonds;
13748
      for (i = 0; i < FORLIM; i++)
13749
        bond[i].ring_count = 0;
13750
    }
13751
}
13752
 
13753
 
13754
static int
13755
ring_lastpos (s)
13756
     int *s;
13757
{
13758
  int i, rc;
13759
  int rlp = 0;
13760
  int FORLIM;
13761
  if (n_rings <= 0)
13762
    return rlp;
13763
  FORLIM = n_rings;
13764
  for (i = 1; i <= FORLIM; i++)
13765
    {
13766
      rc = ringcompare (s, ring[i - 1]);
13767
      if (rc_identical (rc))
13768
        rlp = i;
13769
    }
13770
  return rlp;
13771
}
13772
 
13773
 
13774
static void
13775
remove_redundant_rings ()
13776
{
13777
  int i, j, k, rlp;
13778
  ringpath_type tmp_path;
13779
  int FORLIM, FORLIM1;
13780
  if (n_rings < 2)
13781
    return;
13782
  FORLIM = n_rings;
13783
  for (i = 1; i < FORLIM; i++)
13784
    {
13785
      memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
13786
      rlp = ring_lastpos (tmp_path);
13787
      while (rlp > i)
13788
        {
13789
          FORLIM1 = n_rings;
13790
/* p2c: checkmol.pas, line 9970:
13791
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
13792
          /*$IFDEF debug */
13793
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
13794
          /*$ENDIF */
13795
          for (j = rlp; j < FORLIM1; j++)
13796
            {
13797
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
13798
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
13799
              ringprop[j - 1].arom = ringprop[j].arom;
13800
              ringprop[j - 1].envelope = ringprop[j].envelope;
13801
            }
13802
          for (k = 0; k < max_ringsize; k++)
13803
            ring[n_rings - 1][k] = 0;
13804
          n_rings--;
13805
          rlp = ring_lastpos (tmp_path);
13806
        }
13807
    }
13808
}
13809
 
13810
 
13811
static int
13812
count_aromatic_rings ()
13813
{
13814
  int i;
13815
  int n = 0;
13816
  int FORLIM;
13817
  if (n_rings <= 0)
13818
    return n;
13819
  FORLIM = n_rings;
13820
  for (i = 0; i < FORLIM; i++)
13821
    {
13822
      if (ringprop[i].arom)
13823
        n++;
13824
    }
13825
  return n;
13826
}
13827
 
13828
 
13829
static void
13830
chk_envelopes ()
13831
{
13832
  /* new in v0.3d */
13833
  /* checks if a ring completely contains one or more other rings */
13834
  int a, i, j, k, l, pl, pli;
13835
  boolean found_atom, found_all_atoms, found_ring;
13836
  int FORLIM;
13837
  if (n_rings < 2)
13838
    return;
13839
  FORLIM = n_rings;
13840
  for (i = 1; i < FORLIM; i++)
13841
    {
13842
      found_ring = false;
13843
      j = 0;
13844
      pli = ringprop[i].size;   /* path_length(ring^[i]); */
13845
      while (j < i && found_ring == false)
13846
        {
13847
          j++;
13848
          found_all_atoms = true;
13849
          pl = ringprop[j - 1].size;    /* path_length(ring^[j]); */
13850
          for (k = 0; k < pl; k++)
13851
            {
13852
              found_atom = false;
13853
              a = ring[j - 1][k];
13854
              for (l = 0; l < pli; l++)
13855
                {
13856
                  if (ring[i][l] == a)
13857
                    found_atom = true;
13858
                }
13859
              if (found_atom == false)
13860
                found_all_atoms = false;
13861
            }
13862
          if (found_all_atoms)
13863
            found_ring = true;
13864
        }
13865
      if (found_ring)
13866
        ringprop[i].envelope = true;
13867
    }
13868
}
13869
 
13870
 
13871
static void
13872
update_ringcount ()
13873
{
13874
  int i, j, a1, a2, b, pl, FORLIM;
13875
  if (n_rings <= 0)
13876
    return;
13877
  chk_envelopes ();
13878
  FORLIM = n_rings;
13879
  for (i = 0; i < FORLIM; i++)
13880
    {
13881
      if (ringprop[i].envelope == false)
13882
        {
13883
          pl = ringprop[i].size;        /* path_length(ring^[i]);  (* v0.3d */
13884
          a2 = ring[i][pl - 1];
13885
          for (j = 0; j < pl; j++)
13886
            {
13887
              a1 = ring[i][j];
13888
              atom[a1 - 1].ring_count++;
13889
              b = get_bond (a1, a2);
13890
              bond[b - 1].ring_count++;
13891
              a2 = a1;
13892
            }
13893
        }
13894
    }
13895
}
13896
 
13897
 
13898
static boolean
13899
normalize_ionic_bonds ()
13900
{
13901
  /* v0.3k */
13902
  /* changed from a procedure into a function in v0.3m */
13903
  int i, a1, a2, fc1, fc2;
13904
  char bt;
13905
  boolean res = false;          /* v0.3m */
13906
  int FORLIM;
13907
  /* v0.3m */
13908
  if (n_bonds == 0)
13909
    return false;
13910
  FORLIM = n_bonds;
13911
  for (i = 0; i < FORLIM; i++)
13912
    {
13913
      a1 = bond[i].a1;
13914
      a2 = bond[i].a2;
13915
      bt = bond[i].btype;
13916
      fc1 = atom[a1 - 1].formal_charge;
13917
      fc2 = atom[a2 - 1].formal_charge;
13918
      if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D'))
13919
        {
13920
          atom[a1 - 1].formal_charge = 0;
13921
          atom[a2 - 1].formal_charge = 0;
13922
          if (!strcmp (atom[a1 - 1].atype, "N3+"))      /* v0.3m */
13923
            strcpy (atom[a1 - 1].atype, "N3 ");
13924
          if (!strcmp (atom[a2 - 1].atype, "N3+"))      /* v0.3m */
13925
            strcpy (atom[a2 - 1].atype, "N3 ");
13926
          if (bt == 'D')
13927
            bond[i].btype = 'T';
13928
          if (bt == 'S')
13929
            bond[i].btype = 'D';
13930
          res = true;           /* v0.3m */
13931
        }
13932
    }
13933
  return res;                   /* v0.3m (return true if any change was made */
13934
}
13935
 
13936
#if 0
13937
static void
13938
chk_wildcard_rings ()           // new in v0.3p
13939
// checks if there are any wildcard atom types or bond types
13940
// in a ring of the needle; if yes ==> set the q_arom flag in the
13941
// atom and bond record of all ring members in order to perform the 
13942
// match a bit more generously
13943
{
13944
 
13945
  int i, j, rs;
13946
  int a1, a2, b;
13947
  boolean wcr;
13948
  str3 at;
13949
  char bt;
13950
 
13951
  if (ndl_querymol == false)
13952
    return;
13953
  if (ndl_n_rings == 0)
13954
    return;
13955
  // now look for any not-yet-aromatic rings which contain a wildcard
13956
  for (i = 0; i < ndl_n_rings; i++)
13957
    {
13958
      wcr = false;
13959
      if (ndl_ringprop[i].arom == false)
13960
        {
13961
          rs = ndl_ringprop[i].size;
13962
          a2 = ndl_ring[i][rs];
13963
          for (j = 0; j < rs; j++)
13964
            {
13965
              a1 = ndl_ring[i][j];
13966
              b = get_ndl_bond (a1, a2);
13967
              strcpy (at, ndl_atom[a1].atype);
13968
              bt = ndl_bond[b].btype;
13969
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
13970
                wcr = true;
13971
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
13972
                wcr = true;
13973
              a2 = a1;
13974
            }
13975
          if (wcr)
13976
            {                   // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
13977
              // {$IFDEF debug}
13978
              // debugoutput('wildcard ring found');
13979
              // {$ENDIF}
13980
              a2 = ndl_ring[i][rs];
13981
              for (j = 0; j < rs; j++)
13982
                {
13983
                  a1 = ndl_ring[i][j];
13984
                  b = get_ndl_bond (a1, a2);
13985
                  strcpy (at, ndl_atom[a1].atype);
13986
                  bt = ndl_bond[b].btype;
13987
                  ndl_atom[a1].q_arom = true;
13988
                  ndl_bond[b].q_arom = true;
13989
                  a2 = a1;
13990
                }
13991
            }
13992
        }
13993
    }
13994
  // and now undo this flagging for all rings which contain no wildcard
13995
  for (i = 0; i < ndl_n_rings; i++)
13996
    {
13997
      wcr = false;
13998
      rs = ndl_ringprop[i].size;
13999
      a2 = ndl_ring[i][rs];
14000
      for (j = 0; j < rs; j++)
14001
        {
14002
          a1 = ndl_ring[i][j];
14003
          b = get_ndl_bond (a1, a2);
14004
          strcpy (at, ndl_atom[a1].atype);
14005
          bt = ndl_bond[b].btype;
14006
          if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
14007
            wcr = true;
14008
          if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
14009
            wcr = true;
14010
          a2 = a1;
14011
        }
14012
      if (!wcr)
14013
        {                       // if yes, unflag all atoms and bonds in this ring
14014
          a2 = ndl_ring[i][rs];
14015
          for (j = 0; j < rs; j++)
14016
            {
14017
              a1 = ndl_ring[i][j];
14018
              b = get_ndl_bond (a1, a2);
14019
              strcpy (at, ndl_atom[a1].atype);
14020
              bt = ndl_bond[b].btype;
14021
              ndl_atom[a1].q_arom = false;
14022
              ndl_bond[b].q_arom = false;
14023
              a2 = a1;
14024
            }
14025
        }
14026
    }
14027
  // some further refinement would be necessary here in order to unflag everything
14028
  // which contains a wildcard but which definitely cannot be aromatic
14029
}
14030
#endif
14031
 
14032
#ifndef MAKE_SHARED_LIBRARY
14033
 
14034
int
14035
main (int argc, char *argv[])
14036
{                               /* main routine */
14037
  char STR1[256], STR6[256];
14038
  int FORLIM;
14039
  /* progmode = pmMatchMol */
14040
  rfile = NULL;
14041
  strcpy (progname, argv[0]);
14042
  strncpy (STR1, progname, 253);
14043
  if (strstr (STR1, "matchmol") != NULL)
14044
    progmode = pmMatchMol;
14045
  else
14046
    {
14047
      strncpy (STR6, progname, 253);
14048
      if (strstr (STR6, "checkmol") == NULL)
14049
        {
14050
          printf ("THOU SHALLST NOT RENAME ME!\n");
14051
          exit (9);
14052
        }
14053
      progmode = pmCheckMol;
14054
    }
14055
  if (argc == 1)
14056
    {
14057
      show_usage ();
14058
      exit (1);
14059
    }
14060
  init_globals ();
14061
  init_molstat (&molstat);
14062
  parse_args (argc, argv);
14063
  if (ringsearch_mode == rs_sar)
14064
    max_vringsize = max_ringsize;
14065
  else
14066
    max_vringsize = ssr_vringsize;
14067
  /* v0.3n (was: 10) */
14068
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14069
  if (progmode == pmMatchMol)
14070
    {
14071
      left_trim (ndl_molfilename);
14072
      left_trim (molfilename);
14073
      if ((*molfilename == '\0' || *ndl_molfilename == '\0'
14074
           || argc < 3) && !opt_stdin)
14075
        {
14076
 
14077
          show_usage ();
14078
          exit (2);             /* new in v0.2k */
14079
        }
14080
      if (!(file_exists (ndl_molfilename)) && !opt_stdin)
14081
        {                       /*not  fileexists(ndl_molfilename) REPLACE!!! */
14082
                                   printf("2");
14083
                                   /* p2c: checkmol.pas, line 10128:
14084
                                   * Warning: Expected an expression, found a ')' [227] */
14085
          if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
14086
            show_usage ();
14087
          else
14088
            printf ("file %s not found!\n", ndl_molfilename);
14089
          /* new in v0.2k */
14090
          exit (2);
14091
        }
14092
    }
14093
 
14094
  if (!(file_exists (molfilename)) && !opt_stdin)
14095
    {                           /*not  fileexists(ndl_molfilename) REPLACE!!! */
14096
/* p2c: checkmol.pas, line 10128:
14097
 * Warning: Expected an expression, found a ')' [227] */
14098
 
14099
      if (strlen (molfilename) > 1 && molfilename[0] == '-')
14100
        show_usage ();
14101
      else
14102
        printf ("file %s not found!\n", molfilename);
14103
      /* new in v0.2k */
14104
      exit (2);
14105
    }
14106
 
14107
  /* read the first molecule and process it; if we are in "matchmol" mode, */
14108
  /* this is the "needle" */
14109
  if (progmode == pmMatchMol)
14110
    readinputfile (ndl_molfilename);
14111
  else
14112
    readinputfile (molfilename);
14113
  li = 1;                       /* initialize line pointer for input buffer */
14114
  get_filetype (filetype, ndl_molfilename);
14115
  if (!strcmp (filetype, "unknown"))
14116
    {
14117
      printf ("unknown query file format!\n");
14118
      if (!opt_verbose)
14119
        exit (3);
14120
      printf ("===========================================\n");
14121
      FORLIM = molbufindex;
14122
      for (i = 1; i <= FORLIM; i++)
14123
        puts (molbuf[i - 1]);
14124
      exit (3);
14125
    }
14126
  mol_OK = true;                /* added in v0.2i */
14127
  if (!strcmp (filetype, "alchemy"))
14128
    read_molfile (ndl_molfilename);
14129
  if (!strcmp (filetype, "sybyl"))
14130
    read_mol2file (ndl_molfilename);
14131
  if (!strcmp (filetype, "mdl"))
14132
    read_MDLmolfile (ndl_molfilename);
14133
  count_neighbors ();
14134
  if (!mol_OK || n_atoms < 1)
14135
    {                           /* v0.3g; check if this is a valid query structure */
14136
      printf ("invalid molecule\n");
14137
      exit (3);
14138
    }
14139
  if (!found_arominfo || progmode == pmCheckMol)
14140
    {                           /* added in v0.2b/0.2c */
14141
/* p2c: checkmol.pas, line 10172:
14142
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14143
      /*$IFDEF debug
14144
         if (!found_arominfo)
14145
         debugoutput
14146
         ("no aromaticity information found - checking myself...");
14147
         else
14148
         debugoutput ("performing full aromaticity check");
14149
         // new in v0.3d
14150
      $ENDIF */
14151
      chk_ringbonds ();
14152
      if (ringsearch_mode == rs_ssr)
14153
        remove_redundant_rings ();
14154
      if (n_rings >= max_rings)
14155
        {
14156
          if (opt_verbose)
14157
            printf
14158
              ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14159
               max_rings);
14160
          ringsearch_mode = rs_ssr;
14161
          auto_ssr = true;      /* v0.3n */
14162
          clear_rings ();
14163
          max_vringsize = ssr_vringsize;        /* v0.3n (was: 10) */
14164
          chk_ringbonds ();
14165
          remove_redundant_rings ();
14166
        }
14167
      update_ringcount ();
14168
      /* new in v0.3k: if output is a molfile, leave the original */
14169
      /* representation of N-oxides, S-oxides, nitro groups, etc. */
14170
      /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
14171
      if (!opt_xmdlout)         /* v0.3k */
14172
        normalize_ionic_bonds ();
14173
      update_atypes ();
14174
      update_Htotal ();         /* added in v0.3 */
14175
      chk_arom ();
14176
      if (ringsearch_mode == rs_ssr)
14177
        {                       /* new in v0.3 */
14178
          do
14179
            {
14180
              prev_n_ar = count_aromatic_rings ();
14181
              chk_arom ();
14182
              n_ar = count_aromatic_rings ();
14183
            }
14184
          while (prev_n_ar - n_ar != 0);
14185
        }
14186
    }
14187
  else
14188
    {                           /* v0.3k */
14189
/* p2c: checkmol.pas, line 10206:
14190
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14191
      /*$IFDEF debug
14192
         debugoutput ("found aromaticity information in input file");
14193
         $ENDIF */
14194
      if (!opt_xmdlout)
14195
        normalize_ionic_bonds ();
14196
      update_atypes ();         /* added in v0.2f */
14197
      update_Htotal ();         /* end v0.2b snippet */
14198
    }
14199
  if (progmode == pmCheckMol)
14200
    {
14201
      if (opt_verbose)
14202
        write_mol ();
14203
      get_molstat ();
14204
      if (opt_molstat)
14205
        {
14206
          if (opt_molstat_X)
14207
            write_molstat_X ();
14208
          else
14209
            write_molstat ();
14210
        }
14211
      else
14212
        {
14213
          if (found_querymol)
14214
            {
14215
              printf ("input structure contains query atom or query bond!\n");
14216
              exit (1);
14217
            }
14218
          chk_functionalgroups ();
14219
          if (opt_none)
14220
            opt_text = true;
14221
          if (opt_text)
14222
            write_fg_text ();
14223
          if (opt_text_de)
14224
            write_fg_text_de ();
14225
          if (opt_code)
14226
            write_fg_code ();
14227
          if (opt_bin)
14228
            write_fg_binary ();
14229
          if (opt_bitstring)
14230
            write_fg_bitstring ();
14231
          if (opt_xmdlout)
14232
            write_MDLmolfile ();
14233
        }
14234
      /*if opt_verbose   then write_mol; */
14235
      zap_molecule ();
14236
    }
14237
  else
14238
    {
14239
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14240
      if (!opt_fp)
14241
        {                       /* v0.3m */
14242
          copy_mol_to_needle ();
14243
          //chk_wildcard_rings (); /* 0.3p */
14244
          set_ndl_atom_tags (); /* v0.3o */
14245
          if (opt_verbose)
14246
            write_needle_mol ();
14247
          if (rs_strict)        /* v0.3j */
14248
            ndl_ref_atom = find_ndl_ref_atom_cv ();
14249
          else
14250
            ndl_ref_atom = find_ndl_ref_atom ();
14251
        }
14252
      else
14253
        {
14254
          copy_mol_to_tmp ();   /* v0.3m */
14255
          if (opt_verbose)
14256
            printf ("1st molecule stored in buffer: %s\n", tmp_molname);
14257
        }
14258
      /* next, read the "haystack" file and process it */
14259
      li = 1;
14260
      mol_count = 0;
14261
      fpdecimal = 0;            /* v0.3m */
14262
      fpindex = 0;              /* v0.3m */
14263
      do
14264
        {
14265
          /* new in v0.3i: reset ringsearch_mode to its initial value */
14266
          /* for each new molecule */
14267
          ringsearch_mode = opt_rs;
14268
          if (ringsearch_mode == rs_sar)
14269
            max_vringsize = max_ringsize;
14270
          else
14271
            max_vringsize = ssr_vringsize;
14272
          /* v0.3n (was: 10) */
14273
          readinputfile (molfilename);
14274
          li = 1;
14275
          get_filetype (filetype, molfilename);
14276
          if (strcmp (filetype, "unknown"))
14277
            {
14278
              found_arominfo = false;   /* added in v0.2b */
14279
              mol_OK = true;    /* added in v0.2i */
14280
              if (!strcmp (filetype, "alchemy"))
14281
                read_molfile (molfilename);
14282
              if (!strcmp (filetype, "sybyl"))
14283
                read_mol2file (molfilename);
14284
              if (!strcmp (filetype, "mdl"))
14285
                read_MDLmolfile (molfilename);
14286
              mol_count++;
14287
              fpindex++;
14288
              count_neighbors ();
14289
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14290
              if (!mol_OK || (n_atoms < 1
14291
                  && !(opt_fp && fpformat == fpf_decimal)))
14292
                printf ("%i:F\n", mol_count);
14293
              else
14294
                {
14295
                  if (opt_exact
14296
                      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14297
                          || n_Ntot != ndl_n_Ntot))
14298
                    {           /* new in v0.3g */
14299
                      if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
14300
                        printf ("%i:F\n", mol_count);
14301
                    }
14302
                  else
14303
                    {
14304
                      if (!found_arominfo || (opt_strict && tmfmismatch))
14305
                        {       /* added in v0.3m */
14306
/* p2c: checkmol.pas, line 10294:
14307
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14308
                          /*$IFDEF debug
14309
                             debugoutput
14310
                             ("no aromaticity information found (or tweak mismatch) - checking myself...");
14311
                            *$ENDIF */
14312
                          chk_ringbonds ();
14313
                          if (ringsearch_mode == rs_ssr)
14314
                            remove_redundant_rings ();
14315
                          if (n_rings == max_rings)
14316
                            {
14317
                              if (opt_verbose)
14318
                                printf
14319
                                  ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14320
                                   max_rings);
14321
                              ringsearch_mode = rs_ssr;
14322
                              clear_rings ();
14323
                              max_vringsize = ssr_vringsize;    /* v0.3n (was: 10) */
14324
                              chk_ringbonds ();
14325
                              remove_redundant_rings ();
14326
                            }
14327
                          update_ringcount ();
14328
                          update_atypes ();
14329
                          update_Htotal ();     /* added in v0.3 */
14330
                          chk_arom ();
14331
                          if (ringsearch_mode == rs_ssr)
14332
                            {   /* new in v0.3 */
14333
                              do
14334
                                {
14335
                                  prev_n_ar = count_aromatic_rings ();
14336
                                  chk_arom ();
14337
                                  n_ar = count_aromatic_rings ();
14338
                                }
14339
                              while (prev_n_ar - n_ar != 0);
14340
                            }
14341
                        }
14342
                      else
14343
                        {       /* added in v0.2f */
14344
/* p2c: checkmol.pas, line 10322:
14345
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14346
                          /*$IFDEF debug
14347
                             debugoutput
14348
                             ("found aromaticity information in input file");
14349
                             $ENDIF */
14350
                          if (opt_strict)
14351
                            update_atypes ();
14352
                          update_Htotal ();
14353
                        }
14354
                      init_molstat (&ndl_molstat);
14355
                      if (normalize_ionic_bonds ())
14356
                        /* new in v0.3k, modified in v0.3m */
14357
                        update_atypes ();
14358
                      if (opt_verbose && !opt_fp)
14359
                        write_mol ();
14360
                      /* if in "fingerprint mode", exchange needle and haystack */
14361
                      if (opt_fp)
14362
                        {       /* v0.3m */
14363
                          zap_needle ();
14364
                          copy_mol_to_needle ();
14365
                          //chk_wildcard_rings (); /* 0.3p */
14366
                          zap_molecule ();
14367
                          copy_tmp_to_mol ();
14368
                          if (opt_verbose)
14369
                            write_needle_mol ();
14370
                          if (rs_strict)        /* v0.3j */
14371
                            ndl_ref_atom = find_ndl_ref_atom_cv ();
14372
                          else
14373
                            ndl_ref_atom = find_ndl_ref_atom ();
14374
                          if (opt_verbose)
14375
                            write_mol ();
14376
                        }       /* v0.3m */
14377
                      /* now that we have both molecules, perform the comparison */
14378
                      /* v0.3o: takes care of disconnected fragment... */
14379
                      clear_atom_tags ();
14380
                      set_ndl_atom_tags ();
14381
                      matchsummary = true;
14382
                      perform_match ();
14383
                      matchsummary = matchresult;
14384
                      if (count_tagged_ndl_heavyatoms () > 0
14385
                          && matchsummary == true)
14386
                        {
14387
                          do
14388
                            {
14389
                              if (rs_strict)
14390
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
14391
                              else
14392
                                ndl_ref_atom = find_ndl_ref_atom ();
14393
                              perform_match ();
14394
                              if (matchresult == false)
14395
                                matchsummary = false;
14396
                            }
14397
                          while (count_tagged_ndl_heavyatoms () != 0 &&
14398
                                 matchsummary != false);
14399
                        }
14400
                      /* end of disconnected-fragment matching (v0.3o) */
14401
                      if (matchsummary == true)
14402
                        {       /* v0.3o */
14403
                          if (opt_molout)
14404
                            {
14405
                              FORLIM = molbufindex;
14406
                              for (i = 1; i <= FORLIM; i++)
14407
                                puts (molbuf[i - 1]);
14408
                            }
14409
                          else
14410
                            {
14411
                              if (!opt_fp)      /* inttostr(mol_count) REPLACE!!!, */
14412
                                printf ("%i:T\n", mol_count);
14413
                              else
14414
                                {
14415
                                  if (ndl_n_heavyatoms == n_heavyatoms &&
14416
                                      ndl_n_heavybonds == n_heavybonds)
14417
                                    fp_exacthit = true;
14418
                                  else
14419
                                    fp_exacthit = false;
14420
                                  if (fp_exacthit)
14421
                                    fp_exactblock = true;
14422
                                  if (fpformat == fpf_boolean)
14423
                                    {
14424
                                      if (fp_exacthit)  /* inttostr(mol_count), REPACE!!! */
14425
                                        printf ("%i:TX\n", mol_count);
14426
                                      else
14427
                                        printf ("%i:T\n", mol_count);
14428
                                    }
14429
                                  /* inttostr(mol_count), REPLACE!!! */
14430
                                  if (fpformat == fpf_decimal)
14431
                                    {
14432
                                      fpincrement = 1;
14433
                                      FORLIM = fpindex;
14434
                                      for (i = 1; i <= FORLIM; i++)
14435
                                        fpincrement <<= 1;
14436
                                      fpdecimal += fpincrement;
14437
                                    }
14438
                                }
14439
                            }
14440
                        }
14441
                      else
14442
                        {
14443
                          if (!
14444
                              (opt_molout || (opt_fp
14445
                               && fpformat == fpf_decimal)))
14446
                            /* inttostr(mol_count), REPLACE!!! */
14447
                            printf ("%i:F\n", mol_count);
14448
                        }
14449
                      if (opt_fp && fpformat == fpf_decimal
14450
                          && fpindex == fp_blocksize)
14451
                        {
14452
                          if (fp_exactblock)
14453
                            fpdecimal++;
6786 kbelabas 14454
                          printf ("%lld\n", fpdecimal);
6785 bpr 14455
                          fpindex = 0;
14456
                          fpdecimal = 0;
14457
                          fp_exactblock = false;
14458
                        }
14459
                      zap_molecule ();
14460
                      molbufindex = 0;
14461
                    }
14462
                }
14463
            }
14464
          else
14465
            {
14466
              /* v0.3l */
14467
              /* mol_OK */
14468
              printf ("%i:unknown file format\n", mol_count);
14469
            }
14470
        }
14471
      while (mol_in_queue != false);
14472
      /* if filetype <> 'unknown' */
14473
      if (opt_fp && fpformat == fpf_decimal && fpindex > 0)
14474
        {
14475
          if (fp_exactblock)
14476
            fpdecimal++;
6786 kbelabas 14477
          printf ("%lld\n", fpdecimal);
6785 bpr 14478
        }
14479
      zap_needle ();
14480
      if (rfile_is_open)
14481
        {                       /* new in v0.2g */
14482
          if (rfile != NULL)
14483
            fclose (rfile);
14484
          rfile = NULL;
14485
        }
14486
    }
14487
  if (rfile != NULL)
14488
    fclose (rfile);
14489
  exit (0);
14490
}
14491
 
14492
#else
14493
 
14494
static void
14495
init_globals_dll (void)
14496
{
14497
 
14498
//printf("init_globals_dll\n");
14499
 
14500
  int i;
14501
  opt_verbose = false;
14502
  opt_debug = false;
14503
  opt_stdin = false;
14504
  opt_text = false;
14505
  opt_code = false;
14506
  opt_bin = false;
14507
  opt_bitstring = false;
14508
  opt_molout = false;
14509
  opt_molstat = false;
14510
  opt_molstat_X = false;
14511
  opt_xmdlout = false;
14512
  opt_fp = false;               /* new in v0.3m */
14513
  /*cm_mdlmolfile   := false; */
14514
  found_arominfo = false;
14515
  found_querymol = false;
14516
  ndl_querymol = false;
14517
  opt_rs = rs_sar;              /* v0.3i */
14518
  ringsearch_mode = opt_rs;
14519
  rfile_is_open = false;        /* new in v0.2g */
14520
  ez_flag = false;              /* new in v0.3f */
14521
  chir_flag = false;            /* new in v0.3f */
14522
  n_Ctot = 0;
14523
  n_Otot = 0;
14524
  n_Ntot = 0;                   /* new in v0.3g */
14525
  //for (i = 0; i < max_fg; i++)
14526
  //  fg[i] = false;
14527
  memset (fg, 0, sizeof (fglist));
14528
 
14529
  if (!yet_initialized)
14530
    {
14531
      molbuf = (void *) safe_malloc (sizeof (molbuftype));
14532
      opt_exact = false;
14533
      opt_strict = false;       /* new in v0.2f */
14534
      opt_metalrings = false;   /* new in v0.3 */
14535
      opt_geom = false;         /* new in v0.3d */
14536
      opt_chiral = false;       /* new in v0.3f */
14537
      opt_iso = false;          /* new in v0.3x */
14538
      opt_chg = false;          /* new in v0.3x */
14539
      opt_rad = false;          /* new in v0.3x */
14540
      ez_search = false;        /* new in v0.3d */
14541
      rs_search = false;        /* new in v0.3f */
14542
      rs_strict = false;        /* new in v0.3j */
14543
      ndl_n_Ctot = 0;
14544
      ndl_n_Otot = 0;
14545
      ndl_n_Ntot = 0;           /* new in v0.3g */
14546
      yet_initialized = true;
14547
    }
14548
 
14549
  ether_generic = false;        /* v0.3j */
14550
  amine_generic = false;        /* v0.3j */
14551
  hydroxy_generic = false;      /* v0.3j */
14552
  fpformat = fpf_decimal;       /* v0.3m */
14553
  fpindex = 0;                  /* v0.3m */
14554
  fp_exacthit = false;          /* v0.3m */
14555
  fp_exactblock = false;        /* v0.3m */
14556
  tmfcode = 0;                  /* v0.3m */
14557
  tmfmismatch = false;          /* v0.3m */
14558
  auto_ssr = false;
14559
  recursion_depth = 0;
14560
}
14561
 
14562
static void
14563
mm_init_mol (void)
14564
{
14565
 
14566
//printf("mm_init_mol\n");
14567
  init_globals_dll ();
14568
  init_molstat (&molstat);
14569
  if (opt_rs_dll == RPA_DEFAULT)
14570
    {
14571
      ringsearch_mode = opt_rs;
14572
      //printf("DEFAULT: %i\n",ringsearch_mode);
14573
    }
14574
  else
14575
    {
14576
      ringsearch_mode = opt_rs_dll;
14577
    }
14578
  //printf("RPA: %i\n",ringsearch_mode);
14579
 
14580
  if (ringsearch_mode == rs_sar)
14581
    {
14582
      max_vringsize = max_ringsize;
14583
    }
14584
  else
14585
    {
14586
      max_vringsize = ssr_vringsize;
14587
    }
14588
  zap_molecule ();
14589
  molbufindex = 0;
14590
  mol_count = 0;
14591
//printf("mm_init_mol\n");
14592
}
14593
 
14594
static void
14595
mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
14596
{
14597
//printf("mm_elab_mol\n");
14598
 
14599
  li = 1;                       // initialize line pointer for input buffer
14600
  get_filetype (filetype, ndl_molfilename);
14601
  if (strcmp (filetype, "unknown") == 0)
14602
    {
14603
      //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
14604
      exit (3);
14605
    }
14606
 
14607
  if (checkmol_mode == true)
14608
    progmode = pmCheckMol;
14609
  else
14610
    progmode = pmMatchMol;
14611
  if (strcmp (filetype, "alchemy") == 0)
14612
    read_molfile (ndl_molfilename);
14613
  if (strcmp (filetype, "sybyl") == 0)
14614
    read_mol2file (ndl_molfilename);
14615
  if (strcmp (filetype, "mdl") == 0)
14616
    read_MDLmolfile (ndl_molfilename);
14617
  if (checkmol_mode)
14618
    {
14619
      if (found_querymol)
14620
        {
14621
          printf
14622
            ("Warning: Input structure contains query atom or query bond.\n");
14623
        }
14624
    }
14625
 
14626
  count_neighbors ();
14627
  if (!found_arominfo || checkmol_mode || opt_strict)
14628
    {
14629
      //printf("No arom found or checkmol mode\n");
14630
      chk_ringbonds ();
14631
      if (ringsearch_mode == rs_ssr)
14632
        remove_redundant_rings ();
14633
      if (n_rings >= max_rings)
14634
        {
14635
 
14636
          printf
14637
            ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
14638
             max_rings);
14639
          ringsearch_mode = rs_ssr;
14640
          auto_ssr = true;
14641
          clear_rings ();
14642
          max_vringsize = ssr_vringsize;
14643
          chk_ringbonds ();
14644
          remove_redundant_rings ();
14645
        }
14646
 
14647
      update_ringcount ();
14648
      if (normalize_ionic_bnds) /* v0.3k */
14649
        normalize_ionic_bonds ();
14650
      update_atypes ();
14651
      update_Htotal ();
14652
      chk_arom ();
14653
      if (ringsearch_mode == rs_ssr)
14654
        {                       /* new in v0.3 */
14655
          do
14656
            {
14657
              prev_n_ar = count_aromatic_rings ();
14658
              chk_arom ();
14659
              n_ar = count_aromatic_rings ();
14660
            }
14661
          while (prev_n_ar - n_ar != 0);
14662
        }
14663
    }
14664
  else
14665
    {
14666
      if (normalize_ionic_bnds) /* v0.3k  */
14667
        normalize_ionic_bonds ();
14668
      //if (opt_strict)
14669
      update_atypes ();
14670
      update_Htotal ();
14671
    }
14672
 
14673
 
14674
 
14675
//printf("mm_elab_mol\n");
14676
}
14677
 
14678
DLLEXPORT void
14679
mm_set_current_mol_as_query (void)
14680
{
14681
//printf("mm_set_current_mol_as_query\n");
14682
  zap_needle ();
14683
//mm_ElabMol;
14684
  copy_mol_to_needle ();
14685
  //chk_wildcard_rings (); /* 0.3p */
14686
  set_ndl_atom_tags ();         /* v0.3o */
14687
  if (opt_geom)                 /* v0.3d */
14688
    ez_search = true;
14689
  else if (!ez_flag && ez_search)
14690
    ez_search = false;          //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14691
  if (opt_chiral)
14692
    {                           /* v0.3f */
14693
      rs_search = true;
14694
 
14695
      //printf("%i\n",rs_search);
14696
    }
14697
  else if (!chir_flag && rs_search)
14698
    {
14699
      rs_search = false;        //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14700
      //printf("%i\n",rs_search);
14701
    }
14702
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
14703
    rs_strict = true;
14704
  else
14705
    rs_strict = false;
14706
  /* if (rs_strict)              // v0.3j
14707
     ndl_ref_atom = find_ndl_ref_atom_cv ();
14708
     //ndl_ref_atom = find_ndl_ref_atom ();
14709
     else
14710
     ndl_ref_atom = find_ndl_ref_atom (); */
14711
 
14712
 
14713
 
14714
  molbufindex = 0;
14715
  mol_count = 0;
14716
/*printf("mm_set_current_mol_as_query\n");*/
14717
}
14718
 
14719
DLLEXPORT int
14720
mm_get_rings (void)
14721
{
14722
  return n_rings;
14723
}
14724
 
14725
DLLEXPORT void
14726
xm_version (char *buffer)
14727
{
14728
  buffer[0] = '\0';
14729
  strncpy (buffer, version, 255);
14730
}
14731
 
14732
DLLEXPORT int
14733
mm_get_atom_ring (int atom_number)
14734
{
14735
 
14736
  int i, j, a1, pl;
14737
  int ret = 0;
14738
  a1 = atom[atom_number].ring_count;
14739
  if (n_rings > 0)
14740
    {
14741
      for (i = 1; i < n_rings; i++)
14742
        {
14743
 
14744
          pl = path_length (ring[i]);
14745
//          a2 := ring^[i,pl];
14746
          for (j = 1; j < pl; j++)
14747
            {
14748
 
14749
              a1 = ring[i][j];
14750
              if (atom_number == a1)
14751
                ret = i;
14752
//
14753
//              inc(atom^[a1].ring_count);
14754
//              b := get_bond(a1,a2);
14755
//              inc(bond^[b].ring_count);
14756
//              a2 := a1;
14757
            }
14758
        }
14759
    }
14760
  return ret;
14761
}
14762
 
14763
static void
14764
mm_read_input_line (char *st)
14765
{
14766
//printf("mm_read_input_line_in\n");
14767
//var
14768
//yyy:pchar;
14769
 
14770
  mol_in_queue = false;
14771
  if (molbufindex < (max_atoms + max_bonds + slack))
14772
    {
14773
 
14774
//yyy:=Pchar(IntToStr(molbufindex));
14775
//messagebox (0,yyy,'',0);
14776
//printf("%i\n",molbufindex);
14777
//printf("B:%s\n",st);
14778
      strcpy (molbuf[molbufindex++], st);
14779
//printf("%x %x\n",&molbuf,molbuf);
14780
//printf("%s\n",molbuf[molbufindex-1]);
14781
      //  molbufindex++;
14782
    }
14783
  else
14784
    {
14785
      //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
14786
      printf ("Not enough memory for molfile! %i\n", molbufindex);
14787
      exit (1);
14788
    }
14789
//printf("mm_read_input_line_out\n");
14790
}
14791
 
14792
 
14793
static void
14794
mm_set_mol_dll (const char *st, boolean checkmol_mode,
14795
                boolean normalize_ionic_bnds)
14796
{
14797
//printf("mm_set_mol\n");
14798
//printf("%s\n",st);
14799
  char bb;
14800
  char aa;
14801
  int i;
14802
  int k;
14803
  int J;
14804
  int spt = 0;
14805
  char tt[256];
14806
  char bb10 = '\n';
14807
  char bb13 = '\r';
14808
  char bb0 = '\0';
14809
  int lenst;
14810
//char d[256];
14811
  lenst = strlen (st);
14812
//tt=(char*)safe_malloc(256*sizeof(char));
14813
  tt[0] = '\0';
14814
//messagebox(0,st,'',0);
14815
  mm_init_mol ();
14816
  for (i = spt; i < lenst; i++)
14817
    {
14818
      bb = st[i];
14819
      if ((bb == bb10) || (i == lenst))
14820
        {
14821
          J = 0;
14822
          // d:='';
14823
          for (k = spt; k < i; k++)
14824
            {
14825
 
14826
              aa = st[k];
14827
              if ((aa != bb10) && (aa != bb13))
14828
                {
14829
                  //d:=d+aa;
14830
                  tt[J] = aa;
14831
                  J++;
14832
                }
14833
            }
14834
          tt[J] = bb0;
14835
          spt = i;
14836
          //messagebox (0,tt,tt,0);
14837
//printf("A:%s\n",tt);
14838
          mm_read_input_line (tt);
14839
        }
14840
    }
14841
//free(tt);
14842
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
14843
//printf("mm_set_mol\n");
14844
}
14845
 
14846
DLLEXPORT void
14847
cm_set_mol (const char *st, int normalize_ionic_bnds)
14848
{
14849
  mm_set_mol_dll (st, true, (normalize_ionic_bnds != FEATURE_OFF));
14850
}
14851
 
14852
DLLEXPORT void
14853
mm_set_mol (const char *st)
14854
{
14855
  mm_set_mol_dll (st, false, true);
14856
}
14857
 
14858
DLLEXPORT void
14859
xm_set_strict_typing (int strict_typing)
14860
{
14861
  if (!yet_initialized)
14862
    init_globals_dll ();
14863
  opt_strict = (strict_typing != FEATURE_OFF);
14864
  //opt_strict=false; //This never worked right and is harmful
14865
}
14866
 
14867
DLLEXPORT void
14868
mm_set_r_s_check (int r_s_check)
14869
{
14870
  if (!yet_initialized)
14871
    init_globals_dll ();
14872
  opt_chiral = (r_s_check != FEATURE_OFF);
14873
}
14874
 
14875
DLLEXPORT void
14876
mm_set_e_z_check (int e_z_check)
14877
{
14878
  if (!yet_initialized)
14879
    init_globals_dll ();
14880
  opt_geom = (e_z_check != FEATURE_OFF);
14881
}
14882
 
14883
DLLEXPORT void
14884
mm_set_chg_check (int chg_check)
14885
{
14886
  if (!yet_initialized)
14887
    init_globals_dll ();
14888
  opt_chg = (chg_check != FEATURE_OFF);
14889
}
14890
 
14891
DLLEXPORT void
14892
mm_set_iso_check (int iso_check)
14893
{
14894
  if (!yet_initialized)
14895
    init_globals_dll ();
14896
  opt_iso = (iso_check != FEATURE_OFF);
14897
}
14898
 
14899
DLLEXPORT void
14900
mm_set_rad_check (int rad_check)
14901
{
14902
  if (!yet_initialized)
14903
    init_globals_dll ();
14904
  opt_rad = (rad_check != FEATURE_OFF);
14905
}
14906
 
14907
DLLEXPORT void
14908
mm_set_exact_match (int exact)
14909
{
14910
  if (!yet_initialized)
14911
    init_globals_dll ();
14912
  opt_exact = (exact != FEATURE_OFF);
14913
}
14914
 
14915
DLLEXPORT int
14916
mm_match ()
14917
{
14918
  mol_count = 1;
14919
//     mm_ElabMol;
14920
/*printf("%i\n",opt_exact);
14921
printf("%i\n",n_Ctot);
14922
printf("%i\n",ndl_n_Ctot);
14923
printf("%i\n",n_Otot);
14924
printf("%i\n",ndl_n_Otot);
14925
printf("%i\n",n_Ntot);
14926
printf("%i\n",ndl_n_Ntot);*/
14927
  if (opt_exact
14928
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14929
          || n_Ntot != ndl_n_Ntot))
14930
    return 0;
14931
  init_molstat (&ndl_molstat);
14932
  //perform_match ();
14933
  //---------------------------------------------------- 0.3o
14934
  if (rs_strict)                /* v0.3j */
14935
    ndl_ref_atom = find_ndl_ref_atom_cv ();
14936
  //ndl_ref_atom = find_ndl_ref_atom ();
14937
  else
14938
    ndl_ref_atom = find_ndl_ref_atom ();
14939
  clear_atom_tags ();
14940
  set_ndl_atom_tags ();
14941
  matchsummary = true;
14942
  perform_match ();
14943
  matchsummary = matchresult;
14944
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true)
14945
    {
14946
      do
14947
        {
14948
          if (rs_strict)
14949
            ndl_ref_atom = find_ndl_ref_atom_cv ();
14950
          else
14951
            ndl_ref_atom = find_ndl_ref_atom ();
14952
          perform_match ();
14953
          if (matchresult == false)
14954
            matchsummary = false;
14955
        }
14956
      while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
14957
    }
14958
 
14959
  //-----------------------------------------------------
14960
 
14961
  //mol_count = 0;
14962
 
14963
  //molbufindex = 0;
14964
 
14965
  //return matchresult ? 1 : 0;
14966
 
14967
  return matchsummary ? 1 : 0;
14968
}
14969
 
14970
//-------------------------
14971
 
14972
DLLEXPORT void
14973
xm_set_ring_perception_algorithm (int algo)
14974
{
14975
  switch (algo)
14976
    {
14977
    case RPA_SAR:
14978
      opt_rs_dll = rs_sar;
14979
      break;
14980
    case RPA_SSR:
14981
      opt_rs_dll = rs_ssr;
14982
      break;
14983
    default:
14984
      opt_rs_dll = RPA_DEFAULT;
14985
      break;
14986
    }
14987
  //printf("RPA_SET: %i\n",opt_rs_dll);
14988
}
14989
 
14990
static void
14991
write_molstat_X_dll (char *out_buffer)
14992
{
14993
  char tmp_buf[256];
14994
  out_buffer[0] = '\0';
14995
  if (auto_ssr)                 /* v0.3n */
14996
    fix_ssr_ringcounts ();
14997
  sprintf (tmp_buf, "%d,", n_heavyatoms);
14998
  strcat (out_buffer, tmp_buf);
14999
  sprintf (tmp_buf, "%d,", n_heavybonds);
15000
  strcat (out_buffer, tmp_buf);
15001
#ifdef REDUCED_SAR
15002
  sprintf (tmp_buf, "%d,", n_countablerings);
15003
  strcat (out_buffer, tmp_buf);
15004
#else
15005
  sprintf (tmp_buf, "%d,", n_rings);
15006
  strcat (out_buffer, tmp_buf);
15007
#endif
15008
  sprintf (tmp_buf, "%d,", molstat.n_QA);
15009
  strcat (out_buffer, tmp_buf);
15010
  sprintf (tmp_buf, "%d,", molstat.n_QB);
15011
  strcat (out_buffer, tmp_buf);
15012
  //if (opt_chg)
15013
//    {                         /* 0.3x */
15014
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
15015
//    }
15016
//  else
15017
//    {
15018
  sprintf (tmp_buf, "%d,", molstat.n_chg);
15019
  //   }
15020
  strcat (out_buffer, tmp_buf);
15021
  sprintf (tmp_buf, "%d,", molstat.n_C1);
15022
  strcat (out_buffer, tmp_buf);
15023
  sprintf (tmp_buf, "%d,", molstat.n_C2);
15024
  strcat (out_buffer, tmp_buf);
15025
  sprintf (tmp_buf, "%d,", molstat.n_C);
15026
  strcat (out_buffer, tmp_buf);
15027
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
15028
  strcat (out_buffer, tmp_buf);
15029
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
15030
  strcat (out_buffer, tmp_buf);
15031
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
15032
  strcat (out_buffer, tmp_buf);
15033
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
15034
  strcat (out_buffer, tmp_buf);
15035
  sprintf (tmp_buf, "%d,", molstat.n_O2);
15036
  strcat (out_buffer, tmp_buf);
15037
  sprintf (tmp_buf, "%d,", molstat.n_O3);
15038
  strcat (out_buffer, tmp_buf);
15039
  sprintf (tmp_buf, "%d,", molstat.n_N1);
15040
  strcat (out_buffer, tmp_buf);
15041
  sprintf (tmp_buf, "%d,", molstat.n_N2);
15042
  strcat (out_buffer, tmp_buf);
15043
  sprintf (tmp_buf, "%d,", molstat.n_N3);
15044
  strcat (out_buffer, tmp_buf);
15045
  sprintf (tmp_buf, "%d,", molstat.n_S);
15046
  strcat (out_buffer, tmp_buf);
15047
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
15048
  strcat (out_buffer, tmp_buf);
15049
  sprintf (tmp_buf, "%d,", molstat.n_F);
15050
  strcat (out_buffer, tmp_buf);
15051
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
15052
  strcat (out_buffer, tmp_buf);
15053
  sprintf (tmp_buf, "%d,", molstat.n_Br);
15054
  strcat (out_buffer, tmp_buf);
15055
  sprintf (tmp_buf, "%d,", molstat.n_I);
15056
  strcat (out_buffer, tmp_buf);
15057
  sprintf (tmp_buf, "%d,", molstat.n_P);
15058
  strcat (out_buffer, tmp_buf);
15059
  sprintf (tmp_buf, "%d,", molstat.n_B);
15060
  strcat (out_buffer, tmp_buf);
15061
  sprintf (tmp_buf, "%d,", molstat.n_Met);
15062
  strcat (out_buffer, tmp_buf);
15063
  sprintf (tmp_buf, "%d,", molstat.n_X);
15064
  strcat (out_buffer, tmp_buf);
15065
  sprintf (tmp_buf, "%d,", molstat.n_b1);
15066
  strcat (out_buffer, tmp_buf);
15067
  sprintf (tmp_buf, "%d,", molstat.n_b2);
15068
  strcat (out_buffer, tmp_buf);
15069
  sprintf (tmp_buf, "%d,", molstat.n_b3);
15070
  strcat (out_buffer, tmp_buf);
15071
  sprintf (tmp_buf, "%d,", molstat.n_bar);
15072
  strcat (out_buffer, tmp_buf);
15073
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
15074
  strcat (out_buffer, tmp_buf);
15075
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
15076
  strcat (out_buffer, tmp_buf);
15077
  sprintf (tmp_buf, "%d,", molstat.n_CN);
15078
  strcat (out_buffer, tmp_buf);
15079
  sprintf (tmp_buf, "%d,", molstat.n_XY);
15080
  strcat (out_buffer, tmp_buf);
15081
  sprintf (tmp_buf, "%d,", molstat.n_r3);
15082
  strcat (out_buffer, tmp_buf);
15083
  sprintf (tmp_buf, "%d,", molstat.n_r4);
15084
  strcat (out_buffer, tmp_buf);
15085
  sprintf (tmp_buf, "%d,", molstat.n_r5);
15086
  strcat (out_buffer, tmp_buf);
15087
  sprintf (tmp_buf, "%d,", molstat.n_r6);
15088
  strcat (out_buffer, tmp_buf);
15089
  sprintf (tmp_buf, "%d,", molstat.n_r7);
15090
  strcat (out_buffer, tmp_buf);
15091
  sprintf (tmp_buf, "%d,", molstat.n_r8);
15092
  strcat (out_buffer, tmp_buf);
15093
  sprintf (tmp_buf, "%d,", molstat.n_r9);
15094
  strcat (out_buffer, tmp_buf);
15095
  sprintf (tmp_buf, "%d,", molstat.n_r10);
15096
  strcat (out_buffer, tmp_buf);
15097
  sprintf (tmp_buf, "%d,", molstat.n_r11);
15098
  strcat (out_buffer, tmp_buf);
15099
  sprintf (tmp_buf, "%d,", molstat.n_r12);
15100
  strcat (out_buffer, tmp_buf);
15101
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
15102
  strcat (out_buffer, tmp_buf);
15103
  sprintf (tmp_buf, "%d,", molstat.n_rN);
15104
  strcat (out_buffer, tmp_buf);
15105
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
15106
  strcat (out_buffer, tmp_buf);
15107
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
15108
  strcat (out_buffer, tmp_buf);
15109
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
15110
  strcat (out_buffer, tmp_buf);
15111
  sprintf (tmp_buf, "%d,", molstat.n_rO);
15112
  strcat (out_buffer, tmp_buf);
15113
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
15114
  strcat (out_buffer, tmp_buf);
15115
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
15116
  strcat (out_buffer, tmp_buf);
15117
  sprintf (tmp_buf, "%d,", molstat.n_rS);
15118
  strcat (out_buffer, tmp_buf);
15119
  sprintf (tmp_buf, "%d,", molstat.n_rX);
15120
  strcat (out_buffer, tmp_buf);
15121
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
15122
  strcat (out_buffer, tmp_buf);
15123
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
15124
  strcat (out_buffer, tmp_buf);
15125
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
15126
  strcat (out_buffer, tmp_buf);
15127
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
15128
  strcat (out_buffer, tmp_buf);
15129
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
15130
  strcat (out_buffer, tmp_buf);
15131
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
15132
  strcat (out_buffer, tmp_buf);
15133
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
15134
  strcat (out_buffer, tmp_buf);
15135
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
15136
  strcat (out_buffer, tmp_buf);
15137
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
15138
  strcat (out_buffer, tmp_buf);
15139
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
15140
  strcat (out_buffer, tmp_buf);
15141
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
15142
  strcat (out_buffer, tmp_buf);
15143
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
15144
  strcat (out_buffer, tmp_buf);
15145
  sprintf (tmp_buf, "%d,", molstat.n_psla);
15146
  strcat (out_buffer, tmp_buf);
15147
  sprintf (tmp_buf, "%d,", molstat.n_iso);
15148
  strcat (out_buffer, tmp_buf);
15149
  sprintf (tmp_buf, "%d", molstat.n_rad);
15150
  strcat (out_buffer, tmp_buf);
15151
}
15152
 
15153
static void
15154
write_molstat_dll (char *out_buffer, int mode)
15155
{
15156
  char tmp_buf[256];
15157
  char *sep1;
15158
  char *sep2;
15159
  switch (mode)
15160
    {
15161
    case 1:
15162
      sep1 = "=";
15163
      sep2 = " AND ";
15164
      break;
15165
    case 2:
15166
      sep1 = "<=";
15167
      sep2 = " AND ";
15168
      break;
15169
    default:
15170
      sep1 = ":";
15171
      sep2 = ";";
15172
      break;
15173
    }
15174
 
15175
 
15176
 
15177
  out_buffer[0] = '\0';
15178
 
15179
  if (auto_ssr)                 /* v0.3n */
15180
    fix_ssr_ringcounts ();
15181
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
15182
  strcat (out_buffer, tmp_buf);
15183
  if (n_bonds > 0)
15184
    {
15185
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
15186
      strcat (out_buffer, tmp_buf);
15187
    }
15188
 
15189
#ifdef REDUCED_SAR
15190
  if (n_rings > 0)
15191
    {
15192
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
15193
      strcat (out_buffer, tmp_buf);
15194
    }
15195
#else
15196
  if (n_rings > 0)
15197
    {
15198
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
15199
      strcat (out_buffer, tmp_buf);
15200
    }
15201
#endif
15202
 
15203
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */
15204
    {
15205
      sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
15206
      strcat (out_buffer, tmp_buf);
15207
    }
15208
  if (molstat.n_C1 > 0)
15209
    {
15210
      sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
15211
      strcat (out_buffer, tmp_buf);
15212
    }
15213
  if (molstat.n_C2 > 0)
15214
    {
15215
      sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
15216
      strcat (out_buffer, tmp_buf);
15217
    }
15218
 
15219
 
15220
  if (molstat.n_C > 0)
15221
    {
15222
      sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
15223
      strcat (out_buffer, tmp_buf);
15224
    }
15225
  if (molstat.n_CHB1p > 0)
15226
    {
15227
      sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
15228
      strcat (out_buffer, tmp_buf);
15229
    }
15230
  if (molstat.n_CHB2p > 0)
15231
    {
15232
      sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
15233
      strcat (out_buffer, tmp_buf);
15234
    }
15235
  if (molstat.n_CHB3p > 0)
15236
    {
15237
      sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
15238
      strcat (out_buffer, tmp_buf);
15239
    }
15240
  if (molstat.n_CHB4 > 0)
15241
    {
15242
      sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
15243
      strcat (out_buffer, tmp_buf);
15244
    }
15245
  if (molstat.n_O2 > 0)
15246
    {
15247
      sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
15248
      strcat (out_buffer, tmp_buf);
15249
    }
15250
  if (molstat.n_O3 > 0)
15251
    {
15252
      sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
15253
      strcat (out_buffer, tmp_buf);
15254
    }
15255
  if (molstat.n_N1 > 0)
15256
    {
15257
      sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
15258
      strcat (out_buffer, tmp_buf);
15259
    }
15260
  if (molstat.n_N2 > 0)
15261
    {
15262
      sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
15263
      strcat (out_buffer, tmp_buf);
15264
    }
15265
  if (molstat.n_N3 > 0)
15266
    {
15267
      sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
15268
      strcat (out_buffer, tmp_buf);
15269
    }
15270
  if (molstat.n_S > 0)
15271
    {
15272
      sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
15273
      strcat (out_buffer, tmp_buf);
15274
    }
15275
  if (molstat.n_SeTe > 0)
15276
    {
15277
      sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
15278
      strcat (out_buffer, tmp_buf);
15279
    }
15280
  if (molstat.n_F > 0)
15281
    {
15282
      sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
15283
      strcat (out_buffer, tmp_buf);
15284
    }
15285
  if (molstat.n_Cl > 0)
15286
    {
15287
      sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
15288
      strcat (out_buffer, tmp_buf);
15289
    }
15290
  if (molstat.n_Br > 0)
15291
    {
15292
      sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
15293
      strcat (out_buffer, tmp_buf);
15294
    }
15295
  if (molstat.n_I > 0)
15296
    {
15297
      sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
15298
      strcat (out_buffer, tmp_buf);
15299
    }
15300
  if (molstat.n_P > 0)
15301
    {
15302
      sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
15303
      strcat (out_buffer, tmp_buf);
15304
    }
15305
  if (molstat.n_B > 0)
15306
    {
15307
      sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
15308
      strcat (out_buffer, tmp_buf);
15309
    }
15310
  if (molstat.n_Met > 0)
15311
    {
15312
      sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
15313
      strcat (out_buffer, tmp_buf);
15314
    }
15315
  if (molstat.n_X > 0)
15316
    {
15317
      sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
15318
      strcat (out_buffer, tmp_buf);
15319
    }
15320
  if (molstat.n_b1 > 0)
15321
    {
15322
      sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
15323
      strcat (out_buffer, tmp_buf);
15324
    }
15325
  if (molstat.n_b2 > 0)
15326
    {
15327
      sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
15328
      strcat (out_buffer, tmp_buf);
15329
    }
15330
  if (molstat.n_b3 > 0)
15331
    {
15332
      sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
15333
      strcat (out_buffer, tmp_buf);
15334
    }
15335
  if (molstat.n_bar > 0)
15336
    {
15337
      sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
15338
      strcat (out_buffer, tmp_buf);
15339
    }
15340
  if (molstat.n_C1O > 0)
15341
    {
15342
      sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
15343
      strcat (out_buffer, tmp_buf);
15344
    }
15345
  if (molstat.n_C2O > 0)
15346
    {
15347
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
15348
      strcat (out_buffer, tmp_buf);
15349
    }
15350
  if (molstat.n_CN > 0)
15351
    {
15352
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
15353
      strcat (out_buffer, tmp_buf);
15354
    }
15355
  if (molstat.n_XY > 0)
15356
    {
15357
      sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
15358
      strcat (out_buffer, tmp_buf);
15359
    }
15360
  if (molstat.n_r3 > 0)
15361
    {
15362
      sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
15363
      strcat (out_buffer, tmp_buf);
15364
    }
15365
  if (molstat.n_r4 > 0)
15366
    {
15367
      sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
15368
      strcat (out_buffer, tmp_buf);
15369
    }
15370
  if (molstat.n_r5 > 0)
15371
    {
15372
      sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
15373
      strcat (out_buffer, tmp_buf);
15374
    }
15375
  if (molstat.n_r6 > 0)
15376
    {
15377
      sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
15378
      strcat (out_buffer, tmp_buf);
15379
    }
15380
  if (molstat.n_r7 > 0)
15381
    {
15382
      sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
15383
      strcat (out_buffer, tmp_buf);
15384
    }
15385
  if (molstat.n_r8 > 0)
15386
    {
15387
      sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
15388
      strcat (out_buffer, tmp_buf);
15389
    }
15390
  if (molstat.n_r9 > 0)
15391
    {
15392
      sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
15393
      strcat (out_buffer, tmp_buf);
15394
    }
15395
  if (molstat.n_r10 > 0)
15396
    {
15397
      sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
15398
      strcat (out_buffer, tmp_buf);
15399
    }
15400
  if (molstat.n_r11 > 0)
15401
    {
15402
      sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
15403
      strcat (out_buffer, tmp_buf);
15404
    }
15405
  if (molstat.n_r12 > 0)
15406
    {
15407
      sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
15408
      strcat (out_buffer, tmp_buf);
15409
    }
15410
  if (molstat.n_r13p > 0)
15411
    {
15412
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
15413
      strcat (out_buffer, tmp_buf);
15414
    }
15415
  if (molstat.n_rN > 0)
15416
    {
15417
      sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
15418
      strcat (out_buffer, tmp_buf);
15419
    }
15420
  if (molstat.n_rN1 > 0)
15421
    {
15422
      sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
15423
      strcat (out_buffer, tmp_buf);
15424
    }
15425
  if (molstat.n_rN2 > 0)
15426
    {
15427
      sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
15428
      strcat (out_buffer, tmp_buf);
15429
    }
15430
  if (molstat.n_rN3p > 0)
15431
    {
15432
      sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
15433
      strcat (out_buffer, tmp_buf);
15434
    }
15435
  if (molstat.n_rO > 0)
15436
    {
15437
      sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
15438
      strcat (out_buffer, tmp_buf);
15439
    }
15440
  if (molstat.n_rO1 > 0)
15441
    {
15442
      sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
15443
      strcat (out_buffer, tmp_buf);
15444
    }
15445
  if (molstat.n_rO2p > 0)
15446
    {
15447
      sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
15448
      strcat (out_buffer, tmp_buf);
15449
    }
15450
  if (molstat.n_rS > 0)
15451
    {
15452
      sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
15453
      strcat (out_buffer, tmp_buf);
15454
    }
15455
  if (molstat.n_rX > 0)
15456
    {
15457
      sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
15458
      strcat (out_buffer, tmp_buf);
15459
    }
15460
  if (molstat.n_rAr > 0)
15461
    {
15462
      sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
15463
      strcat (out_buffer, tmp_buf);
15464
    }
15465
 
15466
  if (molstat.n_rBz > 0)
15467
    {
15468
      sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
15469
      strcat (out_buffer, tmp_buf);
15470
    }
15471
 
15472
  if (molstat.n_br2p > 0)
15473
    {
15474
      sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
15475
      strcat (out_buffer, tmp_buf);
15476
    }
15477
 
15478
  if (molstat.n_psg01 > 0)
15479
    {
15480
      sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
15481
      strcat (out_buffer, tmp_buf);
15482
    }
15483
 
15484
  if (molstat.n_psg02 > 0)
15485
    {
15486
      sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
15487
      strcat (out_buffer, tmp_buf);
15488
    }
15489
 
15490
  if (molstat.n_psg13 > 0)
15491
    {
15492
      sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
15493
      strcat (out_buffer, tmp_buf);
15494
    }
15495
 
15496
  if (molstat.n_psg14 > 0)
15497
    {
15498
      sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
15499
      strcat (out_buffer, tmp_buf);
15500
    }
15501
 
15502
  if (molstat.n_psg15 > 0)
15503
    {
15504
      sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
15505
      strcat (out_buffer, tmp_buf);
15506
    }
15507
 
15508
  if (molstat.n_psg16 > 0)
15509
    {
15510
      sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
15511
      strcat (out_buffer, tmp_buf);
15512
    }
15513
 
15514
  if (molstat.n_psg17 > 0)
15515
    {
15516
      sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
15517
      strcat (out_buffer, tmp_buf);
15518
    }
15519
 
15520
  if (molstat.n_psg18 > 0)
15521
    {
15522
      sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
15523
      strcat (out_buffer, tmp_buf);
15524
    }
15525
 
15526
  if (molstat.n_pstm > 0)
15527
    {
15528
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
15529
      strcat (out_buffer, tmp_buf);
15530
    }
15531
 
15532
  if (molstat.n_psla > 0)
15533
    {
15534
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
15535
      strcat (out_buffer, tmp_buf);
15536
    }
15537
 
15538
  if (opt_iso && molstat.n_iso > 0)
15539
    {
15540
      sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
15541
      strcat (out_buffer, tmp_buf);
15542
    }
15543
 
15544
  if (opt_rad && molstat.n_rad > 0)
15545
    {
15546
      sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
15547
      strcat (out_buffer, tmp_buf);
15548
    }
15549
}
15550
 
15551
static void
15552
write_fg_code_dll (char *out_buffer)
15553
{
15554
  char tmp_buf[256];
15555
  out_buffer[0] = '\0';
15556
  if (fg[fg_cation - 1])
15557
    {
15558
      sprintf (tmp_buf, "000000T2;");
15559
      strcat (out_buffer, tmp_buf);
15560
    }
15561
  if (fg[fg_anion - 1])
15562
    {
15563
      sprintf (tmp_buf, "000000T1;");
15564
      strcat (out_buffer, tmp_buf);
15565
    }
15566
 
15567
  if (fg[fg_aldehyde - 1])
15568
    {
15569
      sprintf (tmp_buf, "C2O1H000;");
15570
      strcat (out_buffer, tmp_buf);
15571
    }
15572
  if (fg[fg_ketone - 1])
15573
    {
15574
      sprintf (tmp_buf, "C2O1C000;");
15575
      strcat (out_buffer, tmp_buf);
15576
    }
15577
 
15578
  if (fg[fg_thioaldehyde - 1])
15579
    {
15580
      sprintf (tmp_buf, "C2S1H000;");
15581
      strcat (out_buffer, tmp_buf);
15582
    }
15583
  if (fg[fg_thioketone - 1])
15584
    {
15585
      sprintf (tmp_buf, "C2S1C000;");
15586
      strcat (out_buffer, tmp_buf);
15587
    }
15588
  if (fg[fg_imine - 1])
15589
    {
15590
      sprintf (tmp_buf, "C2N10000;");
15591
      strcat (out_buffer, tmp_buf);
15592
    }
15593
  if (fg[fg_hydrazone - 1])
15594
    {
15595
      sprintf (tmp_buf, "C2N1N000;");
15596
      strcat (out_buffer, tmp_buf);
15597
    }
15598
  if (fg[fg_semicarbazone - 1])
15599
    {
15600
      sprintf (tmp_buf, "C2NNC4ON;");
15601
      strcat (out_buffer, tmp_buf);
15602
    }
15603
  if (fg[fg_thiosemicarbazone - 1])
15604
    {
15605
      sprintf (tmp_buf, "C2NNC4SN;");
15606
      strcat (out_buffer, tmp_buf);
15607
    }
15608
  if (fg[fg_oxime - 1])
15609
    {
15610
      sprintf (tmp_buf, "C2N1OH00;");
15611
      strcat (out_buffer, tmp_buf);
15612
    }
15613
  if (fg[fg_oxime_ether - 1])
15614
    {
15615
      sprintf (tmp_buf, "C2N1OC00;");
15616
      strcat (out_buffer, tmp_buf);
15617
    }
15618
  if (fg[fg_ketene - 1])
15619
    {
15620
      sprintf (tmp_buf, "C3OC0000;");
15621
      strcat (out_buffer, tmp_buf);
15622
    }
15623
  if (fg[fg_ketene_acetal_deriv - 1])
15624
    {
15625
      sprintf (tmp_buf, "C3OCC000;");
15626
      strcat (out_buffer, tmp_buf);
15627
    }
15628
  if (fg[fg_carbonyl_hydrate - 1])
15629
    {
15630
      sprintf (tmp_buf, "C2O2H200;");
15631
      strcat (out_buffer, tmp_buf);
15632
    }
15633
  if (fg[fg_hemiacetal - 1])
15634
    {
15635
      sprintf (tmp_buf, "C2O2HC00;");
15636
      strcat (out_buffer, tmp_buf);
15637
    }
15638
  if (fg[fg_acetal - 1])
15639
    {
15640
      sprintf (tmp_buf, "C2O2CC00;");
15641
      strcat (out_buffer, tmp_buf);
15642
    }
15643
  if (fg[fg_hemiaminal - 1])
15644
    {
15645
      sprintf (tmp_buf, "C2NOHC10;");
15646
      strcat (out_buffer, tmp_buf);
15647
    }
15648
  if (fg[fg_aminal - 1])
15649
    {
15650
      sprintf (tmp_buf, "C2N2CC10;");
15651
      strcat (out_buffer, tmp_buf);
15652
    }
15653
  if (fg[fg_thiohemiaminal - 1])
15654
    {
15655
      sprintf (tmp_buf, "C2NSHC10;");
15656
      strcat (out_buffer, tmp_buf);
15657
    }
15658
  if (fg[fg_thioacetal - 1])
15659
    {
15660
      sprintf (tmp_buf, "C2S2CC00;");
15661
      strcat (out_buffer, tmp_buf);
15662
    }
15663
  if (fg[fg_enamine - 1])
15664
    {
15665
      sprintf (tmp_buf, "C2CNH000;");
15666
      strcat (out_buffer, tmp_buf);
15667
    }
15668
  if (fg[fg_enol - 1])
15669
    {
15670
      sprintf (tmp_buf, "C2COH000;");
15671
      strcat (out_buffer, tmp_buf);
15672
    }
15673
  if (fg[fg_enolether - 1])
15674
    {
15675
      sprintf (tmp_buf, "C2COC000;");
15676
      strcat (out_buffer, tmp_buf);
15677
    }
15678
 
15679
 
15680
  if (fg[fg_prim_alcohol - 1])
15681
    {
15682
      sprintf (tmp_buf, "O1H1C000;");
15683
      strcat (out_buffer, tmp_buf);
15684
    }
15685
  if (fg[fg_sec_alcohol - 1])
15686
    {
15687
      sprintf (tmp_buf, "O1H2C000;");
15688
      strcat (out_buffer, tmp_buf);
15689
    }
15690
  if (fg[fg_tert_alcohol - 1])
15691
    {
15692
      sprintf (tmp_buf, "O1H3C000;");
15693
      strcat (out_buffer, tmp_buf);
15694
    }
15695
  if (fg[fg_1_2_diol - 1])
15696
    {
15697
      sprintf (tmp_buf, "O1H0CO1H;");
15698
      strcat (out_buffer, tmp_buf);
15699
    }
15700
  if (fg[fg_1_2_aminoalcohol - 1])
15701
    {
15702
      sprintf (tmp_buf, "O1H0CN1C;");
15703
      strcat (out_buffer, tmp_buf);
15704
    }
15705
  if (fg[fg_phenol - 1])
15706
    {
15707
      sprintf (tmp_buf, "O1H1A000;");
15708
      strcat (out_buffer, tmp_buf);
15709
    }
15710
  if (fg[fg_1_2_diphenol - 1])
15711
    {
15712
      sprintf (tmp_buf, "O1H2A000;");
15713
      strcat (out_buffer, tmp_buf);
15714
    }
15715
  if (fg[fg_enediol - 1])
15716
    {
15717
      sprintf (tmp_buf, "C2COH200;");
15718
      strcat (out_buffer, tmp_buf);
15719
    }
15720
 
15721
  if (fg[fg_dialkylether - 1])
15722
    {
15723
      sprintf (tmp_buf, "O1C0CC00;");
15724
      strcat (out_buffer, tmp_buf);
15725
    }
15726
  if (fg[fg_alkylarylether - 1])
15727
    {
15728
      sprintf (tmp_buf, "O1C0CA00;");
15729
      strcat (out_buffer, tmp_buf);
15730
    }
15731
  if (fg[fg_diarylether - 1])
15732
    {
15733
      sprintf (tmp_buf, "O1C0AA00;");
15734
      strcat (out_buffer, tmp_buf);
15735
    }
15736
  if (fg[fg_thioether - 1])
15737
    {
15738
      sprintf (tmp_buf, "S1C00000;");
15739
      strcat (out_buffer, tmp_buf);
15740
    }
15741
  if (fg[fg_disulfide - 1])
15742
    {
15743
      sprintf (tmp_buf, "S1S1C000;");
15744
      strcat (out_buffer, tmp_buf);
15745
    }
15746
  if (fg[fg_peroxide - 1])
15747
    {
15748
      sprintf (tmp_buf, "O1O1C000;");
15749
      strcat (out_buffer, tmp_buf);
15750
    }
15751
  if (fg[fg_hydroperoxide - 1])
15752
    {
15753
      sprintf (tmp_buf, "O1O1H000;");
15754
      strcat (out_buffer, tmp_buf);
15755
    }
15756
  if (fg[fg_hydrazine - 1])
15757
    {
15758
      sprintf (tmp_buf, "N1N10000;");
15759
      strcat (out_buffer, tmp_buf);
15760
    }
15761
  if (fg[fg_hydroxylamine - 1])
15762
    {
15763
      sprintf (tmp_buf, "N1O1H000;");
15764
      strcat (out_buffer, tmp_buf);
15765
    }
15766
 
15767
 
15768
  if (fg[fg_prim_aliph_amine - 1])
15769
    {
15770
      sprintf (tmp_buf, "N1C1C000;");
15771
      strcat (out_buffer, tmp_buf);
15772
    }
15773
  if (fg[fg_prim_arom_amine - 1])
15774
    {
15775
      sprintf (tmp_buf, "N1C1A000;");
15776
      strcat (out_buffer, tmp_buf);
15777
    }
15778
 
15779
  if (fg[fg_sec_aliph_amine - 1])
15780
    {
15781
      sprintf (tmp_buf, "N1C2CC00;");
15782
      strcat (out_buffer, tmp_buf);
15783
    }
15784
  if (fg[fg_sec_mixed_amine - 1])
15785
    {
15786
      sprintf (tmp_buf, "N1C2AC00;");
15787
      strcat (out_buffer, tmp_buf);
15788
    }
15789
  if (fg[fg_sec_arom_amine - 1])
15790
    {
15791
      sprintf (tmp_buf, "N1C2AA00;");
15792
      strcat (out_buffer, tmp_buf);
15793
    }
15794
 
15795
  if (fg[fg_tert_aliph_amine - 1])
15796
    {
15797
      sprintf (tmp_buf, "N1C3CC00;");
15798
      strcat (out_buffer, tmp_buf);
15799
    }
15800
  if (fg[fg_tert_mixed_amine - 1])
15801
    {
15802
      sprintf (tmp_buf, "N1C3AC00;");
15803
      strcat (out_buffer, tmp_buf);
15804
    }
15805
  if (fg[fg_tert_arom_amine - 1])
15806
    {
15807
      sprintf (tmp_buf, "N1C3AA00;");
15808
      strcat (out_buffer, tmp_buf);
15809
    }
15810
  if (fg[fg_quart_ammonium - 1])
15811
    {
15812
      sprintf (tmp_buf, "N1C400T2;");
15813
      strcat (out_buffer, tmp_buf);
15814
    }
15815
  if (fg[fg_n_oxide - 1])
15816
    {
15817
      sprintf (tmp_buf, "N0O10000;");
15818
      strcat (out_buffer, tmp_buf);
15819
    }
15820
 
15821
 
15822
  if (fg[fg_halogen_deriv - 1])
15823
    {
15824
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
15825
          !fg[fg_acyl_halide - 1])
15826
        {
15827
          sprintf (tmp_buf, "XX000000;");
15828
          strcat (out_buffer, tmp_buf);
15829
        }
15830
    }
15831
 
15832
  if (fg[fg_alkyl_fluoride - 1])
15833
    {
15834
      sprintf (tmp_buf, "XF00C000;");
15835
      strcat (out_buffer, tmp_buf);
15836
    }
15837
  if (fg[fg_alkyl_chloride - 1])
15838
    {
15839
      sprintf (tmp_buf, "XC00C000;");
15840
      strcat (out_buffer, tmp_buf);
15841
    }
15842
  if (fg[fg_alkyl_bromide - 1])
15843
    {
15844
      sprintf (tmp_buf, "XB00C000;");
15845
      strcat (out_buffer, tmp_buf);
15846
    }
15847
  if (fg[fg_alkyl_iodide - 1])
15848
    {
15849
      sprintf (tmp_buf, "XI00C000;");
15850
      strcat (out_buffer, tmp_buf);
15851
    }
15852
 
15853
  if (fg[fg_aryl_fluoride - 1])
15854
    {
15855
      sprintf (tmp_buf, "XF00A000;");
15856
      strcat (out_buffer, tmp_buf);
15857
    }
15858
  if (fg[fg_aryl_chloride - 1])
15859
    {
15860
      sprintf (tmp_buf, "XC00A000;");
15861
      strcat (out_buffer, tmp_buf);
15862
    }
15863
  if (fg[fg_aryl_bromide - 1])
15864
    {
15865
      sprintf (tmp_buf, "XB00A000;");
15866
      strcat (out_buffer, tmp_buf);
15867
    }
15868
  if (fg[fg_aryl_iodide - 1])
15869
    {
15870
      sprintf (tmp_buf, "XI00A000;");
15871
      strcat (out_buffer, tmp_buf);
15872
    }
15873
  if (fg[fg_organometallic - 1])
15874
    {
15875
      sprintf (tmp_buf, "000000MX;");
15876
      strcat (out_buffer, tmp_buf);
15877
    }
15878
  if (fg[fg_organolithium - 1])
15879
    {
15880
      sprintf (tmp_buf, "000000ML;");
15881
      strcat (out_buffer, tmp_buf);
15882
    }
15883
  if (fg[fg_organomagnesium - 1])
15884
    {
15885
      sprintf (tmp_buf, "000000MM;");
15886
      strcat (out_buffer, tmp_buf);
15887
    }
15888
 
15889
  if (fg[fg_carboxylic_acid - 1])
15890
    {
15891
      sprintf (tmp_buf, "C3O2H000;");
15892
      strcat (out_buffer, tmp_buf);
15893
    }
15894
  if (fg[fg_carboxylic_acid_salt - 1])
15895
    {
15896
      sprintf (tmp_buf, "C3O200T1;");
15897
      strcat (out_buffer, tmp_buf);
15898
    }
15899
  if (fg[fg_carboxylic_acid_ester - 1])
15900
    {
15901
      sprintf (tmp_buf, "C3O2C000;");
15902
      strcat (out_buffer, tmp_buf);
15903
    }
15904
  if (fg[fg_lactone - 1])
15905
    {
15906
      sprintf (tmp_buf, "C3O2CZ00;");
15907
      strcat (out_buffer, tmp_buf);
15908
    }
15909
 
15910
  if (fg[fg_carboxylic_acid_prim_amide - 1])
15911
    {
15912
      sprintf (tmp_buf, "C3ONC100;");
15913
      strcat (out_buffer, tmp_buf);
15914
    }
15915
  if (fg[fg_carboxylic_acid_sec_amide - 1])
15916
    {
15917
      sprintf (tmp_buf, "C3ONC200;");
15918
      strcat (out_buffer, tmp_buf);
15919
    }
15920
  if (fg[fg_carboxylic_acid_tert_amide - 1])
15921
    {
15922
      sprintf (tmp_buf, "C3ONC300;");
15923
      strcat (out_buffer, tmp_buf);
15924
    }
15925
  if (fg[fg_lactam - 1])
15926
    {
15927
      sprintf (tmp_buf, "C3ONCZ00;");
15928
      strcat (out_buffer, tmp_buf);
15929
    }
15930
  if (fg[fg_carboxylic_acid_hydrazide - 1])
15931
    {
15932
      sprintf (tmp_buf, "C3ONN100;");
15933
      strcat (out_buffer, tmp_buf);
15934
    }
15935
  if (fg[fg_carboxylic_acid_azide - 1])
15936
    {
15937
      sprintf (tmp_buf, "C3ONN200;");
15938
      strcat (out_buffer, tmp_buf);
15939
    }
15940
  if (fg[fg_hydroxamic_acid - 1])
15941
    {
15942
      sprintf (tmp_buf, "C3ONOH00;");
15943
      strcat (out_buffer, tmp_buf);
15944
    }
15945
  if (fg[fg_carboxylic_acid_amidine - 1])
15946
    {
15947
      sprintf (tmp_buf, "C3N2H000;");
15948
      strcat (out_buffer, tmp_buf);
15949
    }
15950
  if (fg[fg_carboxylic_acid_amidrazone - 1])
15951
    {
15952
      sprintf (tmp_buf, "C3NNN100;");
15953
      strcat (out_buffer, tmp_buf);
15954
    }
15955
  if (fg[fg_nitrile - 1])
15956
    {
15957
      sprintf (tmp_buf, "C3N00000;");
15958
      strcat (out_buffer, tmp_buf);
15959
    }
15960
 
15961
  if (fg[fg_acyl_fluoride - 1])
15962
    {
15963
      sprintf (tmp_buf, "C3OXF000;");
15964
      strcat (out_buffer, tmp_buf);
15965
    }
15966
  if (fg[fg_acyl_chloride - 1])
15967
    {
15968
      sprintf (tmp_buf, "C3OXC000;");
15969
      strcat (out_buffer, tmp_buf);
15970
    }
15971
  if (fg[fg_acyl_bromide - 1])
15972
    {
15973
      sprintf (tmp_buf, "C3OXB000;");
15974
      strcat (out_buffer, tmp_buf);
15975
    }
15976
  if (fg[fg_acyl_iodide - 1])
15977
    {
15978
      sprintf (tmp_buf, "C3OXI000;");
15979
      strcat (out_buffer, tmp_buf);
15980
    }
15981
  if (fg[fg_acyl_cyanide - 1])
15982
    {
15983
      sprintf (tmp_buf, "C2OC3N00;");
15984
      strcat (out_buffer, tmp_buf);
15985
    }
15986
  if (fg[fg_imido_ester - 1])
15987
    {
15988
      sprintf (tmp_buf, "C3NOC000;");
15989
      strcat (out_buffer, tmp_buf);
15990
    }
15991
  if (fg[fg_imidoyl_halide - 1])
15992
    {
15993
      sprintf (tmp_buf, "C3NXX000;");
15994
      strcat (out_buffer, tmp_buf);
15995
    }
15996
 
15997
  if (fg[fg_thiocarboxylic_acid - 1])
15998
    {
15999
      sprintf (tmp_buf, "C3SOH000;");
16000
      strcat (out_buffer, tmp_buf);
16001
    }
16002
  if (fg[fg_thiocarboxylic_acid_ester - 1])
16003
    {
16004
      sprintf (tmp_buf, "C3SOC000;");
16005
      strcat (out_buffer, tmp_buf);
16006
    }
16007
  if (fg[fg_thiolactone - 1])
16008
    {
16009
      sprintf (tmp_buf, "C3SOCZ00;");
16010
      strcat (out_buffer, tmp_buf);
16011
    }
16012
  if (fg[fg_thiocarboxylic_acid_amide - 1])
16013
    {
16014
      sprintf (tmp_buf, "C3SNH000;");
16015
      strcat (out_buffer, tmp_buf);
16016
    }
16017
  if (fg[fg_thiolactam - 1])
16018
    {
16019
      sprintf (tmp_buf, "C3SNCZ00;");
16020
      strcat (out_buffer, tmp_buf);
16021
    }
16022
  if (fg[fg_imido_thioester - 1])
16023
    {
16024
      sprintf (tmp_buf, "C3NSC000;");
16025
      strcat (out_buffer, tmp_buf);
16026
    }
16027
  if (fg[fg_oxohetarene - 1])
16028
    {
16029
      sprintf (tmp_buf, "C3ONAZ00;");
16030
      strcat (out_buffer, tmp_buf);
16031
    }
16032
  if (fg[fg_thioxohetarene - 1])
16033
    {
16034
      sprintf (tmp_buf, "C3SNAZ00;");
16035
      strcat (out_buffer, tmp_buf);
16036
    }
16037
  if (fg[fg_iminohetarene - 1])
16038
    {
16039
      sprintf (tmp_buf, "C3NNAZ00;");
16040
      strcat (out_buffer, tmp_buf);
16041
    }
16042
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
16043
    {
16044
      sprintf (tmp_buf, "C3O30000;");
16045
      strcat (out_buffer, tmp_buf);
16046
    }
16047
  if (fg[fg_carboxylic_acid_orthoester - 1])
16048
    {
16049
      sprintf (tmp_buf, "C3O3C000;");
16050
      strcat (out_buffer, tmp_buf);
16051
    }
16052
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
16053
    {
16054
      sprintf (tmp_buf, "C3O3NC00;");
16055
      strcat (out_buffer, tmp_buf);
16056
    }
16057
  if (fg[fg_carboxylic_acid_anhydride - 1])
16058
    {
16059
      sprintf (tmp_buf, "C3O2C3O2;");
16060
      strcat (out_buffer, tmp_buf);
16061
    }
16062
 
16063
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
16064
    {
16065
      sprintf (tmp_buf, "C3ONCH10;");
16066
      strcat (out_buffer, tmp_buf);
16067
    }
16068
  if (fg[fg_carboxylic_acid_subst_imide - 1])
16069
    {
16070
      sprintf (tmp_buf, "C3ONCC10;");
16071
      strcat (out_buffer, tmp_buf);
16072
    }
16073
  if (fg[fg_co2_deriv - 1])
16074
    {
16075
      sprintf (tmp_buf, "C4000000;");
16076
      strcat (out_buffer, tmp_buf);
16077
    }
16078
  if (fg[fg_carbonic_acid_deriv - 1])
16079
    {
16080
      sprintf (tmp_buf, "C4O30000;");
16081
      strcat (out_buffer, tmp_buf);
16082
    }
16083
  if (fg[fg_carbonic_acid_monoester - 1])
16084
    {
16085
      sprintf (tmp_buf, "C4O3C100;");
16086
      strcat (out_buffer, tmp_buf);
16087
    }
16088
  if (fg[fg_carbonic_acid_diester - 1])
16089
    {
16090
      sprintf (tmp_buf, "C4O3C200;");
16091
      strcat (out_buffer, tmp_buf);
16092
    }
16093
  if (fg[fg_carbonic_acid_ester_halide - 1])
16094
    {
16095
      sprintf (tmp_buf, "C4O3CX00;");
16096
      strcat (out_buffer, tmp_buf);
16097
    }
16098
  if (fg[fg_thiocarbonic_acid_deriv - 1])
16099
    {
16100
      sprintf (tmp_buf, "C4SO0000;");
16101
      strcat (out_buffer, tmp_buf);
16102
    }
16103
  if (fg[fg_thiocarbonic_acid_monoester - 1])
16104
    {
16105
      sprintf (tmp_buf, "C4SOC100;");
16106
      strcat (out_buffer, tmp_buf);
16107
    }
16108
  if (fg[fg_thiocarbonic_acid_diester - 1])
16109
    {
16110
      sprintf (tmp_buf, "C4SOC200;");
16111
      strcat (out_buffer, tmp_buf);
16112
    }
16113
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
16114
    {
16115
      sprintf (tmp_buf, "C4SOX_00;");
16116
      strcat (out_buffer, tmp_buf);
16117
    }
16118
  if (fg[fg_carbamic_acid_deriv - 1])
16119
    {
16120
      sprintf (tmp_buf, "C4O2N000;");
16121
      strcat (out_buffer, tmp_buf);
16122
    }
16123
  if (fg[fg_carbamic_acid - 1])
16124
    {
16125
      sprintf (tmp_buf, "C4O2NH00;");
16126
      strcat (out_buffer, tmp_buf);
16127
    }
16128
  if (fg[fg_carbamic_acid_ester - 1])
16129
    {
16130
      sprintf (tmp_buf, "C4O2NC00;");
16131
      strcat (out_buffer, tmp_buf);
16132
    }
16133
  if (fg[fg_carbamic_acid_halide - 1])
16134
    {
16135
      sprintf (tmp_buf, "C4O2NX00;");
16136
      strcat (out_buffer, tmp_buf);
16137
    }
16138
  if (fg[fg_thiocarbamic_acid_deriv - 1])
16139
    {
16140
      sprintf (tmp_buf, "C4SN0000;");
16141
      strcat (out_buffer, tmp_buf);
16142
    }
16143
  if (fg[fg_thiocarbamic_acid - 1])
16144
    {
16145
      sprintf (tmp_buf, "C4SNOH00;");
16146
      strcat (out_buffer, tmp_buf);
16147
    }
16148
  if (fg[fg_thiocarbamic_acid_ester - 1])
16149
    {
16150
      sprintf (tmp_buf, "C4SNOC00;");
16151
      strcat (out_buffer, tmp_buf);
16152
    }
16153
  if (fg[fg_thiocarbamic_acid_halide - 1])
16154
    {
16155
      sprintf (tmp_buf, "C4SNXX00;");
16156
      strcat (out_buffer, tmp_buf);
16157
    }
16158
  if (fg[fg_urea - 1])
16159
    {
16160
      sprintf (tmp_buf, "C4O1N200;");
16161
      strcat (out_buffer, tmp_buf);
16162
    }
16163
  if (fg[fg_isourea - 1])
16164
    {
16165
      sprintf (tmp_buf, "C4N2O100;");
16166
      strcat (out_buffer, tmp_buf);
16167
    }
16168
  if (fg[fg_thiourea - 1])
16169
    {
16170
      sprintf (tmp_buf, "C4S1N200;");
16171
      strcat (out_buffer, tmp_buf);
16172
    }
16173
  if (fg[fg_isothiourea - 1])
16174
    {
16175
      sprintf (tmp_buf, "C4N2S100;");
16176
      strcat (out_buffer, tmp_buf);
16177
    }
16178
  if (fg[fg_guanidine - 1])
16179
    {
16180
      sprintf (tmp_buf, "C4N30000;");
16181
      strcat (out_buffer, tmp_buf);
16182
    }
16183
  if (fg[fg_semicarbazide - 1])
16184
    {
16185
      sprintf (tmp_buf, "C4ON2N00;");
16186
      strcat (out_buffer, tmp_buf);
16187
    }
16188
  if (fg[fg_thiosemicarbazide - 1])
16189
    {
16190
      sprintf (tmp_buf, "C4SN2N00;");
16191
      strcat (out_buffer, tmp_buf);
16192
    }
16193
  if (fg[fg_azide - 1])
16194
    {
16195
      sprintf (tmp_buf, "N4N20000;");
16196
      strcat (out_buffer, tmp_buf);
16197
    }
16198
  if (fg[fg_azo_compound - 1])
16199
    {
16200
      sprintf (tmp_buf, "N2N10000;");
16201
      strcat (out_buffer, tmp_buf);
16202
    }
16203
  if (fg[fg_diazonium_salt - 1])
16204
    {
16205
      sprintf (tmp_buf, "N3N100T2;");
16206
      strcat (out_buffer, tmp_buf);
16207
    }
16208
  if (fg[fg_isonitrile - 1])
16209
    {
16210
      sprintf (tmp_buf, "N3C10000;");
16211
      strcat (out_buffer, tmp_buf);
16212
    }
16213
  if (fg[fg_cyanate - 1])
16214
    {
16215
      sprintf (tmp_buf, "C4NO1000;");
16216
      strcat (out_buffer, tmp_buf);
16217
    }
16218
  if (fg[fg_isocyanate - 1])
16219
    {
16220
      sprintf (tmp_buf, "C4NO2000;");
16221
      strcat (out_buffer, tmp_buf);
16222
    }
16223
  if (fg[fg_thiocyanate - 1])
16224
    {
16225
      sprintf (tmp_buf, "C4NS1000;");
16226
      strcat (out_buffer, tmp_buf);
16227
    }
16228
  if (fg[fg_isothiocyanate - 1])
16229
    {
16230
      sprintf (tmp_buf, "C4NS2000;");
16231
      strcat (out_buffer, tmp_buf);
16232
    }
16233
  if (fg[fg_carbodiimide - 1])
16234
    {
16235
      sprintf (tmp_buf, "C4N20000;");
16236
      strcat (out_buffer, tmp_buf);
16237
    }
16238
  if (fg[fg_nitroso_compound - 1])
16239
    {
16240
      sprintf (tmp_buf, "N2O10000;");
16241
      strcat (out_buffer, tmp_buf);
16242
    }
16243
  if (fg[fg_nitro_compound - 1])
16244
    {
16245
      sprintf (tmp_buf, "N4O20000;");
16246
      strcat (out_buffer, tmp_buf);
16247
    }
16248
  if (fg[fg_nitrite - 1])
16249
    {
16250
      sprintf (tmp_buf, "N3O20000;");
16251
      strcat (out_buffer, tmp_buf);
16252
    }
16253
  if (fg[fg_nitrate - 1])
16254
    {
16255
      sprintf (tmp_buf, "N4O30000;");
16256
      strcat (out_buffer, tmp_buf);
16257
    }
16258
  if (fg[fg_sulfuric_acid_deriv - 1])
16259
    {
16260
      sprintf (tmp_buf, "S6O00000;");
16261
      strcat (out_buffer, tmp_buf);
16262
    }
16263
  if (fg[fg_sulfuric_acid - 1])
16264
    {
16265
      sprintf (tmp_buf, "S6O4H000;");
16266
      strcat (out_buffer, tmp_buf);
16267
    }
16268
  if (fg[fg_sulfuric_acid_monoester - 1])
16269
    {
16270
      sprintf (tmp_buf, "S6O4HC00;");
16271
      strcat (out_buffer, tmp_buf);
16272
    }
16273
  if (fg[fg_sulfuric_acid_diester - 1])
16274
    {
16275
      sprintf (tmp_buf, "S6O4CC00;");
16276
      strcat (out_buffer, tmp_buf);
16277
    }
16278
  if (fg[fg_sulfuric_acid_amide_ester - 1])
16279
    {
16280
      sprintf (tmp_buf, "S6O3NC00;");
16281
      strcat (out_buffer, tmp_buf);
16282
    }
16283
  if (fg[fg_sulfuric_acid_amide - 1])
16284
    {
16285
      sprintf (tmp_buf, "S6O3N100;");
16286
      strcat (out_buffer, tmp_buf);
16287
    }
16288
  if (fg[fg_sulfuric_acid_diamide - 1])
16289
    {
16290
      sprintf (tmp_buf, "S6O2N200;");
16291
      strcat (out_buffer, tmp_buf);
16292
    }
16293
  if (fg[fg_sulfuryl_halide - 1])
16294
    {
16295
      sprintf (tmp_buf, "S6O3XX00;");
16296
      strcat (out_buffer, tmp_buf);
16297
    }
16298
  if (fg[fg_sulfonic_acid_deriv - 1])
16299
    {
16300
      sprintf (tmp_buf, "S5O00000;");
16301
      strcat (out_buffer, tmp_buf);
16302
    }
16303
  if (fg[fg_sulfonic_acid - 1])
16304
    {
16305
      sprintf (tmp_buf, "S5O3H000;");
16306
      strcat (out_buffer, tmp_buf);
16307
    }
16308
  if (fg[fg_sulfonic_acid_ester - 1])
16309
    {
16310
      sprintf (tmp_buf, "S5O3C000;");
16311
      strcat (out_buffer, tmp_buf);
16312
    }
16313
  if (fg[fg_sulfonamide - 1])
16314
    {
16315
      sprintf (tmp_buf, "S5O2N000;");
16316
      strcat (out_buffer, tmp_buf);
16317
    }
16318
  if (fg[fg_sulfonyl_halide - 1])
16319
    {
16320
      sprintf (tmp_buf, "S5O2XX00;");
16321
      strcat (out_buffer, tmp_buf);
16322
    }
16323
  if (fg[fg_sulfone - 1])
16324
    {
16325
      sprintf (tmp_buf, "S4O20000;");
16326
      strcat (out_buffer, tmp_buf);
16327
    }
16328
  if (fg[fg_sulfoxide - 1])
16329
    {
16330
      sprintf (tmp_buf, "S2O10000;");
16331
      strcat (out_buffer, tmp_buf);
16332
    }
16333
  if (fg[fg_sulfinic_acid_deriv - 1])
16334
    {
16335
      sprintf (tmp_buf, "S3O00000;");
16336
      strcat (out_buffer, tmp_buf);
16337
    }
16338
  if (fg[fg_sulfinic_acid - 1])
16339
    {
16340
      sprintf (tmp_buf, "S3O2H000;");
16341
      strcat (out_buffer, tmp_buf);
16342
    }
16343
  if (fg[fg_sulfinic_acid_ester - 1])
16344
    {
16345
      sprintf (tmp_buf, "S3O2C000;");
16346
      strcat (out_buffer, tmp_buf);
16347
    }
16348
  if (fg[fg_sulfinic_acid_halide - 1])
16349
    {
16350
      sprintf (tmp_buf, "S3O1XX00;");
16351
      strcat (out_buffer, tmp_buf);
16352
    }
16353
  if (fg[fg_sulfinic_acid_amide - 1])
16354
    {
16355
      sprintf (tmp_buf, "S3O1N000;");
16356
      strcat (out_buffer, tmp_buf);
16357
    }
16358
  if (fg[fg_sulfenic_acid_deriv - 1])
16359
    {
16360
      sprintf (tmp_buf, "S1O00000;");
16361
      strcat (out_buffer, tmp_buf);
16362
    }
16363
  if (fg[fg_sulfenic_acid - 1])
16364
    {
16365
      sprintf (tmp_buf, "S1O1H000;");
16366
      strcat (out_buffer, tmp_buf);
16367
    }
16368
  if (fg[fg_sulfenic_acid_ester - 1])
16369
    {
16370
      sprintf (tmp_buf, "S1O1C000;");
16371
      strcat (out_buffer, tmp_buf);
16372
    }
16373
  if (fg[fg_sulfenic_acid_halide - 1])
16374
    {
16375
      sprintf (tmp_buf, "S1O0XX00;");
16376
      strcat (out_buffer, tmp_buf);
16377
    }
16378
  if (fg[fg_sulfenic_acid_amide - 1])
16379
    {
16380
      sprintf (tmp_buf, "S1O0N100;");
16381
      strcat (out_buffer, tmp_buf);
16382
    }
16383
 
16384
  if (fg[fg_alkylthiol - 1])
16385
    {
16386
      sprintf (tmp_buf, "S1H1C000;");
16387
      strcat (out_buffer, tmp_buf);
16388
    }
16389
  if (fg[fg_arylthiol - 1])
16390
    {
16391
      sprintf (tmp_buf, "S1H1A000;");
16392
      strcat (out_buffer, tmp_buf);
16393
    }
16394
  if (fg[fg_phosphoric_acid_deriv - 1])
16395
    {
16396
      sprintf (tmp_buf, "P5O0H000;");
16397
      strcat (out_buffer, tmp_buf);
16398
    }
16399
  if (fg[fg_phosphoric_acid - 1])
16400
    {
16401
      sprintf (tmp_buf, "P5O4H200;");
16402
      strcat (out_buffer, tmp_buf);
16403
    }
16404
  if (fg[fg_phosphoric_acid_ester - 1])
16405
    {
16406
      sprintf (tmp_buf, "P5O4HC00;");
16407
      strcat (out_buffer, tmp_buf);
16408
    }
16409
  if (fg[fg_phosphoric_acid_halide - 1])
16410
    {
16411
      sprintf (tmp_buf, "P5O3HX00;");
16412
      strcat (out_buffer, tmp_buf);
16413
    }
16414
  if (fg[fg_phosphoric_acid_amide - 1])
16415
    {
16416
      sprintf (tmp_buf, "P5O3HN00;");
16417
      strcat (out_buffer, tmp_buf);
16418
    }
16419
  if (fg[fg_thiophosphoric_acid_deriv - 1])
16420
    {
16421
      sprintf (tmp_buf, "P5O0S000;");
16422
      strcat (out_buffer, tmp_buf);
16423
    }
16424
  if (fg[fg_thiophosphoric_acid - 1])
16425
    {
16426
      sprintf (tmp_buf, "P5O3SH00;");
16427
      strcat (out_buffer, tmp_buf);
16428
    }
16429
  if (fg[fg_thiophosphoric_acid_ester - 1])
16430
    {
16431
      sprintf (tmp_buf, "P5O3SC00;");
16432
      strcat (out_buffer, tmp_buf);
16433
    }
16434
  if (fg[fg_thiophosphoric_acid_halide - 1])
16435
    {
16436
      sprintf (tmp_buf, "P5O2SX00;");
16437
      strcat (out_buffer, tmp_buf);
16438
    }
16439
  if (fg[fg_thiophosphoric_acid_amide - 1])
16440
    {
16441
      sprintf (tmp_buf, "P5O2SN00;");
16442
      strcat (out_buffer, tmp_buf);
16443
    }
16444
  if (fg[fg_phosphonic_acid_deriv - 1])
16445
    {
16446
      sprintf (tmp_buf, "P4O30000;");
16447
      strcat (out_buffer, tmp_buf);
16448
    }
16449
  if (fg[fg_phosphonic_acid - 1])
16450
    {
16451
      sprintf (tmp_buf, "P4O3H000;");
16452
      strcat (out_buffer, tmp_buf);
16453
    }
16454
  if (fg[fg_phosphonic_acid_ester - 1])
16455
    {
16456
      sprintf (tmp_buf, "P4O3C000;");
16457
      strcat (out_buffer, tmp_buf);
16458
    }
16459
  if (fg[fg_phosphine - 1])
16460
    {
16461
      sprintf (tmp_buf, "P3000000;");
16462
      strcat (out_buffer, tmp_buf);
16463
    }
16464
  if (fg[fg_phosphinoxide - 1])
16465
    {
16466
      sprintf (tmp_buf, "P2O00000;");
16467
      strcat (out_buffer, tmp_buf);
16468
    }
16469
  if (fg[fg_boronic_acid_deriv - 1])
16470
    {
16471
      sprintf (tmp_buf, "B2O20000;");
16472
      strcat (out_buffer, tmp_buf);
16473
    }
16474
  if (fg[fg_boronic_acid - 1])
16475
    {
16476
      sprintf (tmp_buf, "B2O2H000;");
16477
      strcat (out_buffer, tmp_buf);
16478
    }
16479
  if (fg[fg_boronic_acid_ester - 1])
16480
    {
16481
      sprintf (tmp_buf, "B2O2C000;");
16482
      strcat (out_buffer, tmp_buf);
16483
    }
16484
  if (fg[fg_alkene - 1])
16485
    {
16486
      sprintf (tmp_buf, "000C2C00;");
16487
      strcat (out_buffer, tmp_buf);
16488
    }
16489
  if (fg[fg_alkyne - 1])
16490
    {
16491
      sprintf (tmp_buf, "000C3C00;");
16492
      strcat (out_buffer, tmp_buf);
16493
    }
16494
  if (fg[fg_aromatic - 1])
16495
    {
16496
      sprintf (tmp_buf, "0000A000;");
16497
      strcat (out_buffer, tmp_buf);
16498
    }
16499
  if (fg[fg_heterocycle - 1])
16500
    {
16501
      sprintf (tmp_buf, "0000CZ00;");
16502
      strcat (out_buffer, tmp_buf);
16503
    }
16504
  if (fg[fg_alpha_aminoacid - 1])
16505
    {
16506
      sprintf (tmp_buf, "C3O2HN1C;");
16507
      strcat (out_buffer, tmp_buf);
16508
    }
16509
  if (fg[fg_alpha_hydroxyacid - 1])
16510
    {
16511
      sprintf (tmp_buf, "C3O2HO1H;");
16512
      strcat (out_buffer, tmp_buf);
16513
    }
16514
}
16515
 
16516
/*static void mm_elab_molstat(void)
16517
{
16518
                count_neighbors();
16519
//      init_molstat(&molstat);
16520
        if (!found_arominfo) {
16521
    chk_ringbonds();
16522
    if (ringsearch_mode == rs_ssr)
16523
      remove_redundant_rings();
16524
    if (n_rings == max_rings) {
16525
      if (opt_verbose)
16526
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
16527
      ringsearch_mode = rs_ssr;
16528
      clear_rings();
16529
      max_vringsize = 10;
16530
      chk_ringbonds();
16531
      remove_redundant_rings();
16532
    }
16533
 
16534
    update_ringcount();
16535
    update_atypes();
16536
    update_Htotal();
16537
    chk_arom();
16538
 
16539
    if (ringsearch_mode == rs_ssr) {
16540
      do {
16541
        prev_n_ar = count_aromatic_rings();
16542
        chk_arom();
16543
        n_ar = count_aromatic_rings();
16544
      } while (prev_n_ar - n_ar != 0);
16545
    }
16546
        } else {
16547
 update_atypes();
16548
    update_Htotal();  
16549
 
16550
        }
16551
 
16552
 // get_molstat();
16553
}*/
16554
 
16555
DLLEXPORT void
16556
cm_molstat_X (char *buf)
16557
{
16558
  init_molstat (&molstat);
16559
//mm_elab_molstat();
16560
  get_molstat ();
16561
  write_molstat_X_dll (buf);
16562
}
16563
 
16564
DLLEXPORT void
16565
cm_molstat (char *buf)
16566
{
16567
  init_molstat (&molstat);
16568
//mm_elab_molstat();
16569
  get_molstat ();
16570
  write_molstat_dll (buf, 0);
16571
}
16572
 
16573
DLLEXPORT void
16574
cm_molstat_sql_exact (char *buf)
16575
{
16576
  init_molstat (&molstat);
16577
//mm_elab_molstat();
16578
  get_molstat ();
16579
  write_molstat_dll (buf, 1);
16580
}
16581
 
16582
DLLEXPORT void
16583
cm_molstat_sql_substruct (char *buf)
16584
{
16585
  init_molstat (&molstat);
16586
//mm_elab_molstat();
16587
  get_molstat ();
16588
  write_molstat_dll (buf, 2);
16589
}
16590
 
16591
DLLEXPORT void
16592
cm_fg_codes (char *buf)
16593
{
16594
//mm_elab_molstat();
16595
  chk_functionalgroups ();
16596
  write_fg_code_dll (buf);
16597
}
16598
 
16599
static void
16600
write_MDLmolfile_dll (char *out_buffer)
16601
{
16602
  int i;
16603
  char tmpstr[256];
16604
  char wline[256];
16605
  int a_chg;
16606
  int a_iso;
16607
  int a_rad;
16608
  char tmflabel[256];           /* v0.3m */
16609
  char STR1[256], STR7[256];
16610
  int FORLIM;
16611
  *out_buffer = '\0';
16612
  *tmpstr = '\0';
16613
  *wline = '\0';
16614
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
16615
  while (strlen (tmflabel) < 2) /* v0.3m */
16616
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
16617
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
16618
  if (strlen (molname) > 80)
16619
    sprintf (molname, "%.80s", strcpy (STR1, molname));
16620
  strncat (out_buffer, molname, 80);
16621
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
16622
  if (ringsearch_mode == rs_sar)        /* v0.3m */
16623
    strcat (wline, ":r0");
16624
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
16625
    strcat (wline, ":r1");
16626
  if (opt_metalrings)
16627
    strcat (wline, ":m1");
16628
  else
16629
    strcat (wline, ":m0");
16630
  /* v0.3m */
16631
  sprintf (tmpstr, "\n%s\n", molcomment);
16632
  strcat (wline, tmpstr);
16633
  sprintf (tmpstr, "%d", n_atoms);
16634
  lblank (3L, tmpstr);
16635
  strcat (wline, tmpstr);
16636
  /* first 3 digits: number of atoms */
16637
  sprintf (tmpstr, "%d", n_bonds);
16638
  lblank (3L, tmpstr);
16639
  strcat (wline, tmpstr);
16640
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
16641
  strcpy (tmpstr, "  0");
16642
  strcat (wline, tmpstr);
16643
  /* next 3 digits: number of atom lists (not used by us) */
16644
/* p2c: checkmol.pas, line 2388:
16645
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
16646
#ifdef REDUCED_SAR
16647
  sprintf (tmpstr, "%d", n_countablerings);
16648
  /* v0.3n; changed n_rings into n_countablerings */
16649
#else
16650
  sprintf (tmpstr, "%d", n_rings);
16651
#endif
16652
  lblank (3L, tmpstr);
16653
  strcat (wline, tmpstr);
16654
  /* officially "obsolete", we use it for the number of rings */
16655
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
16656
  if (chir_flag)
16657
    strcat (wline, "1");
16658
  else
16659
    strcat (wline, "0");
16660
  /* v0.3n */
16661
  strcat (wline, "               999 V2000\n");
16662
  /* v0.3n (adjust string length) */
16663
  strcat (out_buffer, wline);
16664
  FORLIM = n_atoms;
16665
  for (i = 0; i < FORLIM; i++)
16666
    {
16667
      *wline = '\0';
16668
      *tmpstr = '\0';
16669
      sprintf (tmpstr, "%1.4f", atom[i].x);
16670
      lblank (10L, tmpstr);
16671
      strcat (wline, tmpstr);
16672
      sprintf (tmpstr, "%1.4f", atom[i].y);
16673
      lblank (10L, tmpstr);
16674
      strcat (wline, tmpstr);
16675
      sprintf (tmpstr, "%1.4f", atom[i].z);
16676
      lblank (10L, tmpstr);
16677
      strcat (wline, tmpstr);
16678
      strcpy (tmpstr, atom[i].element);
16679
      /* tmpstr := lowercase(tmpstr); REPLACE!!! */
16680
      //tmpstr[0] = toupper (tmpstr[0]);
16681
      all_lowercase (tmpstr);
16682
      tmpstr[0] = toupper (tmpstr[0]);
16683
      /*wline := wline + ' '+atom^[i].element+' '; */
16684
      sprintf (wline + strlen (wline), " %s ", tmpstr);
16685
      strcat (wline, " 0");     /* mass difference (isotopes) */
16686
      /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
16687
      if (atom[i].arom)
16688
        strcpy (tmpstr, " 00");
16689
      else
16690
        strcpy (tmpstr, "  0");
16691
      strcat (wline, tmpstr);
16692
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
16693
      strcat (out_buffer, wline);
16694
    }
16695
  FORLIM = n_bonds;
16696
  for (i = 0; i < FORLIM; i++)
16697
    {
16698
      *wline = '\0';
16699
      *tmpstr = '\0';
16700
      sprintf (tmpstr, "%d", bond[i].a1);
16701
      lblank (3L, tmpstr);
16702
      strcat (wline, tmpstr);
16703
      sprintf (tmpstr, "%d", bond[i].a2);
16704
      lblank (3L, tmpstr);
16705
      strcat (wline, tmpstr);
16706
      if (bond[i].btype == 'S')
16707
        strcpy (tmpstr, "  1");
16708
      if (bond[i].btype == 'D')
16709
        strcpy (tmpstr, "  2");
16710
      if (bond[i].btype == 'T')
16711
        strcpy (tmpstr, "  3");
16712
      if (bond[i].btype == 'A')
16713
        strcpy (tmpstr, "  4");
16714
      if (bond[i].btype == 'l')
16715
        strcpy (tmpstr, "  5");
16716
      if (bond[i].btype == 's')
16717
        strcpy (tmpstr, "  6");
16718
      if (bond[i].btype == 'd')
16719
        strcpy (tmpstr, "  7");
16720
      if (bond[i].btype == 'a')
16721
        strcpy (tmpstr, "  8");
16722
      /* now encode our own aromaticity information */
16723
      if (bond[i].arom)
16724
        tmpstr[1] = '0';
16725
      strcat (wline, tmpstr);   /* next, encode bond stereo property (v0.3f) */
16726
      /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
16727
      /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
16728
      /*    wline := wline + '  0'; */
16729
      /* restore original value from MDL molfile (v0.3n) */
16730
      /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
16731
      *tmpstr = '\0';
16732
      sprintf (tmpstr, "%i", bond[i].mdl_stereo);
16733
      strcat (wline, "  ");
16734
      strcat (wline, tmpstr);
16735
      *tmpstr = '\0';
16736
      /* now encode the ring_count of this bond (using a field which officially is "not used") */
16737
      /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
16738
      sprintf (tmpstr, "%i", bond[i].ring_count);
16739
      while (strlen (tmpstr) < 3)
16740
        sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
16741
      sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
16742
      strcat (out_buffer, wline);
16743
    }
16744
  FORLIM = n_atoms;
16745
  for (i = 1; i <= FORLIM; i++)
16746
    {
16747
      a_chg = atom[i - 1].formal_charge;
16748
      if (a_chg != 0)
16749
        {
16750
          strcpy (wline, "M  CHG  1 ");
16751
          sprintf (tmpstr, "%d", i);
16752
          lblank (3L, tmpstr);
16753
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16754
          sprintf (tmpstr, "%d", a_chg);
16755
          lblank (3L, tmpstr);
16756
          strcat (wline, tmpstr);
16757
          strcat (out_buffer, wline);
16758
          strcat (out_buffer, "\n");
16759
        }
16760
    }
16761
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
16762
    {
16763
      a_iso = atom[i - 1].nucleon_number;
16764
      if (a_iso != 0)
16765
        {
16766
          strcpy (wline, "M  ISO  1 ");
16767
          sprintf (tmpstr, "%d", i);
16768
          lblank (3L, tmpstr);
16769
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16770
          sprintf (tmpstr, "%d", a_iso);
16771
          lblank (3L, tmpstr);
16772
          strcat (wline, tmpstr);
16773
          strcat (out_buffer, wline);
16774
          strcat (out_buffer, "\n");
16775
        }
16776
    }
16777
  for (i = 1; i <= FORLIM; i++) /* 0.3x */
16778
    {
16779
      a_rad = atom[i - 1].radical_type;
16780
      if (a_rad != 0)
16781
        {
16782
          strcpy (wline, "M  RAD  1 ");
16783
          sprintf (tmpstr, "%d", i);
16784
          lblank (3L, tmpstr);
16785
          sprintf (wline + strlen (wline), "%s ", tmpstr);
16786
          sprintf (tmpstr, "%d", a_rad);
16787
          lblank (3L, tmpstr);
16788
          strcat (wline, tmpstr);
16789
          strcat (out_buffer, wline);
16790
          strcat (out_buffer, "\n");
16791
        }
16792
    }
16793
  strcat (out_buffer, "M  END\n");
16794
}
16795
 
16796
DLLEXPORT void
16797
cm_tweak_molfile (char *buf)
16798
{
16799
//chk_functionalgroups();
16800
  write_MDLmolfile_dll (buf);
16801
}
16802
#endif