Subversion Repositories wimsdev

Rev

Rev 14626 | Rev 17891 | 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
14179 bpr 7
 
6785 bpr 8
   compile with gcc without optimizations (except -march= -mcpu=) or it gets SLOWER!
14179 bpr 9
 
6785 bpr 10
   THIS VERSION HAS extended_molstat SWITCHED ON BY DEFAULT!
14179 bpr 11
 
6785 bpr 12
   This file is part of the xchem::tigress project.
13
 
14
   --- DUAL LICENSING ---
14179 bpr 15
 
6785 bpr 16
   If checkmol.c aka. pgchem::barsoi is compiled as a library, it is released under the terms of the
17
   lesser GNU General Public License. For the executable, the original GPL
18
   licensing applies!
14179 bpr 19
 
6785 bpr 20
   This program is free software; you can redistribute it and/or modify
21
   it under the terms of the lesser GNU General Public License as published by
22
   the Free Software Foundation version 2.1 of the License.
14179 bpr 23
 
6785 bpr 24
   This program is distributed in the hope that it will be useful,
25
   but WITHOUT ANY WARRANTY; without even the implied warranty of
26
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
   lesser GNU General Public License for more details.
14179 bpr 28
 
6785 bpr 29
   --- DUAL LICENSING ---
30
 
31
   ORIGINAL HEADER:
14179 bpr 32
 
6785 bpr 33
checkmol/matchmol
34
Norbert Haider, University of Vienna, 2003-2007
35
norbert.haider@univie.ac.at
36
 
37
This software is published under the terms of the GNU General Public
38
License (GPL, see below). For a detailed description of this license,
39
see http://www.gnu.org/copyleft/gpl.html
40
 
41
If invoked as "checkmol", this program reads 2D and 3D molecular structure
42
files in various formats (Tripos Alchemy "mol", Tripos SYBYL "mol2", MDL "mol")
43
and describes the molecule either by its functional groups or by a set of
44
descriptors useful for database pre-screening (number of rings, sp2-hybridized
45
carbons, aromatic bonds, etc.; see definition of molstat_rec).
46
 
47
If invoked as "matchmol", the program reads two individual 2D or 3D molecular
48
structure files in various formats (see above) and checks if the first molecule
49
(the "needle") is a substructure of the second one (the "haystack").
50
"Haystack" can also be a MDL SD-file (containing multiple MOL files);
51
if invoked with "-" as file argument, both "needle" and "haystack" are
52
read as an SD-file from standard input, assuming the first entry in
53
the SDF to be the "needle"; output: entry number + ":F" (false) or ":T" (true)
54
 
55
Compile with fpc (Free Pascal, see http://www.freepascal.org), using
56
the -Sd or -S2 option (Delphi mode; IMPORTANT!)
57
 
58
example for compilation (with optimization) and installation:
59
 
60
fpc checkmol.pas -S2 -Xs -OG -Or -O2u -Op1
61
 
62
as "root", do the following:
63
 
64
cp checkmol /usr/local/bin
65
cd /usr/local/bin
66
ln checkmol matchmol
67
 
68
Version history
69
 
70
v0.1   extends "chkmol" utility (N. Haider, 2002), adds matching functionality;
71
 
72
v0.1a  minor bugfixes:
73
       stop ring search when max_rings is reached (function is_ringpath);
74
       fixed upper/lowercase of element symbol in MDL molfile output;
75
       added debug output for checkmol (-D option)
76
 
77
v0.2   added functionality to switch ring search from SAR (set of all rings) to
78
       SSR (set of small rings; see below) if number of rings exceeds max_rings
79
       (1024), e.g. with Buckminster-fullerenes (thanks to E.-G. Schmid for a hint);
80
       added -r command-line option to force ring search into SSR mode;
81
       as SSR, we regard the set of all rings with max. 10 ring members, and in
82
       which no ring is completely contained in another one
83
 
84
v0.2a  fixed a bug in function is_ringpath which could cause SAR ring search to
85
       overlook a few rings (e.g., the six 8-membered rings in cubane)
86
 
87
v0.2b  fixed unequal treatment of needle and haystack structures with respect
88
       to aromaticity check (trusting input file vs. full check)
89
 
90
v0.2c  modified the changes of v0.2b so that they affect only "matchmol" mode;
91
       added quick_match function
92
 
93
v0.2d  refined function bondtypes_OK so that it does not accept C=O fragments
94
       (and C=S, C=Se, C=Te) as equivalent to aromatic C-O (C-S, C-Se, C-Te);
95
       fixed function find_ndl_ref_atom to use only heavy atoms as "needle"
96
       reference atoms for atom-to-atom match; update function quick_match to
97
       handle queries with only one heavy atom (thanks to A. Barozza for a hint)
98
 
99
v0.2e  modified procedure get_molstat: adds 1 formal double bond for each aromatic
100
       ring to the "fingerprint" in order to allow an isolated double bond in the
101
       needle to be matched as a fragment of an aromatic ring
102
       ATTENTION: "fingerprints" (molecular statistics) generated with a previous
103
       version of checkmol(-x and -X option) must be updated for structure/
104
       substructure database searching with matchmaol.
105
 
106
v0.2f  modified procedures chk_ccx, chk_xccx, write_fg_text, write_fg_text_de,
107
       write_fg_code in order to report halogen derivatives other than alkyl halides,
108
       aryl halides and acyl halides (e.g., vinyl halides) and C=C compounds other
109
       than "true" alkenes, enols, enediols, enamines, etc. (e.g. vinyl halides);
110
       added "strict mode" (option -s) for matching: this uses a more thorough
111
       comparison of atom types and bond types (new functions atomtypes_OK_strict,
112
       bondtypes_OK_strict, several minor modifications in other subroutines).
113
 
114
v0.2g  changed procedure readinputfile (+ minor changes in main routine) in
115
       order to read very large SD input files without "not enough memory" error
116
       (the previous version attempted to read the entire SD file into a buffer,
117
       the new version reads only one molecule at once);
118
       fixed a minor bug in read_mol2file which led to undefined bond types;
119
       added definition of "debug" option as a compiler flag.
120
 
121
v0.2h  fixed a small bug which caused program hangs with (e.g.) some metal
122
       complexes: this was solved just by increasing the number of possible
123
       neighbor atoms from 8 to 16 (now defined in the constant max_neighbors).
124
 
125
v0.2i  introduced some more plausibility checking (number of directly connected
126
       atoms), result stored in variable mol_OK (set in count_neighbors);
127
       completely rewrote function matrix_OK which now can handle up to
128
       max_neighbors substituents per atom (previous versions were limited to
129
       4 substituents; larger numbers are required e.g. for ferrocenes and
130
       similar compounds).
131
 
132
v0.2j  new function raw_hetbond_count: ignores bond order (in contrast to function
133
       hetbond_count), this is better suitable for molecular statistics.
134
       ATTENTION: previously generated "fingerprints" in databases must be updated!
135
       improved recognition of non-conformant SD files (with missing "M  END" line)
136
 
137
v0.2k  changed quick_match routine to compare atom types only by element in
138
       order to avoid (rare) cases of non-matching identical input files;
139
       slightly changed error message for non-existant input files
140
 
141
v0.3   changed function update_Htotal in order to distinguish between 3-valent
142
       and 5-valent phosphorus (thanks to H. Feldman for this suggestion);
143
       added a table (array ringprop) to store ring sizes and aromaticity for
144
       faster lookup; changed aromaticity detection (chk_arom) to be fully
145
       independent of Kekule structures in condensed ring systems; changed add_ring
146
       to store new rings in ascending order (with respect to ring size): this
147
       will cause the aromaticity detection to start with smaller rings;
148
       added additional calls to chk_arom when in SSR ring search mode (to ensure
149
       that all aromatic rings are found); speeded up function is_newring;
150
       added option "-M": this restores the behavior of previous versions,
151
       i.e. metal atoms will be accepted as ring members (which costs a lot
152
       of performance for coordinate compounds like ferrocenes but gives
153
       only little useful information); when used in databases: use the _same_
154
       mode ("-M" or not) _both_ for checkmol (creation of fingerprints) and matchmol;
155
       fixed ugly linebreaks in show_usage;
156
 
157
v0.3a  fixed a bug in read_charges (which was introduced in the v0.3 code cleanup)
158
 
159
v0.3b  fixed recognition of ketenes, CO2, CS2, CSO, phosphines, boronic esters
160
 
161
v0.3c  fixed recognition of hydrazines, hydroxylamines, thiocarboxylic acids,
162
       orthocarboxylic acids; slightly changed textual output for a few functional
163
       groups
164
 
165
v0.3d  added bond topology feature ("any", "ring", "chain", as defined by MDL specs,
166
       plus "always_any", "excess-ringcount", "exact-ringcount") to bond properties
167
       and implemented its use for substructure searches, either as specified in the
168
       query MDL molfile or by using "strict" mode; added ring_count property to
169
       "bonds" section of Checkmol-tweaked molfiles (using an unused field in the MDL
170
       molfile specs);
171
       added option for E/Z isomer search, either globally (-g option) or per
172
       double bond: bstereo_xyz property, encoded either by a leading "0" in the
173
       bond block of a checkmol-tweaked molfile or by using the "stereo care" flag
174
       as defined in the MDL file specs (both atoms of a double bond must carry
175
       this flag)
176
 
177
v0.3e  fixed wrong position of "stereo care" flag expected in input molfile;
178
 
179
v0.3f  added option for enantiospecific search (R/S isomer search); this can be
180
       turned on either globally (-G option or using the "chiral" flag in the
181
       "counts line" of the query MDL molfile) or per atom (using - or abusing -
182
       the "stereo care" flag); enantiomers are compared using the 3D coordinates
183
       of the substituents at a chiral center, so we do not have to rely on the
184
       presence of correct "up" and "down" bond types in the candidate structures;
185
       nevertheless, "pseudo-3D" structures (i.e. flat 2D structures with "up"
186
       and "down" bond notation) can be also used, even in mixed mode both as
187
       query structure and candidate structure; added support for "up" and "down"
188
       bond notation in MDL molfile output (if -m option is used and these bond
189
       types were present in the input file); refined function find_ndl_ref_atom;
190
       fixed Alchemy atom type misinterpretation (upper/lower case mismatch);
191
 
192
v0.3g  minor fixes: recognition of sp2 nitrogen in N=N structures (function
193
       update_atypes); extended E/Z geometry check to C=N and N=N bonds; accelerated
194
       exact search by initial comparison of C,O,N counts; added meaningful error
195
       message for input structures with 0 (zero) atoms;
196
 
197
v0.3h  added a match matrix clean-up step to function is_matching in order to
198
       remove "impossible" multiple matches prior to chirality check; added
199
       function ndl_maybe_chiral as a plausibility check; added support for other
200
       atoms than carbon as chiral centers; changed function is_cis from a
201
       distance-based cis/trans check into a torsion-based check;
202
 
203
v0.3i  minor fixes in functions max_neighbors and chk_ammon;
204
       revert ringsearch_mode to its original value for each new molecule
205
       (main routine)
206
 
207
v0.3j  various improvements in checkmol: added alkenyl (vinyl) and alkynyl
208
       residues as possible substituents for amides, esters, ethers, etc.;
209
       extended recognition of orthocarboxylic acid derivatives; refined
210
       recognition of oxohetarenes and iminohetareenes, ureas, nitroso
211
       compounds; fixed reading of "old-style" charges from MDL files;
212
       refined aromaticity check; fixed a bug in procedure chk_arom and
213
       renamed function is_exocyclic_methylene_C into
214
       find_exocyclic_methylene_C; added assignment of pointers to "nil"
215
       after calling "freemem" in procedure zap_molecule and zap_needle;
216
       matchmol: refined selection of needle reference atom; added "strict
217
       chirality check" mode (if -x -s and -G options are used): returns
218
       "false" if a chiral or pseudochiral atom is matched against its
219
       counterpart with undefined or "flat" geometry; added an alternative
220
       selection mechanism for the needle reference atom, based on the
221
       Morgan algorithm;
222
 
223
v0.3k  improved matching of nitro compounds (ionic vs. non-ionic
224
       representation); some finetuning in recognition of N-oxides,
225
       hydroxylamines, etc.; modified get_molstat in order to ignore
226
       charges in nitro groups, N-oxides, sulfoxides, azides, etc. in
227
       ionic representation; added function normalize_ionic_bonds;
228
       fixed a bug in is_alkenyl; fixed a bug (introduced in v0.3j) in
229
       the treatment of "old-style" MDL charges;
230
 
231
v0.3l  minor adjustments in quick_match (for unknown atom types,
232
       opposite charges); some performance improvements, e.g. in function
233
       path_pos, reduced extensive calls to is_heavyatom and is_metal
234
       by extending atom_rec with boolean fields 'heavy' and 'metal'
235
       (thanks to E.-G.Schmid); added molstat field n_rBz (number of
236
       benzene rings; deactivated by default); added -l command-line
237
       option to checkmol (lists all molstat codes with a short
238
       explanation); added graceful handling of NoStruct (i.e.,
239
       zero-atom) molecules
240
 
241
v0.3m  minor bug fixes (chk_imine), let normalize_ionic_bonds return "true"
242
       if some bond-order change was made; fixed incorrect implementation
243
       of the Morgan algorithm (thanks to H.Feldman), fixed is_matching in
244
       order to prevent wrong matches of larger rings on smaller ones; count
245
       halogens also as type "X" in molstat (as before v0.3l); added some more
246
       molstat descriptors for most elements (deactivated by default; for
247
       activation, uncomment the definition of "extended_molstat", see below);
248
       added support for the generation of binary fingerprints with output
249
       either as boolean values (-f option) or as decimal values (-F option),
250
       fingerprint patterns are supplied by the user (in SDF format, max. 62
251
       structures per file); added a version check ("tweaklevel",
252
       ringsearch_mode, opt_metalrings) for "tweaked" MDL molfiles
253
 
254
v0.3n  increased max_vringsize in SSR mode from 10 to 12 (now defined in
255
       ssr_vringsize); optionally changed ring statistics to ignore envelope
256
       rings (which completely contain another ring, "reduced SAR") in order to
257
       make molstat in SAR and SSR mode more compatible) - disabled by default;
258
       introduced a new molstat descriptor: n_br2p (number of bonds which
259
       belong to two or more rings); changed n_b1 counter to ignore bonds to
260
       explicit hydrogens; added procedure fix_ssr_ringcounts
261
       (see comment in the code); added bond property mdl_stereo for preservation
262
       of original value; slightly changed "get_molstat" and "update_atypes" in
263
       order to consolidate atom type for various N atoms; remember "chiral" flag
264
       status in molfile output (-m); modified chk_arom in order to accept rings
265
       as aromatic if all bonds are of type 'A'; several minor bug fixes
266
 
267
v0.3o  minor changes in update_atypes (nitrogen); changed the matching
268
       algorithm in order to take care of disconnected molecular graphs
269
       (e.g., salts); refined matching of atoms with formal charges
270
 
271
Credits:
272
 
273
Rami Jbara (rami_jbara@hotmail.com) designed the 8-character functional
274
group codes.
275
 
276
I am also very grateful to Ernst-Georg Schmid (Bayer Business Services,
277
Leverkusen/Germany) and to Howard Feldman (The Blueprint Initiative,
278
Toronto/Canada) for numerous bug reports and suggestions for improvements.
279
 
280
===============================================================================
281
DISCLAIMER
282
This program is free software; you can redistribute it and/or
283
modify it under the terms of the GNU General Public License
284
as published by the Free Software Foundation; either version 2
285
of the License, or (at your option) any later version.
286
 
287
This program is distributed in the hope that it will be useful,
288
but WITHOUT ANY WARRANTY; without even the implied warranty of
289
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
290
GNU General Public License for more details.
291
 
292
You should have received a copy of the GNU General Public License
293
along with this program; if not, write to the Free Software Foundation,
294
Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
295
===============================================================================
296
*/
297
 
298
/* $DEFINE debug                    uncomment if desired */
299
/* $DEFINE extended_molstat         uncomment if desired */
300
/* $DEFINE reduced_SAR              uncomment if desired */
301
 
302
/* uses
303
  SYSUTILS, MATH; */
304
 
305
#include <stdlib.h>
306
#include <stdio.h>
307
#include <math.h>
308
#include <string.h>
309
#include <ctype.h>
310
#include <sys/types.h>
311
#include <sys/stat.h>
312
#include "safemem.h"
313
#ifdef MAKE_SHARED_LIBRARY
314
#include "barsoi.h"
315
#endif
316
 
317
#ifdef MAKE_SHARED_LIBRARY
318
#define version         "0.3p C (pgchem::barsoi)"
319
#else
320
#define version         "0.3p C"
321
#endif
322
 
323
#undef REDUCED_SAR
324
 
325
/* How many recursions before aborting is_ringpath and reverting to SSR */
326
#define max_ringpath_recursion_depth   500000
327
 
328
/* How many recursions before aborting is_match and reverting to non-exhaustive match */
329
#define max_match_recursion_depth   500000
330
 
331
#define tweaklevel      2
332
    /* v0.3m; accept tweaks in MDL molfiles only if same level */
333
#define max_atoms       1024
334
#define max_bonds       1024
335
#define slack           8192
336
#define max_ringsize    128
337
#define max_rings       1024
338
#define max_fg          256
339
#define max_neighbors   16      /* new in v0.2h */
340
 
341
#define TAB             '\t'
342
 
343
#define max_matchpath_length  256
344
#define pmCheckMol      1001
345
#define pmMatchMol      1002
346
 
347
#define rs_sar          2001    /* ring search mode: SAR = set of all rings */
348
#define rs_ssr          2002
349
    /*                   SSR = set of small rings */
350
 
351
#define btopo_any       0       /* bond topology, new in v0.3d */
352
#define btopo_ring      1
353
#define btopo_chain     2
354
#define btopo_always_any  3     /* even in "strict mode" */
355
#define btopo_excess_rc  4
356
/* bond in candidate must be included in _more_ rings than
357
                        the matching bond in the query ==> specific search for
358
                        annulated systems */
359
#define btopo_exact_rc  5
360
    /* bond in query and candidate must have same ring count */
361
 
362
#define bstereo_any     0
363
    /* new in v0.3d, any E/Z isomer matches (for double bonds) */
364
#define bstereo_xyz     1
365
    /* E/Z match is checked by using XYZ coordinates of the atoms */
366
#define bstereo_up      11      /* new in v0.3f, flags for single bonds */
367
#define bstereo_down    16
368
#define bstereo_either    14    /* 0.3x */
369
#define bstereo_double_either    13     /* 0.3x */
370
 
371
#define fpf_boolean     3001
372
    /* v0.3m; format for fingerprint output (n:T, n:F) */
373
#define fpf_decimal     3002
374
    /* v0.3m; format for fingerprint output as decimal value of bitstring */
375
#define fp_blocksize    62
376
    /* v0.3m; 1 bit may be used for sign (e.g. by PHP), 1 bit for "exact hit" */
377
#define ssr_vringsize   12      /* v0.3n; max. ring size in SSR mode */
378
 
379
/* Definitions for functional groups: */
380
#define fg_cation       1
381
#define fg_anion        2
382
#define fg_carbonyl     3
383
#define fg_aldehyde     4
384
#define fg_ketone       5
385
#define fg_thiocarbonyl  6
386
#define fg_thioaldehyde  7
387
#define fg_thioketone   8
388
#define fg_imine        9
389
#define fg_hydrazone    10
390
#define fg_semicarbazone  11
391
#define fg_thiosemicarbazone  12
392
#define fg_oxime        13
393
#define fg_oxime_ether  14
394
#define fg_ketene       15
395
#define fg_ketene_acetal_deriv  16
396
#define fg_carbonyl_hydrate  17
397
#define fg_hemiacetal   18
398
#define fg_acetal       19
399
#define fg_hemiaminal   20
400
#define fg_aminal       21
401
#define fg_thiohemiaminal  22
402
#define fg_thioacetal   23
403
#define fg_enamine      24
404
#define fg_enol         25
405
#define fg_enolether    26
406
#define fg_hydroxy      27
407
#define fg_alcohol      28
408
#define fg_prim_alcohol  29
409
#define fg_sec_alcohol  30
410
#define fg_tert_alcohol  31
411
#define fg_1_2_diol     32
412
#define fg_1_2_aminoalcohol  33
413
#define fg_phenol       34
414
#define fg_1_2_diphenol  35
415
#define fg_enediol      36
416
#define fg_ether        37
417
#define fg_dialkylether  38
418
#define fg_alkylarylether  39
419
#define fg_diarylether  40
420
#define fg_thioether    41
421
#define fg_disulfide    42
422
#define fg_peroxide     43
423
#define fg_hydroperoxide  44
424
#define fg_hydrazine    45
425
#define fg_hydroxylamine  46
426
#define fg_amine        47
427
#define fg_prim_amine   48
428
#define fg_prim_aliph_amine  49
429
#define fg_prim_arom_amine  50
430
#define fg_sec_amine    51
431
#define fg_sec_aliph_amine  52
432
#define fg_sec_mixed_amine  53
433
#define fg_sec_arom_amine  54
434
#define fg_tert_amine   55
435
#define fg_tert_aliph_amine  56
436
#define fg_tert_mixed_amine  57
437
#define fg_tert_arom_amine  58
438
#define fg_quart_ammonium  59
439
#define fg_n_oxide      60
440
#define fg_halogen_deriv  61
441
#define fg_alkyl_halide  62
442
#define fg_alkyl_fluoride  63
443
#define fg_alkyl_chloride  64
444
#define fg_alkyl_bromide  65
445
#define fg_alkyl_iodide  66
446
#define fg_aryl_halide  67
447
#define fg_aryl_fluoride  68
448
#define fg_aryl_chloride  69
449
#define fg_aryl_bromide  70
450
#define fg_aryl_iodide  71
451
#define fg_organometallic  72
452
#define fg_organolithium  73
453
#define fg_organomagnesium  74
454
#define fg_carboxylic_acid_deriv  75
455
#define fg_carboxylic_acid  76
456
#define fg_carboxylic_acid_salt  77
457
#define fg_carboxylic_acid_ester  78
458
#define fg_lactone      79
459
#define fg_carboxylic_acid_amide  80
460
#define fg_carboxylic_acid_prim_amide  81
461
#define fg_carboxylic_acid_sec_amide  82
462
#define fg_carboxylic_acid_tert_amide  83
463
#define fg_lactam       84
464
#define fg_carboxylic_acid_hydrazide  85
465
#define fg_carboxylic_acid_azide  86
466
#define fg_hydroxamic_acid  87
467
#define fg_carboxylic_acid_amidine  88
468
#define fg_carboxylic_acid_amidrazone  89
469
#define fg_nitrile      90
470
#define fg_acyl_halide  91
471
#define fg_acyl_fluoride  92
472
#define fg_acyl_chloride  93
473
#define fg_acyl_bromide  94
474
#define fg_acyl_iodide  95
475
#define fg_acyl_cyanide  96
476
#define fg_imido_ester  97
477
#define fg_imidoyl_halide  98
478
#define fg_thiocarboxylic_acid_deriv  99
479
#define fg_thiocarboxylic_acid  100
480
#define fg_thiocarboxylic_acid_ester  101
481
#define fg_thiolactone  102
482
#define fg_thiocarboxylic_acid_amide  103
483
#define fg_thiolactam   104
484
#define fg_imido_thioester  105
485
#define fg_oxohetarene  106
486
#define fg_thioxohetarene  107
487
#define fg_iminohetarene  108
488
#define fg_orthocarboxylic_acid_deriv  109
489
#define fg_carboxylic_acid_orthoester  110
490
#define fg_carboxylic_acid_amide_acetal  111
491
#define fg_carboxylic_acid_anhydride  112
492
#define fg_carboxylic_acid_imide  113
493
#define fg_carboxylic_acid_unsubst_imide  114
494
#define fg_carboxylic_acid_subst_imide  115
495
#define fg_co2_deriv    116
496
#define fg_carbonic_acid_deriv  117
497
#define fg_carbonic_acid_monoester  118
498
#define fg_carbonic_acid_diester  119
499
#define fg_carbonic_acid_ester_halide  120
500
#define fg_thiocarbonic_acid_deriv  121
501
#define fg_thiocarbonic_acid_monoester  122
502
#define fg_thiocarbonic_acid_diester  123
503
#define fg_thiocarbonic_acid_ester_halide  124
504
#define fg_carbamic_acid_deriv  125
505
#define fg_carbamic_acid  126
506
#define fg_carbamic_acid_ester  127
507
#define fg_carbamic_acid_halide  128
508
#define fg_thiocarbamic_acid_deriv  129
509
#define fg_thiocarbamic_acid  130
510
#define fg_thiocarbamic_acid_ester  131
511
#define fg_thiocarbamic_acid_halide  132
512
#define fg_urea         133
513
#define fg_isourea      134
514
#define fg_thiourea     135
515
#define fg_isothiourea  136
516
#define fg_guanidine    137
517
#define fg_semicarbazide  138
518
#define fg_thiosemicarbazide  139
519
#define fg_azide        140
520
#define fg_azo_compound  141
521
#define fg_diazonium_salt  142
522
#define fg_isonitrile   143
523
#define fg_cyanate      144
524
#define fg_isocyanate   145
525
#define fg_thiocyanate  146
526
#define fg_isothiocyanate  147
527
#define fg_carbodiimide  148
528
#define fg_nitroso_compound  149
529
#define fg_nitro_compound  150
530
#define fg_nitrite      151
531
#define fg_nitrate      152
532
#define fg_sulfuric_acid_deriv  153
533
#define fg_sulfuric_acid  154
534
#define fg_sulfuric_acid_monoester  155
535
#define fg_sulfuric_acid_diester  156
536
#define fg_sulfuric_acid_amide_ester  157
537
#define fg_sulfuric_acid_amide  158
538
#define fg_sulfuric_acid_diamide  159
539
#define fg_sulfuryl_halide  160
540
#define fg_sulfonic_acid_deriv  161
541
#define fg_sulfonic_acid  162
542
#define fg_sulfonic_acid_ester  163
543
#define fg_sulfonamide  164
544
#define fg_sulfonyl_halide  165
545
#define fg_sulfone      166
546
#define fg_sulfoxide    167
547
#define fg_sulfinic_acid_deriv  168
548
#define fg_sulfinic_acid  169
549
#define fg_sulfinic_acid_ester  170
550
#define fg_sulfinic_acid_halide  171
551
#define fg_sulfinic_acid_amide  172
552
#define fg_sulfenic_acid_deriv  173
553
#define fg_sulfenic_acid  174
554
#define fg_sulfenic_acid_ester  175
555
#define fg_sulfenic_acid_halide  176
556
#define fg_sulfenic_acid_amide  177
557
#define fg_thiol        178
558
#define fg_alkylthiol   179
559
#define fg_arylthiol    180
560
#define fg_phosphoric_acid_deriv  181
561
#define fg_phosphoric_acid  182
562
#define fg_phosphoric_acid_ester  183
563
#define fg_phosphoric_acid_halide  184
564
#define fg_phosphoric_acid_amide  185
565
#define fg_thiophosphoric_acid_deriv  186
566
#define fg_thiophosphoric_acid  187
567
#define fg_thiophosphoric_acid_ester  188
568
#define fg_thiophosphoric_acid_halide  189
569
#define fg_thiophosphoric_acid_amide  190
570
#define fg_phosphonic_acid_deriv  191
571
#define fg_phosphonic_acid  192
572
#define fg_phosphonic_acid_ester  193
573
#define fg_phosphine    194
574
#define fg_phosphinoxide  195
575
#define fg_boronic_acid_deriv  196
576
#define fg_boronic_acid  197
577
#define fg_boronic_acid_ester  198
578
#define fg_alkene       199
579
#define fg_alkyne       200
580
#define fg_aromatic     201
581
#define fg_heterocycle  202
582
#define fg_alpha_aminoacid  203
583
#define fg_alpha_hydroxyacid  204
584
 
585
typedef enum
14179 bpr 586
  { false = 0, true } boolean;
6785 bpr 587
 
588
typedef char str2[3];
589
 
590
typedef char str3[4];
591
 
592
typedef char str4[5];
593
 
594
typedef char str5[6];
595
 
596
typedef char str8[9];
597
 
598
typedef struct atom_rec
599
{
600
  str2 element;
601
  str3 atype;
602
  float x, y, z;
603
  int formal_charge;
604
  float real_charge;
14179 bpr 605
  int Hexp;      /* explicit H count */
606
  int Htot;      /* total H count */
6785 bpr 607
  int neighbor_count, ring_count;
14179 bpr 608
  boolean arom, stereo_care;  /* new in v0.3d */
609
  boolean q_arom;    // v0.3p potentially aromatic in a query structure
610
  boolean heavy;    /* new in v0.3l */
611
  boolean metal;    /* new in v0.3l */
612
  int nvalences;    /* new in v0.3m */
613
  boolean tag;      /* new in v0.3o */
614
  int nucleon_number;   /* 0.3.x */
6785 bpr 615
  int radical_type;             /* 0.3.x */
616
} atom_rec;
617
 
618
typedef struct bond_rec
619
{
620
  int a1, a2;
621
  char btype;
622
  int ring_count;
623
  boolean arom;
14179 bpr 624
  boolean q_arom;    // v0.3p potentially aromatic in a query structure
625
  int topo;      /* new in v0.3d, see MDL file description */
626
  int stereo;    /* new in v0.3d */
627
  int mdl_stereo;/* new in v0.3n */
6785 bpr 628
} bond_rec;
629
 
630
typedef int ringpath_type[max_ringsize];
631
typedef int matchpath_type[max_matchpath_length];
632
 
633
typedef atom_rec atomlist[max_atoms];
634
typedef bond_rec bondlist[max_bonds];
635
typedef ringpath_type ringlist[max_rings];
14179 bpr 636
typedef int neighbor_rec[max_neighbors];  /* new in v0.2h */
6785 bpr 637
typedef boolean fglist[max_fg];
638
 
639
typedef char molbuftype[max_atoms + max_bonds + slack][256];
640
 
641
typedef boolean matchmatrix[max_neighbors][max_neighbors];
642
    /* new in v0.2i */
643
 
644
typedef struct molstat_rec
645
{
14179 bpr 646
  int n_QA, n_QB, n_chg;  /* number of query atoms, query bonds, charges */
6785 bpr 647
  int n_C1, n_C2, n_C;
648
  /* number of sp, sp2 hybridized, and total no. of carbons */
649
  int n_CHB1p, n_CHB2p, n_CHB3p, n_CHB4;
650
  /* number of C atoms with at least 1, 2, 3 hetero bonds */
14179 bpr 651
  int n_O2, n_O3;    /* number of sp2 and sp3 oxygens */
652
  int n_N1, n_N2, n_N3;    /* number of sp, sp2, and sp3 nitrogens */
6785 bpr 653
  int n_S, n_SeTe;
654
  /* number of sulfur atoms and selenium or tellurium atoms */
655
  int n_F, n_Cl, n_Br, n_I;
656
  /* number of fluorine, chlorine, bromine, iodine atoms */
14179 bpr 657
  int n_P, n_B;      /* number of phosphorus and boron atoms */
6785 bpr 658
  int n_Met, n_X;
659
  /* number of metal and "other" atoms (not listed elsewhere); v0.3l */
660
  int n_b1, n_b2, n_b3, n_bar;
661
  /* number single, double, triple, and aromatic bonds */
662
  int n_C1O, n_C2O, n_CN, n_XY;
663
  /* number of C-O single bonds, C=O double bonds, CN bonds (any type), hetero/hetero bonds */
664
  int n_r3, n_r4, n_r5, n_r6, n_r7, n_r8;
665
  /* number of 3-, 4-, 5-, 6-, 7-, and 8-membered rings */
666
  int n_r9, n_r10, n_r11, n_r12, n_r13p;
667
  /* number of 9-, 10-, 11-, 12-, and 13plus-membered rings */
668
  int n_rN, n_rN1, n_rN2, n_rN3p;
669
  /* number of rings containing N (any number), 1 N, 2 N, and 3 N or more */
670
  int n_rO, n_rO1, n_rO2p;
671
  /* number of rings containing O (any number), 1 O, and 2 O or more */
672
  int n_rS, n_rX, n_rAr, n_rBz;
673
  /* number of rings containing S (any number), any heteroatom (any number),  */
674
  /* number of aromatic rings, number of benzene rings */
14179 bpr 675
  int n_br2p;      /* number of bonds belonging to more than one ring (v0.3n) */
676
  /* p2c: checkmol.pas, line 590:
677
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 678
  /*$IFDEF extended_molstat */
679
  int n_psg01, n_psg02, n_psg13, n_psg14;
680
  /* number of atoms belonging to elements of group 1, 2, etc.  */
681
  int n_psg15, n_psg16, n_psg17, n_psg18;
682
  /* number of atoms belonging to elements of group 15, 16, etc.  */
683
  int n_pstm, n_psla;
684
  /* number of transition metals, lanthanides/actinides */
685
  int n_iso, n_rad;
686
  /* number of isotopes, radicals */
687
  /*$ENDIF */
688
} molstat_rec;
689
 
690
typedef struct ringprop_rec
691
{
692
  /* new in v0.3 */
693
  int size;
694
  boolean arom, envelope;
695
} ringprop_rec;
696
 
697
typedef ringprop_rec ringprop_type[max_rings];
698
 
699
typedef struct p_3d
700
{
701
  /* new in v0.3d */
702
  double x, y, z;
703
} p_3d;
704
 
14179 bpr 705
typedef int chirpath_type[4];  /* new in v0.3f */
6785 bpr 706
 
707
#ifdef MAKE_SHARED_LIBRARY
708
static boolean yet_initialized = false;
709
#endif
710
 
711
typedef struct connval_rec
712
{
713
  /* new in v0.3j */
14179 bpr 714
  int def;      /* better as longint for large molecules? */
6785 bpr 715
  int tmp;
716
} connval_rec;
717
 
14179 bpr 718
typedef connval_rec connval_type[max_atoms];  /* new in v0.3j  */
6785 bpr 719
 
720
static int progmode;
721
static char progname[256];
722
 
723
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 724
static int i;      /* general purpose index */
6785 bpr 725
#endif
726
 
727
static int li;
728
static boolean opt_none, opt_verbose, opt_text, opt_text_de, opt_code,
729
  opt_bin, opt_bitstring, opt_stdin, opt_exact, opt_debug,
730
  opt_molout, opt_molstat, opt_molstat_X, opt_xmdlout, opt_strict;
731
    /* new in v0.2f */
14179 bpr 732
static boolean opt_metalrings;  /* new in v0.3 */
733
static boolean opt_geom;  /* new in v0.3d */
734
static boolean opt_chiral;  /* new in v0.3f */
735
static boolean opt_iso;    /* new in v0.3x */
736
static boolean opt_chg;    /* new in v0.3x */
737
static boolean opt_rad;    /* new in v0.3x */
738
static int opt_rs;    /* new in v0.3i */
6785 bpr 739
 
740
#ifdef MAKE_SHARED_LIBRARY
741
static int opt_rs_dll = RPA_DEFAULT;
742
#endif
743
 
14179 bpr 744
static boolean opt_fp;    /* new in v0.3m */
745
static int fpformat;    /* new in v0.3m */
6785 bpr 746
static char filetype[256];
747
/*molfile : text; */
748
static char molfilename[256];
749
static char ndl_molfilename[256];
750
static char molname[256];
751
static char ndl_molname[256];
14179 bpr 752
static char tmp_molname[256];  /* v0.3m */
6785 bpr 753
static char molcomment[256];
754
static int n_atoms, n_bonds, n_rings;
755
    /* the number of rings we determined ourselves */
756
static int n_countablerings;
757
    /* v0.3n; number of rings which are not envelope rings */
758
static int n_cmrings;
759
    /* the number of rings we read from a (CheckMol-tweaked) MDL molfile */
760
//static int n_charges;         /* number of charges */
761
static int n_heavyatoms, n_heavybonds, ndl_n_atoms, ndl_n_bonds, ndl_n_rings,
762
  ndl_n_heavyatoms, ndl_n_heavybonds;
763
/*cm_mdlmolfile  : boolean; */
764
static boolean found_arominfo, found_querymol, ndl_querymol;
14179 bpr 765
static int tmp_n_atoms;    /* v0.3m */
766
static int tmp_n_bonds;    /* v0.3m */
767
static int tmp_n_rings;    /* v0.3m */
768
static int tmp_n_heavyatoms;  /* v0.3m */
769
static int tmp_n_heavybonds;  /* v0.3m */
6785 bpr 770
 
771
static atom_rec *atom;
772
static bond_rec *bond;
773
static ringpath_type *ring;
14179 bpr 774
static ringprop_rec *ringprop;  /* new in v0.3 */
6785 bpr 775
 
776
static atom_rec *ndl_atom;
777
static bond_rec *ndl_bond;
778
static ringpath_type *ndl_ring;
14179 bpr 779
static ringprop_rec *ndl_ringprop;  /* new in v0.3 */
780
static int ndl_ref_atom;  /* since v0.3j as a global variable */
781
static atom_rec *tmp_atom;  /* v0.3m */
782
static bond_rec *tmp_bond;  /* v0.3m */
783
static ringpath_type *tmp_ring;  /* v0.3m */
784
static ringprop_rec *tmp_ringprop;  /* v0.3m */
6785 bpr 785
 
14179 bpr 786
static boolean matchresult, matchsummary;  /* v0.3o */
6785 bpr 787
static matchpath_type ndl_matchpath, hst_matchpath;
788
 
789
static fglist fg;
790
static str4 atomtype;
791
static str3 newatomtype;
792
 
793
static char (*molbuf)[256];
794
static int molbufindex;
795
 
796
static boolean mol_in_queue;
797
static int mol_count;
798
 
14179 bpr 799
static molstat_rec molstat, ndl_molstat, tmp_molstat;  /* v0.3m */
6785 bpr 800
 
14179 bpr 801
static int ringsearch_mode, max_vringsize;  /* for SSR ring search */
6785 bpr 802
 
803
static FILE *rfile;
14179 bpr 804
static boolean rfile_is_open, mol_OK;  /* new in v0.2i */
6785 bpr 805
 
14179 bpr 806
static int n_ar;    /* new in v0.3 */
807
static int prev_n_ar;    /* new in v0.3 */
808
static boolean ez_search;  /* new in v0.3d */
809
static boolean rs_search;  /* new in v0.3f */
810
static boolean ez_flag;    /* new in v0.3f */
811
static boolean chir_flag;  /* new in v0.3f */
812
static boolean rs_strict;  /* new in v0.3j */
6785 bpr 813
 
14179 bpr 814
static int n_Ctot, n_Otot, n_Ntot;  /* new in v0.3g */
815
static int ndl_n_Ctot, ndl_n_Otot, ndl_n_Ntot;  /* new in v0.3g */
816
static int tmp_n_Ctot, tmp_n_Otot, tmp_n_Ntot;  /* new in v0.3m */
817
static boolean ether_generic;  /* v0.3j */
818
static boolean amine_generic;  /* v0.3j   */
819
static boolean hydroxy_generic;  /* v0.3j */
820
static connval_rec *cv;    /* new in v0.3j */
821
static long long fpdecimal;  /* v0.3m */
6785 bpr 822
static long long fpincrement;
823
static int fpindex;
824
static boolean fp_exacthit, fp_exactblock;
825
static int tmfcode;
826
    /* v0.3m; version number for tweaked MDL molfiles (tweaklevel) */
827
static boolean tmfmismatch;
828
    /* v0.3m; rely on tweaked MDL molfiles only if same level */
829
static boolean auto_ssr;
830
    /* v0.3n; indicates that SAR -> SSR fallback has happened */
831
static int recursion_depth;
832
    /* ====================emulated pascal functions============================ */
833
 
834
static boolean
835
file_exists (const char *fileName)
836
{
837
  struct stat filestat;
838
 
839
  return stat (fileName, &filestat) == 0 ? true : false;
840
}
841
 
14179 bpr 842
static void lblank (int cols, char *nstr)
6785 bpr 843
{
844
  /* inserts leading blanks up to a given number of total characters */
845
  char STR1[256];
846
 
847
  if (strlen (nstr) >= cols)
848
    return;
849
  while (strlen (nstr) < cols)
850
    sprintf (nstr, " %s", strcpy (STR1, nstr));
851
}
852
 
14179 bpr 853
static inline double radtodeg (double rads)
6785 bpr 854
{
855
  return (180.0 / M_PI) * rads;
856
}
857
 
14179 bpr 858
static void strdelete (char *s, int pos, int len)
6785 bpr 859
{
860
  int slen;
861
 
862
  if (--pos < 0)
863
    return;
864
  slen = strlen (s) - pos;
865
  if (slen <= 0)
866
    return;
867
  s += pos;
14179 bpr 868
  if (slen <= len) {
869
    *s = 0;
870
    return;
871
  }
6785 bpr 872
  while ((*s = s[len]))
873
    s++;
874
}
875
 
14179 bpr 876
static int strpos2 (char *s, char *pat, int pos)
6785 bpr 877
{
878
  char *cp, ch;
879
  int slen;
880
 
881
  if (--pos < 0)
882
    return 0;
883
  slen = strlen (s) - pos;
884
  cp = s + pos;
885
  if (!(ch = *pat++))
886
    return 0;
887
  pos = strlen (pat);
888
  slen -= pos;
14179 bpr 889
  while (--slen >= 0) {
890
    if (*cp++ == ch && !strncmp (cp, pat, pos))
891
      return cp - s;
892
  }
6785 bpr 893
  return 0;
894
}
895
 
14179 bpr 896
static char * strsub (char *ret, char *s, int pos, int len)
6785 bpr 897
{
898
  char *s2;
899
 
14179 bpr 900
  if (--pos < 0 || len <= 0){
901
    *ret = 0;
902
    return ret;
903
  }
904
  while (pos > 0){
905
    if (!*s++){
6785 bpr 906
      *ret = 0;
907
      return ret;
908
    }
14179 bpr 909
    pos--;
910
  }
6785 bpr 911
  s2 = ret;
14179 bpr 912
  while (--len >= 0){
913
    if (!(*s2++ = *s++))
914
      return ret;
915
  }
6785 bpr 916
  *s2 = 0;
917
  return ret;
918
}
919
 
920
/*============================= auxiliary functions & procedures */
921
 
14179 bpr 922
inline static void all_lowercase (char *astring)
6785 bpr 923
{
924
  int i;
925
  int l = strlen (astring);
926
 
14179 bpr 927
  for (i = 0; i < l; i++){
928
    astring[i] = tolower (astring[i]);
929
  }
6785 bpr 930
}
931
 
14179 bpr 932
static void init_globals ()
6785 bpr 933
{
934
  /*int i;*/
935
 
936
  opt_verbose = false;
937
  opt_debug = false;
938
  opt_exact = false;
939
  opt_stdin = false;
940
  opt_text = false;
941
  opt_code = false;
942
  opt_bin = false;
943
  opt_bitstring = false;
944
  opt_molout = false;
945
  opt_molstat = false;
946
  opt_molstat_X = false;
947
  opt_xmdlout = false;
14179 bpr 948
  opt_strict = false; /* new in v0.2f */
949
  opt_metalrings = false;  /* new in v0.3 */
950
  opt_geom = false;   /* new in v0.3d */
951
  opt_chiral = false; /* new in v0.3f */
952
  opt_fp = false;     /* new in v0.3m */
953
  opt_iso = false;    /* new in v0.3x */
954
  opt_chg = false;    /* new in v0.3x */
955
  opt_rad = false;    /* new in v0.3x */
6785 bpr 956
  /*cm_mdlmolfile   := false; */
957
  found_arominfo = false;
958
  found_querymol = false;
959
  ndl_querymol = false;
14179 bpr 960
  opt_rs = rs_sar;    /* v0.3i */
6785 bpr 961
  /*ringsearch_mode := rs_sar; */
14179 bpr 962
  rfile_is_open = false;/* new in v0.2g */
963
  ez_search = false;    /* new in v0.3d */
964
  rs_search = false;    /* new in v0.3f */
965
  ez_flag = false;      /* new in v0.3f */
966
  chir_flag = false;    /* new in v0.3f */
967
  rs_strict = false;    /* new in v0.3j */
6785 bpr 968
  n_Ctot = 0;
969
  n_Otot = 0;
14179 bpr 970
  n_Ntot = 0;      /* new in v0.3g */
6785 bpr 971
  ndl_n_Ctot = 0;
972
  ndl_n_Otot = 0;
14179 bpr 973
  ndl_n_Ntot = 0;   /* new in v0.3g */
6785 bpr 974
  //for (i = 0; i < max_fg; i++)
975
  //  fg[i] = false;
976
  memset (fg, 0, sizeof (fglist));
977
  /*try */
978
  molbuf = safe_malloc (sizeof (molbuftype));
979
  /*except
980
     on e:Eoutofmemory do
981
     begin
982
     writeln('Not enough memory');
983
     halt(4);
984
     end;
985
     end; */
14179 bpr 986
  ether_generic = false;  /* v0.3j */
987
  amine_generic = false;  /* v0.3j */
988
  hydroxy_generic = false;/* v0.3j */
989
  fpformat = fpf_decimal; /* v0.3m */
990
  fpindex = 0;            /* v0.3m */
991
  fp_exacthit = false;    /* v0.3m */
992
  fp_exactblock = false;  /* v0.3m */
993
  tmfcode = 0;            /* v0.3m */
994
  tmfmismatch = false;    /* v0.3m */
995
  auto_ssr = false;       /* v0.3n */
6785 bpr 996
  recursion_depth = 0;
997
}
998
 
14179 bpr 999
static inline void init_molstat (mstat)
6785 bpr 1000
     molstat_rec *mstat;
1001
{
1002
  /*
1003
     with mstat do
1004
     begin
1005
     n_QA := 0; n_QB := 0; n_chg := 0;
1006
     n_C1 := 0; n_C2 := 0; n_C  := 0;
1007
     n_CHB1p := 0; n_CHB2p := 0; n_CHB3p := 0; n_CHB4 := 0;
1008
     n_O2 := 0; n_O3  := 0;
1009
     n_N1 := 0; n_N2 := 0; n_N3 := 0;
1010
     n_S := 0; n_SeTe := 0;
1011
     n_F := 0; n_Cl := 0; n_Br := 0; n_I := 0;
1012
     n_P := 0; n_B := 0;
1013
     n_Met := 0; n_X := 0;
1014
     n_b1 := 0; n_b2 := 0; n_b3 := 0; n_bar := 0;
1015
     n_C1O := 0; n_C2O := 0; n_CN := 0; n_XY := 0;
1016
     n_r3 := 0; n_r4 := 0; n_r5 := 0; n_r6 := 0; n_r7 := 0;
1017
     n_r8 := 0; n_r9 := 0; n_r10 := 0; n_r11 := 0; n_r12 := 0; n_r13p := 0;
1018
     n_rN := 0; n_rN1 := 0; n_rN2 := 0; n_rN3p := 0;
1019
     n_rO := 0; n_rO1 := 0; n_rO2p := 0;
1020
     n_rS := 0; n_rX := 0;
1021
     n_rAr := 0; n_rBz := 0; n_br2p := 0;
1022
     end;
1023
   */
14179 bpr 1024
  memset (mstat, 0, sizeof (molstat_rec));  /* v0.3k */
6785 bpr 1025
}
1026
 
1027
#if 0
14179 bpr 1028
static void debugoutput (dstr)
1029
  char *dstr;
6785 bpr 1030
{
1031
  if (opt_debug)
1032
    printf ("%s\n", dstr);
1033
}
1034
#endif
1035
 
14179 bpr 1036
static void left_trim (trimstr)
1037
  char *trimstr;
6785 bpr 1038
{
1039
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1040
    strdelete (trimstr, 1, 1);
1041
}
14626 bpr 1042
/* left_int fixed by D. Bernardi (2020-02-01) */
1043
static int left_int (char *trimstr)
6785 bpr 1044
{
14626 bpr 1045
  char *s = trimstr;
1046
  int r = 0;
1047
  int sg = 1;
6785 bpr 1048
 
14626 bpr 1049
  while (*s == ' ' || *s == '\t' || *s == '+' || *s == '-')
1050
    {if (*s == '-') sg = -sg; s++;}
1051
  while (*s >= '0' && *s <= '9')
1052
    r = 10*r + *s++ - '0';
1053
  while ((*trimstr++ = *s++)); /* gag! */
1054
  return sg * r;
6785 bpr 1055
}
1056
 
14179 bpr 1057
static int path_pos (int id, int *a_path)
6785 bpr 1058
{
1059
  int i = 0;
1060
 
14179 bpr 1061
  for (i = 0; i < max_ringsize; i++){
1062
    if (*(a_path++) == id) {
1063
      return ++i;
6785 bpr 1064
    }
14179 bpr 1065
  }
6785 bpr 1066
  return 0;
1067
}
1068
 
14179 bpr 1069
static int path_length (int *a_path)
6785 bpr 1070
{
1071
  if ((a_path[max_ringsize - 1] != 0) && (path_pos (0, a_path) == 0))
1072
    return max_ringsize;
1073
  else
1074
    return (path_pos (0, a_path) - 1);
1075
}
1076
 
14179 bpr 1077
static int get_bond (int ba1, int ba2)
6785 bpr 1078
{
1079
  int i;
1080
  int b_id = 0;
1081
  int FORLIM;
1082
 
1083
  if (n_bonds <= 0)
1084
    return b_id;
1085
  FORLIM = n_bonds;
14179 bpr 1086
  for (i = 1; i <= FORLIM; i++) {
1087
    if ((bond[i - 1].a1 == ba1 && bond[i - 1].a2 == ba2) ||
1088
      (bond[i - 1].a1 == ba2 && bond[i - 1].a2 == ba1))
1089
      b_id = i;
1090
  }
6785 bpr 1091
  return b_id;
1092
}
1093
 
14179 bpr 1094
static void clear_atom_tags ()
6785 bpr 1095
{
1096
  int i, FORLIM;
1097
 
14179 bpr 1098
  if (n_atoms > 0) {
1099
    FORLIM = n_atoms;
1100
    for (i = 0; i < FORLIM; i++)
1101
      atom[i].tag = false;
1102
  }
6785 bpr 1103
}
1104
 
1105
#if 0
14179 bpr 1106
static void set_atom_tags ()
6785 bpr 1107
{
1108
  int i, FORLIM;
1109
 
14179 bpr 1110
  if (n_atoms > 0){
1111
    FORLIM = n_atoms;
1112
    for (i = 0; i < FORLIM; i++)
1113
      atom[i].tag = true;
1114
  }
6785 bpr 1115
}
1116
#endif
14179 bpr 1117
static void order_ringpath (int *r_path)
6785 bpr 1118
{
1119
  /* order should be: array starts with atom of lowest number, followed by neighbor atom with lower number */
1120
  int i, pl, a_ref, a_left, a_right, a_tmp;
1121
 
1122
  pl = path_length (r_path);
1123
  if (pl < 3)
1124
    return;
1125
  a_ref = n_atoms;
1126
  /* start with highest possible value for an atom number */
14179 bpr 1127
  for (i = 0; i < pl; i++){
1128
    if (r_path[i] < a_ref)  /* find the minimum value ==> reference atom */
1129
     a_ref = r_path[i];
1130
  }
1131
  if (a_ref < 1)   /* just to be sure */
6785 bpr 1132
    return;
1133
  if (path_pos (a_ref, r_path) < pl)
1134
    a_right = r_path[path_pos (a_ref, r_path)];
1135
  else
1136
    a_right = r_path[0];
1137
  if (path_pos (a_ref, r_path) > 1)
1138
    a_left = r_path[path_pos (a_ref, r_path) - 2];
1139
  else
1140
    a_left = r_path[pl - 1];
14179 bpr 1141
  if (a_right == a_left)  /* should never happen */
6785 bpr 1142
    return;
14179 bpr 1143
  if (a_right < a_left) {
6785 bpr 1144
      /* correct ring numbering direction, only shift of the reference atom to the left end required */
14179 bpr 1145
    while (path_pos (a_ref, r_path) > 1){
1146
      a_tmp = r_path[0];
1147
      for (i = 1; i < pl; i++)
1148
        r_path[i - 1] = r_path[i];
1149
      r_path[pl - 1] = a_tmp;
6785 bpr 1150
    }
14179 bpr 1151
    return;
1152
  }
1153
  while (path_pos (a_ref, r_path) < pl) {
6785 bpr 1154
      /* step one: create "mirrored" ring path with reference atom at right end */
14179 bpr 1155
    a_tmp = r_path[pl - 1];
1156
    for (i = pl; i >= 2; i--)
1157
      r_path[i - 1] = r_path[i - 2];
1158
    r_path[0] = a_tmp;
1159
  }
1160
  for (i = 1; i <= pl / 2; i++){        /* one more mirroring */
1161
    a_tmp = r_path[i - 1];
1162
    r_path[i - 1] = r_path[pl - i];
1163
    r_path[pl - i] = a_tmp;
1164
    /* wrong ring numbering direction, two steps required */
1165
  }
6785 bpr 1166
}
1167
 
14179 bpr 1168
static void clear_ndl_atom_tags ()
6785 bpr 1169
{
1170
  int i;
1171
 
14179 bpr 1172
  if (ndl_n_atoms > 0){
1173
    for (i = 0; i < ndl_n_atoms; i++)
1174
      ndl_atom[i].tag = false;
1175
  }
6785 bpr 1176
}
1177
 
14179 bpr 1178
static void set_ndl_atom_tags ()
6785 bpr 1179
{
1180
  int i;
1181
 
14179 bpr 1182
  if (ndl_n_atoms > 0){
1183
    for (i = 0; i < ndl_n_atoms; i++)
1184
     ndl_atom[i].tag = true;
1185
  }
6785 bpr 1186
}
1187
 
14179 bpr 1188
static int count_tagged_ndl_heavyatoms ()
6785 bpr 1189
{
1190
  int i;
1191
  int n = 0;
1192
 
1193
  if (ndl_n_atoms < 1)
1194
    return n;
1195
 
14179 bpr 1196
  for (i = 0; i < ndl_n_atoms; i++){
1197
    if (ndl_atom[i].heavy && ndl_atom[i].tag)
1198
    n++;
1199
  }
6785 bpr 1200
  return n;
1201
}
1202
 
1203
/*============================= geometry functions ========================== */
1204
 
14179 bpr 1205
static double dist3d (p1, p2)
6785 bpr 1206
     p_3d p1, p2;
1207
{
1208
  double res, TEMP, TEMP1, TEMP2;
1209
 
1210
  TEMP = p1.x - p2.x;
1211
  TEMP1 = p1.y - p2.y;
1212
  TEMP2 = p1.z - p2.z;
1213
  res = sqrt (TEMP * TEMP + TEMP1 * TEMP1 + TEMP2 * TEMP2);
1214
  return res;
1215
}
1216
 
1217
/*
1218
function is_cis(p1,p2,p3,p4:p_3d):boolean;  (* new in v0.3d
1219
var                         (* just a simple, distance-based estimation
1220
  total_dist  : double;     (* instead of calculating the dihedral angle
1221
  direct_dist : double;
1222
  res         : boolean;
1223
begin
1224
  res := false;
1225
  total_dist  := dist3d(p1,p2) + dist3d(p2,p3) + dist3d(p3,p4);
1226
  direct_dist := dist3d(p1,p4);
1227
  if (direct_dist < 0.78 * total_dist) then res := true;  (* cutoff value of 0.78 was
1228
  is_cis := res;                                          (* experimentally determined
1229
end;
1230
*/
1231
/* function is_cis was replaced by a new one in v0.3h */
1232
 
14179 bpr 1233
static p_3d subtract_3d (p1, p2)
6785 bpr 1234
     p_3d p1, p2;
1235
{
1236
  p_3d p;
1237
 
1238
  p.x = p1.x - p2.x;
1239
  p.y = p1.y - p2.y;
1240
  p.z = p1.z - p2.z;
1241
  return p;
1242
}
1243
 
14179 bpr 1244
static p_3d add_3d (p1, p2)
6785 bpr 1245
     p_3d p1, p2;
1246
{
1247
  p_3d p;
1248
 
1249
  p.x = p1.x + p2.x;
1250
  p.y = p1.y + p2.y;
1251
  p.z = p1.z + p2.z;
1252
  return p;
1253
}
1254
 
1255
#if 0
14179 bpr 1256
static void vec2origin (p1, p2)
6785 bpr 1257
     p_3d *p1, *p2;
1258
{
1259
  p_3d p;
1260
 
1261
  p = subtract_3d (*p2, *p1);
1262
  *p2 = p;
1263
  p1->x = 0.0;
1264
  p1->y = 0.0;
1265
  p1->z = 0.0;
1266
}
1267
#endif
1268
 
14179 bpr 1269
static double scalar_prod (p1, p2, p3)
6785 bpr 1270
     p_3d p1, p2, p3;
1271
{
1272
  p_3d p;
1273
  double res;
1274
 
1275
  p = subtract_3d (p2, p1);
1276
  p2 = p;
1277
  p = subtract_3d (p3, p1);
1278
  p3 = p;
1279
  p1.x = 0.0;
1280
  p1.y = 0.0;
1281
  p1.z = 0.0;
1282
  res = p2.x * p3.x + p2.y * p3.y + p2.z * p3.z;
1283
  return res;
1284
}
1285
 
14179 bpr 1286
static p_3d cross_prod (p1, p2, p3)
6785 bpr 1287
     p_3d p1, p2, p3;
1288
{
1289
  p_3d p, orig_p1;
1290
 
1291
  orig_p1 = p1;
1292
  p = subtract_3d (p2, p1);
1293
  p2 = p;
1294
  p = subtract_3d (p3, p1);
1295
  p3 = p;
1296
  p.x = p2.y * p3.z - p2.z * p3.y;
1297
  p.y = p2.z * p3.x - p2.x * p3.z;
1298
  p.z = p2.x * p3.y - p2.y * p3.x;
1299
  return (add_3d (orig_p1, p));
1300
}
1301
 
14179 bpr 1302
static double angle_3d (p1, p2, p3)
6785 bpr 1303
     p_3d p1, p2, p3;
1304
{
1305
  p_3d lp1, lp2, lp3, p;
1306
  double res = 0.0;
1307
  double magn_1, magn_2, cos_phi;
1308
 
1309
  lp1 = p1;
1310
  lp2 = p2;
1311
  lp3 = p3;
1312
  p = subtract_3d (lp2, lp1);
1313
  lp2 = p;
1314
  p = subtract_3d (lp3, lp1);
1315
  lp3 = p;
1316
  lp1.x = 0.0;
1317
  lp1.y = 0.0;
1318
  lp1.z = 0.0;
1319
  magn_1 = dist3d (lp1, lp2);
1320
  magn_2 = dist3d (lp1, lp3);
14179 bpr 1321
  if (magn_1 * magn_2 == 0)  /* emergency exit */
6785 bpr 1322
    return M_PI;
1323
  cos_phi = scalar_prod (lp1, lp2, lp3) / (magn_1 * magn_2);
1324
  if (cos_phi < -1)
1325
    cos_phi = -1.0;
1326
  if (cos_phi > 1)
1327
    cos_phi = 1.0;
1328
  res = acos (cos_phi);
1329
  return res;
1330
}
1331
 
14179 bpr 1332
static double torsion (p1, p2, p3, p4)
6785 bpr 1333
     p_3d p1, p2, p3, p4;
1334
{
1335
  p_3d lp1, lp2, lp3, lp4, d1, c1, c2;
1336
  double res;
1337
  p_3d c1xc2, c2xc1;
1338
  double dist1, dist2, sign;
1339
 
1340
  /* copy everything into local variables */
1341
  lp1 = p1;
1342
  lp2 = p2;
1343
  lp3 = p3;
1344
  lp4 = p4;
1345
  /* get the vector between the two central atoms */
1346
  d1 = subtract_3d (p3, p2);
1347
  /* shift the first atom parallel to be attached to p3 instead of p2 */
1348
  lp1 = add_3d (p1, d1);
1349
  /* now get the cross product vectors */
1350
  c1 = cross_prod (lp3, lp2, lp1);
1351
  c2 = cross_prod (lp3, lp2, lp4);
1352
  res = angle_3d (p3, c1, c2);
1353
  /*now check if it is clockwise or anticlockwise: */
1354
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1355
  c1xc2 = cross_prod (lp3, c1, c2);
1356
  c2xc1 = cross_prod (lp3, c2, c1);
1357
  /*next, get the distances from these points to our refernce point lp2 */
1358
  dist1 = dist3d (lp2, c1xc2);
1359
  dist2 = dist3d (lp2, c2xc1);
1360
  if (dist1 <= dist2)
1361
    sign = 1.0;
1362
  else
1363
    sign = -1.0;
1364
  return (sign * res);
1365
}
1366
 
14179 bpr 1367
static double ctorsion (p1, p2, p3, p4)
6785 bpr 1368
     p_3d p1, p2, p3, p4;
1369
{
1370
  /* calculates "pseudo-torsion" defined by atoms 3 and 4, being both */
1371
  /* attached to atom 2, with respect to axis of atoms 1 and 2 */
1372
  p_3d lp1, lp2, lp3, lp4;
1373
  /*d1 : p_3d; */
1374
  p_3d c1, c2;
1375
  double res;
1376
  p_3d c1xc2, c2xc1;
1377
  double dist1, dist2, sign;
1378
 
1379
  /* copy everything into local variables */
1380
  lp1 = p1;
1381
  lp2 = p2;
1382
  lp3 = p3;
1383
  lp4 = p4;
1384
  /* get the cross product vectors */
1385
  c1 = cross_prod (lp2, lp1, lp3);
1386
  c2 = cross_prod (lp2, lp1, lp4);
1387
  res = angle_3d (p2, c1, c2);
1388
  /*now check if it is clockwise or anticlockwise: */
1389
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1390
  c1xc2 = cross_prod (lp2, c1, c2);
1391
  c2xc1 = cross_prod (lp2, c2, c1);
1392
  /*next, get the distances from these points to our refernce point lp1 */
1393
  dist1 = dist3d (lp1, c1xc2);
1394
  dist2 = dist3d (lp1, c2xc1);
1395
  if (dist1 <= dist2)
1396
    sign = 1.0;
1397
  else
1398
    sign = -1.0;
1399
  return (sign * res);
1400
}
1401
 
14179 bpr 1402
static boolean is_cis (p1, p2, p3, p4)
6785 bpr 1403
     p_3d p1, p2, p3, p4;
1404
{
1405
  /* new in v0.3h, uses the dihedral angle */
1406
  double phi;
1407
  boolean res = false;
1408
 
1409
  phi = torsion (p1, p2, p3, p4);
1410
  if (fabs (phi) < M_PI / 2)
1411
    res = true;
1412
  return res;
1413
}
1414
 
1415
/*====================== end of geometry functions ========================== */
1416
 
14179 bpr 1417
static void show_usage () {
1418
  if (progmode == pmMatchMol) {
1419
    printf ("matchmol version %s  N. Haider, University of Vienna, 2003-2007\n", version);
1420
    printf ("Usage: matchmol [options] <needle> <haystack>\n");
1421
    printf (" where <needle> and <haystack> are the two molecules to compare\n");
1422
    printf (" (supported formats: MDL *.mol or *.sdf, Alchemy *.mol, Sybyl *.mol2)\n");
1423
    printf (" options can be:\n");
1424
    printf ("    -v  verbose output\n");
1425
    printf ("    -x  exact match\n");
1426
    printf ("    -s  strict comparison of atom and bond types (including ring check)\n");
6785 bpr 1427
      /* new in v0.2f, v0.3d */
14179 bpr 1428
    printf ("    -r  force SSR (set of small rings) ring search mode\n");
1429
    printf ("    -m  write matching molecule as MDL molfile to standard output\n");
1430
    printf ("        (default output: record number + \":T\" for hit  or \":F\" for miss\n");
1431
    printf ("    -M  accept metal atoms as ring members\n");
1432
    printf ("    -g  check geometry of double bonds (E/Z)\n");
1433
    printf ("    -G  check geometry of chiral centers (R/S)\n");
1434
    printf ("    -a  check charges strict\n");   /* 0.3x */
1435
    printf ("    -i  check isotopes strict\n");  /* 0.3x */
1436
    printf ("    -d  check radicals strict\n");  /* 0.3x */
1437
    printf ("    -f  fingerprint mode (1 haystack, multiple needles) with boolean output\n");
1438
    printf ("    -F  fingerprint mode (1 haystack, multiple needles) with decimal output\n");
1439
    return;
1440
  }
1441
  printf ("checkmol version %s  N. Haider, University of Vienna, 2003-2007\n", version);
6785 bpr 1442
  printf ("Usage: checkmol [options] <filename>\n");
1443
  printf (" where options can be:\n");
14179 bpr 1444
  printf ("    -l  print a list of fingerprint codes + explanation and exit\n");
6785 bpr 1445
  printf ("    -v  verbose output\n");
1446
  printf ("    -r  force SSR (set of small rings) ring search mode\n");
1447
  printf ("    -M  accept metal atoms as ring members\n");
1448
  printf ("  and one of the following:\n");
14179 bpr 1449
  printf ("    -e  english text (common name of functional group; default)\n");
6785 bpr 1450
  printf ("    -d  german text (common name of functional group)\n");
1451
  printf ("    -c  code (acronym-like code for functional group)\n");
14179 bpr 1452
  printf ("    -b  binary (a bitstring representing absence or presence of each group)\n");
1453
  printf ("    -s  the ASCII representation of the above bitstring, i.e. 0s and 1s)\n");
1454
  printf ("    -x  print molecular statistics (number of various atom types, bond types,\n");
6785 bpr 1455
  printf ("        ring sizes, etc.\n");
14179 bpr 1456
  printf ("    -X  same as above, listing all records (even if 0) as comma-separated list\n");
1457
  printf ("    -a  count charges in fingerprint\n");  /* 0.3x */
1458
  printf ("    -m  write MDL molfile (with special encoding for aromatic atoms/bonds)\n");
6785 bpr 1459
  printf (" options can be combined like -vc\n");
1460
  printf (" <filename> specifies any file in the formats supported\n");
14179 bpr 1461
  printf (" (MDL *.mol, Alchemy *.mol, Sybyl *.mol2), the filename \"-\" (without quotes)\n");
6785 bpr 1462
  printf (" specifies standard input\n");
1463
  /* the "debug" option (-D) remains undocumented */
1464
}
1465
 
14179 bpr 1466
static void list_molstat_codes ()
6785 bpr 1467
{
1468
  printf ("n_atoms:     number of heavy atoms\n");
1469
  printf ("n_bonds:     number of bonds between non-H atoms\n");
1470
  printf ("n_rings:     number of rings\n");
1471
  printf ("n_QA:        number of query atoms\n");
1472
  printf ("n_QB:        number of query bonds\n");
1473
  printf ("n_chg:       number of charges\n");
1474
  printf ("n_C1:        number of sp-hybridized carbon atoms\n");
1475
  printf ("n_C2:        number of sp2-hybridized carbon atoms\n");
1476
  printf ("n_C:         total number of carbon atoms\n");
1477
  printf
1478
    ("n_CHB1p:     number of carbon atoms with at least 1 bond to a hetero atom\n");
1479
  printf
1480
    ("n_CHB2p:     number of carbon atoms with at least 2 bonds to a hetero atom\n");
1481
  printf
1482
    ("n_CHB3p:     number of carbon atoms with at least 3 bonds to a hetero atom\n");
1483
  printf
1484
    ("n_CHB4:      number of carbon atoms with 4 bonds to a hetero atom\n");
1485
  printf ("n_O2:        number of sp2-hybridized oxygen atoms\n");
1486
  printf ("n_O3:        number of sp3-hybridized oxygen atoms\n");
1487
  printf ("n_N1:        number of sp-hybridized nitrogen atoms\n");
1488
  printf ("n_N2:        number of sp2-hybridized nitrogen atoms\n");
1489
  printf ("n_N3:        number of sp3-hybridized nitrogen atoms\n");
1490
  printf ("n_S:         number of sulfur atoms\n");
1491
  printf ("n_SeTe:      total number of selenium and tellurium atoms\n");
1492
  printf ("n_F:         number of fluorine atoms\n");
1493
  printf ("n_Cl:        number of chlorine atoms\n");
1494
  printf ("n_Br:        number of bromine atoms\n");
1495
  printf ("n_I:         number of iodine atoms\n");
1496
  printf ("n_P:         number of phosphorus atoms\n");
1497
  printf ("n_B:         number of boron atoms\n");
1498
  printf ("n_Met:       total number of metal atoms\n");
1499
  printf
1500
    ("n_X:         total number of \"other\" atoms (not listed above) and halogens\n");
1501
  printf ("n_b1:        number of single bonds\n");
1502
  printf ("n_b2:        number of double bonds\n");
1503
  printf ("n_b3:        number of triple bonds\n");
1504
  printf ("n_bar:       number of aromatic bonds\n");
1505
  printf ("n_C1O:       number of C-O single bonds\n");
1506
  printf ("n_C2O:       number of C=O double bonds\n");
1507
  printf ("n_CN:        number of C/N bonds (any type)\n");
1508
  printf ("n_XY:        number of heteroatom/heteroatom bonds (any type)\n");
1509
  printf ("n_r3:        number of 3-membered rings\n");
1510
  printf ("n_r4:        number of 4-membered rings\n");
1511
  printf ("n_r5:        number of 5-membered rings\n");
1512
  printf ("n_r6:        number of 6-membered rings\n");
1513
  printf ("n_r7:        number of 7-membered rings\n");
1514
  printf ("n_r8:        number of 8-membered rings\n");
1515
  printf ("n_r9:        number of 9-membered rings\n");
1516
  printf ("n_r10:       number of 10-membered rings\n");
1517
  printf ("n_r11:       number of 11-membered rings\n");
1518
  printf ("n_r12:       number of 12-membered rings\n");
1519
  printf ("n_r13p:      number of 13-membered or larger rings\n");
1520
  printf ("n_rN:        number of rings containing nitrogen (any number)\n");
1521
  printf ("n_rN1:       number of rings containing 1 nitrogen atom\n");
1522
  printf ("n_rN2:       number of rings containing 2 nitrogen atoms\n");
1523
  printf
1524
    ("n_rN3p:      number of rings containing 3 or more nitrogen atoms\n");
1525
  printf ("n_rO:        number of rings containing oxygen (any number)\n");
1526
  printf ("n_rO1:       number of rings containing 1 oxygen atom\n");
1527
  printf ("n_rO2p:      number of rings containing 2 or more oxygen atoms\n");
1528
  printf ("n_rS:        number of rings containing sulfur (any number)\n");
1529
  printf ("n_rX:        number of heterocycles (any type)\n");
1530
  printf ("n_rar:       number of aromatic rings (any type)\n");
14179 bpr 1531
  /* p2c: checkmol.pas, line 1207:
1532
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 1533
  /*$IFDEF extended_molstat */
1534
  printf ("n_rbz:       number of benzene rings\n");
1535
  printf ("n_br2p:      number of bonds belonging to two or more rings\n");
14179 bpr 1536
  printf ("n_psg01:     number of atoms belonging to group 1 of the periodic system\n");
1537
  printf ("n_psg02:     number of atoms belonging to group 2 of the periodic system\n");
1538
  printf ("n_psg13:     number of atoms belonging to group 13 of the periodic system\n");
1539
  printf ("n_psg14:     number of atoms belonging to group 14 of the periodic system\n");
1540
  printf ("n_psg15:     number of atoms belonging to group 15 of the periodic system\n");
1541
  printf ("n_psg16:     number of atoms belonging to group 16 of the periodic system\n");
1542
  printf ("n_psg17:     number of atoms belonging to group 17 of the periodic system\n");
1543
  printf ("n_psg18:     number of atoms belonging to group 18 of the periodic system\n");
1544
  printf ("n_pstm:      number of atoms belonging to the transition metals\n");
1545
  printf ("n_psla:      number of atoms belonging to the lanthanides or actinides\n");
6785 bpr 1546
  printf ("n_iso:      number of isotopes\n");
1547
  printf ("n_rad:      number of radicals\n");
1548
  /*$ENDIF */
1549
}
1550
 
1551
#if 0
14179 bpr 1552
static void parse_args() {
6785 bpr 1553
  int p;
1554
  char parstr[256];
1555
  char tmpstr[256];
1556
  int l;
1557
 
1558
  *tmpstr = '\0';
1559
  opt_none = true;
1560
  if (progmode == pmCheckMol) {
1561
    for (p = 1; p < P_argc; p++) {
1562
      strcpy(parstr, P_argv[p]);
1563
      if (!strcmp(parstr, "-l")) {   /* new in v0.3l */
14179 bpr 1564
        list_molstat_codes();
1565
        _Escape(0);
6785 bpr 1566
      }
1567
      if (p < P_argc - 1) {
14179 bpr 1568
        if (strpos2(parstr, "-", 1) == 1 && p < P_argc - 1) {
1569
          strcpy(tmpstr, P_argv[p]);
1570
          left_trim(tmpstr);
1571
          l = 0;
1572
          if (strpos2(tmpstr, "v", 1) > 0)
1573
            l++;
1574
          if (strpos2(tmpstr, "D", 1) > 0)
1575
            l++;
1576
          if (strpos2(tmpstr, "r", 1) > 0)
1577
            l++;
1578
          if (strpos2(tmpstr, "M", 1) > 0)   /* new in v0.3 */
1579
            l++;
1580
          if (strlen(tmpstr) > l + 2) {
1581
            show_usage();
1582
            _Escape(1);
1583
          }
1584
          opt_none = false;
1585
          if (strpos2(tmpstr, "M", 1) > 0)
1586
            opt_metalrings = true;
1587
          if (strpos2(tmpstr, "v", 1) > 0)
1588
            opt_verbose = true;
1589
            /* p2c: checkmol.pas, line 1261:
1590
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1591
            /*$IFDEF debug
1592
            if (strpos2(tmpstr, "D", 1) > 0)
1593
              opt_debug = true;
1594
            $ENDIF*/
1595
          if (strpos2(tmpstr, "e", 1) > 0)
1596
            opt_text = true;
1597
          else {
1598
            if (strpos2(tmpstr, "d", 1) > 0)
1599
              opt_text_de = true;
1600
            else {
1601
              if (strpos2(tmpstr, "c", 1) > 0)
1602
                opt_code = true;
1603
              else {
1604
                if (strpos2(tmpstr, "b", 1) > 0)
1605
                  opt_bin = true;
1606
                else {
1607
                  if (strpos2(tmpstr, "s", 1) > 0)
1608
                    opt_bitstring = true;
1609
                }
1610
              }
1611
            }
1612
            if (strpos2(tmpstr, "x", 1) > 0)
1613
              opt_molstat = true;
1614
            if (strpos2(tmpstr, "r", 1) > 0)
1615
              opt_rs = rs_ssr;
1616
            if (strpos2(tmpstr, "X", 1) > 0) {
1617
              opt_molstat = true;
1618
              opt_molstat_X = true;
1619
            }
1620
            if (strpos2(tmpstr, "m", 1) > 0) {
1621
              opt_text = false;
1622
              opt_text_de = false;
1623
              opt_bin = false;
1624
              opt_bitstring = false;
1625
              opt_code = false;
1626
              opt_molstat = false;
1627
              opt_xmdlout = true;
1628
                  }
1629
          }
1630
        strcpy(molfilename, tmpstr);
1631
      }
1632
    } else {
1633
      if (strpos2(parstr, "-", 1) == 1) {
1634
        if (strlen(parstr) > 1) {
1635
          show_usage();
1636
          _Escape(1);
1637
        }
1638
        opt_stdin = true;
6785 bpr 1639
      } else {
14179 bpr 1640
      opt_stdin = false;
1641
      strcpy(molfilename, parstr);
6785 bpr 1642
      }
14179 bpr 1643
        }
6785 bpr 1644
    }
1645
    if (opt_text == false && opt_text_de == false && opt_code == false &&
14179 bpr 1646
        opt_bin == false && opt_bitstring == false && opt_molstat == false &&
1647
        opt_molstat_X == false && opt_xmdlout == false)
6785 bpr 1648
      opt_none = true;
1649
  }
1650
  if (progmode == pmMatchMol) {
1651
    *ndl_molfilename = '\0';
1652
    *molfilename = '\0';
1653
    for (p = 1; p < P_argc; p++) {
14179 bpr 1654
        strcpy(parstr, P_argv[p]);
6785 bpr 1655
      if (p == 1) {
14179 bpr 1656
        if (strpos2(parstr, "-", 1) == 1) {
1657
          if (strpos2(parstr, "v", 1) > 1)
1658
            opt_verbose = true;
1659
            /* p2c: checkmol.pas, line 1329:
1660
             * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1661
            /*$IFDEF debug
1662
                if (strpos2(parstr, "D", 1) > 1)
1663
                  opt_debug = true;
1664
               $ENDIF*/
1665
          if (strpos2(parstr, "x", 1) > 1)
1666
            opt_exact = true;
1667
          if (strpos2(parstr, "s", 1) > 1)   /* new in v0.2f */
1668
            opt_strict = true;
1669
          if (strpos2(parstr, "m", 1) > 1)
1670
           opt_molout = true;
1671
          if (strpos2(parstr, "r", 1) > 1)
1672
            opt_rs = rs_ssr;
1673
          if (strpos2(parstr, "M", 1) > 0)   /* new in v0.3 */
1674
            opt_metalrings = true;
1675
          if (strpos2(parstr, "g", 1) > 0)   /* new in v0.3d */
1676
            opt_geom = true;
1677
          if (strpos2(parstr, "G", 1) > 0)   /* new in v0.3f */
1678
            opt_chiral = true;
1679
          if (strpos2(parstr, "f", 1) > 0) {   /* new in v0.3m */
1680
            opt_fp = true;
1681
          fpformat = fpf_boolean;
1682
        }
1683
        if (strpos2(parstr, "F", 1) > 0) {   /* new in v0.3m */
1684
          opt_fp = true;
1685
          fpformat = fpf_decimal;
1686
        }
1687
        if (strpos2(parstr, "h", 1) > 1) {
1688
          show_usage();
1689
          _Escape(0);
1690
        }
1691
            } else
1692
        strcpy(ndl_molfilename, parstr);
1693
    }
1694
    if (p == P_argc - 2) {
1695
      if (strpos2(parstr, "-", 1) != 1)
1696
      strcpy(ndl_molfilename, parstr);
1697
    }
1698
    if (p == P_argc - 1) {
1699
      if (strcmp(parstr, "-"))
1700
        strcpy(molfilename, parstr);
1701
      else
1702
        opt_stdin = true;
1703
      }
1704
    }
1705
    if (opt_geom)   /* v0.3d */
1706
      ez_search = true;
1707
    if (opt_chiral)   /* v0.3f */
1708
      rs_search = true;
1709
    if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1710
        /* new in v0.3j, v0.3m */
1711
      rs_strict = true;
1712
    if (opt_fp) {   /* v0.3m */
1713
        opt_molout = false;
1714
        opt_exact = false;
1715
    }
1716
  }  /* progmode = pmMatchMol */
1717
  ringsearch_mode = opt_rs;   /* v0.3i */
1718
}
6785 bpr 1719
#endif
1720
 
14179 bpr 1721
static void parse_args (int argc, char *argv[])
6785 bpr 1722
{
1723
  short p;
1724
  char parstr[256];
1725
  char tmpstr[256];
1726
  short l;
1727
 
1728
  *tmpstr = '\0';
1729
  opt_none = true;
1730
  *molfilename = '\0';
1731
  *ndl_molfilename = '\0';
14179 bpr 1732
  if (progmode == pmCheckMol) {
1733
    for (p = 1; p <= argc - 1; p++) {
1734
            strcpy (parstr, argv[p]);
1735
            if (!strcmp (parstr, "-l")) {                       /* new in v0.3l */
6785 bpr 1736
              list_molstat_codes ();
1737
              exit (0);
1738
            }
14179 bpr 1739
            if (p < argc - 1) {
1740
              if (strpos2 (parstr, "-", 1) == 1 && p < argc - 1) {
1741
                      strcpy (tmpstr, argv[p]);
1742
                      left_trim (tmpstr);
1743
                      l = 0;
1744
                      if (strpos2 (tmpstr, "v", 1) > 0)
1745
                        l++;
1746
                      if (strpos2 (tmpstr, "D", 1) > 0)
1747
                        l++;
6785 bpr 1748
                      if (strpos2 (tmpstr, "r", 1) > 0)
14179 bpr 1749
                        l++;
1750
                      /*if (strpos2 (tmpstr, "a", 1) > 0)   // 0.3x
1751
                         l++; */
1752
                      if (strpos2 (tmpstr, "M", 1) > 0) /* new in v0.3 */
1753
                        l++;
1754
                      if (strlen (tmpstr) > l + 2) {
1755
                        show_usage ();
1756
                        exit (1);
1757
                      }
1758
                      opt_none = false;
1759
                      if (strpos2 (tmpstr, "M", 1) > 0)
1760
                        opt_metalrings = true;
1761
                      if (strpos2 (tmpstr, "v", 1) > 0)
1762
                        opt_verbose = true;
1763
                      /*{$IFDEF debug
1764
                         if pos('D',tmpstr)>0 then opt_debug       := true;
1765
                         {$ENDIF */
1766
                      if (strpos2 (tmpstr, "e", 1) > 0)
1767
                        opt_text = true;
1768
                      else {
1769
                        if (strpos2 (tmpstr, "d", 1) > 0)
1770
                                 opt_text_de = true;
1771
                        else {
1772
                                if (strpos2 (tmpstr, "c", 1) > 0)
1773
                                  opt_code = true;
1774
                                else {
1775
                                  if (strpos2 (tmpstr, "b", 1) > 0)
1776
                                    opt_bin = true;
1777
                                  else {
1778
                                    if (strpos2 (tmpstr, "s", 1) > 0)
1779
                                      opt_bitstring = true;
1780
                                  }
1781
                                }
1782
                              }
1783
                        if (strpos2 (tmpstr, "x", 1) > 0)
1784
                                opt_molstat = true;
1785
                        if (strpos2 (tmpstr, "r", 1) > 0)
1786
                                opt_rs = rs_ssr;
1787
                          /* if (strpos2 (tmpstr, "a", 1) > 0)
1788
                            opt_chg = true; */ /* 0.3x  */
1789
                        if (strpos2 (tmpstr, "X", 1) > 0) {
1790
                                opt_molstat = true;
1791
                                opt_molstat_X = true;
1792
                              }
1793
                        if (strpos2 (tmpstr, "m", 1) > 0) {
1794
                                opt_text = false;
1795
                                opt_text_de = false;
1796
                                opt_bin = false;
1797
                                opt_bitstring = false;
1798
                                opt_code = false;
1799
                                opt_molstat = false;
1800
                                opt_xmdlout = true;
1801
                              }
1802
                      }
1803
                      strcpy (molfilename, tmpstr);
1804
              }
6785 bpr 1805
            }
14179 bpr 1806
            else {
1807
              if (strpos2 (parstr, "-", 1) == 1) {
1808
                if (strlen (parstr) > 1) {
1809
                  show_usage ();
1810
                  exit (1);
1811
                }
1812
                opt_stdin = true;
1813
              } else {
1814
                      opt_stdin = false;
1815
                      strcpy (molfilename, parstr);
6785 bpr 1816
                    }
1817
            }
14179 bpr 1818
          }
1819
    if (opt_text == false && opt_text_de == false && opt_code == false &&
1820
                opt_bin == false && opt_bitstring == false && opt_molstat == false
1821
                && opt_molstat_X == false && opt_xmdlout == false
1822
                && opt_chg == false)
1823
              opt_none = true;  /* 0.3x */
1824
  }
1825
  if (progmode == pmMatchMol) {
1826
    for (p = 1; p <= argc - 1; p++) {
1827
      strcpy (parstr, argv[p]);
1828
      if (p == 1) {
1829
        if (strpos2 (parstr, "-", 1) == 1) {
1830
          if (strpos2 (parstr, "v", 1) > 1)
1831
            opt_verbose = true;
1832
            /*{$IFDEF debug
1833
               if pos('D',parstr)>1 then opt_debug       := true;
1834
               {$ENDIF */
1835
          if (strpos2 (parstr, "x", 1) > 1)
1836
            opt_exact = true;
1837
          if (strpos2 (parstr, "s", 1) > 1)     /* new in v0.2f */
1838
            opt_strict = true;
1839
          if (strpos2 (parstr, "m", 1) > 1)
1840
            opt_molout = true;
1841
          if (strpos2 (parstr, "r", 1) > 1)
1842
            opt_rs = rs_ssr;
1843
          if (strpos2 (parstr, "a", 1) > 0)
1844
                    opt_chg = true;     /* 0.3x */
1845
          if (strpos2 (parstr, "i", 1) > 0)
1846
            opt_iso = true;     /* 0.3x */
1847
          if (strpos2 (parstr, "d", 1) > 0)
1848
            opt_rad = true;     /* 0.3x */
1849
          if (strpos2 (parstr, "M", 1) > 0)     /* new in v0.3 */
1850
            opt_metalrings = true;
1851
          if (strpos2 (parstr, "g", 1) > 0)     /* new in v0.3d */
1852
            opt_geom = true;
1853
          if (strpos2 (parstr, "G", 1) > 0)     /* new in v0.3f */
1854
            opt_chiral = true;
1855
          if (strpos2 (parstr, "f", 1) > 0) {           /* new in v0.3m */
1856
            opt_fp = true;
1857
            fpformat = fpf_boolean;
1858
          }
1859
          if (strpos2 (parstr, "F", 1) > 0) {           /* new in v0.3m */
1860
            opt_fp = true;
1861
            fpformat = fpf_decimal;
1862
          }
1863
          if (strpos2 (parstr, "h", 1) > 1) {
1864
            show_usage ();
1865
            exit (0);
1866
          }
1867
              } else
1868
                strcpy (ndl_molfilename, parstr);
6785 bpr 1869
            }
14179 bpr 1870
            if (p == argc - 2) {
6785 bpr 1871
              if (strpos2 (parstr, "-", 1) != 1)
14179 bpr 1872
                strcpy (ndl_molfilename, parstr);
1873
              }
1874
            if (p == argc - 1) {
6785 bpr 1875
              if (strcmp (parstr, "-"))
14179 bpr 1876
                strcpy (molfilename, parstr);
6785 bpr 1877
              else
14179 bpr 1878
                opt_stdin = true;
6785 bpr 1879
            }
14179 bpr 1880
          }
1881
    if (opt_geom)               /* v0.3d */
1882
            ez_search = true;
1883
    if (opt_chiral)             /* v0.3f */
1884
            rs_search = true;
1885
    if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1886
            /* new in v0.3j, v0.3m  */
1887
            rs_strict = true;
1888
    if (opt_fp) {                       /* v0.3m */
1889
            opt_molout = false;
1890
            opt_exact = false;
1891
          }
1892
  }                             /* progmode = pmMatchMol */
6785 bpr 1893
  ringsearch_mode = opt_rs;     /* v0.3i */
1894
}
1895
 
1896
/*============== input-related functions & procedures ===================== */
1897
 
14179 bpr 1898
static char *get_filetype (Result, f)
1899
  char *Result;
1900
  char *f;
6785 bpr 1901
{
1902
  char rline[256];
1903
  char auxstr[256];
1904
  int i;
1905
  boolean mdl1 = false;
1906
  int ri;
1907
  int sepcount = 0;
1908
  char STR1[256], STR6[256], STR7[256];
1909
 
1910
  strcpy (auxstr, "unknown");
1911
  i = li;
1912
  ri = li - 1;
14179 bpr 1913
  while (ri < molbufindex && sepcount < 1) {
1914
    ri++;
1915
    strcpy (rline, molbuf[ri - 1]);
1916
    if (strpos2 (rline, "$$$$", 1) > 0)
1917
            sepcount++;
1918
    if ((i == li) && (strcmp (strsub (STR1, rline, 7, 5), "ATOMS") == 0) &&
1919
              (strcmp (strsub (STR6, rline, 20, 5), "BONDS") == 0) &&
1920
              (strcmp (strsub (STR7, rline, 33, 7), "CHARGES") == 0))
1921
            strcpy (auxstr, "alchemy");
1922
    if ((i == li + 3) && (strcmp (strsub (STR1, rline, 35, 5), "V2000") == 0))
1923
            /* and (copy(rline,31,3)='999') */
1924
            mdl1 = true;
1925
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 6), "-ISIS-") == 0))
1926
            mdl1 = true;
1927
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "WLViewer") == 0))
1928
            mdl1 = true;
1929
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CheckMol") == 0))
1930
            mdl1 = true;
1931
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CATALYST") == 0)) {
1932
            mdl1 = true;
1933
            strcpy (auxstr, "mdl");
1934
          }
1935
    if (strpos2 (rline, "M  END", 1) == 1 || mdl1)
1936
            strcpy (auxstr, "mdl");
1937
    if (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) > 0)
1938
            strcpy (auxstr, "sybyl");
1939
    i++;
1940
  }
6785 bpr 1941
  /* new in v0.2j: try to identify non-conformant SD-files */
1942
  if (!strcmp (auxstr, "unknown") && sepcount > 0)
1943
    strcpy (auxstr, "mdl");
1944
  return strcpy (Result, auxstr);
1945
}
1946
 
14179 bpr 1947
static void zap_molecule ()
6785 bpr 1948
{
1949
  /* try */
14179 bpr 1950
  if (atom != NULL) {
1951
    free (atom);
1952
    atom = NULL;                /* added in v0.3j */
1953
  }
1954
  if (bond != NULL) {
1955
    free (bond);
1956
    bond = NULL;                /* added in v0.3j */
1957
  }
1958
  if (ring != NULL) {
1959
    free (ring);
1960
    ring = NULL;                /* added in v0.3j */
1961
  }
1962
  if (ringprop != NULL) {
1963
    free (ringprop);
1964
    ringprop = NULL;            /* added in v0.3j */
1965
  }
6785 bpr 1966
  /* except
14179 bpr 1967
    on e:Einvalidpointer do begin end;
1968
    end; */
6785 bpr 1969
  n_atoms = 0;
1970
  n_bonds = 0;
1971
  n_rings = 0;
1972
}
1973
 
14179 bpr 1974
static void zap_needle ()
6785 bpr 1975
{
1976
  /* try */
14179 bpr 1977
  if (ndl_atom != NULL) {
1978
    free (ndl_atom);
1979
    ndl_atom = NULL;            /* added in v0.3j */
1980
  }
1981
  if (ndl_bond != NULL) {
1982
    free (ndl_bond);
1983
    ndl_bond = NULL;            /* added in v0.3j */
1984
  }
1985
  if (ndl_ring != NULL) {
1986
    free (ndl_ring);
1987
    ndl_ring = NULL;            /* added in v0.3j */
1988
  }
1989
  if (ndl_ringprop != NULL) {
1990
    free (ndl_ringprop);        /* fixed in v0.3g */
1991
    ndl_ringprop = NULL;        /* added in v0.3j */
1992
  }
6785 bpr 1993
  /* except
1994
     on e:Einvalidpointer do begin end;
1995
     end; */
1996
  ndl_n_atoms = 0;
1997
  ndl_n_bonds = 0;
1998
  ndl_n_rings = 0;
1999
}
2000
 
2001
#if 0
14179 bpr 2002
static void zap_tmp ()
6785 bpr 2003
{
2004
  /* try */
14179 bpr 2005
  if (tmp_atom != NULL) {
6785 bpr 2006
      free (tmp_atom);
2007
      tmp_atom = NULL;          /* added in v0.3j */
2008
    }
14179 bpr 2009
  if (tmp_bond != NULL) {
6785 bpr 2010
      free (tmp_bond);
2011
      tmp_bond = NULL;          /* added in v0.3j */
2012
    }
14179 bpr 2013
  if (tmp_ring != NULL) {
6785 bpr 2014
      free (tmp_ring);
2015
      tmp_ring = NULL;          /* added in v0.3j */
2016
    }
14179 bpr 2017
  if (tmp_ringprop != NULL) {
6785 bpr 2018
      free (tmp_ringprop);      /* fixed in v0.3g */
2019
      tmp_ringprop = NULL;      /* added in v0.3j */
2020
    }
2021
  /* except
2022
     on e:Einvalidpointer do begin end;
2023
     end; */
2024
  tmp_n_atoms = 0;
2025
  tmp_n_bonds = 0;
2026
  tmp_n_rings = 0;
2027
}
2028
#endif
2029
 
14179 bpr 2030
static boolean is_heavyatom (id)
6785 bpr 2031
     int id;
2032
{
2033
  str2 el;
2034
 
2035
  strcpy (el, atom[id - 1].element);
14179 bpr 2036
 
6785 bpr 2037
  if (!strcmp (el, "DU") || !strcmp (el, "LP"))
2038
    return false;
2039
  /*if (progmode == pmCheckMol && !strcmp (el, "H ")
2040
     && atom[id - 1].nucleon_number < 2)
2041
     return false;               0.3x  */
14179 bpr 2042
  if (!strcmp (el, "H "))       /* 0.3 p */ {
2043
    if (progmode == pmMatchMol && !opt_iso) {
2044
            return false;
2045
          }
2046
    else {
6785 bpr 2047
          if (atom[id - 1].nucleon_number < 2)
2048
            return false;
14179 bpr 2049
          }
2050
  }
6785 bpr 2051
  return true;
2052
}
2053
 
14179 bpr 2054
static boolean ndl_alkene_C (ba)
6785 bpr 2055
     int ba;
2056
{
2057
  /* new in v0.3f */
2058
  boolean res = false;
2059
  int i, ba2, FORLIM;
2060
 
2061
  if (ndl_n_atoms <= 0 || ndl_n_bonds <= 0)
2062
    return false;
2063
  FORLIM = ndl_n_bonds;
14179 bpr 2064
  for (i = 0; i < FORLIM; i++) {
2065
    if (ndl_bond[i].a1 == ba || ndl_bond[i].a2 == ba) {
2066
            if (ndl_bond[i].a1 == ba)
2067
              ba2 = ndl_bond[i].a2;
2068
            else
2069
              ba2 = ndl_bond[i].a1;
6785 bpr 2070
          if (!strcmp (ndl_atom[ba - 1].atype, "C2 ") &&
2071
              !strcmp (ndl_atom[ba2 - 1].atype, "C2 ")
2072
              && ndl_bond[i].btype == 'D' && ndl_bond[i].arom == false)
2073
            res = true;
14179 bpr 2074
          }
2075
  }
6785 bpr 2076
  return res;
2077
}
2078
 
14179 bpr 2079
static boolean is_metal (id)
6785 bpr 2080
     int id;
2081
{
2082
  boolean r = false;
2083
  str2 el;
2084
 
2085
  strcpy (el, atom[id - 1].element);
2086
  if (!strcmp (el, "LI") || !strcmp (el, "NA") || !strcmp (el, "K ") ||
2087
      !strcmp (el, "RB") || !strcmp (el, "CS") || !strcmp (el, "BE") ||
2088
      !strcmp (el, "MG") || !strcmp (el, "CA") || !strcmp (el, "SR") ||
2089
      !strcmp (el, "BA") || !strcmp (el, "TI") || !strcmp (el, "ZR") ||
2090
      !strcmp (el, "CR") || !strcmp (el, "MO") || !strcmp (el, "MN") ||
2091
      !strcmp (el, "FE") || !strcmp (el, "CO") || !strcmp (el, "NI") ||
2092
      !strcmp (el, "PD") || !strcmp (el, "PT") || !strcmp (el, "SN") ||
2093
      !strcmp (el, "CU") || !strcmp (el, "AG") || !strcmp (el, "AU") ||
2094
      !strcmp (el, "ZN") || !strcmp (el, "CD") || !strcmp (el, "HG") ||
2095
      !strcmp (el, "AL") || !strcmp (el, "SN") || !strcmp (el, "PB") ||
2096
      !strcmp (el, "SB") || !strcmp (el, "BI"))
14179 bpr 2097
  /* p2c: checkmol.pas, line 1577:
2098
  * Note: Line breaker spent 0.0 seconds, 5000 tries on line 1686 [251] */
6785 bpr 2099
    /* etc. etc. */
2100
    r = true;
2101
  return r;
2102
}
2103
 
14179 bpr 2104
static int get_nvalences (a_el)
6785 bpr 2105
     char *a_el;
2106
{
2107
  /* changed name and position in v0.3m */
2108
  /* preliminary version; should be extended to element/atomtype */
2109
  int res = 1;
2110
 
2111
  if (!strcmp (a_el, "H "))
2112
    res = 1;
14179 bpr 2113
  /*if (!strcmp (a_el, "D "))   // v0.3n
6785 bpr 2114
     res = 1; */
2115
  if (!strcmp (a_el, "C "))
2116
    res = 4;
2117
  if (!strcmp (a_el, "N "))
2118
    res = 3;
2119
  if (!strcmp (a_el, "O "))
2120
    res = 2;
2121
  if (!strcmp (a_el, "S "))
2122
    res = 2;
2123
  if (!strcmp (a_el, "SE"))
2124
    res = 2;
2125
  if (!strcmp (a_el, "TE"))
2126
    res = 2;
2127
  if (!strcmp (a_el, "P "))
2128
    res = 3;
2129
  if (!strcmp (a_el, "F "))
2130
    res = 1;
2131
  if (!strcmp (a_el, "CL"))
2132
    res = 1;
2133
  if (!strcmp (a_el, "BR"))
2134
    res = 1;
2135
  if (!strcmp (a_el, "I "))
2136
    res = 1;
2137
  if (!strcmp (a_el, "AT"))
2138
    res = 1;
2139
  if (!strcmp (a_el, "B "))
2140
    res = 3;
2141
  if (!strcmp (a_el, "LI"))
2142
    res = 1;
2143
  if (!strcmp (a_el, "NA"))
2144
    res = 1;
2145
  if (!strcmp (a_el, "K "))
2146
    res = 1;
2147
  if (!strcmp (a_el, "CA"))
2148
    res = 2;
2149
  if (!strcmp (a_el, "SR"))
2150
    res = 2;
2151
  if (!strcmp (a_el, "MG"))
2152
    res = 2;
2153
  if (!strcmp (a_el, "FE"))
2154
    res = 3;
2155
  if (!strcmp (a_el, "MN"))
2156
    res = 2;
2157
  if (!strcmp (a_el, "HG"))
2158
    res = 2;
2159
  if (!strcmp (a_el, "SI"))
2160
    res = 4;
2161
  if (!strcmp (a_el, "SN"))
2162
    res = 4;
2163
  if (!strcmp (a_el, "ZN"))
2164
    res = 2;
2165
  if (!strcmp (a_el, "CU"))
2166
    res = 2;
2167
  if (!strcmp (a_el, "A "))
2168
    res = 4;
2169
  if (!strcmp (a_el, "Q "))
2170
    res = 4;
2171
  return res;
2172
}
2173
 
14179 bpr 2174
static char * convert_type (Result, oldtype)
6785 bpr 2175
     char *Result;
2176
     char *oldtype;
2177
{
2178
  int i;
2179
  str3 newtype;
2180
 
2181
  sprintf (newtype, "%.3s", oldtype);
2182
  for (i = 0; i <= 2; i++)
2183
    newtype[i] = toupper (newtype[i]);
2184
  if (newtype[0] == '~')
2185
    strcpy (newtype, "VAL");
2186
  if (newtype[0] == '*')
2187
    strcpy (newtype, "STR");
2188
  return strcpy (Result, newtype);
2189
}
2190
 
14179 bpr 2191
static char * convert_sybtype (Result, oldtype)
6785 bpr 2192
     char *Result;
2193
     char *oldtype;
2194
{
2195
  str3 newtype;
2196
 
2197
  /*  NewType := Copy(OldType,1,3); */
2198
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2199
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2200
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2201
  strcpy (newtype, "DU ");
2202
  if (!strcmp (oldtype, "H    "))
2203
    strcpy (newtype, "H  ");
2204
  if (!strcmp (oldtype, "C.ar "))
2205
    strcpy (newtype, "CAR");
2206
  if (!strcmp (oldtype, "C.2  "))
2207
    strcpy (newtype, "C2 ");
2208
  if (!strcmp (oldtype, "C.3  "))
2209
    strcpy (newtype, "C3 ");
2210
  if (!strcmp (oldtype, "C.1  "))
2211
    strcpy (newtype, "C1 ");
2212
  if (!strcmp (oldtype, "O.2  "))
2213
    strcpy (newtype, "O2 ");
2214
  if (!strcmp (oldtype, "O.3  "))
2215
    strcpy (newtype, "O3 ");
2216
  if (!strcmp (oldtype, "O.co2"))
2217
    strcpy (newtype, "O2 ");
2218
  if (!strcmp (oldtype, "O.spc"))
2219
    strcpy (newtype, "O3 ");
2220
  if (!strcmp (oldtype, "O.t3p"))
2221
    strcpy (newtype, "O3 ");
2222
  if (!strcmp (oldtype, "N.1  "))
2223
    strcpy (newtype, "N1 ");
2224
  if (!strcmp (oldtype, "N.2  "))
2225
    strcpy (newtype, "N2 ");
2226
  if (!strcmp (oldtype, "N.3  "))
2227
    strcpy (newtype, "N3 ");
2228
  if (!strcmp (oldtype, "N.pl3"))
2229
    strcpy (newtype, "NPL");
2230
  if (!strcmp (oldtype, "N.4  "))
2231
    strcpy (newtype, "N3+");
2232
  if (!strcmp (oldtype, "N.am "))
2233
    strcpy (newtype, "NAM");
2234
  if (!strcmp (oldtype, "N.ar "))
2235
    strcpy (newtype, "NAR");
2236
  if (!strcmp (oldtype, "F    "))
2237
    strcpy (newtype, "F  ");
2238
  if (!strcmp (oldtype, "Cl   "))
2239
    strcpy (newtype, "CL ");
2240
  if (!strcmp (oldtype, "Br   "))
2241
    strcpy (newtype, "BR ");
2242
  if (!strcmp (oldtype, "I    "))
2243
    strcpy (newtype, "I  ");
2244
  if (!strcmp (oldtype, "Al   "))
2245
    strcpy (newtype, "AL ");
2246
  if (!strcmp (oldtype, "ANY  "))
2247
    strcpy (newtype, "A  ");
2248
  if (!strcmp (oldtype, "Ca   "))
2249
    strcpy (newtype, "CA ");
2250
  if (!strcmp (oldtype, "Du   "))
2251
    strcpy (newtype, "DU ");
2252
  if (!strcmp (oldtype, "Du.C "))
2253
    strcpy (newtype, "DU ");
2254
  if (!strcmp (oldtype, "H.spc"))
2255
    strcpy (newtype, "H  ");
2256
  if (!strcmp (oldtype, "H.t3p"))
2257
    strcpy (newtype, "H  ");
2258
  if (!strcmp (oldtype, "HAL  "))
2259
    strcpy (newtype, "Cl ");
2260
  if (!strcmp (oldtype, "HET  "))
2261
    strcpy (newtype, "Q  ");
2262
  if (!strcmp (oldtype, "HEV  "))
2263
    strcpy (newtype, "DU ");
2264
  if (!strcmp (oldtype, "K    "))
2265
    strcpy (newtype, "K  ");
2266
  if (!strcmp (oldtype, "Li   "))
2267
    strcpy (newtype, "LI ");
2268
  if (!strcmp (oldtype, "LP   "))
2269
    strcpy (newtype, "LP ");
2270
  if (!strcmp (oldtype, "Na   "))
2271
    strcpy (newtype, "NA ");
2272
  if (!strcmp (oldtype, "P.3  "))
2273
    strcpy (newtype, "P3 ");
2274
  if (!strcmp (oldtype, "S.2  "))
2275
    strcpy (newtype, "S2 ");
2276
  if (!strcmp (oldtype, "S.3  "))
2277
    strcpy (newtype, "S3 ");
2278
  if (!strcmp (oldtype, "S.o  "))
2279
    strcpy (newtype, "SO ");
2280
  if (!strcmp (oldtype, "S.o2 "))
2281
    strcpy (newtype, "SO2");
2282
  if (!strcmp (oldtype, "Si   "))
2283
    strcpy (newtype, "SI ");
2284
  if (!strcmp (oldtype, "P.4  "))
2285
    strcpy (newtype, "P4 ");
2286
  return strcpy (Result, newtype);
2287
}
2288
 
14179 bpr 2289
static char * convert_MDLtype (Result, oldtype)
6785 bpr 2290
     char *Result, *oldtype;
2291
{
2292
  str3 newtype;
2293
 
2294
  /*  NewType := Copy(OldType,1,3); */
2295
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2296
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2297
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2298
  strcpy (newtype, "DU ");
2299
  if (!strcmp (oldtype, "H  "))
2300
    strcpy (newtype, "H  ");
2301
  if (!strcmp (oldtype, "C  "))
2302
    strcpy (newtype, "C3 ");
2303
  if (!strcmp (oldtype, "O  "))
2304
    strcpy (newtype, "O2 ");
2305
  if (!strcmp (oldtype, "N  "))
2306
    strcpy (newtype, "N3 ");
2307
  if (!strcmp (oldtype, "F  "))
2308
    strcpy (newtype, "F  ");
2309
  if (!strcmp (oldtype, "Cl "))
2310
    strcpy (newtype, "CL ");
2311
  if (!strcmp (oldtype, "Br "))
2312
    strcpy (newtype, "BR ");
2313
  if (!strcmp (oldtype, "I  "))
2314
    strcpy (newtype, "I  ");
2315
  if (!strcmp (oldtype, "Al "))
2316
    strcpy (newtype, "AL ");
2317
  if (!strcmp (oldtype, "ANY"))
2318
    strcpy (newtype, "A  ");
2319
  if (!strcmp (oldtype, "Ca "))
2320
    strcpy (newtype, "CA ");
2321
  if (!strcmp (oldtype, "Du "))
2322
    strcpy (newtype, "DU ");
2323
  if (!strcmp (oldtype, "K  "))
2324
    strcpy (newtype, "K  ");
2325
  if (!strcmp (oldtype, "Li "))
2326
    strcpy (newtype, "LI ");
2327
  if (!strcmp (oldtype, "LP "))
2328
    strcpy (newtype, "LP ");
2329
  if (!strcmp (oldtype, "Na "))
2330
    strcpy (newtype, "NA ");
2331
  if (!strcmp (oldtype, "P  "))
2332
    strcpy (newtype, "P3 ");
2333
  if (!strcmp (oldtype, "S  "))
2334
    strcpy (newtype, "S3 ");
2335
  if (!strcmp (oldtype, "Si "))
2336
    strcpy (newtype, "SI ");
2337
  if (!strcmp (oldtype, "P  "))
2338
    strcpy (newtype, "P4 ");
2339
  if (!strcmp (oldtype, "A  "))
2340
    strcpy (newtype, "A  ");
2341
  if (!strcmp (oldtype, "Q  "))
2342
    strcpy (newtype, "Q  ");
2343
  return strcpy (Result, newtype);
2344
}
2345
 
14179 bpr 2346
static char * get_element (Result, oldtype)
6785 bpr 2347
     char *Result;
2348
     char *oldtype;
2349
{
2350
  char elemstr[256];
2351
 
2352
  if (!strcmp (oldtype, "H   "))
2353
    strcpy (elemstr, "H ");
14179 bpr 2354
  /* if (!strcmp (oldtype, "D   "))  // v0.3n
6785 bpr 2355
     strcpy (elemstr, "D "); */
2356
  if (!strcmp (oldtype, "CAR "))
2357
    strcpy (elemstr, "C ");
2358
  if (!strcmp (oldtype, "C2  "))
2359
    strcpy (elemstr, "C ");
2360
  if (!strcmp (oldtype, "C3  "))
2361
    strcpy (elemstr, "C ");
2362
  if (!strcmp (oldtype, "C1  "))
2363
    strcpy (elemstr, "C ");
2364
  if (!strcmp (oldtype, "O2  "))
2365
    strcpy (elemstr, "O ");
2366
  if (!strcmp (oldtype, "O3  "))
2367
    strcpy (elemstr, "O ");
2368
  if (!strcmp (oldtype, "O2  "))
2369
    strcpy (elemstr, "O ");
2370
  if (!strcmp (oldtype, "O3  "))
2371
    strcpy (elemstr, "O ");
2372
  if (!strcmp (oldtype, "O3  "))
2373
    strcpy (elemstr, "O ");
2374
  if (!strcmp (oldtype, "N1  "))
2375
    strcpy (elemstr, "N ");
2376
  if (!strcmp (oldtype, "N2  "))
2377
    strcpy (elemstr, "N ");
2378
  if (!strcmp (oldtype, "N3  "))
2379
    strcpy (elemstr, "N ");
2380
  if (!strcmp (oldtype, "NPL "))
2381
    strcpy (elemstr, "N ");
2382
  if (!strcmp (oldtype, "N3+ "))
2383
    strcpy (elemstr, "N ");
2384
  if (!strcmp (oldtype, "NAM "))
2385
    strcpy (elemstr, "N ");
2386
  if (!strcmp (oldtype, "NAR "))
2387
    strcpy (elemstr, "N ");
2388
  if (!strcmp (oldtype, "F   "))
2389
    strcpy (elemstr, "F ");
2390
  if (!strcmp (oldtype, "CL  "))
2391
    strcpy (elemstr, "CL");
2392
  if (!strcmp (oldtype, "BR  "))
2393
    strcpy (elemstr, "BR");
2394
  if (!strcmp (oldtype, "I   "))
2395
    strcpy (elemstr, "I ");
2396
  if (!strcmp (oldtype, "AT  "))
2397
    strcpy (elemstr, "AT");
2398
  if (!strcmp (oldtype, "AL  "))
2399
    strcpy (elemstr, "AL");
2400
  if (!strcmp (oldtype, "DU  "))
2401
    strcpy (elemstr, "DU");
2402
  if (!strcmp (oldtype, "CA  "))
2403
    strcpy (elemstr, "CA");
2404
  if (!strcmp (oldtype, "DU  "))
2405
    strcpy (elemstr, "DU");
2406
  if (!strcmp (oldtype, "Cl  "))
2407
    strcpy (elemstr, "CL");
2408
  if (!strcmp (oldtype, "K   "))
2409
    strcpy (elemstr, "K ");
2410
  if (!strcmp (oldtype, "LI  "))
2411
    strcpy (elemstr, "LI");
2412
  if (!strcmp (oldtype, "LP  "))
2413
    strcpy (elemstr, "LP");
2414
  if (!strcmp (oldtype, "NA  "))
2415
    strcpy (elemstr, "NA");
2416
  if (!strcmp (oldtype, "P3  "))
2417
    strcpy (elemstr, "P ");
2418
  if (!strcmp (oldtype, "S2  "))
2419
    strcpy (elemstr, "S ");
2420
  if (!strcmp (oldtype, "S3  "))
2421
    strcpy (elemstr, "S ");
2422
  if (!strcmp (oldtype, "SO  "))
2423
    strcpy (elemstr, "S ");
2424
  if (!strcmp (oldtype, "SO2 "))
2425
    strcpy (elemstr, "S ");
2426
  if (!strcmp (oldtype, "SI  "))
2427
    strcpy (elemstr, "SI");
2428
  if (!strcmp (oldtype, "P4  "))
2429
    strcpy (elemstr, "P ");
2430
  if (!strcmp (oldtype, "A   "))
2431
    strcpy (elemstr, "A ");
2432
  if (!strcmp (oldtype, "Q   "))
2433
    strcpy (elemstr, "Q ");
2434
  return strcpy (Result, elemstr);
2435
}
2436
 
14179 bpr 2437
static char * get_sybelement (Result, oldtype)
6785 bpr 2438
     char *Result;
2439
     char *oldtype;
2440
{
2441
  int i;
2442
  str2 elemstr;
2443
 
2444
  if (strpos2 (oldtype, ".", 1) < 2)
2445
    sprintf (elemstr, "%.2s", oldtype);
14179 bpr 2446
  else {
2447
    sprintf (elemstr, "%.*s", strpos2 (oldtype, ".", 1) - 1, oldtype);
2448
    if (strlen (elemstr) < 2)
2449
            strcat (elemstr, " ");
2450
  }
6785 bpr 2451
  for (i = 0; i <= 1; i++)
2452
    elemstr[i] = toupper (elemstr[i]);
2453
  return strcpy (Result, elemstr);
2454
}
2455
 
14179 bpr 2456
static char * get_MDLelement (Result, oldtype)
6785 bpr 2457
     char *Result;
2458
     char *oldtype;
2459
{
2460
  int i;
2461
  str2 elemstr;
2462
 
2463
  sprintf (elemstr, "%.2s", oldtype);
2464
  for (i = 0; i <= 1; i++)
2465
    elemstr[i] = toupper (elemstr[i]);
2466
  if (elemstr[0] == '~')
2467
    strcpy (elemstr, "??");
2468
  if (elemstr[0] == '*')
2469
    strcpy (elemstr, "??");
2470
  return strcpy (Result, elemstr);
2471
}
2472
 
14179 bpr 2473
static void read_molfile (mfilename)
6785 bpr 2474
     char *mfilename;
2475
{
2476
  /* reads ALCHEMY mol files */
6787 kbelabas 2477
  int n;
6785 bpr 2478
  char rline[256], tmpstr[256];
2479
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2480
  float xval, yval, zval, chgval;
2481
  char a1str[256], a2str[256], elemstr[256];
2482
  int a1val, a2val, ri;
2483
  char STR1[256];
2484
  int FORLIM;
2485
  atom_rec *WITH;
2486
  bond_rec *WITH1;
2487
 
2488
  if (n_atoms > 0)
2489
    zap_molecule ();
2490
  ri = li;
2491
  strcpy (rline, molbuf[ri - 1]);
2492
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2493
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2494
  strsub (tmpstr, rline, 14, 5);
6787 kbelabas 2495
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2496
  strsub (molname, rline, 42, (int) (strlen (rline) - 42L));
2497
  /* try */
2498
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2499
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2500
  ring = safe_calloc (1, sizeof (ringlist));
2501
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2502
  /* except
2503
     on e:Eoutofmemory do
2504
     begin
2505
     writeln('Not enough memory');
2506
     halt(4);
2507
     end;
2508
     end; */
2509
  n_heavyatoms = 0;
2510
  n_heavybonds = 0;
2511
  n_Ctot = 0;                   /* v0.3g */
2512
  n_Otot = 0;                   /* v0.3g */
2513
  n_Ntot = 0;                   /* v0.3g */
2514
  FORLIM = n_atoms;
14179 bpr 2515
  for (n = 1; n <= FORLIM; n++) {
2516
    ri++;
2517
    strcpy (rline, molbuf[ri - 1]);
2518
    strsub (atomtype, rline, 7, 4);
2519
    sprintf (STR1, "%c", toupper (*atomtype));
2520
    strcpy (atomtype, STR1);    /* fixed in v0.3f */
2521
    get_element (elemstr, atomtype);
2522
    if (!strcmp (elemstr, "C "))
2523
            n_Ctot++;
2524
    if (!strcmp (elemstr, "O "))
2525
            n_Otot++;
2526
    if (!strcmp (elemstr, "N "))
2527
            n_Ntot++;
2528
    convert_type (newatomtype, atomtype);
2529
    strsub (xstr, rline, 14, 7);
2530
    strsub (ystr, rline, 23, 7);
2531
    strsub (zstr, rline, 32, 7);
2532
    strsub (chgstr, rline, 43, 7);
2533
    (void)sscanf (xstr, "%g", &xval);
2534
    (void)sscanf (ystr, "%g", &yval);
2535
    (void)sscanf (zstr, "%g", &zval);
2536
    (void)sscanf (chgstr, "%g", &chgval);
2537
    WITH = &atom[n - 1];
2538
    strcpy (WITH->element, elemstr);
2539
    strcpy (WITH->atype, newatomtype);
2540
    WITH->x = xval;
2541
    WITH->y = yval;
2542
    WITH->z = zval;
2543
    WITH->real_charge = chgval;
2544
    if (is_heavyatom (n)) {
2545
            n_heavyatoms++;
2546
            WITH->heavy = true;
2547
            if (is_metal (n))
2548
              WITH->metal = true;
2549
          }
2550
    WITH->nvalences = get_nvalences (WITH->element);    /* v0.3m   */
2551
  }
6785 bpr 2552
  /*
2553
     with atom^[n] do
2554
     begin
2555
     x := 0; y := 0; z := 0;  (* v0.3g
2556
     formal_charge  := 0;
2557
     real_charge    := 0;
2558
     Hexp           := 0;
2559
     Htot           := 0;
2560
     neighbor_count := 0;
2561
     ring_count     := 0;
2562
     arom           := false;
2563
     stereo_care    := false;
2564
     heavy          := false;
2565
     metal          := false;
2566
     tag            := false;
2567
     end;
2568
   */
2569
  FORLIM = n_bonds;
14179 bpr 2570
  for (n = 0; n < FORLIM; n++) {
2571
    ri++;
2572
    strcpy (rline, molbuf[ri - 1]);
2573
    strsub (a1str, rline, 9, 3);
2574
    strsub (a2str, rline, 15, 3);
2575
    (void)sscanf(a1str, "%d", &a1val);
2576
    (void)sscanf(a2str, "%d", &a2val);
2577
    WITH1 = &bond[n];
2578
    WITH1->a1 = a1val;
2579
    WITH1->a2 = a2val;
2580
    WITH1->btype = rline[19];
2581
    WITH1->ring_count = 0;
2582
    WITH1->arom = false;
2583
    WITH1->topo = btopo_any;
2584
    WITH1->stereo = bstereo_any;
2585
    WITH1->mdl_stereo = 0;      /* v0.3n */
2586
    if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2587
            n_heavybonds++;
2588
  }
6785 bpr 2589
  memset (ring, 0, sizeof (ringlist));
14179 bpr 2590
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
2591
    ringprop[n].size = 0;
2592
    ringprop[n].arom = false;
2593
    ringprop[n].envelope = false;
2594
  }
6785 bpr 2595
  li = ri + 1;
2596
}
2597
 
14179 bpr 2598
static void read_mol2file (mfilename) char *mfilename;
6785 bpr 2599
{
2600
  /* reads SYBYL mol2 files */
2601
  int n, code;
2602
  char sybatomtype[6];
2603
  char tmpstr[256], rline[256];
2604
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2605
  float xval, yval, zval, chgval;
2606
  char a1str[256], a2str[256], elemstr[256];
2607
  int a1val, a2val, ri, FORLIM;
2608
  atom_rec *WITH;
2609
  bond_rec *WITH1;
2610
 
2611
  if (n_atoms > 0)
2612
    zap_molecule ();
2613
  *rline = '\0';
2614
  ri = li - 1;
14179 bpr 2615
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) == 0)) {
2616
    ri++;
2617
    strcpy (rline, molbuf[ri - 1]);
2618
  }
2619
  if (ri < molbufindex) {
2620
    ri++;
2621
    strcpy (molname, molbuf[ri - 1]);
2622
  }
2623
  if (ri < molbufindex) {
2624
    ri++;
2625
    strcpy (rline, molbuf[ri - 1]);
2626
  }
6785 bpr 2627
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2628
  (void)sscanf (tmpstr, "%d", &n_atoms);
14179 bpr 2629
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 2630
  strsub (tmpstr, rline, 7, 5);
6787 kbelabas 2631
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2632
  /* try */
14179 bpr 2633
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 2634
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2635
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2636
  ring = safe_calloc (1, sizeof (ringlist));
2637
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2638
  /* except
2639
     on e:Eoutofmemory do
2640
     begin
2641
     writeln('Not enough memory');
2642
     halt(4);
2643
     end;
2644
     end; */
2645
  n_heavyatoms = 0;
2646
  n_heavybonds = 0;
2647
  n_Ctot = 0;                   /* v0.3g */
2648
  n_Otot = 0;                   /* v0.3g */
2649
  n_Ntot = 0;                   /* v0.3g */
14179 bpr 2650
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>ATOM", 1) == 0)) {
2651
    ri++;
2652
    strcpy (rline, molbuf[ri - 1]);
2653
  }
6785 bpr 2654
  FORLIM = n_atoms;
14179 bpr 2655
  for (n = 1; n <= FORLIM; n++) {
2656
    /*
2657
      with atom^[n] do
2658
      begin
2659
      x := 0; y := 0; z := 0;  (* v0.3g
2660
      formal_charge  := 0;
2661
      real_charge    := 0;
2662
      Hexp           := 0;
2663
      Htot           := 0;
2664
      neighbor_count := 0;
2665
      ring_count     := 0;
2666
      arom           := false;
2667
      stereo_care    := false;
2668
      heavy          := false;
2669
      metal          := false;
2670
      tag            := false;
2671
      end;
2672
    */
2673
    if (ri < molbufindex) {
2674
            ri++;
2675
            strcpy (rline, molbuf[ri - 1]);
2676
          }
2677
    strsub (sybatomtype, rline, 48, 5);
2678
    get_sybelement (elemstr, sybatomtype);
2679
    if (!strcmp (elemstr, "C "))
2680
            n_Ctot++;
2681
    if (!strcmp (elemstr, "O "))
2682
            n_Otot++;
2683
    if (!strcmp (elemstr, "N "))
2684
            n_Ntot++;
2685
    convert_sybtype (newatomtype, sybatomtype);
2686
    strsub (xstr, rline, 18, 9);
2687
    strsub (ystr, rline, 28, 9);
2688
    strsub (zstr, rline, 38, 9);
2689
    strsub (chgstr, rline, 70, 9);
2690
    (void)sscanf (xstr, "%g", &xval);
2691
    (void)sscanf (ystr, "%g", &yval);
2692
    (void)sscanf (zstr, "%g", &zval);
2693
    (void)sscanf (chgstr, "%g", &chgval);
2694
    WITH = &atom[n - 1];
2695
    strcpy (WITH->element, elemstr);
2696
    strcpy (WITH->atype, newatomtype);
2697
    WITH->x = xval;
2698
    WITH->y = yval;
2699
    WITH->z = zval;
2700
    WITH->real_charge = chgval;
2701
    if (is_heavyatom (n)) {
2702
            n_heavyatoms++;
2703
            WITH->heavy = true;
2704
            if (is_metal (n))
2705
              WITH->metal = true;
2706
          }
2707
    WITH->nvalences = get_nvalences (WITH->element);    /* v0.3m   */
2708
  }
2709
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>BOND", 1) == 0)) {
2710
    ri++;
2711
    strcpy (rline, molbuf[ri - 1]);
2712
  }
6785 bpr 2713
  FORLIM = n_bonds;
14179 bpr 2714
  for (n = 0; n < FORLIM; n++) {
2715
    if (ri < molbufindex) {
2716
            ri++;
2717
            strcpy (rline, molbuf[ri - 1]);
2718
          }
2719
    strsub (a1str, rline, 9, 3);
2720
    strsub (a2str, rline, 14, 3);
2721
    code = (sscanf (a1str, "%d", &a1val) == 0);
2722
    if (code != 0)
2723
            printf ("%s\007\n", rline);
2724
    code = (sscanf (a2str, "%d", &a2val) == 0);
2725
    if (code != 0)
2726
            printf ("%s\007\n", rline);
2727
    WITH1 = &bond[n];
2728
    WITH1->a1 = a1val;
2729
    WITH1->a2 = a2val;
2730
    if (rline[17] == '1')
2731
            WITH1->btype = 'S';
2732
    if (rline[17] == '2')
2733
            WITH1->btype = 'D';
2734
    if (rline[17] == '3')
2735
            WITH1->btype = 'T';
2736
    if (rline[17] == 'a')
2737
            WITH1->btype = 'A';
2738
    WITH1->ring_count = 0;
2739
    WITH1->arom = false;
2740
    WITH1->topo = btopo_any;
2741
    WITH1->stereo = bstereo_any;
2742
    WITH1->mdl_stereo = 0;      /* v0.3n */
2743
    if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2744
            n_heavybonds++;
2745
  }
6785 bpr 2746
  memset (ring, 0, sizeof (ringlist));
14179 bpr 2747
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
2748
    ringprop[n].size = 0;
2749
    ringprop[n].arom = false;
2750
    ringprop[n].envelope = false;
2751
  }
6785 bpr 2752
  li = ri + 1;
2753
}
2754
 
14179 bpr 2755
static void read_charges (chgstring_)
6785 bpr 2756
     char *chgstring_;
2757
{
2758
  char chgstring[256];
2759
  int a_id, a_chg;
2760
  /* int n_chrg;*/
2761
 
2762
  /* typical example: a molecule with 2 cations + 1 anion */
2763
  /* M  CHG  3   8   1  10   1  11  -1 */
2764
  strcpy (chgstring, chgstring_);
2765
  if (strpos2 (chgstring, "M  CHG", 1) <= 0)
2766
    return;
2767
  strdelete (chgstring, 1, 6);
2768
  left_trim (chgstring);
14179 bpr 2769
  /* n_chrg = left_int (chgstring);*/
6785 bpr 2770
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2771
  /* p2c: checkmol.pas, line 2077:
2772
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2773
  /*$IFDEF debug */
2774
  /*if (n_chrg == 0)
2775
     debugoutput ("strange... M  CHG present, but no charges found"); */
2776
  /*$ENDIF */
14626 bpr 2777
  left_int (chgstring); /* delete the first one, that is the number of atoms */
14179 bpr 2778
  while (*chgstring != '\0') {
2779
    a_id = left_int (chgstring);
2780
    a_chg = left_int (chgstring);
2781
    if (a_id != 0 && a_chg != 0)
14626 bpr 2782
            atom[a_id - 1].formal_charge = a_chg;
2783
          //printf ("CHG %i %i\n", a_id, a_chg);
14179 bpr 2784
  }
6785 bpr 2785
}
2786
 
14179 bpr 2787
static void read_isotopes (char *isotopestring_)
6785 bpr 2788
{
2789
  char isotopestring[256];
2790
  int a_id, a_nucleon_number;
2791
  /* int n_isotopes;*/
2792
 
2793
  /* typical example: a molecule with 2 cations + 1 anion */
2794
  /* M  CHG  3   8   1  10   1  11  -1 */
2795
  strcpy (isotopestring, isotopestring_);
2796
  if (strpos2 (isotopestring, "M  ISO", 1) <= 0)
2797
    return;
2798
  strdelete (isotopestring, 1, 6);
2799
  left_trim (isotopestring);
14626 bpr 2800
  left_int (isotopestring);
14179 bpr 2801
  while (*isotopestring != '\0') {
2802
    a_id = left_int (isotopestring);
2803
    a_nucleon_number = left_int (isotopestring);
2804
    if (a_id != 0 && a_nucleon_number != 0) {
2805
            atom[a_id - 1].nucleon_number = a_nucleon_number;
2806
            if (!strcmp (atom[a_id - 1].element, "H ")) {
6785 bpr 2807
              atom[a_id - 1].heavy = true;
2808
              n_heavyatoms++;
2809
              strcpy (atom[a_id - 1].atype, "DU ");
2810
            }
14179 bpr 2811
          }
14626 bpr 2812
    //printf ("ISO %i, %i\n", a_id, a_nucleon_number);
14179 bpr 2813
  }
6785 bpr 2814
}
2815
 
14179 bpr 2816
static void read_radicals (radstring_)
6785 bpr 2817
     char *radstring_;
2818
{
2819
  char radstring[256];
6788 kbelabas 2820
  int a_id, a_rad;
6785 bpr 2821
 
2822
  /* typical example: a molecule with 2 cations + 1 anion */
2823
  /* M  CHG  3   8   1  10   1  11  -1 */
2824
  strcpy (radstring, radstring_);
2825
  if (strpos2 (radstring, "M  RAD", 1) <= 0)
2826
    return;
2827
  strdelete (radstring, 1, 6);
2828
  left_trim (radstring);
14626 bpr 2829
  left_int (radstring);
6785 bpr 2830
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2831
  /* p2c: checkmol.pas, line 2077:
2832
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2833
  /*$IFDEF debug */
2834
  /*if (n_chrg == 0)
2835
     debugoutput ("strange... M  CHG present, but no charges found"); */
2836
  /*$ENDIF */
14179 bpr 2837
  while (*radstring != '\0') {
2838
    a_id = left_int (radstring);
2839
    a_rad = left_int (radstring);
2840
    if (a_id != 0 && a_rad != 0)
2841
            atom[a_id - 1].radical_type = a_rad;
2842
    //printf ("RAD %i %i\n", a_id, a_rad);
2843
  }
6785 bpr 2844
}
2845
 
14179 bpr 2846
static void read_MDLmolfile (char *mfilename)
6785 bpr 2847
{
2848
  /* reads MDL mol files */
2849
  int n, v, tmp_n_atoms, tmp_n_bonds, code;     /* v0.3l */
2850
  char rline[256], tmpstr[256];
2851
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2852
  float xval, yval, zval, chgval;
2853
  char a1str[256], a2str[256], elemstr[256];
2854
  int a1val, a2val, ri, rc, bt, bs;
2855
  int sepcount = 0;
2856
  int i;                        /* v0.3j */
2857
  boolean clearcharges = true;  /* v0.3j */
2858
  char STR1[256];
14179 bpr 2859
  /*  int FORLIM;*/
6785 bpr 2860
  atom_rec *WITH;
2861
  bond_rec *WITH1;
2862
 
2863
  /* v0.3j */
2864
  if (n_atoms > 0)
2865
    zap_molecule ();
2866
  /*cm_mdlmolfile := false; */
2867
  *rline = '\0';
2868
  ri = li;
2869
  strcpy (molname, molbuf[ri - 1]);     /* line 1 */
2870
  if (ri < molbufindex)         /* line 2 */
2871
    ri++;
2872
  strcpy (rline, molbuf[ri - 1]);
14179 bpr 2873
  if (strpos2 (rline, "CheckMol", 1) == 3) {
2874
    /*cm_mdlmolfile := true; */
2875
    found_arominfo = true;
2876
    tmfcode = 1;                /* v0.3m (begin) */
2877
    code = 0;
2878
    if ((strlen (rline) >= 39) && (strpos2 (rline, "TMF", 1) == 35)) {
2879
      /* v0.3m; encoding of tweaklevel */
2880
            strsub (tmpstr, rline, 38, 2);
2881
            code = (sscanf (tmpstr, "%d", &tmfcode) == 0);
2882
          }
2883
    if (code != 0 || tmfcode != tweaklevel)
2884
            tmfmismatch = true;
2885
    else
2886
            tmfmismatch = false;
17890 bpr 2887
      if ((strpos2 (rline, ":r0", 1) >= 40 && ringsearch_mode != rs_sar) ||
14179 bpr 2888
                (strpos2 (rline, ":r1", 1) >= 40 && ringsearch_mode != rs_ssr))
2889
              tmfmismatch = true;
17890 bpr 2890
      if ((strpos2 (rline, ":m0", 1) >= 40 && opt_metalrings == true) ||
14179 bpr 2891
                (strpos2 (rline, ":m1", 1) >= 40 && opt_metalrings == false))
2892
              tmfmismatch = true;
2893
      /* p2c: checkmol.pas, line 2128:
2894
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
2895
            /*$IFDEF debug */
2896
            //if (tmfmismatch)
2897
            //printf ("\"tweaked\" molfile: version mismatch!\n");
2898
            // else
2899
            //printf ("\"tweaked\" molfile: version OK");
2900
          }
2901
      /*$ENDIF */
2902
      /* v0.3m (end) */
2903
      if (ri < molbufindex)             /* line 3 */
2904
        ri++;
2905
      strcpy (rline, molbuf[ri - 1]);
2906
      strcpy (molcomment, rline);
2907
      if (ri < molbufindex)             /* line 4 */
2908
        ri++;
2909
      strcpy (rline, molbuf[ri - 1]);
2910
      sprintf (tmpstr, "%.3s", rline);
2911
      (void)sscanf (tmpstr, "%d", &n_atoms);
2912
      strsub (tmpstr, rline, 4, 3);
2913
      (void)sscanf (tmpstr, "%d", &n_bonds);
2914
      strsub (tmpstr, rline, 10, 3);
2915
      /* if it is a CheckMol-tweaked molfile, this is the number of rings */
2916
      n_cmrings = 0;
2917
      code = (sscanf (tmpstr, "%d", &n_cmrings) == 0);
2918
      if (code != 0)
2919
        n_cmrings = 0;
2920
      /* do some range checking for n_atoms, n_bonds; new in v0.3l */
2921
      tmp_n_atoms = n_atoms;
2922
      if (n_atoms > max_atoms)
2923
        n_atoms = max_atoms;
2924
      if (n_atoms < 0)
2925
        n_atoms = 0;
2926
      tmp_n_bonds = n_bonds;
2927
      if (n_bonds > max_bonds)
2928
        n_bonds = max_bonds;
2929
      if (n_bonds < 0)
2930
        n_bonds = 0;
2931
      if (n_atoms == 0
6785 bpr 2932
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 2933
        && opt_verbose
6785 bpr 2934
#endif
14179 bpr 2935
    ) {                                 /* v0.3l */
2936
        printf ("WARNING: Possible NoStruct read!\n");
2937
        printf ("NoStructs are proprietary, obsolete and dangerous.\n");
2938
      }
2939
      /* try */
2940
      atom = safe_calloc (n_atoms, sizeof (atom_rec));
2941
      bond = safe_calloc (n_bonds, sizeof (bond_rec));
2942
      /* this would be only one safe_calloc() in C;  v0.3l */
2943
      ring = safe_calloc (1, sizeof (ringlist));
2944
      ringprop = safe_calloc (1, sizeof (ringprop_type));
2945
      /* except
2946
      on e:Eoutofmemory do
2947
      begin
2948
      writeln('Not enough memory');
2949
      (* close(molfile);
2950
      halt(4);
2951
      exit;
2952
      end;
2953
      end; */
2954
      /* check for the chirality flag */
2955
      if (strlen (rline) > 14 && rline[14] == '1')      /* new in v0.3f */
2956
        chir_flag = true;
2957
      n_heavyatoms = 0;
2958
      n_heavybonds = 0;
2959
      n_Ctot = 0;                       /* v0.3g */
2960
      n_Otot = 0;                       /* v0.3g */
2961
      n_Ntot = 0;                       /* v0.3g */
2962
      if (n_atoms > 0) {                                /* v0.3l */
2963
        for (n = 1; n <= tmp_n_atoms; n++) {
2964
                if (n <= max_atoms)
2965
                  v = n;
2966
                else
2967
                  v = max_atoms;
2968
                /* just for safety; v0.3l */
2969
                /*
2970
                with atom^[v] do
2971
                begin
2972
                x := 0; y := 0; z := 0;  (* v0.3g
2973
                formal_charge  := 0;
2974
                real_charge    := 0;
2975
                Hexp           := 0;
2976
                Htot           := 0;
2977
                neighbor_count := 0;
2978
                ring_count     := 0;
2979
                arom           := false;
2980
                stereo_care    := false;
2981
                metal          := false;
2982
                heavy          := false;
2983
                tag            := false;
2984
                end;
2985
                */
2986
                /* replaced by fillchar() after getmem() (see above); v0.3l */
2987
                ri++;
2988
                strcpy (rline, molbuf[ri - 1]);
2989
                strsub (atomtype, rline, 32, 3);
2990
                get_MDLelement (elemstr, atomtype);
2991
                if (!strcmp (elemstr, "C "))
2992
                  n_Ctot++;
2993
                if (!strcmp (elemstr, "O "))
2994
                  n_Otot++;
2995
                if (!strcmp (elemstr, "N "))
2996
                  n_Ntot++;
6785 bpr 2997
 
14179 bpr 2998
                convert_MDLtype (newatomtype, atomtype);
2999
                strsub (xstr, rline, 1, 10);    /* fixed in v0.3k (was: 2,9 etc.) */
3000
                strsub (ystr, rline, 11, 10);
3001
                strsub (zstr, rline, 21, 10);
3002
                /*chgstr := '0'; */
3003
                strsub (chgstr, rline, 37, 3);  /* new in v0.3j */
3004
                (void)sscanf (chgstr, "%f", &chgval);
3005
                if (chgval != 0) {
3006
                  if (chgval >= 1 && chgval <= 7)
3007
                          chgval = 4.0 - chgval;
3008
                  else {
3009
                          chgval = 0.0;
3010
                        }
3011
                }                       /* end (v0.3j) */
3012
                (void)sscanf (xstr, "%f", &xval);
3013
                (void)sscanf (ystr, "%f", &yval);
3014
                (void)sscanf (zstr, "%f", &zval);
3015
                /* v0.3k: removed superfluous val(chgstr,chgval,code) */
3016
                WITH = &atom[v - 1];
3017
                strcpy (WITH->element, elemstr);
3018
                if (!strcmp (elemstr, "A ") || !strcmp (elemstr, "Q ") ||
3019
                    !strcmp (elemstr, "X "))
3020
                  /* 'X ' added in v0.3n */
3021
                  found_querymol = true;
6785 bpr 3022
 
14179 bpr 3023
                strcpy (WITH->atype, newatomtype);
6785 bpr 3024
 
14179 bpr 3025
                if (!strcmp (elemstr, "D ")) {
3026
                  strcpy (WITH->element, "H ");
3027
                  WITH->nucleon_number = 2;
3028
                }                       /* 0.3x */
3029
                if (!strcmp (elemstr, "T ")) {
3030
                  strcpy (WITH->element, "H ");
3031
                  WITH->nucleon_number = 3;
3032
                }                       /* 0.3x */
6785 bpr 3033
 
14179 bpr 3034
                WITH->x = xval;
3035
                WITH->y = yval;
3036
                WITH->z = zval;
3037
                WITH->formal_charge = (long) floor (chgval + 0.5);
3038
                WITH->real_charge = 0.0;        /* v0.3j */
3039
                /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3040
                if (strlen (rline) > 37 && rline[37] == '0') {
3041
                  WITH->arom = true;
3042
                  found_arominfo = true;
3043
                }
3044
                /* new in v0.3d: read stereo care flag */
3045
                if (strlen (rline) > 47 && rline[47] == '1')
3046
                  WITH->stereo_care = true;
3047
                if (is_heavyatom (n)) {
3048
                  n_heavyatoms++;
3049
                  WITH->heavy = true;
3050
                  if (is_metal (n))
3051
                          WITH->metal = true;
3052
                }
3053
                WITH->nvalences = get_nvalences (WITH->element);
3054
                /* v0.3m                 */
3055
              }
3056
      }                         /* if (n_atoms > 0)... */
3057
      if (n_bonds > 0) {                                /* v0.3l */
3058
        for (n = 1; n <= tmp_n_bonds; n++) {
3059
                if (n <= max_bonds)
3060
                  v = n;
3061
                else
3062
                  v = max_bonds;
3063
                /* just for safety; v0.3l */
3064
                ri++;
3065
                strcpy (rline, molbuf[ri - 1]);
3066
                sprintf (a1str, "%.3s", rline);
3067
                strsub (a2str, rline, 4, 3);
3068
                code = (sscanf (a1str, "%d", &a1val) == 0);
3069
                if (code != 0)  /* v0.3l */
3070
                  a1val = 1;
3071
                code = (sscanf (a2str, "%d", &a2val) == 0);
3072
                if (code != 0)  /* v0.3l */
3073
                  a2val = 1;
3074
                WITH1 = &bond[v - 1];
3075
                WITH1->a1 = a1val;
3076
                WITH1->a2 = a2val;
3077
                if (rline[8] == '1')    /* single */
3078
                  WITH1->btype = 'S';
3079
                if (rline[8] == '2')    /* double */
3080
                  WITH1->btype = 'D';
3081
                if (rline[8] == '3')    /* triple */
3082
                  WITH1->btype = 'T';
3083
                if (rline[8] == '4')    /* aromatic */
3084
                  WITH1->btype = 'A';
3085
                if (rline[8] == '5')    /* single or double */
3086
                  WITH1->btype = 'l';
3087
                if (rline[8] == '6')    /* single or aromatic */
3088
                  WITH1->btype = 's';
3089
                if (rline[8] == '7')    /* double or aromatic */
3090
                  WITH1->btype = 'd';
3091
                if (rline[8] == '8')    /* any */
3092
                  WITH1->btype = 'a';
3093
                sprintf (STR1, "%c", WITH1->btype);
3094
                if (strpos2 ("lsda", STR1, 1) > 0)
3095
                  found_querymol = true;
3096
                WITH1->arom = false;
3097
                WITH1->q_arom = false;  /* 0.3p */
3098
                /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3099
                if (WITH1->btype == 'A' || rline[7] == '0') {
3100
                  WITH1->arom = true;
3101
                  if (rline[7] == '0')
3102
                          found_arominfo = true;
3103
                }
3104
                strsub (tmpstr, rline, 13, 3);
3105
                /* new in v0.3d: read ring_count from tweaked molfile */
3106
                code = (sscanf (tmpstr, "%d", &rc) == 0);
3107
                if (code != 0 || rc < 0 || progmode == pmCheckMol || tmfmismatch)
3108
                  WITH1->ring_count = 0;
3109
                else
3110
                 WITH1->ring_count = rc;
3111
                /* v0.3n: added tmfmismatch check */
3112
                strsub (tmpstr, rline, 16, 3);  /* new in v0.3d: read bond topology; */
3113
                code = (sscanf (tmpstr, "%d", &bt) == 0);
3114
                /* extended features are encoded by leading zero */
3115
                if (code != 0 || (unsigned long) bt > 2)
3116
                  WITH1->topo = btopo_any;
3117
                else {
3118
                  if (tmpstr[1] == '0')
3119
                          WITH1->topo = bt + 3;
3120
                  else
3121
                          WITH1->topo = bt;
3122
                }
3123
          /* v0.3n changed >5 into >2 */
3124
          /* new in v0.3d: add stereo property from MDL "stereo care" flag in atom block */
3125
          WITH1->stereo = bstereo_any;
3126
          if (WITH1->btype == 'D') {
3127
            if (atom[WITH1->a1 - 1].stereo_care
3128
                && atom[WITH1->a2 - 1].stereo_care) {           /* this is the MDL-conformant encoding, */
3129
              WITH1->stereo = bstereo_xyz;      /* for an alternative see below */
3130
              ez_flag = true;   /* v0.3f */
3131
            }
3132
                  else {                /* this extended feature is encoded by a leading zero */
3133
                          strsub (tmpstr, rline, 10, 3);
3134
                          /* new in v0.3d: read bond stereo specification; */
3135
                          code = (sscanf (tmpstr, "%d", &bs) == 0);
3136
                          WITH1->mdl_stereo = bs;       /* v0.3n */
3137
                          if (code != 0 || bs <= 0 || bs > 2)
3138
                            WITH1->stereo = bstereo_any;
3139
                          else
3140
                            WITH1->stereo = bstereo_xyz;
3141
                          if (tmpstr[1] == '0')
3142
                            WITH1->stereo = bstereo_xyz;
3143
                        }
3144
                }
3145
                /*if stereo <> bstereo_any then ez_search := true; */
3146
                if (WITH1->stereo != bstereo_any)       /* changed in v0.3f */
3147
                  ez_flag = true;
3148
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '1')
3149
                  WITH1->stereo = bstereo_up;
3150
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '6')
3151
                  WITH1->stereo = bstereo_down;
3152
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '4')
3153
                  WITH1->stereo = bstereo_either;       /* 0.3x */
3154
                if (WITH1->btype == 'D' && strlen (rline) > 11 && rline[11] == '3')
3155
                  WITH1->stereo = bstereo_double_either;        /* 0.3x */
3156
                strsub (tmpstr, rline, 10, 3);
3157
                /* new in v0.3n: save original bond stereo specification; */
3158
                (void)sscanf (tmpstr, "%d", &bs);
3159
                /* v0.3n */
3160
          /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3161
                WITH1->mdl_stereo = bs; /* v0.3n */
3162
                if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
3163
                  n_heavybonds++;
3164
              }
3165
      }                         /* if (n_bonds > 0)... */
3166
      while (ri < molbufindex && sepcount < 1) {
3167
        ri++;
3168
        strcpy (rline, molbuf[ri - 1]);
3169
    if (strpos2 (rline, "M  CHG", 1) > 0) {                     /* new in v0.3j */
3170
            if (clearcharges) {                 /* "M  CHG" supersedes all "old-style" charge values */
6785 bpr 3171
 
3172
              for (i = 0; i < n_atoms; i++)
14179 bpr 3173
                atom[i].formal_charge = 0;
6785 bpr 3174
            }
14179 bpr 3175
            read_charges (rline);
3176
            clearcharges = false;
3177
            /* subsequent "M  CHG" lines must not clear previous values */
3178
          }
6785 bpr 3179
 
14179 bpr 3180
    if (strpos2 (rline, "M  ISO", 1) > 0)
3181
            read_isotopes (rline);      /* 0.3x */
6785 bpr 3182
 
14179 bpr 3183
    if (strpos2 (rline, "M  RAD", 1) > 0)
3184
            read_radicals (rline);      /* 0.3x */
6785 bpr 3185
 
14179 bpr 3186
    if (strpos2 (rline, "$$$$", 1) > 0) {
3187
            sepcount++;
3188
            if (molbufindex > ri + 2)   /* we assume this is an SDF file */
3189
              mol_in_queue = true;
3190
          }
3191
  }
6785 bpr 3192
  memset (ring, 0, sizeof (ringlist));
14179 bpr 3193
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
3194
    ringprop[n].size = 0;
3195
    ringprop[n].arom = false;
3196
    ringprop[n].envelope = false;
3197
  }
6785 bpr 3198
  li = ri + 1;
3199
}
3200
 
14179 bpr 3201
static void write_MDLmolfile ()
6785 bpr 3202
{
3203
  int i;
3204
  char tmpstr[256];
3205
  char wline[256];
3206
  int a_chg;
3207
  int a_iso;
3208
  int a_rad;
3209
  char tmflabel[256];           /* v0.3m */
3210
  char STR1[256];
3211
  /*char STR7[256];*/
3212
  int FORLIM;
3213
 
3214
  sprintf (tmflabel, "%d", (int) tweaklevel);   /* v0.3m */
3215
  while (strlen (tmflabel) < 2) /* v0.3m */
3216
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
3217
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
3218
  if (strlen (molname) > 80)
3219
    sprintf (molname, "%.80s", strcpy (STR1, molname));
3220
  puts (molname);
3221
  printf ("  CheckMol                        %s", tmflabel);    /* v0.3m */
3222
  if (ringsearch_mode == rs_sar)        /* v0.3m */
3223
    printf (":r0");
3224
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
3225
    printf (":r1");
3226
  if (opt_metalrings)
3227
    printf (":m1");
3228
  else
3229
    printf (":m0");
3230
  /* v0.3m */
3231
  printf ("\n%s\n", molcomment);
3232
  *wline = '\0';
3233
  *tmpstr = '\0';
3234
  sprintf (tmpstr, "%d", n_atoms);
3235
  lblank (3L, tmpstr);
3236
  strcat (wline, tmpstr);
3237
  *tmpstr = '\0';               /* first 3 digits: number of atoms */
3238
  sprintf (tmpstr, "%d", n_bonds);
3239
  lblank (3L, tmpstr);
3240
  strcat (wline, tmpstr);
3241
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
3242
  strcpy (tmpstr, "  0");
3243
  strcat (wline, tmpstr);
3244
  *tmpstr = '\0';               /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 3245
  /* p2c: checkmol.pas, line 2388:
3246
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3247
#ifdef REDUCED_SAR
3248
  sprintf (tmpstr, "%d", n_countablerings);
3249
  /* v0.3n; changed n_rings into n_countablerings */
3250
#else
3251
  sprintf (tmpstr, "%d", n_rings);
3252
#endif
3253
  lblank (3L, tmpstr);
3254
  strcat (wline, tmpstr);
3255
  *tmpstr = '\0';
3256
  /* officially "obsolete", we use it for the number of rings */
3257
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
3258
  if (chir_flag)
3259
    strcat (wline, "1");
3260
  else
3261
    strcat (wline, "0");
3262
  /* v0.3n */
3263
  strcat (wline, "               999 V2000");
3264
  /* v0.3n (adjust string length) */
3265
  puts (wline);
3266
  FORLIM = n_atoms;
14179 bpr 3267
  for (i = 0; i < FORLIM; i++) {
3268
    *wline = '\0';
3269
    sprintf (tmpstr, "%1.4f", atom[i].x);
3270
    lblank (10L, tmpstr);
3271
    strcat (wline, tmpstr);
3272
    sprintf (tmpstr, "%1.4f", atom[i].y);
3273
    lblank (10L, tmpstr);
3274
    strcat (wline, tmpstr);
3275
    sprintf (tmpstr, "%1.4f", atom[i].z);
3276
    lblank (10L, tmpstr);
3277
    strcat (wline, tmpstr);
3278
    strcpy (tmpstr, atom[i].element);
3279
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
3280
    //tmpstr[0] = toupper (tmpstr[0]);
3281
    all_lowercase (tmpstr);
3282
    tmpstr[0] = toupper (tmpstr[0]);
3283
    /*wline := wline + ' '+atom^[i].element+' '; */
3284
    sprintf (wline + strlen (wline), " %s ", tmpstr);
3285
    strcat (wline, " 0");       /* mass difference (isotopes) */
3286
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
3287
    if (atom[i].arom)
3288
            strcpy (tmpstr, " 00");
3289
    else
3290
            strcpy (tmpstr, "  0");
6785 bpr 3291
      strcat (wline, tmpstr);
3292
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0");
3293
      puts (wline);
14179 bpr 3294
  }
6785 bpr 3295
  FORLIM = n_bonds;
14179 bpr 3296
  for (i = 0; i < FORLIM; i++) {
3297
    *wline = '\0';
3298
    sprintf (tmpstr, "%d", bond[i].a1);
3299
    lblank (3L, tmpstr);
3300
    strcat (wline, tmpstr);
3301
    sprintf (tmpstr, "%d", bond[i].a2);
3302
    lblank (3L, tmpstr);
3303
    strcat (wline, tmpstr);
3304
    if (bond[i].btype == 'S')
3305
            strcpy (tmpstr, "  1");
3306
    if (bond[i].btype == 'D')
3307
            strcpy (tmpstr, "  2");
3308
    if (bond[i].btype == 'T')
3309
            strcpy (tmpstr, "  3");
3310
    if (bond[i].btype == 'A')
3311
            strcpy (tmpstr, "  4");
3312
    if (bond[i].btype == 'l')
3313
            strcpy (tmpstr, "  5");
3314
    if (bond[i].btype == 's')
3315
            strcpy (tmpstr, "  6");
3316
    if (bond[i].btype == 'd')
3317
            strcpy (tmpstr, "  7");
3318
    if (bond[i].btype == 'a')
3319
            strcpy (tmpstr, "  8");
6785 bpr 3320
      /* now encode our own aromaticity information */
14179 bpr 3321
    if (bond[i].arom)
3322
            tmpstr[1] = '0';
3323
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
3324
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
3325
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
3326
    /*    wline := wline + '  0'; */
3327
    /* restore original value from MDL molfile (v0.3n) */
3328
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
3329
    *tmpstr = '\0';
3330
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
3331
    strcat (wline, "  ");
3332
    strcat (wline, tmpstr);
3333
    *tmpstr = '\0';
3334
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
3335
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
3336
    sprintf (tmpstr, "%i", bond[i].ring_count);
3337
    while (strlen (tmpstr) < 3)
3338
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
3339
    sprintf (wline + strlen (wline), "%s  0  0", tmpstr);
3340
    puts (wline);
3341
  }
6785 bpr 3342
  FORLIM = n_atoms;
14179 bpr 3343
  for (i = 1; i <= FORLIM; i++) {
3344
    a_chg = atom[i - 1].formal_charge;
3345
    if (a_chg != 0) {
3346
            strcpy (wline, "M  CHG  1 ");
3347
            sprintf (tmpstr, "%d", i);
3348
            lblank (3L, tmpstr);
3349
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3350
            sprintf (tmpstr, "%d", a_chg);
3351
            lblank (3L, tmpstr);
3352
            strcat (wline, tmpstr);
3353
            puts (wline);
3354
          }
3355
  }
3356
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
3357
    a_iso = atom[i - 1].nucleon_number;
3358
    if (a_iso != 0) {
3359
            strcpy (wline, "M  ISO  1 ");
3360
            sprintf (tmpstr, "%d", i);
3361
            lblank (3L, tmpstr);
3362
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3363
            sprintf (tmpstr, "%d", a_iso);
3364
            lblank (3L, tmpstr);
3365
            strcat (wline, tmpstr);
3366
            puts (wline);
3367
          }
3368
  }
3369
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
3370
    a_rad = atom[i - 1].radical_type;
3371
    if (a_rad != 0) {
3372
            strcpy (wline, "M  RAD  1 ");
3373
            sprintf (tmpstr, "%d", i);
3374
            lblank (3L, tmpstr);
3375
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3376
            sprintf (tmpstr, "%d", a_rad);
3377
            lblank (3L, tmpstr);
3378
            strcat (wline, tmpstr);
3379
            puts (wline);
3380
          }
3381
  }
6785 bpr 3382
  printf ("M  END\n");
3383
}
3384
 
3385
/*============= chemical processing functions && procedures ============ */
3386
 
14179 bpr 3387
static boolean is_electroneg (a_el)
6785 bpr 3388
     char *a_el;
3389
{
3390
  /* new in v0.3j */
3391
  boolean res = false;
3392
 
3393
  if (!strcmp (a_el, "N "))
3394
    res = true;
3395
  if (!strcmp (a_el, "P "))
3396
    res = true;
3397
  if (!strcmp (a_el, "O "))
3398
    res = true;
3399
  if (!strcmp (a_el, "S "))
3400
    res = true;
3401
  if (!strcmp (a_el, "SE"))
3402
    res = true;
3403
  if (!strcmp (a_el, "TE"))
3404
    res = true;
3405
  if (!strcmp (a_el, "F "))
3406
    res = true;
3407
  if (!strcmp (a_el, "CL"))
3408
    res = true;
3409
  if (!strcmp (a_el, "BR"))
3410
    res = true;
3411
  if (!strcmp (a_el, "I "))
3412
    res = true;
3413
  if (!strcmp (a_el, "AT"))
3414
    res = true;
3415
  return res;
3416
}
3417
 
14179 bpr 3418
static void count_neighbors ()
6785 bpr 3419
{
3420
  /* counts heavy-atom neighbors and explicit hydrogens */
3421
  int i, FORLIM;
3422
 
3423
  if (n_atoms < 1 || n_bonds < 1)
3424
    return;
3425
  FORLIM = n_bonds;
14179 bpr 3426
  for (i = 0; i < FORLIM; i++) {
3427
    if (atom[bond[i].a1 - 1].heavy)
3428
            atom[bond[i].a2 - 1].neighbor_count++;
3429
    if (atom[bond[i].a2 - 1].heavy)
3430
            atom[bond[i].a1 - 1].neighbor_count++;
3431
    if (!strcmp (atom[bond[i].a1 - 1].element, "H "))
3432
            atom[bond[i].a2 - 1].Hexp++;
3433
    if (!strcmp (atom[bond[i].a2 - 1].element, "H "))
3434
            atom[bond[i].a1 - 1].Hexp++;
3435
    /* plausibility check (new in v02.i) */
3436
    if (atom[bond[i].a1 - 1].neighbor_count > max_neighbors ||
3437
              atom[bond[i].a2 - 1].neighbor_count > max_neighbors) {
3438
            mol_OK = false;
3439
            /*writeln('invalid molecule!'); */
3440
          }
3441
  }
6785 bpr 3442
}
3443
 
14179 bpr 3444
static void get_neighbors (Result, id)
3445
  int *Result;
3446
  int id;
6785 bpr 3447
{
6786 kbelabas 3448
  int i;
6785 bpr 3449
  //neighbor_rec nb_tmp;
3450
  int nb_count = 0;
3451
  //int FORLIM = n_bonds;
3452
 
3453
  //memset (Result, 0, sizeof (neighbor_rec));
3454
 
14179 bpr 3455
  for (i = 0; i < n_bonds; i++) {
3456
    if (bond[i].a1 == id && atom[bond[i].a2 - 1].heavy
3457
              && nb_count < max_neighbors) {
3458
            Result[nb_count++] = bond[i].a2;
3459
          }
3460
    if (bond[i].a2 == id && atom[bond[i].a1 - 1].heavy
3461
              && nb_count < max_neighbors) {
3462
            Result[nb_count++] = bond[i].a1;
3463
          }
3464
  }
6785 bpr 3465
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3466
}
3467
 
14179 bpr 3468
static void get_ndl_neighbors (int *Result, int id)
6785 bpr 3469
{
3470
  int i;
3471
  //neighbor_rec nb_tmp;
3472
  int nb_count = 0;
3473
  /* v0.3i: use max_neighbors instead of a fixed value of 8 */
3474
  //int FORLIM = ndl_n_bonds;
3475
 
3476
  //memset (nb_tmp, 0, sizeof (neighbor_rec));
3477
 
14179 bpr 3478
  for (i = 0; i < ndl_n_bonds; i++) {
3479
    if (ndl_bond[i].a1 == id && nb_count < max_neighbors &&
3480
              ndl_atom[ndl_bond[i].a2 - 1].heavy) {
3481
            nb_count++;
3482
            Result[nb_count - 1] = ndl_bond[i].a2;
3483
          }
3484
    if (ndl_bond[i].a2 == id && nb_count < max_neighbors &&
3485
              ndl_atom[ndl_bond[i].a1 - 1].heavy){
3486
            nb_count++;
3487
            Result[nb_count - 1] = ndl_bond[i].a1;
3488
          }
3489
  }
6785 bpr 3490
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3491
}
3492
 
14179 bpr 3493
static int * get_nextneighbors (int *Result, int id, int prev_id)
6785 bpr 3494
{
3495
  int i;
3496
  neighbor_rec nb_tmp;
3497
  int nb_count = 0;
3498
  int FORLIM;
3499
 
3500
  /* gets all neighbors except prev_id (usually the atom where we came from */
3501
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3502
  FORLIM = n_bonds;
14179 bpr 3503
  for (i = 0; i < FORLIM; i++) {
3504
    if (bond[i].a1 == id && bond[i].a2 != prev_id &&
3505
              nb_count < max_neighbors && atom[bond[i].a2 - 1].heavy) {
3506
            nb_count++;
3507
            nb_tmp[nb_count - 1] = bond[i].a2;
3508
          }
3509
    if (bond[i].a2 == id && bond[i].a1 != prev_id &&
3510
              nb_count < max_neighbors && atom[bond[i].a1 - 1].heavy) {
3511
            nb_count++;
3512
            nb_tmp[nb_count - 1] = bond[i].a1;
3513
          }
3514
  }
6785 bpr 3515
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3516
}
3517
 
14179 bpr 3518
static int * get_ndl_nextneighbors (int *Result, int id, int prev_id)
6785 bpr 3519
{
3520
  int i;
3521
  neighbor_rec nb_tmp;
3522
  int nb_count = 0;
3523
  int FORLIM;
3524
 
3525
  /* gets all neighbors except prev_id (usually the atom where we came from */
3526
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3527
  FORLIM = ndl_n_bonds;
14179 bpr 3528
  for (i = 0; i < FORLIM; i++) {
3529
    if (ndl_bond[i].a1 == id && ndl_bond[i].a2 != prev_id &&
3530
              nb_count < max_neighbors && ndl_atom[ndl_bond[i].a2 - 1].heavy) {
3531
            nb_count++;
3532
            nb_tmp[nb_count - 1] = ndl_bond[i].a2;
3533
          }
3534
    if (ndl_bond[i].a2 == id && ndl_bond[i].a1 != prev_id &&
3535
              nb_count < max_neighbors && ndl_atom[ndl_bond[i].a1 - 1].heavy) {
3536
            nb_count++;
3537
            nb_tmp[nb_count - 1] = ndl_bond[i].a1;
3538
          }
3539
  }
6785 bpr 3540
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3541
}
3542
 
3543
#if 0
3544
static int path_pos (id, a_path) int id;
14179 bpr 3545
  int *a_path;
3546
  {
3547
  /* new version in v0.3l */
3548
  int i;
3549
  int pp = 0;
6785 bpr 3550
 
14179 bpr 3551
  for (i = 1; i <= max_ringsize; i++)
3552
  {
3553
  if (a_path[i - 1] == id)
3554
  {
3555
  pp = i;
3556
  /* p2c: checkmol.pas, line 2620:
3557
  * Warning: Expected a '(', found a semicolon [227]  */
3558
  /* p2c: checkmol.pas, line 2620:
3559
  * Warning: Expected an expression, found a semicolon [227] */
3560
  fflush (0);
3561
  P_ioresult = 0;
3562
  }
3563
  }
3564
  return pp;
3565
  }
6785 bpr 3566
#endif
3567
 
14179 bpr 3568
static int matchpath_pos (int id, int *a_path)
6785 bpr 3569
{
3570
  int i;
3571
  int pp = 0;
3572
 
14179 bpr 3573
  for (i = max_matchpath_length; i >= 1; i--) {
3574
    if (a_path[i - 1] == id)
3575
            pp = i;
3576
  }
6785 bpr 3577
  return pp;
3578
}
3579
 
14179 bpr 3580
static int matchpath_length (int *a_path)
6785 bpr 3581
{
3582
  if (a_path[max_matchpath_length - 1] != 0)
3583
    return max_matchpath_length;
3584
  else
3585
    return (matchpath_pos (0L, a_path) - 1);
3586
}
3587
 
14179 bpr 3588
static int get_ndl_bond (int ba1, int ba2)
6785 bpr 3589
{
3590
  int i;
3591
  int b_id = 0;
3592
  int FORLIM;
3593
 
3594
  if (ndl_n_bonds <= 0)
3595
    return b_id;
3596
  FORLIM = ndl_n_bonds;
14179 bpr 3597
  for (i = 1; i <= FORLIM; i++) {
3598
    if ((ndl_bond[i - 1].a1 == ba1 && ndl_bond[i - 1].a2 == ba2) ||
3599
              (ndl_bond[i - 1].a1 == ba2 && ndl_bond[i - 1].a2 == ba1))
3600
          b_id = i;
3601
  }
6785 bpr 3602
  return b_id;
3603
}
3604
 
14179 bpr 3605
static int ringcompare (int *rp1, int *rp2)
6785 bpr 3606
{
3607
  int i, j;
3608
  int rc = 0;
3609
  int rs1, rs2;
3610
  int n_common = 0;
3611
  int max_cra;
3612
 
3613
  rs1 = path_length (rp1);
3614
  rs2 = path_length (rp2);
3615
  if (rs1 < rs2)
3616
    max_cra = rs1;
3617
  else
3618
    max_cra = rs2;
14179 bpr 3619
  for (i = 0; i < rs1; i++) {
3620
    for (j = 0; j < rs2; j++) {
3621
            if (rp1[i] == rp2[j])
3622
              n_common++;
3623
          }
3624
  }
3625
  if (rs1 == rs2 && n_common == max_cra) {
3626
    rc = 0;
3627
    return rc;
3628
  }
6785 bpr 3629
  if (n_common == 0)
3630
    rc += 8;
14179 bpr 3631
  if (n_common < max_cra) {
3632
    rc += 4;
3633
    return rc;
3634
  }
6785 bpr 3635
  if (rs1 < rs2)
3636
    rc++;
3637
  else
3638
    rc += 2;
3639
  return rc;
3640
}
3641
 
14179 bpr 3642
static boolean rc_identical (int rc_int)
6785 bpr 3643
{
3644
  if (rc_int == 0)
3645
    return true;
3646
  else
3647
    return false;
3648
}
3649
 
14179 bpr 3650
static boolean rc_1in2 (int rc_int)
6785 bpr 3651
{
3652
  if (rc_int & 1)
3653
    return true;
3654
  else
3655
    return false;
3656
}
3657
 
14179 bpr 3658
static boolean rc_2in1 (int rc_int)
6785 bpr 3659
{
3660
  rc_int /= 2;
3661
  if (rc_int & 1)
3662
    return true;
3663
  else
3664
    return false;
3665
}
3666
 
3667
#if 0
14179 bpr 3668
static boolean rc_different (int rc_int)
6785 bpr 3669
{
3670
  rc_int /= 4;
3671
  if (rc_int & 1)
3672
    return true;
3673
  else
3674
    return false;
3675
}
3676
#endif
3677
#if 0
14179 bpr 3678
static boolean rc_independent (int rc_int)
6785 bpr 3679
{
3680
  rc_int /= 8;
3681
  if (rc_int & 1)
3682
    return true;
3683
  else
3684
    return false;
3685
}
3686
#endif
3687
 
14179 bpr 3688
static boolean is_newring (int *n_path)
6785 bpr 3689
{
3690
  int i, j;
3691
  boolean nr = true;
3692
  boolean same_ring;
3693
  ringpath_type tmp_path;
3694
  int rc_result;
3695
  boolean found_ring;
3696
  int pl;                       /* new in v0.3 */
3697
  int FORLIM;
3698
 
3699
  pl = path_length (n_path);    /* new in v0.3 */
3700
  if (n_rings <= 0)
3701
    return true;
14179 bpr 3702
  switch (ringsearch_mode) {
6785 bpr 3703
    case rs_sar:
3704
      found_ring = false;
3705
      i = 0;
14179 bpr 3706
      while (i < n_rings && !found_ring) {
3707
              i++;
3708
              if (pl != ringprop[i - 1].size)   /* compare only rings of same size */
3709
                continue;
3710
              same_ring = true;
3711
              for (j = 0; j < max_ringsize; j++) {
3712
                if (ring[i - 1][j] != n_path[j])
3713
                        same_ring = false;
3714
              }
3715
              if (same_ring) {
3716
                nr = false;
3717
                found_ring = true;
3718
              }
6785 bpr 3719
            }
3720
      break;
3721
 
3722
    case rs_ssr:
3723
      FORLIM = n_rings;
14179 bpr 3724
      for (i = 0; i < FORLIM; i++) {
3725
              for (j = 0; j < max_ringsize; j++)
3726
                tmp_path[j] = ring[i][j];
3727
              rc_result = ringcompare (n_path, tmp_path);
3728
              if (rc_identical (rc_result))
3729
                nr = false;
3730
              if (rc_1in2 (rc_result)) {
6785 bpr 3731
              /* exchange existing ring by smaller one */
14179 bpr 3732
                for (j = 0; j < max_ringsize; j++)
3733
                        ring[i][j] = n_path[j];
3734
                /* update ring property record (new in v0.3) */
3735
                ringprop[i].size = pl;
3736
                nr = false;
3737
        /* p2c: checkmol.pas, line 2841:
3738
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3739
              /*$IFDEF debug */
3740
              /* debugoutput('replacing ring '+inttostr(i)+' by smaller one (ringsize: '+inttostr(path_length(n_path))+')'); */
3741
              /*$ENDIF */
3742
        }
3743
        if (rc_2in1 (rc_result)) {
3744
                  /* new ring contains existing one, but is larger ==> discard */
3745
                nr = false;
3746
              }
6785 bpr 3747
            }
14179 bpr 3748
    break;
3749
  }
6785 bpr 3750
  return nr;
3751
}
3752
 
14179 bpr 3753
static void add_ring (int *n_path)
6785 bpr 3754
{
3755
  /* new in v0.3: store rings in an ordered way (with ascending ring size) */
3756
  int i;
3757
  int j = 0;
3758
  int k, s, pl;
14179 bpr 3759
  /* p2c: checkmol.pas, line 2862:
3760
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3761
  /*$IFDEF debug */
3762
  /*char dstr[256];*/
3763
  int FORLIM;
3764
 
3765
  /*$ENDIF */
3766
  pl = path_length (n_path);
3767
 
3768
  if (pl < 1)
3769
    return;
3770
 
14179 bpr 3771
  if (n_rings >= max_rings) {
3772
    /* p2c: checkmol.pas, line 2906:
3773
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3774
          /*$IFDEF debug
3775
             debugoutput ("max_rings exceeded!");
3776
             $ENDIF */
3777
    return;
3778
  }
6785 bpr 3779
  n_rings++;
3780
 
14179 bpr 3781
  /* p2c: checkmol.pas, line 2871:
3782
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3783
    /*$IFDEF debug */
3784
    /* dstr := '';
3785
       for j := 1 to pl do dstr := dstr + inttostr((n_path[j])) + ' ';
3786
       debugoutput('adding ring '+inttostr(n_rings)+':  '+dstr); */
3787
    /*$ENDIF */
3788
  if (n_rings > 1) {
3789
    FORLIM = n_rings;
3790
    for (i = 1; i < FORLIM; i++) {
3791
            s = ringprop[i - 1].size;
3792
            if (pl >= s)
3793
              j = i;
3794
          }
3795
  }
6785 bpr 3796
  j++;                          /* the next position is ours */
14179 bpr 3797
  if (j < n_rings) {                            /* push up the remaining rings by one position */
3798
    for (k = n_rings; k > j; k--) {
3799
            ringprop[k - 1].size = ringprop[k - 2].size;
3800
            /*ringprop^[k].arom := ringprop^[(k-1)].arom; */
3801
            for (i = 0; i < max_ringsize; i++)
3802
              ring[k - 1][i] = ring[k - 2][i];
3803
          }
3804
  }
6785 bpr 3805
  ringprop[j - 1].size = pl;
14179 bpr 3806
  for (i = 0; i < max_ringsize; i++) {
3807
    ring[j - 1][i] = n_path[i];
3808
    /*inc(atom^[(n_path[i])].ring_count); */
3809
  }
6785 bpr 3810
}
3811
 
3812
#if 0
14179 bpr 3813
static boolean is_ringpath (s_path) int *s_path;
3814
   {
3815
   boolean Result;
3816
   int i, j;
3817
   neighbor_rec nb;
3818
   boolean rp = false;
3819
   boolean new_atom;
3820
   int a_last, pl;
3821
   ringpath_type l_path;
3822
   int FORLIM;
6785 bpr 3823
 
14179 bpr 3824
   /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3825
   memset (nb, 0, sizeof (neighbor_rec));
3826
   memset (l_path, 0, sizeof (ringpath_type));
3827
   pl = path_length (s_path);
3828
   if (pl < 1) {
3829
   /* p2c: checkmol.pas, line 2928:
6785 bpr 3830
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14179 bpr 3831
     /*$IFDEF debug
6785 bpr 3832
     debugoutput ("Oops! Got zero-length s_path!");
3833
     $ENDIF */
3834
     return Result;
14179 bpr 3835
    }
3836
    for (i = 0; i < pl; i++)
3837
      l_path[i] = s_path[i];
3838
    /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
3839
    if (opt_metalrings == false) {
3840
      if (atom[l_path[pl - 1] - 1].metal){
3841
        /* p2c: checkmol.pas, line 2942:
3842
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3843
        /*$IFDEF debug
3844
        debugoutput ("skipping metal in ring search");
3845
         $ENDIF */
3846
        return false;
3847
      }
3848
    }
3849
    /* check if ring is already closed */
3850
    if (pl > 2 && l_path[pl - 1] == l_path[0]) {
3851
    l_path[pl - 1] = 0;        /* remove last entry (redundant!) */
3852
    order_ringpath (l_path);
3853
    if (is_newring (l_path)) {
3854
      if (n_rings >= max_rings) {
3855
        /* p2c: checkmol.pas, line 2958:
3856
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3857
        /*$IFDEF debug
3858
        debugoutput ("maximum number of rings exceeded!");
3859
        $ENDIF */
3860
        return false;
3861
      }
3862
      add_ring (l_path);
3863
    }
3864
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3865
    return true;
3866
  }
3867
  /* any other case: ring is not (yet) closed */
3868
  a_last = l_path[pl - 1];
3869
  get_neighbors (nb, a_last);
3870
  if (atom[a_last - 1].neighbor_count <= 1)
3871
    return false;
3872
  if (n_rings >= max_rings)
3873
    /* added in v0.2: check if max_rings is reached **/
3874
  {                          /* if ring is not closed, continue searching */
3875
    return false;
3876
  }
3877
  FORLIM = atom[a_last - 1].neighbor_count;
3878
  for (i = 0; i < FORLIM; i++) {
3879
    new_atom = true;
3880
     for (j = 1; j < pl; j++) {
3881
      if (nb[i] == l_path[j]) {                    /* v0.3k */
3882
       new_atom = false;
3883
       /* p2c: checkmol.pas, line 2982:
3884
       * Warning: Expected a '(', found a semicolon [227] */
3885
       /* p2c: checkmol.pas, line 2982:
3886
       * Warning: Expected an expression, found a semicolon [227] */
3887
       fflush (0);
3888
       P_ioresult = 0;      /* v0.3k */
3889
      }
3890
    }
3891
    /* added in v0.1a: check if max_rings not yet reached */
3892
    /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
3893
    if (new_atom && pl < max_vringsize && n_rings < max_rings) {
3894
      l_path[pl] = nb[i];
3895
      if (pl < max_ringsize - 1)   /* just to be sure */
3896
      l_path[pl + 1] = 0;
3897
      if (is_ringpath (l_path))
3898
       rp = true;
3899
    }
3900
  }
3901
  return rp;
3902
}
6785 bpr 3903
#endif
3904
 
14179 bpr 3905
static boolean is_ringpath (int *s_path)
6785 bpr 3906
{
3907
  int i, j;
3908
  neighbor_rec nb;
3909
  boolean rp = false;
3910
  boolean new_atom;
3911
  int a_last, pl;
3912
  ringpath_type l_path;
3913
  int FORLIM, pl_prev, pl_next, max_ringsize_dec;
3914
 
3915
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3916
  memset ((void *) nb, 0, sizeof (neighbor_rec));
3917
  memset ((void *) l_path, 0, sizeof (ringpath_type));
3918
  pl = path_length (s_path);
14179 bpr 3919
  if (pl < 1) {
3920
    /* p2c: checkmol.pas, line 2524:
3921
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3922
 
3923
      return false;
3924
    }
3925
 
3926
  pl_prev = pl - 1;
3927
  //memcpy (l_path, s_path, sizeof (ringpath_type));
3928
  memcpy (l_path, s_path, pl * sizeof (int));
3929
 
3930
  /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
14179 bpr 3931
  if (opt_metalrings == false) {
3932
    if (atom[l_path[pl_prev] - 1].metal) {
3933
    /* p2c: checkmol.pas, line 2538:
3934
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3935
          return false;
14179 bpr 3936
          }
3937
  }
6785 bpr 3938
  /* check if ring is already closed */
14179 bpr 3939
  if (pl > 2 && l_path[pl_prev] == l_path[0]) {
3940
    l_path[pl_prev] = 0;        /* remove last entry (redundant!) */
3941
    order_ringpath (l_path);
3942
    if (is_newring (l_path)) {
3943
            if (n_rings >= max_rings) {
3944
        /* p2c: checkmol.pas, line 2554:
3945
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3946
              return false;
3947
            }
14179 bpr 3948
            add_ring (l_path);
3949
          }
3950
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 3951
      return true;
14179 bpr 3952
  }
6785 bpr 3953
  /* any other case: ring is not (yet) closed */
3954
  a_last = l_path[pl_prev];
3955
  get_neighbors (nb, a_last);
3956
  if (atom[a_last - 1].neighbor_count <= 1)
3957
    return false;
3958
  if (n_rings >= max_rings)
14179 bpr 3959
    /* added in v0.2: check if max_rings is reached */ {                                /* if ring is not closed, continue searching */
3960
    return false;
3961
  }
6785 bpr 3962
  FORLIM = atom[a_last - 1].neighbor_count;
3963
  pl_next = pl + 1;
3964
  max_ringsize_dec = max_ringsize - 1;
14179 bpr 3965
  for (i = 0; i < FORLIM; i++) {
3966
    new_atom = true;
3967
    for (j = 1; j < pl; j++) {
3968
            if (nb[i] == l_path[j]) {
6785 bpr 3969
              new_atom = false;
3970
              break;
3971
            }
14179 bpr 3972
          }
3973
    /* added in v0.1a: check if max_rings not yet reached */
3974
    /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
3975
    if (new_atom && pl < max_vringsize && n_rings < max_rings) {
3976
            l_path[pl] = nb[i];
3977
            if (pl < max_ringsize_dec)  /* just to be sure */
3978
              l_path[pl_next] = 0;
6785 bpr 3979
 
14179 bpr 3980
            if (max_ringpath_recursion_depth != 0
3981
                && ++recursion_depth > max_ringpath_recursion_depth) {
6785 bpr 3982
#ifndef MAKE_SHARED_LIBRARY
3983
              if (opt_verbose)
3984
#endif
14179 bpr 3985
                    printf ("Warning: max. number of ringpath recursions (%i) reached\n",
3986
                    max_ringpath_recursion_depth);
6785 bpr 3987
              n_rings = max_rings;
3988
              return false;
3989
            }
3990
 
14179 bpr 3991
            /*printf("%i\n",recursion_depth);
3992
            fflush(stdout);*/
6785 bpr 3993
 
14179 bpr 3994
            if (is_ringpath (l_path))
3995
              rp = true;
3996
            /*return true;*/
3997
          }
3998
  }
6785 bpr 3999
  return rp;
4000
}
4001
 
14179 bpr 4002
static boolean is_ringbond (int b_id)
6785 bpr 4003
{
4004
  int i, ra1, ra2;
4005
  neighbor_rec nb;
4006
  ringpath_type search_path;
4007
  boolean rb = false;
4008
  int FORLIM;
4009
 
4010
  recursion_depth = 0;
4011
 
4012
  ra1 = bond[b_id - 1].a1;
4013
  ra2 = bond[b_id - 1].a2;
4014
  memset (nb, 0, sizeof (neighbor_rec));
4015
  memset (search_path, 0, sizeof (ringpath_type));
4016
  get_neighbors (nb, ra2);
4017
  if (atom[ra2 - 1].neighbor_count <= 1 || atom[ra1 - 1].neighbor_count <= 1)
4018
    return false;
4019
  search_path[0] = ra1;
4020
  search_path[1] = ra2;
4021
  FORLIM = atom[ra2 - 1].neighbor_count;
14179 bpr 4022
  for (i = 0; i < FORLIM; i++) {
4023
    if (nb[i] != ra1 && atom[nb[i] - 1].heavy) {
4024
            search_path[2] = nb[i];
4025
            if (is_ringpath (search_path))
4026
              rb = true;
4027
            //return true;
4028
          }
4029
  }
6785 bpr 4030
  return rb;
4031
}
4032
 
14179 bpr 4033
static void chk_ringbonds ()
6785 bpr 4034
{
4035
  int i, a1rc, a2rc;
4036
 
4037
  if (n_bonds < 1)
4038
    return;
4039
 
14179 bpr 4040
  for (i = 0; i < n_bonds; i++) {
4041
    a1rc = atom[bond[i].a1 - 1].ring_count;
4042
    a2rc = atom[bond[i].a2 - 1].ring_count;
4043
    if (n_rings == 0 || (a1rc < n_rings && a2rc < n_rings)) {
4044
            is_ringbond (i + 1);
6785 bpr 4045
          /*inc(bond^[i].ring_count); */
14179 bpr 4046
          }
4047
  }
6785 bpr 4048
}
4049
 
4050
/* v0.3d: moved procedure update_ringcount a bit down */
4051
 
14179 bpr 4052
static int raw_hetbond_count (int a)
6785 bpr 4053
{
4054
  /* new in v0.2j, ignores bond order */
4055
  int i;
4056
  neighbor_rec nb;
4057
  str2 nb_el;
4058
  int hbc = 0;
4059
  int FORLIM;
4060
 
4061
  if (a <= 0 || a > n_atoms)
4062
    return hbc;
4063
  memset (nb, 0, sizeof (neighbor_rec));
4064
  get_neighbors (nb, a);
4065
  if (atom[a - 1].neighbor_count <= 0)
4066
    return hbc;
4067
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4068
  for (i = 0; i < FORLIM; i++) {
4069
    strcpy (nb_el, atom[nb[i] - 1].element);
4070
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /* &&  strcmp (nb_el, "D ") */
4071
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4072
            /* added 'D ' in v0.3n */
4073
          hbc++;
4074
  }
6785 bpr 4075
  return hbc;
4076
}
4077
 
14179 bpr 4078
static int hetbond_count (int a)
6785 bpr 4079
{
4080
  int i;
4081
  neighbor_rec nb;
4082
  str2 nb_el;
4083
  float hbc = 0.0;
4084
  int FORLIM;
4085
 
4086
  if (a <= 0 || a > n_atoms)
4087
    return ((int) floor (hbc + 0.5));
4088
  memset (nb, 0, sizeof (neighbor_rec));
4089
  get_neighbors (nb, a);
4090
  if (atom[a - 1].neighbor_count <= 0)
4091
    return ((int) floor (hbc + 0.5));
4092
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4093
  for (i = 0; i < FORLIM; i++) {
4094
    strcpy (nb_el, atom[nb[i] - 1].element);
4095
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /*&& strcmp (nb_el, "D ") */
4096
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU")) {                        /* added 'D ' in v0.3n */
4097
            if (bond[get_bond (a, nb[i]) - 1].btype == 'S')
4098
              hbc += 1.0;
4099
            if (bond[get_bond (a, nb[i]) - 1].btype == 'A')
4100
              hbc += 1.5;
4101
            if (bond[get_bond (a, nb[i]) - 1].btype == 'D')
4102
              hbc += 2.0;
4103
            if (bond[get_bond (a, nb[i]) - 1].btype == 'T')
4104
              hbc += 3.0;
4105
          }
4106
  }
6785 bpr 4107
  return ((int) floor (hbc + 0.5));
4108
}
4109
 
14179 bpr 4110
static int hetatom_count (int a)
6785 bpr 4111
{
4112
  int i;
4113
  neighbor_rec nb;
4114
  str2 nb_el;
4115
  int hac = 0;
4116
  int FORLIM;
4117
 
4118
  if (a <= 0 || a > n_atoms)
4119
    return hac;
4120
  memset (nb, 0, sizeof (neighbor_rec));
4121
  get_neighbors (nb, a);
4122
  if (atom[a - 1].neighbor_count <= 0)
4123
    return hac;
4124
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4125
  for (i = 0; i < FORLIM; i++) {
4126
    strcpy (nb_el, atom[nb[i] - 1].element);
4127
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4128
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4129
              && strcmp (nb_el, "DU"))
4130
            /* added 'D ' in v0.3n */
4131
            hac++;
4132
  }
6785 bpr 4133
  return hac;
4134
}
4135
 
4136
#if 0
14179 bpr 4137
static int ndl_hetbond_count (int a)
6785 bpr 4138
{
4139
  int i;
4140
  neighbor_rec nb;
4141
  str2 nb_el;
4142
  float hbc = 0.0;
4143
  int FORLIM;
4144
 
4145
  if (a <= 0 || a > n_atoms)
4146
    return ((int) floor (hbc + 0.5));
4147
  memset (nb, 0, sizeof (neighbor_rec));
4148
  get_ndl_neighbors (nb, a);
4149
  if (ndl_atom[a - 1].neighbor_count <= 0)
4150
    return ((int) floor (hbc + 0.5));
4151
  FORLIM = ndl_atom[a - 1].neighbor_count;
14179 bpr 4152
  for (i = 0; i < FORLIM; i++) {
4153
    strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4154
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4155
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4156
              && strcmp (nb_el, "DU")) {                        /* added 'D ' in v0.3n */
4157
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'S')
4158
              hbc += 1.0;
4159
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'A')
4160
              hbc += 1.5;
4161
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'D')
4162
              hbc += 2.0;
4163
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'T')
4164
              hbc += 3.0;
4165
          }
4166
  }
6785 bpr 4167
  return ((int) floor (hbc + 0.5));
4168
}
4169
#endif
4170
 
14179 bpr 4171
static int ndl_hetatom_count (int a)
6785 bpr 4172
{
4173
  int i;
4174
  neighbor_rec nb;
4175
  str2 nb_el;
4176
  int hac = 0;
4177
  int FORLIM;
4178
 
4179
  if (a <= 0 || a > ndl_n_atoms)
4180
    return hac;
4181
  memset (nb, 0, sizeof (neighbor_rec));
4182
  get_ndl_neighbors (nb, a);
4183
  if (ndl_atom[a - 1].neighbor_count <= 0)
4184
    return hac;
4185
  FORLIM = ndl_atom[a - 1].neighbor_count;
14179 bpr 4186
  for (i = 0; i < FORLIM; i++) {                                /* note: query atoms like 'A' should be present only in the needle */
4187
    strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4188
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /*&&  strcmp (nb_el, "D ") */
4189
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4190
            /* added 'D ' in v0.3n */
4191
          hac++;
4192
  }
6785 bpr 4193
  return hac;
4194
}
4195
 
14179 bpr 4196
static boolean is_oxo_C (int id)
6785 bpr 4197
{
4198
  int i;
4199
  boolean r = false;
4200
  neighbor_rec nb;
4201
  int FORLIM;
4202
 
4203
  memset (nb, 0, sizeof (neighbor_rec));
4204
  if (id < 1 || id > n_atoms)
6786 kbelabas 4205
    return false;
6785 bpr 4206
  get_neighbors (nb, id);
4207
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4208
    return false;
4209
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4210
  for (i = 0; i < FORLIM; i++) {
4211
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4212
              !strcmp (atom[nb[i] - 1].element, "O "))
4213
            /* no N, amidines are different... */
4214
            r = true;
6785 bpr 4215
      /* or
4216
         (atom^[(nb[i])].element = 'S ')  or
4217
         (atom^[(nb[i])].element = 'SE') */
14179 bpr 4218
  }
6785 bpr 4219
  return r;
4220
}
4221
 
14179 bpr 4222
static boolean is_thioxo_C (int id)
6785 bpr 4223
{
4224
  int i;
4225
  boolean r = false;
4226
  neighbor_rec nb;
4227
  int FORLIM;
4228
 
4229
  memset (nb, 0, sizeof (neighbor_rec));
4230
  if (id < 1 || id > n_atoms)
6786 kbelabas 4231
    return false;
6785 bpr 4232
  get_neighbors (nb, id);
4233
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4234
    return false;
4235
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4236
  for (i = 0; i < FORLIM; i++) {
4237
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4238
              (!strcmp (atom[nb[i] - 1].element, "S ") ||
4239
              !strcmp (atom[nb[i] - 1].element, "SE")))
4240
            /* no N, amidines are different... */
4241
          r = true;
4242
  }
6785 bpr 4243
  return r;
4244
}
4245
 
14179 bpr 4246
static boolean is_imino_C (int id)
6785 bpr 4247
{
4248
  int i;
4249
  boolean r = false;
4250
  neighbor_rec nb;
4251
  int FORLIM;
4252
 
4253
  memset (nb, 0, sizeof (neighbor_rec));
4254
  if (id < 1 || id > n_atoms)
6786 kbelabas 4255
    return false;
6785 bpr 4256
  get_neighbors (nb, id);
4257
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4258
    return false;
4259
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4260
  for (i = 0; i < FORLIM; i++) {
4261
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4262
              !strcmp (atom[nb[i] - 1].element, "N "))
4263
            r = true;
4264
  }
6785 bpr 4265
  return r;
4266
}
4267
 
14179 bpr 4268
static boolean is_true_imino_C (int id)
6785 bpr 4269
{
4270
  int i;
4271
  boolean r = true;
4272
  neighbor_rec nb;
4273
  str2 nb_el;
4274
  int a_n = 0;
4275
  int b;                        /* v0.3j */
4276
  int FORLIM;
4277
 
4278
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4279
  memset (nb, 0, sizeof (neighbor_rec));
4280
  if (id < 1 || id > n_atoms)
6786 kbelabas 4281
    return false;
6785 bpr 4282
  get_neighbors (nb, id);
4283
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4284
    return false;
4285
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4286
  for (i = 0; i < FORLIM; i++) {
4287
    b = get_bond (id, nb[i]);   /* v0.3j */
4288
    if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4289
              !strcmp (atom[nb[i] - 1].element, "N "))
6785 bpr 4290
        /* v0.3j */
14179 bpr 4291
            a_n = nb[i];
4292
  }
6785 bpr 4293
  if (a_n <= 0)
4294
    return false;
4295
  memset (nb, 0, sizeof (neighbor_rec));
4296
  get_neighbors (nb, a_n);
4297
  FORLIM = atom[a_n - 1].neighbor_count;
14179 bpr 4298
  for (i = 0; i < FORLIM; i++) {
4299
    strcpy (nb_el, atom[nb[i] - 1].element);
4300
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4301
            /*&&  strcmp (nb_el, "D ") */ )
4302
            /* v0.3n: D */
4303
            r = false;
4304
  }
6785 bpr 4305
  return r;
4306
}
4307
 
14179 bpr 4308
static boolean is_true_exocyclic_imino_C (int id, int r_id)
6785 bpr 4309
{
4310
  /* v0.3j */
4311
  int i, j;
4312
  boolean r = false;
4313
  neighbor_rec nb;
4314
  ringpath_type testring;
4315
  int ring_size, b, FORLIM;
4316
 
4317
  memset (nb, 0, sizeof (neighbor_rec));
4318
  if (id < 1 || id > n_atoms)
6789 bpr 4319
    return false;
6785 bpr 4320
  get_neighbors (nb, id);
4321
  memset (testring, 0, sizeof (ringpath_type));
4322
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4323
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4324
    testring[j] = ring[r_id - 1][j];
4325
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4326
    return false;
4327
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4328
  for (i = 0; i < FORLIM; i++) {
4329
    b = get_bond (id, nb[i]);
4330
    if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4331
              !strcmp (atom[nb[i] - 1].element, "N ")) {
4332
            r = true;
4333
            for (j = 0; j < ring_size; j++) {
6785 bpr 4334
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4335
                      r = false;
6785 bpr 4336
            }
14179 bpr 4337
          }
4338
  }
6785 bpr 4339
  return r;
4340
}
4341
 
14179 bpr 4342
static boolean is_exocyclic_imino_C (int id, int r_id)
6785 bpr 4343
{
4344
  int i, j;
4345
  boolean r = false;
4346
  neighbor_rec nb;
4347
  ringpath_type testring;
4348
  int ring_size, FORLIM;
4349
 
4350
  memset (nb, 0, sizeof (neighbor_rec));
4351
  if (id < 1 || id > n_atoms)
6789 bpr 4352
    return false;
6785 bpr 4353
  get_neighbors (nb, id);
4354
  memset (testring, 0, sizeof (ringpath_type));
4355
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4356
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4357
    testring[j] = ring[r_id - 1][j];
4358
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4359
    return false;
4360
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4361
  for (i = 0; i < FORLIM; i++) {
4362
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4363
              !strcmp (atom[nb[i] - 1].element, "N ")) {
4364
            r = true;
4365
            for (j = 0; j < ring_size; j++) {
6785 bpr 4366
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4367
                      r = false;
6785 bpr 4368
            }
14179 bpr 4369
          }
4370
  }
6785 bpr 4371
  return r;
4372
}
4373
 
14179 bpr 4374
static int find_exocyclic_methylene_C (int id, int r_id)
6785 bpr 4375
{
4376
  /* renamed and rewritten in v0.3j */
4377
  int i, j;
4378
  int r = 0;
4379
  neighbor_rec nb;
4380
  ringpath_type testring;
4381
  int ring_size, FORLIM;
4382
 
4383
  memset (nb, 0, sizeof (neighbor_rec));
4384
  if (id < 1 || id > n_atoms)
4385
    return 0;
4386
  get_neighbors (nb, id);
4387
  memset (testring, 0, sizeof (ringpath_type));
4388
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4389
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4390
    testring[j] = ring[r_id - 1][j];
4391
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4392
    return r;
4393
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4394
  for (i = 0; i < FORLIM; i++) {
4395
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4396
              !strcmp (atom[nb[i] - 1].element, "C ")) {
4397
            r = nb[i];
4398
            for (j = 0; j < ring_size; j++) {
6785 bpr 4399
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4400
                    r = 0;
6785 bpr 4401
            }
14179 bpr 4402
          }
4403
  }
6785 bpr 4404
  return r;
4405
}
4406
 
14179 bpr 4407
static boolean is_hydroxy (int a_view, int a_ref)
6785 bpr 4408
{
4409
  boolean r = false;
4410
 
14179 bpr 4411
  if (atom[a_view - 1]. heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4412
    if (!strcmp (atom[a_ref - 1].atype, "O3 ") &&
4413
              atom[a_ref - 1].neighbor_count == 1)
4414
            r = true;
4415
  }
6785 bpr 4416
  return r;
4417
}
4418
 
14179 bpr 4419
static boolean is_sulfanyl (int a_view, int a_ref)
6785 bpr 4420
{
4421
  boolean r = false;
4422
 
4423
  if (atom[a_view - 1].
14179 bpr 4424
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4425
    if (!strcmp (atom[a_ref - 1].atype, "S3 ") &&
4426
              atom[a_ref - 1].neighbor_count == 1)
4427
            r = true;
4428
  }
6785 bpr 4429
  return r;
4430
}
4431
 
14179 bpr 4432
static boolean is_amino (int a_view, int a_ref)
6785 bpr 4433
{
4434
  boolean r = false;
4435
 
4436
  if (atom[a_view - 1].
14179 bpr 4437
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4438
    if ((!strcmp (atom[a_ref - 1].atype, "N3 ") ||
4439
              !strcmp (atom[a_ref - 1].atype, "N3+")) &&
4440
              atom[a_ref - 1].neighbor_count == 1)
4441
            r = true;
6785 bpr 4442
    }
4443
  return r;
4444
}
4445
 
14179 bpr 4446
static boolean is_alkyl (int a_view, int a_ref)
6785 bpr 4447
{
4448
  int i;
4449
  boolean r = false;
4450
  neighbor_rec nb;
4451
  str2 nb_el;
4452
  int het_count = 0;
4453
  int FORLIM;
4454
 
4455
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4456
  if (! (atom[a_view - 1].
4457
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
6785 bpr 4458
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4459
      || atom[a_ref - 1].arom != false)
4460
    return false;
4461
  get_nextneighbors (nb, a_ref, a_view);
4462
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4463
  for (i = 0; i <= FORLIM; i++) {
4464
    strcpy (nb_el, atom[nb[i] - 1].element);
4465
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4466
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4467
              && strcmp (nb_el, "LP"))
4468
            /* added 'D ' in v0.3n */
4469
            het_count++;
4470
  }
6785 bpr 4471
  if (het_count <= 1)           /* we consider (e.g.) alkoxyalkyl groups as alkyl */
4472
    r = true;
4473
  return r;
4474
}
4475
 
14179 bpr 4476
static boolean is_true_alkyl (int a_view, int a_ref)
6785 bpr 4477
{
4478
  int i;
4479
  boolean r = false;
4480
  neighbor_rec nb;
4481
  str2 nb_el;
4482
  int het_count = 0;
4483
  int FORLIM;
4484
 
4485
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4486
  if (!(atom[a_view - 1].
6785 bpr 4487
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4488
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4489
      || atom[a_ref - 1].arom != false)
4490
    return false;
4491
  get_nextneighbors (nb, a_ref, a_view);
4492
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4493
  for (i = 0; i <= FORLIM; i++) {
4494
    strcpy (nb_el, atom[nb[i] - 1].element);
4495
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4496
             /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
4497
             /* added 'D ' in v0.3n */
4498
             het_count++;
4499
  }
6785 bpr 4500
  if (het_count == 0)           /* */
4501
    r = true;
4502
  return r;
4503
}
4504
 
14179 bpr 4505
static boolean is_alkenyl (int a_view, int a_ref)
6785 bpr 4506
{
4507
  /* new in v0.3j */
4508
  int i;
4509
  boolean r = false;
4510
  neighbor_rec nb;
4511
  str2 nb_el;
4512
  str3 nb_at;
4513
  int c2_count = 0, het_count = 0;
4514
  int FORLIM;
4515
 
4516
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4517
  if (! (atom[a_view - 1].
6785 bpr 4518
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4519
      || strcmp (atom[a_ref - 1].atype, "C2 ")
14179 bpr 4520
      || atom[a_ref - 1].arom != false) {
4521
    return false;
4522
  }                             /* v0.3k: changed c2_count = 1 into c2_count >= 1 */
6785 bpr 4523
  get_nextneighbors (nb, a_ref, a_view);
4524
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4525
  for (i = 0; i <= FORLIM; i++) {
4526
    strcpy (nb_el, atom[nb[i] - 1].element);
4527
    strcpy (nb_at, atom[nb[i] - 1].atype);
4528
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4529
            /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4530
             && strcmp (nb_el, "LP"))
4531
            /* added 'D ' in v0.3n */
4532
            het_count++;
4533
    if (!strcmp (nb_at, "C2 "))
4534
            c2_count++;
4535
  }
6785 bpr 4536
  if (c2_count >= 1 && het_count <= 1)
4537
    /* we consider (e.g.) alkoxyalkenyl groups as alkenyl */
4538
    r = true;
4539
  return r;
4540
}
4541
 
14179 bpr 4542
static boolean is_alkynyl (int a_view, int a_ref)
6785 bpr 4543
{
4544
  /* new in v0.3j */
4545
  int i;
4546
  boolean r = false;
4547
  neighbor_rec nb;
4548
  str3 nb_at;
4549
  int c1_count = 0;
4550
  int FORLIM;
4551
 
4552
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4553
  if (!(atom[a_view - 1].
6785 bpr 4554
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4555
      || strcmp (atom[a_ref - 1].atype, "C1 ")
4556
      || atom[a_ref - 1].arom != false)
4557
    return false;
4558
  get_nextneighbors (nb, a_ref, a_view);
4559
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4560
  for (i = 0; i <= FORLIM; i++) {
4561
    strcpy (nb_at, atom[nb[i] - 1].atype);
4562
    if (!strcmp (nb_at, "C1 "))
4563
            c1_count++;
4564
  }
6785 bpr 4565
  if (c1_count == 1)
4566
    r = true;
4567
  return r;
4568
}
4569
 
14179 bpr 4570
static boolean is_aryl (int a_view, int a_ref)
6785 bpr 4571
{
4572
  boolean r = false;
4573
 
4574
  if ((atom[a_view - 1].
4575
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4576
      && !strcmp (atom[a_ref - 1].element, "C ")
4577
      && atom[a_ref - 1].arom == true)
4578
    r = true;
4579
  return r;
4580
}
4581
 
14179 bpr 4582
static boolean is_alkoxy (int a_view, int a_ref)
6785 bpr 4583
{
4584
  boolean r = false;
4585
  neighbor_rec nb;
4586
 
4587
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4588
  if (!(atom[a_view - 1].
6785 bpr 4589
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4590
    return false;
4591
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4592
      || atom[a_ref - 1].neighbor_count != 2)
4593
    return false;
4594
  get_nextneighbors (nb, a_ref, a_view);
4595
  if (is_alkyl (a_ref, nb[0]))
4596
    r = true;
4597
  return r;
4598
}
4599
 
14179 bpr 4600
static boolean is_siloxy (int a_view, int a_ref)
6785 bpr 4601
{
4602
  boolean r = false;
4603
  neighbor_rec nb;
4604
 
4605
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4606
  if (!(atom[a_view - 1].
6785 bpr 4607
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4608
    return false;
4609
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4610
      || atom[a_ref - 1].neighbor_count != 2)
4611
    return false;
4612
  get_nextneighbors (nb, a_ref, a_view);
4613
  if (!strcmp (atom[nb[0] - 1].element, "SI"))
4614
    r = true;
4615
  return r;
4616
}
4617
 
14179 bpr 4618
static boolean is_true_alkoxy (int a_view, int a_ref)
6785 bpr 4619
{
4620
  boolean r = false;
4621
  neighbor_rec nb;
4622
 
4623
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4624
  if (!(atom[a_view - 1].
6785 bpr 4625
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4626
    return false;
4627
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4628
      || atom[a_ref - 1].neighbor_count != 2)
4629
    return false;
4630
  get_nextneighbors (nb, a_ref, a_view);
4631
  if (is_true_alkyl (a_ref, nb[0]))
4632
    r = true;
4633
  return r;
4634
}
4635
 
14179 bpr 4636
static boolean is_aryloxy (int a_view, int a_ref)
6785 bpr 4637
{
4638
  boolean r = false;
4639
  neighbor_rec nb;
4640
 
4641
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4642
  if (!(atom[a_view - 1].
6785 bpr 4643
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4644
    return false;
4645
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4646
      || atom[a_ref - 1].neighbor_count != 2)
4647
    return false;
4648
  get_nextneighbors (nb, a_ref, a_view);
4649
  if (is_aryl (a_ref, nb[0]))
4650
    r = true;
4651
  return r;
4652
}
4653
 
14179 bpr 4654
static boolean is_alkenyloxy (int a_view, int a_ref) {
6785 bpr 4655
  /* v0.3j */
4656
  boolean r = false;
4657
  neighbor_rec nb;
4658
 
4659
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4660
  if (!(atom[a_view - 1].
6785 bpr 4661
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4662
    return false;
4663
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4664
      || atom[a_ref - 1].neighbor_count != 2)
4665
    return false;
4666
  get_nextneighbors (nb, a_ref, a_view);
4667
  if (is_alkenyl (a_ref, nb[0]))
4668
    r = true;
4669
  return r;
4670
}
4671
 
14179 bpr 4672
static boolean is_alkynyloxy (int a_view, int a_ref)
6785 bpr 4673
{
4674
  /* v0.3j */
4675
  boolean r = false;
4676
  neighbor_rec nb;
4677
 
4678
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4679
  if (!(atom[a_view - 1].
6785 bpr 4680
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4681
    return false;
4682
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4683
      || atom[a_ref - 1].neighbor_count != 2)
4684
    return false;
4685
  get_nextneighbors (nb, a_ref, a_view);
4686
  if (is_alkynyl (a_ref, nb[0]))
4687
    r = true;
4688
  return r;
4689
}
4690
 
14179 bpr 4691
static boolean is_alkylsulfanyl (int a_view, int a_ref)
6785 bpr 4692
{
4693
  boolean r = false;
4694
  neighbor_rec nb;
4695
 
4696
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4697
  if (!(atom[a_view - 1].
6785 bpr 4698
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4699
    return false;
4700
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4701
      || atom[a_ref - 1].neighbor_count != 2)
4702
    return false;
4703
  get_nextneighbors (nb, a_ref, a_view);
4704
  if (is_alkyl (a_ref, nb[0]))
4705
    r = true;
4706
  return r;
4707
}
4708
 
14179 bpr 4709
static boolean is_true_alkylsulfanyl (int a_view, int a_ref)
6785 bpr 4710
{
4711
  boolean r = false;
4712
  neighbor_rec nb;
4713
 
4714
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4715
  if (!(atom[a_view - 1].
6785 bpr 4716
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4717
    return false;
4718
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4719
      || atom[a_ref - 1].neighbor_count != 2)
4720
    return false;
4721
  get_nextneighbors (nb, a_ref, a_view);
4722
  if (is_true_alkyl (a_ref, nb[0]))
4723
    r = true;
4724
  return r;
4725
}
4726
 
14179 bpr 4727
static boolean is_arylsulfanyl (int a_view, int a_ref)
6785 bpr 4728
{
4729
  boolean r = false;
4730
  neighbor_rec nb;
4731
 
4732
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4733
  if (!(atom[a_view - 1].
6785 bpr 4734
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4735
    return false;
4736
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4737
      || atom[a_ref - 1].neighbor_count != 2)
4738
    return false;
4739
  get_nextneighbors (nb, a_ref, a_view);
4740
  if (is_aryl (a_ref, nb[0]))
4741
    r = true;
4742
  return r;
4743
}
4744
 
14179 bpr 4745
static boolean is_alkenylsulfanyl (a_view, a_ref)
6785 bpr 4746
     int a_view, a_ref;
4747
{
4748
  /* v0.3j */
4749
  boolean r = false;
4750
  neighbor_rec nb;
4751
 
4752
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4753
  if (!(atom[a_view - 1].
6785 bpr 4754
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4755
    return false;
4756
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4757
      || atom[a_ref - 1].neighbor_count != 2)
4758
    return false;
4759
  get_nextneighbors (nb, a_ref, a_view);
4760
  if (is_alkenyl (a_ref, nb[0]))
4761
    r = true;
4762
  return r;
4763
}
4764
 
14179 bpr 4765
static boolean is_alkynylsulfanyl (a_view, a_ref)
6785 bpr 4766
     int a_view, a_ref;
4767
{
4768
  /* v0.3j */
4769
  boolean r = false;
4770
  neighbor_rec nb;
4771
 
4772
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4773
  if (!(atom[a_view - 1].
6785 bpr 4774
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4775
    return false;
4776
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4777
      || atom[a_ref - 1].neighbor_count != 2)
4778
    return false;
4779
  get_nextneighbors (nb, a_ref, a_view);
4780
  if (is_alkynyl (a_ref, nb[0]))
4781
    r = true;
4782
  return r;
4783
}
4784
 
14179 bpr 4785
static boolean is_alkylamino (a_view, a_ref)
6785 bpr 4786
     int a_view, a_ref;
4787
{
4788
  boolean r = false;
4789
  neighbor_rec nb;
4790
  int alkyl_count = 0;
4791
 
4792
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4793
  if (!(atom[a_view - 1].
6785 bpr 4794
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4795
    return false;
4796
  if (strcmp (atom[a_ref - 1].element, "N ")
4797
      || atom[a_ref - 1].neighbor_count != 2)
4798
    return false;
4799
  get_nextneighbors (nb, a_ref, a_view);
4800
  if (is_alkyl (a_ref, nb[0]))
4801
    alkyl_count++;
4802
  if (alkyl_count == 1)
4803
    r = true;
4804
  return r;
4805
}
4806
 
14179 bpr 4807
static boolean is_dialkylamino (a_view, a_ref)
6785 bpr 4808
     int a_view, a_ref;
4809
{
4810
  int i;
4811
  boolean r = false;
4812
  neighbor_rec nb;
4813
  int alkyl_count = 0;
4814
 
4815
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4816
  if (!(atom[a_view - 1].
6785 bpr 4817
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4818
    return false;
4819
  if (strcmp (atom[a_ref - 1].element, "N ")
4820
      || atom[a_ref - 1].neighbor_count != 3)
4821
    return false;
4822
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4823
  for (i = 0; i <= 1; i++) {
4824
    if (is_alkyl (a_ref, nb[i]))
4825
            alkyl_count++;
4826
  }
6785 bpr 4827
  if (alkyl_count == 2)
4828
    r = true;
4829
  return r;
4830
}
4831
 
14179 bpr 4832
static boolean is_arylamino (a_view, a_ref)
6785 bpr 4833
     int a_view, a_ref;
4834
{
4835
  boolean r = false;
4836
  neighbor_rec nb;
4837
  int aryl_count = 0;
4838
 
4839
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4840
  if (!(atom[a_view - 1].
6785 bpr 4841
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4842
    return false;
4843
  if (strcmp (atom[a_ref - 1].element, "N ")
4844
      || atom[a_ref - 1].neighbor_count != 2)
4845
    return false;
4846
  get_nextneighbors (nb, a_ref, a_view);
4847
  if (is_aryl (a_ref, nb[0]))
4848
    aryl_count++;
4849
  if (aryl_count == 1)
4850
    r = true;
4851
  return r;
4852
}
4853
 
14179 bpr 4854
static boolean is_diarylamino (a_view, a_ref)
6785 bpr 4855
     int a_view, a_ref;
4856
{
4857
  int i;
4858
  boolean r = false;
4859
  neighbor_rec nb;
4860
  int aryl_count = 0;
4861
 
4862
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4863
  if (!(atom[a_view - 1].
6785 bpr 4864
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4865
    return false;
4866
  if (strcmp (atom[a_ref - 1].element, "N ")
4867
      || atom[a_ref - 1].neighbor_count != 3)
4868
    return false;
4869
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4870
  for (i = 0; i <= 1; i++) {
4871
    if (is_aryl (a_ref, nb[i]))
4872
            aryl_count++;
4873
  }
6785 bpr 4874
  if (aryl_count == 2)
4875
    r = true;
4876
  return r;
4877
}
4878
 
14179 bpr 4879
static boolean is_alkylarylamino (a_view, a_ref)
6785 bpr 4880
     int a_view, a_ref;
4881
{
4882
  int i;
4883
  boolean r = false;
4884
  neighbor_rec nb;
4885
  int alkyl_count = 0, aryl_count = 0;
4886
 
4887
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4888
  if (!(atom[a_view - 1].
6785 bpr 4889
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4890
    return false;
4891
  if (strcmp (atom[a_ref - 1].element, "N ")
4892
      || atom[a_ref - 1].neighbor_count != 3)
4893
    return false;
4894
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4895
  for (i = 0; i <= 1; i++) {
4896
    if (is_alkyl (a_ref, nb[i]))
4897
            alkyl_count++;
4898
    if (is_aryl (a_ref, nb[i]))
4899
            aryl_count++;
4900
  }
6785 bpr 4901
  if (alkyl_count == 1 && aryl_count == 1)
4902
    r = true;
4903
  return r;
4904
}
4905
 
14179 bpr 4906
static boolean is_C_monosubst_amino (a_view, a_ref)
6785 bpr 4907
     int a_view, a_ref;
4908
{
4909
  /* new in v0.3j */
4910
  boolean r = false;
4911
  neighbor_rec nb;
4912
  int c_count = 0;
4913
 
4914
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4915
  if (! (atom[a_view - 1].
6785 bpr 4916
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4917
    return false;
4918
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4919
      && strcmp (atom[a_ref - 1].atype, "NAM"))
4920
      || atom[a_ref - 1].neighbor_count != 2)
4921
    return false;
4922
  get_nextneighbors (nb, a_ref, a_view);
4923
  if (!strcmp (atom[nb[0] - 1].element, "C "))
4924
    c_count++;
4925
  if (c_count == 1)
4926
    r = true;
4927
  return r;
4928
}
4929
 
14179 bpr 4930
static boolean is_C_disubst_amino (a_view, a_ref)
6785 bpr 4931
     int a_view, a_ref;
4932
{
4933
  /* new in v0.3j */
4934
  int i;
4935
  boolean r = false;
4936
  neighbor_rec nb;
4937
  int b;
4938
  int c_count = 0;
4939
 
4940
  b = get_bond (a_view, a_ref);
4941
  memset (nb, 0, sizeof (neighbor_rec));
4942
  if (!(atom[a_view - 1].heavy && bond[b - 1].btype == 'S' &&
14179 bpr 4943
            bond[b - 1].arom == false))
6785 bpr 4944
    return false;
4945
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4946
      && strcmp (atom[a_ref - 1].atype, "NAM"))
4947
      || atom[a_ref - 1].neighbor_count != 3)
4948
    return false;
4949
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4950
  for (i = 0; i <= 1; i++) {
4951
    if (!strcmp (atom[nb[i] - 1].element, "C "))
4952
            c_count++;
4953
  }
6785 bpr 4954
  if (c_count == 2)
4955
    r = true;
4956
  return r;
4957
}
4958
 
14179 bpr 4959
static boolean is_subst_amino (a_view, a_ref)
6785 bpr 4960
     int a_view, a_ref;
4961
{
4962
  boolean r = false;
4963
 
4964
  if (is_amino (a_view, a_ref) || is_alkylamino (a_view, a_ref) |
4965
      is_arylamino (a_view, a_ref) || is_dialkylamino (a_view, a_ref) |
4966
      is_alkylarylamino (a_view, a_ref) || is_diarylamino (a_view, a_ref))
4967
    r = true;
4968
  return r;
4969
}
4970
 
14179 bpr 4971
static boolean is_true_alkylamino (a_view, a_ref)
6785 bpr 4972
     int a_view, a_ref;
4973
{
4974
  boolean r = false;
4975
  neighbor_rec nb;
4976
  int alkyl_count = 0;
4977
 
4978
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4979
  if (!(atom[a_view - 1].
6785 bpr 4980
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4981
    return false;
4982
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4983
      && strcmp (atom[a_ref - 1].atype, "N3+"))
4984
      || atom[a_ref - 1].neighbor_count != 2)
4985
    return false;
4986
  get_nextneighbors (nb, a_ref, a_view);
4987
  if (is_true_alkyl (a_ref, nb[0]))
4988
    alkyl_count++;
4989
  if (alkyl_count == 1)
4990
    r = true;
4991
  return r;
4992
}
4993
 
14179 bpr 4994
static boolean is_true_dialkylamino (a_view, a_ref)
6785 bpr 4995
     int a_view, a_ref;
4996
{
4997
  int i;
4998
  boolean r = false;
4999
  neighbor_rec nb;
5000
  int alkyl_count = 0;
5001
 
5002
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5003
  if (!(atom[a_view - 1].
6785 bpr 5004
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5005
    return false;
5006
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5007
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5008
      || atom[a_ref - 1].neighbor_count != 3)
5009
    return false;
5010
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5011
  for (i = 0; i <= 1; i++) {
5012
    if (is_true_alkyl (a_ref, nb[i]))
5013
            alkyl_count++;
5014
  }
6785 bpr 5015
  if (alkyl_count == 2)
5016
    r = true;
5017
  return r;
5018
}
5019
 
5020
#if 0
14179 bpr 5021
static boolean is_true_alkylarylamino (a_view, a_ref)
6785 bpr 5022
     int a_view, a_ref;
5023
{
5024
  int i;
5025
  boolean r = false;
5026
  neighbor_rec nb;
5027
  int alkyl_count = 0, aryl_count = 0;
5028
 
5029
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5030
  if (!(atom[a_view - 1].
6785 bpr 5031
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5032
    return false;
5033
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5034
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5035
      || atom[a_ref - 1].neighbor_count != 3)
5036
    return false;
5037
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5038
  for (i = 0; i <= 1; i++) {
5039
    if (is_true_alkyl (a_ref, nb[i]))
5040
            alkyl_count++;
5041
    if (is_aryl (a_ref, nb[i]))
5042
            aryl_count++;
5043
  }
6785 bpr 5044
  if (alkyl_count == 1 && aryl_count == 1)
5045
    r = true;
5046
  return r;
5047
}
5048
#endif
5049
 
14179 bpr 5050
static boolean is_hydroxylamino (a_view, a_ref)
6785 bpr 5051
     int a_view, a_ref;
5052
{
5053
  int i;
5054
  boolean r = false;
5055
  neighbor_rec nb;
5056
  int oh_count = 0, het_count = 0;      /* v0.3k */
5057
  str2 nb_el;                   /* v0.3k */
5058
  int FORLIM;
5059
 
5060
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5061
  if (!(atom[a_view - 1].
6785 bpr 5062
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5063
    return false;
5064
  if (strcmp (atom[a_ref - 1].element, "N ")
5065
      || atom[a_ref - 1].neighbor_count < 2)
5066
    /* v0.3c */
5067
    return false;
5068
  get_nextneighbors (nb, a_ref, a_view);
5069
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5070
  for (i = 0; i <= FORLIM; i++) {                               /* v0.3c */
5071
    if (is_hydroxy (a_ref, nb[i]))
5072
            oh_count++;
5073
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
5074
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
5075
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
5076
              && strcmp (nb_el, "LP"))
5077
              /* v0.3k */
5078
            het_count++;
6785 bpr 5079
      /* v0.3n: D */
14179 bpr 5080
  }
6785 bpr 5081
  if (oh_count == 1 && het_count == 1)
5082
    r = true;
5083
  return r;
5084
}
5085
 
14179 bpr 5086
static boolean is_nitro (a_view, a_ref)
6785 bpr 5087
     int a_view, a_ref;
5088
{
5089
  int i;
5090
  boolean r = false;
5091
  neighbor_rec nb;
5092
  int o_count = 0, bond_count = 0;
5093
 
5094
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5095
  if (!(atom[a_view - 1].
6785 bpr 5096
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5097
    return false;
5098
  if (strcmp (atom[a_ref - 1].element, "N ")
5099
      || atom[a_ref - 1].neighbor_count != 3)
5100
    return false;
5101
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5102
  for (i = 0; i <= 1; i++) {
5103
    if (!strcmp (atom[nb[i] - 1].element, "O "))
5104
            o_count++;
5105
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
5106
            bond_count++;
5107
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
5108
            bond_count += 2;
5109
  }
6785 bpr 5110
  if (o_count == 2 && bond_count >= 3)
5111
    r = true;
5112
  return r;
5113
}
5114
 
14179 bpr 5115
static boolean is_azido (a_view, a_ref)
6785 bpr 5116
     int a_view, a_ref;
5117
{
5118
  boolean r = false;
5119
  neighbor_rec nb;
5120
  int bond_count = 0, n1 = 0, n2 = 0, n3 = 0;
5121
 
14179 bpr 5122
  if (!(atom[a_view - 1].
6785 bpr 5123
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5124
    return false;
5125
  if (strcmp (atom[a_ref - 1].element, "N ")
5126
      || atom[a_ref - 1].neighbor_count != 2)
5127
    return false;
5128
  n1 = a_ref;
5129
  memset (nb, 0, sizeof (neighbor_rec));
5130
  get_nextneighbors (nb, n1, a_view);
14179 bpr 5131
  if (!strcmp (atom[nb[0] - 1].element, "N ")) {
5132
    n2 = nb[0];
5133
    if (bond[get_bond (n1, n2) - 1].btype == 'S')
6785 bpr 5134
            bond_count++;
14179 bpr 5135
    if (bond[get_bond (n1, n2) - 1].btype == 'D')
6785 bpr 5136
            bond_count += 2;
14179 bpr 5137
    if (bond[get_bond (n1, n2) - 1].btype == 'T')
6785 bpr 5138
            bond_count += 3;
14179 bpr 5139
  }
5140
  if (n2 > 0 && atom[n2 - 1].neighbor_count == 2) {
5141
    memset (nb, 0, sizeof (neighbor_rec));
5142
    get_nextneighbors (nb, n2, n1);
5143
    if (!strcmp (atom[nb[0] - 1].element, "N ")){
5144
            n3 = nb[0];
5145
            if (bond[get_bond (n2, n3) - 1].btype == 'S')
5146
              bond_count++;
5147
            if (bond[get_bond (n2, n3) - 1].btype == 'D')
5148
              bond_count += 2;
5149
            if (bond[get_bond (n2, n3) - 1].btype == 'T')
5150
              bond_count += 3;
5151
          }
5152
  }
6785 bpr 5153
  if (n1 > 0 && n2 > 0 && n3 > 0 && atom[n3 - 1].neighbor_count == 1 &&
5154
      bond_count > 3)
5155
    r = true;
5156
  return r;
5157
}
5158
 
14179 bpr 5159
static boolean is_diazonium (a_view, a_ref)
6785 bpr 5160
     int a_view, a_ref;
5161
{
5162
  boolean r = false;
5163
  neighbor_rec nb;
5164
  int bond_count = 0, chg_count = 0, n1 = 0, n2 = 0;
5165
 
14179 bpr 5166
  if (!(atom[a_view - 1].
6785 bpr 5167
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5168
    return false;
5169
  if (strcmp (atom[a_ref - 1].element, "N ")
5170
      || atom[a_ref - 1].neighbor_count != 2)
5171
    return false;
5172
  n1 = a_ref;
5173
  chg_count = atom[n1 - 1].formal_charge;
5174
  memset (nb, 0, sizeof (neighbor_rec));
5175
  get_nextneighbors (nb, n1, a_view);
14179 bpr 5176
  if (!strcmp (atom[nb[0] - 1].element, "N ")) {
5177
    n2 = nb[0];
5178
    chg_count += atom[n2 - 1].formal_charge;
5179
    if (bond[get_bond (n1, n2) - 1].btype == 'S')
5180
            bond_count++;
5181
    if (bond[get_bond (n1, n2) - 1].btype == 'D')
5182
            bond_count += 2;
5183
    if (bond[get_bond (n1, n2) - 1].btype == 'T')
5184
            bond_count += 3;
5185
  }
6785 bpr 5186
  if (n1 > 0 && n2 > 0 && atom[n2 - 1].neighbor_count == 1
5187
      && bond_count >= 2 && chg_count > 0)
5188
    r = true;
5189
  return r;
5190
}
5191
 
14179 bpr 5192
static boolean is_hydroximino_C (id)
6785 bpr 5193
     int id;
5194
{
5195
  int i;
5196
  boolean r = false;
5197
  neighbor_rec nb;
5198
  int a_het = 0;
5199
  int FORLIM;
5200
 
5201
  memset (nb, 0, sizeof (neighbor_rec));
5202
  if (id < 1 || id > n_atoms)
6789 bpr 5203
    return false;
6785 bpr 5204
  get_neighbors (nb, id);
5205
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5206
    return false;
5207
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 5208
  for (i = 0; i < FORLIM; i++) {
5209
    if ((bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5210
              !strcmp (atom[nb[i] - 1].element, "N ")) && (hetbond_count (nb[i]) == 3))
5211
            a_het = nb[i];
5212
  }
6785 bpr 5213
  if (a_het <= 0)
5214
    return false;
5215
  memset (nb, 0, sizeof (neighbor_rec));
5216
  get_neighbors (nb, a_het);
5217
  if (strcmp (atom[a_het - 1].element, "N ")
5218
      || atom[a_het - 1].neighbor_count <= 0)
5219
    return false;
5220
  FORLIM = atom[a_het - 1].neighbor_count;
14179 bpr 5221
  for (i = 0; i < FORLIM; i++) {
5222
    if (is_hydroxy (a_het, nb[i]))
5223
          r = true;
5224
  }
6785 bpr 5225
  return r;
5226
}
5227
 
14179 bpr 5228
static boolean is_hydrazono_C (id)
6785 bpr 5229
     int id;
5230
{
5231
  int i;
5232
  boolean r = false;
5233
  neighbor_rec nb;
5234
  int a_het = 0;
5235
  int FORLIM;
5236
 
5237
  memset (nb, 0, sizeof (neighbor_rec));
5238
  if (id < 1 || id > n_atoms)
6789 bpr 5239
    return false;
6785 bpr 5240
  get_neighbors (nb, id);
5241
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5242
    return false;
5243
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 5244
  for (i = 0; i < FORLIM; i++) {
5245
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5246
              !strcmp (atom[nb[i] - 1].element, "N ")) {
6785 bpr 5247
          /* and
5248
             (hetbond_count(nb[i]) = 3)  */
5249
          a_het = nb[i];
14179 bpr 5250
          }
5251
  }
6785 bpr 5252
  if (a_het <= 0)
5253
    return false;
5254
  memset (nb, 0, sizeof (neighbor_rec));
5255
  get_neighbors (nb, a_het);
5256
  if (strcmp (atom[a_het - 1].element, "N ")
5257
      || atom[a_het - 1].neighbor_count <= 0)
5258
    return false;
5259
  FORLIM = atom[a_het - 1].neighbor_count;
14179 bpr 5260
  for (i = 0; i < FORLIM; i++) {
5261
    if (is_amino (a_het, nb[i]) || is_alkylamino (a_het, nb[i]) |
5262
              is_alkylarylamino (a_het, nb[i]) || is_arylamino (a_het, nb[i]) |
5263
              is_dialkylamino (a_het, nb[i]) || is_diarylamino (a_het, nb[i]))
5264
            r = true;
5265
  }
6785 bpr 5266
  return r;
5267
}
5268
 
14179 bpr 5269
static boolean is_alkoxycarbonyl (a_view, a_ref)
6785 bpr 5270
     int a_view, a_ref;
5271
{
5272
  int i;
5273
  boolean r = false;
5274
  neighbor_rec nb;
5275
 
5276
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5277
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6785 bpr 5278
    return false;
5279
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5280
    return false;
5281
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5282
  for (i = 0; i <= 1; i++) {
5283
    if (is_alkoxy (a_ref, nb[i]))
5284
            r = true;
5285
  }
6785 bpr 5286
  return r;
5287
}
5288
 
14179 bpr 5289
static boolean is_aryloxycarbonyl (a_view, a_ref)
6785 bpr 5290
     int a_view, a_ref;
5291
{
5292
  int i;
5293
  boolean r = false;
5294
  neighbor_rec nb;
5295
 
5296
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5297
  if (!(atom[a_view - 1].
6785 bpr 5298
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5299
    return false;
5300
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5301
    return false;
5302
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5303
  for (i = 0; i <= 1; i++) {
5304
    if (is_aryloxy (a_ref, nb[i]))
5305
            r = true;
5306
  }
6785 bpr 5307
  return r;
5308
}
5309
 
14179 bpr 5310
static boolean is_carbamoyl (a_view, a_ref)
6785 bpr 5311
     int a_view, a_ref;
5312
{
5313
  int i;
5314
  boolean r = false;
5315
  neighbor_rec nb;
5316
 
5317
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5318
  if (!(atom[a_view - 1].
6785 bpr 5319
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5320
    return false;
5321
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5322
    return false;
5323
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5324
  for (i = 0; i <= 1; i++) {
5325
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
5326
            r = true;
5327
  }
6785 bpr 5328
  return r;
5329
}
5330
 
14179 bpr 5331
static boolean is_alkoxythiocarbonyl (a_view, a_ref)
6785 bpr 5332
     int a_view, a_ref;
5333
{
5334
  int i;
5335
  boolean r = false;
5336
  neighbor_rec nb;
5337
 
5338
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5339
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6785 bpr 5340
    return false;
5341
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5342
    return false;
5343
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5344
  for (i = 0; i <= 1; i++) {
5345
    if (is_alkoxy (a_ref, nb[i]))
5346
            r = true;
5347
  }
6785 bpr 5348
  return r;
5349
}
5350
 
14179 bpr 5351
static boolean is_aryloxythiocarbonyl (a_view, a_ref)
6785 bpr 5352
     int a_view, a_ref;
5353
{
5354
  int i;
5355
  boolean r = false;
5356
  neighbor_rec nb;
5357
 
5358
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5359
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6785 bpr 5360
    return false;
5361
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5362
    return false;
5363
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5364
  for (i = 0; i <= 1; i++) {
5365
    if (is_aryloxy (a_ref, nb[i]))
5366
            r = true;
5367
  }
6785 bpr 5368
  return r;
5369
}
5370
 
14179 bpr 5371
static boolean is_thiocarbamoyl (a_view, a_ref)
6785 bpr 5372
     int a_view, a_ref;
5373
{
5374
  int i;
5375
  boolean r = false;
5376
  neighbor_rec nb;
5377
 
5378
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5379
  if (!(atom[a_view - 1].
6785 bpr 5380
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5381
    return false;
5382
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5383
    return false;
5384
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5385
  for (i = 0; i <= 1; i++) {
5386
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5387
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
5388
            r = true;
5389
  }
6785 bpr 5390
  return r;
5391
}
5392
 
14179 bpr 5393
static boolean is_alkanoyl (a_view, a_ref)
6785 bpr 5394
     int a_view, a_ref;
5395
{
5396
  int i;
5397
  boolean r = false;
5398
  neighbor_rec nb;
5399
 
5400
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5401
  if (!(atom[a_view - 1].
6785 bpr 5402
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5403
    return false;
5404
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5405
    return false;
5406
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5407
  for (i = 0; i <= 1; i++) {
5408
    if (is_alkyl (a_ref, nb[i]))
5409
            r = true;
5410
  }
6785 bpr 5411
  return r;
5412
}
5413
 
14179 bpr 5414
static boolean is_aroyl (a_view, a_ref)
6785 bpr 5415
     int a_view, a_ref;
5416
{
5417
  int i;
5418
  boolean r = false;
5419
  neighbor_rec nb;
5420
 
5421
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5422
  if (!(atom[a_view - 1].
6785 bpr 5423
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5424
    return false;
5425
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5426
    return false;
5427
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5428
  for (i = 0; i <= 1; i++) {
5429
    if (is_aryl (a_ref, nb[i]))
5430
            r = true;
5431
  }
6785 bpr 5432
  return r;
5433
}
5434
 
14179 bpr 5435
static boolean is_acyl (a_view, a_ref)
6785 bpr 5436
     int a_view, a_ref;
5437
{
5438
  boolean r = false;
5439
 
5440
  if (is_alkanoyl (a_view, a_ref) || is_aroyl (a_view, a_ref))
5441
    r = true;
5442
  return r;
5443
}
5444
 
14179 bpr 5445
static boolean is_acyl_gen (a_view, a_ref)
6785 bpr 5446
     int a_view, a_ref;
5447
{
5448
  /* new in v0.3j */
5449
  boolean r = false;
5450
 
5451
  if (is_oxo_C (a_ref))
5452
    r = true;
5453
  return r;
5454
}
5455
 
14179 bpr 5456
static boolean is_acylamino (a_view, a_ref)
6785 bpr 5457
     int a_view, a_ref;
5458
{
5459
  boolean r = false;
5460
  neighbor_rec nb;
5461
  int acyl_count = 0;
5462
 
5463
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5464
  if (!(atom[a_view - 1].
6785 bpr 5465
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5466
    return false;
5467
  if (strcmp (atom[a_ref - 1].element, "N ")
5468
      || atom[a_ref - 1].neighbor_count != 2)
5469
    return false;
5470
  get_nextneighbors (nb, a_ref, a_view);
5471
  if (is_acyl (a_ref, nb[0]))
5472
    acyl_count++;
5473
  if (acyl_count == 1)
5474
    r = true;
5475
  return r;
5476
}
5477
 
14179 bpr 5478
static boolean is_subst_acylamino (a_view, a_ref)
6785 bpr 5479
     int a_view, a_ref;
5480
{
5481
  /* may be substituted _or_ unsubstituted acylamino group! */
5482
  int i;
5483
  boolean r = false;
5484
  neighbor_rec nb;
5485
  int acyl_count = 0;
5486
  int FORLIM;
5487
 
5488
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5489
  if (!(atom[a_view - 1].
6785 bpr 5490
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5491
    return false;
5492
  if (strcmp (atom[a_ref - 1].element, "N ")
5493
      || atom[a_ref - 1].neighbor_count < 2)
5494
    return false;
5495
  get_nextneighbors (nb, a_ref, a_view);
5496
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5497
  for (i = 0; i <= FORLIM; i++) {
5498
    if (is_acyl_gen (a_ref, nb[i]))     /* v0.3j */
5499
            acyl_count++;
5500
  }
6785 bpr 5501
  if (acyl_count > 0)
5502
    r = true;
5503
  return r;
5504
}
5505
 
14179 bpr 5506
static boolean is_hydrazino (a_view, a_ref)
6785 bpr 5507
     int a_view, a_ref;
5508
{
5509
  int i;
5510
  boolean r = false;
5511
  neighbor_rec nb;
5512
  int nr_count = 0;
5513
  int FORLIM;
5514
 
5515
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5516
  if (!(atom[a_view - 1].
6785 bpr 5517
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5518
    return false;
5519
  if (strcmp (atom[a_ref - 1].element, "N ")
5520
      || atom[a_ref - 1].neighbor_count < 2)
5521
    return false;
5522
  get_nextneighbors (nb, a_ref, a_view);
5523
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5524
  for (i = 0; i <= FORLIM; i++) {                               /* fixed in v0.3c */
5525
    if (is_amino (a_ref, nb[i]) || is_subst_amino (a_ref, nb[i]))
5526
            nr_count++;
5527
  }
6785 bpr 5528
  if (nr_count == 1)
5529
    r = true;
5530
  return r;
5531
}
5532
 
14179 bpr 5533
static boolean is_nitroso (a_view, a_ref)
6785 bpr 5534
     int a_view, a_ref;
5535
{
5536
  /* new in v0.3j */
5537
  boolean r = false;
5538
  neighbor_rec nb;
5539
  int o_count = 0;
5540
  int a2;
5541
 
5542
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5543
  if (!(atom[a_view - 1].
6785 bpr 5544
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5545
    return false;
5546
  if (strcmp (atom[a_ref - 1].element, "N ")
5547
      || atom[a_ref - 1].neighbor_count != 2)
5548
    return false;
5549
  get_nextneighbors (nb, a_ref, a_view);
5550
  a2 = nb[0];
5551
  if ((strcmp (atom[a2 - 1].element, "O ") == 0) &
5552
      (bond[get_bond (a_ref, a2) - 1].btype == 'D'))
5553
    o_count++;
5554
  if (o_count == 1)
5555
    r = true;
5556
  return r;
5557
}
5558
 
14179 bpr 5559
static boolean is_subst_hydrazino (a_view, a_ref)
6785 bpr 5560
     int a_view, a_ref;
5561
{
5562
  int i;
5563
  boolean r = false;
5564
  neighbor_rec nb;
5565
  int nr_count = 0;
5566
  int a2, FORLIM;
5567
 
5568
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5569
  if (!(atom[a_view - 1].
6785 bpr 5570
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5571
    return false;
5572
  if (strcmp (atom[a_ref - 1].element, "N ")
5573
      || atom[a_ref - 1].neighbor_count < 2)
5574
    return false;
5575
  get_nextneighbors (nb, a_ref, a_view);
5576
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5577
  for (i = 0; i <= FORLIM; i++) {
5578
    a2 = nb[i];
5579
    if ((strcmp (atom[a2 - 1].element, "N ") == 0) && (!is_nitroso (a_ref, a2)))
5580
            /* v0.3j */
5581
            nr_count++;
5582
  }
6785 bpr 5583
  if (nr_count == 1)
5584
    r = true;
5585
  return r;
5586
}
5587
 
14179 bpr 5588
static boolean is_cyano (a_view, a_ref)
6785 bpr 5589
     int a_view, a_ref;
5590
{
5591
  boolean r = false;
5592
 
5593
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
14179 bpr 5594
      (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6785 bpr 5595
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
5596
      atom[a_ref - 1].neighbor_count == 1)
5597
    r = true;
5598
  return r;
5599
}
5600
 
14179 bpr 5601
static boolean is_cyano_c (a_ref)
6785 bpr 5602
     int a_ref;
5603
{
5604
  int i;
5605
  boolean r = false;
5606
  neighbor_rec nb;
5607
  int FORLIM;
5608
 
5609
  memset (nb, 0, sizeof (neighbor_rec));
5610
  if (strcmp (atom[a_ref - 1].atype, "C1 ")
5611
      || atom[a_ref - 1].neighbor_count <= 0)
5612
    return false;
5613
  get_neighbors (nb, a_ref);
5614
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 5615
  for (i = 0; i < FORLIM; i++) {
5616
    if (is_cyano (a_ref, nb[i]))
5617
            r = true;
5618
  }
6785 bpr 5619
  return r;
5620
}
5621
 
14179 bpr 5622
static boolean is_nitrile (a_view, a_ref)
6785 bpr 5623
     int a_view, a_ref;
5624
{
5625
  boolean r = false;
5626
  neighbor_rec nb;
5627
  str2 nb_el;
5628
 
5629
  if (!is_cyano (a_view, a_ref))
5630
    return false;
5631
  if (atom[a_view - 1].neighbor_count == 1
5632
      && atom[a_view - 1].formal_charge == 0)
5633
    return true;
5634
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
5635
  get_nextneighbors (nb, a_view, a_ref);
5636
  strcpy (nb_el, atom[nb[0] - 1].element);
5637
  if (!strcmp (nb_el, "C ")
5638
      || !strcmp (nb_el, "H ") /*|| !strcmp (nb_el, "D ") */ )
5639
    /* v0.3n: D */
5640
    r = true;
5641
  /* HCN is also a nitrile! */
5642
  return r;
5643
}
5644
 
14179 bpr 5645
static boolean is_isonitrile (a_view, a_ref)
6785 bpr 5646
     int a_view, a_ref;
5647
{
5648
  /* only recognized with CN triple bond! */
5649
  boolean r = false;
5650
 
17890 bpr 5651
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &&
6785 bpr 5652
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
5653
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
5654
      atom[a_ref - 1].neighbor_count == 2
5655
      && atom[a_view - 1].neighbor_count == 1)
5656
    r = true;
5657
  return r;
5658
}
5659
 
14179 bpr 5660
static boolean is_cyanate (a_view, a_ref)
6785 bpr 5661
     int a_view, a_ref;
5662
{
5663
  boolean r = false;
5664
  neighbor_rec nb;
5665
 
5666
  if (!is_cyano (a_view, a_ref))
5667
    return false;
5668
  if (atom[a_view - 1].neighbor_count != 2)
5669
    return false;
5670
  get_nextneighbors (nb, a_view, a_ref);
5671
  if (is_alkoxy (a_view, nb[0]) || is_aryloxy (a_view, nb[0]))
5672
    r = true;
5673
  return r;
5674
}
5675
 
14179 bpr 5676
static boolean is_thiocyanate (a_view, a_ref)
6785 bpr 5677
     int a_view, a_ref;
5678
{
5679
  boolean r = false;
5680
  neighbor_rec nb;
5681
 
5682
  if (!is_cyano (a_view, a_ref))
5683
    return false;
5684
  if (atom[a_view - 1].neighbor_count != 2)
5685
    return false;
5686
  get_nextneighbors (nb, a_view, a_ref);
5687
  if (is_alkylsulfanyl (a_view, nb[0]) || is_arylsulfanyl (a_view, nb[0]))
5688
    r = true;
5689
  return r;
5690
}
5691
 
14179 bpr 5692
static void update_Htotal ()
6785 bpr 5693
{
5694
  int i, j, b_id;
5695
  neighbor_rec nb;
5696
  int single_count, double_count, triple_count, arom_count, total_bonds,
5697
    Htotal, nval;
5698
  /* new in v0.3 */
5699
  boolean diazon = false;       /* new in v0.3j */
5700
  neighbor_rec nb2;             /* new in v0.3j */
5701
  int a1, a2, a3;               /* new in v0.3j */
5702
  int FORLIM, FORLIM1;
5703
 
5704
  if (n_atoms < 1)
5705
    return;
5706
  memset (nb, 0, sizeof (neighbor_rec));
5707
  FORLIM = n_atoms;
14179 bpr 5708
  for (i = 1; i <= FORLIM; i++) {
5709
    single_count = 0;
5710
    double_count = 0;
5711
    triple_count = 0;
5712
    arom_count = 0;
5713
    total_bonds = 0;
5714
    Htotal = 0;
5715
    get_neighbors (nb, i);
5716
    if (atom[i - 1].neighbor_count > 0) {
5717
            /* count single, double, triple, and aromatic bonds to all neighbor atoms */
5718
            FORLIM1 = atom[i - 1].neighbor_count;
5719
            for (j = 0; j < FORLIM1; j++) {
5720
                b_id = get_bond (i, nb[j]);
5721
              if (b_id > 0) {
5722
                      if (bond[b_id - 1].btype == 'S')
5723
                        single_count++;
5724
                      if (bond[b_id - 1].btype == 'D')
5725
                        double_count++;
5726
                      if (bond[b_id - 1].btype == 'T')
5727
                        triple_count++;
5728
                      if (bond[b_id - 1].btype == 'A')
5729
                        arom_count++;
5730
                    }
6785 bpr 5731
            }
14179 bpr 5732
            /*check for diazonium salts */
5733
            a1 = i;
5734
            a2 = nb[0];
5735
            if (!strcmp (atom[a1 - 1].element, "N ") && !strcmp (atom[a2 - 1].element, "N ")) {
5736
              if (atom[a2 - 1].neighbor_count == 2) {
5737
                      get_nextneighbors (nb2, a2, a1);
5738
                      a3 = nb2[0];
5739
                      if ((strcmp (atom[a3 - 1].element, "C ") == 0) && is_diazonium (a3, a2))
5740
                        diazon = true;
5741
                  }
6785 bpr 5742
            }
14179 bpr 5743
          }
5744
    total_bonds = single_count + double_count * 2 + triple_count * 3 + (int) (1.5 * arom_count);
6785 bpr 5745
      /* calculate number of total hydrogens per atom */
5746
      /*nval := nvalences(atom^[i].element);    (* new in v0.3 */
14179 bpr 5747
    nval = atom[i - 1].nvalences;       /* new in v0.3m */
5748
    if (!strcmp (atom[i - 1].element, "P ")) {
5749
            if (total_bonds - atom[i - 1].formal_charge > 3)    /* refined in v0.3n */
5750
              nval = 5;
5751
          }                     /*  */
5752
    if (!strcmp (atom[i - 1].element, "S ")) {                  /* v0.3h */
5753
            if (total_bonds > 2 && atom[i - 1].formal_charge < 1)
5754
              /* updated in v0.3j */
5755
              nval = 4;
5756
            if (total_bonds > 4)        /* this will need some refinement... */
5757
              nval = 6;
5758
          }                     /*  */
5759
    Htotal = nval - total_bonds + atom[i - 1].formal_charge;
5760
    if (diazon)         /* v0.3j */
5761
            Htotal = 0;
5762
    if (Htotal < 0)             /* e.g., N in nitro group */
5763
            Htotal = 0;
6785 bpr 5764
      atom[i - 1].Htot = Htotal;
14179 bpr 5765
    if (atom[i - 1].Hexp > atom[i - 1].Htot)    /* v0.3n; just to be sure... */
5766
            atom[i - 1].Htot = atom[i - 1].Hexp;
5767
  }
6785 bpr 5768
}
5769
 
14179 bpr 5770
static void update_atypes ()
6785 bpr 5771
{
5772
  int i, j, b_id;
5773
  neighbor_rec nb;
5774
  int single_count, double_count, triple_count, arom_count, acyl_count,
5775
    C_count, O_count, total_bonds, NdO_count, NdC_count, Htotal, FORLIM,
5776
    FORLIM1;
5777
 
5778
  if (n_atoms < 1)
5779
    return;
5780
  memset (nb, 0, sizeof (neighbor_rec));
5781
  FORLIM = n_atoms;
14179 bpr 5782
  for (i = 0; i < FORLIM; i++) {
5783
    single_count = 0;
5784
    double_count = 0;
5785
    triple_count = 0;
5786
    arom_count = 0;
5787
    total_bonds = 0;
5788
    acyl_count = 0;
5789
    C_count = 0;
5790
    O_count = 0;
5791
    NdO_count = 0;
5792
    NdC_count = 0;
5793
    Htotal = 0;
5794
    get_neighbors (nb, i + 1);
5795
    if (atom[i].neighbor_count > 0) {
5796
            /* count single, double, triple, and aromatic bonds to all neighbor atoms */
5797
            FORLIM1 = atom[i].neighbor_count;
5798
            for (j = 0; j < FORLIM1; j++) {
6785 bpr 5799
              if (is_oxo_C (nb[j]) || is_thioxo_C (nb[j]))
14179 bpr 5800
          acyl_count++;
6785 bpr 5801
              if (!strcmp (atom[nb[j] - 1].element, "C "))
14179 bpr 5802
                      C_count++;
6785 bpr 5803
              if (!strcmp (atom[nb[j] - 1].element, "O "))
14179 bpr 5804
                      O_count++;
6785 bpr 5805
              b_id = get_bond (i + 1, nb[j]);
14179 bpr 5806
              if (b_id > 0) {
5807
                      if (bond[b_id - 1].btype == 'S')
5808
                        single_count++;
6785 bpr 5809
                      if (bond[b_id - 1].btype == 'D')
14179 bpr 5810
                        double_count++;
5811
                      if (bond[b_id - 1].btype == 'T')
5812
                        triple_count++;
5813
                      if (bond[b_id - 1].btype == 'A'){
5814
                        /* v0.3n: special treatment for acyclic bonds */
5815
                           /* flagged as "aromatic" (in query structures) */
5816
                        if (bond[b_id - 1].ring_count > 0)
5817
                                arom_count++;
5818
                        else
5819
                                double_count++;
5820
                      }
5821
                      if ((!strcmp (atom[i].element, "N ") &&
5822
                          !strcmp (atom[nb[j] - 1].element, "O ")) ||
5823
                          (!strcmp (atom[i].element, "O ") &&
5824
                        !strcmp (atom[nb[j] - 1].element, "N "))) {
5825
                        /* check if it is an N-oxide drawn with a double bond ==> should be N3 */
5826
                        if (bond[b_id - 1].btype == 'D')
5827
                                NdO_count++;
5828
                     }
5829
                    if ((!strcmp (atom[i].element, "N ") &&
5830
                         !strcmp (atom[nb[j] - 1].element, "C ")) ||
5831
                        (!strcmp (atom[i].element, "C ") &&
5832
                         !strcmp (atom[nb[j] - 1].element, "N "))) {
6785 bpr 5833
                      if (bond[b_id - 1].btype == 'D')
14179 bpr 5834
                              NdC_count++;
6785 bpr 5835
                    }
14179 bpr 5836
                  }
5837
          }
6785 bpr 5838
          total_bonds = single_count + double_count * 2 + triple_count * 3 +
5839
            (int) (1.5 * arom_count);
5840
          /* calculate number of total hydrogens per atom */
5841
          /*Htotal := nvalences(atom^[i].element) - total_bonds + atom^[i].formal_charge; */
5842
          Htotal = atom[i].nvalences - total_bonds + atom[i].formal_charge;
5843
          if (Htotal < 0)       /* e.g., N in nitro group */
5844
            Htotal = 0;
5845
          atom[i].Htot = Htotal;
5846
          /* refine atom types, based on bond types */
14179 bpr 5847
          if (!strcmp (atom[i].element, "C ")) {
5848
            if (arom_count > 1)
5849
                    strcpy (atom[i].atype, "CAR");
5850
      if (triple_count == 1 || double_count == 2)
5851
                    strcpy (atom[i].atype, "C1 ");
5852
            if (double_count == 1)
5853
                    strcpy (atom[i].atype, "C2 ");
5854
            if (triple_count == 0 && double_count == 0 && arom_count < 2)
5855
                    strcpy (atom[i].atype, "C3 ");
5856
          }
5857
          if (!strcmp (atom[i].element, "O ")) {
5858
            if (double_count == 1)
5859
                    strcpy (atom[i].atype, "O2 ");
5860
            if (double_count == 0)
5861
                    strcpy (atom[i].atype, "O3 ");
5862
          }
5863
          if (!strcmp (atom[i].element, "N ")) {
5864
            if (total_bonds > 3) {
5865
                    if (O_count == 0) {
6785 bpr 5866
                      if (single_count > 3 ||
14179 bpr 5867
                                (single_count == 2 && double_count == 1 && C_count >= 2))
5868
                              atom[i].formal_charge = 1;
6785 bpr 5869
                    }
14179 bpr 5870
                    else {
6785 bpr 5871
                      if (O_count == 1 && atom[i].formal_charge == 0)   /* v0.3m */
14179 bpr 5872
                              strcpy (atom[i].atype, "N3 ");
5873
                      if (O_count == 2 && atom[i].formal_charge == 0) {
5874
                              if (atom[i].neighbor_count > 2)   /* nitro v0.3o */
5875
                                strcpy (atom[i].atype, "N2 ");
5876
                              if (atom[i].neighbor_count == 2)  /* NO2   v0.3o */
5877
                                strcpy (atom[i].atype, "N1 ");
5878
                            }
6785 bpr 5879
                      /* the rest is left empty, so far.... */
5880
                    }
14179 bpr 5881
                  }
5882
            /* could be an N-oxide -> should be found elsewhere  */
5883
            if (triple_count == 1 || (double_count == 2 && atom[i].neighbor_count == 2))
5884
                    /* v0.3n */
5885
                    strcpy (atom[i].atype, "N1 ");
5886
              if (double_count == 1) {
5887
                      /*if NdC_count > 0 then atom^[i].atype := 'N2 '; */
5888
                      if (NdC_count == 0 && NdO_count > 0 && C_count >= 2)
5889
                        strcpy (atom[i].atype, "N3 ");
5890
                      /* N-oxide is N3 except in hetarene etc. */
5891
                      else
5892
                        strcpy (atom[i].atype, "N2 ");
5893
                    }
6785 bpr 5894
              /* fallback, added in v0.3g  */
5895
              if (arom_count > 1 || atom[i].arom == true)       /* v0.3n */
14179 bpr 5896
                      strcpy (atom[i].atype, "NAR");
5897
              if (triple_count == 0 && double_count == 0) {
5898
                      if (atom[i].formal_charge == 0) {
5899
                        if (acyl_count == 0)
5900
                                strcpy (atom[i].atype, "N3 ");
5901
                        if (acyl_count > 0)
5902
                                strcpy (atom[i].atype, "NAM");
5903
                      }
5904
                      if (atom[i].formal_charge == 1)
5905
                        strcpy (atom[i].atype, "N3+");
5906
                      }
5907
              }
5908
              if (!strcmp (atom[i].element, "P ")) {
5909
                if (single_count > 4)
5910
                        strcpy (atom[i].atype, "P4 ");
5911
                if (single_count <= 4 && double_count == 0)
5912
                        strcpy (atom[i].atype, "P3 ");
5913
                if (double_count == 2)
5914
                        strcpy (atom[i].atype, "P3D");
5915
             }
5916
            if (!strcmp (atom[i].element, "S ")) {
6785 bpr 5917
              if (double_count == 1 && single_count == 0)
14179 bpr 5918
                      strcpy (atom[i].atype, "S2 ");
6785 bpr 5919
              if (double_count == 0)
14179 bpr 5920
                      strcpy (atom[i].atype, "S3 ");
6785 bpr 5921
              if (double_count == 1 && single_count > 0)
14179 bpr 5922
                      strcpy (atom[i].atype, "SO ");
6785 bpr 5923
              if (double_count == 2 && single_count > 0)
14179 bpr 5924
                      strcpy (atom[i].atype, "SO2");
6785 bpr 5925
            }
5926
          /* further atom types should go here */
14179 bpr 5927
          }
5928
  }
6785 bpr 5929
}
5930
 
14179 bpr 5931
static void chk_arom ()
6785 bpr 5932
{
5933
  int i, j, pi_count, ring_size, b, a1, a2;     /* v0.3n */
5934
  ringpath_type testring;
5935
  int a_ref, a_prev, a_next, b_bk, b_fw, b_exo;
5936
  char bt_bk, bt_fw;
5937
  boolean ar_bk, ar_fw, ar_exo; /* new in v0.3 */
5938
  boolean conj_intr, ko, aromatic, aromatic_bt; /* v0.3n */
5939
  int n_db, n_sb, n_ar;
5940
  boolean cumul;
5941
  int exo_mC;                   /* v0.3j */
5942
  int arom_pi_diff;             /* v0.3j */
5943
  int FORLIM;
5944
 
5945
  if (n_rings < 1)
5946
    return;
5947
  FORLIM = n_rings;
5948
  /* first, do a very quick check for benzene, pyridine, etc. */
14179 bpr 5949
  for (i = 0; i < FORLIM; i++) {
5950
    ring_size = ringprop[i].size;
5951
    if (ring_size == 6) {
5952
            memset (testring, 0, sizeof (ringpath_type));
5953
            for (j = 0; j < ring_size; j++)
5954
              testring[j] = ring[i][j];
5955
            cumul = false;
5956
            n_sb = 0;
5957
            n_db = 0;
5958
            n_ar = 0;
5959
            a_prev = testring[ring_size - 1];
5960
            for (j = 1; j <= ring_size; j++) {
6785 bpr 5961
              a_ref = testring[j - 1];
5962
              if (j < ring_size)
14179 bpr 5963
               a_next = testring[j];
6785 bpr 5964
              else
14179 bpr 5965
               a_next = testring[0];
6785 bpr 5966
              b_bk = get_bond (a_prev, a_ref);
5967
              b_fw = get_bond (a_ref, a_next);
5968
              bt_bk = bond[b_bk - 1].btype;
5969
              bt_fw = bond[b_fw - 1].btype;
5970
              if (bt_fw == 'S')
14179 bpr 5971
                n_sb++;
6785 bpr 5972
              if (bt_fw == 'D')
14179 bpr 5973
                n_db++;
6785 bpr 5974
              if (bt_fw == 'A')
14179 bpr 5975
                      n_ar++;
6785 bpr 5976
              if (bt_fw != 'A' && bt_bk == bt_fw)
14179 bpr 5977
                      cumul = true;
6785 bpr 5978
              a_prev = a_ref;
5979
            }
14179 bpr 5980
            if (n_ar == 6 || (n_sb == 3 && n_db == 3 && cumul == false)) {
5981
              /* this ring is aromatic */
6785 bpr 5982
              a_prev = testring[ring_size - 1];
14179 bpr 5983
              for (j = 0; j < ring_size; j++) {
5984
                      a_ref = testring[j];
5985
                      b_bk = get_bond (a_prev, a_ref);
5986
                      bond[b_bk - 1].arom = true;
5987
                      a_prev = a_ref;
5988
                    }
6785 bpr 5989
              ringprop[i].arom = true;
5990
            }
14179 bpr 5991
          }
5992
  }
6785 bpr 5993
  FORLIM = n_rings;
14179 bpr 5994
  for (i = 1; i <= FORLIM; i++) {
5995
    if (ringprop[i - 1].arom == false) {
5996
            /* do the hard work only for those rings which are not yet flagged aromatic */
5997
            memset (testring, 0, sizeof (ringpath_type));
5998
            ring_size = ringprop[i - 1].size;   /* v0.3j */
5999
            for (j = 0; j < ring_size; j++)     /* v0.3j */
6000
              testring[j] = ring[i - 1][j];
6001
            pi_count = 0;
6002
            arom_pi_diff = 0;   /* v0.3j */
6003
      /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6004
            ko = false;
6005
            a_prev = testring[ring_size - 1];
6006
            for (j = 1; j <= ring_size; j++) {
6785 bpr 6007
              a_ref = testring[j - 1];
6008
              if (j < ring_size)
14179 bpr 6009
                a_next = testring[j];
6785 bpr 6010
              else
14179 bpr 6011
                a_next = testring[0];
6785 bpr 6012
              b_bk = get_bond (a_prev, a_ref);
6013
              b_fw = get_bond (a_ref, a_next);
6014
              bt_bk = bond[b_bk - 1].btype;
6015
              bt_fw = bond[b_fw - 1].btype;
6016
              ar_bk = bond[b_bk - 1].arom;
6017
              ar_fw = bond[b_fw - 1].arom;
14179 bpr 6018
              if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == false && ar_fw == false) {
6019
                /* first, assume the worst case (interrupted conjugation) */
6020
                conj_intr = true;
6021
                /* conjugation can be restored by hetero atoms */
6022
                if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6023
                    !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6024
                          !strcmp (atom[a_ref - 1].element, "N ") ||
6025
                          !strcmp (atom[a_ref - 1].element, "SE")) {
6026
                        conj_intr = false;
6027
                        pi_count += 2;  /* lone pair adds for 2 pi electrons */
6028
                      }
6029
                      /* conjugation can be restored by a formal charge at a methylene group */
6785 bpr 6030
                      if (!strcmp (atom[a_ref - 1].element, "C ") &&
14179 bpr 6031
                          atom[a_ref - 1].formal_charge != 0) {
6032
                          conj_intr = false;
6033
                          pi_count -= atom[a_ref - 1].formal_charge;
6034
                          /* neg. charge increases pi_count! */
6035
                      }
6036
                      /* conjugation can be restored by carbonyl groups etc. */
6037
                      if (is_oxo_C (a_ref) || is_thioxo_C (a_ref) |
6038
                          is_exocyclic_imino_C (a_ref, i))
6039
                        conj_intr = false;
6040
                      /* conjugation can be restored by exocyclic C=C double bond, */
6041
                      /* adds 2 pi electrons to 5-membered rings, not to 7-membered rings (CAUTION!) */
6042
                      /* apply only to non-aromatic exocyclic C=C bonds */
6785 bpr 6043
                      exo_mC = find_exocyclic_methylene_C (a_ref, i);   /* v0.3j */
14179 bpr 6044
                      if (exo_mC > 0 && (ring_size & 1)) {              /* v0.3j */
6045
                          b_exo = get_bond (a_ref, exo_mC);     /* v0.3j  */
6046
                          ar_exo = bond[b_exo - 1].arom;
6047
                        if (((ring_size - 1) & 3) == 0) {       /* 5-membered rings and related */
6048
                                conj_intr = false;
6049
                                pi_count += 2;
6050
                              }
6051
                        else {
6052
                                if (!ar_exo)
6053
                                  conj_intr = false;
6054
                              }
6055
                      }
6056
                      /* 7-membered rings and related */
6057
                      /* if conjugation is still interrupted ==> knock-out */
6058
                      if (conj_intr)
6059
                        ko = true;
6785 bpr 6060
                    }
14179 bpr 6061
              else {
6062
                      if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == true && ar_fw == true) {
6063
                        if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6064
                                  !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6065
                                  !strcmp (atom[a_ref - 1].element, "N ") ||
6066
                                  !strcmp (atom[a_ref - 1].element, "SE"))
6067
                                pi_count += 2;  /* lone pair adds for 2 pi electrons */
6068
                        if (!strcmp (atom[a_ref - 1].element, "C ") &&
6069
                                  atom[a_ref - 1].formal_charge != 0)
6070
                                pi_count -= atom[a_ref - 1].formal_charge;
6071
                          /* neg. charge increases pi_count! */
6072
                        exo_mC = find_exocyclic_methylene_C (a_ref, i); /* v0.3j */
6073
                        if (exo_mC > 0 && (ring_size & 1))  {   /* v0.3j */
6074
                                b_exo = get_bond (a_ref, exo_mC);       /* v0.3j */
6075
            /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6076
                                if (((ring_size - 1) & 3) == 0)
6077
                                  /* 5-membered rings and related */
6078
                                  pi_count += 2;
6079
                              }
6080
                      }
6081
                      else {
6082
                  pi_count++;   /* v0.3j; adjustment for bridgehead N: see below */
6083
                  if (bt_bk == 'S' && bt_fw == 'S' && ((ar_bk == true && ar_fw == false) ||
6084
                                  (ar_bk == false && ar_fw == true))) {
6085
                                /* v0.3j; if a bridgehead N were not aromatic, it could  */
6086
                                /* contribute 2 pi electrons --> try also this variant */
6087
                                /* (example: CAS 32278-54-9) */
6088
                                if (!strcmp (atom[a_ref - 1].element, "N ")) {
6089
                                  arom_pi_diff++;
6090
                                  /* any other case: increase pi count by one electron */
6091
                                }
6092
                              }
6093
                      }
6785 bpr 6094
                    }
14179 bpr 6095
        /* last command: */
6096
        a_prev = a_ref;
6785 bpr 6097
            }                   /* for j := 1 to ring_size */
14179 bpr 6098
            /* now we can draw our conclusion */
6099
            /*if not ((ko) or (odd(pi_count))) then */
6100
            if (!ko) {
6101
              /* v0.3j; odd pi_count might be compensated by arom_pi_diff */
6102
                          /* apply Hueckel's rule */
6785 bpr 6103
              if (labs (ring_size - pi_count) < 2 &&
14179 bpr 6104
                        (((pi_count - 2) & 3) == 0 || ((pi_count + arom_pi_diff - 2) & 3) == 0)) {
6105
                      /* this ring is aromatic */
6106
                      ringprop[i - 1].arom = true;
6107
                      /* now mark _all_ bonds in the ring as aromatic */
6108
                      a_prev = testring[ring_size - 1];
6109
                      for (j = 0; j < ring_size; j++) {
6110
                        a_ref = testring[j];
6111
                        bond[get_bond (a_prev, a_ref) - 1].arom = true;
6112
                        a_prev = a_ref;
6113
                      }
6785 bpr 6114
                    }
6115
            }
14179 bpr 6116
          }
6117
  }                             /* (for i := 1 to n_rings) */
6785 bpr 6118
  FORLIM = n_bonds;
6119
  /* finally, mark all involved atoms as aromatic */
14179 bpr 6120
  for (i = 0; i < FORLIM; i++) {
6121
    if (bond[i].arom) {
6122
            a1 = bond[i].a1;    /* v0.3n */
6123
            a2 = bond[i].a2;    /* v0.3n */
6124
            atom[a1 - 1].arom = true;
6125
            atom[a2 - 1].arom = true;
6126
            /* v0.3n: update atom types if applicable (C and N) */
6127
            if (!strcmp (atom[a1 - 1].element, "C "))
6128
              strcpy (atom[a1 - 1].atype, "CAR");
6129
            if (!strcmp (atom[a2 - 1].element, "C "))
6130
              strcpy (atom[a2 - 1].atype, "CAR");
6131
            if (!strcmp (atom[a1 - 1].element, "N "))
6132
              strcpy (atom[a1 - 1].atype, "NAR");
6133
            if (!strcmp (atom[a2 - 1].element, "N "))
6134
              strcpy (atom[a2 - 1].atype, "NAR");
6135
          }
6136
  }
6785 bpr 6137
  FORLIM = n_rings;
6138
  /* update aromaticity information in ringprop */
6139
  /* new in v0.3n: accept rings as aromatic if all bonds are of type 'A' */
14179 bpr 6140
  for (i = 0; i < FORLIM; i++) {
6141
    memcpy (testring, ring[i], sizeof (ringpath_type));
6142
    /*ring_size := path_length(testring); */
6143
    ring_size = ringprop[i].size;       /* v0.3j */
6144
    aromatic = true;
6145
    aromatic_bt = true; /* v0.3n */
6146
    a_prev = testring[ring_size - 1];
6147
    for (j = 0; j < ring_size; j++) {
6148
            a_ref = testring[j];
6149
            b = get_bond (a_prev, a_ref);       /* v0.3n */
6150
            if (!bond[b - 1].arom)
6151
              aromatic = false;
6152
            if (bond[b - 1].btype != 'A')       /* v0.3n */
6153
              aromatic_bt = false;
6154
            a_prev = a_ref;
6155
          }
6156
    if (aromatic_bt && !aromatic) {                     /* v0.3n: update aromaticity flag */
6157
            a_prev = testring[ring_size - 1];
6158
            for (j = 0; j < ring_size; j++) {
6785 bpr 6159
              a_ref = testring[j];
6160
              b = get_bond (a_prev, a_ref);
6161
              bond[b - 1].arom = true;
6162
              if (!strcmp (atom[a_ref - 1].element, "C "))
14179 bpr 6163
                      strcpy (atom[a_ref - 1].atype, "CAR");
6785 bpr 6164
              if (!strcmp (atom[a_ref - 1].element, "N "))
14179 bpr 6165
                      strcpy (atom[a_ref - 1].atype, "NAR");
6785 bpr 6166
              a_prev = a_ref;
6167
            }
14179 bpr 6168
            aromatic = true;
6169
          }                     /* end v0.3n block   */
6170
    if (aromatic)
6171
            ringprop[i].arom = true;
6172
    else
6173
            ringprop[i].arom = false;
6174
  }
6785 bpr 6175
}
6176
 
14179 bpr 6177
static void write_mol ()
6785 bpr 6178
{
6179
  int i, j;
6180
  ringpath_type testring;
6181
  int ring_size, FORLIM;
6182
 
6183
  /*aromatic : boolean; */
6184
  /*a_prev, a_ref : integer; */
6185
  if (progmode == pmCheckMol)
6186
    printf ("Molecule name: %s\n", molname);
6187
  else
6188
    printf ("Molecule name (haystack): %s\n", molname);
6189
  printf ("atoms: %d  bonds: %d  rings: %d\n", n_atoms, n_bonds, n_rings);
6190
  if (n_atoms < 1)
6191
    return;
6192
  if (n_bonds < 1)
6193
    return;
6194
  FORLIM = n_atoms;
14179 bpr 6195
  for (i = 1; i <= FORLIM; i++) {
6196
    if (i < 10) putchar (' ');
6197
    if (i < 100) putchar (' ');
6198
    if (i < 1000) putchar (' ');
6199
    printf ("%d %s %s %f %f ",
6785 bpr 6200
              i, atom[i - 1].element, atom[i - 1].atype, atom[i - 1].x,
6201
              atom[i - 1].y);
14179 bpr 6202
    printf ("%f", atom[i - 1].z);
6203
    printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6204
            atom[i - 1].neighbor_count, atom[i - 1].Hexp, atom[i - 1].Htot);
6205
    if (atom[i - 1].formal_charge != 0)
6206
            printf ("  charge: %d", atom[i - 1].formal_charge);
6207
    putchar ('\n');
6208
  }
6785 bpr 6209
  FORLIM = n_bonds;
14179 bpr 6210
  for (i = 1; i <= FORLIM; i++) {
6211
    if (i < 10) putchar (' ');
6212
    if (i < 100) putchar (' ');
6213
    if (i < 1000) putchar (' ');
6214
    printf ("%d %d %d %c", i, bond[i - 1].a1, bond[i - 1].a2, bond[i - 1].btype);
6215
    if (bond[i - 1].ring_count > 0)
6216
            printf (", contained in %d ring(s)", bond[i - 1].ring_count);
6217
    if (bond[i - 1].arom) printf (" (aromatic) ");
6218
    putchar ('\n');
6219
  }
6785 bpr 6220
  if (n_rings <= 0)
6221
    return;
6222
  FORLIM = n_rings;
14179 bpr 6223
  for (i = 0; i < FORLIM; i++) {
6224
    printf ("ring %d: ", i + 1);
6225
    /*aromatic := true; */
6226
    memset (testring, 0, sizeof (ringpath_type));
6227
    ring_size = ringprop[i].size;       /* v0.3j */
6228
    /*for j := 1 to max_ringsize do if ring^[i,j] > 0 then testring[j] := ring^[i,j]; */
6229
    for (j = 0; j < ring_size; j++)     /* v0.3j */
6230
            testring[j] = ring[i][j];
6231
    /*ring_size := path_length(testring); */
6232
    /*a_prev := testring[ring_size]; */
6233
    for (j = 0; j < ring_size; j++) {
6234
            printf ("%d ", testring[j]);
6235
            /*a_ref := testring[j]; */
6236
            /*if (not bond^[get_bond(a_prev,a_ref)].arom) then aromatic := false; */
6237
            /*a_prev := a_ref; */
6238
          }
6239
    /*if aromatic then write(' (aromatic)'); */
6240
    if (ringprop[i].arom) printf (" (aromatic)");
6241
    if (ringprop[i].envelope) printf (" (env)");
6242
    putchar ('\n');
6243
  }
6785 bpr 6244
}
6245
 
14179 bpr 6246
static void write_needle_mol ()
6785 bpr 6247
{
6248
  int i, j;
6249
  ringpath_type testring;
6250
  int ring_size;
6251
  boolean aromatic;
6252
  int a_prev, a_ref, FORLIM;
6253
 
6254
  printf ("Molecule name (needle): %s\n", ndl_molname);
6255
  printf ("atoms: %d  bonds: %d  rings: %d\n",
6256
          ndl_n_atoms, ndl_n_bonds, ndl_n_rings);
6257
  if (ndl_n_atoms < 1)
6258
    return;
6259
  if (ndl_n_bonds < 1)
6260
    return;
6261
  FORLIM = ndl_n_atoms;
14179 bpr 6262
  for (i = 1; i <= FORLIM; i++) {
6263
    if (i < 10) putchar (' ');
6264
    if (i < 100) putchar (' ');
6265
    if (i < 1000) putchar (' ');
6266
    printf ("%d %s %s %f %f ",
6785 bpr 6267
              i, ndl_atom[i - 1].element, ndl_atom[i - 1].atype,
6268
              ndl_atom[i - 1].x, atom[i - 1].y);
14179 bpr 6269
    printf ("%f", ndl_atom[i - 1].z);
6270
    printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6271
            ndl_atom[i - 1].neighbor_count, ndl_atom[i - 1].Hexp,
6272
            ndl_atom[i - 1].Htot);
6273
    if (ndl_atom[i - 1].formal_charge != 0)
6274
            printf ("  charge: %d", ndl_atom[i - 1].formal_charge);
6275
    putchar ('\n');
6276
  }
6785 bpr 6277
  FORLIM = ndl_n_bonds;
14179 bpr 6278
  for (i = 1; i <= FORLIM; i++) {
6279
    if (i < 10) putchar (' ');
6280
    if (i < 100) putchar (' ');
6281
    if (i < 1000) putchar (' ');
6282
    printf ("%d %d %d %c", i, ndl_bond[i - 1].a1, ndl_bond[i - 1].a2,
6785 bpr 6283
              ndl_bond[i - 1].btype);
14179 bpr 6284
    if (ndl_bond[i - 1].ring_count > 0)
6285
            printf (", contained in %d ring(s)", ndl_bond[i - 1].ring_count);
6286
    if (ndl_bond[i - 1].arom)
6287
            printf (" (aromatic) ");
6288
    putchar ('\n');
6289
  }
6785 bpr 6290
  if (ndl_n_rings <= 0)
6291
    return;
6292
  FORLIM = ndl_n_rings;
14179 bpr 6293
  for (i = 0; i < FORLIM; i++) {
6294
    aromatic = true;
6295
    memset (testring, 0, sizeof (ringpath_type));
6296
    for (j = 0; j < max_ringsize; j++) {
6297
            if (ndl_ring[i][j] > 0)
6298
              testring[j] = ndl_ring[i][j];
6299
          }
6300
    ring_size = path_length (testring);
6301
    printf ("ring %d: ", i + 1);
6302
    a_prev = testring[ring_size - 1];
6303
    for (j = 0; j < ring_size; j++) {
6304
            printf ("%d ", testring[j]);
6305
            a_ref = testring[j];
6306
            if (!ndl_bond[get_ndl_bond (a_prev, a_ref) - 1].arom)       /* v0.3k */
6307
              aromatic = false;
6308
            a_prev = a_ref;
6309
          }
6310
    if (aromatic) printf (" (aromatic)");
6311
    putchar ('\n');
6312
  }
6785 bpr 6313
}
6314
 
14179 bpr 6315
static void chk_so2_deriv (a_ref)
6785 bpr 6316
     int a_ref;
6317
{
6318
  int i;
6319
  neighbor_rec nb;
6320
  str2 nb_el;
6321
  int het_count = 0, o_count = 0, or_count = 0, hal_count = 0, n_count = 0,
6322
    c_count = 0;
6323
  int FORLIM;
6324
 
6325
  memset (nb, 0, sizeof (neighbor_rec));
6326
  if (strcmp (atom[a_ref - 1].atype, "SO2"))
6327
    return;
6328
  get_neighbors (nb, a_ref);
6329
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6330
  for (i = 0; i < FORLIM; i++) {
6331
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6332
            strcpy (nb_el, atom[nb[i] - 1].element);
6333
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6334
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
6335
                && strcmp (nb_el, "LP"))
6336
              /* added 'D ' in v0.3n */
6337
              het_count++;
6338
            if (!strcmp (nb_el, "O ")) {
6785 bpr 6339
              o_count++;
6340
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
14179 bpr 6341
                      or_count++;
6785 bpr 6342
            }
14179 bpr 6343
            if (!strcmp (nb_el, "N "))
6344
              n_count++;
6345
            if (!strcmp (nb_el, "C "))
6346
              c_count++;
6347
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6348
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6349
                || !strcmp (nb_el, "AT"))
6350
              hal_count++;
6351
          }
6352
  }
6353
  if (het_count == 2) {                                 /* sulfuric acid derivative */
6354
    fg[fg_sulfuric_acid_deriv - 1] = true;
6355
    if (o_count == 2) {
6356
            if (or_count == 0)
6357
              fg[fg_sulfuric_acid - 1] = true;
6358
            if (or_count == 1)
6359
              fg[fg_sulfuric_acid_monoester - 1] = true;
6360
            if (or_count == 2)
6361
              fg[fg_sulfuric_acid_diester - 1] = true;
6362
          }
6363
    if (o_count == 1) {
6364
            if (or_count == 1 && n_count == 1)
6365
              fg[fg_sulfuric_acid_amide_ester - 1] = true;
6366
            if (or_count == 0 && n_count == 1)
6367
              fg[fg_sulfuric_acid_amide - 1] = true;
6368
          }
6369
    if (n_count == 2)
6370
            fg[fg_sulfuric_acid_diamide - 1] = true;
6371
    if (hal_count > 0)
6372
            fg[fg_sulfuryl_halide - 1] = true;
6373
  }
6374
  if (het_count == 1 && c_count == 1) {                                 /* sulfonic acid derivative */
6375
    fg[fg_sulfonic_acid_deriv - 1] = true;
6376
    if (o_count == 1 && or_count == 0)
6377
            fg[fg_sulfonic_acid - 1] = true;
6378
    if (o_count == 1 && or_count == 1)
6379
            fg[fg_sulfonic_acid_ester - 1] = true;
6380
    if (n_count == 1)
6381
            fg[fg_sulfonamide - 1] = true;
6382
    if (hal_count == 1)
6383
            fg[fg_sulfonyl_halide - 1] = true;
6384
  }
6785 bpr 6385
  if (het_count == 0 && c_count == 2)   /* sulfone */
6386
    fg[fg_sulfone - 1] = true;
6387
}
6388
 
14179 bpr 6389
static void chk_p_deriv (a_ref)
6785 bpr 6390
     int a_ref;
6391
{
6392
  int i;
6393
  neighbor_rec nb;
6394
  str2 nb_el, dbl_het;
6395
  int het_count;
6396
  int oh_count = 0, or_count = 0, hal_count = 0, n_count = 0, c_count = 0;
6397
  int FORLIM;
6398
 
6399
  if (strcmp (atom[a_ref - 1].element, "P "))
6400
    return;
6401
  memset (nb, 0, sizeof (neighbor_rec));
6402
  get_neighbors (nb, a_ref);
6403
  *dbl_het = '\0';
14179 bpr 6404
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 6405
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6406
  for (i = 0; i < FORLIM; i++) {
6407
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
6408
            strcpy (dbl_het, atom[nb[i] - 1].element);
6409
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6410
            strcpy (nb_el, atom[nb[i] - 1].element);
6411
            if (!strcmp (nb_el, "C "))
6412
              c_count++;
6413
            if (is_hydroxy (a_ref, nb[i]))
6414
              oh_count++;
6415
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6416
              or_count++;
6417
            if (!strcmp (nb_el, "N "))
6418
              n_count++;
6419
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6420
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6421
                || !strcmp (nb_el, "AT"))
6422
              hal_count++;
6423
          }
6424
  }
6785 bpr 6425
  het_count = oh_count + or_count + hal_count + n_count;
6426
  if (!strcmp (atom[a_ref - 1].atype, "P3D") ||
14179 bpr 6427
      !strcmp (atom[a_ref - 1].atype, "P4 ")) {
6428
    if (!strcmp (dbl_het, "O ")) {
6429
            if (c_count == 0) {
6785 bpr 6430
              fg[fg_phosphoric_acid_deriv - 1] = true;
6431
              if (oh_count == 3)
14179 bpr 6432
                fg[fg_phosphoric_acid - 1] = true;
6785 bpr 6433
              if (or_count > 0)
14179 bpr 6434
                fg[fg_phosphoric_acid_ester - 1] = true;
6785 bpr 6435
              if (hal_count > 0)
14179 bpr 6436
                fg[fg_phosphoric_acid_halide - 1] = true;
6785 bpr 6437
              if (n_count > 0)
14179 bpr 6438
                fg[fg_phosphoric_acid_amide - 1] = true;
6785 bpr 6439
            }
14179 bpr 6440
            if (c_count == 1) {
6785 bpr 6441
              fg[fg_phosphonic_acid_deriv - 1] = true;
6442
              if (oh_count == 2)
14179 bpr 6443
                fg[fg_phosphonic_acid - 1] = true;
6785 bpr 6444
              if (or_count > 0)
14179 bpr 6445
                fg[fg_phosphonic_acid_ester - 1] = true;
6785 bpr 6446
              /*if (hal_count > 0)  then fg[fg_phosphonic_acid_halide] := true;             */
6447
              /*if (n_count > 0)    then fg[fg_phosphonic_acid_amide]  := true; */
6448
            }
14179 bpr 6449
            if (c_count == 3)
6450
              fg[fg_phosphinoxide - 1] = true;
6451
          }
6452
    if (!strcmp (dbl_het, "S ")) {
6453
      if (c_count == 0) {
6454
        fg[fg_thiophosphoric_acid_deriv - 1] = true;
6455
        if (oh_count == 3)
6456
            fg[fg_thiophosphoric_acid - 1] = true;
6457
        if (or_count > 0)
6458
            fg[fg_thiophosphoric_acid_ester - 1] = true;
6459
        if (hal_count > 0)
6460
            fg[fg_thiophosphoric_acid_halide - 1] = true;
6461
        if (n_count > 0)
6462
            fg[fg_thiophosphoric_acid_amide - 1] = true;
6463
      }
6785 bpr 6464
    }
14179 bpr 6465
  }
6785 bpr 6466
  /*  if (atom^[a_ref].atype = 'P4 ') then fg[fg_phosphoric_acid_deriv] := true; */
6467
  if (strcmp (atom[a_ref - 1].atype, "P3 "))    /* changed P3D into P3 in v0.3b */
6468
    return;
6469
  if (c_count == 3 && het_count == 0)
6470
    fg[fg_phosphine - 1] = true;
6471
  if (c_count == 3 && oh_count == 1)
6472
    fg[fg_phosphinoxide - 1] = true;
6473
}
6474
 
14179 bpr 6475
static void chk_b_deriv (a_ref)
6785 bpr 6476
     int a_ref;
6477
{
6478
  int i;
6479
  neighbor_rec nb;
6480
  str2 nb_el;
6481
  int het_count = 0, oh_count = 0, or_count = 0, hal_count = 0, n_count = 0,
6482
    c_count = 0;
6483
  int FORLIM;
6484
 
6485
  if (strcmp (atom[a_ref - 1].element, "B "))
6486
    return;
6487
  memset (nb, 0, sizeof (neighbor_rec));
6488
  get_neighbors (nb, a_ref);
6489
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6490
  for (i = 0; i < FORLIM; i++) {
6491
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6492
            strcpy (nb_el, atom[nb[i] - 1].element);
6493
            if (!strcmp (nb_el, "C "))
6494
              c_count++;
6495
            else
14249 bpr 6496
              if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP"))
14179 bpr 6497
                /* v0.3n: D */
14249 bpr 6498
                het_count++;
6499
            if (is_hydroxy (a_ref, nb[i]))
6500
              oh_count++;
6501
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6502
              /* fixed in v0.3b */
6503
              or_count++;
6504
            if (!strcmp (nb_el, "N "))
6505
              n_count++;
6506
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6507
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6508
                || !strcmp (nb_el, "AT"))
6509
              hal_count++;
14179 bpr 6510
          }
6511
  }
6785 bpr 6512
  het_count = oh_count + or_count + hal_count + n_count;
6513
  /* fixed in v0.3b */
6514
  if (c_count != 1 || het_count != 2)
6515
    return;
6516
  fg[fg_boronic_acid_deriv - 1] = true;
6517
  if (oh_count == 2)
6518
    fg[fg_boronic_acid - 1] = true;
6519
  if (or_count > 0)
6520
    fg[fg_boronic_acid_ester - 1] = true;
6521
}
6522
 
14179 bpr 6523
static void chk_ammon (a_ref)
6785 bpr 6524
     int a_ref;
6525
{
6526
  int i;
6527
  neighbor_rec nb;
6528
  str2 nb_el;
6529
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
6530
  char bt;                      /* v0.3k */
6531
  float bo_sum = 0.0;
6532
  boolean ha;
6533
  int FORLIM;
6534
 
6535
  memset (nb, 0, sizeof (neighbor_rec));
6536
  if (strcmp (atom[a_ref - 1].atype, "N3+")
6537
      && atom[a_ref - 1].formal_charge == 0)
6538
    return;
6539
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
6540
    return;
6541
  get_neighbors (nb, a_ref);
6542
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6543
  for (i = 0; i < FORLIM; i++) {
6544
    bt = bond[get_bond (a_ref, nb[i]) - 1].btype;       /* v0.3k */
6545
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
6546
    ha = atom[nb[i] - 1].heavy; /* v0.3k */
6547
    if (bt == 'S') {
6548
            if (ha)
6549
              bo_sum += 1.0;
6550
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6551
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")) {
6552
                /* added 'D ' in v0.3n */
6785 bpr 6553
              het_count++;
14179 bpr 6554
              if (!strcmp (nb_el, "O ")) {
6555
                      o_count++;
6556
                      if (atom[nb[i] - 1].neighbor_count > 1)
6557
                        or_count++;
6558
                    }
6785 bpr 6559
            }
14179 bpr 6560
            if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
6561
                is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
6562
              /* v0.3k */
6563
              r_count++;
6564
          }
6565
    if (bt == 'D') {
6566
            if (ha)
6567
              bo_sum += 2.0;
6568
            if (strcmp (nb_el, "C ")) {
6785 bpr 6569
              het_count += 2;
6570
              if (!strcmp (nb_el, "O "))
14179 bpr 6571
                      o_count += 2;
6785 bpr 6572
            }
14179 bpr 6573
            if (!strcmp (nb_el, "C "))
6574
              r_count++;
6575
          }
6576
    if (bt == 'A' && ha)
6577
            bo_sum += 1.5;
6578
  }                             /* v0.3k: corrected end of "for ..." loop */
6785 bpr 6579
  if (het_count == 0 && r_count == 4)
6580
    fg[fg_quart_ammonium - 1] = true;
6581
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
6582
    return;
6583
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
6584
    fg[fg_n_oxide - 1] = true;  /* finds only aliphatic N-oxides! */
6585
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
6586
      atom[a_ref - 1].arom == true)
6587
    fg[fg_quart_ammonium - 1] = true;
6588
}
6589
 
14179 bpr 6590
static void swap_atoms (a1, a2)
6785 bpr 6591
     int *a1, *a2;
6592
{
6593
  int a_tmp;
6594
 
6595
  a_tmp = *a1;
6596
  *a1 = *a2;
6597
  *a2 = a_tmp;
6598
}
6599
 
14179 bpr 6600
static void orient_bond (a1, a2)
6785 bpr 6601
     int *a1, *a2;
6602
{
6603
  str2 a1_el, a2_el;
6604
 
6605
  strcpy (a1_el, atom[*a1 - 1].element);
6606
  strcpy (a2_el, atom[*a2 - 1].element);
6607
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
6608
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
6609
    /* v0.3n: D */
6610
    return;
6611
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
6612
    swap_atoms (a1, a2);
14179 bpr 6613
  if (!strcmp (a2_el, a1_el)) {
6614
    if (hetbond_count (*a1) > hetbond_count (*a2))
6785 bpr 6615
            swap_atoms (a1, a2);
14179 bpr 6616
  }
6617
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el)) {
6618
    if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O ")) {
6619
            if (!strcmp (a1_el, "O "))
6620
              swap_atoms (a1, a2);
6621
          }
6622
  }
6623
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el)) {
6785 bpr 6624
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
14179 bpr 6625
              atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
6626
          swap_atoms (a1, a2);
6627
  }
6785 bpr 6628
}
6629
 
14179 bpr 6630
static void chk_imine (a_ref, a_view)
6785 bpr 6631
     int a_ref, a_view;
6632
{
6633
  /* a_ref = C, a_view = N */
6634
  int i;
6635
  neighbor_rec nb;
6636
  str2 nb_el;
6788 kbelabas 6637
  int a_het = 0, a_c;
6785 bpr 6638
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
6639
  int FORLIM;
6640
 
6641
  /* v0.3k */
14179 bpr 6642
  if (atom[a_view - 1].neighbor_count == 1) {
6785 bpr 6643
      if (atom[a_ref - 1].arom == false)
6644
        fg[fg_imine - 1] = true;
6645
      return;
6646
    }
6647
  memset (nb, 0, sizeof (neighbor_rec));
6648
  get_neighbors (nb, a_view);
6649
  if (atom[a_view - 1].neighbor_count <= 1)
6650
    return;
6651
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6652
  for (i = 0; i < FORLIM; i++) {
6653
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')){
6654
            strcpy (nb_el, atom[nb[i] - 1].element);
6655
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6656
              a_c = nb[i];
6657
              c_count++;
6658
            }
14179 bpr 6659
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")) {
6785 bpr 6660
              a_het = nb[i];
6661
              het_count++;
6662
            }
14179 bpr 6663
            if ((!strcmp (nb_el, "O ")
6785 bpr 6664
               && atom[nb[i] - 1].neighbor_count ==
6665
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
14179 bpr 6666
              /* v0.3k */
6667
              o_count++;
6668
          }
6669
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')){
6670
      /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
6671
            strcpy (nb_el, atom[nb[i] - 1].element);
6672
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ") || !strcmp (nb_el, "S ")) {
6785 bpr 6673
              a_het = nb[i];    /* v0.3m */
6674
              het_count++;
6675
            }
14179 bpr 6676
            if ((!strcmp (nb_el, "O ")
6677
                && atom[nb[i] - 1].neighbor_count == 1) &&
6678
                  (bond[get_bond (a_view, nb[i]) - 1].arom == false))
6679
              /* v0.3k */
6680
              o_count++;
6681
          }
6682
  }
6683
  if (c_count == 1) {
6684
    if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
6685
              is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
6686
              && atom[a_ref - 1].arom == false && het_count == 0)
6785 bpr 6687
            /* v0.3k */
14179 bpr 6688
            fg[fg_imine - 1] = true;
6689
  }
6690
  if (het_count == 1) {
6691
    strcpy (nb_el, atom[a_het - 1].element);
6692
    if (!strcmp (nb_el, "O ")) {
6693
            if (is_hydroxy (a_view, a_het))
6694
              fg[fg_oxime - 1] = true;
6785 bpr 6695
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
6696
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
6697
            fg[fg_oxime_ether - 1] = true;
14179 bpr 6698
          }
6699
    if (!strcmp (nb_el, "N ")) {
6700
            if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
6701
                is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,a_het) |
6702
                is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
6703
              fg[fg_hydrazone - 1] = true;
6704
            else {
6785 bpr 6705
              memset (nb, 0, sizeof (neighbor_rec));
6706
              get_neighbors (nb, a_het);
14179 bpr 6707
              if (atom[a_het - 1].neighbor_count > 1) {
6708
                      FORLIM = atom[a_het - 1].neighbor_count;
6709
                      for (i = 0; i < FORLIM; i++) {
6710
                        if (nb[i] != a_view) {
6711
                                if (is_carbamoyl (a_het, nb[i]))
6712
                                  fg[fg_semicarbazone - 1] = true;
6713
                                if (is_thiocarbamoyl (a_het, nb[i]))
6714
                                  fg[fg_thiosemicarbazone - 1] = true;
6715
                              }
6716
                      }
6785 bpr 6717
                    }
6718
            }
14179 bpr 6719
          }
6720
  }                             /* v0.3k: nitro groups in "azi" form */
6785 bpr 6721
  /* check for semicarbazone or thiosemicarbazone */
6722
  if (het_count == 2 && o_count == 2)
6723
    fg[fg_nitro_compound - 1] = true;
6724
}
6725
 
14179 bpr 6726
static void chk_carbonyl_deriv (a_view, a_ref)
6785 bpr 6727
     int a_view, a_ref;
6728
{
6729
  /* a_view = C */
6730
  int i;
6731
  neighbor_rec nb;
6732
  str2 nb_el;
6733
  int c_count = 0, cn_count = 0;
6734
  char bt;                      /* new in v0.3b */
6735
  int n_db = 0;                 /* new in v0.3b */
6736
  int FORLIM;
6737
 
6738
  memset (nb, 0, sizeof (neighbor_rec));
6739
  get_neighbors (nb, a_view);
6740
  FORLIM = atom[a_view - 1].neighbor_count;
6741
  /* new in v0.3b */
14179 bpr 6742
  for (i = 0; i < FORLIM; i++) {
6743
    bt = bond[get_bond (a_view, nb[i]) - 1].btype;
6744
    if (bt == 'S') {
6745
            strcpy (nb_el, atom[nb[i] - 1].element);
6746
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6747
              if (is_cyano_c (nb[i]))
14179 bpr 6748
                      cn_count++;
6785 bpr 6749
              else
14179 bpr 6750
                      c_count++;
6785 bpr 6751
            }
14179 bpr 6752
          }
6753
    else {
6754
            if (bt == 'D')
6755
              n_db++;
6756
          }
6757
  }
6785 bpr 6758
  /* new in v0.3b */
14179 bpr 6759
  if (is_oxo_C (a_view)) {
6760
    fg[fg_carbonyl - 1] = true;
6761
    if (c_count + cn_count < 2) {                       /* new in v0.3b (detection of ketenes) */
6762
            if (n_db <= 1)
6763
              fg[fg_aldehyde - 1] = true;
6764
            else
6765
              fg[fg_ketene - 1] = true;
6766
          }
6767
    if (c_count == 2) {
6768
            if (atom[a_view - 1].arom)
6769
              fg[fg_oxohetarene - 1] = true;
6770
            else
6771
              fg[fg_ketone - 1] = true;
6772
          }
6773
    if (cn_count > 0)
6774
            fg[fg_acyl_cyanide - 1] = true;
6775
  }
6776
  if (is_thioxo_C (a_view)) {
6777
    fg[fg_thiocarbonyl - 1] = true;
6778
    if (c_count < 2)
6779
            fg[fg_thioaldehyde - 1] = true;
6780
    if (c_count == 2) {
6781
            if (atom[a_view - 1].arom)
6782
              fg[fg_thioxohetarene - 1] = true;
6783
            else
6784
              fg[fg_thioketone - 1] = true;
6785
          }
6786
  }
6785 bpr 6787
  if (is_imino_C (a_view))
6788
    chk_imine (a_view, a_ref);
6789
}
6790
 
14179 bpr 6791
static void chk_carboxyl_deriv (a_view, a_ref)
6785 bpr 6792
     int a_view, a_ref;
6793
{
6794
  int i;
6795
  neighbor_rec nb;
6796
  str2 nb_el;
6797
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 6798
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 6799
 
6800
  memset (nb, 0, sizeof (neighbor_rec));
6801
  get_neighbors (nb, a_view);
6802
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6803
  for (i = 0; i < FORLIM; i++) {
6804
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
6805
            strcpy (nb_el, atom[nb[i] - 1].element);
6806
            if (strcmp (nb_el, "C ")) {
6807
              if (!strcmp (nb_el, "O ")) {
6808
                      o_count++;
6809
                      a_o = nb[i];
6810
                    }
6811
              if (!strcmp (nb_el, "N ")) {
6812
                      n_count++;
6813
                      a_n = nb[i];
6814
                    }
6815
              if (!strcmp (nb_el, "S ")) {
6816
                      s_count++;
6817
                      a_s = nb[i];
6818
                    }
6785 bpr 6819
            }
14179 bpr 6820
          }
6821
  }
6822
  if (is_oxo_C (a_view)) {
6823
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
6824
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
6825
              fg[fg_carboxylic_acid_deriv - 1] = true;
6826
            if (is_hydroxy (a_view, a_o)) {
6785 bpr 6827
              if (atom[a_o - 1].formal_charge == 0)
14179 bpr 6828
                      fg[fg_carboxylic_acid - 1] = true;
6785 bpr 6829
              if (atom[a_o - 1].formal_charge == -1)
14179 bpr 6830
                      fg[fg_carboxylic_acid_salt - 1] = true;
6785 bpr 6831
            }
14179 bpr 6832
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
6833
                is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o)) {
6785 bpr 6834
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
14179 bpr 6835
                      fg[fg_carboxylic_acid_ester - 1] = true;
6836
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
6837
                      if (bond[get_bond (a_view, a_o) - 1].arom == true) {
6838
                        /*fg[fg_lactone_heteroarom] := true else fg[fg_lactone] := true; */
6839
                        fg[fg_oxohetarene - 1] = true;
6840
                      }
6841
                    else
6842
                      fg[fg_lactone - 1] = true;
6785 bpr 6843
                    }
6844
            }
14179 bpr 6845
          }
6846
    if (n_count == 1) {
6847
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6848
              fg[fg_carboxylic_acid_deriv - 1] = true;
6849
            else {
6785 bpr 6850
              /*fg[fg_lactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6851
              fg[fg_oxohetarene - 1] = true;
6852
            }
14179 bpr 6853
            if (is_amino (a_view, a_n) || (!strcmp (atom[a_n - 1].atype, "NAM")
6854
                      && atom[a_n - 1].neighbor_count == 1)) {
6785 bpr 6855
              fg[fg_carboxylic_acid_amide - 1] = true;
6856
              fg[fg_carboxylic_acid_prim_amide - 1] = true;
6857
            }
14179 bpr 6858
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6859
            if (is_C_monosubst_amino (a_view, a_n) &
6860
                (!is_subst_acylamino (a_view, a_n))) {                  /* v0.3j */
6785 bpr 6861
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6862
                      fg[fg_carboxylic_acid_amide - 1] = true;
6785 bpr 6863
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6864
                      fg[fg_carboxylic_acid_sec_amide - 1] = true;
6865
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6866
                      if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6867
                        /*fg[fg_lactam_heteroarom]    := true else  */
6868
                        fg[fg_oxohetarene - 1] = true;
6869
                      }
6870
                      else
6871
                        fg[fg_lactam - 1] = true;
6785 bpr 6872
                    }
6873
            }
14179 bpr 6874
            /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6875
            /*   (is_diarylamino(a_view,a_n)) then  */
6876
            if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6877
              /* v0.3j */
6785 bpr 6878
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6879
                fg[fg_carboxylic_acid_amide - 1] = true;
6785 bpr 6880
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6881
                fg[fg_carboxylic_acid_tert_amide - 1] = true;
6882
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6883
                if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6884
                        /*fg[fg_lactam_heteroarom]    := true else  */
6885
                        fg[fg_oxohetarene - 1] = true;
6886
                      }
6887
                      else
6888
                        fg[fg_lactam - 1] = true;
6785 bpr 6889
                    }
6890
            }
14179 bpr 6891
            if (is_hydroxylamino (a_view, a_n))
6892
              fg[fg_hydroxamic_acid - 1] = true;
6893
            if (is_hydrazino (a_view, a_n))
6894
              fg[fg_carboxylic_acid_hydrazide - 1] = true;
6895
            if (is_azido (a_view, a_n))
6896
              fg[fg_carboxylic_acid_azide - 1] = true;
6897
          }
6898
    if (s_count == 1) {                 /* anhydride is checked somewhere else */
6899
            if (bond[get_bond (a_view, a_s) - 1].arom == false)
6900
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6901
            if (is_sulfanyl (a_view, a_s))
6902
              fg[fg_thiocarboxylic_acid - 1] = true;
6903
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6785 bpr 6904
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 6905
                      fg[fg_thiocarboxylic_acid_ester - 1] = true;
6906
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
6907
                      if (bond[get_bond (a_view, a_s) - 1].arom == true) {
6908
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6909
                        fg[fg_oxohetarene - 1] = true;
6910
                      }
6911
                      else
6912
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6913
                    }
6914
            }
14179 bpr 6915
          }
6916
  }                             /* end Oxo-C */
6917
  if (is_thioxo_C (a_view)) {
6918
    /* fg[fg_thiocarboxylic_acid_deriv]  := true; */
6919
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
6920
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
6921
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6922
            if (is_hydroxy (a_view, a_o))
6923
              fg[fg_thiocarboxylic_acid - 1] = true;    /* fixed in v0.3c */
6924
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
6785 bpr 6925
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 6926
                      fg[fg_thiocarboxylic_acid_ester - 1] = true;
6927
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
6928
                      if (bond[get_bond (a_view, a_o) - 1].arom == true) {
6929
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6930
                        fg[fg_thioxohetarene - 1] = true;
6931
                      }
6932
                      else
6933
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6934
                    }
6935
            }
14179 bpr 6936
          }
6937
    if (n_count == 1) {
6938
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6939
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6940
            else {
6785 bpr 6941
              /*fg[fg_thiolactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6942
              fg[fg_thioxohetarene - 1] = true;
6943
            }
14179 bpr 6944
            /* catches also pyridazines, 1,2,3-triazines, etc. */
6945
            if (is_amino (a_view, a_n)){
6785 bpr 6946
              fg[fg_thiocarboxylic_acid_amide - 1] = true;
6947
              /* fg[fg_thiocarboxylic_acid_prim_amide] := true; */
6948
            }
14179 bpr 6949
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6950
            if (is_C_monosubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6951
              /* v0.3j */
6785 bpr 6952
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6953
                      fg[fg_thiocarboxylic_acid_amide - 1] = true;
6785 bpr 6954
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := true; */
14179 bpr 6955
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6956
                      if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6957
                        /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
6958
                        fg[fg_thioxohetarene - 1] = true;
6785 bpr 6959
                    }
14179 bpr 6960
                    else
6961
                      fg[fg_thiolactam - 1] = true;
6962
                  }
6963
          }
6785 bpr 6964
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6965
          /*   (is_diarylamino(a_view,a_n)) then  */
14179 bpr 6966
          if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6967
            /* v0.3j */
6968
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6969
                    fg[fg_thiocarboxylic_acid_amide - 1] = true;
6785 bpr 6970
              /*fg[fg_thiocarboxylic_acid_tert_amide] := true; */
14179 bpr 6971
            if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6972
                    if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6785 bpr 6973
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
6974
                      fg[fg_thioxohetarene - 1] = true;
6975
                    }
14179 bpr 6976
                    else
6977
                      fg[fg_thiolactam - 1] = true;
6978
                  }
6979
          }
6785 bpr 6980
        }
14179 bpr 6981
  if (s_count == 1) {                   /* anhydride is checked somewhere else */
6785 bpr 6982
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
6983
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6984
          if (is_sulfanyl (a_view, a_s))
6985
            fg[fg_thiocarboxylic_acid - 1] = true;
14179 bpr 6986
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6987
      if (bond[get_bond (a_view, a_s) - 1].arom == false)
6988
                    fg[fg_thiocarboxylic_acid_ester - 1] = true;
6989
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
6990
                      if (bond[get_bond (a_view, a_s) - 1].arom == true) {
6991
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6992
                        fg[fg_thioxohetarene - 1] = true;
6993
                      }
6994
                      else
6995
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6996
                    }
6997
            }
14179 bpr 6998
          }
6999
  }                             /* end Thioxo-C */
7000
  if (is_true_imino_C (a_view)) {
7001
    if (o_count == 1) {
7002
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
7003
              fg[fg_carboxylic_acid_deriv - 1] = true;
7004
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
6785 bpr 7005
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
14179 bpr 7006
                      fg[fg_imido_ester - 1] = true;
6785 bpr 7007
            }
14179 bpr 7008
          }
7009
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == false)) {
7010
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
7011
              fg[fg_carboxylic_acid_deriv - 1] = true;
7012
            if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n)) {
6785 bpr 7013
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 7014
                      fg[fg_carboxylic_acid_deriv - 1] = true;
6785 bpr 7015
              fg[fg_carboxylic_acid_amidine - 1] = true;
7016
            }
14179 bpr 7017
            if (is_hydrazino (a_view, a_n)) {
6785 bpr 7018
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 7019
                      fg[fg_carboxylic_acid_amidrazone - 1] = true;
6785 bpr 7020
            }
14179 bpr 7021
          }
7022
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == true))
7023
            /* catches also pyridazines, 1,2,3-triazines, etc. */
7024
          fg[fg_iminohetarene - 1] = true;
7025
    if (s_count == 1) {
7026
            if (bond[get_bond (a_view, a_s) - 1].arom == false)
7027
              fg[fg_carboxylic_acid_deriv - 1] = true;
7028
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6785 bpr 7029
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 7030
                 fg[fg_imido_thioester - 1] = true;
6785 bpr 7031
            }
14179 bpr 7032
          }
7033
  }
7034
  if (is_hydroximino_C (a_view)) {
7035
    if (bond[get_bond (a_view, a_n) - 1].arom == false)
7036
            fg[fg_carboxylic_acid_deriv - 1] = true;
7037
      if (o_count == 1) {
7038
              if (is_hydroxy (a_view, a_o))
7039
                fg[fg_hydroxamic_acid - 1] = true;
7040
            }
6785 bpr 7041
    }
14179 bpr 7042
    if (!is_hydrazono_C (a_view))
7043
      return;
7044
    if (bond[get_bond (a_view, a_n) - 1].arom == false)
7045
      fg[fg_carboxylic_acid_deriv - 1] = true;
7046
    if (n_count == 1) {
7047
        if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7048
          fg[fg_carboxylic_acid_amidrazone - 1] = true;
7049
  }
6785 bpr 7050
}
7051
 
14179 bpr 7052
static void chk_co2_sp2 (a_view, a_ref)
6785 bpr 7053
     int a_view, a_ref;
7054
{
7055
  int i;
7056
  neighbor_rec nb;
7057
  str2 nb_el;
7058
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
7059
    s_count = 0, sr_count = 0;
7060
  int FORLIM;
7061
 
7062
  memset (nb, 0, sizeof (neighbor_rec));
7063
  get_neighbors (nb, a_view);
7064
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7065
  for (i = 0; i < FORLIM; i++) {
7066
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7067
           strcpy (nb_el, atom[nb[i] - 1].element);
7068
            if (strcmp (nb_el, "C ")) {
7069
              if (!strcmp (nb_el, "O ")) {
7070
                      o_count++;
7071
                      if (is_alkoxy (a_view, nb[i]) |
7072
                          is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,nb[i]))
7073
                        /* v0.3j */
7074
                        or_count++;
7075
                    }
7076
              if (!strcmp (nb_el, "N ")) {
7077
                      n_count++;
7078
                      if (is_hydrazino (a_view, nb[i]))
7079
                        nn_count++;
7080
                      if (is_subst_hydrazino (a_view, nb[i]))   /* more general... */
7081
                        nnx_count++;
7082
                    }
7083
              if (!strcmp (nb_el, "S ")) {
7084
                      s_count++;
7085
                      if (is_alkylsulfanyl (a_view, nb[i]) | is_arylsulfanyl (a_view, nb[i]))
7086
                        sr_count++;
7087
                    }
6785 bpr 7088
            }
14179 bpr 7089
          }
7090
  }
7091
  if (is_oxo_C (a_view)) {
7092
      if (o_count == 2) {
7093
              fg[fg_carbonic_acid_deriv - 1] = true;
7094
              if (or_count == 1)
7095
                fg[fg_carbonic_acid_monoester - 1] = true;
7096
              if (or_count == 2)
7097
                fg[fg_carbonic_acid_diester - 1] = true;
7098
            }
7099
      if (o_count == 1 && s_count == 1) {
7100
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7101
              if (or_count + sr_count == 1)
7102
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7103
              if (or_count + sr_count == 2)
7104
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7105
            }
7106
      if (s_count == 2) {
7107
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7108
              if (sr_count == 1)
7109
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7110
              if (sr_count == 2)
7111
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7112
            }
7113
      if (o_count == 1 && n_count == 1) {
7114
              fg[fg_carbamic_acid_deriv - 1] = true;
7115
              if (or_count == 0)
7116
                fg[fg_carbamic_acid - 1] = true;
7117
              if (or_count == 1)
7118
                fg[fg_carbamic_acid_ester - 1] = true;
7119
            }
7120
      if (s_count == 1 && n_count == 1) {
7121
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7122
              if (sr_count == 0)
7123
                fg[fg_thiocarbamic_acid - 1] = true;
7124
              if (sr_count == 1)
7125
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7126
            }
7127
      if (n_count == 2) {
7128
            if (nn_count == 1)
7129
              fg[fg_semicarbazide - 1] = true;
7130
            else {
6785 bpr 7131
              if (nnx_count == 0)       /* excludes semicarbazones */
14179 bpr 7132
                      fg[fg_urea - 1] = true;
6785 bpr 7133
            }
14179 bpr 7134
          }
7135
  }                             /* end Oxo-C */
7136
  if (is_thioxo_C (a_view)) {
7137
      if (o_count == 2) {
7138
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7139
              if (or_count == 1)
7140
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7141
              if (or_count == 2)
7142
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7143
            }
7144
      if (o_count == 1 && s_count == 1) {
7145
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7146
              if (or_count + sr_count == 1)
7147
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7148
              if (or_count + sr_count == 2)
7149
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7150
            }
7151
      if (s_count == 2) {
7152
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7153
              if (sr_count == 1)
7154
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7155
              if (sr_count == 2)
7156
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7157
            }
7158
      if (o_count == 1 && n_count == 1) {
7159
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7160
              if (or_count == 0)
7161
                fg[fg_thiocarbamic_acid - 1] = true;
7162
              if (or_count == 1)
7163
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7164
            }
7165
      if (s_count == 1 && n_count == 1) {
7166
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7167
              if (sr_count == 0)
7168
                fg[fg_thiocarbamic_acid - 1] = true;
7169
              if (sr_count == 1)
7170
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7171
            }
7172
      if (n_count == 2) {
7173
            if (nn_count == 1)
7174
              fg[fg_thiosemicarbazide - 1] = true;
7175
            else {
6785 bpr 7176
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
14179 bpr 7177
                      fg[fg_thiourea - 1] = true;
6785 bpr 7178
            }
14179 bpr 7179
          }
7180
  }                             /* end Thioxo-C */
7181
  if (!(is_true_imino_C (a_view) &
7182
       (bond[get_bond (a_view, a_ref) - 1].arom == false))) {
6785 bpr 7183
      return;
14179 bpr 7184
  }                             /* end Imino-C */
6785 bpr 7185
  if (o_count == 1 && n_count == 1)
7186
    fg[fg_isourea - 1] = true;
7187
  if (s_count == 1 && n_count == 1)
7188
    fg[fg_isothiourea - 1] = true;
7189
  if (n_count == 2)
7190
    fg[fg_guanidine - 1] = true;
7191
}
7192
 
14179 bpr 7193
static void chk_co2_sp (a_view, a_ref)
6785 bpr 7194
     int a_view, a_ref;
7195
{
7196
  int i;
7197
  neighbor_rec nb;
7198
  str2 nb_el;
7199
  int o_count = 0, n_count = 0, s_count = 0;
7200
  int FORLIM;
7201
 
7202
  memset (nb, 0, sizeof (neighbor_rec));
7203
  get_neighbors (nb, a_view);
7204
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7205
  for (i = 0; i < FORLIM; i++) {
7206
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D') {
7207
            strcpy (nb_el, atom[nb[i] - 1].element);
7208
            if (strcmp (nb_el, "C ")) {
6785 bpr 7209
              if (!strcmp (nb_el, "O "))
14179 bpr 7210
                      o_count++;
6785 bpr 7211
              if (!strcmp (nb_el, "N "))
14179 bpr 7212
                      n_count++;
6785 bpr 7213
              if (!strcmp (nb_el, "S "))
14179 bpr 7214
                      s_count++;
6785 bpr 7215
            }
14179 bpr 7216
          }
7217
  }
6785 bpr 7218
  if (o_count + s_count == 2)   /* new in v0.3b */
7219
    fg[fg_co2_deriv - 1] = true;
7220
  if (o_count == 1 && n_count == 1)
7221
    fg[fg_isocyanate - 1] = true;
7222
  if (s_count == 1 && n_count == 1)
7223
    fg[fg_isothiocyanate - 1] = true;
7224
  if (n_count == 2)
7225
    fg[fg_carbodiimide - 1] = true;
7226
}
7227
 
14179 bpr 7228
static void chk_triple (a1, a2)
6785 bpr 7229
     int a1, a2;
7230
{
7231
  str2 a1_el, a2_el;
7232
 
7233
  strcpy (a1_el, atom[a1 - 1].element);
7234
  strcpy (a2_el, atom[a2 - 1].element);
17890 bpr 7235
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &&
6785 bpr 7236
      (bond[get_bond (a1, a2) - 1].arom == false))
7237
    fg[fg_alkyne - 1] = true;
7238
  if (is_nitrile (a1, a2))
7239
    fg[fg_nitrile - 1] = true;
7240
  if (is_isonitrile (a1, a2))
7241
    fg[fg_isonitrile - 1] = true;
7242
  if (is_cyanate (a1, a2))
7243
    fg[fg_cyanate - 1] = true;
7244
  if (is_thiocyanate (a1, a2))
7245
    fg[fg_thiocyanate - 1] = true;
7246
}
7247
 
14179 bpr 7248
static void chk_ccx (a_view, a_ref)
6785 bpr 7249
     int a_view, a_ref;
7250
{
7251
  int i;
7252
  neighbor_rec nb;
7253
  int oh_count = 0, or_count = 0, n_count = 0;
7254
  int FORLIM;
7255
 
7256
  memset (nb, 0, sizeof (neighbor_rec));
7257
  get_neighbors (nb, a_ref);
7258
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7259
  for (i = 0; i < FORLIM; i++) {
7260
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6785 bpr 7261
          if (is_hydroxy (a_ref, nb[i]))
7262
            oh_count++;
7263
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7264
              is_siloxy (a_ref, nb[i]))
7265
            or_count++;
7266
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7267
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7268
            n_count++;
14179 bpr 7269
          }
7270
  }
6785 bpr 7271
  if (oh_count == 1)
7272
    fg[fg_enol - 1] = true;
7273
  if (or_count == 1)
7274
    fg[fg_enolether - 1] = true;
7275
  if (n_count == 1)
7276
    fg[fg_enamine - 1] = true;
7277
  /* new in v0.2f   (regard anything else as an alkene) */
7278
  if (oh_count + or_count + n_count == 0)
7279
    fg[fg_alkene - 1] = true;
7280
}
7281
 
14179 bpr 7282
static void chk_xccx (a_view, a_ref)
6785 bpr 7283
     int a_view, a_ref;
7284
{
7285
  int i;
7286
  neighbor_rec nb;
7287
  int oh_count = 0, or_count = 0, n_count = 0;
7288
  int FORLIM;
7289
 
7290
  memset (nb, 0, sizeof (neighbor_rec));
7291
  get_neighbors (nb, a_view);
7292
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7293
  for (i = 0; i < FORLIM; i++) {
7294
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7295
            if (is_hydroxy (a_view, nb[i]))
7296
              oh_count++;
7297
            if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
7298
                is_siloxy (a_view, nb[i]))
7299
              or_count++;
7300
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7301
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7302
              n_count++;
7303
          }
7304
  }
6785 bpr 7305
  memset (nb, 0, sizeof (neighbor_rec));
7306
  get_neighbors (nb, a_ref);
7307
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7308
  for (i = 0; i < FORLIM; i++) {
7309
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
7310
            if (is_hydroxy (a_ref, nb[i]))
7311
              oh_count++;
7312
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7313
                is_siloxy (a_ref, nb[i]))
7314
              or_count++;
7315
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7316
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7317
              n_count++;
7318
          }
7319
  }
6785 bpr 7320
  if (oh_count == 2)
7321
    fg[fg_enediol - 1] = true;
7322
  /* new in v0.2f   (regard anything else as an alkene) */
7323
  if (oh_count + or_count + n_count == 0)
7324
    fg[fg_alkene - 1] = true;
7325
}
7326
 
14179 bpr 7327
static void chk_n_o_dbl (a1, a2)
6785 bpr 7328
     int a1, a2;
7329
{
7330
  int i;
7331
  neighbor_rec nb;
7332
  str2 nb_el;
7333
  int or_count = 0, n_count = 0, c_count = 0;
7334
  int b;                        /* v0.3j */
7335
  int het_count = 0;            /* v0.3k */
7336
  char bt;                      /* v0.3k */
7337
  float bo_sum = 0.0;           /* v0.3k */
7338
  int FORLIM;
7339
 
7340
  memset (nb, 0, sizeof (neighbor_rec));
7341
  get_neighbors (nb, a1);
7342
  FORLIM = atom[a1 - 1].neighbor_count;
7343
  /* v0.3k */
7344
  /* v0.3k */
14179 bpr 7345
  for (i = 0; i < FORLIM; i++) {
7346
    if (nb[i] != a2) {
7347
            b = get_bond (a1, nb[i]);   /* v0.3j */
7348
            strcpy (nb_el, atom[nb[i] - 1].element);
7349
            bt = bond[b - 1].btype;     /* v0.3k */
7350
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7351
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
7352
                && strcmp (nb_el, "LP") && bond[b - 1].arom == false)
7353
                /* added 'D ' in v0.3n */
7354
              het_count++;
7355
            /* v0.3k: ignore hetero atoms */
7356
            /* in aromatic rings like isoxazole  */
7357
            if (bt == 'S')
7358
              bo_sum += 1.0;
7359
            if (bt == 'D')
7360
              bo_sum += 2.0;
7361
            if (bt == 'A')
7362
              bo_sum += 1.5;
7363
            if (!strcmp (nb_el, "O "))
7364
              or_count++;
7365
            if (!strcmp (nb_el, "N "))
7366
              n_count++;
7367
            if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')      /* v0.3k */
7368
              c_count++;
7369
            /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
7370
          }
7371
  }
7372
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2) {
7373
    /* excludes nitro etc. */
7374
    if (or_count == 1)
7375
            fg[fg_nitrite - 1] = true;
7376
    if (c_count == 1)
7377
            fg[fg_nitroso_compound - 1] = true;
7378
    if (n_count == 1)           /* instead of nitrosamine  v0.3j */
7379
            fg[fg_nitroso_compound - 1] = true;
7380
    /*if (n_count = 1) then fg[fg_nitrosamine]   := true;  (* still missing */
7381
  }
6785 bpr 7382
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
7383
  /*  begin */
7384
  /*    fg[fg_n_oxide] := true; */
7385
  /*  end; */
7386
  /* new approach in v0.3k */
7387
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
7388
    fg[fg_n_oxide - 1] = true;
7389
}
7390
 
14179 bpr 7391
static void chk_sulfoxide (a1, a2)
6785 bpr 7392
     int a1, a2;
7393
{
7394
  int i;
7395
  neighbor_rec nb;
7396
  str2 nb_el;
7397
  int o_count = 0, c_count = 0;
7398
  int FORLIM;
7399
 
7400
  memset (nb, 0, sizeof (neighbor_rec));
7401
  get_neighbors (nb, a1);
7402
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7403
  for (i = 0; i < FORLIM; i++) {
7404
    strcpy (nb_el, atom[nb[i] - 1].element);
7405
    if (!strcmp (nb_el, "O "))
7406
            o_count++;
7407
    if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
7408
            c_count++;
7409
  }
6785 bpr 7410
  if (o_count == 1 && c_count == 2)
7411
    fg[fg_sulfoxide - 1] = true;
7412
}
7413
 
14179 bpr 7414
static void chk_double (a1, a2)
6785 bpr 7415
     int a1, a2;
7416
{
7417
  str2 a1_el, a2_el;
7418
 
7419
  strcpy (a1_el, atom[a1 - 1].element);
7420
  strcpy (a2_el, atom[a2 - 1].element);
17890 bpr 7421
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &&
14179 bpr 7422
      (bond[get_bond (a1, a2) - 1].arom == false)) {
7423
    if (hetbond_count (a1) == 2)
7424
            chk_carbonyl_deriv (a1, a2);
7425
    if (hetbond_count (a1) == 3)
7426
            chk_carboxyl_deriv (a1, a2);
7427
    if (hetbond_count (a1) == 4) {
7428
            if (!strcmp (atom[a1 - 1].atype, "C2 "))
7429
              chk_co2_sp2 (a1, a2);
7430
            if (!strcmp (atom[a1 - 1].atype, "C1 "))
7431
              chk_co2_sp (a1, a2);
7432
          }
7433
  }                             /* end C=X */
6785 bpr 7434
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
7435
       && !strcmp (atom[a2 - 1].atype,
14179 bpr 7436
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == false)) {
7437
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
7438
            fg[fg_ketene_acetal_deriv - 1] = true;
7439
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
7440
            chk_ccx (a1, a2);
7441
    if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
7442
            chk_xccx (a1, a2);
7443
    if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
7444
              atom[a1 - 1].arom == false && atom[a2 - 1].arom == false)
7445
            fg[fg_alkene - 1] = true;
7446
  }
7447
  if (((!strcmp (a1_el, "N ") && !strcmp (a2_el, "N "))
7448
      && (hetbond_count (a1) == 2) && (hetbond_count (a2) == 2)
7449
      && (bond[get_bond (a1, a2) - 1].arom == false))
6785 bpr 7450
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
7451
    fg[fg_azo_compound - 1] = true;
7452
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
7453
    chk_n_o_dbl (a1, a2);
7454
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
7455
    chk_sulfoxide (a1, a2);
7456
}
7457
 
14179 bpr 7458
static void chk_c_hal (a1, a2)
6785 bpr 7459
     int a1, a2;
7460
{
7461
  str2 a2_el;
7462
 
7463
  strcpy (a2_el, atom[a2 - 1].element);
7464
  fg[fg_halogen_deriv - 1] = true;
14179 bpr 7465
  if (atom[a1 - 1].arom) {
7466
    fg[fg_aryl_halide - 1] = true;
7467
    if (!strcmp (a2_el, "F "))
7468
            fg[fg_aryl_fluoride - 1] = true;
7469
    if (!strcmp (a2_el, "CL"))
7470
            fg[fg_aryl_chloride - 1] = true;
7471
    if (!strcmp (a2_el, "BR"))
7472
            fg[fg_aryl_bromide - 1] = true;
7473
    if (!strcmp (a2_el, "I "))
7474
            fg[fg_aryl_iodide - 1] = true;
7475
    return;
7476
  }
7477
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2)) {
7478
    /* alkyl halides */
7479
    fg[fg_alkyl_halide - 1] = true;
7480
    if (!strcmp (a2_el, "F "))
7481
            fg[fg_alkyl_fluoride - 1] = true;
7482
    if (!strcmp (a2_el, "CL"))
7483
            fg[fg_alkyl_chloride - 1] = true;
7484
    if (!strcmp (a2_el, "BR"))
7485
            fg[fg_alkyl_bromide - 1] = true;
7486
    if (!strcmp (a2_el, "I "))
7487
            fg[fg_alkyl_iodide - 1] = true;
7488
  }
7489
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3)) {
7490
    /* acyl halides and related compounds */
7491
    if (is_oxo_C (a1)) {
7492
            fg[fg_acyl_halide - 1] = true;
7493
            if (!strcmp (a2_el, "F "))
7494
              fg[fg_acyl_fluoride - 1] = true;
7495
            if (!strcmp (a2_el, "CL"))
7496
              fg[fg_acyl_chloride - 1] = true;
7497
            if (!strcmp (a2_el, "BR"))
7498
              fg[fg_acyl_bromide - 1] = true;
7499
            if (!strcmp (a2_el, "I "))
7500
              fg[fg_acyl_iodide - 1] = true;
7501
          }
7502
    if (is_thioxo_C (a1))
7503
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7504
    if (is_imino_C (a1))
7505
            fg[fg_imidoyl_halide - 1] = true;
7506
  }
7507
  if (!((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
6785 bpr 7508
       && (hetbond_count (a1) == 4)))
7509
    /* chloroformates etc. */
7510
    return;
7511
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
7512
  fg[fg_co2_deriv - 1] = true;
14179 bpr 7513
  if (is_oxo_C (a1)) {
6785 bpr 7514
      fg[fg_carbonic_acid_deriv - 1] = true;
14179 bpr 7515
    if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
7516
            fg[fg_carbonic_acid_ester_halide - 1] = true;
7517
    if (is_carbamoyl (a2, a1)) {
7518
            fg[fg_carbamic_acid_deriv - 1] = true;
7519
            fg[fg_carbamic_acid_halide - 1] = true;
7520
          }
7521
  }
6785 bpr 7522
  if (!is_thioxo_C (a1))
7523
    return;
7524
  fg[fg_thiocarbonic_acid_deriv - 1] = true;
7525
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
7526
    fg[fg_thiocarbonic_acid_ester_halide - 1] = true;
14179 bpr 7527
  if (is_thiocarbamoyl (a2, a1)) {
7528
    fg[fg_thiocarbamic_acid_deriv - 1] = true;
7529
    fg[fg_thiocarbamic_acid_halide - 1] = true;
6785 bpr 7530
      /* end of non-aromatic halogen compounds */
14179 bpr 7531
  }
6785 bpr 7532
}
7533
 
14179 bpr 7534
static void chk_c_o (a1, a2)
6785 bpr 7535
     int a1, a2;
7536
{
7537
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
7538
  if (bond[get_bond (a1, a2) - 1].arom == true)
7539
    return;
14179 bpr 7540
  if (is_true_alkyl (a2, a1) && is_hydroxy (a1, a2)) {
7541
    fg[fg_hydroxy - 1] = true;
7542
    fg[fg_alcohol - 1] = true;
7543
    if (atom[a1 - 1].neighbor_count <= 2)
7544
            fg[fg_prim_alcohol - 1] = true;
7545
    if (atom[a1 - 1].neighbor_count == 3)
7546
            fg[fg_sec_alcohol - 1] = true;
7547
    if (atom[a1 - 1].neighbor_count == 4)
7548
            fg[fg_tert_alcohol - 1] = true;
7549
  }
7550
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2)) {
7551
    fg[fg_hydroxy - 1] = true;
7552
    fg[fg_phenol - 1] = true;
7553
  }
7554
  if (is_true_alkyl (a2, a1) && is_true_alkoxy (a1, a2)) {
7555
    fg[fg_ether - 1] = true;
7556
    fg[fg_dialkylether - 1] = true;
7557
  }
17890 bpr 7558
  if ((is_true_alkyl (a2, a1) && is_aryloxy (a1, a2)) ||
14179 bpr 7559
      (is_aryl (a2, a1) && is_true_alkoxy (a1, a2))) {
7560
    fg[fg_ether - 1] = true;
7561
    fg[fg_alkylarylether - 1] = true;
7562
  }
7563
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2)) {
7564
    fg[fg_ether - 1] = true;
7565
    fg[fg_diarylether - 1] = true;
7566
  }
7567
  if ((is_true_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2)) {
7568
    fg[fg_ether - 1] = true;
7569
    ether_generic = true;
7570
  }
7571
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2)) {
7572
    fg[fg_hydroxy - 1] = true;
7573
    hydroxy_generic = true;
7574
  }
6785 bpr 7575
}
7576
 
14179 bpr 7577
static void chk_c_s (a1, a2)
6785 bpr 7578
     int a1, a2;
7579
{
7580
  int i;
7581
  neighbor_rec nb;
7582
  str2 nb_el;
7583
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
7584
    hal_count = 0;
7585
  int FORLIM;
7586
 
7587
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
7588
  if (bond[get_bond (a1, a2) - 1].arom == true)
7589
    return;
14179 bpr 7590
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2)) {
7591
    fg[fg_thiol - 1] = true;
7592
    fg[fg_alkylthiol - 1] = true;
7593
  }
7594
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2)) {
7595
    fg[fg_thiol - 1] = true;
7596
    fg[fg_arylthiol - 1] = true;
7597
  }
6785 bpr 7598
  if (is_true_alkyl (a2, a1) && is_true_alkylsulfanyl (a1, a2))
7599
    fg[fg_thioether - 1] = true;
17890 bpr 7600
  if ((is_true_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) ||
14179 bpr 7601
        (is_aryl (a2, a1) && is_true_alkylsulfanyl (a1, a2)))
6785 bpr 7602
    fg[fg_thioether - 1] = true;
7603
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
7604
    fg[fg_thioether - 1] = true;
7605
  /* check for sulfinic/sulfenic acid derivatives */
7606
  memset (nb, 0, sizeof (neighbor_rec));
7607
  get_neighbors (nb, a2);
7608
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7609
  for (i = 0; i < FORLIM; i++) {
7610
    strcpy (nb_el, atom[nb[i] - 1].element);
7611
    if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
7612
            c_count++;
7613
    if (is_hydroxy (a2, nb[i]))
7614
            oh_count++;
7615
    if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
7616
            or_count++;
7617
    if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
7618
            n_count++;
7619
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7620
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
7621
            hal_count++;
7622
    if (!strcmp (nb_el, "O "))
7623
            o_count++;
7624
  }
6785 bpr 7625
  if (c_count != 1)
7626
    return;
14179 bpr 7627
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1) {
7628
    /* sulfinic acid && derivs */
7629
    fg[fg_sulfinic_acid_deriv - 1] = true;
7630
    if (oh_count == 1)
7631
            fg[fg_sulfinic_acid - 1] = true;
7632
    if (or_count == 1)
7633
            fg[fg_sulfinic_acid_ester - 1] = true;
7634
    if (hal_count == 1)
7635
            fg[fg_sulfinic_acid_halide - 1] = true;
7636
    if (n_count == 1)
7637
            fg[fg_sulfinic_acid_amide - 1] = true;
7638
  }
6785 bpr 7639
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
7640
    /* sulfenic acid && derivs */
7641
    return;
7642
 
7643
  fg[fg_sulfenic_acid_deriv - 1] = true;
7644
  if (oh_count == 1)
7645
    fg[fg_sulfenic_acid - 1] = true;
7646
  if (or_count == 1)
7647
    fg[fg_sulfenic_acid_ester - 1] = true;
7648
  if (hal_count == 1)
7649
    fg[fg_sulfenic_acid_halide - 1] = true;
7650
  if (n_count == 1)
7651
    fg[fg_sulfenic_acid_amide - 1] = true;
7652
}
7653
 
14179 bpr 7654
static void chk_c_n (a1, a2)
6785 bpr 7655
     int a1, a2;
7656
{
7657
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
7658
  if (atom[a2 - 1].arom == true)
7659
    return;
14179 bpr 7660
  if (is_true_alkyl (a2, a1) && is_amino (a1, a2)) {
7661
    fg[fg_amine - 1] = true;
7662
    fg[fg_prim_amine - 1] = true;
7663
    fg[fg_prim_aliph_amine - 1] = true;
6785 bpr 7664
    }
14179 bpr 7665
  if (is_aryl (a2, a1) && is_amino (a1, a2)) {
7666
    fg[fg_amine - 1] = true;
7667
    fg[fg_prim_amine - 1] = true;
7668
    fg[fg_prim_arom_amine - 1] = true;
7669
  }
7670
  if (is_true_alkyl (a2, a1) && is_true_alkylamino (a1, a2)) {
7671
    fg[fg_amine - 1] = true;
7672
    fg[fg_sec_amine - 1] = true;
7673
    fg[fg_sec_aliph_amine - 1] = true;
7674
  }
7675
  if (is_aryl (a2, a1) && is_true_alkylamino (a1, a2)) {
7676
    fg[fg_amine - 1] = true;
7677
    fg[fg_sec_amine - 1] = true;
7678
    fg[fg_sec_mixed_amine - 1] = true;
7679
  }
7680
  if (is_aryl (a2, a1) && is_arylamino (a1, a2)) {
7681
    fg[fg_amine - 1] = true;
7682
    fg[fg_sec_amine - 1] = true;
7683
    fg[fg_sec_arom_amine - 1] = true;
7684
  }
7685
  if (is_true_alkyl (a2, a1) && is_true_dialkylamino (a1, a2)) {
7686
    fg[fg_amine - 1] = true;
7687
    fg[fg_tert_amine - 1] = true;
7688
    fg[fg_tert_aliph_amine - 1] = true;
7689
  }
17890 bpr 7690
  if ((is_true_alkyl (a2, a1) && is_diarylamino (a1, a2)) ||
14179 bpr 7691
      (is_aryl (a2, a1) && is_true_dialkylamino (a1, a2))) {
7692
    fg[fg_amine - 1] = true;
7693
    fg[fg_tert_amine - 1] = true;
7694
    fg[fg_tert_mixed_amine - 1] = true;
7695
  }
7696
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2)) {
7697
    fg[fg_amine - 1] = true;
7698
    fg[fg_tert_amine - 1] = true;
7699
    fg[fg_tert_arom_amine - 1] = true;
7700
  }
17890 bpr 7701
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) ||
14179 bpr 7702
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2, a1) == false))
6785 bpr 7703
    /* v0.3k */
7704
    fg[fg_hydroxylamine - 1] = true;
7705
  /* v0.3k */
7706
  /* v0.3k  */
17890 bpr 7707
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) ||
6785 bpr 7708
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
7709
    fg[fg_hydrazine - 1] = true;
17890 bpr 7710
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) ||
6785 bpr 7711
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
7712
    /* v0.3k */
7713
    fg[fg_azide - 1] = true;
17890 bpr 7714
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) ||
6785 bpr 7715
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
7716
    /* v0.3k */
7717
    fg[fg_diazonium_salt - 1] = true;
7718
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7719
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
7720
    /* v0.3k */
7721
    fg[fg_nitro_compound - 1] = true;
7722
  if (is_alkynyl (a2, a1) &
14179 bpr 7723
        (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
7724
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2))))) {
6785 bpr 7725
      fg[fg_amine - 1] = true;
7726
      amine_generic = true;
14179 bpr 7727
  }
6785 bpr 7728
}
7729
 
14179 bpr 7730
static void chk_c_c (a1, a2)
6785 bpr 7731
     int a1, a2;
7732
{
7733
  int i;
7734
  neighbor_rec nb;
7735
  int oh_count, nhr_count, FORLIM;
7736
 
7737
  /* ignore aromatic rings */
7738
  if (atom[a2 - 1].arom == true)
7739
    return;
7740
  /*check for 1,2-diols and 1,2-aminoalcoholes */
7741
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
14179 bpr 7742
        && !strcmp (atom[a2 - 1].atype, "C3 ")) {
7743
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1)) {
7744
            oh_count = 0;
7745
            nhr_count = 0;
7746
            memset (nb, 0, sizeof (neighbor_rec));
7747
            get_neighbors (nb, a1);
7748
            FORLIM = atom[a1 - 1].neighbor_count;
7749
            for (i = 0; i < FORLIM; i++) {
7750
              if (nb[i] != a2) {
7751
                      if (is_hydroxy (a1, nb[i]))
7752
                        oh_count++;
7753
                      if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7754
                        is_arylamino (a1, nb[i]))
7755
                      nhr_count++;
7756
                    }
6785 bpr 7757
            }
14179 bpr 7758
            memset (nb, 0, sizeof (neighbor_rec));
7759
            get_neighbors (nb, a2);
7760
            FORLIM = atom[a2 - 1].neighbor_count;
7761
            for (i = 0; i < FORLIM; i++) {
7762
              if (nb[i] != a1) {
7763
                      if (is_hydroxy (a2, nb[i]))
7764
                        oh_count++;
7765
                      if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
7766
                          is_arylamino (a2, nb[i]))
7767
                        nhr_count++;
7768
                    }
6785 bpr 7769
            }
14179 bpr 7770
            if (oh_count == 2)
7771
              fg[fg_1_2_diol - 1] = true;
7772
            if (oh_count == 1 && nhr_count == 1)
7773
              fg[fg_1_2_aminoalcohol - 1] = true;
7774
          }
7775
  }
6785 bpr 7776
  /* check for alpha-aminoacids and alpha-hydroxyacids */
7777
  if (strcmp (atom[a1 - 1].atype, "C3 ")
7778
      || strcmp (atom[a2 - 1].atype, "C2 "))
7779
    return;
7780
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
7781
    return;
7782
  oh_count = 0;
7783
  nhr_count = 0;
7784
  memset (nb, 0, sizeof (neighbor_rec));
7785
  get_neighbors (nb, a1);
7786
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7787
  for (i = 0; i < FORLIM; i++) {
7788
    if (nb[i] != a2) {
7789
            if (is_hydroxy (a1, nb[i]))
7790
              oh_count++;
7791
            if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7792
                is_arylamino (a1, nb[i]))
7793
              nhr_count++;
7794
          }
7795
  }
6785 bpr 7796
  memset (nb, 0, sizeof (neighbor_rec));
7797
  get_neighbors (nb, a2);
7798
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7799
  for (i = 0; i < FORLIM; i++) {
7800
    if (nb[i] != a1) {
7801
            if (is_hydroxy (a2, nb[i]))
7802
              oh_count++;
7803
          }
7804
  }
6785 bpr 7805
  if ((oh_count == 2) && is_oxo_C (a2))
7806
    fg[fg_alpha_hydroxyacid - 1] = true;
7807
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
7808
    fg[fg_alpha_aminoacid - 1] = true;
7809
}
7810
 
14179 bpr 7811
static void chk_x_y_single (a_view, a_ref)
6785 bpr 7812
     int a_view, a_ref;
7813
{
7814
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
14179 bpr 7815
        !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7816
    if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
7817
            fg[fg_hydroperoxide - 1] = true;
7818
    if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
7819
              is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,a_ref) |
7820
                        is_aryloxy (a_view, a_ref) |
7821
                        is_siloxy (a_view, a_ref)))
7822
            fg[fg_peroxide - 1] = true;
7823
  }                             /* still missing: peracid */
6785 bpr 7824
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
14179 bpr 7825
      !strcmp (atom[a_ref - 1].atype, "S3 ")) {
6785 bpr 7826
      if (atom[a_view - 1].neighbor_count == 2 &&
7827
          atom[a_ref - 1].neighbor_count == 2)
14179 bpr 7828
          fg[fg_disulfide - 1] = true;
7829
  }
6785 bpr 7830
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7831
       !strcmp (atom[a_ref - 1].element, "N ")) && (hetbond_count (a_view) == 1)
7832
      && (hetbond_count (a_ref) == 1)) {
6785 bpr 7833
      /*if ((is_amino(a_ref,a_view)) or  */
7834
      /*    (is_subst_amino(a_ref,a_view)) or */
7835
      /*    (is_acylamino(a_ref,a_view))) and */
7836
      /*   ((is_amino(a_view,a_ref)) or  */
7837
      /*    (is_subst_amino(a_view,a_ref)) or */
7838
      /*    (is_acylamino(a_ref,a_view))) then  */
7839
      if (bond[get_bond (a_view, a_ref) - 1].arom == false)
14179 bpr 7840
              fg[fg_hydrazine - 1] = true;
7841
  }
6785 bpr 7842
  if (!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7843
      !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7844
    /* bond is in "opposite" direction */
7845
    if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &
7846
              is_nitro (a_ref, a_view))
7847
            fg[fg_nitrate - 1] = true;
7848
    if ((is_nitro (a_ref, a_view) == false
7849
              && atom[a_view - 1].arom == false) && (is_amino (a_ref, a_view) |
7850
                    is_subst_amino (a_ref, a_view)) &
7851
              (is_acylamino (a_ref, a_view) == false))
7852
            fg[fg_hydroxylamine - 1] = true;    /* new in v0.3c */
7853
  }
6785 bpr 7854
  if (!strcmp (atom[a_view - 1].element, "S ") &&
7855
      !strcmp (atom[a_ref - 1].element, "O "))
7856
    chk_sulfoxide (a_view, a_ref);
7857
}
7858
 
14179 bpr 7859
static void chk_single (a1, a2)
6785 bpr 7860
     int a1, a2;
7861
{
7862
  str2 a1_el, a2_el;
7863
 
7864
  strcpy (a1_el, atom[a1 - 1].element);
7865
  strcpy (a2_el, atom[a2 - 1].element);
7866
  if (!strcmp (a1_el, "C ") &&
7867
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
7868
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
7869
    chk_c_hal (a1, a2);
7870
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
7871
    chk_c_o (a1, a2);
7872
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
7873
    chk_c_s (a1, a2);
7874
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
7875
    chk_c_n (a1, a2);
14179 bpr 7876
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) == false)) {
6785 bpr 7877
      fg[fg_organometallic - 1] = true;
7878
      if (!strcmp (a2_el, "LI"))
14179 bpr 7879
              fg[fg_organolithium - 1] = true;
6785 bpr 7880
      if (!strcmp (a2_el, "MG"))
14179 bpr 7881
              fg[fg_organomagnesium - 1] = true;
7882
  }
6785 bpr 7883
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
7884
    chk_c_c (a1, a2);
7885
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
7886
    chk_x_y_single (a1, a2);
7887
}
7888
 
14179 bpr 7889
static void chk_carbonyl_deriv_sp3 (a_ref)
6785 bpr 7890
     int a_ref;
7891
{
7892
  int i;
7893
  neighbor_rec nb;
7894
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
7895
  int FORLIM;
7896
 
7897
  memset (nb, 0, sizeof (neighbor_rec));
7898
  get_neighbors (nb, a_ref);
7899
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7900
  for (i = 0; i < FORLIM; i++) {
7901
    if (is_hydroxy (a_ref, nb[i]))
7902
            oh_count++;
7903
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7904
              is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
7905
            or_count++;
7906
    if (is_sulfanyl (a_ref, nb[i]))
7907
            sh_count++;
7908
    if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
7909
              is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref, nb[i]))
7910
            sr_count++;
7911
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
7912
            n_count++;
7913
  }
6785 bpr 7914
  if (oh_count == 2)
7915
    fg[fg_carbonyl_hydrate - 1] = true;
7916
  if (oh_count == 1 && or_count == 1)
7917
    fg[fg_hemiacetal - 1] = true;
7918
  if (or_count == 2)
7919
    fg[fg_acetal - 1] = true;
7920
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
7921
    fg[fg_hemiaminal - 1] = true;
7922
  if (n_count == 2)
7923
    fg[fg_aminal - 1] = true;
7924
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
7925
    fg[fg_thiohemiaminal - 1] = true;
7926
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
7927
    fg[fg_thioacetal - 1] = true;
7928
}
7929
 
14179 bpr 7930
static void chk_carboxyl_deriv_sp3 (a_ref)
6785 bpr 7931
     int a_ref;
7932
{
7933
  int i;
7934
  neighbor_rec nb;
7935
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
7936
  int electroneg_count = 0;     /* new in v0.3j */
7937
  int hal_count = 0;
7938
  str2 nb_el;
7939
  int FORLIM;
7940
 
7941
  memset (nb, 0, sizeof (neighbor_rec));
7942
  get_neighbors (nb, a_ref);
7943
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7944
  for (i = 0; i < FORLIM; i++) {
7945
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3j */
7946
    if (is_electroneg (nb_el))
7947
            electroneg_count++;
7948
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7949
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7950
              || !strcmp (nb_el, "AT"))
7951
            hal_count++;
7952
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7953
              is_siloxy (a_ref, nb[i]))
7954
            or_count++;
7955
    if (is_hydroxy (a_ref, nb[i]))      /* new in v0.3c    */
7956
            oh_count++;
7957
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7958
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7959
            n_count++;
7960
  }
6785 bpr 7961
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := true;  (* until v0.3i */
7962
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
7963
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
7964
  if (or_count == 3)
7965
    fg[fg_carboxylic_acid_orthoester - 1] = true;
7966
  if (or_count == 2 && n_count == 1)
7967
    fg[fg_carboxylic_acid_amide_acetal - 1] = true;
7968
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
7969
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
7970
}
7971
 
14179 bpr 7972
static void chk_anhydride (a_ref)
6785 bpr 7973
     int a_ref;
7974
{
7975
  int i;
7976
  neighbor_rec nb;
7977
  int acyl_count = 0;
7978
  int FORLIM;
7979
 
7980
  memset (nb, 0, sizeof (neighbor_rec));
7981
  get_neighbors (nb, a_ref);
7982
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7983
  for (i = 0; i < FORLIM; i++) {
7984
    if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
7985
            acyl_count++;
7986
  }
7987
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7988
    fg[fg_carboxylic_acid_deriv - 1] = true;
7989
    fg[fg_carboxylic_acid_anhydride - 1] = true;
7990
  }
6785 bpr 7991
}
7992
 
14179 bpr 7993
static void chk_imide (a_ref)
6785 bpr 7994
     int a_ref;
7995
{
7996
  int i;
7997
  neighbor_rec nb;
7998
  int acyl_count = 0;
7999
  int FORLIM;
8000
 
8001
  memset (nb, 0, sizeof (neighbor_rec));
8002
  get_neighbors (nb, a_ref);
8003
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 8004
  for (i = 0; i < FORLIM; i++) {
8005
    if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))      /* v0.3j */
8006
            acyl_count++;
8007
  }
6785 bpr 8008
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
8009
    /* v0.3j: accept also N-acyl-imides */
8010
    return;
8011
  fg[fg_carboxylic_acid_deriv - 1] = true;
8012
  fg[fg_carboxylic_acid_imide - 1] = true;
8013
  if (atom[a_ref - 1].neighbor_count == 2)
8014
    fg[fg_carboxylic_acid_unsubst_imide - 1] = true;
8015
  if (atom[a_ref - 1].neighbor_count == 3)
8016
    fg[fg_carboxylic_acid_subst_imide - 1] = true;
8017
}
8018
 
14179 bpr 8019
static void chk_12diphenol (a_view, a_ref)
6785 bpr 8020
     int a_view, a_ref;
8021
{
8022
  int i;
8023
  neighbor_rec nb;
8024
  int oh_count = 0;
8025
  int FORLIM;
8026
 
8027
  memset (nb, 0, sizeof (neighbor_rec));
8028
  get_neighbors (nb, a_view);
8029
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 8030
  for (i = 0; i < FORLIM; i++) {
8031
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
8032
            if (is_hydroxy (a_view, nb[i]))
8033
              oh_count++;
8034
          }
8035
  }
6785 bpr 8036
  memset (nb, 0, sizeof (neighbor_rec));
8037
  get_neighbors (nb, a_ref);
8038
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 8039
  for (i = 0; i < FORLIM; i++) {
8040
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
8041
            if (is_hydroxy (a_ref, nb[i]))
8042
              oh_count++;
8043
          }
8044
  }
6785 bpr 8045
  if (oh_count == 2)
8046
    fg[fg_1_2_diphenol - 1] = true;
8047
}
8048
 
14179 bpr 8049
static void chk_arom_fg (a1, a2)
6785 bpr 8050
     int a1, a2;
8051
{
8052
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8053
    chk_12diphenol (a1, a2);
8054
}
8055
 
14179 bpr 8056
static boolean is_arene (r_id)
6785 bpr 8057
     int r_id;
8058
{
8059
  int i, j;
8060
  boolean r = true;
8061
  ringpath_type testring;
8062
  int ring_size, a_prev, a_ref;
8063
 
8064
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
8065
  if (r_id < 1 || r_id > n_rings)
8066
    return false;
8067
  memset (testring, 0, sizeof (ringpath_type));
8068
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8069
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8070
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8071
    testring[j] = ring[r_id - 1][j];
8072
  /*ring_size := path_length(testring); */
8073
  if (ring_size <= 2)
8074
    return false;
8075
  a_prev = testring[ring_size - 1];
14179 bpr 8076
  for (i = 0; i < ring_size; i++) {
8077
    a_ref = testring[i];
8078
    if (bond[get_bond (a_prev, a_ref) - 1].arom == false)
8079
            r = false;
8080
    a_prev = a_ref;
8081
  }
6785 bpr 8082
  return r;
8083
}
8084
 
14179 bpr 8085
static boolean is_heterocycle (r_id)
6785 bpr 8086
     int r_id;
8087
{
8088
  int i, j;
8089
  boolean r = false;
8090
  ringpath_type testring;
8091
  int ring_size, a_ref;
8092
 
8093
  if (r_id < 1 || r_id > n_rings)
8094
    return false;
8095
  memset (testring, 0, sizeof (ringpath_type));
8096
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8097
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8098
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8099
    testring[j] = ring[r_id - 1][j];
8100
  /*ring_size := path_length(testring); */
8101
  if (ring_size <= 2)
8102
    return false;
14179 bpr 8103
  for (i = 0; i < ring_size; i++) {
8104
    a_ref = testring[i];
8105
    if (strcmp (atom[a_ref - 1].element, "C "))
8106
            r = true;
8107
  }
6785 bpr 8108
  return r;
8109
}
8110
 
14179 bpr 8111
static void chk_oxo_thioxo_imino_hetarene (r_id)
6785 bpr 8112
     int r_id;
8113
{
8114
  int i, j;
8115
  ringpath_type testring;
8116
  int ring_size, a_ref;
8117
 
8118
  if (r_id < 1 || r_id > n_rings)
8119
    return;
8120
  memset (testring, 0, sizeof (ringpath_type));
8121
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8122
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8123
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8124
    testring[j] = ring[r_id - 1][j];
8125
  /*ring_size := path_length(testring); */
8126
  /*if (is_arene(r_id)) and (odd(ring_size) = false) then */
8127
  if (!is_arene (r_id))         /* v0.3j */
8128
    return;
14179 bpr 8129
  for (i = 0; i < ring_size; i++) {
8130
    a_ref = testring[i];
8131
    if (is_oxo_C (a_ref))
8132
            fg[fg_oxohetarene - 1] = true;
8133
    if (is_thioxo_C (a_ref))
8134
            fg[fg_thioxohetarene - 1] = true;
8135
    if (is_true_exocyclic_imino_C (a_ref, r_id))        /* v0.3j */
8136
            fg[fg_iminohetarene - 1] = true;
8137
  }
6785 bpr 8138
}
8139
 
14179 bpr 8140
static void chk_ion (a_ref)
6785 bpr 8141
     int a_ref;
8142
{
8143
  int i;
8144
  neighbor_rec nb;
8145
  int charge, FORLIM;
8146
 
8147
  memset (nb, 0, sizeof (neighbor_rec));
8148
  get_neighbors (nb, a_ref);
8149
  charge = atom[a_ref - 1].formal_charge;
8150
  if (charge == 0)
8151
    /* check if charge is neutralized by an adjacent opposite charge */
8152
    return;
8153
  FORLIM = atom[a_ref - 1].neighbor_count;
8154
  for (i = 0; i < FORLIM; i++)
8155
    charge += atom[nb[i] - 1].formal_charge;
8156
  if (charge > 0)
8157
    fg[fg_cation - 1] = true;
8158
  if (charge < 0)
8159
    fg[fg_anion - 1] = true;
8160
}
8161
 
14179 bpr 8162
static void chk_functionalgroups ()
6785 bpr 8163
{
8164
  int i, a1, a2;
8165
  char bt;
8166
  int pos_chg = 0, neg_chg = 0;
8167
  int FORLIM;
8168
 
8169
  if (n_atoms < 1 || n_bonds < 1)
8170
    return;
8171
  FORLIM = n_atoms;
14179 bpr 8172
  for (i = 1; i <= FORLIM; i++) {                               /* a few groups are best discovered in the atom list */
8173
    if (!strcmp (atom[i - 1].atype, "SO2"))
8174
            chk_so2_deriv (i);
8175
    /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := true;  (* do another check in the bond list!! */
8176
    if (!strcmp (atom[i - 1].element, "P "))
8177
            chk_p_deriv (i);
8178
    if (!strcmp (atom[i - 1].element, "B "))
8179
            chk_b_deriv (i);
8180
    if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
8181
            chk_ammon (i);
8182
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 2))
8183
            chk_carbonyl_deriv_sp3 (i);
8184
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 3))
8185
            chk_carboxyl_deriv_sp3 (i);
8186
    if (!strcmp (atom[i - 1].atype, "O3 ") && atom[i - 1].neighbor_count == 2)
8187
            chk_anhydride (i);
8188
    if ((!strcmp (atom[i - 1].atype, "N3 ") || !strcmp (atom[i - 1].atype, "NAM"))
8189
              && atom[i - 1].neighbor_count >= 2)
8190
            chk_imide (i);
8191
    if (atom[i - 1].formal_charge > 0)
8192
            pos_chg += atom[i - 1].formal_charge;
8193
    if (atom[i - 1].formal_charge < 0)
8194
            neg_chg += atom[i - 1].formal_charge;
8195
    chk_ion (i);
8196
  }
6785 bpr 8197
  FORLIM = n_bonds;
14179 bpr 8198
  for (i = 0; i < FORLIM; i++) {                                /* most groups are best discovered in the bond list */
8199
    a1 = bond[i].a1;
8200
    a2 = bond[i].a2;
8201
    bt = bond[i].btype;
8202
    if (atom[a1 - 1].heavy && atom[a2 - 1].heavy) {
8203
            orient_bond (&a1, &a2);
8204
            if (bt == 'T')
8205
              chk_triple (a1, a2);
8206
            if (bt == 'D')
8207
              chk_double (a1, a2);
8208
            if (bt == 'S')
8209
              chk_single (a1, a2);
8210
            if (bond[i].arom)
8211
              chk_arom_fg (a1, a2);
8212
          }
8213
  }
8214
  if (n_rings > 0) {
8215
    FORLIM = n_rings;
8216
    for (i = 1; i <= FORLIM; i++) {
8217
            chk_oxo_thioxo_imino_hetarene (i);
8218
            if (is_arene (i))
8219
              fg[fg_aromatic - 1] = true;
8220
            if (is_heterocycle (i))
8221
              fg[fg_heterocycle - 1] = true;
8222
          }
8223
  }
6785 bpr 8224
  if (pos_chg + neg_chg > 0)
8225
    fg[fg_cation - 1] = true;
8226
  if (pos_chg + neg_chg < 0)
8227
    fg[fg_anion - 1] = true;
8228
}
8229
 
14179 bpr 8230
static void write_fg_text ()
6785 bpr 8231
{
8232
  if (fg[fg_cation - 1])
8233
    printf ("cation\n");
8234
  if (fg[fg_anion - 1])
8235
    printf ("anion\n");
8236
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
8237
  if (fg[fg_aldehyde - 1])
8238
    printf ("aldehyde\n");
8239
  if (fg[fg_ketone - 1])
8240
    printf ("ketone\n");
8241
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
8242
  if (fg[fg_thioaldehyde - 1])
8243
    printf ("thioaldehyde\n");
8244
  if (fg[fg_thioketone - 1])
8245
    printf ("thioketone\n");
8246
  if (fg[fg_imine - 1])
8247
    printf ("imine\n");
8248
  if (fg[fg_hydrazone - 1])
8249
    printf ("hydrazone\n");
8250
  if (fg[fg_semicarbazone - 1])
8251
    printf ("semicarbazone\n");
8252
  if (fg[fg_thiosemicarbazone - 1])
8253
    printf ("thiosemicarbazone\n");
8254
  if (fg[fg_oxime - 1])
8255
    printf ("oxime\n");
8256
  if (fg[fg_oxime_ether - 1])
8257
    printf ("oxime ether\n");
8258
  if (fg[fg_ketene - 1])
8259
    printf ("ketene\n");
8260
  if (fg[fg_ketene_acetal_deriv - 1])
8261
    printf ("ketene acetal or derivative\n");
8262
  if (fg[fg_carbonyl_hydrate - 1])
8263
    printf ("carbonyl hydrate\n");
8264
  if (fg[fg_hemiacetal - 1])
8265
    printf ("hemiacetal\n");
8266
  if (fg[fg_acetal - 1])
8267
    printf ("acetal\n");
8268
  if (fg[fg_hemiaminal - 1])
8269
    printf ("hemiaminal\n");
8270
  if (fg[fg_aminal - 1])
8271
    printf ("aminal\n");
8272
  if (fg[fg_thiohemiaminal - 1])
8273
    printf ("hemithioaminal\n");
8274
  if (fg[fg_thioacetal - 1])
8275
    printf ("thioacetal\n");
8276
  if (fg[fg_enamine - 1])
8277
    printf ("enamine\n");
8278
  if (fg[fg_enol - 1])
8279
    printf ("enol\n");
8280
  if (fg[fg_enolether - 1])
8281
    printf ("enol ether\n");
8282
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8283
    printf ("hydroxy compound\n");
8284
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
8285
  if (fg[fg_prim_alcohol - 1])
8286
    printf ("primary alcohol\n");
8287
  if (fg[fg_sec_alcohol - 1])
8288
    printf ("secondary alcohol\n");
8289
  if (fg[fg_tert_alcohol - 1])
8290
    printf ("tertiary alcohol\n");
8291
  if (fg[fg_1_2_diol - 1])
8292
    printf ("1,2-diol\n");
8293
  if (fg[fg_1_2_aminoalcohol - 1])
8294
    printf ("1,2-aminoalcohol\n");
8295
  if (fg[fg_phenol - 1])
8296
    printf ("phenol or hydroxyhetarene\n");
8297
  if (fg[fg_1_2_diphenol - 1])
8298
    printf ("1,2-diphenol\n");
8299
  if (fg[fg_enediol - 1])
8300
    printf ("enediol\n");
8301
  if (fg[fg_ether - 1] && ether_generic)
8302
    printf ("ether\n");
8303
  if (fg[fg_dialkylether - 1])
8304
    printf ("dialkyl ether\n");
8305
  if (fg[fg_alkylarylether - 1])
8306
    printf ("alkyl aryl ether \n");
8307
  if (fg[fg_diarylether - 1])
8308
    printf ("diaryl ether\n");
8309
  if (fg[fg_thioether - 1])
8310
    printf ("thioether\n");
8311
  if (fg[fg_disulfide - 1])
8312
    printf ("disulfide\n");
8313
  if (fg[fg_peroxide - 1])
8314
    printf ("peroxide\n");
8315
  if (fg[fg_hydroperoxide - 1])
8316
    printf ("hydroperoxide \n");
8317
  if (fg[fg_hydrazine - 1])
8318
    printf ("hydrazine derivative\n");
8319
  if (fg[fg_hydroxylamine - 1])
8320
    printf ("hydroxylamine\n");
8321
  if (fg[fg_amine - 1] && amine_generic)
8322
    printf ("amine\n");
8323
  if (fg[fg_prim_amine - 1])
8324
    printf ("primary amine\n");
8325
  if (fg[fg_prim_aliph_amine - 1])
8326
    printf ("primary aliphatic amine (alkylamine)\n");
8327
  if (fg[fg_prim_arom_amine - 1])
8328
    printf ("primary aromatic amine\n");
8329
  if (fg[fg_sec_amine - 1])
8330
    printf ("secondary amine\n");
8331
  if (fg[fg_sec_aliph_amine - 1])
8332
    printf ("secondary aliphatic amine (dialkylamine)\n");
8333
  if (fg[fg_sec_mixed_amine - 1])
8334
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
8335
  if (fg[fg_sec_arom_amine - 1])
8336
    printf ("secondary aromatic amine (diarylamine)\n");
8337
  if (fg[fg_tert_amine - 1])
8338
    printf ("tertiary amine\n");
8339
  if (fg[fg_tert_aliph_amine - 1])
8340
    printf ("tertiary aliphatic amine (trialkylamine)\n");
8341
  if (fg[fg_tert_mixed_amine - 1])
8342
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
8343
  if (fg[fg_tert_arom_amine - 1])
8344
    printf ("tertiary aromatic amine (triarylamine)\n");
8345
  if (fg[fg_quart_ammonium - 1])
8346
    printf ("quaternary ammonium salt\n");
8347
  if (fg[fg_n_oxide - 1])
8348
    printf ("N-oxide\n");
8349
  /* new in v0.2f */
14179 bpr 8350
  if (fg[fg_halogen_deriv - 1]) {
6785 bpr 8351
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
14179 bpr 8352
              !fg[fg_acyl_halide - 1])
8353
            printf ("halogen derivative\n");
8354
  }
6785 bpr 8355
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
8356
  if (fg[fg_alkyl_fluoride - 1])
8357
    printf ("alkyl fluoride\n");
8358
  if (fg[fg_alkyl_chloride - 1])
8359
    printf ("alkyl chloride\n");
8360
  if (fg[fg_alkyl_bromide - 1])
8361
    printf ("alkyl bromide\n");
8362
  if (fg[fg_alkyl_iodide - 1])
8363
    printf ("alkyl iodide\n");
8364
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
8365
  if (fg[fg_aryl_fluoride - 1])
8366
    printf ("aryl fluoride\n");
8367
  if (fg[fg_aryl_chloride - 1])
8368
    printf ("aryl chloride\n");
8369
  if (fg[fg_aryl_bromide - 1])
8370
    printf ("aryl bromide\n");
8371
  if (fg[fg_aryl_iodide - 1])
8372
    printf ("aryl iodide\n");
8373
  if (fg[fg_organometallic - 1])
8374
    printf ("organometallic compound\n");
8375
  if (fg[fg_organolithium - 1])
8376
    printf ("organolithium compound\n");
8377
  if (fg[fg_organomagnesium - 1])
8378
    printf ("organomagnesium compound\n");
8379
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
8380
  if (fg[fg_carboxylic_acid - 1])
8381
    printf ("carboxylic acid\n");
8382
  if (fg[fg_carboxylic_acid_salt - 1])
8383
    printf ("carboxylic acid salt\n");
8384
  if (fg[fg_carboxylic_acid_ester - 1])
8385
    printf ("carboxylic acid ester\n");
8386
  if (fg[fg_lactone - 1])
8387
    printf ("lactone\n");
8388
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
8389
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8390
    printf ("primary carboxylic acid amide\n");
8391
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8392
    printf ("secondary carboxylic acid amide\n");
8393
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8394
    printf ("tertiary carboxylic acid amide\n");
8395
  if (fg[fg_lactam - 1])
8396
    printf ("lactam\n");
8397
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8398
    printf ("carboxylic acid hydrazide\n");
8399
  if (fg[fg_carboxylic_acid_azide - 1])
8400
    printf ("carboxylic acid azide\n");
8401
  if (fg[fg_hydroxamic_acid - 1])
8402
    printf ("hydroxamic acid\n");
8403
  if (fg[fg_carboxylic_acid_amidine - 1])
8404
    printf ("carboxylic acid amidine\n");
8405
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8406
    printf ("carboxylic acid amidrazone\n");
8407
  if (fg[fg_nitrile - 1])
8408
    printf ("carbonitrile\n");
8409
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
8410
  if (fg[fg_acyl_fluoride - 1])
8411
    printf ("acyl fluoride\n");
8412
  if (fg[fg_acyl_chloride - 1])
8413
    printf ("acyl chloride\n");
8414
  if (fg[fg_acyl_bromide - 1])
8415
    printf ("acyl bromide\n");
8416
  if (fg[fg_acyl_iodide - 1])
8417
    printf ("acyl iodide\n");
8418
  if (fg[fg_acyl_cyanide - 1])
8419
    printf ("acyl cyanide\n");
8420
  if (fg[fg_imido_ester - 1])
8421
    printf ("imido ester\n");
8422
  if (fg[fg_imidoyl_halide - 1])
8423
    printf ("imidoyl halide\n");
8424
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
8425
  if (fg[fg_thiocarboxylic_acid - 1])
8426
    printf ("thiocarboxylic acid\n");
8427
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8428
    printf ("thiocarboxylic acid ester\n");
8429
  if (fg[fg_thiolactone - 1])
8430
    printf ("thiolactone\n");
8431
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8432
    printf ("thiocarboxylic acid amide\n");
8433
  if (fg[fg_thiolactam - 1])
8434
    printf ("thiolactam\n");
8435
  if (fg[fg_imido_thioester - 1])
8436
    printf ("imidothioester\n");
8437
  if (fg[fg_oxohetarene - 1])
8438
    printf ("oxo(het)arene\n");
8439
  if (fg[fg_thioxohetarene - 1])
8440
    printf ("thioxo(het)arene\n");
8441
  if (fg[fg_iminohetarene - 1])
8442
    printf ("imino(het)arene\n");
8443
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8444
    printf ("orthocarboxylic acid derivative\n");
8445
  if (fg[fg_carboxylic_acid_orthoester - 1])
8446
    printf ("orthoester\n");
8447
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8448
    printf ("amide acetal\n");
8449
  if (fg[fg_carboxylic_acid_anhydride - 1])
8450
    printf ("carboxylic acid anhydride\n");
8451
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
8452
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8453
    printf ("carboxylic acid imide, N-unsubstituted\n");
8454
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8455
    printf ("carboxylic acid imide, N-substituted\n");
8456
  if (fg[fg_co2_deriv - 1])
8457
    printf ("CO2 derivative (general)\n");
8458
  if (fg[fg_carbonic_acid_deriv - 1] &&
8459
      !(fg[fg_carbonic_acid_monoester - 1]
8460
        || fg[fg_carbonic_acid_diester - 1]
8461
        || fg[fg_carbonic_acid_ester_halide - 1]))
8462
    /* changed in v0.3c */
8463
    printf ("carbonic acid derivative\n");
8464
  if (fg[fg_carbonic_acid_monoester - 1])
8465
    printf ("carbonic acid monoester\n");
8466
  if (fg[fg_carbonic_acid_diester - 1])
8467
    printf ("carbonic acid diester\n");
8468
  if (fg[fg_carbonic_acid_ester_halide - 1])
8469
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
8470
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8471
    printf ("thiocarbonic acid derivative\n");
8472
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8473
    printf ("thiocarbonic acid monoester\n");
8474
  if (fg[fg_thiocarbonic_acid_diester - 1])
8475
    printf ("thiocarbonic acid diester\n");
8476
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
8477
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
8478
  if (fg[fg_carbamic_acid_deriv - 1]
8479
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
8480
           || fg[fg_carbamic_acid_halide - 1]))
8481
    /* changed in v0.3c */
8482
    printf ("carbamic acid derivative\n");
8483
  if (fg[fg_carbamic_acid - 1])
8484
    printf ("carbamic acid\n");
8485
  if (fg[fg_carbamic_acid_ester - 1])
8486
    printf ("carbamic acid ester (urethane)\n");
8487
  if (fg[fg_carbamic_acid_halide - 1])
8488
    printf ("carbamic acid halide (haloformic acid amide)\n");
8489
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8490
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
8491
        || fg[fg_thiocarbamic_acid_halide - 1]))
8492
    /* changed in v0.3c */
8493
    printf ("thiocarbamic acid derivative\n");
8494
  if (fg[fg_thiocarbamic_acid - 1])
8495
    printf ("thiocarbamic acid\n");
8496
  if (fg[fg_thiocarbamic_acid_ester - 1])
8497
    printf ("thiocarbamic acid ester\n");
8498
  if (fg[fg_thiocarbamic_acid_halide - 1])
8499
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
8500
  if (fg[fg_urea - 1])
8501
    printf ("urea\n");
8502
  if (fg[fg_isourea - 1])
8503
    printf ("isourea\n");
8504
  if (fg[fg_thiourea - 1])
8505
    printf ("thiourea\n");
8506
  if (fg[fg_isothiourea - 1])
8507
    printf ("isothiourea\n");
8508
  if (fg[fg_guanidine - 1])
8509
    printf ("guanidine\n");
8510
  if (fg[fg_semicarbazide - 1])
8511
    printf ("semicarbazide\n");
8512
  if (fg[fg_thiosemicarbazide - 1])
8513
    printf ("thiosemicarbazide\n");
8514
  if (fg[fg_azide - 1])
8515
    printf ("azide\n");
8516
  if (fg[fg_azo_compound - 1])
8517
    printf ("azo compound\n");
8518
  if (fg[fg_diazonium_salt - 1])
8519
    printf ("diazonium salt\n");
8520
  if (fg[fg_isonitrile - 1])
8521
    printf ("isonitrile\n");
8522
  if (fg[fg_cyanate - 1])
8523
    printf ("cyanate\n");
8524
  if (fg[fg_isocyanate - 1])
8525
    printf ("isocyanate\n");
8526
  if (fg[fg_thiocyanate - 1])
8527
    printf ("thiocyanate\n");
8528
  if (fg[fg_isothiocyanate - 1])
8529
    printf ("isothiocyanate\n");
8530
  if (fg[fg_carbodiimide - 1])
8531
    printf ("carbodiimide\n");
8532
  if (fg[fg_nitroso_compound - 1])
8533
    printf ("nitroso compound\n");
8534
  if (fg[fg_nitro_compound - 1])
8535
    printf ("nitro compound\n");
8536
  if (fg[fg_nitrite - 1])
8537
    printf ("nitrite\n");
8538
  if (fg[fg_nitrate - 1])
8539
    printf ("nitrate\n");
8540
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
8541
  if (fg[fg_sulfuric_acid - 1])
8542
    printf ("sulfuric acid\n");
8543
  if (fg[fg_sulfuric_acid_monoester - 1])
8544
    printf ("sulfuric acid monoester\n");
8545
  if (fg[fg_sulfuric_acid_diester - 1])
8546
    printf ("sulfuric acid diester\n");
8547
  if (fg[fg_sulfuric_acid_amide_ester - 1])
8548
    printf ("sulfuric acid amide ester\n");
8549
  if (fg[fg_sulfuric_acid_amide - 1])
8550
    printf ("sulfuric acid amide\n");
8551
  if (fg[fg_sulfuric_acid_diamide - 1])
8552
    printf ("sulfuric acid diamide\n");
8553
  if (fg[fg_sulfuryl_halide - 1])
8554
    printf ("sulfuryl halide\n");
8555
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
8556
  if (fg[fg_sulfonic_acid - 1])
8557
    printf ("sulfonic acid\n");
8558
  if (fg[fg_sulfonic_acid_ester - 1])
8559
    printf ("sulfonic acid ester\n");
8560
  if (fg[fg_sulfonamide - 1])
8561
    printf ("sulfonamide\n");
8562
  if (fg[fg_sulfonyl_halide - 1])
8563
    printf ("sulfonyl halide\n");
8564
  if (fg[fg_sulfone - 1])
8565
    printf ("sulfone\n");
8566
  if (fg[fg_sulfoxide - 1])
8567
    printf ("sulfoxide\n");
8568
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
8569
  if (fg[fg_sulfinic_acid - 1])
8570
    printf ("sulfinic acid\n");
8571
  if (fg[fg_sulfinic_acid_ester - 1])
8572
    printf ("sulfinic acid ester\n");
8573
  if (fg[fg_sulfinic_acid_halide - 1])
8574
    printf ("sulfinic acid halide\n");
8575
  if (fg[fg_sulfinic_acid_amide - 1])
8576
    printf ("sulfinic acid amide\n");
8577
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
8578
  if (fg[fg_sulfenic_acid - 1])
8579
    printf ("sulfenic acid\n");
8580
  if (fg[fg_sulfenic_acid_ester - 1])
8581
    printf ("sulfenic acid ester\n");
8582
  if (fg[fg_sulfenic_acid_halide - 1])
8583
    printf ("sulfenic acid halide\n");
8584
  if (fg[fg_sulfenic_acid_amide - 1])
8585
    printf ("sulfenic acid amide\n");
8586
  if (fg[fg_thiol - 1])
8587
    printf ("thiol (sulfanyl compound)\n");
8588
  if (fg[fg_alkylthiol - 1])
8589
    printf ("alkylthiol\n");
8590
  if (fg[fg_arylthiol - 1])
8591
    printf ("arylthiol\n");
8592
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
8593
  if (fg[fg_phosphoric_acid - 1])
8594
    printf ("phosphoric acid\n");
8595
  if (fg[fg_phosphoric_acid_ester - 1])
8596
    printf ("phosphoric acid ester\n");
8597
  if (fg[fg_phosphoric_acid_halide - 1])
8598
    printf ("phosphoric acid halide\n");
8599
  if (fg[fg_phosphoric_acid_amide - 1])
8600
    printf ("phosphoric acid amide\n");
8601
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
8602
  if (fg[fg_thiophosphoric_acid - 1])
8603
    printf ("thiophosphoric acid\n");
8604
  if (fg[fg_thiophosphoric_acid_ester - 1])
8605
    printf ("thiophosphoric acid ester\n");
8606
  if (fg[fg_thiophosphoric_acid_halide - 1])
8607
    printf ("thiophosphoric acid halide\n");
8608
  if (fg[fg_thiophosphoric_acid_amide - 1])
8609
    printf ("thiophosphoric acid amide\n");
8610
  if (fg[fg_phosphonic_acid_deriv - 1])
8611
    printf ("phosphonic acid derivative \n");
8612
  if (fg[fg_phosphonic_acid - 1])
8613
    printf ("phosphonic acid\n");
8614
  if (fg[fg_phosphonic_acid_ester - 1])
8615
    printf ("phosphonic acid ester\n");
8616
  if (fg[fg_phosphine - 1])
8617
    printf ("phosphine\n");
8618
  if (fg[fg_phosphinoxide - 1])
8619
    printf ("phosphine oxide\n");
8620
  if (fg[fg_boronic_acid_deriv - 1])
8621
    printf ("boronic acid derivative\n");
8622
  if (fg[fg_boronic_acid - 1])
8623
    printf ("boronic acid\n");
8624
  if (fg[fg_boronic_acid_ester - 1])
8625
    printf ("boronic acid ester\n");
8626
  if (fg[fg_alkene - 1])
8627
    printf ("alkene\n");
8628
  if (fg[fg_alkyne - 1])
8629
    printf ("alkyne\n");
8630
  if (fg[fg_aromatic - 1])
8631
    printf ("aromatic compound\n");
8632
  if (fg[fg_heterocycle - 1])
8633
    printf ("heterocyclic compound\n");
8634
  if (fg[fg_alpha_aminoacid - 1])
8635
    printf ("alpha-aminoacid\n");
8636
  if (fg[fg_alpha_hydroxyacid - 1])
8637
    printf ("alpha-hydroxyacid\n");
8638
}
8639
 
14179 bpr 8640
static void write_fg_text_de ()
6785 bpr 8641
{
8642
  if (fg[fg_cation - 1])
8643
    printf ("Kation\n");
8644
  if (fg[fg_anion - 1])
8645
    printf ("Anion\n");
8646
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
8647
  if (fg[fg_aldehyde - 1])
8648
    printf ("Aldehyd\n");
8649
  if (fg[fg_ketone - 1])
8650
    printf ("Keton\n");
8651
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
8652
  if (fg[fg_thioaldehyde - 1])
8653
    printf ("Thioaldehyd\n");
8654
  if (fg[fg_thioketone - 1])
8655
    printf ("Thioketon\n");
8656
  if (fg[fg_imine - 1])
8657
    printf ("Imin\n");
8658
  if (fg[fg_hydrazone - 1])
8659
    printf ("Hydrazon\n");
8660
  if (fg[fg_semicarbazone - 1])
8661
    printf ("Semicarbazon\n");
8662
  if (fg[fg_thiosemicarbazone - 1])
8663
    printf ("Thiosemicarbazon\n");
8664
  if (fg[fg_oxime - 1])
8665
    printf ("Oxim\n");
8666
  if (fg[fg_oxime_ether - 1])
8667
    printf ("Oximether\n");
8668
  if (fg[fg_ketene - 1])
8669
    printf ("Keten\n");
8670
  if (fg[fg_ketene_acetal_deriv - 1])
8671
    printf ("Keten-Acetal oder Derivat\n");
8672
  if (fg[fg_carbonyl_hydrate - 1])
8673
    printf ("Carbonyl-Hydrat\n");
8674
  if (fg[fg_hemiacetal - 1])
8675
    printf ("Halbacetal\n");
8676
  if (fg[fg_acetal - 1])
8677
    printf ("Acetal\n");
8678
  if (fg[fg_hemiaminal - 1])
8679
    printf ("Halbaminal\n");
8680
  if (fg[fg_aminal - 1])
8681
    printf ("Aminal\n");
8682
  if (fg[fg_thiohemiaminal - 1])
8683
    printf ("Thiohalbaminal\n");
8684
  if (fg[fg_thioacetal - 1])
8685
    printf ("Thioacetal\n");
8686
  if (fg[fg_enamine - 1])
8687
    printf ("Enamin\n");
8688
  if (fg[fg_enol - 1])
8689
    printf ("Enol\n");
8690
  if (fg[fg_enolether - 1])
8691
    printf ("Enolether\n");
8692
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8693
    printf ("Hydroxy-Verbindung\n");
8694
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
8695
  if (fg[fg_prim_alcohol - 1])
8696
    printf ("prim\344rer Alkohol\n");
14179 bpr 8697
  /* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
6785 bpr 8698
  if (fg[fg_sec_alcohol - 1])
8699
    printf ("sekund\344rer Alkohol\n");
14179 bpr 8700
  /* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
6785 bpr 8701
  if (fg[fg_tert_alcohol - 1])
8702
    printf ("terti\344rer Alkohol\n");
14179 bpr 8703
  /* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
6785 bpr 8704
  if (fg[fg_1_2_diol - 1])
8705
    printf ("1,2-Diol\n");
8706
  if (fg[fg_1_2_aminoalcohol - 1])
8707
    printf ("1,2-Aminoalkohol\n");
8708
  if (fg[fg_phenol - 1])
8709
    printf ("Phenol oder Hydroxyhetaren\n");
8710
  if (fg[fg_1_2_diphenol - 1])
8711
    printf ("1,2-Diphenol\n");
8712
  if (fg[fg_enediol - 1])
8713
    printf ("Endiol\n");
8714
  if (fg[fg_ether - 1] && ether_generic)
8715
    printf ("Ether\n");
8716
  if (fg[fg_dialkylether - 1])
8717
    printf ("Dialkylether\n");
8718
  if (fg[fg_alkylarylether - 1])
8719
    printf ("Alkylarylether \n");
8720
  if (fg[fg_diarylether - 1])
8721
    printf ("Diarylether\n");
8722
  if (fg[fg_thioether - 1])
8723
    printf ("Thioether\n");
8724
  if (fg[fg_disulfide - 1])
8725
    printf ("Disulfid\n");
8726
  if (fg[fg_peroxide - 1])
8727
    printf ("Peroxid\n");
8728
  if (fg[fg_hydroperoxide - 1])
8729
    printf ("Hydroperoxid\n");
8730
  if (fg[fg_hydrazine - 1])
8731
    printf ("Hydrazin-Derivat\n");
8732
  if (fg[fg_hydroxylamine - 1])
8733
    printf ("Hydroxylamin\n");
8734
  if (fg[fg_amine - 1] && amine_generic)
8735
    printf ("Amin\n");
8736
  if (fg[fg_prim_amine - 1])
8737
    printf ("prim\344res Amin\n");
14179 bpr 8738
  /* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
6785 bpr 8739
  if (fg[fg_prim_aliph_amine - 1])
8740
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
14179 bpr 8741
  /* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
6785 bpr 8742
  if (fg[fg_prim_arom_amine - 1])
8743
    printf ("prim\344res aromatisches Amin\n");
14179 bpr 8744
  /* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
6785 bpr 8745
  if (fg[fg_sec_amine - 1])
8746
    printf ("sekund\344res Amin\n");
14179 bpr 8747
  /* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
6785 bpr 8748
  if (fg[fg_sec_aliph_amine - 1])
8749
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
14179 bpr 8750
  /* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
6785 bpr 8751
  if (fg[fg_sec_mixed_amine - 1])
8752
    printf
8753
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8754
  /* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
6785 bpr 8755
  if (fg[fg_sec_arom_amine - 1])
8756
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
14179 bpr 8757
  /* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
6785 bpr 8758
  if (fg[fg_tert_amine - 1])
8759
    printf ("terti\344res Amin\n");
14179 bpr 8760
  /* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
6785 bpr 8761
  if (fg[fg_tert_aliph_amine - 1])
8762
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
14179 bpr 8763
  /* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
6785 bpr 8764
  if (fg[fg_tert_mixed_amine - 1])
8765
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8766
  /* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
6785 bpr 8767
  if (fg[fg_tert_arom_amine - 1])
8768
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
14179 bpr 8769
  /* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
6785 bpr 8770
  if (fg[fg_quart_ammonium - 1])
8771
    printf ("quart\344res Ammoniumsalz\n");
14179 bpr 8772
  /* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
6785 bpr 8773
  if (fg[fg_n_oxide - 1])
8774
    printf ("N-Oxid\n");
8775
  /* new in v0.2f */
14179 bpr 8776
  if (fg[fg_halogen_deriv - 1]) {
8777
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
8778
              !fg[fg_acyl_halide - 1])
8779
            printf ("Halogenverbindung\n");
8780
  }
6785 bpr 8781
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
8782
  if (fg[fg_alkyl_fluoride - 1])
8783
    printf ("Alkylfluorid\n");
8784
  if (fg[fg_alkyl_chloride - 1])
8785
    printf ("Alkylchlorid\n");
8786
  if (fg[fg_alkyl_bromide - 1])
8787
    printf ("Alkylbromid\n");
8788
  if (fg[fg_alkyl_iodide - 1])
8789
    printf ("Alkyliodid\n");
8790
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
8791
  if (fg[fg_aryl_fluoride - 1])
8792
    printf ("Arylfluorid\n");
8793
  if (fg[fg_aryl_chloride - 1])
8794
    printf ("Arylchlorid\n");
8795
  if (fg[fg_aryl_bromide - 1])
8796
    printf ("Arylbromid\n");
8797
  if (fg[fg_aryl_iodide - 1])
8798
    printf ("Aryliodid\n");
8799
  if (fg[fg_organometallic - 1])
8800
    printf ("Organometall-Verbindung\n");
8801
  if (fg[fg_organolithium - 1])
8802
    printf ("Organolithium-Verbindung\n");
8803
  if (fg[fg_organomagnesium - 1])
8804
    printf ("Organomagnesium-Verbindung\n");
8805
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
8806
  if (fg[fg_carboxylic_acid - 1])
8807
    printf ("Carbons\344ure\n");
14179 bpr 8808
  /* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
6785 bpr 8809
  if (fg[fg_carboxylic_acid_salt - 1])
8810
    printf ("Carbons\344uresalz\n");
14179 bpr 8811
  /* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
6785 bpr 8812
  if (fg[fg_carboxylic_acid_ester - 1])
8813
    printf ("Carbons\344ureester\n");
14179 bpr 8814
  /* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
6785 bpr 8815
  if (fg[fg_lactone - 1])
8816
    printf ("Lacton\n");
8817
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
8818
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8819
    printf ("prim\344res Carbons\344ureamid\n");
14179 bpr 8820
  /* p2c: checkmol.pas, line 7340:
8821
  * Note: characters >= 128 encountered [281] */
6785 bpr 8822
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8823
    printf ("sekund\344res Carbons\344ureamid\n");
14179 bpr 8824
  /* p2c: checkmol.pas, line 7341:
8825
  * Note: characters >= 128 encountered [281] */
6785 bpr 8826
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8827
    printf ("terti\344res Carbons\344ureamid\n");
14179 bpr 8828
  /* p2c: checkmol.pas, line 7342:
8829
  * Note: characters >= 128 encountered [281] */
6785 bpr 8830
  if (fg[fg_lactam - 1])
8831
    printf ("Lactam\n");
8832
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8833
    printf ("Carbons\344urehydrazid\n");
14179 bpr 8834
  /* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
6785 bpr 8835
  if (fg[fg_carboxylic_acid_azide - 1])
8836
    printf ("Carbons\344ureazid\n");
14179 bpr 8837
  /* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
6785 bpr 8838
  if (fg[fg_hydroxamic_acid - 1])
8839
    printf ("Hydroxams\344ure\n");
14179 bpr 8840
  /* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
6785 bpr 8841
  if (fg[fg_carboxylic_acid_amidine - 1])
8842
    printf ("Carbons\344ureamidin\n");
14179 bpr 8843
  /* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
6785 bpr 8844
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8845
    printf ("Carbons\344ureamidrazon\n");
14179 bpr 8846
  /* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
6785 bpr 8847
  if (fg[fg_nitrile - 1])
8848
    printf ("Carbonitril\n");
8849
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
8850
  if (fg[fg_acyl_fluoride - 1])
8851
    printf ("Acylfluorid\n");
8852
  if (fg[fg_acyl_chloride - 1])
8853
    printf ("Acylchlorid\n");
8854
  if (fg[fg_acyl_bromide - 1])
8855
    printf ("Acylbromid\n");
8856
  if (fg[fg_acyl_iodide - 1])
8857
    printf ("Acyliodid\n");
8858
  if (fg[fg_acyl_cyanide - 1])
8859
    printf ("Acylcyanid\n");
8860
  if (fg[fg_imido_ester - 1])
8861
    printf ("Imidoester\n");
8862
  if (fg[fg_imidoyl_halide - 1])
8863
    printf ("Imidoylhalogenid\n");
8864
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
8865
  if (fg[fg_thiocarboxylic_acid - 1])
8866
    printf ("Thiocarbons\344ure\n");
14179 bpr 8867
  /* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
6785 bpr 8868
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8869
    printf ("Thiocarbons\344ureester\n");
14179 bpr 8870
  /* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
6785 bpr 8871
  if (fg[fg_thiolactone - 1])
8872
    printf ("Thiolacton\n");
8873
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8874
    printf ("Thiocarbons\344ureamid\n");
14179 bpr 8875
  /* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
6785 bpr 8876
  if (fg[fg_thiolactam - 1])
8877
    printf ("Thiolactam\n");
8878
  if (fg[fg_imido_thioester - 1])
8879
    printf ("Imidothioester\n");
8880
  if (fg[fg_oxohetarene - 1])
8881
    printf ("Oxo(het)aren\n");
8882
  if (fg[fg_thioxohetarene - 1])
8883
    printf ("Thioxo(het)aren\n");
8884
  if (fg[fg_iminohetarene - 1])
8885
    printf ("Imino(het)aren\n");
8886
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8887
    printf ("Orthocarbons\344ure-Derivat\n");
14179 bpr 8888
  /* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
6785 bpr 8889
  if (fg[fg_carboxylic_acid_orthoester - 1])
8890
    printf ("Orthoester\n");
8891
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8892
    printf ("Amidacetal\n");
8893
  if (fg[fg_carboxylic_acid_anhydride - 1])
8894
    printf ("Carbons\344ureanhydrid\n");
14179 bpr 8895
  /* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
6785 bpr 8896
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
8897
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8898
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
14179 bpr 8899
  /* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
6785 bpr 8900
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8901
    printf ("Carbons\344ureimid, N-substituiert\n");
14179 bpr 8902
  /* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
6785 bpr 8903
  if (fg[fg_co2_deriv - 1])
8904
    printf ("CO2-Derivat (allgemein)\n");
14179 bpr 8905
  if (fg[fg_carbonic_acid_deriv - 1] && !(fg[fg_carbonic_acid_monoester - 1]
8906
            || fg[fg_carbonic_acid_diester - 1] || fg[fg_carbonic_acid_ester_halide - 1]))
6785 bpr 8907
    /* changed in v0.3c */
8908
    printf ("Kohlens\344ure-Derivat\n");
14179 bpr 8909
  /* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
6785 bpr 8910
  if (fg[fg_carbonic_acid_monoester - 1])
8911
    printf ("Kohlens\344uremonoester\n");
14179 bpr 8912
  /* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
6785 bpr 8913
  if (fg[fg_carbonic_acid_diester - 1])
8914
    printf ("Kohlens\344urediester\n");
14179 bpr 8915
  /* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
6785 bpr 8916
  if (fg[fg_carbonic_acid_ester_halide - 1])
8917
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
14179 bpr 8918
  /* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
6785 bpr 8919
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8920
    printf ("Thiokohlens\344ure-Derivat\n");
14179 bpr 8921
  /* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
6785 bpr 8922
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8923
    printf ("Thiokohlens\344uremonoester\n");
14179 bpr 8924
  /* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
6785 bpr 8925
  if (fg[fg_thiocarbonic_acid_diester - 1])
8926
    printf ("Thiokohlens\344urediester\n");
14179 bpr 8927
  /* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
6785 bpr 8928
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
14179 bpr 8929
    printf ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
8930
  /* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
6785 bpr 8931
  if (fg[fg_carbamic_acid_deriv - 1] &&
8932
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
14179 bpr 8933
            fg[fg_carbamic_acid_halide - 1]))
6785 bpr 8934
    /* changed in v0.3c */
8935
    printf ("Carbamins\344ure-Derivat\n");
14179 bpr 8936
  /* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
6785 bpr 8937
  if (fg[fg_carbamic_acid - 1])
8938
    printf ("Carbamins\344ure\n");
14179 bpr 8939
  /* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
6785 bpr 8940
  if (fg[fg_carbamic_acid_ester - 1])
8941
    printf ("Carbamins\344ureester (Urethan)\n");
14179 bpr 8942
  /* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
6785 bpr 8943
  if (fg[fg_carbamic_acid_halide - 1])
8944
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
14179 bpr 8945
  /* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
6785 bpr 8946
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8947
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
14179 bpr 8948
            || fg[fg_thiocarbamic_acid_halide - 1]))
6785 bpr 8949
    /* changed in v0.3c */
8950
    printf ("Thiocarbamins\344ure-Derivat\n");
14179 bpr 8951
  /* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
6785 bpr 8952
  if (fg[fg_thiocarbamic_acid - 1])
8953
    printf ("Thiocarbamins\344ure\n");
14179 bpr 8954
  /* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
6785 bpr 8955
  if (fg[fg_thiocarbamic_acid_ester - 1])
8956
    printf ("Thiocarbamins\344ureester\n");
14179 bpr 8957
  /* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
6785 bpr 8958
  if (fg[fg_thiocarbamic_acid_halide - 1])
8959
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
14179 bpr 8960
  /* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
6785 bpr 8961
  if (fg[fg_urea - 1])
8962
    printf ("Harnstoff\n");
8963
  if (fg[fg_isourea - 1])
8964
    printf ("Isoharnstoff\n");
8965
  if (fg[fg_thiourea - 1])
8966
    printf ("Thioharnstoff\n");
8967
  if (fg[fg_isothiourea - 1])
8968
    printf ("Isothioharnstoff\n");
8969
  if (fg[fg_guanidine - 1])
8970
    printf ("Guanidin\n");
8971
  if (fg[fg_semicarbazide - 1])
8972
    printf ("Semicarbazid\n");
8973
  if (fg[fg_thiosemicarbazide - 1])
8974
    printf ("Thiosemicarbazid\n");
8975
  if (fg[fg_azide - 1])
8976
    printf ("Azid\n");
8977
  if (fg[fg_azo_compound - 1])
8978
    printf ("Azoverbindung\n");
8979
  if (fg[fg_diazonium_salt - 1])
8980
    printf ("Diazoniumsalz\n");
8981
  if (fg[fg_isonitrile - 1])
8982
    printf ("Isonitril\n");
8983
  if (fg[fg_cyanate - 1])
8984
    printf ("Cyanat\n");
8985
  if (fg[fg_isocyanate - 1])
8986
    printf ("Isocyanat\n");
8987
  if (fg[fg_thiocyanate - 1])
8988
    printf ("Thiocyanat\n");
8989
  if (fg[fg_isothiocyanate - 1])
8990
    printf ("Isothiocyanat\n");
8991
  if (fg[fg_carbodiimide - 1])
8992
    printf ("Carbodiimid\n");
8993
  if (fg[fg_nitroso_compound - 1])
8994
    printf ("Nitroso-Verbindung\n");
8995
  if (fg[fg_nitro_compound - 1])
8996
    printf ("Nitro-Verbindung\n");
8997
  if (fg[fg_nitrite - 1])
8998
    printf ("Nitrit\n");
8999
  if (fg[fg_nitrate - 1])
9000
    printf ("Nitrat\n");
9001
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
9002
  if (fg[fg_sulfuric_acid - 1])
9003
    printf ("Schwefels\344ure\n");
14179 bpr 9004
  /* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
6785 bpr 9005
  if (fg[fg_sulfuric_acid_monoester - 1])
9006
    printf ("Schwefels\344uremonoester\n");
14179 bpr 9007
  /* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
6785 bpr 9008
  if (fg[fg_sulfuric_acid_diester - 1])
9009
    printf ("Schwefels\344urediester\n");
14179 bpr 9010
  /* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
6785 bpr 9011
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9012
    printf ("Schwefels\344ureamidester\n");
14179 bpr 9013
  /* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
6785 bpr 9014
  if (fg[fg_sulfuric_acid_amide - 1])
9015
    printf ("Schwefels\344ureamid\n");
14179 bpr 9016
  /* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
6785 bpr 9017
  if (fg[fg_sulfuric_acid_diamide - 1])
9018
    printf ("Schwefels\344urediamid\n");
14179 bpr 9019
  /* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
6785 bpr 9020
  if (fg[fg_sulfuryl_halide - 1])
9021
    printf ("Sulfurylhalogenid\n");
9022
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
9023
  if (fg[fg_sulfonic_acid - 1])
9024
    printf ("Sulfons\344ure\n");
14179 bpr 9025
  /* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
6785 bpr 9026
  if (fg[fg_sulfonic_acid_ester - 1])
9027
    printf ("Sulfons\344ureester\n");
14179 bpr 9028
  /* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
6785 bpr 9029
  if (fg[fg_sulfonamide - 1])
9030
    printf ("Sulfonamid\n");
9031
  if (fg[fg_sulfonyl_halide - 1])
9032
    printf ("Sulfonylhalogenid\n");
9033
  if (fg[fg_sulfone - 1])
9034
    printf ("Sulfon\n");
9035
  if (fg[fg_sulfoxide - 1])
9036
    printf ("Sulfoxid\n");
9037
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
9038
  if (fg[fg_sulfinic_acid - 1])
9039
    printf ("Sulfins\344ure\n");
14179 bpr 9040
  /* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
6785 bpr 9041
  if (fg[fg_sulfinic_acid_ester - 1])
9042
    printf ("Sulfins\344ureester\n");
14179 bpr 9043
  /* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
6785 bpr 9044
  if (fg[fg_sulfinic_acid_halide - 1])
9045
    printf ("Sulfins\344urehalogenid\n");
14179 bpr 9046
  /* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
6785 bpr 9047
  if (fg[fg_sulfinic_acid_amide - 1])
9048
    printf ("Sulfins\344ureamid\n");
14179 bpr 9049
  /* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
6785 bpr 9050
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
9051
  if (fg[fg_sulfenic_acid - 1])
9052
    printf ("Sulfens\344ure\n");
14179 bpr 9053
  /* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
6785 bpr 9054
  if (fg[fg_sulfenic_acid_ester - 1])
9055
    printf ("Sulfens\344ureester\n");
14179 bpr 9056
  /* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
6785 bpr 9057
  if (fg[fg_sulfenic_acid_halide - 1])
9058
    printf ("Sulfens\344urehalogenid\n");
14179 bpr 9059
  /* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
6785 bpr 9060
  if (fg[fg_sulfenic_acid_amide - 1])
9061
    printf ("Sulfens\344ureamid\n");
14179 bpr 9062
  /* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
6785 bpr 9063
  if (fg[fg_thiol - 1])
9064
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
9065
  if (fg[fg_alkylthiol - 1])
9066
    printf ("Alkylthiol\n");
9067
  if (fg[fg_arylthiol - 1])
9068
    printf ("Arylthiol\n");
9069
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
9070
  if (fg[fg_phosphoric_acid - 1])
9071
    printf ("Phosphors\344ure\n");
14179 bpr 9072
  /* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
6785 bpr 9073
  if (fg[fg_phosphoric_acid_ester - 1])
9074
    printf ("Phosphors\344ureester\n");
14179 bpr 9075
  /* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
6785 bpr 9076
  if (fg[fg_phosphoric_acid_halide - 1])
9077
    printf ("Phosphors\344urehalogenid\n");
14179 bpr 9078
  /* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
6785 bpr 9079
  if (fg[fg_phosphoric_acid_amide - 1])
9080
    printf ("Phosphors\344ureamid\n");
14179 bpr 9081
  /* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
6785 bpr 9082
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
9083
  if (fg[fg_thiophosphoric_acid - 1])
9084
    printf ("Thiophosphors\344ure\n");
14179 bpr 9085
  /* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
6785 bpr 9086
  if (fg[fg_thiophosphoric_acid_ester - 1])
9087
    printf ("Thiophosphors\344ureester\n");
14179 bpr 9088
  /* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
6785 bpr 9089
  if (fg[fg_thiophosphoric_acid_halide - 1])
9090
    printf ("Thiophosphors\344urehalogenid\n");
14179 bpr 9091
  /* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
6785 bpr 9092
  if (fg[fg_thiophosphoric_acid_amide - 1])
9093
    printf ("Thiophosphors\344ureamid\n");
14179 bpr 9094
  /* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
6785 bpr 9095
  if (fg[fg_phosphonic_acid_deriv - 1])
9096
    printf ("Phosphons\344ure-Derivat \n");
14179 bpr 9097
  /* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
6785 bpr 9098
  if (fg[fg_phosphonic_acid - 1])
9099
    printf ("Phosphons\344ure\n");
14179 bpr 9100
  /* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
6785 bpr 9101
  if (fg[fg_phosphonic_acid_ester - 1])
9102
    printf ("Phosphons\344ureester\n");
14179 bpr 9103
  /* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
6785 bpr 9104
  if (fg[fg_phosphine - 1])
9105
    printf ("Phosphin\n");
9106
  if (fg[fg_phosphinoxide - 1])
9107
    printf ("Phosphinoxid\n");
9108
  if (fg[fg_boronic_acid_deriv - 1])
9109
    printf ("Borons\344ure-Derivat\n");
14179 bpr 9110
  /* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
6785 bpr 9111
  if (fg[fg_boronic_acid - 1])
9112
    printf ("Borons\344ure\n");
14179 bpr 9113
  /* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
6785 bpr 9114
  if (fg[fg_boronic_acid_ester - 1])
9115
    printf ("Borons\344ureester\n");
14179 bpr 9116
  /* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
6785 bpr 9117
  if (fg[fg_alkene - 1])
9118
    printf ("Alken\n");
9119
  if (fg[fg_alkyne - 1])
9120
    printf ("Alkin\n");
9121
  if (fg[fg_aromatic - 1])
9122
    printf ("aromatische Verbindung\n");
9123
  if (fg[fg_heterocycle - 1])
9124
    printf ("heterocyclische Verbindung\n");
9125
  if (fg[fg_alpha_aminoacid - 1])
9126
    printf ("alpha-Aminos\344ure\n");
14179 bpr 9127
  /* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
6785 bpr 9128
  if (fg[fg_alpha_hydroxyacid - 1])
9129
    printf ("alpha-Hydroxys\344ure\n");
14179 bpr 9130
  /* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
6785 bpr 9131
}
9132
 
9133
#define sc              ';'
9134
 
14179 bpr 9135
static void write_fg_code ()
6785 bpr 9136
{
9137
  if (fg[fg_cation - 1])
9138
    printf ("000000T2%c", sc);
9139
  if (fg[fg_anion - 1])
9140
    printf ("000000T1%c", sc);
9141
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
9142
  if (fg[fg_aldehyde - 1])
9143
    printf ("C2O1H000%c", sc);
9144
  if (fg[fg_ketone - 1])
9145
    printf ("C2O1C000%c", sc);
9146
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
9147
  if (fg[fg_thioaldehyde - 1])
9148
    printf ("C2S1H000%c", sc);
9149
  if (fg[fg_thioketone - 1])
9150
    printf ("C2S1C000%c", sc);
9151
  if (fg[fg_imine - 1])
9152
    printf ("C2N10000%c", sc);
9153
  if (fg[fg_hydrazone - 1])
9154
    printf ("C2N1N000%c", sc);
9155
  if (fg[fg_semicarbazone - 1])
9156
    printf ("C2NNC4ON%c", sc);
9157
  if (fg[fg_thiosemicarbazone - 1])
9158
    printf ("C2NNC4SN%c", sc);
9159
  if (fg[fg_oxime - 1])
9160
    printf ("C2N1OH00%c", sc);
9161
  if (fg[fg_oxime_ether - 1])
9162
    printf ("C2N1OC00%c", sc);
9163
  if (fg[fg_ketene - 1])
9164
    printf ("C3OC0000%c", sc);
9165
  if (fg[fg_ketene_acetal_deriv - 1])
9166
    printf ("C3OCC000%c", sc);
9167
  if (fg[fg_carbonyl_hydrate - 1])
9168
    printf ("C2O2H200%c", sc);
9169
  if (fg[fg_hemiacetal - 1])
9170
    printf ("C2O2HC00%c", sc);
9171
  if (fg[fg_acetal - 1])
9172
    printf ("C2O2CC00%c", sc);
9173
  if (fg[fg_hemiaminal - 1])
9174
    printf ("C2NOHC10%c", sc);
9175
  if (fg[fg_aminal - 1])
9176
    printf ("C2N2CC10%c", sc);
9177
  if (fg[fg_thiohemiaminal - 1])
9178
    printf ("C2NSHC10%c", sc);
9179
  if (fg[fg_thioacetal - 1])
9180
    printf ("C2S2CC00%c", sc);
9181
  if (fg[fg_enamine - 1])
9182
    printf ("C2CNH000%c", sc);
9183
  if (fg[fg_enol - 1])
9184
    printf ("C2COH000%c", sc);
9185
  if (fg[fg_enolether - 1])
9186
    printf ("C2COC000%c", sc);
9187
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9188
    printf ("O1H00000%c", sc);
9189
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
9190
  if (fg[fg_prim_alcohol - 1])
9191
    printf ("O1H1C000%c", sc);
9192
  if (fg[fg_sec_alcohol - 1])
9193
    printf ("O1H2C000%c", sc);
9194
  if (fg[fg_tert_alcohol - 1])
9195
    printf ("O1H3C000%c", sc);
9196
  if (fg[fg_1_2_diol - 1])
9197
    printf ("O1H0CO1H%c", sc);
9198
  if (fg[fg_1_2_aminoalcohol - 1])
9199
    printf ("O1H0CN1C%c", sc);
9200
  if (fg[fg_phenol - 1])
9201
    printf ("O1H1A000%c", sc);
9202
  if (fg[fg_1_2_diphenol - 1])
9203
    printf ("O1H2A000%c", sc);
9204
  if (fg[fg_enediol - 1])
9205
    printf ("C2COH200%c", sc);
9206
  if (fg[fg_ether - 1] && ether_generic)
9207
    printf ("O1C00000%c", sc);
9208
  if (fg[fg_dialkylether - 1])
9209
    printf ("O1C0CC00%c", sc);
9210
  if (fg[fg_alkylarylether - 1])
9211
    printf ("O1C0CA00%c", sc);
9212
  if (fg[fg_diarylether - 1])
9213
    printf ("O1C0AA00%c", sc);
9214
  if (fg[fg_thioether - 1])
9215
    printf ("S1C00000%c", sc);
9216
  if (fg[fg_disulfide - 1])
9217
    printf ("S1S1C000%c", sc);
9218
  if (fg[fg_peroxide - 1])
9219
    printf ("O1O1C000%c", sc);
9220
  if (fg[fg_hydroperoxide - 1])
9221
    printf ("O1O1H000%c", sc);
9222
  if (fg[fg_hydrazine - 1])
9223
    printf ("N1N10000%c", sc);
9224
  if (fg[fg_hydroxylamine - 1])
9225
    printf ("N1O1H000%c", sc);
9226
  if (fg[fg_amine - 1] && amine_generic)
9227
    printf ("N1C00000%c", sc);
9228
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
9229
  if (fg[fg_prim_aliph_amine - 1])
9230
    printf ("N1C1C000%c", sc);
9231
  if (fg[fg_prim_arom_amine - 1])
9232
    printf ("N1C1A000%c", sc);
9233
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
9234
  if (fg[fg_sec_aliph_amine - 1])
9235
    printf ("N1C2CC00%c", sc);
9236
  if (fg[fg_sec_mixed_amine - 1])
9237
    printf ("N1C2AC00%c", sc);
9238
  if (fg[fg_sec_arom_amine - 1])
9239
    printf ("N1C2AA00%c", sc);
9240
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
9241
  if (fg[fg_tert_aliph_amine - 1])
9242
    printf ("N1C3CC00%c", sc);
9243
  if (fg[fg_tert_mixed_amine - 1])
9244
    printf ("N1C3AC00%c", sc);
9245
  if (fg[fg_tert_arom_amine - 1])
9246
    printf ("N1C3AA00%c", sc);
9247
  if (fg[fg_quart_ammonium - 1])
9248
    printf ("N1C400T2%c", sc);
9249
  if (fg[fg_n_oxide - 1])
9250
    printf ("N0O10000%c", sc);
9251
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
9252
  /* new in v0.2f */
14179 bpr 9253
  if (fg[fg_halogen_deriv - 1]) {
9254
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1])
9255
              printf ("XX000000%c", sc);
9256
  }
6785 bpr 9257
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
9258
  if (fg[fg_alkyl_fluoride - 1])
9259
    printf ("XF00C000%c", sc);
9260
  if (fg[fg_alkyl_chloride - 1])
9261
    printf ("XC00C000%c", sc);
9262
  if (fg[fg_alkyl_bromide - 1])
9263
    printf ("XB00C000%c", sc);
9264
  if (fg[fg_alkyl_iodide - 1])
9265
    printf ("XI00C000%c", sc);
9266
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
9267
  if (fg[fg_aryl_fluoride - 1])
9268
    printf ("XF00A000%c", sc);
9269
  if (fg[fg_aryl_chloride - 1])
9270
    printf ("XC00A000%c", sc);
9271
  if (fg[fg_aryl_bromide - 1])
9272
    printf ("XB00A000%c", sc);
9273
  if (fg[fg_aryl_iodide - 1])
9274
    printf ("XI00A000%c", sc);
9275
  if (fg[fg_organometallic - 1])
9276
    printf ("000000MX%c", sc);
9277
  if (fg[fg_organolithium - 1])
9278
    printf ("000000ML%c", sc);
9279
  if (fg[fg_organomagnesium - 1])
9280
    printf ("000000MM%c", sc);
9281
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
9282
  if (fg[fg_carboxylic_acid - 1])
9283
    printf ("C3O2H000%c", sc);
9284
  if (fg[fg_carboxylic_acid_salt - 1])
9285
    printf ("C3O200T1%c", sc);
9286
  if (fg[fg_carboxylic_acid_ester - 1])
9287
    printf ("C3O2C000%c", sc);
9288
  if (fg[fg_lactone - 1])
9289
    printf ("C3O2CZ00%c", sc);
9290
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
9291
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9292
    printf ("C3ONC100%c", sc);
9293
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9294
    printf ("C3ONC200%c", sc);
9295
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9296
    printf ("C3ONC300%c", sc);
9297
  if (fg[fg_lactam - 1])
9298
    printf ("C3ONCZ00%c", sc);
9299
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9300
    printf ("C3ONN100%c", sc);
9301
  if (fg[fg_carboxylic_acid_azide - 1])
9302
    printf ("C3ONN200%c", sc);
9303
  if (fg[fg_hydroxamic_acid - 1])
9304
    printf ("C3ONOH00%c", sc);
9305
  if (fg[fg_carboxylic_acid_amidine - 1])
9306
    printf ("C3N2H000%c", sc);
9307
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9308
    printf ("C3NNN100%c", sc);
9309
  if (fg[fg_nitrile - 1])
9310
    printf ("C3N00000%c", sc);
9311
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
9312
  if (fg[fg_acyl_fluoride - 1])
9313
    printf ("C3OXF000%c", sc);
9314
  if (fg[fg_acyl_chloride - 1])
9315
    printf ("C3OXC000%c", sc);
9316
  if (fg[fg_acyl_bromide - 1])
9317
    printf ("C3OXB000%c", sc);
9318
  if (fg[fg_acyl_iodide - 1])
9319
    printf ("C3OXI000%c", sc);
9320
  if (fg[fg_acyl_cyanide - 1])
9321
    printf ("C2OC3N00%c", sc);
9322
  if (fg[fg_imido_ester - 1])
9323
    printf ("C3NOC000%c", sc);
9324
  if (fg[fg_imidoyl_halide - 1])
9325
    printf ("C3NXX000%c", sc);
9326
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
9327
  if (fg[fg_thiocarboxylic_acid - 1])
9328
    printf ("C3SOH000%c", sc);
9329
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9330
    printf ("C3SOC000%c", sc);
9331
  if (fg[fg_thiolactone - 1])
9332
    printf ("C3SOCZ00%c", sc);
9333
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9334
    printf ("C3SNH000%c", sc);
9335
  if (fg[fg_thiolactam - 1])
9336
    printf ("C3SNCZ00%c", sc);
9337
  if (fg[fg_imido_thioester - 1])
9338
    printf ("C3NSC000%c", sc);
9339
  if (fg[fg_oxohetarene - 1])
9340
    printf ("C3ONAZ00%c", sc);
9341
  if (fg[fg_thioxohetarene - 1])
9342
    printf ("C3SNAZ00%c", sc);
9343
  if (fg[fg_iminohetarene - 1])
9344
    printf ("C3NNAZ00%c", sc);
9345
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9346
    printf ("C3O30000%c", sc);
9347
  if (fg[fg_carboxylic_acid_orthoester - 1])
9348
    printf ("C3O3C000%c", sc);
9349
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9350
    printf ("C3O3NC00%c", sc);
9351
  if (fg[fg_carboxylic_acid_anhydride - 1])
9352
    printf ("C3O2C3O2%c", sc);
9353
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
9354
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9355
    printf ("C3ONCH10%c", sc);
9356
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9357
    printf ("C3ONCC10%c", sc);
9358
  if (fg[fg_co2_deriv - 1])
9359
    printf ("C4000000%c", sc);
9360
  if (fg[fg_carbonic_acid_deriv - 1])
9361
    printf ("C4O30000%c", sc);
9362
  if (fg[fg_carbonic_acid_monoester - 1])
9363
    printf ("C4O3C100%c", sc);
9364
  if (fg[fg_carbonic_acid_diester - 1])
9365
    printf ("C4O3C200%c", sc);
9366
  if (fg[fg_carbonic_acid_ester_halide - 1])
9367
    printf ("C4O3CX00%c", sc);
9368
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9369
    printf ("C4SO0000%c", sc);
9370
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9371
    printf ("C4SOC100%c", sc);
9372
  if (fg[fg_thiocarbonic_acid_diester - 1])
9373
    printf ("C4SOC200%c", sc);
9374
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9375
    printf ("C4SOX_00%c", sc);
9376
  if (fg[fg_carbamic_acid_deriv - 1])
9377
    printf ("C4O2N000%c", sc);
9378
  if (fg[fg_carbamic_acid - 1])
9379
    printf ("C4O2NH00%c", sc);
9380
  if (fg[fg_carbamic_acid_ester - 1])
9381
    printf ("C4O2NC00%c", sc);
9382
  if (fg[fg_carbamic_acid_halide - 1])
9383
    printf ("C4O2NX00%c", sc);
9384
  if (fg[fg_thiocarbamic_acid_deriv - 1])
9385
    printf ("C4SN0000%c", sc);
9386
  if (fg[fg_thiocarbamic_acid - 1])
9387
    printf ("C4SNOH00%c", sc);
9388
  if (fg[fg_thiocarbamic_acid_ester - 1])
9389
    printf ("C4SNOC00%c", sc);
9390
  if (fg[fg_thiocarbamic_acid_halide - 1])
9391
    printf ("C4SNXX00%c", sc);
9392
  if (fg[fg_urea - 1])
9393
    printf ("C4O1N200%c", sc);
9394
  if (fg[fg_isourea - 1])
9395
    printf ("C4N2O100%c", sc);
9396
  if (fg[fg_thiourea - 1])
9397
    printf ("C4S1N200%c", sc);
9398
  if (fg[fg_isothiourea - 1])
9399
    printf ("C4N2S100%c", sc);
9400
  if (fg[fg_guanidine - 1])
9401
    printf ("C4N30000%c", sc);
9402
  if (fg[fg_semicarbazide - 1])
9403
    printf ("C4ON2N00%c", sc);
9404
  if (fg[fg_thiosemicarbazide - 1])
9405
    printf ("C4SN2N00%c", sc);
9406
  if (fg[fg_azide - 1])
9407
    printf ("N4N20000%c", sc);
9408
  if (fg[fg_azo_compound - 1])
9409
    printf ("N2N10000%c", sc);
9410
  if (fg[fg_diazonium_salt - 1])
9411
    printf ("N3N100T2%c", sc);
9412
  if (fg[fg_isonitrile - 1])
9413
    printf ("N3C10000%c", sc);
9414
  if (fg[fg_cyanate - 1])
9415
    printf ("C4NO1000%c", sc);
9416
  if (fg[fg_isocyanate - 1])
9417
    printf ("C4NO2000%c", sc);
9418
  if (fg[fg_thiocyanate - 1])
9419
    printf ("C4NS1000%c", sc);
9420
  if (fg[fg_isothiocyanate - 1])
9421
    printf ("C4NS2000%c", sc);
9422
  if (fg[fg_carbodiimide - 1])
9423
    printf ("C4N20000%c", sc);
9424
  if (fg[fg_nitroso_compound - 1])
9425
    printf ("N2O10000%c", sc);
9426
  if (fg[fg_nitro_compound - 1])
9427
    printf ("N4O20000%c", sc);
9428
  if (fg[fg_nitrite - 1])
9429
    printf ("N3O20000%c", sc);
9430
  if (fg[fg_nitrate - 1])
9431
    printf ("N4O30000%c", sc);
9432
  if (fg[fg_sulfuric_acid_deriv - 1])
9433
    printf ("S6O00000%c", sc);
9434
  if (fg[fg_sulfuric_acid - 1])
9435
    printf ("S6O4H000%c", sc);
9436
  if (fg[fg_sulfuric_acid_monoester - 1])
9437
    printf ("S6O4HC00%c", sc);
9438
  if (fg[fg_sulfuric_acid_diester - 1])
9439
    printf ("S6O4CC00%c", sc);
9440
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9441
    printf ("S6O3NC00%c", sc);
9442
  if (fg[fg_sulfuric_acid_amide - 1])
9443
    printf ("S6O3N100%c", sc);
9444
  if (fg[fg_sulfuric_acid_diamide - 1])
9445
    printf ("S6O2N200%c", sc);
9446
  if (fg[fg_sulfuryl_halide - 1])
9447
    printf ("S6O3XX00%c", sc);
9448
  if (fg[fg_sulfonic_acid_deriv - 1])
9449
    printf ("S5O00000%c", sc);
9450
  if (fg[fg_sulfonic_acid - 1])
9451
    printf ("S5O3H000%c", sc);
9452
  if (fg[fg_sulfonic_acid_ester - 1])
9453
    printf ("S5O3C000%c", sc);
9454
  if (fg[fg_sulfonamide - 1])
9455
    printf ("S5O2N000%c", sc);
9456
  if (fg[fg_sulfonyl_halide - 1])
9457
    printf ("S5O2XX00%c", sc);
9458
  if (fg[fg_sulfone - 1])
9459
    printf ("S4O20000%c", sc);
9460
  if (fg[fg_sulfoxide - 1])
9461
    printf ("S2O10000%c", sc);
9462
  if (fg[fg_sulfinic_acid_deriv - 1])
9463
    printf ("S3O00000%c", sc);
9464
  if (fg[fg_sulfinic_acid - 1])
9465
    printf ("S3O2H000%c", sc);
9466
  if (fg[fg_sulfinic_acid_ester - 1])
9467
    printf ("S3O2C000%c", sc);
9468
  if (fg[fg_sulfinic_acid_halide - 1])
9469
    printf ("S3O1XX00%c", sc);
9470
  if (fg[fg_sulfinic_acid_amide - 1])
9471
    printf ("S3O1N000%c", sc);
9472
  if (fg[fg_sulfenic_acid_deriv - 1])
9473
    printf ("S1O00000%c", sc);
9474
  if (fg[fg_sulfenic_acid - 1])
9475
    printf ("S1O1H000%c", sc);
9476
  if (fg[fg_sulfenic_acid_ester - 1])
9477
    printf ("S1O1C000%c", sc);
9478
  if (fg[fg_sulfenic_acid_halide - 1])
9479
    printf ("S1O0XX00%c", sc);
9480
  if (fg[fg_sulfenic_acid_amide - 1])
9481
    printf ("S1O0N100%c", sc);
9482
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
9483
  if (fg[fg_alkylthiol - 1])
9484
    printf ("S1H1C000%c", sc);
9485
  if (fg[fg_arylthiol - 1])
9486
    printf ("S1H1A000%c", sc);
9487
  if (fg[fg_phosphoric_acid_deriv - 1])
9488
    printf ("P5O0H000%c", sc);
9489
  if (fg[fg_phosphoric_acid - 1])
9490
    printf ("P5O4H200%c", sc);
9491
  if (fg[fg_phosphoric_acid_ester - 1])
9492
    printf ("P5O4HC00%c", sc);
9493
  if (fg[fg_phosphoric_acid_halide - 1])
9494
    printf ("P5O3HX00%c", sc);
9495
  if (fg[fg_phosphoric_acid_amide - 1])
9496
    printf ("P5O3HN00%c", sc);
9497
  if (fg[fg_thiophosphoric_acid_deriv - 1])
9498
    printf ("P5O0S000%c", sc);
9499
  if (fg[fg_thiophosphoric_acid - 1])
9500
    printf ("P5O3SH00%c", sc);
9501
  if (fg[fg_thiophosphoric_acid_ester - 1])
9502
    printf ("P5O3SC00%c", sc);
9503
  if (fg[fg_thiophosphoric_acid_halide - 1])
9504
    printf ("P5O2SX00%c", sc);
9505
  if (fg[fg_thiophosphoric_acid_amide - 1])
9506
    printf ("P5O2SN00%c", sc);
9507
  if (fg[fg_phosphonic_acid_deriv - 1])
9508
    printf ("P4O30000%c", sc);
9509
  if (fg[fg_phosphonic_acid - 1])
9510
    printf ("P4O3H000%c", sc);
9511
  if (fg[fg_phosphonic_acid_ester - 1])
9512
    printf ("P4O3C000%c", sc);
9513
  if (fg[fg_phosphine - 1])
9514
    printf ("P3000000%c", sc);
9515
  if (fg[fg_phosphinoxide - 1])
9516
    printf ("P2O00000%c", sc);
9517
  if (fg[fg_boronic_acid_deriv - 1])
9518
    printf ("B2O20000%c", sc);
9519
  if (fg[fg_boronic_acid - 1])
9520
    printf ("B2O2H000%c", sc);
9521
  if (fg[fg_boronic_acid_ester - 1])
9522
    printf ("B2O2C000%c", sc);
9523
  if (fg[fg_alkene - 1])
9524
    printf ("000C2C00%c", sc);
9525
  if (fg[fg_alkyne - 1])
9526
    printf ("000C3C00%c", sc);
9527
  if (fg[fg_aromatic - 1])
9528
    printf ("0000A000%c", sc);
9529
  if (fg[fg_heterocycle - 1])
9530
    printf ("0000CZ00%c", sc);
9531
  if (fg[fg_alpha_aminoacid - 1])
9532
    printf ("C3O2HN1C%c", sc);
9533
  if (fg[fg_alpha_hydroxyacid - 1])
9534
    printf ("C3O2HO1H%c", sc);
9535
}
9536
 
9537
#undef sc
9538
 
14179 bpr 9539
static void write_fg_binary ()
6785 bpr 9540
{
9541
  int i, n;
9542
  char o;
9543
 
14179 bpr 9544
  for (i = 1; i <= max_fg / 8; i++) {
9545
    n = 0;
9546
    if (fg[i * 8 - 1])
9547
            n++;
9548
    if (fg[i * 8 - 2])
9549
            n += 2;
9550
    if (fg[i * 8 - 3])
9551
            n += 4;
9552
    if (fg[i * 8 - 4])
9553
            n += 8;
9554
    if (fg[i * 8 - 5])
9555
            n += 16;
9556
    if (fg[i * 8 - 6])
9557
            n += 32;
9558
    if (fg[i * 8 - 7])
9559
            n += 64;
9560
    if (fg[i * 8 - 8])
9561
            n += 128;
9562
    o = (char) n;
9563
    putchar (o);
9564
  }
6785 bpr 9565
}
9566
 
14179 bpr 9567
static void write_fg_bitstring ()
6785 bpr 9568
{
9569
  int i;
9570
 
14179 bpr 9571
  for (i = 0; i < max_fg; i++) {
9572
    if (fg[i])
9573
            putchar ('1');
9574
    else
9575
            putchar ('0');
9576
  }
6785 bpr 9577
}
9578
 
9579
#if 0
9580
static void readinputfile (molfilename) char *molfilename;
14179 bpr 9581
  {
9582
  /* new version in v0.2g */
9583
  char rline[256];
9584
  char *TEMP;
6785 bpr 9585
 
14179 bpr 9586
  molbufindex = 0;
9587
  if (!opt_stdin)
9588
  {
9589
  if (!rfile_is_open)
9590
  {
9591
  assign (rfile, molfilename);
9592
  rewind (rfile);
9593
  rfile_is_open = true;
9594
  }
9595
  /* p2c: checkmol.pas, line 7733: Warning:
9596
  * Don't know how to ASSIGN to a non-explicit file variable [207] */
9597
  *rline = '\0';
9598
  mol_in_queue = false;
9599
  while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
9600
  {
9601
  fgets (rline, 256, rfile);
9602
  TEMP = strchr (rline, '\n');
9603
  if (TEMP != NULL)
9604
  *TEMP = 0;
9605
  /*mol_in_queue := false; */
9606
  if (molbufindex >= max_atoms + max_bonds + 64)
9607
  {
9608
  printf ("Not enough memory for molfile! %12ld\n",
9609
  molbufindex);
9610
  if (rfile != NULL)
9611
  fclose (rfile);
9612
  rfile = NULL;
9613
  _Escape (1);
9614
  }
9615
  molbufindex++;
9616
  strcpy (molbuf[molbufindex - 1], rline);
9617
  if (strpos2 (rline, "$$$$", 1) > 0)
9618
  mol_in_queue = true;
9619
  }
9620
  if (!P_eof (rfile))
9621
  return;
9622
  if (rfile != NULL)
9623
  fclose (rfile);
9624
  rfile = NULL;
9625
  rfile_is_open = false;
9626
  mol_in_queue = false;
9627
  return;
9628
  }
9629
  *rline = '\0';
9630
  mol_in_queue = false;
9631
  while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
9632
  {
9633
  gets (rline);
9634
  if (molbufindex >= max_atoms + max_bonds + 64)
9635
  {
9636
  printf ("Not enough memory!\n");
9637
  _Escape (1);
9638
  }
9639
  molbufindex++;
9640
  strcpy (molbuf[molbufindex - 1], rline);
9641
  if (strpos2 (rline, "$$$$", 1) > 0)
9642
  {
9643
  mol_in_queue = true;
9644
  /* read from standard input
9645
  }
9646
  }
9647
  } */
6785 bpr 9648
#endif
9649
 
14179 bpr 9650
static void readinputfile (char *molfilename)
6785 bpr 9651
{
9652
  /* new version in v0.2g */
9653
  char rline[256];
9654
  char *TEMP;
9655
 
9656
  molbufindex = 0;
14179 bpr 9657
  if (!opt_stdin) {
9658
    if (!rfile_is_open) {
9659
            rfile = fopen (molfilename, "r");
9660
            rewind (rfile);
9661
            rfile_is_open = true;
9662
          }
9663
    /* p2c: checkmol.pas, line 7226: Warning:
9664
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
9665
    *rline = '\0';
9666
    mol_in_queue = false;
9667
    while ((fgets (rline, 256, rfile) != NULL) && (strstr (rline, "$$$$") == NULL)) {
9668
            TEMP = strchr (rline, '\n');
9669
            if (TEMP != NULL)
9670
              *TEMP = 0;
9671
            /*mol_in_queue := false; */
9672
            if (molbufindex >= max_atoms + max_bonds + 64) {
6785 bpr 9673
              printf ("Not enough memory for molfile! %d\n", molbufindex);
9674
              if (rfile != NULL)
14179 bpr 9675
                      fclose (rfile);
6785 bpr 9676
              rfile = NULL;
9677
              exit (1);
9678
            }
14179 bpr 9679
            //molbufindex++;
9680
            strcpy (molbuf[molbufindex++], rline);
9681
            if (strstr (rline, "$$$$") != NULL)
9682
              mol_in_queue = true;
9683
          }
9684
    if (!feof (rfile))
9685
            return;
9686
    if (rfile != NULL)
9687
            fclose (rfile);
9688
    rfile = NULL;
9689
    rfile_is_open = false;
9690
    mol_in_queue = false;
9691
    return;
9692
  }
6785 bpr 9693
  *rline = '\0';
9694
  mol_in_queue = false;
14179 bpr 9695
  do {
9696
    if(fgets (rline, 256, stdin)==NULL || feof (stdin))
9697
            return;
9698
    TEMP = strchr (rline, '\n');
9699
    if (TEMP != NULL)
9700
            *TEMP = '\0';
9701
    if (molbufindex >= max_atoms + max_bonds + 64) {
9702
            printf ("Not enough memory!\n");
9703
            exit (1);
9704
          }
9705
    //molbufindex++;
9706
    strcpy (molbuf[molbufindex++], rline);
9707
    if (strstr (rline, "$$$$") != NULL) {
9708
            mol_in_queue = true;
9709
            /* read from standard input */
9710
          }
9711
  }
6785 bpr 9712
  while (strstr (rline, "$$$$") == NULL);
9713
}
9714
 
9715
#if 0
9716
static void copy_mol_to_needle()
9717
{
9718
  int i, j, FORLIM;
9719
 
9720
  if (n_atoms == 0)
9721
    return;
9722
  /* try */
9723
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9724
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9725
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9726
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9727
  /* except*/
9728
    on e:Eoutofmemory do
9729
      begin
9730
        writeln('Not enough memory');
9731
        halt(4);
9732
      end;
14179 bpr 9733
  end;
6785 bpr 9734
  ndl_n_atoms = n_atoms;
9735
  ndl_n_bonds = n_bonds;
9736
  ndl_n_rings = n_rings;
9737
  ndl_n_heavyatoms = n_heavyatoms;
9738
  ndl_n_heavybonds = n_heavybonds;
9739
  strcpy(ndl_molname, molname);
9740
  ndl_n_Ctot = n_Ctot;
9741
  ndl_n_Otot = n_Otot;
9742
  ndl_n_Ntot = n_Ntot;
9743
  FORLIM = n_atoms;
9744
  for (i = 0; i < FORLIM; i++) {
9745
    strcpy(ndl_atom[i].element, atom[i].element);
9746
    strcpy(ndl_atom[i].atype, atom[i].atype);
9747
    ndl_atom[i].x = atom[i].x;
9748
    ndl_atom[i].y = atom[i].y;
9749
    ndl_atom[i].z = atom[i].z;
9750
    ndl_atom[i].formal_charge = atom[i].formal_charge;
9751
    ndl_atom[i].real_charge = atom[i].real_charge;
9752
    ndl_atom[i].Hexp = atom[i].Hexp;
9753
    ndl_atom[i].Htot = atom[i].Htot;
9754
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
9755
    ndl_atom[i].ring_count = atom[i].ring_count;
9756
    ndl_atom[i].arom = atom[i].arom;
9757
    ndl_atom[i].stereo_care = atom[i].stereo_care;
9758
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
9759
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
9760
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
14179 bpr 9761
        }
9762
        if (n_bonds > 0) {
9763
          FORLIM = n_bonds;
9764
          for (i = 0; i < FORLIM; i++) {
9765
            ndl_bond[i].a1 = bond[i].a1;
9766
            ndl_bond[i].a2 = bond[i].a2;
9767
            ndl_bond[i].btype = bond[i].btype;
9768
            ndl_bond[i].arom = bond[i].arom;
9769
            ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
9770
            ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
9771
            ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
9772
          }
9773
        }
9774
        if (n_rings > 0) {
9775
          FORLIM = n_rings;
9776
          for (i = 0; i < FORLIM; i++) {
9777
            for (j = 0; j < max_ringsize; j++)
9778
              ndl_ring[i][j] = ring[i][j];
9779
          }
9780
          for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
9781
            ndl_ringprop[i].size = ringprop[i].size;
9782
            ndl_ringprop[i].arom = ringprop[i].arom;
9783
            ndl_ringprop[i].envelope = ringprop[i].envelope;
9784
          }
9785
        }
9786
        ndl_molstat.n_QA = molstat.n_QA;
9787
  ndl_molstat.n_QB = molstat.n_QB;
9788
  ndl_molstat.n_chg = molstat.n_chg;
9789
  ndl_molstat.n_C1 = molstat.n_C1;
9790
  ndl_molstat.n_C2 = molstat.n_C2;
9791
  ndl_molstat.n_C = molstat.n_C;
9792
  ndl_molstat.n_CHB1p = molstat.n_CHB1p;
9793
  ndl_molstat.n_CHB2p = molstat.n_CHB2p;
9794
  ndl_molstat.n_CHB3p = molstat.n_CHB3p;
9795
  ndl_molstat.n_CHB4 = molstat.n_CHB4;
9796
  ndl_molstat.n_O2 = molstat.n_O2;
9797
  ndl_molstat.n_O3 = molstat.n_O3;
9798
  ndl_molstat.n_N1 = molstat.n_N1;
9799
  ndl_molstat.n_N2 = molstat.n_N2;
9800
  ndl_molstat.n_N3 = molstat.n_N3;
9801
  ndl_molstat.n_S = molstat.n_S;
9802
  ndl_molstat.n_SeTe = molstat.n_SeTe;
9803
  ndl_molstat.n_F = molstat.n_F;
9804
  ndl_molstat.n_Cl = molstat.n_Cl;
9805
  ndl_molstat.n_Br = molstat.n_Br;
9806
  ndl_molstat.n_I = molstat.n_I;
9807
  ndl_molstat.n_P = molstat.n_P;
9808
  ndl_molstat.n_B = molstat.n_B;
9809
  ndl_molstat.n_Met = molstat.n_Met;
9810
  ndl_molstat.n_X = molstat.n_X;
9811
  ndl_molstat.n_b1 = molstat.n_b1;
9812
  ndl_molstat.n_b2 = molstat.n_b2;
9813
  ndl_molstat.n_b3 = molstat.n_b3;
9814
  ndl_molstat.n_bar = molstat.n_bar;
9815
  ndl_molstat.n_C1O = molstat.n_C1O;
9816
  ndl_molstat.n_C2O = molstat.n_C2O;
9817
  ndl_molstat.n_CN = molstat.n_CN;
9818
  ndl_molstat.n_XY = molstat.n_XY;
9819
  ndl_molstat.n_r3 = molstat.n_r3;
9820
  ndl_molstat.n_r4 = molstat.n_r4;
9821
  ndl_molstat.n_r5 = molstat.n_r5;
9822
  ndl_molstat.n_r6 = molstat.n_r6;
9823
  ndl_molstat.n_r7 = molstat.n_r7;
9824
        ndl_molstat.n_r8 = molstat.n_r8;
9825
        ndl_molstat.n_r9 = molstat.n_r9;
9826
        ndl_molstat.n_r10 = molstat.n_r10;
9827
        ndl_molstat.n_r11 = molstat.n_r11;
9828
        ndl_molstat.n_r12 = molstat.n_r12;
9829
        ndl_molstat.n_r13p = molstat.n_r13p;
9830
        ndl_molstat.n_rN = molstat.n_rN;
9831
        ndl_molstat.n_rN1 = molstat.n_rN1;
9832
        ndl_molstat.n_rN2 = molstat.n_rN2;
9833
        ndl_molstat.n_rN3p = molstat.n_rN3p;
9834
        ndl_molstat.n_rO = molstat.n_rO;
9835
        ndl_molstat.n_rO1 = molstat.n_rO1;
9836
        ndl_molstat.n_rO2p = molstat.n_rO2p;
9837
        ndl_molstat.n_rS = molstat.n_rS;
9838
        ndl_molstat.n_rX = molstat.n_rX;
9839
        ndl_molstat.n_rAr = molstat.n_rAr;
9840
        ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
9841
        ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
9842
        /* p2c: checkmol.pas, line 7875:
9843
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
9844
        /*$IFDEF extended_molstat
9845
         v0.3m */
9846
        ndl_molstat.n_psg01 = molstat.n_psg01;
9847
        ndl_molstat.n_psg02 = molstat.n_psg02;
9848
        ndl_molstat.n_psg13 = molstat.n_psg13;
9849
        ndl_molstat.n_psg14 = molstat.n_psg14;
9850
        ndl_molstat.n_psg15 = molstat.n_psg15;
9851
        ndl_molstat.n_psg16 = molstat.n_psg16;
9852
        ndl_molstat.n_psg17 = molstat.n_psg17;
9853
        ndl_molstat.n_psg18 = molstat.n_psg18;
9854
        ndl_molstat.n_pstm = molstat.n_pstm;
9855
        ndl_molstat.n_psla = molstat.n_psla;
9856
        $ENDIF*/
9857
  /* make sure some modes can be switched on only by the query file *M*/
9858
  /* and not by subsequent haystack file(s) */
9859
  if (ez_flag)   /* new in v0.3f */
9860
   ez_search = true;
9861
  if (chir_flag)   /* new in v0.3f */
9862
    rs_search = true;
9863
}
6785 bpr 9864
#endif
9865
 
14179 bpr 9866
static void copy_mol_to_needle ()
6785 bpr 9867
{
9868
  //int i, j, FORLIM;
9869
 
9870
  /*if (n_atoms == 0)
9871
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9872
 
9873
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9874
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9875
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9876
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9877
 
9878
  ndl_n_atoms = n_atoms;
9879
  ndl_n_bonds = n_bonds;
9880
  ndl_n_rings = n_rings;
9881
  ndl_n_heavyatoms = n_heavyatoms;
9882
  ndl_n_heavybonds = n_heavybonds;
9883
  strcpy (ndl_molname, molname);
9884
  ndl_n_Ctot = n_Ctot;
9885
  ndl_n_Otot = n_Otot;
9886
  ndl_n_Ntot = n_Ntot;
9887
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
9888
 
9889
  if (n_bonds > 0)
9890
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
9891
 
14179 bpr 9892
  if (n_rings > 0) {
9893
    memcpy (ndl_ring, ring, sizeof (ringlist));
9894
    memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
9895
  }
6785 bpr 9896
 
9897
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
9898
 
14179 bpr 9899
  // make sure some modes can be switched on only by the query file
9900
  // and not by subsequent haystack file(s)
9901
  if (ez_flag)                  // new in v0.3f
6785 bpr 9902
    ez_search = true;
9903
 
14179 bpr 9904
  if (chir_flag)                // new in v0.3f
6785 bpr 9905
    rs_search = true;
9906
 
9907
  ndl_querymol = found_querymol;        /* 0.3p */
9908
 
9909
}
9910
 
14179 bpr 9911
static void copy_mol_to_tmp ()
6785 bpr 9912
{
9913
  //int i, j, FORLIM;
9914
 
9915
  /*if (n_atoms == 0)
9916
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9917
 
9918
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9919
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9920
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9921
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9922
 
9923
  tmp_n_atoms = n_atoms;
9924
  tmp_n_bonds = n_bonds;
9925
  tmp_n_rings = n_rings;
9926
  tmp_n_heavyatoms = n_heavyatoms;
9927
  tmp_n_heavybonds = n_heavybonds;
9928
  strcpy (tmp_molname, molname);
9929
  tmp_n_Ctot = n_Ctot;
9930
  tmp_n_Otot = n_Otot;
9931
  tmp_n_Ntot = n_Ntot;
9932
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
9933
 
9934
  if (n_bonds > 0)
9935
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
9936
 
14179 bpr 9937
  if (n_rings > 0) {
6785 bpr 9938
      memcpy (tmp_ring, ring, sizeof (ringlist));
9939
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
14179 bpr 9940
  }
6785 bpr 9941
 
9942
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
9943
 
14179 bpr 9944
  // make sure some modes can be switched on only by the query file
9945
  // and not by subsequent haystack file(s)
9946
  if (ez_flag)                  // new in v0.3f
6785 bpr 9947
    ez_search = true;
9948
 
14179 bpr 9949
  if (chir_flag)                // new in v0.3f
6785 bpr 9950
    rs_search = true;
9951
 
9952
  ndl_querymol = found_querymol;        /* 0.3p */
9953
 
9954
}
9955
 
9956
#if 0
9957
static void copy_mol_to_tmp()
9958
{
9959
  int i, j, FORLIM;
9960
 
9961
  if (n_atoms == 0)
9962
    return;
9963
  /* try */
9964
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9965
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9966
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9967
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9968
  /* except */
9969
    on e:Eoutofmemory do
9970
      begin
9971
        writeln('Not enough memory');
9972
        halt(4);
9973
      end;
9974
  end;
9975
  tmp_n_atoms = n_atoms;
9976
  tmp_n_bonds = n_bonds;
9977
  tmp_n_rings = n_rings;
9978
  tmp_n_heavyatoms = n_heavyatoms;
9979
  tmp_n_heavybonds = n_heavybonds;
9980
  strcpy(tmp_molname, molname);
9981
  tmp_n_Ctot = n_Ctot;
9982
  tmp_n_Otot = n_Otot;
9983
  tmp_n_Ntot = n_Ntot;
9984
  FORLIM = n_atoms;
9985
  for (i = 0; i < FORLIM; i++) {
9986
    strcpy(tmp_atom[i].element, atom[i].element);
9987
    strcpy(tmp_atom[i].atype, atom[i].atype);
9988
    tmp_atom[i].x = atom[i].x;
9989
    tmp_atom[i].y = atom[i].y;
9990
    tmp_atom[i].z = atom[i].z;
9991
    tmp_atom[i].formal_charge = atom[i].formal_charge;
9992
    tmp_atom[i].real_charge = atom[i].real_charge;
9993
    tmp_atom[i].Hexp = atom[i].Hexp;
9994
    tmp_atom[i].Htot = atom[i].Htot;
9995
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
9996
    tmp_atom[i].ring_count = atom[i].ring_count;
9997
    tmp_atom[i].arom = atom[i].arom;
9998
    tmp_atom[i].stereo_care = atom[i].stereo_care;
9999
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
10000
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
10001
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
10002
  }
10003
  if (n_bonds > 0) {
10004
    FORLIM = n_bonds;
10005
    for (i = 0; i < FORLIM; i++) {
10006
      tmp_bond[i].a1 = bond[i].a1;
10007
      tmp_bond[i].a2 = bond[i].a2;
10008
      tmp_bond[i].btype = bond[i].btype;
10009
      tmp_bond[i].arom = bond[i].arom;
10010
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
10011
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
10012
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
10013
    }
10014
  }
10015
  if (n_rings > 0) {
10016
    FORLIM = n_rings;
10017
    for (i = 0; i < FORLIM; i++) {
10018
      for (j = 0; j < max_ringsize; j++)
10019
        tmp_ring[i][j] = ring[i][j];
10020
    }
10021
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10022
      tmp_ringprop[i].size = ringprop[i].size;
10023
      tmp_ringprop[i].arom = ringprop[i].arom;
10024
      tmp_ringprop[i].envelope = ringprop[i].envelope;
10025
    }
10026
  }
10027
  tmp_molstat.n_QA = molstat.n_QA;
10028
  tmp_molstat.n_QB = molstat.n_QB;
10029
  tmp_molstat.n_chg = molstat.n_chg;
10030
  tmp_molstat.n_C1 = molstat.n_C1;
10031
  tmp_molstat.n_C2 = molstat.n_C2;
10032
  tmp_molstat.n_C = molstat.n_C;
10033
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
10034
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
10035
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
10036
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
10037
  tmp_molstat.n_O2 = molstat.n_O2;
10038
  tmp_molstat.n_O3 = molstat.n_O3;
10039
  tmp_molstat.n_N1 = molstat.n_N1;
10040
  tmp_molstat.n_N2 = molstat.n_N2;
10041
  tmp_molstat.n_N3 = molstat.n_N3;
10042
  tmp_molstat.n_S = molstat.n_S;
10043
  tmp_molstat.n_SeTe = molstat.n_SeTe;
10044
  tmp_molstat.n_F = molstat.n_F;
10045
  tmp_molstat.n_Cl = molstat.n_Cl;
10046
  tmp_molstat.n_Br = molstat.n_Br;
10047
  tmp_molstat.n_I = molstat.n_I;
10048
  tmp_molstat.n_P = molstat.n_P;
10049
  tmp_molstat.n_B = molstat.n_B;
10050
  tmp_molstat.n_Met = molstat.n_Met;
10051
  tmp_molstat.n_X = molstat.n_X;
10052
  tmp_molstat.n_b1 = molstat.n_b1;
10053
  tmp_molstat.n_b2 = molstat.n_b2;
10054
  tmp_molstat.n_b3 = molstat.n_b3;
10055
  tmp_molstat.n_bar = molstat.n_bar;
10056
  tmp_molstat.n_C1O = molstat.n_C1O;
10057
  tmp_molstat.n_C2O = molstat.n_C2O;
10058
  tmp_molstat.n_CN = molstat.n_CN;
10059
  tmp_molstat.n_XY = molstat.n_XY;
10060
  tmp_molstat.n_r3 = molstat.n_r3;
10061
  tmp_molstat.n_r4 = molstat.n_r4;
10062
  tmp_molstat.n_r5 = molstat.n_r5;
10063
  tmp_molstat.n_r6 = molstat.n_r6;
10064
  tmp_molstat.n_r7 = molstat.n_r7;
10065
  tmp_molstat.n_r8 = molstat.n_r8;
10066
  tmp_molstat.n_r9 = molstat.n_r9;
10067
  tmp_molstat.n_r10 = molstat.n_r10;
10068
  tmp_molstat.n_r11 = molstat.n_r11;
10069
  tmp_molstat.n_r12 = molstat.n_r12;
10070
  tmp_molstat.n_r13p = molstat.n_r13p;
10071
  tmp_molstat.n_rN = molstat.n_rN;
10072
  tmp_molstat.n_rN1 = molstat.n_rN1;
10073
  tmp_molstat.n_rN2 = molstat.n_rN2;
10074
  tmp_molstat.n_rN3p = molstat.n_rN3p;
10075
  tmp_molstat.n_rO = molstat.n_rO;
10076
  tmp_molstat.n_rO1 = molstat.n_rO1;
10077
  tmp_molstat.n_rO2p = molstat.n_rO2p;
10078
  tmp_molstat.n_rS = molstat.n_rS;
10079
  tmp_molstat.n_rX = molstat.n_rX;
10080
  tmp_molstat.n_rAr = molstat.n_rAr;
10081
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
10082
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
10083
/* p2c: checkmol.pas, line 8022:
10084
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10085
  /*$IFDEF extended_molstat
14179 bpr 10086
   v0.3m
6785 bpr 10087
  tmp_molstat.n_psg01 = molstat.n_psg01;
10088
  tmp_molstat.n_psg02 = molstat.n_psg02;
10089
  tmp_molstat.n_psg13 = molstat.n_psg13;
10090
  tmp_molstat.n_psg14 = molstat.n_psg14;
10091
  tmp_molstat.n_psg15 = molstat.n_psg15;
10092
  tmp_molstat.n_psg16 = molstat.n_psg16;
10093
  tmp_molstat.n_psg17 = molstat.n_psg17;
10094
  tmp_molstat.n_psg18 = molstat.n_psg18;
10095
  tmp_molstat.n_pstm = molstat.n_pstm;
10096
  tmp_molstat.n_psla = molstat.n_psla;
10097
  $ENDIF*/
10098
  /* make sure some modes can be switched on only by the query file */
10099
  /* and not by subsequent haystack file(s) */
10100
  if (ez_flag)   /* new in v0.3f */
10101
    ez_search = true;
10102
  if (chir_flag)   /* new in v0.3f */
10103
    rs_search = true;
10104
}
10105
#endif
10106
 
14179 bpr 10107
static void copy_tmp_to_mol ()
6785 bpr 10108
{
10109
  //int i, j, FORLIM;
10110
 
10111
  /*if (n_atoms == 0)
10112
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10113
 
10114
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10115
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10116
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10117
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10118
 
10119
  n_atoms = tmp_n_atoms;
10120
  n_bonds = tmp_n_bonds;
10121
  n_rings = tmp_n_rings;
10122
  n_heavyatoms = tmp_n_heavyatoms;
10123
  n_heavybonds = tmp_n_heavybonds;
10124
  strcpy (molname, tmp_molname);
10125
  n_Ctot = tmp_n_Ctot;
10126
  n_Otot = tmp_n_Otot;
10127
  n_Ntot = tmp_n_Ntot;
10128
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
10129
 
10130
  if (tmp_n_bonds > 0)
10131
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
10132
 
14179 bpr 10133
  if (tmp_n_rings > 0) {
6785 bpr 10134
      memcpy (ring, tmp_ring, sizeof (ringlist));
10135
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
14179 bpr 10136
  }
6785 bpr 10137
 
10138
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
10139
 
14179 bpr 10140
  // make sure some modes can be switched on only by the query file
10141
  // and not by subsequent haystack file(s)
10142
  if (ez_flag)                  // new in v0.3f
6785 bpr 10143
    ez_search = true;
10144
 
14179 bpr 10145
  if (chir_flag)                // new in v0.3f
6785 bpr 10146
    rs_search = true;
10147
 
10148
}
10149
 
10150
#if 0
10151
static void copy_tmp_to_mol()
10152
{
10153
  int i, j, FORLIM;
10154
 
10155
  if (tmp_n_atoms == 0)
10156
    return;
10157
  n_atoms = tmp_n_atoms;
10158
  n_bonds = tmp_n_bonds;
10159
  n_rings = tmp_n_rings;
10160
  n_heavyatoms = tmp_n_heavyatoms;
10161
  n_heavybonds = tmp_n_heavybonds;
10162
  strcpy(molname, tmp_molname);
10163
  n_Ctot = tmp_n_Ctot;
10164
  n_Otot = tmp_n_Otot;
10165
  n_Ntot = tmp_n_Ntot;
10166
  /* try */
10167
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10168
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10169
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10170
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10171
  FORLIM = tmp_n_atoms;
10172
  /* except*/
10173
    on e:Eoutofmemory do
10174
      begin
10175
        writeln('Not enough memory');
10176
        halt(4);
10177
      end;
14179 bpr 10178
  end;
6785 bpr 10179
  for (i = 0; i < FORLIM; i++) {
10180
    strcpy(atom[i].element, tmp_atom[i].element);
10181
    strcpy(atom[i].atype, tmp_atom[i].atype);
10182
    atom[i].x = tmp_atom[i].x;
10183
    atom[i].y = tmp_atom[i].y;
10184
    atom[i].z = tmp_atom[i].z;
10185
    atom[i].formal_charge = tmp_atom[i].formal_charge;
10186
    atom[i].real_charge = tmp_atom[i].real_charge;
10187
    atom[i].Hexp = tmp_atom[i].Hexp;
10188
    atom[i].Htot = tmp_atom[i].Htot;
10189
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
10190
    atom[i].ring_count = tmp_atom[i].ring_count;
10191
    atom[i].arom = tmp_atom[i].arom;
10192
    atom[i].stereo_care = tmp_atom[i].stereo_care;
10193
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
10194
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
10195
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
10196
  }
10197
  if (tmp_n_bonds > 0) {
10198
    FORLIM = tmp_n_bonds;
10199
    for (i = 0; i < FORLIM; i++) {
10200
      bond[i].a1 = tmp_bond[i].a1;
10201
      bond[i].a2 = tmp_bond[i].a2;
10202
      bond[i].btype = tmp_bond[i].btype;
10203
      bond[i].arom = tmp_bond[i].arom;
10204
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
10205
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
10206
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
10207
    }
10208
  }
10209
  if (tmp_n_rings > 0) {
10210
    FORLIM = tmp_n_rings;
10211
    for (i = 0; i < FORLIM; i++) {
10212
      for (j = 0; j < max_ringsize; j++)
10213
        ring[i][j] = tmp_ring[i][j];
10214
    }
10215
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10216
      ringprop[i].size = tmp_ringprop[i].size;
10217
      ringprop[i].arom = tmp_ringprop[i].arom;
10218
      ringprop[i].envelope = tmp_ringprop[i].envelope;
10219
    }
10220
  }
10221
  molstat.n_QA = tmp_molstat.n_QA;
10222
  molstat.n_QB = tmp_molstat.n_QB;
10223
  molstat.n_chg = tmp_molstat.n_chg;
10224
  molstat.n_C1 = tmp_molstat.n_C1;
10225
  molstat.n_C2 = tmp_molstat.n_C2;
10226
  molstat.n_C = tmp_molstat.n_C;
10227
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
10228
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
10229
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
10230
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
10231
  molstat.n_O2 = tmp_molstat.n_O2;
10232
  molstat.n_O3 = tmp_molstat.n_O3;
10233
  molstat.n_N1 = tmp_molstat.n_N1;
10234
  molstat.n_N2 = tmp_molstat.n_N2;
10235
  molstat.n_N3 = tmp_molstat.n_N3;
10236
  molstat.n_S = tmp_molstat.n_S;
10237
  molstat.n_SeTe = tmp_molstat.n_SeTe;
10238
  molstat.n_F = tmp_molstat.n_F;
10239
  molstat.n_Cl = tmp_molstat.n_Cl;
10240
  molstat.n_Br = tmp_molstat.n_Br;
10241
  molstat.n_I = tmp_molstat.n_I;
10242
  molstat.n_P = tmp_molstat.n_P;
10243
  molstat.n_B = tmp_molstat.n_B;
10244
  molstat.n_Met = tmp_molstat.n_Met;
10245
  molstat.n_X = tmp_molstat.n_X;
10246
  molstat.n_b1 = tmp_molstat.n_b1;
10247
  molstat.n_b2 = tmp_molstat.n_b2;
10248
  molstat.n_b3 = tmp_molstat.n_b3;
10249
  molstat.n_bar = tmp_molstat.n_bar;
10250
  molstat.n_C1O = tmp_molstat.n_C1O;
10251
  molstat.n_C2O = tmp_molstat.n_C2O;
10252
  molstat.n_CN = tmp_molstat.n_CN;
10253
  molstat.n_XY = tmp_molstat.n_XY;
10254
  molstat.n_r3 = tmp_molstat.n_r3;
10255
  molstat.n_r4 = tmp_molstat.n_r4;
10256
  molstat.n_r5 = tmp_molstat.n_r5;
10257
  molstat.n_r6 = tmp_molstat.n_r6;
10258
  molstat.n_r7 = tmp_molstat.n_r7;
10259
  molstat.n_r8 = tmp_molstat.n_r8;
10260
  molstat.n_r9 = tmp_molstat.n_r9;
10261
  molstat.n_r10 = tmp_molstat.n_r10;
10262
  molstat.n_r11 = tmp_molstat.n_r11;
10263
  molstat.n_r12 = tmp_molstat.n_r12;
10264
  molstat.n_r13p = tmp_molstat.n_r13p;
10265
  molstat.n_rN = tmp_molstat.n_rN;
10266
  molstat.n_rN1 = tmp_molstat.n_rN1;
10267
  molstat.n_rN2 = tmp_molstat.n_rN2;
10268
  molstat.n_rN3p = tmp_molstat.n_rN3p;
10269
  molstat.n_rO = tmp_molstat.n_rO;
10270
  molstat.n_rO1 = tmp_molstat.n_rO1;
10271
  molstat.n_rO2p = tmp_molstat.n_rO2p;
10272
  molstat.n_rS = tmp_molstat.n_rS;
10273
  molstat.n_rX = tmp_molstat.n_rX;
10274
  molstat.n_rAr = tmp_molstat.n_rAr;
10275
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
10276
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
10277
/* p2c: checkmol.pas, line 8169:
10278
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10279
  /*$IFDEF extended_molstat
10280
     molstat.n_psg01 = tmp_molstat.n_psg01;
10281
     molstat.n_psg02 = tmp_molstat.n_psg02;
10282
     molstat.n_psg13 = tmp_molstat.n_psg13;
10283
     molstat.n_psg14 = tmp_molstat.n_psg14;
10284
     molstat.n_psg15 = tmp_molstat.n_psg15;
10285
     molstat.n_psg16 = tmp_molstat.n_psg16;
10286
     molstat.n_psg17 = tmp_molstat.n_psg17;
10287
     molstat.n_psg18 = tmp_molstat.n_psg18;
10288
     molstat.n_pstm = tmp_molstat.n_pstm;
10289
     molstat.n_psla = tmp_molstat.n_psla;
10290
     $ENDIF */
10291
  /* make sure some modes can be switched on only by the query file */
10292
  /* and not by subsequent haystack file(s) */
10293
     if (ez_flag)
10294
     ez_search = true;
10295
     if (chir_flag)
10296
     rs_search = true;
10297
     }
10298
#endif
10299
 
14179 bpr 10300
static void get_ringstat (r_id)
6785 bpr 10301
     int r_id;
10302
{
10303
  int i, j;
10304
  ringpath_type testring;
10305
  int ring_size, a_ref;
10306
  str2 elem;
10307
  int nN = 0, nO = 0, nS = 0, nX = 0;
10308
 
10309
  if (r_id < 1 || r_id > n_rings)
10310
    return;
10311
  memset (testring, 0, sizeof (ringpath_type));
10312
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
10313
  for (j = 0; j < ring_size; j++)       /* v0.3j */
10314
    testring[j] = ring[r_id - 1][j];
14179 bpr 10315
    /* p2c: checkmol.pas, line 8238:
10316
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10317
#ifdef reduced_SAR
10318
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != false)
10319
    /* v0.3n: ignore envelope rings */
10320
    return;
10321
#else
10322
  if (ring_size <= 2)
10323
    return;
10324
#endif
14179 bpr 10325
  for (i = 0; i < ring_size; i++) {
10326
    a_ref = testring[i];
10327
    strcpy (elem, atom[a_ref - 1].element);
10328
    if (strcmp (elem, "C ") && strcmp (elem, "A ")) {
10329
            nX++;                       /* general heteroatom count */
10330
            if (!strcmp (elem, "N "))
10331
              nN++;
10332
            if (!strcmp (elem, "O "))
10333
              nO++;
10334
            if (!strcmp (elem, "S "))
10335
              nS++;
10336
          }
10337
  }
10338
  if (nN > 0) {
10339
    molstat.n_rN++;
10340
    if (nN == 1)
10341
            molstat.n_rN1++;
10342
    if (nN == 2)
10343
            molstat.n_rN2++;
10344
    if (nN > 2)
10345
            molstat.n_rN3p++;
10346
  }
10347
  if (nO > 0) {
10348
    molstat.n_rO++;
10349
    if (nO == 1)
10350
            molstat.n_rO1++;
10351
    if (nO == 2)
10352
            molstat.n_rO2p++;
10353
  }
6785 bpr 10354
  if (nS > 0)
10355
    molstat.n_rS++;
10356
  if (nX > 0)
10357
    molstat.n_rX++;
10358
  /* general ringsize descriptors; v0.3m */
14179 bpr 10359
  switch (ring_size) {
6785 bpr 10360
    case 3:
10361
      molstat.n_r3++;
10362
      break;
10363
 
10364
    case 4:
10365
      molstat.n_r4++;
10366
      break;
10367
 
10368
    case 5:
10369
      molstat.n_r5++;
10370
      break;
10371
 
10372
    case 6:
10373
      molstat.n_r6++;
10374
      break;
10375
 
10376
    case 7:
10377
      molstat.n_r7++;
10378
      break;
10379
 
10380
    case 8:
10381
      molstat.n_r8++;
10382
      break;
10383
 
10384
    case 9:
10385
      molstat.n_r9++;
10386
      break;
10387
 
10388
    case 10:
10389
      molstat.n_r10++;
10390
      break;
10391
 
10392
    case 11:
10393
      molstat.n_r11++;
10394
      break;
10395
 
10396
    case 12:
10397
      molstat.n_r12++;
10398
      break;
10399
 
10400
    default:
10401
      molstat.n_r13p++;
10402
      break;
14179 bpr 10403
  }                             /* end v0.3m        */
6785 bpr 10404
}
10405
 
14179 bpr 10406
static void get_molstat ()
6785 bpr 10407
{
10408
  int i;
10409
  str2 elem;
10410
  str3 atype;
10411
  int a1, a2;
10412
  str2 a1el, a2el;
10413
  char btype;
10414
  int hbc;
10415
  int n_b2formal = 0;           /* new in v0.2e */
10416
  int FORLIM;
10417
 
10418
  if (n_atoms == 0)
10419
    return;
10420
  FORLIM = n_atoms;
14179 bpr 10421
  for (i = 0; i < FORLIM; i++) {
10422
    if (atom[i].heavy) {
10423
            strcpy (elem, atom[i].element);
10424
            strcpy (atype, atom[i].atype);
10425
            if (!strcmp (atype, "C1 "))
10426
              molstat.n_C1++;
10427
            if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
10428
              molstat.n_C2++;
10429
            if (!strcmp (elem, "C "))
10430
              molstat.n_C++;
10431
            if (!strcmp (atype, "O2 "))
10432
              molstat.n_O2++;
10433
            if (!strcmp (atype, "O3 "))
10434
              molstat.n_O3++;
10435
            if (!strcmp (atype, "N1 "))
10436
              molstat.n_N1++;
10437
            if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
10438
                (!strcmp (atype, "NAM") && atom[i].arom == true))
10439
              /* v0.3n */
10440
              molstat.n_N2++;
10441
            if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
10442
                !strcmp (atype, "N3+") ||
10443
                (!strcmp (atype, "NAM") && atom[i].arom == false))
10444
              /* v0.3n */
10445
              molstat.n_N3++;
10446
            if (!strcmp (elem, "A "))   /* query atom */
10447
              molstat.n_QA++;
10448
            if (!strcmp (elem, "Q "))   /* query atom */
10449
              molstat.n_QA++;
10450
            if (!strcmp (elem, "X "))   /* query atom */
10451
              molstat.n_QA++;
10452
            if (!strcmp (elem, "S "))
10453
              molstat.n_S++;
10454
            if (!strcmp (elem, "SE"))
6785 bpr 10455
            molstat.n_SeTe++;
14179 bpr 10456
            if (!strcmp (elem, "TE"))
10457
              molstat.n_SeTe++;
10458
            if (!strcmp (elem, "F "))
10459
              molstat.n_F++;
10460
            if (!strcmp (elem, "CL"))
10461
              molstat.n_Cl++;
10462
            if (!strcmp (elem, "BR"))
10463
              molstat.n_Br++;
10464
            if (!strcmp (elem, "I "))
10465
              molstat.n_I++;
10466
            if (!strcmp (elem, "P "))
10467
              molstat.n_P++;
10468
            if (!strcmp (elem, "B "))
10469
              molstat.n_B++;
10470
            /* check for known metals */
10471
            if (atom[i].metal)  /* v0.3l */
10472
              molstat.n_Met++;
10473
            /* still missing: unknown elements */
6785 bpr 10474
 
14179 bpr 10475
            /* check number of heteroatom bonds per C atom */
10476
            if (!strcmp (elem, "C ")) {
6785 bpr 10477
              hbc = raw_hetbond_count (i + 1);
10478
              /* new in v0.2j (replaces hetbond_count) */
10479
              if (hbc >= 1)
14179 bpr 10480
                      molstat.n_CHB1p++;
6785 bpr 10481
              if (hbc >= 2)
14179 bpr 10482
                      molstat.n_CHB2p++;
6785 bpr 10483
              if (hbc >= 3)
14179 bpr 10484
                      molstat.n_CHB3p++;
6785 bpr 10485
              if (hbc == 4)
14179 bpr 10486
                      molstat.n_CHB4++;
6785 bpr 10487
            }
14179 bpr 10488
            if (atom[i].formal_charge != 0) {
6785 bpr 10489
              molstat.n_chg++;
10490
              //n_charges++;
10491
            }
14179 bpr 10492
            if (atom[i].nucleon_number != 0) {
6785 bpr 10493
              molstat.n_iso++;
10494
            }
14179 bpr 10495
            if (atom[i].radical_type != 0) {
6785 bpr 10496
              molstat.n_rad++;
10497
            }
14179 bpr 10498
            /* check for "other" elements;  v0.3l */
10499
            if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
10500
                && strcmp (elem, "O ") && strcmp (elem, "S ")
10501
                && strcmp (elem, "SE") && strcmp (elem, "TE")
10502
                && strcmp (elem, "P ") && strcmp (elem, "B ")
10503
                && strcmp (elem, "A ") && strcmp (elem, "Q "))
10504
              molstat.n_X++;
10505
            /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
10506
      /* p2c: checkmol.pas, line 8353:
10507
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10508
            /*$IFDEF extended_molstat */
10509
            if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
10510
                || !strcmp (elem, "K ") || !strcmp (elem, "RB")
10511
                || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
10512
              molstat.n_psg01++;
10513
            if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
10514
                || !strcmp (elem, "CA") || !strcmp (elem, "SR")
10515
                || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
10516
              molstat.n_psg02++;
10517
            if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
10518
                || !strcmp (elem, "GA") || !strcmp (elem, "IN")
10519
                || !strcmp (elem, "TL"))
10520
              molstat.n_psg13++;
10521
            if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
10522
                || !strcmp (elem, "GE") || !strcmp (elem, "SN")
10523
                || !strcmp (elem, "PB"))
10524
              molstat.n_psg14++;
10525
            if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
6785 bpr 10526
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
10527
              || !strcmp (elem, "BI"))
10528
            molstat.n_psg15++;
14179 bpr 10529
            if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
10530
                || !strcmp (elem, "SE") || !strcmp (elem, "TE")
10531
                || !strcmp (elem, "PO"))
10532
              molstat.n_psg16++;
10533
            if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
10534
                || !strcmp (elem, "BR") || !strcmp (elem, "I ")
10535
                || !strcmp (elem, "AT"))
10536
              molstat.n_psg17++;
10537
            if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
10538
                || !strcmp (elem, "AR") || !strcmp (elem, "KR")
10539
                || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
10540
              molstat.n_psg18++;
10541
            if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
10542
                || !strcmp (elem, "LU") || !strcmp (elem, "LR")
10543
                || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
10544
                || !strcmp (elem, "HF") || !strcmp (elem, "RF")
10545
                || !strcmp (elem, "V ") || !strcmp (elem, "NB")
10546
                || !strcmp (elem, "TA") || !strcmp (elem, "DB")
10547
                || !strcmp (elem, "CR") || !strcmp (elem, "MO")
10548
                || !strcmp (elem, "W ") || !strcmp (elem, "SG")
10549
                || !strcmp (elem, "MN") || !strcmp (elem, "TC")
10550
                || !strcmp (elem, "RE") || !strcmp (elem, "BH")
10551
                || !strcmp (elem, "FE") || !strcmp (elem, "RU")
10552
                || !strcmp (elem, "OS") || !strcmp (elem, "HS")
10553
                || !strcmp (elem, "CO") || !strcmp (elem, "RH")
10554
                || !strcmp (elem, "IR") || !strcmp (elem, "MT")
10555
                || !strcmp (elem, "NI") || !strcmp (elem, "PD")
10556
                || !strcmp (elem, "PT") || !strcmp (elem, "DS")
10557
                || !strcmp (elem, "CU") || !strcmp (elem, "AG")
10558
                || !strcmp (elem, "AU") || !strcmp (elem, "RG")
10559
                || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
10560
                || !strcmp (elem, "HG"))
10561
        /* p2c: checkmol.pas, line 8439:
10562
        * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
10563
              molstat.n_pstm++;
10564
            if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
10565
                || !strcmp (elem, "PR") || !strcmp (elem, "ND")
10566
                || !strcmp (elem, "PM") || !strcmp (elem, "SM")
10567
                || !strcmp (elem, "EU") || !strcmp (elem, "GD")
10568
                || !strcmp (elem, "TB") || !strcmp (elem, "DY")
10569
                || !strcmp (elem, "HO") || !strcmp (elem, "ER")
10570
                || !strcmp (elem, "TM") || !strcmp (elem, "YB")
10571
                || !strcmp (elem, "AC") || !strcmp (elem, "TH")
10572
                || !strcmp (elem, "PA") || !strcmp (elem, "U ")
10573
                || !strcmp (elem, "NP") || !strcmp (elem, "PU")
10574
                || !strcmp (elem, "AM") || !strcmp (elem, "CM")
10575
                || !strcmp (elem, "BK") || !strcmp (elem, "CF")
10576
                || !strcmp (elem, "ES") || !strcmp (elem, "FM")
10577
                || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
10578
      /* p2c: checkmol.pas, line 8439:
10579
      * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
10580
              molstat.n_psla++;
10581
            /*$ENDIF */
10582
          }                     /* is heavy */
10583
  }                             /* atoms */
10584
  if (n_bonds > 0) {
10585
    FORLIM = n_bonds;
10586
    for (i = 0; i < FORLIM; i++) {
10587
            a1 = bond[i].a1;
10588
            a2 = bond[i].a2;
10589
            strcpy (a1el, atom[a1 - 1].element);
10590
            strcpy (a2el, atom[a2 - 1].element);
10591
            btype = bond[i].btype;
10592
            if (bond[i].arom)
10593
              molstat.n_bar++;
10594
            else {
6785 bpr 10595
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
14179 bpr 10596
                      molstat.n_b1++;
6785 bpr 10597
              if (btype == 'D')
14179 bpr 10598
                     molstat.n_b2++;
6785 bpr 10599
              if (btype == 'T')
14179 bpr 10600
                      molstat.n_b3++;
6785 bpr 10601
            }
14179 bpr 10602
            /* v0.3n: ignore bonds to (explicit) hydrogens */
10603
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
10604
                (!strcmp (a1el, "O ") && !strcmp (a2el, "C "))) {
6785 bpr 10605
              if (btype == 'S')
14179 bpr 10606
                      molstat.n_C1O++;
6785 bpr 10607
              if (btype == 'D')
14179 bpr 10608
                      molstat.n_C2O++;
6785 bpr 10609
            }
14179 bpr 10610
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
10611
                (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
10612
              molstat.n_CN++;
10613
            if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
10614
                && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
10615
              molstat.n_XY++;
10616
            /* new in v0.3n: number of bonds belonging to more than one ring */
10617
            if (bond[i].ring_count > 1)
10618
              molstat.n_br2p++;
10619
          }
10620
  }                             /* bonds */
10621
  if (n_rings <= 0) {
6785 bpr 10622
      return;
14179 bpr 10623
  }                             /* rings */
6785 bpr 10624
  /* v0.3n */
10625
  n_countablerings = 0;         /* v0.3n */
10626
  FORLIM = n_rings;
14179 bpr 10627
  for (i = 1; i <= FORLIM; i++) {
10628
    if (ringprop[i - 1].envelope == false)      /* v0.3n */
10629
            n_countablerings++;
10630
    if (is_arene (i) && ringprop[i - 1].envelope == false) {
10631
      /* v0.3n: ignore envelope rings */
10632
            molstat.n_rAr++;
10633
            if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == false))
10634
              /* v0.3l */
10635
              molstat.n_rBz++;
10636
          }
10637
    get_ringstat (i);
10638
    if (ringprop[i - 1].arom == true && ringprop[i - 1].envelope == false)
10639
            /* new in v0.3n; replaces assignment below */
10640
            n_b2formal++;
10641
  }
6785 bpr 10642
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
10643
  /* in order to allow an isolated double bond in the needle */
10644
  /* to be matched as a ring fragment of an aromatic ring */
10645
  if (n_b2formal > molstat.n_bar / 2)
10646
    n_b2formal = molstat.n_bar / 2;
10647
  molstat.n_b2 += n_b2formal;
10648
}
10649
 
14179 bpr 10650
static void fix_ssr_ringcounts ()
6785 bpr 10651
{
10652
  /* new in v0.3n */
10653
  /* if SAR -> SSR fallback happens, set some molstat values */
10654
  /* to a maximum (ring counts for various ring sizes); */
10655
  /* this should be necessary only for ring sizes which */
10656
  /* are a) too large for the SSR (depending on ssr_vringsize) */
10657
  /* and b) which are likely to contain "envelope rings" */
10658
  /* (size 6 and above) */
10659
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
10660
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
10661
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
10662
  if (molstat.n_r6 == 0)
10663
    molstat.n_r6 = max_rings;
10664
  if (molstat.n_r7 == 0)
10665
    molstat.n_r7 = max_rings;
10666
  if (molstat.n_r8 == 0)
10667
    molstat.n_r8 = max_rings;
10668
  if (molstat.n_r9 == 0)
10669
    molstat.n_r9 = max_rings;
10670
  if (molstat.n_r10 == 0)
10671
    molstat.n_r10 = max_rings;
10672
  if (molstat.n_r11 == 0)
10673
    molstat.n_r11 = max_rings;
10674
  if (molstat.n_r12 == 0)
10675
    molstat.n_r12 = max_rings;
10676
  if (molstat.n_r13p == 0)
10677
    molstat.n_r13p = max_rings;
10678
}
10679
 
14179 bpr 10680
static void write_molstat ()
6785 bpr 10681
{
10682
  if (auto_ssr)                 /* v0.3n */
10683
    fix_ssr_ringcounts ();
10684
  printf ("n_atoms:%d;", n_heavyatoms);
10685
  /* count only non-H atoms (some molfiles contain explicit H's) */
10686
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
10687
    printf ("n_bonds:%d;", n_heavybonds);
14179 bpr 10688
  /* p2c: checkmol.pas, line 8471:
10689
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10690
#ifdef REDUCED_SAR
10691
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10692
    printf ("n_rings:%d;", n_countablerings);
10693
#else
10694
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10695
    printf ("n_rings:%d;", n_rings);
10696
#endif
10697
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
10698
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
10699
  if (molstat.n_chg > 0)        /* 0.3x */
10700
    printf ("n_chg:%d;", molstat.n_chg);
10701
 
10702
  if (molstat.n_C1 > 0)
10703
    printf ("n_C1:%d;", molstat.n_C1);
10704
  if (molstat.n_C2 > 0)
10705
    printf ("n_C2:%d;", molstat.n_C2);
10706
  /* requirement of a given number of sp3 carbons might be too restrictive, */
10707
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
10708
  if (molstat.n_C > 0)
10709
    printf ("n_C:%d;", molstat.n_C);
10710
  if (molstat.n_CHB1p > 0)
10711
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
10712
  if (molstat.n_CHB2p > 0)
10713
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
10714
  if (molstat.n_CHB3p > 0)
10715
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
10716
  if (molstat.n_CHB4 > 0)
10717
    printf ("n_CHB4:%d;", molstat.n_CHB4);
10718
  if (molstat.n_O2 > 0)
10719
    printf ("n_O2:%d;", molstat.n_O2);
10720
  if (molstat.n_O3 > 0)
10721
    printf ("n_O3:%d;", molstat.n_O3);
10722
  if (molstat.n_N1 > 0)
10723
    printf ("n_N1:%d;", molstat.n_N1);
10724
  if (molstat.n_N2 > 0)
10725
    printf ("n_N2:%d;", molstat.n_N2);
10726
  if (molstat.n_N3 > 0)
10727
    printf ("n_N3:%d;", molstat.n_N3);
10728
  if (molstat.n_S > 0)
10729
    printf ("n_S:%d;", molstat.n_S);
10730
  if (molstat.n_SeTe > 0)
10731
    printf ("n_SeTe:%d;", molstat.n_SeTe);
10732
  if (molstat.n_F > 0)
10733
    printf ("n_F:%d;", molstat.n_F);
10734
  if (molstat.n_Cl > 0)
10735
    printf ("n_Cl:%d;", molstat.n_Cl);
10736
  if (molstat.n_Br > 0)
10737
    printf ("n_Br:%d;", molstat.n_Br);
10738
  if (molstat.n_I > 0)
10739
    printf ("n_I:%d;", molstat.n_I);
10740
  if (molstat.n_P > 0)
10741
    printf ("n_P:%d;", molstat.n_P);
10742
  if (molstat.n_B > 0)
10743
    printf ("n_B:%d;", molstat.n_B);
10744
  if (molstat.n_Met > 0)
10745
    printf ("n_Met:%d;", molstat.n_Met);
10746
  if (molstat.n_X > 0)
10747
    printf ("n_X:%d;", molstat.n_X);
10748
  if (molstat.n_b1 > 0)
10749
    printf ("n_b1:%d;", molstat.n_b1);
10750
  if (molstat.n_b2 > 0)
10751
    printf ("n_b2:%d;", molstat.n_b2);
10752
  if (molstat.n_b3 > 0)
10753
    printf ("n_b3:%d;", molstat.n_b3);
10754
  if (molstat.n_bar > 0)
10755
    printf ("n_bar:%d;", molstat.n_bar);
10756
  if (molstat.n_C1O > 0)
10757
    printf ("n_C1O:%d;", molstat.n_C1O);
10758
  if (molstat.n_C2O > 0)
10759
    printf ("n_C2O:%d;", molstat.n_C2O);
10760
  if (molstat.n_CN > 0)
10761
    printf ("n_CN:%d;", molstat.n_CN);
10762
  if (molstat.n_XY > 0)
10763
    printf ("n_XY:%d;", molstat.n_XY);
10764
  if (molstat.n_r3 > 0)
10765
    printf ("n_r3:%d;", molstat.n_r3);
10766
  if (molstat.n_r4 > 0)
10767
    printf ("n_r4:%d;", molstat.n_r4);
10768
  if (molstat.n_r5 > 0)
10769
    printf ("n_r5:%d;", molstat.n_r5);
10770
  if (molstat.n_r6 > 0)
10771
    printf ("n_r6:%d;", molstat.n_r6);
10772
  if (molstat.n_r7 > 0)
10773
    printf ("n_r7:%d;", molstat.n_r7);
10774
  if (molstat.n_r8 > 0)
10775
    printf ("n_r8:%d;", molstat.n_r8);
10776
  if (molstat.n_r9 > 0)
10777
    printf ("n_r9:%d;", molstat.n_r9);
10778
  if (molstat.n_r10 > 0)
10779
    printf ("n_r10:%d;", molstat.n_r10);
10780
  if (molstat.n_r11 > 0)
10781
    printf ("n_r11:%d;", molstat.n_r11);
10782
  if (molstat.n_r12 > 0)
10783
    printf ("n_r12:%d;", molstat.n_r12);
10784
  if (molstat.n_r13p > 0)
10785
    printf ("n_r13p:%d;", molstat.n_r13p);
10786
  if (molstat.n_rN > 0)
10787
    printf ("n_rN:%d;", molstat.n_rN);
10788
  if (molstat.n_rN1 > 0)
10789
    printf ("n_rN1:%d;", molstat.n_rN1);
10790
  if (molstat.n_rN2 > 0)
10791
    printf ("n_rN2:%d;", molstat.n_rN2);
10792
  if (molstat.n_rN3p > 0)
10793
    printf ("n_rN3p:%d;", molstat.n_rN3p);
10794
  if (molstat.n_rO > 0)
10795
    printf ("n_rO:%d;", molstat.n_rO);
10796
  if (molstat.n_rO1 > 0)
10797
    printf ("n_rO1:%d;", molstat.n_rO1);
10798
  if (molstat.n_rO2p > 0)
10799
    printf ("n_rO2p:%d;", molstat.n_rO2p);
10800
  if (molstat.n_rS > 0)
10801
    printf ("n_rS:%d;", molstat.n_rS);
10802
  if (molstat.n_rX > 0)
10803
    printf ("n_rX:%d;", molstat.n_rX);
10804
  if (molstat.n_rAr > 0)
10805
    printf ("n_rar:%d;", molstat.n_rAr);
10806
/* p2c: checkmol.pas, line 8532:
10807
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10808
  /*$IFDEF extended_molstat */
10809
  if (molstat.n_rBz > 0)
10810
    printf ("n_rbz:%d;", molstat.n_rBz);
10811
  if (molstat.n_br2p > 0)
10812
    printf ("n_br2p:%d;", molstat.n_br2p);
10813
  if (molstat.n_psg01 > 0)
10814
    printf ("n_psg01:%d;", molstat.n_psg01);
10815
  if (molstat.n_psg02 > 0)
10816
    printf ("n_psg02:%d;", molstat.n_psg02);
10817
  if (molstat.n_psg13 > 0)
10818
    printf ("n_psg13:%d;", molstat.n_psg13);
10819
  if (molstat.n_psg14 > 0)
10820
    printf ("n_psg14:%d;", molstat.n_psg14);
10821
  if (molstat.n_psg15 > 0)
10822
    printf ("n_psg15:%d;", molstat.n_psg15);
10823
  if (molstat.n_psg16 > 0)
10824
    printf ("n_psg16:%d;", molstat.n_psg16);
10825
  if (molstat.n_psg17 > 0)
10826
    printf ("n_psg17:%d;", molstat.n_psg17);
10827
  if (molstat.n_psg18 > 0)
10828
    printf ("n_psg18:%d;", molstat.n_psg18);
10829
  if (molstat.n_pstm > 0)
10830
    printf ("n_pstm:%d;", molstat.n_pstm);
10831
  if (molstat.n_psla > 0)
10832
    printf ("n_psla:%d;", molstat.n_psla);
10833
  if (molstat.n_iso > 0)
10834
    printf ("n_iso:%d;", molstat.n_iso);
10835
  if (molstat.n_rad > 0)
10836
    printf ("n_rad:%d;", molstat.n_rad);
10837
  /*$ENDIF */
10838
  putchar ('\n');
10839
}
10840
 
14179 bpr 10841
static void write_molstat_X ()
6785 bpr 10842
{
10843
  if (auto_ssr)                 /* v0.3n */
10844
    fix_ssr_ringcounts ();
14179 bpr 10845
    /* p2c: checkmol.pas, line 8556:
10846
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10847
#ifdef REDUCED_SAR
10848
  printf ("%d,", n_heavyatoms);
10849
  printf ("%d,", n_heavybonds);
10850
  printf ("%d,", n_countablerings);
14179 bpr 10851
    /* v0.3n: n_rings =?> n_countablerings */
6785 bpr 10852
#else
10853
  printf ("%d,", n_heavyatoms);
10854
  printf ("%d,", n_heavybonds);
10855
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
10856
#endif
10857
  printf ("%d,", molstat.n_QA);
10858
  printf ("%d,", molstat.n_QB);
10859
 
10860
  /* 0.3x */
10861
  printf ("%d,", molstat.n_chg);
10862
 
10863
  printf ("%d,", molstat.n_C1);
10864
  printf ("%d,", molstat.n_C2);
10865
  printf ("%d,", molstat.n_C);
10866
  printf ("%d,", molstat.n_CHB1p);
10867
  printf ("%d,", molstat.n_CHB2p);
10868
  printf ("%d,", molstat.n_CHB3p);
10869
  printf ("%d,", molstat.n_CHB4);
10870
  printf ("%d,", molstat.n_O2);
10871
  printf ("%d,", molstat.n_O3);
10872
  printf ("%d,", molstat.n_N1);
10873
  printf ("%d,", molstat.n_N2);
10874
  printf ("%d,", molstat.n_N3);
10875
  printf ("%d,", molstat.n_S);
10876
  printf ("%d,", molstat.n_SeTe);
10877
  printf ("%d,", molstat.n_F);
10878
  printf ("%d,", molstat.n_Cl);
10879
  printf ("%d,", molstat.n_Br);
10880
  printf ("%d,", molstat.n_I);
10881
  printf ("%d,", molstat.n_P);
10882
  printf ("%d,", molstat.n_B);
10883
  printf ("%d,", molstat.n_Met);
10884
  printf ("%d,", molstat.n_X);
10885
  printf ("%d,", molstat.n_b1);
10886
  printf ("%d,", molstat.n_b2);
10887
  printf ("%d,", molstat.n_b3);
10888
  printf ("%d,", molstat.n_bar);
10889
  printf ("%d,", molstat.n_C1O);
10890
  printf ("%d,", molstat.n_C2O);
10891
  printf ("%d,", molstat.n_CN);
10892
  printf ("%d,", molstat.n_XY);
10893
  printf ("%d,", molstat.n_r3);
10894
  printf ("%d,", molstat.n_r4);
10895
  printf ("%d,", molstat.n_r5);
10896
  printf ("%d,", molstat.n_r6);
10897
  printf ("%d,", molstat.n_r7);
10898
  printf ("%d,", molstat.n_r8);
10899
  printf ("%d,", molstat.n_r9);
10900
  printf ("%d,", molstat.n_r10);
10901
  printf ("%d,", molstat.n_r11);
10902
  printf ("%d,", molstat.n_r12);
10903
  printf ("%d,", molstat.n_r13p);
10904
  printf ("%d,", molstat.n_rN);
10905
  printf ("%d,", molstat.n_rN1);
10906
  printf ("%d,", molstat.n_rN2);
10907
  printf ("%d,", molstat.n_rN3p);
10908
  printf ("%d,", molstat.n_rO);
10909
  printf ("%d,", molstat.n_rO1);
10910
  printf ("%d,", molstat.n_rO2p);
10911
  printf ("%d,", molstat.n_rS);
10912
  printf ("%d,", molstat.n_rX);
10913
  printf ("%d", molstat.n_rAr);
14179 bpr 10914
  /* p2c: checkmol.pas, line 8579:
10915
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10916
  /*$IFDEF extended_molstat */
10917
  printf (",%d", molstat.n_rBz);
10918
  printf (",%d", molstat.n_br2p);
10919
  printf (",%d", molstat.n_psg01);
10920
  printf (",%d", molstat.n_psg02);
10921
  printf (",%d", molstat.n_psg13);
10922
  printf (",%d", molstat.n_psg14);
10923
  printf (",%d", molstat.n_psg15);
10924
  printf (",%d", molstat.n_psg16);
10925
  printf (",%d", molstat.n_psg17);
10926
  printf (",%d", molstat.n_psg18);
10927
  printf (",%d", molstat.n_pstm);
10928
  printf (",%d", molstat.n_psla);
10929
  printf (",%d", molstat.n_iso);
10930
  printf (",%d\n", molstat.n_rad);
10931
  /*$ENDIF */
10932
}
10933
 
10934
/* routines for substructure matching */
10935
 
14179 bpr 10936
static int find_ndl_ref_atom ()
6785 bpr 10937
{
6786 kbelabas 10938
  int i;
6785 bpr 10939
  int score = -1, index = 0;
10940
  int n_nb, n_hc, FORLIM;
10941
 
10942
  /* finds a characteristic atom in the needle molecule, */
10943
  /* i.e., one with as many substituents as possible and */
10944
  /* with as many heteroatom substitutents as possible; */
10945
  /* added in v0.2d: make sure that reference atom is a heavy atom */
10946
  /* and not (accidentally) an explicit hydrogen; */
10947
  /* new in v0.3d: special treatment in case of E/Z geometry search */
10948
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
10949
  /* matchpath, regardless where the recursive search starts; */
10950
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
10951
  /* added in v0.3o: needle atom must be "tagged" in order to be */
10952
  /* selected (prevents unconnected fragments from being overlooked) */
10953
  if (ndl_n_atoms == 0)
6786 kbelabas 10954
    return false;
14179 bpr 10955
  if (ez_search && ndl_n_heavyatoms > 2) {
10956
    FORLIM = ndl_n_atoms;
10957
    for (i = 1; i <= FORLIM; i++) {                     /* ignore sp2-carbons if not aromatic */
10958
           /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = true)) then */
10959
            if (ndl_alkene_C (i) == false && ndl_atom[i - 1].tag) {                     /* v0.3o */
6785 bpr 10960
              n_nb = ndl_atom[i - 1].neighbor_count;
10961
              n_hc = ndl_hetatom_count (i);
14179 bpr 10962
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy) {
10963
                /* v0.3j */
10964
                index = i;
10965
                score = n_nb * 11 + n_hc * 7;   /* changed in v0.3j */
10966
              }
6785 bpr 10967
            }
14179 bpr 10968
          }
10969
  }
6785 bpr 10970
  /* it is possible that no suitable reference atom has been found here */
10971
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
14179 bpr 10972
  if (index == 0) {
10973
    ez_search = false;  /* just in case it was true */
10974
    opt_geom = false;           /* just in case it was true */
10975
    FORLIM = ndl_n_atoms;
10976
    for (i = 1; i <= FORLIM; i++) {
10977
            n_nb = ndl_atom[i - 1].neighbor_count;
10978
            n_hc = ndl_hetatom_count (i);
10979
            if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
10980
                ndl_atom[i - 1].tag) {                  /* v0.3j */
6785 bpr 10981
              index = i;
10982
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
10983
            }
14179 bpr 10984
            /* v0.3o */
10985
          }
10986
  }
6785 bpr 10987
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
10988
  if (index == 0)               /* just to be sure... */
10989
    index++;
10990
  return index;
10991
}
10992
 
14179 bpr 10993
static void cv_init ()
6785 bpr 10994
{
10995
  /* new in v0.3j */
10996
  int i;
10997
 
10998
  if (cv == NULL)
10999
    return;
11000
  memset (cv, 0, sizeof (connval_type));
11001
 
11002
  for (i = 0; i < ndl_n_atoms; i++)
11003
    cv[i].def = ndl_atom[i].neighbor_count;
11004
}
11005
 
14179 bpr 11006
static int cv_count ()
6785 bpr 11007
{
11008
  /* new in v0.3j, modified in v0.3m */
11009
  int i, j;
11010
  int cvlist[max_atoms];
11011
  int cvdef;
11012
  boolean isnew;
11013
  int entries = 0;
11014
  int FORLIM;
11015
 
11016
  if (cv == NULL)
11017
    return 0;
11018
  memset (cvlist, 0, sizeof (int) * max_atoms);
11019
  FORLIM = ndl_n_atoms;
14179 bpr 11020
  for (i = 0; i < FORLIM; i++) {
11021
    if (ndl_atom[i].heavy == true) {
11022
            cvdef = cv[i].def;
11023
            isnew = true;
11024
            if (entries > 0) {
11025
              for (j = 0; j < entries; j++) {
11026
                      if (cvlist[j] == cvdef)
11027
                        isnew = false;
11028
                    }
6785 bpr 11029
            }
14179 bpr 11030
            if (isnew) {
11031
                entries++;
11032
                cvlist[entries - 1] = cvdef;
6785 bpr 11033
            }
14179 bpr 11034
            /* now we have a list of unique connection values */
11035
          }
11036
  }
6785 bpr 11037
  return entries;
11038
}
11039
 
14179 bpr 11040
static int cv_iterate (n_cv_prev)
6785 bpr 11041
     int n_cv_prev;
11042
{
11043
  /* new in v0.3j, modified in v0.3m */
6788 kbelabas 11044
  int i, j;
6785 bpr 11045
  neighbor_rec nb;
11046
  int nnb, nsum, n_cv, FORLIM;
11047
 
11048
  if (cv == NULL || ndl_n_atoms == 0)
6788 kbelabas 11049
    return false;
6785 bpr 11050
  FORLIM = ndl_n_atoms;
11051
  /* update the connection values (Morgan algorithm) */
11052
 
11053
  memset (nb, 0, sizeof (neighbor_rec));
11054
 
14179 bpr 11055
  for (i = 1; i <= FORLIM; i++) {
11056
    if (ndl_atom[i - 1].heavy == true) {
11057
            get_ndl_neighbors (nb, i);
11058
            nnb = ndl_atom[i - 1].neighbor_count;
11059
            nsum = 0;
11060
            if (nnb > 0) {
11061
              for (j = 0; j < nnb; j++) {
11062
                if (ndl_atom[nb[j] - 1].heavy == true)
11063
                  nsum += cv[nb[j] - 1].def;
11064
              }
6785 bpr 11065
            }
14179 bpr 11066
            cv[i - 1].tmp = nsum;
11067
          }
11068
  }
6785 bpr 11069
  n_cv = cv_count ();
14179 bpr 11070
  if (n_cv > n_cv_prev) {
11071
    FORLIM = ndl_n_atoms;
11072
    for (i = 0; i < FORLIM; i++)
11073
            cv[i].def = cv[i].tmp;
11074
  }
6785 bpr 11075
  return n_cv;
11076
}
11077
 
14179 bpr 11078
static int find_ndl_ref_atom_cv ()
6785 bpr 11079
{
11080
  /* new in v0.3j, modified in v0.3m */
11081
  int Result, i;
11082
  int res = 1, it = 0;
11083
  int n_cv;
11084
  int n_cv_prev = 0;
11085
  boolean finished = false;
11086
  int cvmax = 0;
11087
  int FORLIM;
11088
 
11089
  if (ndl_n_atoms == 0)
11090
    return 0;
11091
  /* try */
11092
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
11093
  /* except
11094
     on e:Eoutofmemory do
11095
     begin
11096
     res := find_ndl_ref_atom;
11097
     $IFDEF debug
11098
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
11099
     $ENDIF
11100
     end;
11101
     end; */
11102
  cv_init ();
14179 bpr 11103
  do {
11104
    it++;                       /* iteration counter (a safeguard against infinite loops) */
11105
    n_cv = cv_iterate (n_cv_prev);
11106
    if (n_cv <= n_cv_prev)
11107
            finished = true;
11108
    n_cv_prev = n_cv;
11109
  }
6785 bpr 11110
  while (!(finished || it > 10000));
11111
  FORLIM = ndl_n_atoms;
11112
  /* now that we have canonical connection values (Morgan algorithm), */
11113
  /* pick the atom with the highest value */
11114
  /* added in v0.3o: atom must be "tagged" */
14179 bpr 11115
  for (i = 1; i <= FORLIM; i++) {
6785 bpr 11116
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
14179 bpr 11117
    if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == false || ez_search == false))
11118
              && ndl_atom[i - 1].tag) {                 /* v0.3o */
11119
            cvmax = cv[i - 1].def;
11120
            res = i;
11121
          }
11122
  }
6785 bpr 11123
  Result = res;
11124
  /* try */
14179 bpr 11125
  if (cv != NULL) {
6785 bpr 11126
      free (cv);
11127
      cv = NULL;
11128
    }
11129
  /* except
11130
     on e:Einvalidpointer do begin end;
11131
     end; */
11132
  return Result;
11133
}
11134
 
14179 bpr 11135
static boolean atomtypes_OK_strict (ndl_a, hst_a)
6785 bpr 11136
     int ndl_a, hst_a;
11137
{
11138
  /* new in v0.2f */
11139
  str2 ndl_el;
11140
  str3 ndl_atype;
11141
  str2 hst_el;
11142
  str3 hst_atype;
11143
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
11144
  boolean res = false;
11145
 
11146
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11147
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
11148
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11149
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11150
  strcpy (hst_el, atom[hst_a - 1].element);
11151
  strcpy (hst_atype, atom[hst_a - 1].atype);
11152
  hst_nbc = atom[hst_a - 1].neighbor_count;
11153
  hst_Htot = atom[hst_a - 1].Htot;
11154
  /* v0.3o: formal charges must be the same */
11155
 
11156
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
11157
    return false;
11158
 
11159
  /* v0.3x: isotope nucleon numbers must be the same */
11160
 
11161
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
11162
    return false;
11163
 
11164
  /* v0.3x: radicals must be the same */
11165
 
11166
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11167
    return false;
11168
 
11169
  if (!strcmp (ndl_atype, hst_atype))
11170
    res = true;
14179 bpr 11171
  else {
11172
    if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom && atom[hst_a - 1].arom)
11173
            res = true;
11174
    if (ndl_querymol && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
11175
            res = true;         /* 0.3 p */
11176
  }
6785 bpr 11177
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
11178
    res = true;
14179 bpr 11179
  if (!strcmp (ndl_el, "Q ")) {
11180
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
11181
            res = true;
11182
  }
11183
  if (!strcmp (ndl_el, "X ")) {
11184
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11185
            !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11186
            || !strcmp (hst_el, "AT"))
11187
          res = true;
11188
  }
6785 bpr 11189
  /* if needle atom has more substituents than haystack atom ==> no match */
11190
  if (ndl_nbc > hst_nbc)
11191
    res = false;
11192
  /* check for explicit hydrogens */
11193
  if (ndl_Hexp > hst_Htot)
11194
    res = false;
14179 bpr 11195
    /* p2c: checkmol.pas, line 8859:
11196
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11197
    /*$IFDEF debug */
11198
    /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
6785 bpr 11199
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
14179 bpr 11200
    /*$ENDIF */
11201
    /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
11202
  if (opt_fp) {
11203
    if (strcmp (ndl_el, hst_el))
11204
            res = false;
11205
  }
6785 bpr 11206
  return res;
11207
}
11208
 
14179 bpr 11209
static boolean atomtypes_OK (ndl_a, hst_a)
6785 bpr 11210
     int ndl_a, hst_a;
11211
{
11212
  str2 ndl_el, hst_el;
11213
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
11214
  boolean res = false;
11215
 
11216
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
11217
    return false;
11218
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
11219
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
11220
  /* are tolerated (this is a feature, not a bug) */
14179 bpr 11221
  if (opt_chg) {
11222
    if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
6785 bpr 11223
        return false;
14179 bpr 11224
  }
11225
  //  else
11226
  //    {
11227
  //      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
11228
  //        atom[hst_a - 1].formal_charge != 0 &&
11229
  //        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
11230
  //      return false;
11231
  //    }
11232
  //
11233
  //  /* v0.3x: isotopes must be the same */
11234
  if (opt_iso) {
11235
    if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
11236
            return false;
11237
  }
11238
  //  else
11239
  //    {
11240
  //      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
11241
  //        atom[hst_a - 1].nucleon_number != 0 &&
11242
  //        ndl_atom[ndl_a - 1].nucleon_number !=
11243
  //        atom[hst_a - 1].nucleon_number)
11244
  //      return false;
11245
  //    }
11246
  //
11247
  //  /* v0.3x: radicals must be the same */
11248
  if (opt_rad) {
11249
    if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11250
            return false;
11251
  }
11252
  //  else
11253
  //    {
11254
  //      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
11255
  //        atom[hst_a - 1].radical_type != 0 &&
11256
  //        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11257
  //      return false;
11258
  //    }
6785 bpr 11259
 
11260
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
14179 bpr 11261
  if (opt_exact && atom[hst_a - 1].tag == true) {
11262
    /* p2c: checkmol.pas, line 8899:
11263
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11264
      /*$IFDEF debug */
11265
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
11266
      /*$ENDIF */
11267
      return false;
14179 bpr 11268
  }
6785 bpr 11269
  if (opt_strict)               /* new in v0.2f */
11270
    return (atomtypes_OK_strict (ndl_a, hst_a));
11271
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11272
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11273
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11274
  strcpy (hst_el, atom[hst_a - 1].element);
11275
  hst_nbc = atom[hst_a - 1].neighbor_count;
11276
  hst_Htot = atom[hst_a - 1].Htot;
11277
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
11278
    res = true;
11279
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
11280
    res = true;
14179 bpr 11281
  if (!strcmp (ndl_el, "Q ")) {
11282
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
11283
            res = true;
11284
  }
11285
  if (!strcmp (ndl_el, "X ")) {
11286
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11287
              !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11288
              || !strcmp (hst_el, "AT"))
11289
            res = true;
11290
  }
6785 bpr 11291
  /* v0.3o: in exact mode, check for identical neighbor_count */
14179 bpr 11292
  if (opt_exact) {
11293
    if (ndl_nbc != hst_nbc) {
6785 bpr 11294
          res = false;
14179 bpr 11295
    /* p2c: checkmol.pas, line 8934:
11296
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11297
          /*$IFDEF debug */
11298
          //debugoutput
11299
          //  ("exact match failed: different number of neighbor atoms");
11300
          /*$ENDIF */
11301
          }
11302
  }
6785 bpr 11303
  /* if needle atom has more substituents than haystack atom ==> no match */
11304
  if (ndl_nbc > hst_nbc)
11305
    res = false;
11306
  /* check for explicit hydrogens */
11307
  if (ndl_Hexp > hst_Htot)
11308
    res = false;
14179 bpr 11309
  /* p2c: checkmol.pas, line 8943:
11310
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11311
  /*$IFDEF debug */
11312
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
11313
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
11314
  /*$ENDIF */
11315
  return res;
11316
}
11317
 
14179 bpr 11318
static boolean bondtypes_OK_strict (ndl_b, hst_b)
6785 bpr 11319
     int ndl_b, hst_b;
11320
{
11321
  boolean ndl_arom, hst_arom;
11322
  char ndl_btype, hst_btype;
11323
  int ndl_rc;                   /* new in v0.3d */
11324
  int hst_rc;                   /* new in v0.3d */
11325
  int ndl_btopo;                /* new in v0.3d */
11326
  boolean res = false;
14179 bpr 11327
  /* p2c: checkmol.pas, line 8960:
11328
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11329
  /*$IFDEF debug */
11330
  /*char na[256]; char ha[256];*/
11331
  char tstr[256];
11332
 
11333
  /*$ENDIF */
14179 bpr 11334
  /* p2c: checkmol.pas, line 8966:
11335
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11336
  /*$IFDEF debug */
11337
  *tstr = '\0';                 /* for debugging purposes only */
11338
  /*$ENDIF */
11339
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11340
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11341
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11342
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
11343
  hst_arom = bond[hst_b - 1].arom;
11344
  hst_btype = bond[hst_b - 1].btype;
11345
  hst_rc = bond[hst_b - 1].ring_count;
14179 bpr 11346
  /* p2c: checkmol.pas, line 8976:
11347
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11348
   /*$IFDEF debug */
11349
   /*if (ndl_arom)
11350
     strcpy (na, "(ar)");
11351
   else
11352
     *na = '\0';
11353
   if (hst_arom)
11354
     strcpy (ha, "(ar)");
11355
   else
11356
     *ha = '\0';*/
11357
   /*$ENDIF */
6785 bpr 11358
  if (ndl_arom == true && hst_arom == true)
11359
    res = true;
14179 bpr 11360
  if (ndl_arom == false && hst_arom == false) {
11361
    if (ndl_btype == hst_btype)
11362
            res = true;
11363
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
11364
            res = true;
11365
    if (ndl_btype == 's' && hst_btype == 'S')
11366
            res = true;
11367
    if (ndl_btype == 'd' && hst_btype == 'D')
11368
            res = true;
11369
  }
6785 bpr 11370
  /* a little exception: */
14179 bpr 11371
  if (ndl_arom == false && hst_arom == true) {
11372
    if (ndl_btype == 'A')
11373
            res = true;
11374
    if (ndl_btype == 's' || ndl_btype == 'd')
11375
            res = true;
11376
    if (ndl_bond[ndl_b - 1].q_arom)
11377
            res = true;         /* 0.3p */
11378
  }
6785 bpr 11379
  if (ndl_btype == 'a')
11380
    res = true;
11381
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
14179 bpr 11382
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc) {
11383
    if (ndl_rc != hst_rc) {
11384
            res = false;                /* this excludes further ring annulations as well as */
11385
      /* p2c: checkmol.pas, line 9001:
11386
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11387
            /*$IFDEF debug */
11388
            /* open-chains query structures to be found in rings */
11389
            /*
11390
               tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
11391
            /*$ENDIF */
11392
          }
11393
  }
11394
  else {
11395
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc) {
11396
            res = false;
11397
    /* p2c: checkmol.pas, line 9010:
11398
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11399
          /*$IFDEF debug */
11400
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
11401
          /*$ENDIF */
14179 bpr 11402
          }
11403
  }
11404
  /* p2c: checkmol.pas, line 9015:
11405
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11406
    /*$IFDEF debug */
11407
    /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11408
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11409
    /*$ENDIF */
6785 bpr 11410
  return res;
11411
}
11412
 
14179 bpr 11413
static boolean bondtypes_OK (ndl_b, hst_b)
6785 bpr 11414
     int ndl_b, hst_b;
11415
{
11416
  boolean ndl_arom, hst_arom;
11417
  char ndl_btype, hst_btype;
11418
  int ndl_rc;                   /* new in v0.3d */
11419
  int hst_rc;                   /* new in v0.3d */
11420
  int ndl_btopo;                /* new in v0.3d */
11421
  boolean res = false;
14179 bpr 11422
  /* p2c: checkmol.pas, line 9032:
11423
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11424
  /*$IFDEF debug */
11425
  /*char na[256], ha[256];*/
11426
  char tstr[256];
11427
  /*$ENDIF */
11428
  int a1, a2;
11429
  str2 a1_el, a2_el;
11430
 
11431
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
11432
    return false;
11433
  if (opt_strict)               /* new in v0.2f */
11434
    return (bondtypes_OK_strict (ndl_b, hst_b));
14179 bpr 11435
  /* p2c: checkmol.pas, line 9051:
11436
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11437
  /*$IFDEF debug */
11438
  *tstr = '\0';                 /* for debug purposes only */
11439
  /*$ENDIF */
11440
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11441
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11442
  hst_arom = bond[hst_b - 1].arom;
11443
  hst_btype = bond[hst_b - 1].btype;
11444
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11445
  hst_rc = bond[hst_b - 1].ring_count;
11446
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
14179 bpr 11447
  /* p2c: checkmol.pas, line 9061:
11448
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11449
    /*$IFDEF debug */
11450
    //if (ndl_arom)
11451
  //    strcpy (na, "(ar)");
11452
  //  else
11453
  //    *na = '\0';
11454
  //  if (hst_arom)
11455
  //    strcpy (ha, "(ar)");
11456
  //  else
11457
  //    *ha = '\0';
6785 bpr 11458
  /*$ENDIF */
11459
  if (ndl_arom == true && hst_arom == true)
11460
    res = true;
14179 bpr 11461
  if (ndl_arom == false && hst_arom == false) {
11462
    if (ndl_btype == hst_btype)
11463
            res = true;
11464
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
11465
            res = true;
11466
    if (ndl_btype == 's' && hst_btype == 'S')
11467
            res = true;
11468
    if (ndl_btype == 'd' && hst_btype == 'D')
11469
            res = true;
11470
  }
6785 bpr 11471
  /* a little exception: */
14179 bpr 11472
  if (ndl_arom == false && hst_arom == true) {
11473
    if (ndl_btype == 'A')
6785 bpr 11474
            res = true;
14179 bpr 11475
    if (ndl_btype == 's' || ndl_btype == 'd')
11476
            res = true;
11477
    if (ndl_btype == 'D') {                     /* added in 0.2d: do not accept C=O etc. as C-O/arom */
11478
            a1 = ndl_bond[ndl_b - 1].a1;
11479
            a2 = ndl_bond[ndl_b - 1].a2;
11480
            strcpy (a1_el, ndl_atom[a1 - 1].element);
11481
            strcpy (a2_el, ndl_atom[a2 - 1].element);
11482
            if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
11483
                && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
11484
                && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
11485
                && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
11486
              res = true;
11487
          }
11488
    if (ndl_bond[ndl_b - 1].q_arom)
11489
            res = true;         /* 0.3p */
11490
  }
6785 bpr 11491
  if (ndl_btype == 'a')
11492
    res = true;
11493
  /* new in v0.3d: obey topology requirements in query structure */
14179 bpr 11494
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any) {
11495
    if (ndl_btopo == btopo_ring && hst_rc == 0)
11496
      res = false;
11497
    if (ndl_btopo == btopo_chain && hst_rc > 0)
11498
      res = false;
11499
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
11500
      res = false;
11501
    if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
11502
      res = false;
11503
  }
11504
  /* p2c: checkmol.pas, line 9098:
11505
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11506
    /*$IFDEF debug */
11507
    /* if res = false then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
11508
    /*$ENDIF */
11509
  /* p2c: checkmol.pas, line 9102:
11510
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11511
    /*$IFDEF debug */
11512
    /*
11513
       if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11514
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11515
    /*$ENDIF */
6785 bpr 11516
  return res;
11517
}
11518
 
14179 bpr 11519
static boolean matrix_OK (m, ndl_dim, hst_dim)
6785 bpr 11520
boolean (*m)[max_neighbors];
11521
     int ndl_dim, hst_dim;
11522
{
11523
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
11524
  boolean mr = false;
11525
  matchmatrix lm;
11526
  int i, ii, j, lndl_dim, lhst_dim;
11527
 
11528
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
11529
      hst_dim > max_neighbors || ndl_dim > hst_dim)
11530
    return false;
14179 bpr 11531
  if (ndl_dim == 1) {
11532
    for (i = 0; i < hst_dim; i++) {
11533
            if (m[0][i])
11534
              mr = true;
11535
          }
11536
    return mr;
11537
  }
11538
  for (i = 1; i <= hst_dim; i++) {
11539
    if (m[0][i - 1]) {
11540
            /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
11541
            memset (lm, false, sizeof (matchmatrix));
11542
            for (j = 2; j <= ndl_dim; j++) {
6785 bpr 11543
              lhst_dim = 0;
14179 bpr 11544
              for (ii = 1; ii <= hst_dim; ii++) {
11545
                if (ii != i) {
11546
                  lhst_dim++;
11547
                  lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
11548
                }
11549
              }
6785 bpr 11550
            }
14179 bpr 11551
            lndl_dim = ndl_dim - 1;
11552
            if (matrix_OK (lm, lndl_dim, lhst_dim)) {                   /* recursive call to matrix_OK */
6785 bpr 11553
              return true;
14179 bpr 11554
            /* stop any further work immediately */
6785 bpr 11555
            }
14179 bpr 11556
          }
11557
  }
6785 bpr 11558
  return false;
11559
}
11560
 
14179 bpr 11561
static boolean is_flat (angle_deg)
6785 bpr 11562
     double angle_deg;
11563
{
11564
  /* new in v0.3j */
11565
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
11566
    return false;
11567
  else
11568
    return true;
11569
}
11570
 
14179 bpr 11571
static boolean chirality_OK (ndl_cp, hst_cp)
6785 bpr 11572
     int *ndl_cp, *hst_cp;
11573
{
11574
  boolean res = true;
11575
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
11576
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
11577
  int level = 0;
11578
  int i;
11579
  boolean up = false, down = false, updown = false;
11580
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
11581
 
11582
  /* fill temporary atom variables */
11583
  ta1 = ndl_cp[0];              /* this is the central atom */
11584
  ta2 = ndl_cp[1];
11585
  ta3 = ndl_cp[2];
11586
  ta4 = ndl_cp[3];
11587
  /* first, get the central atom of the needle */
11588
  np2.x = ndl_atom[ta1 - 1].x;
11589
  np2.y = ndl_atom[ta1 - 1].y;
11590
  np2.z = ndl_atom[ta1 - 1].z;
11591
  /* next, do the same for all 3 substituent atoms */
11592
  np1.x = ndl_atom[ta2 - 1].x;
11593
  np1.y = ndl_atom[ta2 - 1].y;
11594
  np1.z = ndl_atom[ta2 - 1].z;
11595
  np3.x = ndl_atom[ta3 - 1].x;
11596
  np3.y = ndl_atom[ta3 - 1].y;
11597
  np3.z = ndl_atom[ta3 - 1].z;
11598
  np4.x = ndl_atom[ta4 - 1].x;
11599
  np4.y = ndl_atom[ta4 - 1].y;
11600
  np4.z = ndl_atom[ta4 - 1].z;
11601
  /* now check all needle bonds if we should care about up/down bonds */
14179 bpr 11602
  if (ndl_n_bonds > 0) {
11603
    FORLIM = ndl_n_bonds;
11604
    for (i = 0; i < FORLIM; i++) {
11605
            if (ndl_bond[i].stereo == bstereo_up ||
11606
                  ndl_bond[i].stereo == bstereo_down) {
6785 bpr 11607
              ba1 = ndl_bond[i].a1;
11608
              ba2 = ndl_bond[i].a2;
14179 bpr 11609
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up) {
11610
                      up = true;
11611
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11612
                        updown = true;
11613
                        if (ba2 == ta2)
11614
                                np1.z += 0.8;
11615
                        if (ba2 == ta3)
11616
                                np3.z += 0.8;
11617
                        if (ba2 == ta4)
11618
                                np4.z += 0.8;
11619
                      }
11620
                      else
11621
                        level++;
6785 bpr 11622
                    }
14179 bpr 11623
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down) {
11624
                      down = true;
11625
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11626
                        updown = true;
11627
                        if (ba2 == ta2)
11628
                                np1.z -= 0.8;
11629
                        if (ba2 == ta3)
11630
                                np3.z -= 0.8;
11631
                        if (ba2 == ta4)
11632
                                np4.z -= 0.8;
11633
                      }
11634
                      else
11635
                        level--;
6785 bpr 11636
                    }
14179 bpr 11637
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up) {
11638
                      down = true;
11639
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11640
                        updown = true;
11641
                        if (ba1 == ta2)
11642
                          np1.z -= 0.8;
11643
                        if (ba1 == ta3)
11644
                          np3.z -= 0.8;
11645
                        if (ba1 == ta4)
11646
                          np4.z -= 0.8;
11647
                      }
11648
                      else
11649
                        level--;
6785 bpr 11650
                    }
14179 bpr 11651
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down) {
11652
                      up = true;
11653
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11654
                        updown = true;
11655
                        if (ba1 == ta2)
11656
                                np1.z += 0.8;
11657
                        if (ba1 == ta3)
11658
                                np3.z += 0.8;
11659
                        if (ba1 == ta4)
11660
                                np4.z += 0.8;
11661
                      }
11662
                      else
11663
                        level++;
6785 bpr 11664
                    }
11665
            }
14179 bpr 11666
          }                     /* for i ... */
11667
    if (updown == false && level != 0) {
11668
            if (level > 0)
11669
              np2.z += 0.3;
11670
            if (level < 0)
11671
              np2.z -= 0.3;
11672
          }
11673
    else {
11674
            if (up)
11675
              np2.z += 0.1;
11676
            if (down)
11677
              np2.z -= 0.1;
11678
          }
11679
  }
6785 bpr 11680
  /* fill temporary atom variables again */
11681
  ta1 = hst_cp[0];
11682
  ta2 = hst_cp[1];
11683
  ta3 = hst_cp[2];
11684
  ta4 = hst_cp[3];
11685
  /* then, get the central atom of the haystack */
11686
  hp2.x = atom[ta1 - 1].x;
11687
  hp2.y = atom[ta1 - 1].y;
11688
  hp2.z = atom[ta1 - 1].z;
11689
  /* next, do the same for all 3 substituent atoms */
11690
  hp1.x = atom[ta2 - 1].x;
11691
  hp1.y = atom[ta2 - 1].y;
11692
  hp1.z = atom[ta2 - 1].z;
11693
  hp3.x = atom[ta3 - 1].x;
11694
  hp3.y = atom[ta3 - 1].y;
11695
  hp3.z = atom[ta3 - 1].z;
11696
  hp4.x = atom[ta4 - 1].x;
11697
  hp4.y = atom[ta4 - 1].y;
11698
  hp4.z = atom[ta4 - 1].z;
11699
  /* now check all haystack bonds if we should care about up/down bonds */
11700
  level = 0;
11701
  updown = false;
11702
  up = false;
11703
  down = false;
14179 bpr 11704
  if (n_bonds > 0) {
11705
    FORLIM = n_bonds;
11706
    for (i = 0; i < FORLIM; i++) {
11707
            if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down) {
6785 bpr 11708
              ba1 = bond[i].a1;
11709
              ba2 = bond[i].a2;
14179 bpr 11710
              if (ba1 == ta1 && bond[i].stereo == bstereo_up) {
11711
                      up = true;
11712
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11713
                        updown = true;
11714
                        if (ba2 == ta2)
11715
                                hp1.z += 0.8;
11716
                        if (ba2 == ta3)
11717
                                hp3.z += 0.8;
11718
                        if (ba2 == ta4)
11719
                                hp4.z += 0.8;
11720
                      }
11721
                      else
11722
                        level++;
6785 bpr 11723
                    }
14179 bpr 11724
              if (ba1 == ta1 && bond[i].stereo == bstereo_down) {
11725
                      down = true;
11726
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11727
                        updown = true;
11728
                        if (ba2 == ta2)
11729
                              hp1.z -= 0.8;
11730
                        if (ba2 == ta3)
11731
                                hp3.z -= 0.8;
11732
                        if (ba2 == ta4)
11733
                              hp4.z -= 0.8;
11734
                     }
11735
                    else
11736
                      level--;
6785 bpr 11737
                    }
14179 bpr 11738
              if (ba2 == ta1 && bond[i].stereo == bstereo_up) {
11739
                      down = true;
11740
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11741
                        updown = true;
11742
                        if (ba1 == ta2)
11743
                               hp1.z -= 0.8;
11744
                        if (ba1 == ta3)
11745
                                hp3.z -= 0.8;
11746
                        if (ba1 == ta4)
11747
                                hp4.z -= 0.8;
11748
                      }
11749
                      else
11750
                        level--;
6785 bpr 11751
                    }
14179 bpr 11752
              if (ba2 == ta1 && bond[i].stereo == bstereo_down) {
11753
                      up = true;
11754
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11755
                        updown = true;
11756
                        if (ba1 == ta2)
11757
                                hp1.z += 0.8;
11758
                        if (ba1 == ta3)
11759
                                hp3.z += 0.8;
11760
                        if (ba1 == ta4)
11761
                                hp4.z += 0.8;
11762
                      }
11763
                      else
11764
                        level++;
6785 bpr 11765
                    }
11766
            }
14179 bpr 11767
          }                     /* for i ... */
11768
    if (updown == false && level != 0) {
11769
            if (level > 0)
11770
              hp2.z += 0.3;
11771
            if (level < 0)
11772
              hp2.z -= 0.3;
11773
          }
11774
    else {
11775
            if (up)
11776
              hp2.z += 0.1;
11777
            if (down)
11778
              hp2.z -= 0.1;
11779
          }
11780
  }
6785 bpr 11781
  /* get the pseudo-torsion angles */
11782
  ndl_ct = ctorsion (np1, np2, np3, np4);
11783
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
11784
  ndl_ct_deg = radtodeg (ndl_ct);
11785
  hst_ct_deg = radtodeg (hst_ct);
11786
  /* now do a plausibility check and finally check the sense */
11787
  /* (clockwise or counterclockwise) */
11788
  /*
11789
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
11790
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
11791
     (ndl_ct_deg * hst_ct_deg < 0) then res := false;
11792
   */
11793
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
11794
      ndl_ct_deg * hst_ct_deg < 0)
11795
    res = false;
14179 bpr 11796
  if (rs_strict) {
17890 bpr 11797
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) ||
14179 bpr 11798
                (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
11799
                ndl_ct_deg * hst_ct_deg < 0)
11800
              res = false;
11801
  }
6785 bpr 11802
  return res;
11803
}
11804
 
14179 bpr 11805
static boolean ndl_maybe_chiral (na)
6785 bpr 11806
     int na;
11807
{
11808
  /* new in v0.3h */
11809
  boolean res = false;
11810
  str2 el;
11811
  str3 at;
11812
  int n_nb;
11813
 
11814
  strcpy (el, ndl_atom[na - 1].element);
11815
  strcpy (at, ndl_atom[na - 1].atype);
11816
  n_nb = ndl_atom[na - 1].neighbor_count;
11817
  if (!strcmp (at, "C3 ") && n_nb > 2)
11818
    res = true;
14179 bpr 11819
  if (!strcmp (el, "N ")) {
11820
    if (!strcmp (at, "N3+") && n_nb == 4)
11821
            res = true;
11822
  }
11823
  if (!strcmp (el, "S ")) {                             /* sulfoxide */
11824
    if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
11825
            res = true;
11826
  }
6785 bpr 11827
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
11828
    return res;
11829
  if (n_nb > 3)                 /* are we missing something here? */
11830
    res = true;
11831
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
11832
    res = false;
11833
  return res;
11834
}
11835
 
14179 bpr 11836
static boolean is_matching (ndl_xmp, hst_xmp)
6785 bpr 11837
     int *ndl_xmp, *hst_xmp;
11838
{
11839
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
11840
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
11841
  int next_ndl_a, next_hst_a;
11842
  neighbor_rec ndl_nb, hst_nb;
11843
  matchmatrix mm;
11844
  int ndl_mp_len, hst_mp_len;
11845
  matchpath_type ndl_mp, hst_mp;
11846
  boolean emptyline, res, ndl_cis, hst_cis;
11847
  int na1, na2, na3, na4;       /* v0.3d */
11848
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
11849
  int prev_ndl_b;
11850
  int prev_hst_b;
11851
  p_3d p1, p2, p3, p4;
11852
  /*hst_torsion, ndl_torsion : double; */
11853
  chirpath_type ncp, hcp;
11854
  int n_hits, n_singlehits;
14179 bpr 11855
  /* p2c: checkmol.pas, line 9433:
11856
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11857
  /*$IFDEF debug */
11858
  //char tmpstr[256];
11859
 
11860
  /*$ENDIF */
11861
  /* initialize local matchpath variables */
11862
  //memset (ndl_mp, 0, sizeof (matchpath_type));
11863
  //memset (hst_mp, 0, sizeof (matchpath_type));
11864
  /* copy content of external variables into local ones */
11865
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
11866
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
11867
 
11868
  /*for (i = 0; i < max_matchpath_length; i++)
11869
     {
11870
     ndl_mp[i] = ndl_xmp[i];
11871
     hst_mp[i] = hst_xmp[i];
11872
     } */
11873
 
11874
  ndl_mp_len = matchpath_length (ndl_mp);
11875
  hst_mp_len = matchpath_length (hst_mp);
14179 bpr 11876
  if (ndl_mp_len != hst_mp_len) {
6785 bpr 11877
      /* this should never happen.... */
14179 bpr 11878
  /* p2c: checkmol.pas, line 9451:
11879
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11880
      /*$IFDEF debug */
11881
      //debugoutput ("needle and haystack matchpaths are of different length");
11882
      /*$ENDIF */
14179 bpr 11883
    return false;
11884
  }
6785 bpr 11885
  ndl_a = ndl_mp[ndl_mp_len - 1];
11886
  hst_a = hst_mp[hst_mp_len - 1];
11887
  ndl_atom[ndl_a - 1].tag = false;
11888
  /* new in v0.3o: mark the last needle atom as "visited" */
14179 bpr 11889
  if (ndl_mp_len > 1) {
11890
    prev_ndl_a = ndl_mp[ndl_mp_len - 2];
11891
    prev_hst_a = hst_mp[hst_mp_len - 2];
6785 bpr 11892
    }
11893
  /* if geometry checking is on, check it here */
14179 bpr 11894
  if (ez_search == true && ndl_mp_len > 3) {
11895
    na1 = ndl_mp[ndl_mp_len - 1];
11896
    na2 = ndl_mp[ndl_mp_len - 2];
11897
    na3 = ndl_mp[ndl_mp_len - 3];
11898
    na4 = ndl_mp[ndl_mp_len - 4];
11899
    ha1 = hst_mp[hst_mp_len - 1];
11900
    ha2 = hst_mp[hst_mp_len - 2];
11901
    ha3 = hst_mp[hst_mp_len - 3];
11902
    ha4 = hst_mp[hst_mp_len - 4];
11903
    prev_ndl_b = get_ndl_bond (na2, na3);
11904
    prev_hst_b = get_bond (ha2, ha3);
11905
    if (ndl_bond[prev_ndl_b - 1].btype == 'D' && bond[prev_hst_b - 1].arom == false
11906
              && (ndl_bond[prev_ndl_b - 1].stereo != bstereo_double_either
11907
              && bond[prev_hst_b - 1].stereo != bstereo_double_either)
11908
              /* 0.3x always match if needle and/or haystack bond is double_either */
11909
              && (!strcmp (atom[ha2 - 1].element, "C ")
11910
              || !strcmp (atom[ha2 - 1].element, "N "))
11911
              && (!strcmp (atom[ha3 - 1].element, "C ")
11912
              || !strcmp (atom[ha3 - 1].element, "N "))){
11913
                /* v0.3g; check C=C, C=N, N=N bonds */
11914
            p1.x = atom[ha1 - 1].x;
11915
            p1.y = atom[ha1 - 1].y;
11916
            p1.z = atom[ha1 - 1].z;
11917
            p2.x = atom[ha2 - 1].x;
11918
            p2.y = atom[ha2 - 1].y;
11919
            p2.z = atom[ha2 - 1].z;
11920
            p3.x = atom[ha3 - 1].x;
11921
            p3.y = atom[ha3 - 1].y;
11922
            p3.z = atom[ha3 - 1].z;
11923
            p4.x = atom[ha4 - 1].x;
11924
            p4.y = atom[ha4 - 1].y;
11925
            p4.z = atom[ha4 - 1].z;
11926
            hst_cis = is_cis (p1, p2, p3, p4);
11927
            /*hst_torsion := torsion(p1,p2,p3,p4); */
11928
            p1.x = ndl_atom[na1 - 1].x;
11929
            p1.y = ndl_atom[na1 - 1].y;
11930
            p1.z = ndl_atom[na1 - 1].z;
11931
            p2.x = ndl_atom[na2 - 1].x;
11932
            p2.y = ndl_atom[na2 - 1].y;
11933
            p2.z = ndl_atom[na2 - 1].z;
11934
            p3.x = ndl_atom[na3 - 1].x;
11935
            p3.y = ndl_atom[na3 - 1].y;
11936
            p3.z = ndl_atom[na3 - 1].z;
11937
            p4.x = ndl_atom[na4 - 1].x;
11938
            p4.y = ndl_atom[na4 - 1].y;
11939
            p4.z = ndl_atom[na4 - 1].z;
11940
            /*ndl_torsion := torsion(p1,p2,p3,p4); */
11941
            ndl_cis = is_cis (p1, p2, p3, p4);
11942
            if (ndl_cis != hst_cis) {
11943
        /* p2c: checkmol.pas, line 9501:
11944
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11945
              /*$IFDEF debug */
11946
              //debugoutput ("E/Z geometry mismatch");
11947
              /*$ENDIF */
11948
              return false;
11949
            }
14179 bpr 11950
          }
11951
  }                             /* end of E/Z geometry check */
6785 bpr 11952
  /* check whatever can be checked as early as now: */
11953
  /* e.g. different elements or more substituents on needle atom than on haystack */
11954
  if (!atomtypes_OK (ndl_a, hst_a))
11955
    return false;
11956
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
14179 bpr 11957
  if (atom[hst_a - 1].neighbor_count == 0 && ndl_atom[ndl_a - 1].neighbor_count == 0) {
11958
    if (!atomtypes_OK (ndl_a, hst_a))
11959
            return false;
11960
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
11961
    atom[hst_a - 1].tag = true;
11962
    return true;
11963
  }
6785 bpr 11964
  /* and other possibilities: */
11965
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
11966
  hst_b = get_bond (prev_hst_a, hst_a);
14179 bpr 11967
  /* p2c: checkmol.pas, line 9529:
11968
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11969
  /*$IFDEF debug */
11970
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
11971
  /*$ENDIF */
14179 bpr 11972
  if (ndl_b > 0 && hst_b > 0) {
11973
    /* do a quick check if bond types match */
11974
    if (!bondtypes_OK (ndl_b, hst_b)) {
11975
      /* p2c: checkmol.pas, line 9537:
11976
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11977
            /*$IFDEF debug */
11978
            /*
6785 bpr 11979
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
14179 bpr 11980
           /*$ENDIF */
11981
            return false;
11982
          }
11983
  }
6785 bpr 11984
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
14179 bpr 11985
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a, hst_a) &&
11986
      bondtypes_OK (ndl_b, hst_b)) {
11987
    return true;
11988
  /* p2c: checkmol.pas, line 9549:
11989
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11990
      /*$IFDEF debug */
11991
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
11992
      /*$ENDIF */
14179 bpr 11993
  }
6785 bpr 11994
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
11995
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
14179 bpr 11996
        (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp))) {
11997
    return false;
11998
    /* p2c: checkmol.pas, line 9559:
11999
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12000
      /*$IFDEF debug */
12001
      /*
12002
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
12003
         {$ENDIF */
14179 bpr 12004
  }
6785 bpr 12005
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
12006
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
14179 bpr 12007
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp))) {
12008
    if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
12009
              atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b)) {
12010
              /* 1st chirality check */
12011
            if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
12012
                                                       ndl_atom[ndl_a -1].stereo_care)) && ndl_maybe_chiral (ndl_a))) {
12013
                                        /* new in v0.3h */
6785 bpr 12014
              return true;
12015
            }                   /* end of 1st chirality check */
14179 bpr 12016
            na1 = ndl_a;                /* the (potential) chiral center (v0.3f) */
12017
            na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
12018
            na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
12019
            na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
12020
            ha1 = hst_a;
12021
            ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
12022
            ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
12023
            ha4 = hst_mp[matchpath_length (hst_mp) - 2];
12024
            memset (ncp, 0, sizeof (chirpath_type));
12025
            memset (hcp, 0, sizeof (chirpath_type));
12026
            ncp[0] = na1;
12027
            ncp[1] = na2;
12028
            ncp[2] = na3;
12029
            ncp[3] = na4;
12030
            hcp[0] = ha1;
12031
            hcp[1] = ha2;
12032
            hcp[2] = ha3;
12033
            hcp[3] = ha4;
12034
            if (!chirality_OK (ncp, hcp)) {
12035
        /* p2c: checkmol.pas, line 9589:
12036
         * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12037
                      /*$IFDEF debug */
12038
                      //debugoutput ("chirality check failed at ring junction");
12039
                      /*$ENDIF */
12040
        return false;
12041
      }
12042
      /* p2c: checkmol.pas, line 9596:
12043
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12044
          /*$IFDEF debug */
12045
          //debugoutput ("chirality check succeeded at ring junction");
12046
          /*$ENDIF */
12047
      return true;
12048
      /* p2c: checkmol.pas, line 9602:
12049
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12050
            /*$IFDEF debug */
12051
            /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
12052
            /*$ENDIF */
12053
          }
12054
    else {
12055
            return false;
12056
      /* p2c: checkmol.pas, line 9609:
12057
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12058
            /*$IFDEF debug */
12059
            /*
12060
               debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
12061
            /*$ENDIF */
12062
          }
12063
  }
6785 bpr 12064
  /* in all other cases, do the hard work: */
12065
  /* first, get all heavy-atom neighbors of needle and haystack; */
12066
  /* at the beginning of the search, this means all neighbors, then it means */
12067
  /* all but the previous atom (where we came from) */
12068
  memset (ndl_nb, 0, sizeof (neighbor_rec));
12069
  memset (hst_nb, 0, sizeof (neighbor_rec));
12070
 
14179 bpr 12071
  if (matchpath_length (ndl_mp) == 1) {
12072
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
12073
    n_nb = atom[hst_a - 1].neighbor_count;
12074
    get_ndl_neighbors (ndl_nb, ndl_a);
12075
    get_neighbors (hst_nb, hst_a);
12076
  }
12077
  else {
12078
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
12079
    n_nb = atom[hst_a - 1].neighbor_count - 1;
12080
    get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
12081
    get_nextneighbors (hst_nb, hst_a, prev_hst_a);
12082
  }
6785 bpr 12083
  /* v0.3o: mark all neighbor atoms as "visited" */
12084
  for (i = 0; i < ndl_n_nb; i++)
12085
    ndl_atom[ndl_nb[i] - 1].tag = false;
12086
  /* now that the neighbor-arrays are filled, get all */
12087
  /* combinations of matches recursively; */
12088
  /* first, initialize the match matrix */
12089
  memset (mm, false, sizeof (matchmatrix));     /* new in v0.2i */
12090
  /* make sure there are not too many neighbors (max. max_neighbors)   */
14179 bpr 12091
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors) {                               /* updated in v0.2i */
12092
    /* p2c: checkmol.pas, line 9644:
12093
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12094
      /*$IFDEF debug */
12095
      //debugoutput ("too many neighbors - exiting");
12096
      /*$ENDIF */
14179 bpr 12097
    return false;
12098
  }
6785 bpr 12099
  /* check if matchpath is not already filled up */
14179 bpr 12100
  if (matchpath_length (ndl_mp) == max_matchpath_length) {
12101
    /* p2c: checkmol.pas, line 9653:
12102
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12103
      /*$IFDEF debug */
12104
      //debugoutput ("matchpath too int - exiting");
12105
      /*$ENDIF */
14179 bpr 12106
    return false;
12107
  }
6785 bpr 12108
  /* next, check which chain of the needle matches which chain of the haystack  */
14179 bpr 12109
  for (i = 0; i < ndl_n_nb; i++) {
12110
    emptyline = true;
12111
    next_ndl_a = ndl_nb[i];
12112
    for (j = 0; j < n_nb; j++) {
12113
            next_hst_a = hst_nb[j];
12114
            ndl_mp[ndl_mp_len] = next_ndl_a;
12115
            hst_mp[hst_mp_len] = next_hst_a;
12116
            if (is_matching (ndl_mp, hst_mp)) {                 /* recursive function call */
6785 bpr 12117
              if (max_match_recursion_depth != 0
14179 bpr 12118
                          && ++recursion_depth > max_match_recursion_depth) {
6785 bpr 12119
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 12120
                      if (opt_verbose)
6785 bpr 12121
#endif
14179 bpr 12122
                        printf
6785 bpr 12123
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
14179 bpr 12124
                      max_match_recursion_depth);
12125
                      //n_rings = max_rings;
12126
                     return true;
12127
                    }
6785 bpr 12128
              mm[i][j] = true;
12129
              emptyline = false;
12130
            }
14179 bpr 12131
          }
12132
    /* if a needle substituent does not match any of the haystack substituents, */
12133
    /* stop any further work immediately */
12134
    if (emptyline)
12135
            return false;
12136
  }
6785 bpr 12137
  /* finally, check the content of the matrix */
12138
  res = matrix_OK (mm, ndl_n_nb, n_nb);
12139
  /* optional: chirality check */
14179 bpr 12140
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) && ndl_maybe_chiral (ndl_a)))
6785 bpr 12141
    return res;
12142
  /* first, we have to clean up the match matrix in order to remove */
12143
  /* "impossible" multiple matches (new in v0.3h) */
14179 bpr 12144
  for (i = 1; i <= 3; i++) {
12145
    for (j = 1; j <= max_neighbors; j++) {                      /* haystack dimension */
12146
            n_hits = 0;
12147
            l = 0;
12148
            for (k = 1; k <= max_neighbors; k++) {                      /* needle dimension */
12149
              if (mm[k - 1][j - 1]) {
12150
                      n_hits++;
12151
                      l = k;
12152
                    }
6785 bpr 12153
            }
14179 bpr 12154
            if (n_hits == 1) {                  /* a unique match ==> kick out any other match at this pos. */
12155
              for (m = 1; m <= max_neighbors; m++) {
12156
                      if (m != j)
12157
                        mm[l - 1][m - 1] = false;
12158
                    }
6785 bpr 12159
            }
14179 bpr 12160
          }
12161
  }
6785 bpr 12162
  /* end of match matrix clean-up */
14179 bpr 12163
  if (prev_ndl_a > 0) {
12164
    n_singlehits = 1;
12165
    ncp[1] = prev_ndl_a;
12166
    hcp[1] = prev_hst_a;
12167
  }
6785 bpr 12168
  else
12169
    n_singlehits = 0;
12170
  ncp[0] = ndl_a;
12171
  hcp[0] = hst_a;
12172
  i = 0;
12173
  l = 0;
14179 bpr 12174
  while (n_singlehits < 3 && i < 4) {
12175
    i++;
12176
    n_hits = 0;
12177
    for (k = 1; k <= n_nb; k++) {
12178
            if (mm[i - 1][k - 1]) {
6785 bpr 12179
              n_hits++;
12180
              l = k;
12181
            }
14179 bpr 12182
          }
12183
    if (n_hits == 1) {
12184
            n_singlehits++;
12185
            ncp[n_singlehits] = ndl_nb[i - 1];
12186
            hcp[n_singlehits] = hst_nb[l - 1];
12187
          }
12188
  }
6785 bpr 12189
  if (n_singlehits != 3)
12190
    return res;
14179 bpr 12191
  if (!chirality_OK (ncp, hcp)) {
12192
    /* p2c: checkmol.pas, line 9749:
12193
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12194
          /*$IFDEF debug */
12195
          //debugoutput ("chirality check failed");
12196
          /*$ENDIF */
12197
          res = false;
12198
  }
12199
  else {
6785 bpr 12200
/* p2c: checkmol.pas, line 9755:
12201
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12202
      /*$IFDEF debug */
12203
      //debugoutput ("chirality check OK");
12204
      /*$ENDIF */
14179 bpr 12205
  }
6785 bpr 12206
  return res;
14179 bpr 12207
  /* p2c: checkmol.pas, line 9762:
12208
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12209
    /*$IFDEF debug */
12210
    /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
12211
       debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
12212
    /*$ENDIF */
6785 bpr 12213
}
12214
 
14179 bpr 12215
static boolean quick_match ()
6785 bpr 12216
{
12217
  /* added in v0.2c */
12218
  int i;
12219
  boolean res = true;
14179 bpr 12220
  /* str3 ndl_atype;*/
6785 bpr 12221
  str2 ndl_el;                  /* v0.3l */
6788 kbelabas 12222
  int ndl_chg = 0;              /* v0.3l */
12223
  int ndl_rad = 0;              /* v0.3x */
12224
  int ndl_iso = 0;              /* v0.3x */
6785 bpr 12225
 
12226
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
12227
    /* v0.3f, v0.3m, v0.3o */
12228
    return false;
12229
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
14179 bpr 12230
        ndl_n_bonds > n_bonds) {                                /* just to be sure... */
12231
    /* p2c: checkmol.pas, line 9786:
12232
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12233
          /*$IFDEF debug */
12234
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
12235
          //debugoutput (" ==> quick_match failed");
12236
          /*$ENDIF */
12237
    return false;
12238
  }
6785 bpr 12239
 
14179 bpr 12240
  if (ndl_n_heavyatoms > 1) {
12241
    for (i = 0; i < ndl_n_atoms; i++) {
12242
            /*if atom^[i].atype <> ndl_atom^[i].atype then res := false;    (* changed in */
12243
            if (strcmp (atom[i].element, ndl_atom[i].element))  /* v0.2k */
12244
              return false;
12245
            //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
12246
            //res = false;
6785 bpr 12247
 
14179 bpr 12248
            if (opt_chg) {
6785 bpr 12249
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
14179 bpr 12250
                      return false;
6785 bpr 12251
            }
14179 bpr 12252
      /*  else {
12253
            if (ndl_atom[i].formal_charge != 0 &&
12254
          atom[i].formal_charge != 0 &&
12255
          ndl_atom[i].formal_charge != atom[i].formal_charge)
12256
        return false;
12257
          } */
6785 bpr 12258
 
14179 bpr 12259
          /* v0.3x: isotopes must be the same */
12260
            if (opt_iso) {
6785 bpr 12261
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
14179 bpr 12262
                      return false;
6785 bpr 12263
            }
14179 bpr 12264
          /*  else {
12265
          if (ndl_atom[i].nucleon_number != 0 &&
12266
          atom[i].nucleon_number != 0 &&
12267
          ndl_atom[i].nucleon_number !=
12268
          atom[i].nucleon_number)
12269
        return false;
12270
        }*/
6785 bpr 12271
 
14179 bpr 12272
            /* v0.3x: radicals must be the same */
12273
            if (opt_rad) {
6785 bpr 12274
              if (ndl_atom[i].radical_type != atom[i].radical_type)
14179 bpr 12275
                      return false;
6785 bpr 12276
            }
14179 bpr 12277
      /*  else {
12278
         if (ndl_atom[i].radical_type != 0 &&
12279
             atom[i].radical_type != 0 &&
12280
             ndl_atom[i].radical_type != atom[i].radical_type)
12281
           return false;
12282
       }*/
6785 bpr 12283
 
12284
        }
14179 bpr 12285
  /* p2c: checkmol.pas, line 9798:
12286
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12287
      /*$IFDEF debug */
12288
      //if (res)
12289
      //debugoutput (" ==> quick_match: atoms OK");
12290
      //else
12291
      //  debugoutput (" ==> quick_match: atoms not OK");
12292
      /*$ENDIF */
14179 bpr 12293
    if (ndl_n_bonds > 0) {
12294
            for (i = 0; i < ndl_n_bonds; i++) {
6785 bpr 12295
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
14179 bpr 12296
                        || ndl_bond[i].btype != bond[i].btype)
12297
                      return false;
6785 bpr 12298
            }
14179 bpr 12299
          }
12300
    /* p2c: checkmol.pas, line 9810:
12301
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12302
         /*$IFDEF debug */
12303
         //if (res)
12304
         //  debugoutput (" ==> quick_match: bonds OK");
12305
         //else
12306
         //  debugoutput (" ==> quick_match: bonds not OK");
12307
         /*$ENDIF */
12308
         /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
12309
   }
12310
  else {
12311
    /* first, find out the element and atom type of the only heavy atom       */
12312
    for (i = 0; i < ndl_n_atoms; i++) {
12313
            if (ndl_atom[i].heavy) {
6785 bpr 12314
              //strcpy (ndl_atype, ndl_atom[i].atype);
12315
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
12316
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
12317
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
12318
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
12319
            }
14179 bpr 12320
          }
12321
    for (i = 0; i < n_atoms; i++) {                     /* v0.3l, v0.3o */
12322
            if (                //      !strcmp (atom[i].atype, ndl_atype) &&
12323
                !strcmp (atom[i].element, ndl_el)) {
12324
              if (opt_chg || opt_strict) {
12325
                      if (ndl_chg != atom[i].formal_charge)
12326
                        return false;
12327
                    }
12328
              if (opt_iso || opt_strict) {
12329
                      if (ndl_iso != atom[i].nucleon_number)
12330
                        return false;
12331
                    }
6785 bpr 12332
 
14179 bpr 12333
              if (opt_rad || opt_strict) {
12334
                      if (ndl_rad != atom[i].radical_type)
12335
                        return false;
12336
                    }
12337
                    return true;
12338
            }
12339
            else {
12340
              res=false;
12341
            }
12342
          }
12343
  }
12344
  /* p2c: checkmol.pas, line 9828:
12345
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12346
  /*$IFDEF debug */
12347
  //if (res)
12348
  //  debugoutput (" ==> quick_match succeeded");
12349
  //else
12350
  //  debugoutput (" ==> quick_match failed (2)");
12351
  /*$ENDIF */
12352
  return res;
12353
}
12354
 
14179 bpr 12355
static void perform_match ()
6785 bpr 12356
{
12357
  int i = 0;
12358
  int j;
12359
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
12360
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
12361
  boolean qm;                   /* v0.3l */
12362
  /* check for NoStruct (0 atoms);  v0.3l */
14179 bpr 12363
  if (n_atoms == 0 || ndl_n_atoms == 0) {
6785 bpr 12364
      matchresult = false;
14179 bpr 12365
  /* p2c: checkmol.pas, line 9849:
12366
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12367
      /*$IFDEF debug */
12368
      //debugoutput ("NoStruct encountered - aborted match routine");
12369
      /*$ENDIF */
14179 bpr 12370
    return;
12371
  }
6785 bpr 12372
  /* if we perform an exact match, needle and haystack must have */
12373
  /* the same number of atoms, bonds, and rings */
14179 bpr 12374
  if (opt_exact && opt_iso)     /* 0.3x */ {
12375
      if (n_heavyatoms != ndl_n_heavyatoms || n_heavybonds != ndl_n_heavybonds) {
12376
              matchresult = false;
12377
      /* p2c: checkmol.pas, line 9861:
12378
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12379
          /*$IFDEF debug */
12380
          //debugoutput ("different number of heavy atoms and/or bonds");
12381
          /*$ENDIF */
12382
          //return;
12383
          }
12384
  }
6785 bpr 12385
 
12386
  /* have a quick look if needle and haystack are identical molfiles */
12387
  qm = quick_match ();          /* v0.3l */
14179 bpr 12388
  if (qm) {
12389
    matchresult = true;
12390
    clear_ndl_atom_tags ();     /* v0.3o */
12391
    return;
12392
  }
6785 bpr 12393
  /* if we have only one heavy atom and quick_match fails, return "false";  v0.3l */
14179 bpr 12394
  if (ndl_n_heavyatoms == 1) {
12395
    matchresult = false;
12396
    return;
12397
  }
12398
  /* p2c: checkmol.pas, line 9881:
12399
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12400
  /*$IFDEF debug */
12401
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
12402
  /*$ENDIF */
12403
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
12404
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
14179 bpr 12405
  /* p2c: checkmol.pas, line 9886:
12406
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12407
  /*$IFDEF debug */
12408
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
12409
  /*$ENDIF */
12410
  matchresult = false;
14179 bpr 12411
  for (j = 0; j < max_matchpath_length; j++) {
12412
    ndl_matchpath[j] = 0;
12413
    hst_matchpath[j] = 0;
12414
  }
6785 bpr 12415
  ndl_matchpath[0] = ndl_ref_atom;
14179 bpr 12416
  while (i < n_atoms && matchresult == false) {
12417
    i++;
12418
    n_nb = atom[i - 1].neighbor_count;
12419
    n_hc = hetatom_count (i);
12420
    if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc) {
12421
      /* p2c: checkmol.pas, line 9904:
12422
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12423
              /*$IFDEF debug */
12424
              /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
12425
              /*$ENDIF */
6785 bpr 12426
 
14179 bpr 12427
            recursion_depth = 0;
12428
            hst_matchpath[0] = i;
12429
            matchresult = is_matching (ndl_matchpath, hst_matchpath);
12430
      /* p2c: checkmol.pas, line 9909:
12431
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12432
          /*$IFDEF debug */
12433
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
12434
          /*$ENDIF */
12435
      if (matchresult)  /* v0.3o; mark this fragment as matched */
12436
        atom[i - 1].tag = true;
12437
          }
12438
  }
6785 bpr 12439
}
12440
 
14179 bpr 12441
static void clear_rings ()
6785 bpr 12442
{
12443
  int i, FORLIM;
12444
  n_rings = 0;
12445
  memset (ring, 0, sizeof (ringlist));
14179 bpr 12446
  for (i = 0; i < max_rings; i++) {                             /* new in v0.3 */
12447
    ringprop[i].size = 0;
12448
    ringprop[i].arom = false;
12449
    ringprop[i].envelope = false;
12450
  }
12451
  if (n_atoms > 0) {
12452
    FORLIM = n_atoms;
12453
    for (i = 0; i < FORLIM; i++)
12454
            atom[i].ring_count = 0;
12455
  }
12456
  if (n_bonds > 0) {
12457
    FORLIM = n_bonds;
12458
    for (i = 0; i < FORLIM; i++)
12459
            bond[i].ring_count = 0;
12460
  }
6785 bpr 12461
}
12462
 
14179 bpr 12463
static int ring_lastpos (s)
6785 bpr 12464
     int *s;
12465
{
12466
  int i, rc;
12467
  int rlp = 0;
12468
  int FORLIM;
12469
  if (n_rings <= 0)
12470
    return rlp;
12471
  FORLIM = n_rings;
14179 bpr 12472
  for (i = 1; i <= FORLIM; i++) {
12473
    rc = ringcompare (s, ring[i - 1]);
12474
    if (rc_identical (rc))
12475
            rlp = i;
12476
  }
6785 bpr 12477
  return rlp;
12478
}
12479
 
14179 bpr 12480
static void remove_redundant_rings ()
6785 bpr 12481
{
12482
  int i, j, k, rlp;
12483
  ringpath_type tmp_path;
12484
  int FORLIM, FORLIM1;
12485
  if (n_rings < 2)
12486
    return;
12487
  FORLIM = n_rings;
14179 bpr 12488
  for (i = 1; i < FORLIM; i++) {
12489
    memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
12490
    rlp = ring_lastpos (tmp_path);
12491
    while (rlp > i) {
12492
           FORLIM1 = n_rings;
12493
      /* p2c: checkmol.pas, line 9970:
12494
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12495
          /*$IFDEF debug */
12496
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
12497
          /*$ENDIF */
14179 bpr 12498
            for (j = rlp; j < FORLIM1; j++) {
6785 bpr 12499
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
12500
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
12501
              ringprop[j - 1].arom = ringprop[j].arom;
12502
              ringprop[j - 1].envelope = ringprop[j].envelope;
12503
            }
14179 bpr 12504
            for (k = 0; k < max_ringsize; k++)
12505
              ring[n_rings - 1][k] = 0;
12506
            n_rings--;
12507
            rlp = ring_lastpos (tmp_path);
12508
          }
12509
  }
6785 bpr 12510
}
12511
 
14179 bpr 12512
static int count_aromatic_rings ()
6785 bpr 12513
{
12514
  int i;
12515
  int n = 0;
12516
  int FORLIM;
12517
  if (n_rings <= 0)
12518
    return n;
12519
  FORLIM = n_rings;
14179 bpr 12520
  for (i = 0; i < FORLIM; i++) {
12521
    if (ringprop[i].arom)
12522
            n++;
12523
  }
6785 bpr 12524
  return n;
12525
}
12526
 
14179 bpr 12527
static void chk_envelopes ()
6785 bpr 12528
{
12529
  /* new in v0.3d */
12530
  /* checks if a ring completely contains one or more other rings */
12531
  int a, i, j, k, l, pl, pli;
12532
  boolean found_atom, found_all_atoms, found_ring;
12533
  int FORLIM;
12534
  if (n_rings < 2)
12535
    return;
12536
  FORLIM = n_rings;
14179 bpr 12537
  for (i = 1; i < FORLIM; i++) {
12538
    found_ring = false;
12539
    j = 0;
12540
    pli = ringprop[i].size;     /* path_length(ring^[i]); */
12541
    while (j < i && found_ring == false) {
12542
            j++;
12543
            found_all_atoms = true;
12544
            pl = ringprop[j - 1].size;  /* path_length(ring^[j]); */
12545
            for (k = 0; k < pl; k++) {
6785 bpr 12546
              found_atom = false;
12547
              a = ring[j - 1][k];
14179 bpr 12548
              for (l = 0; l < pli; l++) {
12549
                      if (ring[i][l] == a)
12550
                        found_atom = true;
12551
                    }
6785 bpr 12552
              if (found_atom == false)
14179 bpr 12553
                      found_all_atoms = false;
6785 bpr 12554
            }
14179 bpr 12555
            if (found_all_atoms)
12556
              found_ring = true;
12557
          }
12558
    if (found_ring)
12559
            ringprop[i].envelope = true;
12560
  }
6785 bpr 12561
}
12562
 
14179 bpr 12563
static void update_ringcount ()
6785 bpr 12564
{
12565
  int i, j, a1, a2, b, pl, FORLIM;
12566
  if (n_rings <= 0)
12567
    return;
12568
  chk_envelopes ();
12569
  FORLIM = n_rings;
14179 bpr 12570
  for (i = 0; i < FORLIM; i++) {
12571
      if (ringprop[i].envelope == false) {
12572
            pl = ringprop[i].size;      /* path_length(ring^[i]);  (* v0.3d */
12573
            a2 = ring[i][pl - 1];
12574
            for (j = 0; j < pl; j++) {
6785 bpr 12575
              a1 = ring[i][j];
12576
              atom[a1 - 1].ring_count++;
12577
              b = get_bond (a1, a2);
12578
              bond[b - 1].ring_count++;
12579
              a2 = a1;
12580
            }
14179 bpr 12581
          }
12582
  }
6785 bpr 12583
}
12584
 
14179 bpr 12585
static boolean normalize_ionic_bonds ()
6785 bpr 12586
{
12587
  /* v0.3k */
12588
  /* changed from a procedure into a function in v0.3m */
12589
  int i, a1, a2, fc1, fc2;
12590
  char bt;
12591
  boolean res = false;          /* v0.3m */
12592
  int FORLIM;
12593
  /* v0.3m */
12594
  if (n_bonds == 0)
12595
    return false;
12596
  FORLIM = n_bonds;
14179 bpr 12597
  for (i = 0; i < FORLIM; i++) {
12598
    a1 = bond[i].a1;
12599
    a2 = bond[i].a2;
12600
    bt = bond[i].btype;
12601
    fc1 = atom[a1 - 1].formal_charge;
12602
    fc2 = atom[a2 - 1].formal_charge;
12603
    if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D')) {
12604
            atom[a1 - 1].formal_charge = 0;
12605
            atom[a2 - 1].formal_charge = 0;
12606
            if (!strcmp (atom[a1 - 1].atype, "N3+"))    /* v0.3m */
12607
              strcpy (atom[a1 - 1].atype, "N3 ");
12608
            if (!strcmp (atom[a2 - 1].atype, "N3+"))    /* v0.3m */
12609
              strcpy (atom[a2 - 1].atype, "N3 ");
12610
            if (bt == 'D')
12611
              bond[i].btype = 'T';
12612
            if (bt == 'S')
12613
              bond[i].btype = 'D';
12614
            res = true;         /* v0.3m */
12615
          }
12616
  }
6785 bpr 12617
  return res;                   /* v0.3m (return true if any change was made */
12618
}
12619
 
12620
#if 0
14179 bpr 12621
static void chk_wildcard_rings ()               // new in v0.3p
6785 bpr 12622
// checks if there are any wildcard atom types or bond types
12623
// in a ring of the needle; if yes ==> set the q_arom flag in the
14179 bpr 12624
// atom and bond record of all ring members in order to perform the
6785 bpr 12625
// match a bit more generously
12626
{
12627
 
12628
  int i, j, rs;
12629
  int a1, a2, b;
12630
  boolean wcr;
12631
  str3 at;
12632
  char bt;
12633
 
12634
  if (ndl_querymol == false)
12635
    return;
12636
  if (ndl_n_rings == 0)
12637
    return;
12638
  // now look for any not-yet-aromatic rings which contain a wildcard
14179 bpr 12639
  for (i = 0; i < ndl_n_rings; i++) {
12640
    wcr = false;
12641
    if (ndl_ringprop[i].arom == false) {
12642
            rs = ndl_ringprop[i].size;
12643
            a2 = ndl_ring[i][rs];
12644
            for (j = 0; j < rs; j++) {
6785 bpr 12645
              a1 = ndl_ring[i][j];
12646
              b = get_ndl_bond (a1, a2);
12647
              strcpy (at, ndl_atom[a1].atype);
12648
              bt = ndl_bond[b].btype;
12649
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
14179 bpr 12650
                      wcr = true;
6785 bpr 12651
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
14179 bpr 12652
                      wcr = true;
6785 bpr 12653
              a2 = a1;
12654
            }
14179 bpr 12655
            if (wcr) {                  // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
6785 bpr 12656
              // {$IFDEF debug}
12657
              // debugoutput('wildcard ring found');
12658
              // {$ENDIF}
12659
              a2 = ndl_ring[i][rs];
14179 bpr 12660
              for (j = 0; j < rs; j++) {
12661
                      a1 = ndl_ring[i][j];
12662
                      b = get_ndl_bond (a1, a2);
12663
                      strcpy (at, ndl_atom[a1].atype);
12664
                      bt = ndl_bond[b].btype;
12665
                      ndl_atom[a1].q_arom = true;
12666
                      ndl_bond[b].q_arom = true;
12667
                      a2 = a1;
12668
                    }
6785 bpr 12669
            }
14179 bpr 12670
          }
12671
  }
6785 bpr 12672
  // and now undo this flagging for all rings which contain no wildcard
14179 bpr 12673
  for (i = 0; i < ndl_n_rings; i++) {
12674
    wcr = false;
12675
    rs = ndl_ringprop[i].size;
12676
    a2 = ndl_ring[i][rs];
12677
    for (j = 0; j < rs; j++) {
12678
            a1 = ndl_ring[i][j];
12679
            b = get_ndl_bond (a1, a2);
12680
            strcpy (at, ndl_atom[a1].atype);
12681
            bt = ndl_bond[b].btype;
12682
            if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
12683
              wcr = true;
12684
            if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
12685
              wcr = true;
12686
            a2 = a1;
12687
          }
12688
    if (!wcr) {                 // if yes, unflag all atoms and bonds in this ring
12689
            a2 = ndl_ring[i][rs];
12690
            for (j = 0; j < rs; j++) {
6785 bpr 12691
              a1 = ndl_ring[i][j];
12692
              b = get_ndl_bond (a1, a2);
12693
              strcpy (at, ndl_atom[a1].atype);
12694
              bt = ndl_bond[b].btype;
12695
              ndl_atom[a1].q_arom = false;
12696
              ndl_bond[b].q_arom = false;
12697
              a2 = a1;
12698
            }
14179 bpr 12699
          }
12700
  }
6785 bpr 12701
  // some further refinement would be necessary here in order to unflag everything
12702
  // which contains a wildcard but which definitely cannot be aromatic
12703
}
12704
#endif
12705
 
12706
#ifndef MAKE_SHARED_LIBRARY
12707
 
14179 bpr 12708
int main (int argc, char *argv[])
6785 bpr 12709
{                               /* main routine */
12710
  char STR1[256], STR6[256];
12711
  int FORLIM;
12712
  /* progmode = pmMatchMol */
12713
  rfile = NULL;
12714
  strcpy (progname, argv[0]);
12715
  strncpy (STR1, progname, 253);
12716
  if (strstr (STR1, "matchmol") != NULL)
12717
    progmode = pmMatchMol;
14179 bpr 12718
  else {
12719
    strncpy (STR6, progname, 253);
12720
    if (strstr (STR6, "checkmol") == NULL) {
12721
            printf ("THOU SHALLST NOT RENAME ME!\n");
12722
            exit (9);
12723
          }
12724
    progmode = pmCheckMol;
12725
  }
12726
  if (argc == 1) {
12727
    show_usage ();
12728
    exit (1);
12729
  }
6785 bpr 12730
  init_globals ();
12731
  init_molstat (&molstat);
12732
  parse_args (argc, argv);
12733
  if (ringsearch_mode == rs_sar)
12734
    max_vringsize = max_ringsize;
12735
  else
12736
    max_vringsize = ssr_vringsize;
12737
  /* v0.3n (was: 10) */
12738
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14179 bpr 12739
  if (progmode == pmMatchMol) {
12740
    left_trim (ndl_molfilename);
12741
    left_trim (molfilename);
12742
    if ((*molfilename == '\0' || *ndl_molfilename == '\0' || argc < 3) && !opt_stdin) {
6785 bpr 12743
            show_usage ();
14179 bpr 12744
            exit (2);           /* new in v0.2k */
12745
          }
12746
    if (!(file_exists (ndl_molfilename)) && !opt_stdin) {
12747
      /*not  fileexists(ndl_molfilename) REPLACE!!! */
12748
                  printf("2");
12749
                  /* p2c: checkmol.pas, line 10128:
12750
                  * Warning: Expected an expression, found a ')' [227] */
12751
            if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
12752
              show_usage ();
12753
            else
12754
              printf ("file %s not found!\n", ndl_molfilename);
12755
            /* new in v0.2k */
12756
            exit (2);
12757
          }
12758
  }
6785 bpr 12759
 
14179 bpr 12760
  if (!(file_exists (molfilename)) && !opt_stdin) {                             /*not  fileexists(ndl_molfilename) REPLACE!!! */
12761
    /* p2c: checkmol.pas, line 10128:
12762
    * Warning: Expected an expression, found a ')' [227] */
6785 bpr 12763
 
14179 bpr 12764
    if (strlen (molfilename) > 1 && molfilename[0] == '-')
12765
            show_usage ();
12766
    else
12767
            printf ("file %s not found!\n", molfilename);
6785 bpr 12768
      /* new in v0.2k */
12769
      exit (2);
14179 bpr 12770
  }
6785 bpr 12771
 
12772
  /* read the first molecule and process it; if we are in "matchmol" mode, */
12773
  /* this is the "needle" */
12774
  if (progmode == pmMatchMol)
12775
    readinputfile (ndl_molfilename);
12776
  else
12777
    readinputfile (molfilename);
12778
  li = 1;                       /* initialize line pointer for input buffer */
12779
  get_filetype (filetype, ndl_molfilename);
14179 bpr 12780
  if (!strcmp (filetype, "unknown")) {
12781
    printf ("unknown query file format!\n");
12782
    if (!opt_verbose)
12783
            exit (3);
12784
    printf ("===========================================\n");
12785
    FORLIM = molbufindex;
12786
    for (i = 1; i <= FORLIM; i++)
12787
            puts (molbuf[i - 1]);
12788
    exit (3);
12789
  }
6785 bpr 12790
  mol_OK = true;                /* added in v0.2i */
12791
  if (!strcmp (filetype, "alchemy"))
12792
    read_molfile (ndl_molfilename);
12793
  if (!strcmp (filetype, "sybyl"))
12794
    read_mol2file (ndl_molfilename);
12795
  if (!strcmp (filetype, "mdl"))
12796
    read_MDLmolfile (ndl_molfilename);
12797
  count_neighbors ();
14179 bpr 12798
  if (!mol_OK || n_atoms < 1) {                                 /* v0.3g; check if this is a valid query structure */
12799
    printf ("invalid molecule\n");
12800
    exit (3);
12801
  }
12802
  if (!found_arominfo || progmode == pmCheckMol) {                              /* added in v0.2b/0.2c */
12803
  /* p2c: checkmol.pas, line 10172:
12804
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12805
      /*$IFDEF debug
6785 bpr 12806
         if (!found_arominfo)
12807
         debugoutput
12808
         ("no aromaticity information found - checking myself...");
12809
         else
12810
         debugoutput ("performing full aromaticity check");
14179 bpr 12811
         // new in v0.3d
6785 bpr 12812
      $ENDIF */
14179 bpr 12813
    chk_ringbonds ();
12814
    if (ringsearch_mode == rs_ssr)
12815
            remove_redundant_rings ();
12816
    if (n_rings >= max_rings) {
12817
            if (opt_verbose)
12818
              printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12819
                 max_rings);
12820
            ringsearch_mode = rs_ssr;
12821
            auto_ssr = true;    /* v0.3n */
12822
            clear_rings ();
12823
            max_vringsize = ssr_vringsize;      /* v0.3n (was: 10) */
12824
            chk_ringbonds ();
12825
            remove_redundant_rings ();
12826
          }
12827
    update_ringcount ();
12828
    /* new in v0.3k: if output is a molfile, leave the original */
12829
    /* representation of N-oxides, S-oxides, nitro groups, etc. */
12830
    /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
12831
    if (!opt_xmdlout)           /* v0.3k */
12832
            normalize_ionic_bonds ();
12833
    update_atypes ();
12834
    update_Htotal ();           /* added in v0.3 */
12835
    chk_arom ();
12836
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
12837
            do {
6785 bpr 12838
              prev_n_ar = count_aromatic_rings ();
12839
              chk_arom ();
12840
              n_ar = count_aromatic_rings ();
12841
            }
14179 bpr 12842
            while (prev_n_ar - n_ar != 0);
12843
          }
12844
  }
12845
  else {                                /* v0.3k */
12846
    /* p2c: checkmol.pas, line 10206:
12847
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12848
      /*$IFDEF debug
6785 bpr 12849
         debugoutput ("found aromaticity information in input file");
12850
         $ENDIF */
14179 bpr 12851
    if (!opt_xmdlout)
12852
            normalize_ionic_bonds ();
12853
    update_atypes ();           /* added in v0.2f */
12854
    update_Htotal ();           /* end v0.2b snippet */
12855
  }
12856
  if (progmode == pmCheckMol) {
12857
    if (opt_verbose)
12858
            write_mol ();
12859
    get_molstat ();
12860
    if (opt_molstat) {
12861
            if (opt_molstat_X)
12862
              write_molstat_X ();
12863
            else
12864
              write_molstat ();
12865
          }
12866
    else {
12867
            if (found_querymol) {
12868
                printf ("input structure contains query atom or query bond!\n");
12869
                exit (1);
6785 bpr 12870
            }
14179 bpr 12871
            chk_functionalgroups ();
12872
            if (opt_none)
12873
              opt_text = true;
12874
            if (opt_text)
12875
              write_fg_text ();
12876
            if (opt_text_de)
12877
              write_fg_text_de ();
12878
            if (opt_code)
12879
              write_fg_code ();
12880
            if (opt_bin)
12881
              write_fg_binary ();
12882
            if (opt_bitstring)
12883
              write_fg_bitstring ();
12884
            if (opt_xmdlout)
12885
              write_MDLmolfile ();
12886
          }
6785 bpr 12887
      /*if opt_verbose   then write_mol; */
14179 bpr 12888
    zap_molecule ();
12889
  }
12890
  else {
6785 bpr 12891
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14179 bpr 12892
    if (!opt_fp) {                      /* v0.3m */
12893
            copy_mol_to_needle ();
12894
            //chk_wildcard_rings (); /* 0.3p */
12895
            set_ndl_atom_tags ();       /* v0.3o */
12896
            if (opt_verbose)
12897
              write_needle_mol ();
12898
            if (rs_strict)      /* v0.3j */
12899
              ndl_ref_atom = find_ndl_ref_atom_cv ();
12900
            else
12901
              ndl_ref_atom = find_ndl_ref_atom ();
12902
          }
12903
    else {
12904
            copy_mol_to_tmp (); /* v0.3m */
12905
            if (opt_verbose)
12906
              printf ("1st molecule stored in buffer: %s\n", tmp_molname);
12907
          }
12908
    /* next, read the "haystack" file and process it */
12909
    li = 1;
12910
    mol_count = 0;
12911
    fpdecimal = 0;              /* v0.3m */
12912
    fpindex = 0;                /* v0.3m */
12913
    do {
12914
            /* new in v0.3i: reset ringsearch_mode to its initial value */
12915
            /* for each new molecule */
12916
            ringsearch_mode = opt_rs;
12917
            if (ringsearch_mode == rs_sar)
12918
              max_vringsize = max_ringsize;
12919
            else
12920
              max_vringsize = ssr_vringsize;
12921
            /* v0.3n (was: 10) */
12922
            readinputfile (molfilename);
12923
            li = 1;
12924
            get_filetype (filetype, molfilename);
12925
            if (strcmp (filetype, "unknown")) {
6785 bpr 12926
              found_arominfo = false;   /* added in v0.2b */
12927
              mol_OK = true;    /* added in v0.2i */
12928
              if (!strcmp (filetype, "alchemy"))
14179 bpr 12929
                      read_molfile (molfilename);
6785 bpr 12930
              if (!strcmp (filetype, "sybyl"))
14179 bpr 12931
                      read_mol2file (molfilename);
6785 bpr 12932
              if (!strcmp (filetype, "mdl"))
14179 bpr 12933
                      read_MDLmolfile (molfilename);
6785 bpr 12934
              mol_count++;
12935
              fpindex++;
12936
              count_neighbors ();
12937
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14179 bpr 12938
              if (!mol_OK || (n_atoms < 1 && !(opt_fp && fpformat == fpf_decimal)))
12939
                      printf ("%i:F\n", mol_count);
12940
              else {
12941
                      if (opt_exact && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
12942
                                || n_Ntot != ndl_n_Ntot)) {             /* new in v0.3g */
12943
                        if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
12944
                                printf ("%i:F\n", mol_count);
12945
                      }
12946
                      else {
12947
                        if (!found_arominfo || (opt_strict && tmfmismatch)) {   /* added in v0.3m */
12948
              /* p2c: checkmol.pas, line 10294:
12949
               * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12950
                                  /*$IFDEF debug
12951
                              debugoutput
12952
                              ("no aromaticity information found (or tweak mismatch) - checking myself...");
12953
                              *$ENDIF */
6785 bpr 12954
                              chk_ringbonds ();
14179 bpr 12955
                              if (ringsearch_mode == rs_ssr)
12956
                                remove_redundant_rings ();
12957
                               if (n_rings == max_rings) {
12958
                                if (opt_verbose)
12959
                                        printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12960
                                         max_rings);
12961
                                ringsearch_mode = rs_ssr;
12962
                                clear_rings ();
12963
                                max_vringsize = ssr_vringsize;  /* v0.3n (was: 10) */
12964
                                chk_ringbonds ();
12965
                                remove_redundant_rings ();
12966
                              }
12967
                              update_ringcount ();
12968
                              update_atypes ();
12969
                              update_Htotal (); /* added in v0.3 */
12970
                              chk_arom ();
12971
                              if (ringsearch_mode == rs_ssr) {  /* new in v0.3 */
12972
                                do {
12973
                                        prev_n_ar = count_aromatic_rings ();
12974
                                        chk_arom ();
12975
                                        n_ar = count_aromatic_rings ();
12976
                                      }
12977
                                while (prev_n_ar - n_ar != 0);
12978
                              }
6785 bpr 12979
                            }
14179 bpr 12980
                      else {    /* added in v0.2f */
12981
            /* p2c: checkmol.pas, line 10322:
12982
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12983
                            /*$IFDEF debug
6785 bpr 12984
                             debugoutput
12985
                             ("found aromaticity information in input file");
12986
                             $ENDIF */
14179 bpr 12987
                              if (opt_strict)
12988
                                update_atypes ();
12989
                              update_Htotal ();
12990
                            }
6785 bpr 12991
                      init_molstat (&ndl_molstat);
12992
                      if (normalize_ionic_bonds ())
14179 bpr 12993
                              /* new in v0.3k, modified in v0.3m */
12994
                              update_atypes ();
6785 bpr 12995
                      if (opt_verbose && !opt_fp)
14179 bpr 12996
                              write_mol ();
6785 bpr 12997
                      /* if in "fingerprint mode", exchange needle and haystack */
14179 bpr 12998
                      if (opt_fp) {     /* v0.3m */
12999
                              zap_needle ();
13000
                              copy_mol_to_needle ();
13001
                              //chk_wildcard_rings (); /* 0.3p */
13002
                              zap_molecule ();
13003
                              copy_tmp_to_mol ();
13004
                              if (opt_verbose)
13005
                                write_needle_mol ();
13006
                              if (rs_strict)    /* v0.3j */
13007
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
13008
                              else
13009
                                ndl_ref_atom = find_ndl_ref_atom ();
13010
                              if (opt_verbose)
13011
                                write_mol ();
13012
                            }   /* v0.3m */
6785 bpr 13013
                      /* now that we have both molecules, perform the comparison */
13014
                      /* v0.3o: takes care of disconnected fragment... */
13015
                      clear_atom_tags ();
13016
                      set_ndl_atom_tags ();
13017
                      matchsummary = true;
13018
                      perform_match ();
13019
                      matchsummary = matchresult;
14179 bpr 13020
                      if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true) {
13021
                              do {
13022
                                if (rs_strict)
13023
                                        ndl_ref_atom = find_ndl_ref_atom_cv ();
13024
                                else
13025
                                        ndl_ref_atom = find_ndl_ref_atom ();
13026
                                perform_match ();
13027
                                if (matchresult == false)
13028
                                        matchsummary = false;
13029
                              }
13030
                              while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
6785 bpr 13031
                            }
13032
                      /* end of disconnected-fragment matching (v0.3o) */
14179 bpr 13033
                      if (matchsummary == true) {       /* v0.3o */
13034
                              if (opt_molout) {
13035
                                FORLIM = molbufindex;
13036
                                for (i = 1; i <= FORLIM; i++)
13037
                                        puts (molbuf[i - 1]);
13038
                              }
13039
                              else {
13040
                                if (!opt_fp)    /* inttostr(mol_count) REPLACE!!!, */
13041
                                        printf ("%i:T\n", mol_count);
13042
                                else {
13043
                                        if (ndl_n_heavyatoms == n_heavyatoms &&
13044
                                            ndl_n_heavybonds == n_heavybonds)
13045
                                          fp_exacthit = true;
13046
                                        else
13047
                                          fp_exacthit = false;
13048
                                        if (fp_exacthit)
13049
                                          fp_exactblock = true;
13050
                                        if (fpformat == fpf_boolean) {
13051
                                          if (fp_exacthit)      /* inttostr(mol_count), REPACE!!! */
13052
                                                  printf ("%i:TX\n", mol_count);
13053
                                          else
13054
                                                  printf ("%i:T\n", mol_count);
13055
                                        }
13056
                                        /* inttostr(mol_count), REPLACE!!! */
13057
                                        if (fpformat == fpf_decimal) {
13058
                                          fpincrement = 1;
13059
                                          FORLIM = fpindex;
13060
                                          for (i = 1; i <= FORLIM; i++)
13061
                                                  fpincrement <<= 1;
13062
                                          fpdecimal += fpincrement;
13063
                                        }
13064
                                      }
13065
                              }
6785 bpr 13066
                            }
14179 bpr 13067
                      else {
13068
                              if (!(opt_molout || (opt_fp && fpformat == fpf_decimal)))
13069
                                /* inttostr(mol_count), REPLACE!!! */
13070
                               printf ("%i:F\n", mol_count);
6785 bpr 13071
                            }
14179 bpr 13072
                      if (opt_fp && fpformat == fpf_decimal && fpindex == fp_blocksize) {
13073
                              if (fp_exactblock)
13074
                                fpdecimal++;
13075
                              printf ("%lld\n", fpdecimal);
13076
                              fpindex = 0;
13077
                              fpdecimal = 0;
13078
                              fp_exactblock = false;
13079
                            }
6785 bpr 13080
                      zap_molecule ();
13081
                      molbufindex = 0;
13082
                    }
14179 bpr 13083
                  }
13084
          }
13085
          else {
13086
            /* v0.3l */
13087
            /* mol_OK */
13088
            printf ("%i:unknown file format\n", mol_count);
13089
          }
6785 bpr 13090
        }
14179 bpr 13091
  while (mol_in_queue != false);
13092
    /* if filetype <> 'unknown' */
13093
    if (opt_fp && fpformat == fpf_decimal && fpindex > 0) {
13094
            if (fp_exactblock)
13095
              fpdecimal++;
13096
            printf ("%lld\n", fpdecimal);
13097
          }
13098
    zap_needle ();
13099
    if (rfile_is_open){                 /* new in v0.2g */
13100
            if (rfile != NULL)
13101
              fclose (rfile);
13102
            rfile = NULL;
13103
          }
13104
  }
6785 bpr 13105
  if (rfile != NULL)
13106
    fclose (rfile);
13107
  exit (0);
13108
}
13109
 
13110
#else
13111
 
14179 bpr 13112
static void init_globals_dll (void)
6785 bpr 13113
{
13114
 
13115
//printf("init_globals_dll\n");
13116
 
13117
  int i;
13118
  opt_verbose = false;
13119
  opt_debug = false;
13120
  opt_stdin = false;
13121
  opt_text = false;
13122
  opt_code = false;
13123
  opt_bin = false;
13124
  opt_bitstring = false;
13125
  opt_molout = false;
13126
  opt_molstat = false;
13127
  opt_molstat_X = false;
13128
  opt_xmdlout = false;
13129
  opt_fp = false;               /* new in v0.3m */
13130
  /*cm_mdlmolfile   := false; */
13131
  found_arominfo = false;
13132
  found_querymol = false;
13133
  ndl_querymol = false;
13134
  opt_rs = rs_sar;              /* v0.3i */
13135
  ringsearch_mode = opt_rs;
13136
  rfile_is_open = false;        /* new in v0.2g */
13137
  ez_flag = false;              /* new in v0.3f */
13138
  chir_flag = false;            /* new in v0.3f */
13139
  n_Ctot = 0;
13140
  n_Otot = 0;
13141
  n_Ntot = 0;                   /* new in v0.3g */
13142
  //for (i = 0; i < max_fg; i++)
13143
  //  fg[i] = false;
13144
  memset (fg, 0, sizeof (fglist));
13145
 
14179 bpr 13146
  if (!yet_initialized) {
13147
    molbuf = (void *) safe_malloc (sizeof (molbuftype));
13148
    opt_exact = false;
13149
    opt_strict = false; /* new in v0.2f */
13150
    opt_metalrings = false;     /* new in v0.3 */
13151
    opt_geom = false;           /* new in v0.3d */
13152
    opt_chiral = false; /* new in v0.3f */
13153
    opt_iso = false;            /* new in v0.3x */
13154
    opt_chg = false;            /* new in v0.3x */
13155
    opt_rad = false;            /* new in v0.3x */
13156
    ez_search = false;  /* new in v0.3d */
13157
    rs_search = false;  /* new in v0.3f */
13158
    rs_strict = false;  /* new in v0.3j */
13159
    ndl_n_Ctot = 0;
13160
    ndl_n_Otot = 0;
13161
    ndl_n_Ntot = 0;             /* new in v0.3g */
13162
    yet_initialized = true;
13163
  }
6785 bpr 13164
 
13165
  ether_generic = false;        /* v0.3j */
13166
  amine_generic = false;        /* v0.3j */
13167
  hydroxy_generic = false;      /* v0.3j */
13168
  fpformat = fpf_decimal;       /* v0.3m */
13169
  fpindex = 0;                  /* v0.3m */
13170
  fp_exacthit = false;          /* v0.3m */
13171
  fp_exactblock = false;        /* v0.3m */
13172
  tmfcode = 0;                  /* v0.3m */
13173
  tmfmismatch = false;          /* v0.3m */
13174
  auto_ssr = false;
13175
  recursion_depth = 0;
13176
}
13177
 
14179 bpr 13178
static void mm_init_mol (void)
6785 bpr 13179
{
13180
//printf("mm_init_mol\n");
13181
  init_globals_dll ();
13182
  init_molstat (&molstat);
14179 bpr 13183
  if (opt_rs_dll == RPA_DEFAULT) {
13184
    ringsearch_mode = opt_rs;
13185
    //printf("DEFAULT: %i\n",ringsearch_mode);
13186
  }
13187
  else {
13188
    ringsearch_mode = opt_rs_dll;
13189
  }
6785 bpr 13190
  //printf("RPA: %i\n",ringsearch_mode);
13191
 
14179 bpr 13192
  if (ringsearch_mode == rs_sar) {
6785 bpr 13193
      max_vringsize = max_ringsize;
14179 bpr 13194
  }
13195
  else {
6785 bpr 13196
      max_vringsize = ssr_vringsize;
14179 bpr 13197
  }
6785 bpr 13198
  zap_molecule ();
13199
  molbufindex = 0;
13200
  mol_count = 0;
13201
//printf("mm_init_mol\n");
13202
}
13203
 
14179 bpr 13204
static void mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
6785 bpr 13205
{
13206
//printf("mm_elab_mol\n");
13207
 
13208
  li = 1;                       // initialize line pointer for input buffer
13209
  get_filetype (filetype, ndl_molfilename);
14179 bpr 13210
  if (strcmp (filetype, "unknown") == 0) {
13211
    //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
13212
    exit (3);
13213
  }
6785 bpr 13214
 
13215
  if (checkmol_mode == true)
13216
    progmode = pmCheckMol;
13217
  else
13218
    progmode = pmMatchMol;
13219
  if (strcmp (filetype, "alchemy") == 0)
13220
    read_molfile (ndl_molfilename);
13221
  if (strcmp (filetype, "sybyl") == 0)
13222
    read_mol2file (ndl_molfilename);
13223
  if (strcmp (filetype, "mdl") == 0)
13224
    read_MDLmolfile (ndl_molfilename);
14179 bpr 13225
  if (checkmol_mode) {
13226
    if (found_querymol) {
13227
            printf ("Warning: Input structure contains query atom or query bond.\n");
13228
          }
13229
  }
6785 bpr 13230
 
13231
  count_neighbors ();
14179 bpr 13232
  if (!found_arominfo || checkmol_mode || opt_strict) {
13233
    //printf("No arom found or checkmol mode\n");
13234
    chk_ringbonds ();
13235
    if (ringsearch_mode == rs_ssr)
13236
            remove_redundant_rings ();
13237
    if (n_rings >= max_rings) {
13238
            printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
13239
               max_rings);
13240
            ringsearch_mode = rs_ssr;
13241
            auto_ssr = true;
13242
            clear_rings ();
13243
            max_vringsize = ssr_vringsize;
13244
            chk_ringbonds ();
13245
            remove_redundant_rings ();
13246
          }
6785 bpr 13247
 
14179 bpr 13248
    update_ringcount ();
13249
    if (normalize_ionic_bnds)   /* v0.3k */
13250
            normalize_ionic_bonds ();
13251
    update_atypes ();
13252
    update_Htotal ();
13253
    chk_arom ();
13254
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
13255
            do {
6785 bpr 13256
              prev_n_ar = count_aromatic_rings ();
13257
              chk_arom ();
13258
              n_ar = count_aromatic_rings ();
13259
            }
14179 bpr 13260
            while (prev_n_ar - n_ar != 0);
13261
          }
13262
  }
13263
  else {
13264
    if (normalize_ionic_bnds)   /* v0.3k  */
13265
            normalize_ionic_bonds ();
13266
    //if (opt_strict)
13267
    update_atypes ();
13268
    update_Htotal ();
13269
  }
13270
  //printf("mm_elab_mol\n");
6785 bpr 13271
}
13272
 
14179 bpr 13273
DLLEXPORT void mm_set_current_mol_as_query (void)
6785 bpr 13274
{
14179 bpr 13275
  //printf("mm_set_current_mol_as_query\n");
6785 bpr 13276
  zap_needle ();
14179 bpr 13277
  //mm_ElabMol;
6785 bpr 13278
  copy_mol_to_needle ();
13279
  //chk_wildcard_rings (); /* 0.3p */
13280
  set_ndl_atom_tags ();         /* v0.3o */
13281
  if (opt_geom)                 /* v0.3d */
13282
    ez_search = true;
13283
  else if (!ez_flag && ez_search)
13284
    ez_search = false;          //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14179 bpr 13285
  if (opt_chiral) {                             /* v0.3f */
6785 bpr 13286
      rs_search = true;
13287
      //printf("%i\n",rs_search);
14179 bpr 13288
  }
13289
  else
13290
    if (!chir_flag && rs_search) {
6785 bpr 13291
      rs_search = false;        //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
13292
      //printf("%i\n",rs_search);
13293
    }
13294
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
13295
    rs_strict = true;
13296
  else
13297
    rs_strict = false;
14179 bpr 13298
    /* if (rs_strict)              // v0.3j
13299
       ndl_ref_atom = find_ndl_ref_atom_cv ();
13300
       //ndl_ref_atom = find_ndl_ref_atom ();
13301
       else
13302
       ndl_ref_atom = find_ndl_ref_atom (); */
6785 bpr 13303
 
13304
  molbufindex = 0;
13305
  mol_count = 0;
14179 bpr 13306
  /*printf("mm_set_current_mol_as_query\n");*/
6785 bpr 13307
}
13308
 
14179 bpr 13309
DLLEXPORT int mm_get_rings (void)
6785 bpr 13310
{
13311
  return n_rings;
13312
}
13313
 
14179 bpr 13314
DLLEXPORT void xm_version (char *buffer)
6785 bpr 13315
{
13316
  buffer[0] = '\0';
13317
  strncpy (buffer, version, 255);
13318
}
13319
 
14179 bpr 13320
DLLEXPORT int mm_get_atom_ring (int atom_number)
6785 bpr 13321
{
13322
 
13323
  int i, j, a1, pl;
13324
  int ret = 0;
13325
  a1 = atom[atom_number].ring_count;
14179 bpr 13326
  if (n_rings > 0) {
13327
    for (i = 1; i < n_rings; i++) {
13328
            pl = path_length (ring[i]);
13329
      //          a2 := ring^[i,pl];
13330
            for (j = 1; j < pl; j++) {
6785 bpr 13331
              a1 = ring[i][j];
13332
              if (atom_number == a1)
14179 bpr 13333
                      ret = i;
13334
          //
13335
          //              inc(atom^[a1].ring_count);
13336
          //              b := get_bond(a1,a2);
13337
          //              inc(bond^[b].ring_count);
13338
          //              a2 := a1;
6785 bpr 13339
            }
14179 bpr 13340
          }
13341
  }
6785 bpr 13342
  return ret;
13343
}
13344
 
14179 bpr 13345
static void mm_read_input_line (char *st)
6785 bpr 13346
{
13347
//printf("mm_read_input_line_in\n");
13348
//var
13349
//yyy:pchar;
13350
 
13351
  mol_in_queue = false;
14179 bpr 13352
  if (molbufindex < (max_atoms + max_bonds + slack)) {
6785 bpr 13353
 
14179 bpr 13354
    //yyy:=Pchar(IntToStr(molbufindex));
13355
    //messagebox (0,yyy,'',0);
13356
    //printf("%i\n",molbufindex);
13357
    //printf("B:%s\n",st);
13358
          strcpy (molbuf[molbufindex++], st);
13359
    //printf("%x %x\n",&molbuf,molbuf);
13360
    //printf("%s\n",molbuf[molbufindex-1]);
13361
          //  molbufindex++;
13362
  }
13363
  else {
13364
    //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
13365
    printf ("Not enough memory for molfile! %i\n", molbufindex);
13366
    exit (1);
13367
  }
6785 bpr 13368
//printf("mm_read_input_line_out\n");
13369
}
13370
 
14179 bpr 13371
static void mm_set_mol_dll (const char *st, boolean checkmol_mode,
6785 bpr 13372
                boolean normalize_ionic_bnds)
13373
{
14179 bpr 13374
  //printf("mm_set_mol\n");
13375
  //printf("%s\n",st);
6785 bpr 13376
  char bb;
13377
  char aa;
13378
  int i;
13379
  int k;
13380
  int J;
13381
  int spt = 0;
13382
  char tt[256];
13383
  char bb10 = '\n';
13384
  char bb13 = '\r';
13385
  char bb0 = '\0';
13386
  int lenst;
14179 bpr 13387
  //char d[256];
6785 bpr 13388
  lenst = strlen (st);
14179 bpr 13389
  //tt=(char*)safe_malloc(256*sizeof(char));
6785 bpr 13390
  tt[0] = '\0';
14179 bpr 13391
  //messagebox(0,st,'',0);
6785 bpr 13392
  mm_init_mol ();
14179 bpr 13393
  for (i = spt; i < lenst; i++) {
13394
    bb = st[i];
13395
    if ((bb == bb10) || (i == lenst)) {
13396
            J = 0;
13397
            // d:='';
13398
            for (k = spt; k < i; k++) {
6785 bpr 13399
              aa = st[k];
14179 bpr 13400
              if ((aa != bb10) && (aa != bb13)) {
13401
                      //d:=d+aa;
13402
                      tt[J] = aa;
13403
                      J++;
13404
                    }
6785 bpr 13405
            }
14179 bpr 13406
            tt[J] = bb0;
13407
            spt = i;
13408
            //messagebox (0,tt,tt,0);
13409
      //printf("A:%s\n",tt);
13410
            mm_read_input_line (tt);
13411
          }
13412
  }
6785 bpr 13413
//free(tt);
13414
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
13415
//printf("mm_set_mol\n");
13416
}
13417
 
14179 bpr 13418
DLLEXPORT void cm_set_mol (const char *st, int normalize_ionic_bnds)
6785 bpr 13419
{
13420
  mm_set_mol_dll (st, true, (normalize_ionic_bnds != FEATURE_OFF));
13421
}
13422
 
14179 bpr 13423
DLLEXPORT void mm_set_mol (const char *st)
6785 bpr 13424
{
13425
  mm_set_mol_dll (st, false, true);
13426
}
13427
 
14179 bpr 13428
DLLEXPORT void xm_set_strict_typing (int strict_typing)
6785 bpr 13429
{
13430
  if (!yet_initialized)
13431
    init_globals_dll ();
13432
  opt_strict = (strict_typing != FEATURE_OFF);
13433
  //opt_strict=false; //This never worked right and is harmful
13434
}
13435
 
14179 bpr 13436
DLLEXPORT void mm_set_r_s_check (int r_s_check)
6785 bpr 13437
{
13438
  if (!yet_initialized)
13439
    init_globals_dll ();
13440
  opt_chiral = (r_s_check != FEATURE_OFF);
13441
}
13442
 
14179 bpr 13443
DLLEXPORT void mm_set_e_z_check (int e_z_check)
6785 bpr 13444
{
13445
  if (!yet_initialized)
13446
    init_globals_dll ();
13447
  opt_geom = (e_z_check != FEATURE_OFF);
13448
}
13449
 
14179 bpr 13450
DLLEXPORT void mm_set_chg_check (int chg_check)
6785 bpr 13451
{
13452
  if (!yet_initialized)
13453
    init_globals_dll ();
13454
  opt_chg = (chg_check != FEATURE_OFF);
13455
}
13456
 
14179 bpr 13457
DLLEXPORT void mm_set_iso_check (int iso_check)
6785 bpr 13458
{
13459
  if (!yet_initialized)
13460
    init_globals_dll ();
13461
  opt_iso = (iso_check != FEATURE_OFF);
13462
}
13463
 
14179 bpr 13464
DLLEXPORT void mm_set_rad_check (int rad_check)
6785 bpr 13465
{
13466
  if (!yet_initialized)
13467
    init_globals_dll ();
13468
  opt_rad = (rad_check != FEATURE_OFF);
13469
}
13470
 
14179 bpr 13471
DLLEXPORT void mm_set_exact_match (int exact)
6785 bpr 13472
{
13473
  if (!yet_initialized)
13474
    init_globals_dll ();
13475
  opt_exact = (exact != FEATURE_OFF);
13476
}
13477
 
14179 bpr 13478
DLLEXPORT int mm_match ()
6785 bpr 13479
{
13480
  mol_count = 1;
14179 bpr 13481
  //     mm_ElabMol;
13482
  /*printf("%i\n",opt_exact);
13483
  printf("%i\n",n_Ctot);
13484
  printf("%i\n",ndl_n_Ctot);
13485
  printf("%i\n",n_Otot);
13486
  printf("%i\n",ndl_n_Otot);
13487
  printf("%i\n",n_Ntot);
13488
  printf("%i\n",ndl_n_Ntot);*/
6785 bpr 13489
  if (opt_exact
13490
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14179 bpr 13491
            || n_Ntot != ndl_n_Ntot))
6785 bpr 13492
    return 0;
13493
  init_molstat (&ndl_molstat);
13494
  //perform_match ();
13495
  //---------------------------------------------------- 0.3o
13496
  if (rs_strict)                /* v0.3j */
13497
    ndl_ref_atom = find_ndl_ref_atom_cv ();
13498
  //ndl_ref_atom = find_ndl_ref_atom ();
13499
  else
13500
    ndl_ref_atom = find_ndl_ref_atom ();
13501
  clear_atom_tags ();
13502
  set_ndl_atom_tags ();
13503
  matchsummary = true;
13504
  perform_match ();
13505
  matchsummary = matchresult;
14179 bpr 13506
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true) {
13507
    do {
13508
            if (rs_strict)
13509
              ndl_ref_atom = find_ndl_ref_atom_cv ();
13510
            else
13511
              ndl_ref_atom = find_ndl_ref_atom ();
13512
            perform_match ();
13513
            if (matchresult == false)
13514
             matchsummary = false;
13515
          }
13516
    while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
13517
  }
6785 bpr 13518
 
13519
  //-----------------------------------------------------
13520
 
13521
  //mol_count = 0;
13522
 
13523
  //molbufindex = 0;
13524
 
13525
  //return matchresult ? 1 : 0;
13526
 
13527
  return matchsummary ? 1 : 0;
13528
}
13529
 
13530
//-------------------------
13531
 
14179 bpr 13532
DLLEXPORT void xm_set_ring_perception_algorithm (int algo)
6785 bpr 13533
{
14179 bpr 13534
  switch (algo) {
6785 bpr 13535
    case RPA_SAR:
13536
      opt_rs_dll = rs_sar;
13537
      break;
13538
    case RPA_SSR:
13539
      opt_rs_dll = rs_ssr;
13540
      break;
13541
    default:
13542
      opt_rs_dll = RPA_DEFAULT;
13543
      break;
13544
    }
13545
  //printf("RPA_SET: %i\n",opt_rs_dll);
13546
}
13547
 
14179 bpr 13548
static void write_molstat_X_dll (char *out_buffer)
6785 bpr 13549
{
13550
  char tmp_buf[256];
13551
  out_buffer[0] = '\0';
13552
  if (auto_ssr)                 /* v0.3n */
13553
    fix_ssr_ringcounts ();
13554
  sprintf (tmp_buf, "%d,", n_heavyatoms);
13555
  strcat (out_buffer, tmp_buf);
13556
  sprintf (tmp_buf, "%d,", n_heavybonds);
13557
  strcat (out_buffer, tmp_buf);
13558
#ifdef REDUCED_SAR
13559
  sprintf (tmp_buf, "%d,", n_countablerings);
13560
  strcat (out_buffer, tmp_buf);
13561
#else
13562
  sprintf (tmp_buf, "%d,", n_rings);
13563
  strcat (out_buffer, tmp_buf);
13564
#endif
13565
  sprintf (tmp_buf, "%d,", molstat.n_QA);
13566
  strcat (out_buffer, tmp_buf);
13567
  sprintf (tmp_buf, "%d,", molstat.n_QB);
13568
  strcat (out_buffer, tmp_buf);
13569
  //if (opt_chg)
13570
//    {                         /* 0.3x */
13571
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
13572
//    }
13573
//  else
13574
//    {
13575
  sprintf (tmp_buf, "%d,", molstat.n_chg);
13576
  //   }
13577
  strcat (out_buffer, tmp_buf);
13578
  sprintf (tmp_buf, "%d,", molstat.n_C1);
13579
  strcat (out_buffer, tmp_buf);
13580
  sprintf (tmp_buf, "%d,", molstat.n_C2);
13581
  strcat (out_buffer, tmp_buf);
13582
  sprintf (tmp_buf, "%d,", molstat.n_C);
13583
  strcat (out_buffer, tmp_buf);
13584
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
13585
  strcat (out_buffer, tmp_buf);
13586
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
13587
  strcat (out_buffer, tmp_buf);
13588
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
13589
  strcat (out_buffer, tmp_buf);
13590
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
13591
  strcat (out_buffer, tmp_buf);
13592
  sprintf (tmp_buf, "%d,", molstat.n_O2);
13593
  strcat (out_buffer, tmp_buf);
13594
  sprintf (tmp_buf, "%d,", molstat.n_O3);
13595
  strcat (out_buffer, tmp_buf);
13596
  sprintf (tmp_buf, "%d,", molstat.n_N1);
13597
  strcat (out_buffer, tmp_buf);
13598
  sprintf (tmp_buf, "%d,", molstat.n_N2);
13599
  strcat (out_buffer, tmp_buf);
13600
  sprintf (tmp_buf, "%d,", molstat.n_N3);
13601
  strcat (out_buffer, tmp_buf);
13602
  sprintf (tmp_buf, "%d,", molstat.n_S);
13603
  strcat (out_buffer, tmp_buf);
13604
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
13605
  strcat (out_buffer, tmp_buf);
13606
  sprintf (tmp_buf, "%d,", molstat.n_F);
13607
  strcat (out_buffer, tmp_buf);
13608
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
13609
  strcat (out_buffer, tmp_buf);
13610
  sprintf (tmp_buf, "%d,", molstat.n_Br);
13611
  strcat (out_buffer, tmp_buf);
13612
  sprintf (tmp_buf, "%d,", molstat.n_I);
13613
  strcat (out_buffer, tmp_buf);
13614
  sprintf (tmp_buf, "%d,", molstat.n_P);
13615
  strcat (out_buffer, tmp_buf);
13616
  sprintf (tmp_buf, "%d,", molstat.n_B);
13617
  strcat (out_buffer, tmp_buf);
13618
  sprintf (tmp_buf, "%d,", molstat.n_Met);
13619
  strcat (out_buffer, tmp_buf);
13620
  sprintf (tmp_buf, "%d,", molstat.n_X);
13621
  strcat (out_buffer, tmp_buf);
13622
  sprintf (tmp_buf, "%d,", molstat.n_b1);
13623
  strcat (out_buffer, tmp_buf);
13624
  sprintf (tmp_buf, "%d,", molstat.n_b2);
13625
  strcat (out_buffer, tmp_buf);
13626
  sprintf (tmp_buf, "%d,", molstat.n_b3);
13627
  strcat (out_buffer, tmp_buf);
13628
  sprintf (tmp_buf, "%d,", molstat.n_bar);
13629
  strcat (out_buffer, tmp_buf);
13630
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
13631
  strcat (out_buffer, tmp_buf);
13632
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
13633
  strcat (out_buffer, tmp_buf);
13634
  sprintf (tmp_buf, "%d,", molstat.n_CN);
13635
  strcat (out_buffer, tmp_buf);
13636
  sprintf (tmp_buf, "%d,", molstat.n_XY);
13637
  strcat (out_buffer, tmp_buf);
13638
  sprintf (tmp_buf, "%d,", molstat.n_r3);
13639
  strcat (out_buffer, tmp_buf);
13640
  sprintf (tmp_buf, "%d,", molstat.n_r4);
13641
  strcat (out_buffer, tmp_buf);
13642
  sprintf (tmp_buf, "%d,", molstat.n_r5);
13643
  strcat (out_buffer, tmp_buf);
13644
  sprintf (tmp_buf, "%d,", molstat.n_r6);
13645
  strcat (out_buffer, tmp_buf);
13646
  sprintf (tmp_buf, "%d,", molstat.n_r7);
13647
  strcat (out_buffer, tmp_buf);
13648
  sprintf (tmp_buf, "%d,", molstat.n_r8);
13649
  strcat (out_buffer, tmp_buf);
13650
  sprintf (tmp_buf, "%d,", molstat.n_r9);
13651
  strcat (out_buffer, tmp_buf);
13652
  sprintf (tmp_buf, "%d,", molstat.n_r10);
13653
  strcat (out_buffer, tmp_buf);
13654
  sprintf (tmp_buf, "%d,", molstat.n_r11);
13655
  strcat (out_buffer, tmp_buf);
13656
  sprintf (tmp_buf, "%d,", molstat.n_r12);
13657
  strcat (out_buffer, tmp_buf);
13658
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
13659
  strcat (out_buffer, tmp_buf);
13660
  sprintf (tmp_buf, "%d,", molstat.n_rN);
13661
  strcat (out_buffer, tmp_buf);
13662
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
13663
  strcat (out_buffer, tmp_buf);
13664
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
13665
  strcat (out_buffer, tmp_buf);
13666
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
13667
  strcat (out_buffer, tmp_buf);
13668
  sprintf (tmp_buf, "%d,", molstat.n_rO);
13669
  strcat (out_buffer, tmp_buf);
13670
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
13671
  strcat (out_buffer, tmp_buf);
13672
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
13673
  strcat (out_buffer, tmp_buf);
13674
  sprintf (tmp_buf, "%d,", molstat.n_rS);
13675
  strcat (out_buffer, tmp_buf);
13676
  sprintf (tmp_buf, "%d,", molstat.n_rX);
13677
  strcat (out_buffer, tmp_buf);
13678
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
13679
  strcat (out_buffer, tmp_buf);
13680
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
13681
  strcat (out_buffer, tmp_buf);
13682
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
13683
  strcat (out_buffer, tmp_buf);
13684
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
13685
  strcat (out_buffer, tmp_buf);
13686
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
13687
  strcat (out_buffer, tmp_buf);
13688
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
13689
  strcat (out_buffer, tmp_buf);
13690
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
13691
  strcat (out_buffer, tmp_buf);
13692
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
13693
  strcat (out_buffer, tmp_buf);
13694
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
13695
  strcat (out_buffer, tmp_buf);
13696
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
13697
  strcat (out_buffer, tmp_buf);
13698
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
13699
  strcat (out_buffer, tmp_buf);
13700
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
13701
  strcat (out_buffer, tmp_buf);
13702
  sprintf (tmp_buf, "%d,", molstat.n_psla);
13703
  strcat (out_buffer, tmp_buf);
13704
  sprintf (tmp_buf, "%d,", molstat.n_iso);
13705
  strcat (out_buffer, tmp_buf);
13706
  sprintf (tmp_buf, "%d", molstat.n_rad);
13707
  strcat (out_buffer, tmp_buf);
13708
}
13709
 
14179 bpr 13710
static void write_molstat_dll (char *out_buffer, int mode) {
6785 bpr 13711
  char tmp_buf[256];
13712
  char *sep1;
13713
  char *sep2;
14179 bpr 13714
  switch (mode) {
6785 bpr 13715
    case 1:
13716
      sep1 = "=";
13717
      sep2 = " AND ";
13718
      break;
13719
    case 2:
13720
      sep1 = "<=";
13721
      sep2 = " AND ";
13722
      break;
13723
    default:
13724
      sep1 = ":";
13725
      sep2 = ";";
13726
      break;
13727
    }
13728
 
13729
  out_buffer[0] = '\0';
13730
 
13731
  if (auto_ssr)                 /* v0.3n */
13732
    fix_ssr_ringcounts ();
13733
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
13734
  strcat (out_buffer, tmp_buf);
14179 bpr 13735
  if (n_bonds > 0) {
6785 bpr 13736
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
13737
      strcat (out_buffer, tmp_buf);
13738
    }
13739
 
13740
#ifdef REDUCED_SAR
14179 bpr 13741
  if (n_rings > 0) {
6785 bpr 13742
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
13743
      strcat (out_buffer, tmp_buf);
13744
    }
13745
#else
14179 bpr 13746
  if (n_rings > 0) {
6785 bpr 13747
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
13748
      strcat (out_buffer, tmp_buf);
13749
    }
13750
#endif
13751
 
14179 bpr 13752
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */ {
13753
    sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
13754
    strcat (out_buffer, tmp_buf);
13755
  }
13756
  if (molstat.n_C1 > 0) {
13757
    sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
13758
    strcat (out_buffer, tmp_buf);
13759
  }
13760
  if (molstat.n_C2 > 0) {
13761
    sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
13762
    strcat (out_buffer, tmp_buf);
13763
  }
6785 bpr 13764
 
14179 bpr 13765
  if (molstat.n_C > 0) {
13766
    sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
13767
    strcat (out_buffer, tmp_buf);
13768
  }
13769
  if (molstat.n_CHB1p > 0) {
13770
    sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
13771
    strcat (out_buffer, tmp_buf);
13772
  }
13773
  if (molstat.n_CHB2p > 0) {
13774
    sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
13775
    strcat (out_buffer, tmp_buf);
13776
  }
13777
  if (molstat.n_CHB3p > 0) {
13778
    sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
13779
    strcat (out_buffer, tmp_buf);
13780
  }
13781
  if (molstat.n_CHB4 > 0) {
13782
    sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
13783
    strcat (out_buffer, tmp_buf);
13784
  }
13785
  if (molstat.n_O2 > 0) {
13786
    sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
13787
    strcat (out_buffer, tmp_buf);
13788
  }
13789
  if (molstat.n_O3 > 0) {
13790
    sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
13791
    strcat (out_buffer, tmp_buf);
13792
  }
13793
  if (molstat.n_N1 > 0) {
13794
    sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
13795
    strcat (out_buffer, tmp_buf);
13796
  }
13797
  if (molstat.n_N2 > 0) {
13798
    sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
13799
    strcat (out_buffer, tmp_buf);
13800
  }
13801
  if (molstat.n_N3 > 0) {
13802
    sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
13803
    strcat (out_buffer, tmp_buf);
13804
  }
13805
  if (molstat.n_S > 0) {
13806
    sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
13807
    strcat (out_buffer, tmp_buf);
13808
  }
13809
  if (molstat.n_SeTe > 0) {
13810
    sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
13811
    strcat (out_buffer, tmp_buf);
13812
  }
13813
  if (molstat.n_F > 0) {
13814
    sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
13815
    strcat (out_buffer, tmp_buf);
13816
  }
13817
  if (molstat.n_Cl > 0) {
13818
    sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
13819
    strcat (out_buffer, tmp_buf);
13820
  }
13821
  if (molstat.n_Br > 0) {
13822
    sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
13823
    strcat (out_buffer, tmp_buf);
13824
  }
13825
  if (molstat.n_I > 0) {
13826
    sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
13827
    strcat (out_buffer, tmp_buf);
13828
  }
13829
  if (molstat.n_P > 0) {
13830
    sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
13831
    strcat (out_buffer, tmp_buf);
13832
  }
13833
  if (molstat.n_B > 0) {
13834
    sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
13835
    strcat (out_buffer, tmp_buf);
13836
  }
13837
  if (molstat.n_Met > 0) {
13838
    sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
13839
    strcat (out_buffer, tmp_buf);
13840
  }
13841
  if (molstat.n_X > 0) {
13842
    sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
13843
    strcat (out_buffer, tmp_buf);
13844
  }
13845
  if (molstat.n_b1 > 0) {
13846
    sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
13847
    strcat (out_buffer, tmp_buf);
13848
  }
13849
  if (molstat.n_b2 > 0) {
13850
    sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
13851
    strcat (out_buffer, tmp_buf);
13852
  }
13853
  if (molstat.n_b3 > 0) {
13854
    sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
13855
    strcat (out_buffer, tmp_buf);
13856
  }
13857
  if (molstat.n_bar > 0) {
13858
   sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
13859
   strcat (out_buffer, tmp_buf);
13860
  }
13861
  if (molstat.n_C1O > 0) {
13862
    sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
13863
    strcat (out_buffer, tmp_buf);
13864
  }
13865
  if (molstat.n_C2O > 0) {
6785 bpr 13866
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
13867
      strcat (out_buffer, tmp_buf);
13868
    }
14179 bpr 13869
  if (molstat.n_CN > 0) {
6785 bpr 13870
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
13871
      strcat (out_buffer, tmp_buf);
13872
    }
14179 bpr 13873
  if (molstat.n_XY > 0) {
13874
    sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
13875
    strcat (out_buffer, tmp_buf);
13876
  }
13877
  if (molstat.n_r3 > 0) {
13878
    sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
13879
    strcat (out_buffer, tmp_buf);
13880
  }
13881
  if (molstat.n_r4 > 0) {
13882
    sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
13883
    strcat (out_buffer, tmp_buf);
13884
  }
13885
  if (molstat.n_r5 > 0) {
13886
    sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
13887
    strcat (out_buffer, tmp_buf);
13888
  }
13889
  if (molstat.n_r6 > 0) {
13890
    sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
13891
    strcat (out_buffer, tmp_buf);
13892
  }
13893
  if (molstat.n_r7 > 0) {
13894
    sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
13895
    strcat (out_buffer, tmp_buf);
13896
  }
13897
  if (molstat.n_r8 > 0) {
13898
    sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
13899
    strcat (out_buffer, tmp_buf);
13900
  }
13901
  if (molstat.n_r9 > 0) {
13902
    sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
13903
    strcat (out_buffer, tmp_buf);
13904
  }
13905
  if (molstat.n_r10 > 0) {
13906
    sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
13907
    strcat (out_buffer, tmp_buf);
13908
  }
13909
  if (molstat.n_r11 > 0) {
13910
    sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
13911
    strcat (out_buffer, tmp_buf);
13912
  }
13913
  if (molstat.n_r12 > 0) {
13914
    sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
13915
    strcat (out_buffer, tmp_buf);
13916
  }
13917
  if (molstat.n_r13p > 0) {
6785 bpr 13918
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
13919
      strcat (out_buffer, tmp_buf);
13920
    }
14179 bpr 13921
  if (molstat.n_rN > 0) {
13922
    sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
13923
    strcat (out_buffer, tmp_buf);
13924
  }
13925
  if (molstat.n_rN1 > 0) {
13926
    sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
13927
    strcat (out_buffer, tmp_buf);
13928
  }
13929
  if (molstat.n_rN2 > 0) {
13930
    sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
13931
    strcat (out_buffer, tmp_buf);
13932
  }
13933
  if (molstat.n_rN3p > 0) {
13934
    sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
13935
    strcat (out_buffer, tmp_buf);
13936
  }
13937
  if (molstat.n_rO > 0) {
13938
    sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
13939
    strcat (out_buffer, tmp_buf);
13940
  }
13941
  if (molstat.n_rO1 > 0) {
13942
    sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
13943
    strcat (out_buffer, tmp_buf);
13944
  }
13945
  if (molstat.n_rO2p > 0) {
13946
    sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
13947
    strcat (out_buffer, tmp_buf);
13948
  }
13949
  if (molstat.n_rS > 0) {
13950
    sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
13951
    strcat (out_buffer, tmp_buf);
13952
  }
13953
  if (molstat.n_rX > 0) {
13954
    sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
13955
    strcat (out_buffer, tmp_buf);
13956
  }
13957
  if (molstat.n_rAr > 0) {
13958
    sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
13959
    strcat (out_buffer, tmp_buf);
13960
  }
6785 bpr 13961
 
14179 bpr 13962
  if (molstat.n_rBz > 0) {
13963
    sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
13964
    strcat (out_buffer, tmp_buf);
13965
  }
6785 bpr 13966
 
14179 bpr 13967
  if (molstat.n_br2p > 0) {
13968
    sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
13969
    strcat (out_buffer, tmp_buf);
13970
  }
6785 bpr 13971
 
14179 bpr 13972
  if (molstat.n_psg01 > 0) {
13973
    sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
13974
    strcat (out_buffer, tmp_buf);
13975
  }
6785 bpr 13976
 
14179 bpr 13977
  if (molstat.n_psg02 > 0) {
13978
    sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
13979
    strcat (out_buffer, tmp_buf);
13980
  }
6785 bpr 13981
 
14179 bpr 13982
  if (molstat.n_psg13 > 0) {
13983
    sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
13984
    strcat (out_buffer, tmp_buf);
13985
  }
6785 bpr 13986
 
14179 bpr 13987
  if (molstat.n_psg14 > 0) {
13988
    sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
13989
    strcat (out_buffer, tmp_buf);
13990
  }
6785 bpr 13991
 
14179 bpr 13992
  if (molstat.n_psg15 > 0) {
13993
    sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
13994
    strcat (out_buffer, tmp_buf);
13995
  }
6785 bpr 13996
 
14179 bpr 13997
  if (molstat.n_psg16 > 0) {
13998
    sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
13999
    strcat (out_buffer, tmp_buf);
14000
  }
6785 bpr 14001
 
14179 bpr 14002
  if (molstat.n_psg17 > 0) {
14003
    sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
14004
    strcat (out_buffer, tmp_buf);
14005
  }
6785 bpr 14006
 
14179 bpr 14007
  if (molstat.n_psg18 > 0) {
14008
    sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
14009
    strcat (out_buffer, tmp_buf);
14010
  }
6785 bpr 14011
 
14179 bpr 14012
  if (molstat.n_pstm > 0) {
6785 bpr 14013
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
14014
      strcat (out_buffer, tmp_buf);
14015
    }
14016
 
14179 bpr 14017
  if (molstat.n_psla > 0) {
6785 bpr 14018
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
14019
      strcat (out_buffer, tmp_buf);
14020
    }
14021
 
14179 bpr 14022
  if (opt_iso && molstat.n_iso > 0) {
14023
    sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
14024
    strcat (out_buffer, tmp_buf);
14025
  }
6785 bpr 14026
 
14179 bpr 14027
  if (opt_rad && molstat.n_rad > 0) {
14028
    sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
14029
    strcat (out_buffer, tmp_buf);
14030
  }
6785 bpr 14031
}
14032
 
14033
static void
14034
write_fg_code_dll (char *out_buffer)
14035
{
14036
  char tmp_buf[256];
14037
  out_buffer[0] = '\0';
14179 bpr 14038
  if (fg[fg_cation - 1]) {
14039
    sprintf (tmp_buf, "000000T2;");
14040
    strcat (out_buffer, tmp_buf);
14041
  }
14042
  if (fg[fg_anion - 1]) {
14043
    sprintf (tmp_buf, "000000T1;");
14044
    strcat (out_buffer, tmp_buf);
14045
  }
6785 bpr 14046
 
14179 bpr 14047
  if (fg[fg_aldehyde - 1]) {
14048
    sprintf (tmp_buf, "C2O1H000;");
14049
    strcat (out_buffer, tmp_buf);
14050
  }
14051
  if (fg[fg_ketone - 1]) {
14052
    sprintf (tmp_buf, "C2O1C000;");
14053
    strcat (out_buffer, tmp_buf);
14054
  }
6785 bpr 14055
 
14179 bpr 14056
  if (fg[fg_thioaldehyde - 1]) {
14057
    sprintf (tmp_buf, "C2S1H000;");
14058
    strcat (out_buffer, tmp_buf);
14059
  }
14060
  if (fg[fg_thioketone - 1]) {
14061
    sprintf (tmp_buf, "C2S1C000;");
14062
    strcat (out_buffer, tmp_buf);
14063
  }
14064
  if (fg[fg_imine - 1]) {
14065
    sprintf (tmp_buf, "C2N10000;");
14066
    strcat (out_buffer, tmp_buf);
14067
  }
14068
  if (fg[fg_hydrazone - 1]) {
14069
    sprintf (tmp_buf, "C2N1N000;");
14070
    strcat (out_buffer, tmp_buf);
14071
  }
14072
  if (fg[fg_semicarbazone - 1]) {
14073
    sprintf (tmp_buf, "C2NNC4ON;");
14074
    strcat (out_buffer, tmp_buf);
14075
  }
14076
  if (fg[fg_thiosemicarbazone - 1]) {
14077
    sprintf (tmp_buf, "C2NNC4SN;");
14078
    strcat (out_buffer, tmp_buf);
14079
  }
14080
  if (fg[fg_oxime - 1]) {
14081
    sprintf (tmp_buf, "C2N1OH00;");
14082
    strcat (out_buffer, tmp_buf);
14083
  }
14084
  if (fg[fg_oxime_ether - 1]) {
14085
    sprintf (tmp_buf, "C2N1OC00;");
14086
    strcat (out_buffer, tmp_buf);
14087
  }
14088
  if (fg[fg_ketene - 1]) {
14089
    sprintf (tmp_buf, "C3OC0000;");
14090
    strcat (out_buffer, tmp_buf);
14091
  }
14092
  if (fg[fg_ketene_acetal_deriv - 1]) {
14093
    sprintf (tmp_buf, "C3OCC000;");
14094
    strcat (out_buffer, tmp_buf);
14095
  }
14096
  if (fg[fg_carbonyl_hydrate - 1]) {
14097
    sprintf (tmp_buf, "C2O2H200;");
14098
    strcat (out_buffer, tmp_buf);
14099
  }
14100
  if (fg[fg_hemiacetal - 1]) {
14101
    sprintf (tmp_buf, "C2O2HC00;");
14102
    strcat (out_buffer, tmp_buf);
14103
  }
14104
  if (fg[fg_acetal - 1]) {
14105
   sprintf (tmp_buf, "C2O2CC00;");
14106
   strcat (out_buffer, tmp_buf);
14107
  }
14108
  if (fg[fg_hemiaminal - 1]) {
14109
    sprintf (tmp_buf, "C2NOHC10;");
14110
    strcat (out_buffer, tmp_buf);
14111
  }
14112
  if (fg[fg_aminal - 1]) {
14113
    sprintf (tmp_buf, "C2N2CC10;");
14114
    strcat (out_buffer, tmp_buf);
14115
  }
14116
  if (fg[fg_thiohemiaminal - 1]) {
14117
    sprintf (tmp_buf, "C2NSHC10;");
14118
    strcat (out_buffer, tmp_buf);
14119
  }
14120
  if (fg[fg_thioacetal - 1]) {
14121
    sprintf (tmp_buf, "C2S2CC00;");
14122
    strcat (out_buffer, tmp_buf);
14123
  }
14124
  if (fg[fg_enamine - 1]) {
14125
    sprintf (tmp_buf, "C2CNH000;");
14126
    strcat (out_buffer, tmp_buf);
14127
  }
14128
  if (fg[fg_enol - 1]) {
14129
    sprintf (tmp_buf, "C2COH000;");
14130
    strcat (out_buffer, tmp_buf);
14131
  }
14132
  if (fg[fg_enolether - 1]) {
14133
    sprintf (tmp_buf, "C2COC000;");
14134
    strcat (out_buffer, tmp_buf);
14135
  }
6785 bpr 14136
 
14179 bpr 14137
  if (fg[fg_prim_alcohol - 1]) {
14138
    sprintf (tmp_buf, "O1H1C000;");
14139
    strcat (out_buffer, tmp_buf);
14140
  }
14141
  if (fg[fg_sec_alcohol - 1]) {
14142
    sprintf (tmp_buf, "O1H2C000;");
14143
    strcat (out_buffer, tmp_buf);
14144
  }
14145
  if (fg[fg_tert_alcohol - 1]) {
14146
    sprintf (tmp_buf, "O1H3C000;");
14147
    strcat (out_buffer, tmp_buf);
14148
  }
14149
  if (fg[fg_1_2_diol - 1]) {
14150
    sprintf (tmp_buf, "O1H0CO1H;");
14151
    strcat (out_buffer, tmp_buf);
14152
  }
14153
  if (fg[fg_1_2_aminoalcohol - 1]) {
14154
    sprintf (tmp_buf, "O1H0CN1C;");
14155
    strcat (out_buffer, tmp_buf);
14156
  }
14157
  if (fg[fg_phenol - 1]) {
14158
    sprintf (tmp_buf, "O1H1A000;");
14159
    strcat (out_buffer, tmp_buf);
14160
  }
14161
  if (fg[fg_1_2_diphenol - 1]) {
14162
    sprintf (tmp_buf, "O1H2A000;");
14163
    strcat (out_buffer, tmp_buf);
14164
  }
14165
  if (fg[fg_enediol - 1]) {
14166
    sprintf (tmp_buf, "C2COH200;");
14167
    strcat (out_buffer, tmp_buf);
14168
  }
6785 bpr 14169
 
14179 bpr 14170
  if (fg[fg_dialkylether - 1]) {
14171
    sprintf (tmp_buf, "O1C0CC00;");
14172
    strcat (out_buffer, tmp_buf);
14173
  }
14174
  if (fg[fg_alkylarylether - 1]) {
14175
    sprintf (tmp_buf, "O1C0CA00;");
14176
    strcat (out_buffer, tmp_buf);
14177
  }
14178
  if (fg[fg_diarylether - 1]) {
14179
    sprintf (tmp_buf, "O1C0AA00;");
14180
    strcat (out_buffer, tmp_buf);
14181
  }
14182
  if (fg[fg_thioether - 1]) {
14183
    sprintf (tmp_buf, "S1C00000;");
14184
    strcat (out_buffer, tmp_buf);
14185
  }
14186
  if (fg[fg_disulfide - 1]) {
14187
    sprintf (tmp_buf, "S1S1C000;");
14188
    strcat (out_buffer, tmp_buf);
14189
  }
14190
  if (fg[fg_peroxide - 1]) {
14191
    sprintf (tmp_buf, "O1O1C000;");
14192
    strcat (out_buffer, tmp_buf);
14193
  }
14194
  if (fg[fg_hydroperoxide - 1]) {
14195
    sprintf (tmp_buf, "O1O1H000;");
14196
    strcat (out_buffer, tmp_buf);
14197
  }
14198
  if (fg[fg_hydrazine - 1]) {
14199
    sprintf (tmp_buf, "N1N10000;");
14200
    strcat (out_buffer, tmp_buf);
14201
  }
14202
  if (fg[fg_hydroxylamine - 1]) {
14203
    sprintf (tmp_buf, "N1O1H000;");
14204
    strcat (out_buffer, tmp_buf);
14205
  }
6785 bpr 14206
 
14179 bpr 14207
  if (fg[fg_prim_aliph_amine - 1]) {
14208
    sprintf (tmp_buf, "N1C1C000;");
14209
    strcat (out_buffer, tmp_buf);
14210
  }
14211
  if (fg[fg_prim_arom_amine - 1]) {
14212
    sprintf (tmp_buf, "N1C1A000;");
14213
    strcat (out_buffer, tmp_buf);
14214
  }
6785 bpr 14215
 
14179 bpr 14216
  if (fg[fg_sec_aliph_amine - 1]) {
14217
    sprintf (tmp_buf, "N1C2CC00;");
14218
    strcat (out_buffer, tmp_buf);
14219
  }
14220
  if (fg[fg_sec_mixed_amine - 1]) {
14221
    sprintf (tmp_buf, "N1C2AC00;");
14222
    strcat (out_buffer, tmp_buf);
14223
  }
14224
  if (fg[fg_sec_arom_amine - 1]) {
14225
    sprintf (tmp_buf, "N1C2AA00;");
14226
    strcat (out_buffer, tmp_buf);
14227
  }
6785 bpr 14228
 
14179 bpr 14229
  if (fg[fg_tert_aliph_amine - 1]) {
14230
    sprintf (tmp_buf, "N1C3CC00;");
14231
    strcat (out_buffer, tmp_buf);
14232
  }
14233
  if (fg[fg_tert_mixed_amine - 1]) {
14234
    sprintf (tmp_buf, "N1C3AC00;");
14235
    strcat (out_buffer, tmp_buf);
14236
  }
14237
  if (fg[fg_tert_arom_amine - 1]) {
14238
    sprintf (tmp_buf, "N1C3AA00;");
14239
    strcat (out_buffer, tmp_buf);
14240
  }
14241
  if (fg[fg_quart_ammonium - 1]) {
14242
    sprintf (tmp_buf, "N1C400T2;");
14243
    strcat (out_buffer, tmp_buf);
14244
  }
14245
  if (fg[fg_n_oxide - 1]) {
14246
    sprintf (tmp_buf, "N0O10000;");
14247
    strcat (out_buffer, tmp_buf);
14248
  }
6785 bpr 14249
 
14179 bpr 14250
  if (fg[fg_halogen_deriv - 1]) {
14251
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1]) {
14252
            sprintf (tmp_buf, "XX000000;");
14253
            strcat (out_buffer, tmp_buf);
14254
          }
14255
  }
6785 bpr 14256
 
14179 bpr 14257
  if (fg[fg_alkyl_fluoride - 1]) {
14258
    sprintf (tmp_buf, "XF00C000;");
14259
    strcat (out_buffer, tmp_buf);
14260
  }
14261
  if (fg[fg_alkyl_chloride - 1]) {
14262
    sprintf (tmp_buf, "XC00C000;");
14263
    strcat (out_buffer, tmp_buf);
14264
  }
14265
  if (fg[fg_alkyl_bromide - 1]) {
14266
    sprintf (tmp_buf, "XB00C000;");
14267
    strcat (out_buffer, tmp_buf);
14268
  }
14269
  if (fg[fg_alkyl_iodide - 1]) {
14270
    sprintf (tmp_buf, "XI00C000;");
14271
    strcat (out_buffer, tmp_buf);
14272
  }
6785 bpr 14273
 
14179 bpr 14274
  if (fg[fg_aryl_fluoride - 1]) {
14275
    sprintf (tmp_buf, "XF00A000;");
14276
    strcat (out_buffer, tmp_buf);
14277
  }
14278
  if (fg[fg_aryl_chloride - 1]) {
14279
    sprintf (tmp_buf, "XC00A000;");
14280
    strcat (out_buffer, tmp_buf);
14281
  }
14282
  if (fg[fg_aryl_bromide - 1]) {
14283
    sprintf (tmp_buf, "XB00A000;");
14284
    strcat (out_buffer, tmp_buf);
14285
  }
14286
  if (fg[fg_aryl_iodide - 1]) {
14287
    sprintf (tmp_buf, "XI00A000;");
14288
    strcat (out_buffer, tmp_buf);
14289
  }
14290
  if (fg[fg_organometallic - 1]) {
14291
    sprintf (tmp_buf, "000000MX;");
14292
    strcat (out_buffer, tmp_buf);
14293
  }
14294
  if (fg[fg_organolithium - 1]) {
14295
    sprintf (tmp_buf, "000000ML;");
14296
    strcat (out_buffer, tmp_buf);
14297
  }
14298
  if (fg[fg_organomagnesium - 1]) {
14299
    sprintf (tmp_buf, "000000MM;");
14300
    strcat (out_buffer, tmp_buf);
14301
  }
6785 bpr 14302
 
14179 bpr 14303
  if (fg[fg_carboxylic_acid - 1]) {
14304
    sprintf (tmp_buf, "C3O2H000;");
14305
    strcat (out_buffer, tmp_buf);
14306
  }
14307
  if (fg[fg_carboxylic_acid_salt - 1]) {
14308
    sprintf (tmp_buf, "C3O200T1;");
14309
    strcat (out_buffer, tmp_buf);
14310
  }
14311
  if (fg[fg_carboxylic_acid_ester - 1]) {
14312
    sprintf (tmp_buf, "C3O2C000;");
14313
    strcat (out_buffer, tmp_buf);
14314
  }
14315
  if (fg[fg_lactone - 1]) {
14316
    sprintf (tmp_buf, "C3O2CZ00;");
14317
    strcat (out_buffer, tmp_buf);
14318
  }
6785 bpr 14319
 
14179 bpr 14320
  if (fg[fg_carboxylic_acid_prim_amide - 1]) {
14321
    sprintf (tmp_buf, "C3ONC100;");
14322
    strcat (out_buffer, tmp_buf);
14323
  }
14324
  if (fg[fg_carboxylic_acid_sec_amide - 1]) {
14325
    sprintf (tmp_buf, "C3ONC200;");
14326
    strcat (out_buffer, tmp_buf);
14327
  }
14328
  if (fg[fg_carboxylic_acid_tert_amide - 1]) {
14329
    sprintf (tmp_buf, "C3ONC300;");
14330
    strcat (out_buffer, tmp_buf);
14331
  }
14332
  if (fg[fg_lactam - 1]) {
14333
    sprintf (tmp_buf, "C3ONCZ00;");
14334
    strcat (out_buffer, tmp_buf);
14335
  }
14336
  if (fg[fg_carboxylic_acid_hydrazide - 1]) {
14337
    sprintf (tmp_buf, "C3ONN100;");
14338
    strcat (out_buffer, tmp_buf);
14339
  }
14340
  if (fg[fg_carboxylic_acid_azide - 1]) {
14341
    sprintf (tmp_buf, "C3ONN200;");
14342
    strcat (out_buffer, tmp_buf);
14343
  }
14344
  if (fg[fg_hydroxamic_acid - 1]) {
14345
    sprintf (tmp_buf, "C3ONOH00;");
14346
    strcat (out_buffer, tmp_buf);
14347
  }
14348
  if (fg[fg_carboxylic_acid_amidine - 1]) {
14349
    sprintf (tmp_buf, "C3N2H000;");
14350
    strcat (out_buffer, tmp_buf);
14351
  }
14352
  if (fg[fg_carboxylic_acid_amidrazone - 1]) {
14353
    sprintf (tmp_buf, "C3NNN100;");
14354
    strcat (out_buffer, tmp_buf);
14355
  }
14356
  if (fg[fg_nitrile - 1]) {
14357
    sprintf (tmp_buf, "C3N00000;");
14358
    strcat (out_buffer, tmp_buf);
14359
  }
6785 bpr 14360
 
14179 bpr 14361
  if (fg[fg_acyl_fluoride - 1]) {
14362
    sprintf (tmp_buf, "C3OXF000;");
14363
    strcat (out_buffer, tmp_buf);
14364
  }
14365
  if (fg[fg_acyl_chloride - 1]) {
14366
    sprintf (tmp_buf, "C3OXC000;");
14367
    strcat (out_buffer, tmp_buf);
14368
  }
14369
  if (fg[fg_acyl_bromide - 1]) {
14370
    sprintf (tmp_buf, "C3OXB000;");
14371
    strcat (out_buffer, tmp_buf);
14372
  }
14373
  if (fg[fg_acyl_iodide - 1]) {
14374
    sprintf (tmp_buf, "C3OXI000;");
14375
    strcat (out_buffer, tmp_buf);
14376
  }
14377
  if (fg[fg_acyl_cyanide - 1]) {
14378
    sprintf (tmp_buf, "C2OC3N00;");
14379
    strcat (out_buffer, tmp_buf);
14380
  }
14381
  if (fg[fg_imido_ester - 1]) {
14382
    sprintf (tmp_buf, "C3NOC000;");
14383
    strcat (out_buffer, tmp_buf);
14384
  }
14385
  if (fg[fg_imidoyl_halide - 1]) {
14386
    sprintf (tmp_buf, "C3NXX000;");
14387
    strcat (out_buffer, tmp_buf);
14388
  }
6785 bpr 14389
 
14179 bpr 14390
  if (fg[fg_thiocarboxylic_acid - 1]) {
14391
    sprintf (tmp_buf, "C3SOH000;");
14392
    strcat (out_buffer, tmp_buf);
14393
  }
14394
  if (fg[fg_thiocarboxylic_acid_ester - 1]) {
14395
    sprintf (tmp_buf, "C3SOC000;");
14396
    strcat (out_buffer, tmp_buf);
14397
  }
14398
  if (fg[fg_thiolactone - 1]) {
14399
    sprintf (tmp_buf, "C3SOCZ00;");
14400
    strcat (out_buffer, tmp_buf);
14401
  }
14402
  if (fg[fg_thiocarboxylic_acid_amide - 1]) {
14403
    sprintf (tmp_buf, "C3SNH000;");
14404
    strcat (out_buffer, tmp_buf);
14405
  }
14406
  if (fg[fg_thiolactam - 1]) {
14407
    sprintf (tmp_buf, "C3SNCZ00;");
14408
    strcat (out_buffer, tmp_buf);
14409
  }
14410
  if (fg[fg_imido_thioester - 1]) {
14411
    sprintf (tmp_buf, "C3NSC000;");
14412
    strcat (out_buffer, tmp_buf);
14413
  }
14414
  if (fg[fg_oxohetarene - 1]) {
14415
    sprintf (tmp_buf, "C3ONAZ00;");
14416
    strcat (out_buffer, tmp_buf);
14417
  }
14418
  if (fg[fg_thioxohetarene - 1]) {
14419
    sprintf (tmp_buf, "C3SNAZ00;");
14420
    strcat (out_buffer, tmp_buf);
14421
  }
14422
  if (fg[fg_iminohetarene - 1]) {
14423
    sprintf (tmp_buf, "C3NNAZ00;");
14424
    strcat (out_buffer, tmp_buf);
14425
  }
14426
  if (fg[fg_orthocarboxylic_acid_deriv - 1]) {
14427
    sprintf (tmp_buf, "C3O30000;");
14428
    strcat (out_buffer, tmp_buf);
14429
  }
14430
  if (fg[fg_carboxylic_acid_orthoester - 1]) {
14431
    sprintf (tmp_buf, "C3O3C000;");
14432
    strcat (out_buffer, tmp_buf);
14433
  }
14434
  if (fg[fg_carboxylic_acid_amide_acetal - 1]) {
14435
    sprintf (tmp_buf, "C3O3NC00;");
14436
    strcat (out_buffer, tmp_buf);
14437
  }
14438
  if (fg[fg_carboxylic_acid_anhydride - 1]) {
14439
    sprintf (tmp_buf, "C3O2C3O2;");
14440
    strcat (out_buffer, tmp_buf);
14441
  }
6785 bpr 14442
 
14179 bpr 14443
  if (fg[fg_carboxylic_acid_unsubst_imide - 1]) {
14444
    sprintf (tmp_buf, "C3ONCH10;");
14445
    strcat (out_buffer, tmp_buf);
14446
  }
14447
  if (fg[fg_carboxylic_acid_subst_imide - 1]) {
14448
    sprintf (tmp_buf, "C3ONCC10;");
14449
    strcat (out_buffer, tmp_buf);
14450
  }
14451
  if (fg[fg_co2_deriv - 1]) {
14452
    sprintf (tmp_buf, "C4000000;");
14453
    strcat (out_buffer, tmp_buf);
14454
  }
14455
  if (fg[fg_carbonic_acid_deriv - 1]) {
14456
    sprintf (tmp_buf, "C4O30000;");
14457
    strcat (out_buffer, tmp_buf);
14458
  }
14459
  if (fg[fg_carbonic_acid_monoester - 1]) {
14460
    sprintf (tmp_buf, "C4O3C100;");
14461
    strcat (out_buffer, tmp_buf);
14462
  }
14463
  if (fg[fg_carbonic_acid_diester - 1]) {
14464
    sprintf (tmp_buf, "C4O3C200;");
14465
    strcat (out_buffer, tmp_buf);
14466
  }
14467
  if (fg[fg_carbonic_acid_ester_halide - 1]) {
14468
    sprintf (tmp_buf, "C4O3CX00;");
14469
    strcat (out_buffer, tmp_buf);
14470
  }
14471
  if (fg[fg_thiocarbonic_acid_deriv - 1]) {
14472
    sprintf (tmp_buf, "C4SO0000;");
14473
    strcat (out_buffer, tmp_buf);
14474
  }
14475
  if (fg[fg_thiocarbonic_acid_monoester - 1]) {
14476
    sprintf (tmp_buf, "C4SOC100;");
14477
    strcat (out_buffer, tmp_buf);
14478
  }
14479
  if (fg[fg_thiocarbonic_acid_diester - 1]) {
14480
    sprintf (tmp_buf, "C4SOC200;");
14481
    strcat (out_buffer, tmp_buf);
14482
  }
14483
  if (fg[fg_thiocarbonic_acid_ester_halide - 1]) {
14484
    sprintf (tmp_buf, "C4SOX_00;");
14485
    strcat (out_buffer, tmp_buf);
14486
  }
14487
  if (fg[fg_carbamic_acid_deriv - 1]) {
14488
    sprintf (tmp_buf, "C4O2N000;");
14489
    strcat (out_buffer, tmp_buf);
14490
  }
14491
  if (fg[fg_carbamic_acid - 1]) {
14492
    sprintf (tmp_buf, "C4O2NH00;");
14493
    strcat (out_buffer, tmp_buf);
14494
  }
14495
  if (fg[fg_carbamic_acid_ester - 1]) {
14496
    sprintf (tmp_buf, "C4O2NC00;");
14497
    strcat (out_buffer, tmp_buf);
14498
  }
14499
  if (fg[fg_carbamic_acid_halide - 1]) {
14500
    sprintf (tmp_buf, "C4O2NX00;");
14501
    strcat (out_buffer, tmp_buf);
14502
  }
14503
  if (fg[fg_thiocarbamic_acid_deriv - 1]) {
14504
    sprintf (tmp_buf, "C4SN0000;");
14505
    strcat (out_buffer, tmp_buf);
14506
  }
14507
  if (fg[fg_thiocarbamic_acid - 1]) {
14508
    sprintf (tmp_buf, "C4SNOH00;");
14509
    strcat (out_buffer, tmp_buf);
14510
  }
14511
  if (fg[fg_thiocarbamic_acid_ester - 1]) {
14512
    sprintf (tmp_buf, "C4SNOC00;");
14513
    strcat (out_buffer, tmp_buf);
14514
  }
14515
  if (fg[fg_thiocarbamic_acid_halide - 1]) {
14516
    sprintf (tmp_buf, "C4SNXX00;");
14517
    strcat (out_buffer, tmp_buf);
14518
  }
14519
  if (fg[fg_urea - 1]) {
14520
    sprintf (tmp_buf, "C4O1N200;");
14521
    strcat (out_buffer, tmp_buf);
14522
  }
14523
  if (fg[fg_isourea - 1]) {
14524
    sprintf (tmp_buf, "C4N2O100;");
14525
    strcat (out_buffer, tmp_buf);
14526
  }
14527
  if (fg[fg_thiourea - 1]) {
14528
    sprintf (tmp_buf, "C4S1N200;");
14529
    strcat (out_buffer, tmp_buf);
14530
  }
14531
  if (fg[fg_isothiourea - 1]) {
14532
    sprintf (tmp_buf, "C4N2S100;");
14533
    strcat (out_buffer, tmp_buf);
14534
  }
14535
  if (fg[fg_guanidine - 1]) {
14536
    sprintf (tmp_buf, "C4N30000;");
14537
    strcat (out_buffer, tmp_buf);
14538
  }
14539
  if (fg[fg_semicarbazide - 1]) {
14540
    sprintf (tmp_buf, "C4ON2N00;");
14541
    strcat (out_buffer, tmp_buf);
14542
  }
14543
  if (fg[fg_thiosemicarbazide - 1]) {
14544
    sprintf (tmp_buf, "C4SN2N00;");
14545
    strcat (out_buffer, tmp_buf);
14546
  }
14547
  if (fg[fg_azide - 1]) {
14548
    sprintf (tmp_buf, "N4N20000;");
14549
    strcat (out_buffer, tmp_buf);
14550
  }
14551
  if (fg[fg_azo_compound - 1]) {
14552
    sprintf (tmp_buf, "N2N10000;");
14553
    strcat (out_buffer, tmp_buf);
14554
  }
14555
  if (fg[fg_diazonium_salt - 1]) {
14556
    sprintf (tmp_buf, "N3N100T2;");
14557
    strcat (out_buffer, tmp_buf);
14558
  }
14559
  if (fg[fg_isonitrile - 1]) {
14560
    sprintf (tmp_buf, "N3C10000;");
14561
    strcat (out_buffer, tmp_buf);
14562
  }
14563
  if (fg[fg_cyanate - 1]) {
14564
    sprintf (tmp_buf, "C4NO1000;");
14565
    strcat (out_buffer, tmp_buf);
14566
  }
14567
  if (fg[fg_isocyanate - 1]) {
14568
    sprintf (tmp_buf, "C4NO2000;");
14569
    strcat (out_buffer, tmp_buf);
14570
  }
14571
  if (fg[fg_thiocyanate - 1]) {
14572
    sprintf (tmp_buf, "C4NS1000;");
14573
    strcat (out_buffer, tmp_buf);
14574
  }
14575
  if (fg[fg_isothiocyanate - 1]) {
14576
    sprintf (tmp_buf, "C4NS2000;");
14577
    strcat (out_buffer, tmp_buf);
14578
  }
14579
  if (fg[fg_carbodiimide - 1]) {
14580
    sprintf (tmp_buf, "C4N20000;");
14581
    strcat (out_buffer, tmp_buf);
14582
  }
14583
  if (fg[fg_nitroso_compound - 1]) {
14584
    sprintf (tmp_buf, "N2O10000;");
14585
    strcat (out_buffer, tmp_buf);
14586
  }
14587
  if (fg[fg_nitro_compound - 1]) {
14588
    sprintf (tmp_buf, "N4O20000;");
14589
    strcat (out_buffer, tmp_buf);
14590
  }
14591
  if (fg[fg_nitrite - 1]) {
14592
    sprintf (tmp_buf, "N3O20000;");
14593
    strcat (out_buffer, tmp_buf);
14594
  }
14595
  if (fg[fg_nitrate - 1]) {
14596
    sprintf (tmp_buf, "N4O30000;");
14597
    strcat (out_buffer, tmp_buf);
14598
  }
14599
  if (fg[fg_sulfuric_acid_deriv - 1]) {
14600
    sprintf (tmp_buf, "S6O00000;");
14601
    strcat (out_buffer, tmp_buf);
14602
  }
14603
  if (fg[fg_sulfuric_acid - 1]) {
14604
    sprintf (tmp_buf, "S6O4H000;");
14605
    strcat (out_buffer, tmp_buf);
14606
  }
14607
  if (fg[fg_sulfuric_acid_monoester - 1]) {
14608
    sprintf (tmp_buf, "S6O4HC00;");
14609
    strcat (out_buffer, tmp_buf);
14610
  }
14611
  if (fg[fg_sulfuric_acid_diester - 1]) {
14612
    sprintf (tmp_buf, "S6O4CC00;");
14613
    strcat (out_buffer, tmp_buf);
14614
  }
14615
  if (fg[fg_sulfuric_acid_amide_ester - 1]) {
14616
    sprintf (tmp_buf, "S6O3NC00;");
14617
    strcat (out_buffer, tmp_buf);
14618
  }
14619
  if (fg[fg_sulfuric_acid_amide - 1]) {
14620
    sprintf (tmp_buf, "S6O3N100;");
14621
    strcat (out_buffer, tmp_buf);
14622
  }
14623
  if (fg[fg_sulfuric_acid_diamide - 1]) {
14624
    sprintf (tmp_buf, "S6O2N200;");
14625
    strcat (out_buffer, tmp_buf);
14626
  }
14627
  if (fg[fg_sulfuryl_halide - 1]) {
14628
    sprintf (tmp_buf, "S6O3XX00;");
14629
    strcat (out_buffer, tmp_buf);
14630
  }
14631
  if (fg[fg_sulfonic_acid_deriv - 1]) {
14632
    sprintf (tmp_buf, "S5O00000;");
14633
    strcat (out_buffer, tmp_buf);
14634
  }
14635
  if (fg[fg_sulfonic_acid - 1]) {
14636
    sprintf (tmp_buf, "S5O3H000;");
14637
    strcat (out_buffer, tmp_buf);
14638
  }
14639
  if (fg[fg_sulfonic_acid_ester - 1]) {
14640
    sprintf (tmp_buf, "S5O3C000;");
14641
    strcat (out_buffer, tmp_buf);
14642
  }
14643
  if (fg[fg_sulfonamide - 1]) {
14644
    sprintf (tmp_buf, "S5O2N000;");
14645
    strcat (out_buffer, tmp_buf);
14646
  }
14647
  if (fg[fg_sulfonyl_halide - 1]) {
14648
    sprintf (tmp_buf, "S5O2XX00;");
14649
    strcat (out_buffer, tmp_buf);
14650
  }
14651
  if (fg[fg_sulfone - 1]) {
14652
    sprintf (tmp_buf, "S4O20000;");
14653
    strcat (out_buffer, tmp_buf);
14654
  }
14655
  if (fg[fg_sulfoxide - 1]) {
14656
    sprintf (tmp_buf, "S2O10000;");
14657
    strcat (out_buffer, tmp_buf);
14658
  }
14659
  if (fg[fg_sulfinic_acid_deriv - 1]) {
14660
    sprintf (tmp_buf, "S3O00000;");
14661
    strcat (out_buffer, tmp_buf);
14662
  }
14663
  if (fg[fg_sulfinic_acid - 1]) {
14664
    sprintf (tmp_buf, "S3O2H000;");
14665
    strcat (out_buffer, tmp_buf);
14666
  }
14667
  if (fg[fg_sulfinic_acid_ester - 1]) {
14668
    sprintf (tmp_buf, "S3O2C000;");
14669
    strcat (out_buffer, tmp_buf);
14670
  }
14671
  if (fg[fg_sulfinic_acid_halide - 1]) {
14672
    sprintf (tmp_buf, "S3O1XX00;");
14673
    strcat (out_buffer, tmp_buf);
14674
  }
14675
  if (fg[fg_sulfinic_acid_amide - 1]) {
6785 bpr 14676
      sprintf (tmp_buf, "S3O1N000;");
14677
      strcat (out_buffer, tmp_buf);
14678
    }
14179 bpr 14679
  if (fg[fg_sulfenic_acid_deriv - 1]) {
14680
    sprintf (tmp_buf, "S1O00000;");
14681
    strcat (out_buffer, tmp_buf);
14682
  }
14683
  if (fg[fg_sulfenic_acid - 1]) {
14684
    sprintf (tmp_buf, "S1O1H000;");
14685
    strcat (out_buffer, tmp_buf);
14686
  }
14687
  if (fg[fg_sulfenic_acid_ester - 1]) {
14688
    sprintf (tmp_buf, "S1O1C000;");
14689
    strcat (out_buffer, tmp_buf);
14690
  }
14691
  if (fg[fg_sulfenic_acid_halide - 1]) {
14692
    sprintf (tmp_buf, "S1O0XX00;");
14693
    strcat (out_buffer, tmp_buf);
14694
  }
14695
  if (fg[fg_sulfenic_acid_amide - 1]) {
14696
    sprintf (tmp_buf, "S1O0N100;");
14697
    strcat (out_buffer, tmp_buf);
14698
  }
6785 bpr 14699
 
14179 bpr 14700
  if (fg[fg_alkylthiol - 1]) {
14701
    sprintf (tmp_buf, "S1H1C000;");
14702
    strcat (out_buffer, tmp_buf);
14703
  }
14704
  if (fg[fg_arylthiol - 1]) {
14705
    sprintf (tmp_buf, "S1H1A000;");
14706
    strcat (out_buffer, tmp_buf);
14707
  }
14708
  if (fg[fg_phosphoric_acid_deriv - 1]) {
14709
    sprintf (tmp_buf, "P5O0H000;");
14710
    strcat (out_buffer, tmp_buf);
14711
  }
14712
  if (fg[fg_phosphoric_acid - 1]) {
14713
    sprintf (tmp_buf, "P5O4H200;");
14714
    strcat (out_buffer, tmp_buf);
14715
  }
14716
  if (fg[fg_phosphoric_acid_ester - 1]) {
14717
    sprintf (tmp_buf, "P5O4HC00;");
14718
    strcat (out_buffer, tmp_buf);
14719
  }
14720
  if (fg[fg_phosphoric_acid_halide - 1]) {
14721
    sprintf (tmp_buf, "P5O3HX00;");
14722
    strcat (out_buffer, tmp_buf);
14723
  }
14724
  if (fg[fg_phosphoric_acid_amide - 1]) {
14725
    sprintf (tmp_buf, "P5O3HN00;");
14726
    strcat (out_buffer, tmp_buf);
14727
  }
14728
  if (fg[fg_thiophosphoric_acid_deriv - 1]) {
14729
    sprintf (tmp_buf, "P5O0S000;");
14730
    strcat (out_buffer, tmp_buf);
14731
  }
14732
  if (fg[fg_thiophosphoric_acid - 1]) {
14733
    sprintf (tmp_buf, "P5O3SH00;");
14734
    strcat (out_buffer, tmp_buf);
14735
  }
14736
  if (fg[fg_thiophosphoric_acid_ester - 1]) {
14737
    sprintf (tmp_buf, "P5O3SC00;");
14738
    strcat (out_buffer, tmp_buf);
14739
  }
14740
  if (fg[fg_thiophosphoric_acid_halide - 1]) {
14741
    sprintf (tmp_buf, "P5O2SX00;");
14742
    strcat (out_buffer, tmp_buf);
14743
  }
14744
  if (fg[fg_thiophosphoric_acid_amide - 1]) {
14745
    sprintf (tmp_buf, "P5O2SN00;");
14746
    strcat (out_buffer, tmp_buf);
14747
  }
14748
  if (fg[fg_phosphonic_acid_deriv - 1]) {
14749
    sprintf (tmp_buf, "P4O30000;");
14750
    strcat (out_buffer, tmp_buf);
14751
  }
14752
  if (fg[fg_phosphonic_acid - 1]) {
14753
    sprintf (tmp_buf, "P4O3H000;");
14754
    strcat (out_buffer, tmp_buf);
14755
  }
14756
  if (fg[fg_phosphonic_acid_ester - 1]) {
14757
    sprintf (tmp_buf, "P4O3C000;");
14758
    strcat (out_buffer, tmp_buf);
14759
  }
14760
  if (fg[fg_phosphine - 1]) {
14761
    sprintf (tmp_buf, "P3000000;");
14762
    strcat (out_buffer, tmp_buf);
14763
  }
14764
  if (fg[fg_phosphinoxide - 1]) {
14765
    sprintf (tmp_buf, "P2O00000;");
14766
    strcat (out_buffer, tmp_buf);
14767
  }
14768
  if (fg[fg_boronic_acid_deriv - 1]) {
14769
    sprintf (tmp_buf, "B2O20000;");
14770
    strcat (out_buffer, tmp_buf);
14771
  }
14772
  if (fg[fg_boronic_acid - 1]) {
14773
    sprintf (tmp_buf, "B2O2H000;");
14774
    strcat (out_buffer, tmp_buf);
14775
  }
14776
  if (fg[fg_boronic_acid_ester - 1]) {
14777
    sprintf (tmp_buf, "B2O2C000;");
14778
    strcat (out_buffer, tmp_buf);
14779
  }
14780
  if (fg[fg_alkene - 1]) {
14781
    sprintf (tmp_buf, "000C2C00;");
14782
    strcat (out_buffer, tmp_buf);
14783
  }
14784
  if (fg[fg_alkyne - 1]) {
14785
    sprintf (tmp_buf, "000C3C00;");
14786
    strcat (out_buffer, tmp_buf);
14787
  }
14788
  if (fg[fg_aromatic - 1]) {
14789
    sprintf (tmp_buf, "0000A000;");
14790
    strcat (out_buffer, tmp_buf);
14791
  }
14792
  if (fg[fg_heterocycle - 1]) {
14793
    sprintf (tmp_buf, "0000CZ00;");
14794
    strcat (out_buffer, tmp_buf);
14795
  }
14796
  if (fg[fg_alpha_aminoacid - 1]) {
14797
    sprintf (tmp_buf, "C3O2HN1C;");
14798
    strcat (out_buffer, tmp_buf);
14799
  }
14800
  if (fg[fg_alpha_hydroxyacid - 1]) {
14801
    sprintf (tmp_buf, "C3O2HO1H;");
14802
    strcat (out_buffer, tmp_buf);
14803
  }
6785 bpr 14804
}
14805
 
14806
/*static void mm_elab_molstat(void)
14807
{
14808
                count_neighbors();
14809
//      init_molstat(&molstat);
14810
        if (!found_arominfo) {
14811
    chk_ringbonds();
14812
    if (ringsearch_mode == rs_ssr)
14813
      remove_redundant_rings();
14814
    if (n_rings == max_rings) {
14815
      if (opt_verbose)
14816
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
14817
      ringsearch_mode = rs_ssr;
14818
      clear_rings();
14819
      max_vringsize = 10;
14820
      chk_ringbonds();
14821
      remove_redundant_rings();
14822
    }
14179 bpr 14823
 
6785 bpr 14824
    update_ringcount();
14825
    update_atypes();
14826
    update_Htotal();
14827
    chk_arom();
14828
 
14829
    if (ringsearch_mode == rs_ssr) {
14830
      do {
14831
        prev_n_ar = count_aromatic_rings();
14832
        chk_arom();
14833
        n_ar = count_aromatic_rings();
14834
      } while (prev_n_ar - n_ar != 0);
14835
    }
14836
        } else {
14837
 update_atypes();
14179 bpr 14838
    update_Htotal();
14839
 
6785 bpr 14840
        }
14179 bpr 14841
 
6785 bpr 14842
 // get_molstat();
14843
}*/
14844
 
14845
DLLEXPORT void
14846
cm_molstat_X (char *buf)
14847
{
14848
  init_molstat (&molstat);
14849
//mm_elab_molstat();
14850
  get_molstat ();
14851
  write_molstat_X_dll (buf);
14852
}
14853
 
14854
DLLEXPORT void
14855
cm_molstat (char *buf)
14856
{
14857
  init_molstat (&molstat);
14858
//mm_elab_molstat();
14859
  get_molstat ();
14860
  write_molstat_dll (buf, 0);
14861
}
14862
 
14863
DLLEXPORT void
14864
cm_molstat_sql_exact (char *buf)
14865
{
14866
  init_molstat (&molstat);
14867
//mm_elab_molstat();
14868
  get_molstat ();
14869
  write_molstat_dll (buf, 1);
14870
}
14871
 
14872
DLLEXPORT void
14873
cm_molstat_sql_substruct (char *buf)
14874
{
14875
  init_molstat (&molstat);
14876
//mm_elab_molstat();
14877
  get_molstat ();
14878
  write_molstat_dll (buf, 2);
14879
}
14880
 
14881
DLLEXPORT void
14882
cm_fg_codes (char *buf)
14883
{
14884
//mm_elab_molstat();
14885
  chk_functionalgroups ();
14886
  write_fg_code_dll (buf);
14887
}
14888
 
14179 bpr 14889
static void write_MDLmolfile_dll (char *out_buffer)
6785 bpr 14890
{
14891
  int i;
14892
  char tmpstr[256];
14893
  char wline[256];
14894
  int a_chg;
14895
  int a_iso;
14896
  int a_rad;
14897
  char tmflabel[256];           /* v0.3m */
14898
  char STR1[256], STR7[256];
14899
  int FORLIM;
14900
  *out_buffer = '\0';
14901
  *tmpstr = '\0';
14902
  *wline = '\0';
14903
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
14904
  while (strlen (tmflabel) < 2) /* v0.3m */
14905
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
14906
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
14907
  if (strlen (molname) > 80)
14908
    sprintf (molname, "%.80s", strcpy (STR1, molname));
14909
  strncat (out_buffer, molname, 80);
14910
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
14911
  if (ringsearch_mode == rs_sar)        /* v0.3m */
14912
    strcat (wline, ":r0");
14913
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
14914
    strcat (wline, ":r1");
14915
  if (opt_metalrings)
14916
    strcat (wline, ":m1");
14917
  else
14918
    strcat (wline, ":m0");
14919
  /* v0.3m */
14920
  sprintf (tmpstr, "\n%s\n", molcomment);
14921
  strcat (wline, tmpstr);
14922
  sprintf (tmpstr, "%d", n_atoms);
14923
  lblank (3L, tmpstr);
14924
  strcat (wline, tmpstr);
14925
  /* first 3 digits: number of atoms */
14926
  sprintf (tmpstr, "%d", n_bonds);
14927
  lblank (3L, tmpstr);
14928
  strcat (wline, tmpstr);
14929
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
14930
  strcpy (tmpstr, "  0");
14931
  strcat (wline, tmpstr);
14932
  /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 14933
  /* p2c: checkmol.pas, line 2388:
14934
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 14935
#ifdef REDUCED_SAR
14936
  sprintf (tmpstr, "%d", n_countablerings);
14937
  /* v0.3n; changed n_rings into n_countablerings */
14938
#else
14939
  sprintf (tmpstr, "%d", n_rings);
14940
#endif
14941
  lblank (3L, tmpstr);
14942
  strcat (wline, tmpstr);
14943
  /* officially "obsolete", we use it for the number of rings */
14944
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
14945
  if (chir_flag)
14946
    strcat (wline, "1");
14947
  else
14948
    strcat (wline, "0");
14949
  /* v0.3n */
14950
  strcat (wline, "               999 V2000\n");
14951
  /* v0.3n (adjust string length) */
14952
  strcat (out_buffer, wline);
14953
  FORLIM = n_atoms;
14179 bpr 14954
  for (i = 0; i < FORLIM; i++) {
14955
    *wline = '\0';
14956
    *tmpstr = '\0';
14957
    sprintf (tmpstr, "%1.4f", atom[i].x);
14958
    lblank (10L, tmpstr);
14959
    strcat (wline, tmpstr);
14960
    sprintf (tmpstr, "%1.4f", atom[i].y);
14961
    lblank (10L, tmpstr);
14962
    strcat (wline, tmpstr);
14963
    sprintf (tmpstr, "%1.4f", atom[i].z);
14964
    lblank (10L, tmpstr);
14965
    strcat (wline, tmpstr);
14966
    strcpy (tmpstr, atom[i].element);
14967
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
14968
    //tmpstr[0] = toupper (tmpstr[0]);
14969
    all_lowercase (tmpstr);
14970
    tmpstr[0] = toupper (tmpstr[0]);
14971
    /*wline := wline + ' '+atom^[i].element+' '; */
14972
    sprintf (wline + strlen (wline), " %s ", tmpstr);
14973
    strcat (wline, " 0");       /* mass difference (isotopes) */
14974
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
14975
    if (atom[i].arom)
14976
            strcpy (tmpstr, " 00");
14977
    else
14978
            strcpy (tmpstr, "  0");
14979
    strcat (wline, tmpstr);
14980
    strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
14981
    strcat (out_buffer, wline);
14982
  }
6785 bpr 14983
  FORLIM = n_bonds;
14179 bpr 14984
  for (i = 0; i < FORLIM; i++) {
14985
    *wline = '\0';
14986
    *tmpstr = '\0';
14987
    sprintf (tmpstr, "%d", bond[i].a1);
14988
    lblank (3L, tmpstr);
14989
    strcat (wline, tmpstr);
14990
    sprintf (tmpstr, "%d", bond[i].a2);
14991
    lblank (3L, tmpstr);
14992
    strcat (wline, tmpstr);
14993
    if (bond[i].btype == 'S')
14994
            strcpy (tmpstr, "  1");
14995
    if (bond[i].btype == 'D')
14996
            strcpy (tmpstr, "  2");
14997
    if (bond[i].btype == 'T')
14998
            strcpy (tmpstr, "  3");
14999
    if (bond[i].btype == 'A')
15000
            strcpy (tmpstr, "  4");
15001
    if (bond[i].btype == 'l')
15002
            strcpy (tmpstr, "  5");
15003
    if (bond[i].btype == 's')
15004
            strcpy (tmpstr, "  6");
15005
    if (bond[i].btype == 'd')
15006
            strcpy (tmpstr, "  7");
15007
    if (bond[i].btype == 'a')
15008
            strcpy (tmpstr, "  8");
15009
        /* now encode our own aromaticity information */
15010
    if (bond[i].arom)
15011
            tmpstr[1] = '0';
15012
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
15013
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
15014
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
15015
    /*    wline := wline + '  0'; */
15016
    /* restore original value from MDL molfile (v0.3n) */
15017
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
15018
    *tmpstr = '\0';
15019
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
15020
    strcat (wline, "  ");
15021
    strcat (wline, tmpstr);
15022
    *tmpstr = '\0';
15023
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
15024
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
15025
    sprintf (tmpstr, "%i", bond[i].ring_count);
15026
    while (strlen (tmpstr) < 3)
15027
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
15028
    sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
15029
    strcat (out_buffer, wline);
15030
  }
6785 bpr 15031
  FORLIM = n_atoms;
14179 bpr 15032
  for (i = 1; i <= FORLIM; i++) {
15033
    a_chg = atom[i - 1].formal_charge;
15034
    if (a_chg != 0) {
15035
            strcpy (wline, "M  CHG  1 ");
15036
            sprintf (tmpstr, "%d", i);
15037
            lblank (3L, tmpstr);
15038
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15039
            sprintf (tmpstr, "%d", a_chg);
15040
            lblank (3L, tmpstr);
15041
            strcat (wline, tmpstr);
15042
            strcat (out_buffer, wline);
15043
            strcat (out_buffer, "\n");
15044
          }
15045
  }
15046
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
15047
    a_iso = atom[i - 1].nucleon_number;
15048
    if (a_iso != 0) {
15049
            strcpy (wline, "M  ISO  1 ");
15050
            sprintf (tmpstr, "%d", i);
15051
            lblank (3L, tmpstr);
15052
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15053
            sprintf (tmpstr, "%d", a_iso);
15054
            lblank (3L, tmpstr);
15055
            strcat (wline, tmpstr);
15056
            strcat (out_buffer, wline);
15057
            strcat (out_buffer, "\n");
15058
          }
15059
  }
15060
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
15061
    a_rad = atom[i - 1].radical_type;
15062
    if (a_rad != 0) {
15063
            strcpy (wline, "M  RAD  1 ");
15064
            sprintf (tmpstr, "%d", i);
15065
            lblank (3L, tmpstr);
15066
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15067
            sprintf (tmpstr, "%d", a_rad);
15068
            lblank (3L, tmpstr);
15069
            strcat (wline, tmpstr);
15070
            strcat (out_buffer, wline);
15071
            strcat (out_buffer, "\n");
15072
          }
15073
  }
6785 bpr 15074
  strcat (out_buffer, "M  END\n");
15075
}
15076
 
15077
DLLEXPORT void
15078
cm_tweak_molfile (char *buf)
15079
{
15080
//chk_functionalgroups();
15081
  write_MDLmolfile_dll (buf);
15082
}
15083
#endif