Subversion Repositories wimsdev

Rev

Rev 14179 | Rev 14626 | 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
}
1042
 
14179 bpr 1043
static int left_int (trimstr)
1044
  char *trimstr;
6785 bpr 1045
{
1046
  char numstr[256];
1047
  char auxstr[256];
1048
  int auxint = 0;
1049
  char STR1[256];
1050
 
1051
  strcpy (numstr, "-+0123456789");
1052
  *auxstr = '\0';
1053
  while (*trimstr != '\0' && (trimstr[0] == ' ' || trimstr[0] == TAB))
1054
    strdelete (trimstr, 1, 1);
1055
  while ((*trimstr != '\0') &&
14179 bpr 1056
    (strpos2 (numstr, (sprintf (STR1, "%c", trimstr[0]), STR1), 1) > 0)){
1057
    sprintf (auxstr + strlen (auxstr), "%c", trimstr[0]);
1058
    strdelete (trimstr, 1, 1);
1059
  }
6785 bpr 1060
  return auxint;
1061
}
1062
 
14179 bpr 1063
static int path_pos (int id, int *a_path)
6785 bpr 1064
{
1065
  int i = 0;
1066
 
14179 bpr 1067
  for (i = 0; i < max_ringsize; i++){
1068
    if (*(a_path++) == id) {
1069
      return ++i;
6785 bpr 1070
    }
14179 bpr 1071
  }
6785 bpr 1072
  return 0;
1073
}
1074
 
14179 bpr 1075
static int path_length (int *a_path)
6785 bpr 1076
{
1077
  if ((a_path[max_ringsize - 1] != 0) && (path_pos (0, a_path) == 0))
1078
    return max_ringsize;
1079
  else
1080
    return (path_pos (0, a_path) - 1);
1081
}
1082
 
14179 bpr 1083
static int get_bond (int ba1, int ba2)
6785 bpr 1084
{
1085
  int i;
1086
  int b_id = 0;
1087
  int FORLIM;
1088
 
1089
  if (n_bonds <= 0)
1090
    return b_id;
1091
  FORLIM = n_bonds;
14179 bpr 1092
  for (i = 1; i <= FORLIM; i++) {
1093
    if ((bond[i - 1].a1 == ba1 && bond[i - 1].a2 == ba2) ||
1094
      (bond[i - 1].a1 == ba2 && bond[i - 1].a2 == ba1))
1095
      b_id = i;
1096
  }
6785 bpr 1097
  return b_id;
1098
}
1099
 
14179 bpr 1100
static void clear_atom_tags ()
6785 bpr 1101
{
1102
  int i, FORLIM;
1103
 
14179 bpr 1104
  if (n_atoms > 0) {
1105
    FORLIM = n_atoms;
1106
    for (i = 0; i < FORLIM; i++)
1107
      atom[i].tag = false;
1108
  }
6785 bpr 1109
}
1110
 
1111
#if 0
14179 bpr 1112
static void set_atom_tags ()
6785 bpr 1113
{
1114
  int i, FORLIM;
1115
 
14179 bpr 1116
  if (n_atoms > 0){
1117
    FORLIM = n_atoms;
1118
    for (i = 0; i < FORLIM; i++)
1119
      atom[i].tag = true;
1120
  }
6785 bpr 1121
}
1122
#endif
14179 bpr 1123
static void order_ringpath (int *r_path)
6785 bpr 1124
{
1125
  /* order should be: array starts with atom of lowest number, followed by neighbor atom with lower number */
1126
  int i, pl, a_ref, a_left, a_right, a_tmp;
1127
 
1128
  pl = path_length (r_path);
1129
  if (pl < 3)
1130
    return;
1131
  a_ref = n_atoms;
1132
  /* start with highest possible value for an atom number */
14179 bpr 1133
  for (i = 0; i < pl; i++){
1134
    if (r_path[i] < a_ref)  /* find the minimum value ==> reference atom */
1135
     a_ref = r_path[i];
1136
  }
1137
  if (a_ref < 1)   /* just to be sure */
6785 bpr 1138
    return;
1139
  if (path_pos (a_ref, r_path) < pl)
1140
    a_right = r_path[path_pos (a_ref, r_path)];
1141
  else
1142
    a_right = r_path[0];
1143
  if (path_pos (a_ref, r_path) > 1)
1144
    a_left = r_path[path_pos (a_ref, r_path) - 2];
1145
  else
1146
    a_left = r_path[pl - 1];
14179 bpr 1147
  if (a_right == a_left)  /* should never happen */
6785 bpr 1148
    return;
14179 bpr 1149
  if (a_right < a_left) {
6785 bpr 1150
      /* correct ring numbering direction, only shift of the reference atom to the left end required */
14179 bpr 1151
    while (path_pos (a_ref, r_path) > 1){
1152
      a_tmp = r_path[0];
1153
      for (i = 1; i < pl; i++)
1154
        r_path[i - 1] = r_path[i];
1155
      r_path[pl - 1] = a_tmp;
6785 bpr 1156
    }
14179 bpr 1157
    return;
1158
  }
1159
  while (path_pos (a_ref, r_path) < pl) {
6785 bpr 1160
      /* step one: create "mirrored" ring path with reference atom at right end */
14179 bpr 1161
    a_tmp = r_path[pl - 1];
1162
    for (i = pl; i >= 2; i--)
1163
      r_path[i - 1] = r_path[i - 2];
1164
    r_path[0] = a_tmp;
1165
  }
1166
  for (i = 1; i <= pl / 2; i++){        /* one more mirroring */
1167
    a_tmp = r_path[i - 1];
1168
    r_path[i - 1] = r_path[pl - i];
1169
    r_path[pl - i] = a_tmp;
1170
    /* wrong ring numbering direction, two steps required */
1171
  }
6785 bpr 1172
}
1173
 
14179 bpr 1174
static void clear_ndl_atom_tags ()
6785 bpr 1175
{
1176
  int i;
1177
 
14179 bpr 1178
  if (ndl_n_atoms > 0){
1179
    for (i = 0; i < ndl_n_atoms; i++)
1180
      ndl_atom[i].tag = false;
1181
  }
6785 bpr 1182
}
1183
 
14179 bpr 1184
static void set_ndl_atom_tags ()
6785 bpr 1185
{
1186
  int i;
1187
 
14179 bpr 1188
  if (ndl_n_atoms > 0){
1189
    for (i = 0; i < ndl_n_atoms; i++)
1190
     ndl_atom[i].tag = true;
1191
  }
6785 bpr 1192
}
1193
 
14179 bpr 1194
static int count_tagged_ndl_heavyatoms ()
6785 bpr 1195
{
1196
  int i;
1197
  int n = 0;
1198
 
1199
  if (ndl_n_atoms < 1)
1200
    return n;
1201
 
14179 bpr 1202
  for (i = 0; i < ndl_n_atoms; i++){
1203
    if (ndl_atom[i].heavy && ndl_atom[i].tag)
1204
    n++;
1205
  }
6785 bpr 1206
  return n;
1207
}
1208
 
1209
/*============================= geometry functions ========================== */
1210
 
14179 bpr 1211
static double dist3d (p1, p2)
6785 bpr 1212
     p_3d p1, p2;
1213
{
1214
  double res, TEMP, TEMP1, TEMP2;
1215
 
1216
  TEMP = p1.x - p2.x;
1217
  TEMP1 = p1.y - p2.y;
1218
  TEMP2 = p1.z - p2.z;
1219
  res = sqrt (TEMP * TEMP + TEMP1 * TEMP1 + TEMP2 * TEMP2);
1220
  return res;
1221
}
1222
 
1223
/*
1224
function is_cis(p1,p2,p3,p4:p_3d):boolean;  (* new in v0.3d
1225
var                         (* just a simple, distance-based estimation
1226
  total_dist  : double;     (* instead of calculating the dihedral angle
1227
  direct_dist : double;
1228
  res         : boolean;
1229
begin
1230
  res := false;
1231
  total_dist  := dist3d(p1,p2) + dist3d(p2,p3) + dist3d(p3,p4);
1232
  direct_dist := dist3d(p1,p4);
1233
  if (direct_dist < 0.78 * total_dist) then res := true;  (* cutoff value of 0.78 was
1234
  is_cis := res;                                          (* experimentally determined
1235
end;
1236
*/
1237
/* function is_cis was replaced by a new one in v0.3h */
1238
 
14179 bpr 1239
static p_3d subtract_3d (p1, p2)
6785 bpr 1240
     p_3d p1, p2;
1241
{
1242
  p_3d p;
1243
 
1244
  p.x = p1.x - p2.x;
1245
  p.y = p1.y - p2.y;
1246
  p.z = p1.z - p2.z;
1247
  return p;
1248
}
1249
 
14179 bpr 1250
static p_3d add_3d (p1, p2)
6785 bpr 1251
     p_3d p1, p2;
1252
{
1253
  p_3d p;
1254
 
1255
  p.x = p1.x + p2.x;
1256
  p.y = p1.y + p2.y;
1257
  p.z = p1.z + p2.z;
1258
  return p;
1259
}
1260
 
1261
#if 0
14179 bpr 1262
static void vec2origin (p1, p2)
6785 bpr 1263
     p_3d *p1, *p2;
1264
{
1265
  p_3d p;
1266
 
1267
  p = subtract_3d (*p2, *p1);
1268
  *p2 = p;
1269
  p1->x = 0.0;
1270
  p1->y = 0.0;
1271
  p1->z = 0.0;
1272
}
1273
#endif
1274
 
14179 bpr 1275
static double scalar_prod (p1, p2, p3)
6785 bpr 1276
     p_3d p1, p2, p3;
1277
{
1278
  p_3d p;
1279
  double res;
1280
 
1281
  p = subtract_3d (p2, p1);
1282
  p2 = p;
1283
  p = subtract_3d (p3, p1);
1284
  p3 = p;
1285
  p1.x = 0.0;
1286
  p1.y = 0.0;
1287
  p1.z = 0.0;
1288
  res = p2.x * p3.x + p2.y * p3.y + p2.z * p3.z;
1289
  return res;
1290
}
1291
 
14179 bpr 1292
static p_3d cross_prod (p1, p2, p3)
6785 bpr 1293
     p_3d p1, p2, p3;
1294
{
1295
  p_3d p, orig_p1;
1296
 
1297
  orig_p1 = p1;
1298
  p = subtract_3d (p2, p1);
1299
  p2 = p;
1300
  p = subtract_3d (p3, p1);
1301
  p3 = p;
1302
  p.x = p2.y * p3.z - p2.z * p3.y;
1303
  p.y = p2.z * p3.x - p2.x * p3.z;
1304
  p.z = p2.x * p3.y - p2.y * p3.x;
1305
  return (add_3d (orig_p1, p));
1306
}
1307
 
14179 bpr 1308
static double angle_3d (p1, p2, p3)
6785 bpr 1309
     p_3d p1, p2, p3;
1310
{
1311
  p_3d lp1, lp2, lp3, p;
1312
  double res = 0.0;
1313
  double magn_1, magn_2, cos_phi;
1314
 
1315
  lp1 = p1;
1316
  lp2 = p2;
1317
  lp3 = p3;
1318
  p = subtract_3d (lp2, lp1);
1319
  lp2 = p;
1320
  p = subtract_3d (lp3, lp1);
1321
  lp3 = p;
1322
  lp1.x = 0.0;
1323
  lp1.y = 0.0;
1324
  lp1.z = 0.0;
1325
  magn_1 = dist3d (lp1, lp2);
1326
  magn_2 = dist3d (lp1, lp3);
14179 bpr 1327
  if (magn_1 * magn_2 == 0)  /* emergency exit */
6785 bpr 1328
    return M_PI;
1329
  cos_phi = scalar_prod (lp1, lp2, lp3) / (magn_1 * magn_2);
1330
  if (cos_phi < -1)
1331
    cos_phi = -1.0;
1332
  if (cos_phi > 1)
1333
    cos_phi = 1.0;
1334
  res = acos (cos_phi);
1335
  return res;
1336
}
1337
 
14179 bpr 1338
static double torsion (p1, p2, p3, p4)
6785 bpr 1339
     p_3d p1, p2, p3, p4;
1340
{
1341
  p_3d lp1, lp2, lp3, lp4, d1, c1, c2;
1342
  double res;
1343
  p_3d c1xc2, c2xc1;
1344
  double dist1, dist2, sign;
1345
 
1346
  /* copy everything into local variables */
1347
  lp1 = p1;
1348
  lp2 = p2;
1349
  lp3 = p3;
1350
  lp4 = p4;
1351
  /* get the vector between the two central atoms */
1352
  d1 = subtract_3d (p3, p2);
1353
  /* shift the first atom parallel to be attached to p3 instead of p2 */
1354
  lp1 = add_3d (p1, d1);
1355
  /* now get the cross product vectors */
1356
  c1 = cross_prod (lp3, lp2, lp1);
1357
  c2 = cross_prod (lp3, lp2, lp4);
1358
  res = angle_3d (p3, c1, c2);
1359
  /*now check if it is clockwise or anticlockwise: */
1360
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1361
  c1xc2 = cross_prod (lp3, c1, c2);
1362
  c2xc1 = cross_prod (lp3, c2, c1);
1363
  /*next, get the distances from these points to our refernce point lp2 */
1364
  dist1 = dist3d (lp2, c1xc2);
1365
  dist2 = dist3d (lp2, c2xc1);
1366
  if (dist1 <= dist2)
1367
    sign = 1.0;
1368
  else
1369
    sign = -1.0;
1370
  return (sign * res);
1371
}
1372
 
14179 bpr 1373
static double ctorsion (p1, p2, p3, p4)
6785 bpr 1374
     p_3d p1, p2, p3, p4;
1375
{
1376
  /* calculates "pseudo-torsion" defined by atoms 3 and 4, being both */
1377
  /* attached to atom 2, with respect to axis of atoms 1 and 2 */
1378
  p_3d lp1, lp2, lp3, lp4;
1379
  /*d1 : p_3d; */
1380
  p_3d c1, c2;
1381
  double res;
1382
  p_3d c1xc2, c2xc1;
1383
  double dist1, dist2, sign;
1384
 
1385
  /* copy everything into local variables */
1386
  lp1 = p1;
1387
  lp2 = p2;
1388
  lp3 = p3;
1389
  lp4 = p4;
1390
  /* get the cross product vectors */
1391
  c1 = cross_prod (lp2, lp1, lp3);
1392
  c2 = cross_prod (lp2, lp1, lp4);
1393
  res = angle_3d (p2, c1, c2);
1394
  /*now check if it is clockwise or anticlockwise: */
1395
  /*first, make the cross products of the two cross products c1 and c2 (both ways) */
1396
  c1xc2 = cross_prod (lp2, c1, c2);
1397
  c2xc1 = cross_prod (lp2, c2, c1);
1398
  /*next, get the distances from these points to our refernce point lp1 */
1399
  dist1 = dist3d (lp1, c1xc2);
1400
  dist2 = dist3d (lp1, c2xc1);
1401
  if (dist1 <= dist2)
1402
    sign = 1.0;
1403
  else
1404
    sign = -1.0;
1405
  return (sign * res);
1406
}
1407
 
14179 bpr 1408
static boolean is_cis (p1, p2, p3, p4)
6785 bpr 1409
     p_3d p1, p2, p3, p4;
1410
{
1411
  /* new in v0.3h, uses the dihedral angle */
1412
  double phi;
1413
  boolean res = false;
1414
 
1415
  phi = torsion (p1, p2, p3, p4);
1416
  if (fabs (phi) < M_PI / 2)
1417
    res = true;
1418
  return res;
1419
}
1420
 
1421
/*====================== end of geometry functions ========================== */
1422
 
14179 bpr 1423
static void show_usage () {
1424
  if (progmode == pmMatchMol) {
1425
    printf ("matchmol version %s  N. Haider, University of Vienna, 2003-2007\n", version);
1426
    printf ("Usage: matchmol [options] <needle> <haystack>\n");
1427
    printf (" where <needle> and <haystack> are the two molecules to compare\n");
1428
    printf (" (supported formats: MDL *.mol or *.sdf, Alchemy *.mol, Sybyl *.mol2)\n");
1429
    printf (" options can be:\n");
1430
    printf ("    -v  verbose output\n");
1431
    printf ("    -x  exact match\n");
1432
    printf ("    -s  strict comparison of atom and bond types (including ring check)\n");
6785 bpr 1433
      /* new in v0.2f, v0.3d */
14179 bpr 1434
    printf ("    -r  force SSR (set of small rings) ring search mode\n");
1435
    printf ("    -m  write matching molecule as MDL molfile to standard output\n");
1436
    printf ("        (default output: record number + \":T\" for hit  or \":F\" for miss\n");
1437
    printf ("    -M  accept metal atoms as ring members\n");
1438
    printf ("    -g  check geometry of double bonds (E/Z)\n");
1439
    printf ("    -G  check geometry of chiral centers (R/S)\n");
1440
    printf ("    -a  check charges strict\n");   /* 0.3x */
1441
    printf ("    -i  check isotopes strict\n");  /* 0.3x */
1442
    printf ("    -d  check radicals strict\n");  /* 0.3x */
1443
    printf ("    -f  fingerprint mode (1 haystack, multiple needles) with boolean output\n");
1444
    printf ("    -F  fingerprint mode (1 haystack, multiple needles) with decimal output\n");
1445
    return;
1446
  }
1447
  printf ("checkmol version %s  N. Haider, University of Vienna, 2003-2007\n", version);
6785 bpr 1448
  printf ("Usage: checkmol [options] <filename>\n");
1449
  printf (" where options can be:\n");
14179 bpr 1450
  printf ("    -l  print a list of fingerprint codes + explanation and exit\n");
6785 bpr 1451
  printf ("    -v  verbose output\n");
1452
  printf ("    -r  force SSR (set of small rings) ring search mode\n");
1453
  printf ("    -M  accept metal atoms as ring members\n");
1454
  printf ("  and one of the following:\n");
14179 bpr 1455
  printf ("    -e  english text (common name of functional group; default)\n");
6785 bpr 1456
  printf ("    -d  german text (common name of functional group)\n");
1457
  printf ("    -c  code (acronym-like code for functional group)\n");
14179 bpr 1458
  printf ("    -b  binary (a bitstring representing absence or presence of each group)\n");
1459
  printf ("    -s  the ASCII representation of the above bitstring, i.e. 0s and 1s)\n");
1460
  printf ("    -x  print molecular statistics (number of various atom types, bond types,\n");
6785 bpr 1461
  printf ("        ring sizes, etc.\n");
14179 bpr 1462
  printf ("    -X  same as above, listing all records (even if 0) as comma-separated list\n");
1463
  printf ("    -a  count charges in fingerprint\n");  /* 0.3x */
1464
  printf ("    -m  write MDL molfile (with special encoding for aromatic atoms/bonds)\n");
6785 bpr 1465
  printf (" options can be combined like -vc\n");
1466
  printf (" <filename> specifies any file in the formats supported\n");
14179 bpr 1467
  printf (" (MDL *.mol, Alchemy *.mol, Sybyl *.mol2), the filename \"-\" (without quotes)\n");
6785 bpr 1468
  printf (" specifies standard input\n");
1469
  /* the "debug" option (-D) remains undocumented */
1470
}
1471
 
14179 bpr 1472
static void list_molstat_codes ()
6785 bpr 1473
{
1474
  printf ("n_atoms:     number of heavy atoms\n");
1475
  printf ("n_bonds:     number of bonds between non-H atoms\n");
1476
  printf ("n_rings:     number of rings\n");
1477
  printf ("n_QA:        number of query atoms\n");
1478
  printf ("n_QB:        number of query bonds\n");
1479
  printf ("n_chg:       number of charges\n");
1480
  printf ("n_C1:        number of sp-hybridized carbon atoms\n");
1481
  printf ("n_C2:        number of sp2-hybridized carbon atoms\n");
1482
  printf ("n_C:         total number of carbon atoms\n");
1483
  printf
1484
    ("n_CHB1p:     number of carbon atoms with at least 1 bond to a hetero atom\n");
1485
  printf
1486
    ("n_CHB2p:     number of carbon atoms with at least 2 bonds to a hetero atom\n");
1487
  printf
1488
    ("n_CHB3p:     number of carbon atoms with at least 3 bonds to a hetero atom\n");
1489
  printf
1490
    ("n_CHB4:      number of carbon atoms with 4 bonds to a hetero atom\n");
1491
  printf ("n_O2:        number of sp2-hybridized oxygen atoms\n");
1492
  printf ("n_O3:        number of sp3-hybridized oxygen atoms\n");
1493
  printf ("n_N1:        number of sp-hybridized nitrogen atoms\n");
1494
  printf ("n_N2:        number of sp2-hybridized nitrogen atoms\n");
1495
  printf ("n_N3:        number of sp3-hybridized nitrogen atoms\n");
1496
  printf ("n_S:         number of sulfur atoms\n");
1497
  printf ("n_SeTe:      total number of selenium and tellurium atoms\n");
1498
  printf ("n_F:         number of fluorine atoms\n");
1499
  printf ("n_Cl:        number of chlorine atoms\n");
1500
  printf ("n_Br:        number of bromine atoms\n");
1501
  printf ("n_I:         number of iodine atoms\n");
1502
  printf ("n_P:         number of phosphorus atoms\n");
1503
  printf ("n_B:         number of boron atoms\n");
1504
  printf ("n_Met:       total number of metal atoms\n");
1505
  printf
1506
    ("n_X:         total number of \"other\" atoms (not listed above) and halogens\n");
1507
  printf ("n_b1:        number of single bonds\n");
1508
  printf ("n_b2:        number of double bonds\n");
1509
  printf ("n_b3:        number of triple bonds\n");
1510
  printf ("n_bar:       number of aromatic bonds\n");
1511
  printf ("n_C1O:       number of C-O single bonds\n");
1512
  printf ("n_C2O:       number of C=O double bonds\n");
1513
  printf ("n_CN:        number of C/N bonds (any type)\n");
1514
  printf ("n_XY:        number of heteroatom/heteroatom bonds (any type)\n");
1515
  printf ("n_r3:        number of 3-membered rings\n");
1516
  printf ("n_r4:        number of 4-membered rings\n");
1517
  printf ("n_r5:        number of 5-membered rings\n");
1518
  printf ("n_r6:        number of 6-membered rings\n");
1519
  printf ("n_r7:        number of 7-membered rings\n");
1520
  printf ("n_r8:        number of 8-membered rings\n");
1521
  printf ("n_r9:        number of 9-membered rings\n");
1522
  printf ("n_r10:       number of 10-membered rings\n");
1523
  printf ("n_r11:       number of 11-membered rings\n");
1524
  printf ("n_r12:       number of 12-membered rings\n");
1525
  printf ("n_r13p:      number of 13-membered or larger rings\n");
1526
  printf ("n_rN:        number of rings containing nitrogen (any number)\n");
1527
  printf ("n_rN1:       number of rings containing 1 nitrogen atom\n");
1528
  printf ("n_rN2:       number of rings containing 2 nitrogen atoms\n");
1529
  printf
1530
    ("n_rN3p:      number of rings containing 3 or more nitrogen atoms\n");
1531
  printf ("n_rO:        number of rings containing oxygen (any number)\n");
1532
  printf ("n_rO1:       number of rings containing 1 oxygen atom\n");
1533
  printf ("n_rO2p:      number of rings containing 2 or more oxygen atoms\n");
1534
  printf ("n_rS:        number of rings containing sulfur (any number)\n");
1535
  printf ("n_rX:        number of heterocycles (any type)\n");
1536
  printf ("n_rar:       number of aromatic rings (any type)\n");
14179 bpr 1537
  /* p2c: checkmol.pas, line 1207:
1538
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 1539
  /*$IFDEF extended_molstat */
1540
  printf ("n_rbz:       number of benzene rings\n");
1541
  printf ("n_br2p:      number of bonds belonging to two or more rings\n");
14179 bpr 1542
  printf ("n_psg01:     number of atoms belonging to group 1 of the periodic system\n");
1543
  printf ("n_psg02:     number of atoms belonging to group 2 of the periodic system\n");
1544
  printf ("n_psg13:     number of atoms belonging to group 13 of the periodic system\n");
1545
  printf ("n_psg14:     number of atoms belonging to group 14 of the periodic system\n");
1546
  printf ("n_psg15:     number of atoms belonging to group 15 of the periodic system\n");
1547
  printf ("n_psg16:     number of atoms belonging to group 16 of the periodic system\n");
1548
  printf ("n_psg17:     number of atoms belonging to group 17 of the periodic system\n");
1549
  printf ("n_psg18:     number of atoms belonging to group 18 of the periodic system\n");
1550
  printf ("n_pstm:      number of atoms belonging to the transition metals\n");
1551
  printf ("n_psla:      number of atoms belonging to the lanthanides or actinides\n");
6785 bpr 1552
  printf ("n_iso:      number of isotopes\n");
1553
  printf ("n_rad:      number of radicals\n");
1554
  /*$ENDIF */
1555
}
1556
 
1557
#if 0
14179 bpr 1558
static void parse_args() {
6785 bpr 1559
  int p;
1560
  char parstr[256];
1561
  char tmpstr[256];
1562
  int l;
1563
 
1564
  *tmpstr = '\0';
1565
  opt_none = true;
1566
  if (progmode == pmCheckMol) {
1567
    for (p = 1; p < P_argc; p++) {
1568
      strcpy(parstr, P_argv[p]);
1569
      if (!strcmp(parstr, "-l")) {   /* new in v0.3l */
14179 bpr 1570
        list_molstat_codes();
1571
        _Escape(0);
6785 bpr 1572
      }
1573
      if (p < P_argc - 1) {
14179 bpr 1574
        if (strpos2(parstr, "-", 1) == 1 && p < P_argc - 1) {
1575
          strcpy(tmpstr, P_argv[p]);
1576
          left_trim(tmpstr);
1577
          l = 0;
1578
          if (strpos2(tmpstr, "v", 1) > 0)
1579
            l++;
1580
          if (strpos2(tmpstr, "D", 1) > 0)
1581
            l++;
1582
          if (strpos2(tmpstr, "r", 1) > 0)
1583
            l++;
1584
          if (strpos2(tmpstr, "M", 1) > 0)   /* new in v0.3 */
1585
            l++;
1586
          if (strlen(tmpstr) > l + 2) {
1587
            show_usage();
1588
            _Escape(1);
1589
          }
1590
          opt_none = false;
1591
          if (strpos2(tmpstr, "M", 1) > 0)
1592
            opt_metalrings = true;
1593
          if (strpos2(tmpstr, "v", 1) > 0)
1594
            opt_verbose = true;
1595
            /* p2c: checkmol.pas, line 1261:
1596
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1597
            /*$IFDEF debug
1598
            if (strpos2(tmpstr, "D", 1) > 0)
1599
              opt_debug = true;
1600
            $ENDIF*/
1601
          if (strpos2(tmpstr, "e", 1) > 0)
1602
            opt_text = true;
1603
          else {
1604
            if (strpos2(tmpstr, "d", 1) > 0)
1605
              opt_text_de = true;
1606
            else {
1607
              if (strpos2(tmpstr, "c", 1) > 0)
1608
                opt_code = true;
1609
              else {
1610
                if (strpos2(tmpstr, "b", 1) > 0)
1611
                  opt_bin = true;
1612
                else {
1613
                  if (strpos2(tmpstr, "s", 1) > 0)
1614
                    opt_bitstring = true;
1615
                }
1616
              }
1617
            }
1618
            if (strpos2(tmpstr, "x", 1) > 0)
1619
              opt_molstat = true;
1620
            if (strpos2(tmpstr, "r", 1) > 0)
1621
              opt_rs = rs_ssr;
1622
            if (strpos2(tmpstr, "X", 1) > 0) {
1623
              opt_molstat = true;
1624
              opt_molstat_X = true;
1625
            }
1626
            if (strpos2(tmpstr, "m", 1) > 0) {
1627
              opt_text = false;
1628
              opt_text_de = false;
1629
              opt_bin = false;
1630
              opt_bitstring = false;
1631
              opt_code = false;
1632
              opt_molstat = false;
1633
              opt_xmdlout = true;
1634
                  }
1635
          }
1636
        strcpy(molfilename, tmpstr);
1637
      }
1638
    } else {
1639
      if (strpos2(parstr, "-", 1) == 1) {
1640
        if (strlen(parstr) > 1) {
1641
          show_usage();
1642
          _Escape(1);
1643
        }
1644
        opt_stdin = true;
6785 bpr 1645
      } else {
14179 bpr 1646
      opt_stdin = false;
1647
      strcpy(molfilename, parstr);
6785 bpr 1648
      }
14179 bpr 1649
        }
6785 bpr 1650
    }
1651
    if (opt_text == false && opt_text_de == false && opt_code == false &&
14179 bpr 1652
        opt_bin == false && opt_bitstring == false && opt_molstat == false &&
1653
        opt_molstat_X == false && opt_xmdlout == false)
6785 bpr 1654
      opt_none = true;
1655
  }
1656
  if (progmode == pmMatchMol) {
1657
    *ndl_molfilename = '\0';
1658
    *molfilename = '\0';
1659
    for (p = 1; p < P_argc; p++) {
14179 bpr 1660
        strcpy(parstr, P_argv[p]);
6785 bpr 1661
      if (p == 1) {
14179 bpr 1662
        if (strpos2(parstr, "-", 1) == 1) {
1663
          if (strpos2(parstr, "v", 1) > 1)
1664
            opt_verbose = true;
1665
            /* p2c: checkmol.pas, line 1329:
1666
             * Note: Turbo Pascal conditional compilation directive was ignored [218] */
1667
            /*$IFDEF debug
1668
                if (strpos2(parstr, "D", 1) > 1)
1669
                  opt_debug = true;
1670
               $ENDIF*/
1671
          if (strpos2(parstr, "x", 1) > 1)
1672
            opt_exact = true;
1673
          if (strpos2(parstr, "s", 1) > 1)   /* new in v0.2f */
1674
            opt_strict = true;
1675
          if (strpos2(parstr, "m", 1) > 1)
1676
           opt_molout = true;
1677
          if (strpos2(parstr, "r", 1) > 1)
1678
            opt_rs = rs_ssr;
1679
          if (strpos2(parstr, "M", 1) > 0)   /* new in v0.3 */
1680
            opt_metalrings = true;
1681
          if (strpos2(parstr, "g", 1) > 0)   /* new in v0.3d */
1682
            opt_geom = true;
1683
          if (strpos2(parstr, "G", 1) > 0)   /* new in v0.3f */
1684
            opt_chiral = true;
1685
          if (strpos2(parstr, "f", 1) > 0) {   /* new in v0.3m */
1686
            opt_fp = true;
1687
          fpformat = fpf_boolean;
1688
        }
1689
        if (strpos2(parstr, "F", 1) > 0) {   /* new in v0.3m */
1690
          opt_fp = true;
1691
          fpformat = fpf_decimal;
1692
        }
1693
        if (strpos2(parstr, "h", 1) > 1) {
1694
          show_usage();
1695
          _Escape(0);
1696
        }
1697
            } else
1698
        strcpy(ndl_molfilename, parstr);
1699
    }
1700
    if (p == P_argc - 2) {
1701
      if (strpos2(parstr, "-", 1) != 1)
1702
      strcpy(ndl_molfilename, parstr);
1703
    }
1704
    if (p == P_argc - 1) {
1705
      if (strcmp(parstr, "-"))
1706
        strcpy(molfilename, parstr);
1707
      else
1708
        opt_stdin = true;
1709
      }
1710
    }
1711
    if (opt_geom)   /* v0.3d */
1712
      ez_search = true;
1713
    if (opt_chiral)   /* v0.3f */
1714
      rs_search = true;
1715
    if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1716
        /* new in v0.3j, v0.3m */
1717
      rs_strict = true;
1718
    if (opt_fp) {   /* v0.3m */
1719
        opt_molout = false;
1720
        opt_exact = false;
1721
    }
1722
  }  /* progmode = pmMatchMol */
1723
  ringsearch_mode = opt_rs;   /* v0.3i */
1724
}
6785 bpr 1725
#endif
1726
 
14179 bpr 1727
static void parse_args (int argc, char *argv[])
6785 bpr 1728
{
1729
  short p;
1730
  char parstr[256];
1731
  char tmpstr[256];
1732
  short l;
1733
 
1734
  *tmpstr = '\0';
1735
  opt_none = true;
1736
  *molfilename = '\0';
1737
  *ndl_molfilename = '\0';
14179 bpr 1738
  if (progmode == pmCheckMol) {
1739
    for (p = 1; p <= argc - 1; p++) {
1740
            strcpy (parstr, argv[p]);
1741
            if (!strcmp (parstr, "-l")) {                       /* new in v0.3l */
6785 bpr 1742
              list_molstat_codes ();
1743
              exit (0);
1744
            }
14179 bpr 1745
            if (p < argc - 1) {
1746
              if (strpos2 (parstr, "-", 1) == 1 && p < argc - 1) {
1747
                      strcpy (tmpstr, argv[p]);
1748
                      left_trim (tmpstr);
1749
                      l = 0;
1750
                      if (strpos2 (tmpstr, "v", 1) > 0)
1751
                        l++;
1752
                      if (strpos2 (tmpstr, "D", 1) > 0)
1753
                        l++;
6785 bpr 1754
                      if (strpos2 (tmpstr, "r", 1) > 0)
14179 bpr 1755
                        l++;
1756
                      /*if (strpos2 (tmpstr, "a", 1) > 0)   // 0.3x
1757
                         l++; */
1758
                      if (strpos2 (tmpstr, "M", 1) > 0) /* new in v0.3 */
1759
                        l++;
1760
                      if (strlen (tmpstr) > l + 2) {
1761
                        show_usage ();
1762
                        exit (1);
1763
                      }
1764
                      opt_none = false;
1765
                      if (strpos2 (tmpstr, "M", 1) > 0)
1766
                        opt_metalrings = true;
1767
                      if (strpos2 (tmpstr, "v", 1) > 0)
1768
                        opt_verbose = true;
1769
                      /*{$IFDEF debug
1770
                         if pos('D',tmpstr)>0 then opt_debug       := true;
1771
                         {$ENDIF */
1772
                      if (strpos2 (tmpstr, "e", 1) > 0)
1773
                        opt_text = true;
1774
                      else {
1775
                        if (strpos2 (tmpstr, "d", 1) > 0)
1776
                                 opt_text_de = true;
1777
                        else {
1778
                                if (strpos2 (tmpstr, "c", 1) > 0)
1779
                                  opt_code = true;
1780
                                else {
1781
                                  if (strpos2 (tmpstr, "b", 1) > 0)
1782
                                    opt_bin = true;
1783
                                  else {
1784
                                    if (strpos2 (tmpstr, "s", 1) > 0)
1785
                                      opt_bitstring = true;
1786
                                  }
1787
                                }
1788
                              }
1789
                        if (strpos2 (tmpstr, "x", 1) > 0)
1790
                                opt_molstat = true;
1791
                        if (strpos2 (tmpstr, "r", 1) > 0)
1792
                                opt_rs = rs_ssr;
1793
                          /* if (strpos2 (tmpstr, "a", 1) > 0)
1794
                            opt_chg = true; */ /* 0.3x  */
1795
                        if (strpos2 (tmpstr, "X", 1) > 0) {
1796
                                opt_molstat = true;
1797
                                opt_molstat_X = true;
1798
                              }
1799
                        if (strpos2 (tmpstr, "m", 1) > 0) {
1800
                                opt_text = false;
1801
                                opt_text_de = false;
1802
                                opt_bin = false;
1803
                                opt_bitstring = false;
1804
                                opt_code = false;
1805
                                opt_molstat = false;
1806
                                opt_xmdlout = true;
1807
                              }
1808
                      }
1809
                      strcpy (molfilename, tmpstr);
1810
              }
6785 bpr 1811
            }
14179 bpr 1812
            else {
1813
              if (strpos2 (parstr, "-", 1) == 1) {
1814
                if (strlen (parstr) > 1) {
1815
                  show_usage ();
1816
                  exit (1);
1817
                }
1818
                opt_stdin = true;
1819
              } else {
1820
                      opt_stdin = false;
1821
                      strcpy (molfilename, parstr);
6785 bpr 1822
                    }
1823
            }
14179 bpr 1824
          }
1825
    if (opt_text == false && opt_text_de == false && opt_code == false &&
1826
                opt_bin == false && opt_bitstring == false && opt_molstat == false
1827
                && opt_molstat_X == false && opt_xmdlout == false
1828
                && opt_chg == false)
1829
              opt_none = true;  /* 0.3x */
1830
  }
1831
  if (progmode == pmMatchMol) {
1832
    for (p = 1; p <= argc - 1; p++) {
1833
      strcpy (parstr, argv[p]);
1834
      if (p == 1) {
1835
        if (strpos2 (parstr, "-", 1) == 1) {
1836
          if (strpos2 (parstr, "v", 1) > 1)
1837
            opt_verbose = true;
1838
            /*{$IFDEF debug
1839
               if pos('D',parstr)>1 then opt_debug       := true;
1840
               {$ENDIF */
1841
          if (strpos2 (parstr, "x", 1) > 1)
1842
            opt_exact = true;
1843
          if (strpos2 (parstr, "s", 1) > 1)     /* new in v0.2f */
1844
            opt_strict = true;
1845
          if (strpos2 (parstr, "m", 1) > 1)
1846
            opt_molout = true;
1847
          if (strpos2 (parstr, "r", 1) > 1)
1848
            opt_rs = rs_ssr;
1849
          if (strpos2 (parstr, "a", 1) > 0)
1850
                    opt_chg = true;     /* 0.3x */
1851
          if (strpos2 (parstr, "i", 1) > 0)
1852
            opt_iso = true;     /* 0.3x */
1853
          if (strpos2 (parstr, "d", 1) > 0)
1854
            opt_rad = true;     /* 0.3x */
1855
          if (strpos2 (parstr, "M", 1) > 0)     /* new in v0.3 */
1856
            opt_metalrings = true;
1857
          if (strpos2 (parstr, "g", 1) > 0)     /* new in v0.3d */
1858
            opt_geom = true;
1859
          if (strpos2 (parstr, "G", 1) > 0)     /* new in v0.3f */
1860
            opt_chiral = true;
1861
          if (strpos2 (parstr, "f", 1) > 0) {           /* new in v0.3m */
1862
            opt_fp = true;
1863
            fpformat = fpf_boolean;
1864
          }
1865
          if (strpos2 (parstr, "F", 1) > 0) {           /* new in v0.3m */
1866
            opt_fp = true;
1867
            fpformat = fpf_decimal;
1868
          }
1869
          if (strpos2 (parstr, "h", 1) > 1) {
1870
            show_usage ();
1871
            exit (0);
1872
          }
1873
              } else
1874
                strcpy (ndl_molfilename, parstr);
6785 bpr 1875
            }
14179 bpr 1876
            if (p == argc - 2) {
6785 bpr 1877
              if (strpos2 (parstr, "-", 1) != 1)
14179 bpr 1878
                strcpy (ndl_molfilename, parstr);
1879
              }
1880
            if (p == argc - 1) {
6785 bpr 1881
              if (strcmp (parstr, "-"))
14179 bpr 1882
                strcpy (molfilename, parstr);
6785 bpr 1883
              else
14179 bpr 1884
                opt_stdin = true;
6785 bpr 1885
            }
14179 bpr 1886
          }
1887
    if (opt_geom)               /* v0.3d */
1888
            ez_search = true;
1889
    if (opt_chiral)             /* v0.3f */
1890
            rs_search = true;
1891
    if (opt_chiral && opt_strict && (opt_exact || opt_fp))
1892
            /* new in v0.3j, v0.3m  */
1893
            rs_strict = true;
1894
    if (opt_fp) {                       /* v0.3m */
1895
            opt_molout = false;
1896
            opt_exact = false;
1897
          }
1898
  }                             /* progmode = pmMatchMol */
6785 bpr 1899
  ringsearch_mode = opt_rs;     /* v0.3i */
1900
}
1901
 
1902
/*============== input-related functions & procedures ===================== */
1903
 
14179 bpr 1904
static char *get_filetype (Result, f)
1905
  char *Result;
1906
  char *f;
6785 bpr 1907
{
1908
  char rline[256];
1909
  char auxstr[256];
1910
  int i;
1911
  boolean mdl1 = false;
1912
  int ri;
1913
  int sepcount = 0;
1914
  char STR1[256], STR6[256], STR7[256];
1915
 
1916
  strcpy (auxstr, "unknown");
1917
  i = li;
1918
  ri = li - 1;
14179 bpr 1919
  while (ri < molbufindex && sepcount < 1) {
1920
    ri++;
1921
    strcpy (rline, molbuf[ri - 1]);
1922
    if (strpos2 (rline, "$$$$", 1) > 0)
1923
            sepcount++;
1924
    if ((i == li) && (strcmp (strsub (STR1, rline, 7, 5), "ATOMS") == 0) &&
1925
              (strcmp (strsub (STR6, rline, 20, 5), "BONDS") == 0) &&
1926
              (strcmp (strsub (STR7, rline, 33, 7), "CHARGES") == 0))
1927
            strcpy (auxstr, "alchemy");
1928
    if ((i == li + 3) && (strcmp (strsub (STR1, rline, 35, 5), "V2000") == 0))
1929
            /* and (copy(rline,31,3)='999') */
1930
            mdl1 = true;
1931
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 6), "-ISIS-") == 0))
1932
            mdl1 = true;
1933
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "WLViewer") == 0))
1934
            mdl1 = true;
1935
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CheckMol") == 0))
1936
            mdl1 = true;
1937
    if ((i == li + 1) && (strcmp (strsub (STR1, rline, 3, 8), "CATALYST") == 0)) {
1938
            mdl1 = true;
1939
            strcpy (auxstr, "mdl");
1940
          }
1941
    if (strpos2 (rline, "M  END", 1) == 1 || mdl1)
1942
            strcpy (auxstr, "mdl");
1943
    if (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) > 0)
1944
            strcpy (auxstr, "sybyl");
1945
    i++;
1946
  }
6785 bpr 1947
  /* new in v0.2j: try to identify non-conformant SD-files */
1948
  if (!strcmp (auxstr, "unknown") && sepcount > 0)
1949
    strcpy (auxstr, "mdl");
1950
  return strcpy (Result, auxstr);
1951
}
1952
 
14179 bpr 1953
static void zap_molecule ()
6785 bpr 1954
{
1955
  /* try */
14179 bpr 1956
  if (atom != NULL) {
1957
    free (atom);
1958
    atom = NULL;                /* added in v0.3j */
1959
  }
1960
  if (bond != NULL) {
1961
    free (bond);
1962
    bond = NULL;                /* added in v0.3j */
1963
  }
1964
  if (ring != NULL) {
1965
    free (ring);
1966
    ring = NULL;                /* added in v0.3j */
1967
  }
1968
  if (ringprop != NULL) {
1969
    free (ringprop);
1970
    ringprop = NULL;            /* added in v0.3j */
1971
  }
6785 bpr 1972
  /* except
14179 bpr 1973
    on e:Einvalidpointer do begin end;
1974
    end; */
6785 bpr 1975
  n_atoms = 0;
1976
  n_bonds = 0;
1977
  n_rings = 0;
1978
}
1979
 
14179 bpr 1980
static void zap_needle ()
6785 bpr 1981
{
1982
  /* try */
14179 bpr 1983
  if (ndl_atom != NULL) {
1984
    free (ndl_atom);
1985
    ndl_atom = NULL;            /* added in v0.3j */
1986
  }
1987
  if (ndl_bond != NULL) {
1988
    free (ndl_bond);
1989
    ndl_bond = NULL;            /* added in v0.3j */
1990
  }
1991
  if (ndl_ring != NULL) {
1992
    free (ndl_ring);
1993
    ndl_ring = NULL;            /* added in v0.3j */
1994
  }
1995
  if (ndl_ringprop != NULL) {
1996
    free (ndl_ringprop);        /* fixed in v0.3g */
1997
    ndl_ringprop = NULL;        /* added in v0.3j */
1998
  }
6785 bpr 1999
  /* except
2000
     on e:Einvalidpointer do begin end;
2001
     end; */
2002
  ndl_n_atoms = 0;
2003
  ndl_n_bonds = 0;
2004
  ndl_n_rings = 0;
2005
}
2006
 
2007
#if 0
14179 bpr 2008
static void zap_tmp ()
6785 bpr 2009
{
2010
  /* try */
14179 bpr 2011
  if (tmp_atom != NULL) {
6785 bpr 2012
      free (tmp_atom);
2013
      tmp_atom = NULL;          /* added in v0.3j */
2014
    }
14179 bpr 2015
  if (tmp_bond != NULL) {
6785 bpr 2016
      free (tmp_bond);
2017
      tmp_bond = NULL;          /* added in v0.3j */
2018
    }
14179 bpr 2019
  if (tmp_ring != NULL) {
6785 bpr 2020
      free (tmp_ring);
2021
      tmp_ring = NULL;          /* added in v0.3j */
2022
    }
14179 bpr 2023
  if (tmp_ringprop != NULL) {
6785 bpr 2024
      free (tmp_ringprop);      /* fixed in v0.3g */
2025
      tmp_ringprop = NULL;      /* added in v0.3j */
2026
    }
2027
  /* except
2028
     on e:Einvalidpointer do begin end;
2029
     end; */
2030
  tmp_n_atoms = 0;
2031
  tmp_n_bonds = 0;
2032
  tmp_n_rings = 0;
2033
}
2034
#endif
2035
 
14179 bpr 2036
static boolean is_heavyatom (id)
6785 bpr 2037
     int id;
2038
{
2039
  str2 el;
2040
 
2041
  strcpy (el, atom[id - 1].element);
14179 bpr 2042
 
6785 bpr 2043
  if (!strcmp (el, "DU") || !strcmp (el, "LP"))
2044
    return false;
2045
  /*if (progmode == pmCheckMol && !strcmp (el, "H ")
2046
     && atom[id - 1].nucleon_number < 2)
2047
     return false;               0.3x  */
14179 bpr 2048
  if (!strcmp (el, "H "))       /* 0.3 p */ {
2049
    if (progmode == pmMatchMol && !opt_iso) {
2050
            return false;
2051
          }
2052
    else {
6785 bpr 2053
          if (atom[id - 1].nucleon_number < 2)
2054
            return false;
14179 bpr 2055
          }
2056
  }
6785 bpr 2057
  return true;
2058
}
2059
 
14179 bpr 2060
static boolean ndl_alkene_C (ba)
6785 bpr 2061
     int ba;
2062
{
2063
  /* new in v0.3f */
2064
  boolean res = false;
2065
  int i, ba2, FORLIM;
2066
 
2067
  if (ndl_n_atoms <= 0 || ndl_n_bonds <= 0)
2068
    return false;
2069
  FORLIM = ndl_n_bonds;
14179 bpr 2070
  for (i = 0; i < FORLIM; i++) {
2071
    if (ndl_bond[i].a1 == ba || ndl_bond[i].a2 == ba) {
2072
            if (ndl_bond[i].a1 == ba)
2073
              ba2 = ndl_bond[i].a2;
2074
            else
2075
              ba2 = ndl_bond[i].a1;
6785 bpr 2076
          if (!strcmp (ndl_atom[ba - 1].atype, "C2 ") &&
2077
              !strcmp (ndl_atom[ba2 - 1].atype, "C2 ")
2078
              && ndl_bond[i].btype == 'D' && ndl_bond[i].arom == false)
2079
            res = true;
14179 bpr 2080
          }
2081
  }
6785 bpr 2082
  return res;
2083
}
2084
 
14179 bpr 2085
static boolean is_metal (id)
6785 bpr 2086
     int id;
2087
{
2088
  boolean r = false;
2089
  str2 el;
2090
 
2091
  strcpy (el, atom[id - 1].element);
2092
  if (!strcmp (el, "LI") || !strcmp (el, "NA") || !strcmp (el, "K ") ||
2093
      !strcmp (el, "RB") || !strcmp (el, "CS") || !strcmp (el, "BE") ||
2094
      !strcmp (el, "MG") || !strcmp (el, "CA") || !strcmp (el, "SR") ||
2095
      !strcmp (el, "BA") || !strcmp (el, "TI") || !strcmp (el, "ZR") ||
2096
      !strcmp (el, "CR") || !strcmp (el, "MO") || !strcmp (el, "MN") ||
2097
      !strcmp (el, "FE") || !strcmp (el, "CO") || !strcmp (el, "NI") ||
2098
      !strcmp (el, "PD") || !strcmp (el, "PT") || !strcmp (el, "SN") ||
2099
      !strcmp (el, "CU") || !strcmp (el, "AG") || !strcmp (el, "AU") ||
2100
      !strcmp (el, "ZN") || !strcmp (el, "CD") || !strcmp (el, "HG") ||
2101
      !strcmp (el, "AL") || !strcmp (el, "SN") || !strcmp (el, "PB") ||
2102
      !strcmp (el, "SB") || !strcmp (el, "BI"))
14179 bpr 2103
  /* p2c: checkmol.pas, line 1577:
2104
  * Note: Line breaker spent 0.0 seconds, 5000 tries on line 1686 [251] */
6785 bpr 2105
    /* etc. etc. */
2106
    r = true;
2107
  return r;
2108
}
2109
 
14179 bpr 2110
static int get_nvalences (a_el)
6785 bpr 2111
     char *a_el;
2112
{
2113
  /* changed name and position in v0.3m */
2114
  /* preliminary version; should be extended to element/atomtype */
2115
  int res = 1;
2116
 
2117
  if (!strcmp (a_el, "H "))
2118
    res = 1;
14179 bpr 2119
  /*if (!strcmp (a_el, "D "))   // v0.3n
6785 bpr 2120
     res = 1; */
2121
  if (!strcmp (a_el, "C "))
2122
    res = 4;
2123
  if (!strcmp (a_el, "N "))
2124
    res = 3;
2125
  if (!strcmp (a_el, "O "))
2126
    res = 2;
2127
  if (!strcmp (a_el, "S "))
2128
    res = 2;
2129
  if (!strcmp (a_el, "SE"))
2130
    res = 2;
2131
  if (!strcmp (a_el, "TE"))
2132
    res = 2;
2133
  if (!strcmp (a_el, "P "))
2134
    res = 3;
2135
  if (!strcmp (a_el, "F "))
2136
    res = 1;
2137
  if (!strcmp (a_el, "CL"))
2138
    res = 1;
2139
  if (!strcmp (a_el, "BR"))
2140
    res = 1;
2141
  if (!strcmp (a_el, "I "))
2142
    res = 1;
2143
  if (!strcmp (a_el, "AT"))
2144
    res = 1;
2145
  if (!strcmp (a_el, "B "))
2146
    res = 3;
2147
  if (!strcmp (a_el, "LI"))
2148
    res = 1;
2149
  if (!strcmp (a_el, "NA"))
2150
    res = 1;
2151
  if (!strcmp (a_el, "K "))
2152
    res = 1;
2153
  if (!strcmp (a_el, "CA"))
2154
    res = 2;
2155
  if (!strcmp (a_el, "SR"))
2156
    res = 2;
2157
  if (!strcmp (a_el, "MG"))
2158
    res = 2;
2159
  if (!strcmp (a_el, "FE"))
2160
    res = 3;
2161
  if (!strcmp (a_el, "MN"))
2162
    res = 2;
2163
  if (!strcmp (a_el, "HG"))
2164
    res = 2;
2165
  if (!strcmp (a_el, "SI"))
2166
    res = 4;
2167
  if (!strcmp (a_el, "SN"))
2168
    res = 4;
2169
  if (!strcmp (a_el, "ZN"))
2170
    res = 2;
2171
  if (!strcmp (a_el, "CU"))
2172
    res = 2;
2173
  if (!strcmp (a_el, "A "))
2174
    res = 4;
2175
  if (!strcmp (a_el, "Q "))
2176
    res = 4;
2177
  return res;
2178
}
2179
 
14179 bpr 2180
static char * convert_type (Result, oldtype)
6785 bpr 2181
     char *Result;
2182
     char *oldtype;
2183
{
2184
  int i;
2185
  str3 newtype;
2186
 
2187
  sprintf (newtype, "%.3s", oldtype);
2188
  for (i = 0; i <= 2; i++)
2189
    newtype[i] = toupper (newtype[i]);
2190
  if (newtype[0] == '~')
2191
    strcpy (newtype, "VAL");
2192
  if (newtype[0] == '*')
2193
    strcpy (newtype, "STR");
2194
  return strcpy (Result, newtype);
2195
}
2196
 
14179 bpr 2197
static char * convert_sybtype (Result, oldtype)
6785 bpr 2198
     char *Result;
2199
     char *oldtype;
2200
{
2201
  str3 newtype;
2202
 
2203
  /*  NewType := Copy(OldType,1,3); */
2204
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2205
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2206
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2207
  strcpy (newtype, "DU ");
2208
  if (!strcmp (oldtype, "H    "))
2209
    strcpy (newtype, "H  ");
2210
  if (!strcmp (oldtype, "C.ar "))
2211
    strcpy (newtype, "CAR");
2212
  if (!strcmp (oldtype, "C.2  "))
2213
    strcpy (newtype, "C2 ");
2214
  if (!strcmp (oldtype, "C.3  "))
2215
    strcpy (newtype, "C3 ");
2216
  if (!strcmp (oldtype, "C.1  "))
2217
    strcpy (newtype, "C1 ");
2218
  if (!strcmp (oldtype, "O.2  "))
2219
    strcpy (newtype, "O2 ");
2220
  if (!strcmp (oldtype, "O.3  "))
2221
    strcpy (newtype, "O3 ");
2222
  if (!strcmp (oldtype, "O.co2"))
2223
    strcpy (newtype, "O2 ");
2224
  if (!strcmp (oldtype, "O.spc"))
2225
    strcpy (newtype, "O3 ");
2226
  if (!strcmp (oldtype, "O.t3p"))
2227
    strcpy (newtype, "O3 ");
2228
  if (!strcmp (oldtype, "N.1  "))
2229
    strcpy (newtype, "N1 ");
2230
  if (!strcmp (oldtype, "N.2  "))
2231
    strcpy (newtype, "N2 ");
2232
  if (!strcmp (oldtype, "N.3  "))
2233
    strcpy (newtype, "N3 ");
2234
  if (!strcmp (oldtype, "N.pl3"))
2235
    strcpy (newtype, "NPL");
2236
  if (!strcmp (oldtype, "N.4  "))
2237
    strcpy (newtype, "N3+");
2238
  if (!strcmp (oldtype, "N.am "))
2239
    strcpy (newtype, "NAM");
2240
  if (!strcmp (oldtype, "N.ar "))
2241
    strcpy (newtype, "NAR");
2242
  if (!strcmp (oldtype, "F    "))
2243
    strcpy (newtype, "F  ");
2244
  if (!strcmp (oldtype, "Cl   "))
2245
    strcpy (newtype, "CL ");
2246
  if (!strcmp (oldtype, "Br   "))
2247
    strcpy (newtype, "BR ");
2248
  if (!strcmp (oldtype, "I    "))
2249
    strcpy (newtype, "I  ");
2250
  if (!strcmp (oldtype, "Al   "))
2251
    strcpy (newtype, "AL ");
2252
  if (!strcmp (oldtype, "ANY  "))
2253
    strcpy (newtype, "A  ");
2254
  if (!strcmp (oldtype, "Ca   "))
2255
    strcpy (newtype, "CA ");
2256
  if (!strcmp (oldtype, "Du   "))
2257
    strcpy (newtype, "DU ");
2258
  if (!strcmp (oldtype, "Du.C "))
2259
    strcpy (newtype, "DU ");
2260
  if (!strcmp (oldtype, "H.spc"))
2261
    strcpy (newtype, "H  ");
2262
  if (!strcmp (oldtype, "H.t3p"))
2263
    strcpy (newtype, "H  ");
2264
  if (!strcmp (oldtype, "HAL  "))
2265
    strcpy (newtype, "Cl ");
2266
  if (!strcmp (oldtype, "HET  "))
2267
    strcpy (newtype, "Q  ");
2268
  if (!strcmp (oldtype, "HEV  "))
2269
    strcpy (newtype, "DU ");
2270
  if (!strcmp (oldtype, "K    "))
2271
    strcpy (newtype, "K  ");
2272
  if (!strcmp (oldtype, "Li   "))
2273
    strcpy (newtype, "LI ");
2274
  if (!strcmp (oldtype, "LP   "))
2275
    strcpy (newtype, "LP ");
2276
  if (!strcmp (oldtype, "Na   "))
2277
    strcpy (newtype, "NA ");
2278
  if (!strcmp (oldtype, "P.3  "))
2279
    strcpy (newtype, "P3 ");
2280
  if (!strcmp (oldtype, "S.2  "))
2281
    strcpy (newtype, "S2 ");
2282
  if (!strcmp (oldtype, "S.3  "))
2283
    strcpy (newtype, "S3 ");
2284
  if (!strcmp (oldtype, "S.o  "))
2285
    strcpy (newtype, "SO ");
2286
  if (!strcmp (oldtype, "S.o2 "))
2287
    strcpy (newtype, "SO2");
2288
  if (!strcmp (oldtype, "Si   "))
2289
    strcpy (newtype, "SI ");
2290
  if (!strcmp (oldtype, "P.4  "))
2291
    strcpy (newtype, "P4 ");
2292
  return strcpy (Result, newtype);
2293
}
2294
 
14179 bpr 2295
static char * convert_MDLtype (Result, oldtype)
6785 bpr 2296
     char *Result, *oldtype;
2297
{
2298
  str3 newtype;
2299
 
2300
  /*  NewType := Copy(OldType,1,3); */
2301
  /*  For i := 1 To 3 Do NewType[i] := UpCase(NewType[i]); */
2302
  /*  If NewType[1] = '~' Then NewType := 'VAL'; */
2303
  /*  If NewType[1] = '*' Then NewType := 'STR'; */
2304
  strcpy (newtype, "DU ");
2305
  if (!strcmp (oldtype, "H  "))
2306
    strcpy (newtype, "H  ");
2307
  if (!strcmp (oldtype, "C  "))
2308
    strcpy (newtype, "C3 ");
2309
  if (!strcmp (oldtype, "O  "))
2310
    strcpy (newtype, "O2 ");
2311
  if (!strcmp (oldtype, "N  "))
2312
    strcpy (newtype, "N3 ");
2313
  if (!strcmp (oldtype, "F  "))
2314
    strcpy (newtype, "F  ");
2315
  if (!strcmp (oldtype, "Cl "))
2316
    strcpy (newtype, "CL ");
2317
  if (!strcmp (oldtype, "Br "))
2318
    strcpy (newtype, "BR ");
2319
  if (!strcmp (oldtype, "I  "))
2320
    strcpy (newtype, "I  ");
2321
  if (!strcmp (oldtype, "Al "))
2322
    strcpy (newtype, "AL ");
2323
  if (!strcmp (oldtype, "ANY"))
2324
    strcpy (newtype, "A  ");
2325
  if (!strcmp (oldtype, "Ca "))
2326
    strcpy (newtype, "CA ");
2327
  if (!strcmp (oldtype, "Du "))
2328
    strcpy (newtype, "DU ");
2329
  if (!strcmp (oldtype, "K  "))
2330
    strcpy (newtype, "K  ");
2331
  if (!strcmp (oldtype, "Li "))
2332
    strcpy (newtype, "LI ");
2333
  if (!strcmp (oldtype, "LP "))
2334
    strcpy (newtype, "LP ");
2335
  if (!strcmp (oldtype, "Na "))
2336
    strcpy (newtype, "NA ");
2337
  if (!strcmp (oldtype, "P  "))
2338
    strcpy (newtype, "P3 ");
2339
  if (!strcmp (oldtype, "S  "))
2340
    strcpy (newtype, "S3 ");
2341
  if (!strcmp (oldtype, "Si "))
2342
    strcpy (newtype, "SI ");
2343
  if (!strcmp (oldtype, "P  "))
2344
    strcpy (newtype, "P4 ");
2345
  if (!strcmp (oldtype, "A  "))
2346
    strcpy (newtype, "A  ");
2347
  if (!strcmp (oldtype, "Q  "))
2348
    strcpy (newtype, "Q  ");
2349
  return strcpy (Result, newtype);
2350
}
2351
 
14179 bpr 2352
static char * get_element (Result, oldtype)
6785 bpr 2353
     char *Result;
2354
     char *oldtype;
2355
{
2356
  char elemstr[256];
2357
 
2358
  if (!strcmp (oldtype, "H   "))
2359
    strcpy (elemstr, "H ");
14179 bpr 2360
  /* if (!strcmp (oldtype, "D   "))  // v0.3n
6785 bpr 2361
     strcpy (elemstr, "D "); */
2362
  if (!strcmp (oldtype, "CAR "))
2363
    strcpy (elemstr, "C ");
2364
  if (!strcmp (oldtype, "C2  "))
2365
    strcpy (elemstr, "C ");
2366
  if (!strcmp (oldtype, "C3  "))
2367
    strcpy (elemstr, "C ");
2368
  if (!strcmp (oldtype, "C1  "))
2369
    strcpy (elemstr, "C ");
2370
  if (!strcmp (oldtype, "O2  "))
2371
    strcpy (elemstr, "O ");
2372
  if (!strcmp (oldtype, "O3  "))
2373
    strcpy (elemstr, "O ");
2374
  if (!strcmp (oldtype, "O2  "))
2375
    strcpy (elemstr, "O ");
2376
  if (!strcmp (oldtype, "O3  "))
2377
    strcpy (elemstr, "O ");
2378
  if (!strcmp (oldtype, "O3  "))
2379
    strcpy (elemstr, "O ");
2380
  if (!strcmp (oldtype, "N1  "))
2381
    strcpy (elemstr, "N ");
2382
  if (!strcmp (oldtype, "N2  "))
2383
    strcpy (elemstr, "N ");
2384
  if (!strcmp (oldtype, "N3  "))
2385
    strcpy (elemstr, "N ");
2386
  if (!strcmp (oldtype, "NPL "))
2387
    strcpy (elemstr, "N ");
2388
  if (!strcmp (oldtype, "N3+ "))
2389
    strcpy (elemstr, "N ");
2390
  if (!strcmp (oldtype, "NAM "))
2391
    strcpy (elemstr, "N ");
2392
  if (!strcmp (oldtype, "NAR "))
2393
    strcpy (elemstr, "N ");
2394
  if (!strcmp (oldtype, "F   "))
2395
    strcpy (elemstr, "F ");
2396
  if (!strcmp (oldtype, "CL  "))
2397
    strcpy (elemstr, "CL");
2398
  if (!strcmp (oldtype, "BR  "))
2399
    strcpy (elemstr, "BR");
2400
  if (!strcmp (oldtype, "I   "))
2401
    strcpy (elemstr, "I ");
2402
  if (!strcmp (oldtype, "AT  "))
2403
    strcpy (elemstr, "AT");
2404
  if (!strcmp (oldtype, "AL  "))
2405
    strcpy (elemstr, "AL");
2406
  if (!strcmp (oldtype, "DU  "))
2407
    strcpy (elemstr, "DU");
2408
  if (!strcmp (oldtype, "CA  "))
2409
    strcpy (elemstr, "CA");
2410
  if (!strcmp (oldtype, "DU  "))
2411
    strcpy (elemstr, "DU");
2412
  if (!strcmp (oldtype, "Cl  "))
2413
    strcpy (elemstr, "CL");
2414
  if (!strcmp (oldtype, "K   "))
2415
    strcpy (elemstr, "K ");
2416
  if (!strcmp (oldtype, "LI  "))
2417
    strcpy (elemstr, "LI");
2418
  if (!strcmp (oldtype, "LP  "))
2419
    strcpy (elemstr, "LP");
2420
  if (!strcmp (oldtype, "NA  "))
2421
    strcpy (elemstr, "NA");
2422
  if (!strcmp (oldtype, "P3  "))
2423
    strcpy (elemstr, "P ");
2424
  if (!strcmp (oldtype, "S2  "))
2425
    strcpy (elemstr, "S ");
2426
  if (!strcmp (oldtype, "S3  "))
2427
    strcpy (elemstr, "S ");
2428
  if (!strcmp (oldtype, "SO  "))
2429
    strcpy (elemstr, "S ");
2430
  if (!strcmp (oldtype, "SO2 "))
2431
    strcpy (elemstr, "S ");
2432
  if (!strcmp (oldtype, "SI  "))
2433
    strcpy (elemstr, "SI");
2434
  if (!strcmp (oldtype, "P4  "))
2435
    strcpy (elemstr, "P ");
2436
  if (!strcmp (oldtype, "A   "))
2437
    strcpy (elemstr, "A ");
2438
  if (!strcmp (oldtype, "Q   "))
2439
    strcpy (elemstr, "Q ");
2440
  return strcpy (Result, elemstr);
2441
}
2442
 
14179 bpr 2443
static char * get_sybelement (Result, oldtype)
6785 bpr 2444
     char *Result;
2445
     char *oldtype;
2446
{
2447
  int i;
2448
  str2 elemstr;
2449
 
2450
  if (strpos2 (oldtype, ".", 1) < 2)
2451
    sprintf (elemstr, "%.2s", oldtype);
14179 bpr 2452
  else {
2453
    sprintf (elemstr, "%.*s", strpos2 (oldtype, ".", 1) - 1, oldtype);
2454
    if (strlen (elemstr) < 2)
2455
            strcat (elemstr, " ");
2456
  }
6785 bpr 2457
  for (i = 0; i <= 1; i++)
2458
    elemstr[i] = toupper (elemstr[i]);
2459
  return strcpy (Result, elemstr);
2460
}
2461
 
14179 bpr 2462
static char * get_MDLelement (Result, oldtype)
6785 bpr 2463
     char *Result;
2464
     char *oldtype;
2465
{
2466
  int i;
2467
  str2 elemstr;
2468
 
2469
  sprintf (elemstr, "%.2s", oldtype);
2470
  for (i = 0; i <= 1; i++)
2471
    elemstr[i] = toupper (elemstr[i]);
2472
  if (elemstr[0] == '~')
2473
    strcpy (elemstr, "??");
2474
  if (elemstr[0] == '*')
2475
    strcpy (elemstr, "??");
2476
  return strcpy (Result, elemstr);
2477
}
2478
 
14179 bpr 2479
static void read_molfile (mfilename)
6785 bpr 2480
     char *mfilename;
2481
{
2482
  /* reads ALCHEMY mol files */
6787 kbelabas 2483
  int n;
6785 bpr 2484
  char rline[256], tmpstr[256];
2485
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2486
  float xval, yval, zval, chgval;
2487
  char a1str[256], a2str[256], elemstr[256];
2488
  int a1val, a2val, ri;
2489
  char STR1[256];
2490
  int FORLIM;
2491
  atom_rec *WITH;
2492
  bond_rec *WITH1;
2493
 
2494
  if (n_atoms > 0)
2495
    zap_molecule ();
2496
  ri = li;
2497
  strcpy (rline, molbuf[ri - 1]);
2498
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2499
  (void)sscanf (tmpstr, "%d", &n_atoms);
6785 bpr 2500
  strsub (tmpstr, rline, 14, 5);
6787 kbelabas 2501
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2502
  strsub (molname, rline, 42, (int) (strlen (rline) - 42L));
2503
  /* try */
2504
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2505
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2506
  ring = safe_calloc (1, sizeof (ringlist));
2507
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2508
  /* except
2509
     on e:Eoutofmemory do
2510
     begin
2511
     writeln('Not enough memory');
2512
     halt(4);
2513
     end;
2514
     end; */
2515
  n_heavyatoms = 0;
2516
  n_heavybonds = 0;
2517
  n_Ctot = 0;                   /* v0.3g */
2518
  n_Otot = 0;                   /* v0.3g */
2519
  n_Ntot = 0;                   /* v0.3g */
2520
  FORLIM = n_atoms;
14179 bpr 2521
  for (n = 1; n <= FORLIM; n++) {
2522
    ri++;
2523
    strcpy (rline, molbuf[ri - 1]);
2524
    strsub (atomtype, rline, 7, 4);
2525
    sprintf (STR1, "%c", toupper (*atomtype));
2526
    strcpy (atomtype, STR1);    /* fixed in v0.3f */
2527
    get_element (elemstr, atomtype);
2528
    if (!strcmp (elemstr, "C "))
2529
            n_Ctot++;
2530
    if (!strcmp (elemstr, "O "))
2531
            n_Otot++;
2532
    if (!strcmp (elemstr, "N "))
2533
            n_Ntot++;
2534
    convert_type (newatomtype, atomtype);
2535
    strsub (xstr, rline, 14, 7);
2536
    strsub (ystr, rline, 23, 7);
2537
    strsub (zstr, rline, 32, 7);
2538
    strsub (chgstr, rline, 43, 7);
2539
    (void)sscanf (xstr, "%g", &xval);
2540
    (void)sscanf (ystr, "%g", &yval);
2541
    (void)sscanf (zstr, "%g", &zval);
2542
    (void)sscanf (chgstr, "%g", &chgval);
2543
    WITH = &atom[n - 1];
2544
    strcpy (WITH->element, elemstr);
2545
    strcpy (WITH->atype, newatomtype);
2546
    WITH->x = xval;
2547
    WITH->y = yval;
2548
    WITH->z = zval;
2549
    WITH->real_charge = chgval;
2550
    if (is_heavyatom (n)) {
2551
            n_heavyatoms++;
2552
            WITH->heavy = true;
2553
            if (is_metal (n))
2554
              WITH->metal = true;
2555
          }
2556
    WITH->nvalences = get_nvalences (WITH->element);    /* v0.3m   */
2557
  }
6785 bpr 2558
  /*
2559
     with atom^[n] do
2560
     begin
2561
     x := 0; y := 0; z := 0;  (* v0.3g
2562
     formal_charge  := 0;
2563
     real_charge    := 0;
2564
     Hexp           := 0;
2565
     Htot           := 0;
2566
     neighbor_count := 0;
2567
     ring_count     := 0;
2568
     arom           := false;
2569
     stereo_care    := false;
2570
     heavy          := false;
2571
     metal          := false;
2572
     tag            := false;
2573
     end;
2574
   */
2575
  FORLIM = n_bonds;
14179 bpr 2576
  for (n = 0; n < FORLIM; n++) {
2577
    ri++;
2578
    strcpy (rline, molbuf[ri - 1]);
2579
    strsub (a1str, rline, 9, 3);
2580
    strsub (a2str, rline, 15, 3);
2581
    (void)sscanf(a1str, "%d", &a1val);
2582
    (void)sscanf(a2str, "%d", &a2val);
2583
    WITH1 = &bond[n];
2584
    WITH1->a1 = a1val;
2585
    WITH1->a2 = a2val;
2586
    WITH1->btype = rline[19];
2587
    WITH1->ring_count = 0;
2588
    WITH1->arom = false;
2589
    WITH1->topo = btopo_any;
2590
    WITH1->stereo = bstereo_any;
2591
    WITH1->mdl_stereo = 0;      /* v0.3n */
2592
    if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2593
            n_heavybonds++;
2594
  }
6785 bpr 2595
  memset (ring, 0, sizeof (ringlist));
14179 bpr 2596
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
2597
    ringprop[n].size = 0;
2598
    ringprop[n].arom = false;
2599
    ringprop[n].envelope = false;
2600
  }
6785 bpr 2601
  li = ri + 1;
2602
}
2603
 
14179 bpr 2604
static void read_mol2file (mfilename) char *mfilename;
6785 bpr 2605
{
2606
  /* reads SYBYL mol2 files */
2607
  int n, code;
2608
  char sybatomtype[6];
2609
  char tmpstr[256], rline[256];
2610
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2611
  float xval, yval, zval, chgval;
2612
  char a1str[256], a2str[256], elemstr[256];
2613
  int a1val, a2val, ri, FORLIM;
2614
  atom_rec *WITH;
2615
  bond_rec *WITH1;
2616
 
2617
  if (n_atoms > 0)
2618
    zap_molecule ();
2619
  *rline = '\0';
2620
  ri = li - 1;
14179 bpr 2621
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>MOLECULE", 1) == 0)) {
2622
    ri++;
2623
    strcpy (rline, molbuf[ri - 1]);
2624
  }
2625
  if (ri < molbufindex) {
2626
    ri++;
2627
    strcpy (molname, molbuf[ri - 1]);
2628
  }
2629
  if (ri < molbufindex) {
2630
    ri++;
2631
    strcpy (rline, molbuf[ri - 1]);
2632
  }
6785 bpr 2633
  sprintf (tmpstr, "%.5s", rline);
6787 kbelabas 2634
  (void)sscanf (tmpstr, "%d", &n_atoms);
14179 bpr 2635
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 2636
  strsub (tmpstr, rline, 7, 5);
6787 kbelabas 2637
  (void)sscanf (tmpstr, "%d", &n_bonds);
6785 bpr 2638
  /* try */
14179 bpr 2639
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 2640
  atom = safe_calloc (n_atoms, sizeof (atom_rec));
2641
  bond = safe_calloc (n_bonds, sizeof (bond_rec));
2642
  ring = safe_calloc (1, sizeof (ringlist));
2643
  ringprop = safe_calloc (1, sizeof (ringprop_type));
2644
  /* except
2645
     on e:Eoutofmemory do
2646
     begin
2647
     writeln('Not enough memory');
2648
     halt(4);
2649
     end;
2650
     end; */
2651
  n_heavyatoms = 0;
2652
  n_heavybonds = 0;
2653
  n_Ctot = 0;                   /* v0.3g */
2654
  n_Otot = 0;                   /* v0.3g */
2655
  n_Ntot = 0;                   /* v0.3g */
14179 bpr 2656
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>ATOM", 1) == 0)) {
2657
    ri++;
2658
    strcpy (rline, molbuf[ri - 1]);
2659
  }
6785 bpr 2660
  FORLIM = n_atoms;
14179 bpr 2661
  for (n = 1; n <= FORLIM; n++) {
2662
    /*
2663
      with atom^[n] do
2664
      begin
2665
      x := 0; y := 0; z := 0;  (* v0.3g
2666
      formal_charge  := 0;
2667
      real_charge    := 0;
2668
      Hexp           := 0;
2669
      Htot           := 0;
2670
      neighbor_count := 0;
2671
      ring_count     := 0;
2672
      arom           := false;
2673
      stereo_care    := false;
2674
      heavy          := false;
2675
      metal          := false;
2676
      tag            := false;
2677
      end;
2678
    */
2679
    if (ri < molbufindex) {
2680
            ri++;
2681
            strcpy (rline, molbuf[ri - 1]);
2682
          }
2683
    strsub (sybatomtype, rline, 48, 5);
2684
    get_sybelement (elemstr, sybatomtype);
2685
    if (!strcmp (elemstr, "C "))
2686
            n_Ctot++;
2687
    if (!strcmp (elemstr, "O "))
2688
            n_Otot++;
2689
    if (!strcmp (elemstr, "N "))
2690
            n_Ntot++;
2691
    convert_sybtype (newatomtype, sybatomtype);
2692
    strsub (xstr, rline, 18, 9);
2693
    strsub (ystr, rline, 28, 9);
2694
    strsub (zstr, rline, 38, 9);
2695
    strsub (chgstr, rline, 70, 9);
2696
    (void)sscanf (xstr, "%g", &xval);
2697
    (void)sscanf (ystr, "%g", &yval);
2698
    (void)sscanf (zstr, "%g", &zval);
2699
    (void)sscanf (chgstr, "%g", &chgval);
2700
    WITH = &atom[n - 1];
2701
    strcpy (WITH->element, elemstr);
2702
    strcpy (WITH->atype, newatomtype);
2703
    WITH->x = xval;
2704
    WITH->y = yval;
2705
    WITH->z = zval;
2706
    WITH->real_charge = chgval;
2707
    if (is_heavyatom (n)) {
2708
            n_heavyatoms++;
2709
            WITH->heavy = true;
2710
            if (is_metal (n))
2711
              WITH->metal = true;
2712
          }
2713
    WITH->nvalences = get_nvalences (WITH->element);    /* v0.3m   */
2714
  }
2715
  while ((ri < molbufindex) && (strpos2 (rline, "@<TRIPOS>BOND", 1) == 0)) {
2716
    ri++;
2717
    strcpy (rline, molbuf[ri - 1]);
2718
  }
6785 bpr 2719
  FORLIM = n_bonds;
14179 bpr 2720
  for (n = 0; n < FORLIM; n++) {
2721
    if (ri < molbufindex) {
2722
            ri++;
2723
            strcpy (rline, molbuf[ri - 1]);
2724
          }
2725
    strsub (a1str, rline, 9, 3);
2726
    strsub (a2str, rline, 14, 3);
2727
    code = (sscanf (a1str, "%d", &a1val) == 0);
2728
    if (code != 0)
2729
            printf ("%s\007\n", rline);
2730
    code = (sscanf (a2str, "%d", &a2val) == 0);
2731
    if (code != 0)
2732
            printf ("%s\007\n", rline);
2733
    WITH1 = &bond[n];
2734
    WITH1->a1 = a1val;
2735
    WITH1->a2 = a2val;
2736
    if (rline[17] == '1')
2737
            WITH1->btype = 'S';
2738
    if (rline[17] == '2')
2739
            WITH1->btype = 'D';
2740
    if (rline[17] == '3')
2741
            WITH1->btype = 'T';
2742
    if (rline[17] == 'a')
2743
            WITH1->btype = 'A';
2744
    WITH1->ring_count = 0;
2745
    WITH1->arom = false;
2746
    WITH1->topo = btopo_any;
2747
    WITH1->stereo = bstereo_any;
2748
    WITH1->mdl_stereo = 0;      /* v0.3n */
2749
    if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
2750
            n_heavybonds++;
2751
  }
6785 bpr 2752
  memset (ring, 0, sizeof (ringlist));
14179 bpr 2753
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
2754
    ringprop[n].size = 0;
2755
    ringprop[n].arom = false;
2756
    ringprop[n].envelope = false;
2757
  }
6785 bpr 2758
  li = ri + 1;
2759
}
2760
 
14179 bpr 2761
static void read_charges (chgstring_)
6785 bpr 2762
     char *chgstring_;
2763
{
2764
  char chgstring[256];
2765
  int a_id, a_chg;
2766
  /* int n_chrg;*/
2767
 
2768
  /* typical example: a molecule with 2 cations + 1 anion */
2769
  /* M  CHG  3   8   1  10   1  11  -1 */
2770
  strcpy (chgstring, chgstring_);
2771
  if (strpos2 (chgstring, "M  CHG", 1) <= 0)
2772
    return;
2773
  strdelete (chgstring, 1, 6);
2774
  left_trim (chgstring);
14179 bpr 2775
  /* n_chrg = left_int (chgstring);*/
6785 bpr 2776
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2777
  /* p2c: checkmol.pas, line 2077:
2778
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2779
  /*$IFDEF debug */
2780
  /*if (n_chrg == 0)
2781
     debugoutput ("strange... M  CHG present, but no charges found"); */
2782
  /*$ENDIF */
14179 bpr 2783
  while (*chgstring != '\0') {
2784
    a_id = left_int (chgstring);
2785
    a_chg = left_int (chgstring);
2786
    if (a_id != 0 && a_chg != 0)
2787
          atom[a_id - 1].formal_charge = a_chg;
6785 bpr 2788
      //printf ("CHG %i %i\n", a_id, a_chg);
14179 bpr 2789
  }
6785 bpr 2790
}
2791
 
14179 bpr 2792
static void read_isotopes (char *isotopestring_)
6785 bpr 2793
{
2794
  char isotopestring[256];
2795
  int a_id, a_nucleon_number;
2796
  /* int n_isotopes;*/
2797
 
2798
  /* typical example: a molecule with 2 cations + 1 anion */
2799
  /* M  CHG  3   8   1  10   1  11  -1 */
2800
  strcpy (isotopestring, isotopestring_);
2801
  if (strpos2 (isotopestring, "M  ISO", 1) <= 0)
2802
    return;
2803
  strdelete (isotopestring, 1, 6);
2804
  left_trim (isotopestring);
2805
  /*n_isotopes = left_int (isotopestring);*/
2806
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2807
  /* p2c: checkmol.pas, line 2077:
2808
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2809
  /*$IFDEF debug */
2810
  /*if (n_chrg == 0)
2811
     debugoutput ("strange... M  CHG present, but no charges found"); */
2812
  /*$ENDIF */
14179 bpr 2813
  while (*isotopestring != '\0') {
2814
    a_id = left_int (isotopestring);
2815
    a_nucleon_number = left_int (isotopestring);
2816
    if (a_id != 0 && a_nucleon_number != 0) {
2817
            atom[a_id - 1].nucleon_number = a_nucleon_number;
2818
            if (!strcmp (atom[a_id - 1].element, "H ")) {
6785 bpr 2819
              atom[a_id - 1].heavy = true;
2820
              n_heavyatoms++;
2821
              strcpy (atom[a_id - 1].atype, "DU ");
2822
            }
14179 bpr 2823
          }
6785 bpr 2824
      //printf ("ISO %i %i\n", a_id, a_nucleon_number);
14179 bpr 2825
  }
6785 bpr 2826
}
2827
 
14179 bpr 2828
static void read_radicals (radstring_)
6785 bpr 2829
     char *radstring_;
2830
{
2831
  char radstring[256];
6788 kbelabas 2832
  int a_id, a_rad;
6785 bpr 2833
 
2834
  /* typical example: a molecule with 2 cations + 1 anion */
2835
  /* M  CHG  3   8   1  10   1  11  -1 */
2836
  strcpy (radstring, radstring_);
2837
  if (strpos2 (radstring, "M  RAD", 1) <= 0)
2838
    return;
2839
  strdelete (radstring, 1, 6);
2840
  left_trim (radstring);
6788 kbelabas 2841
  (void)left_int (radstring);
6785 bpr 2842
  /* this assignment must be kept also in non-debug mode! */
14179 bpr 2843
  /* p2c: checkmol.pas, line 2077:
2844
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 2845
  /*$IFDEF debug */
2846
  /*if (n_chrg == 0)
2847
     debugoutput ("strange... M  CHG present, but no charges found"); */
2848
  /*$ENDIF */
14179 bpr 2849
  while (*radstring != '\0') {
2850
    a_id = left_int (radstring);
2851
    a_rad = left_int (radstring);
2852
    if (a_id != 0 && a_rad != 0)
2853
            atom[a_id - 1].radical_type = a_rad;
2854
    //printf ("RAD %i %i\n", a_id, a_rad);
2855
  }
6785 bpr 2856
}
2857
 
14179 bpr 2858
static void read_MDLmolfile (char *mfilename)
6785 bpr 2859
{
2860
  /* reads MDL mol files */
2861
  int n, v, tmp_n_atoms, tmp_n_bonds, code;     /* v0.3l */
2862
  char rline[256], tmpstr[256];
2863
  char xstr[256], ystr[256], zstr[256], chgstr[256];
2864
  float xval, yval, zval, chgval;
2865
  char a1str[256], a2str[256], elemstr[256];
2866
  int a1val, a2val, ri, rc, bt, bs;
2867
  int sepcount = 0;
2868
  int i;                        /* v0.3j */
2869
  boolean clearcharges = true;  /* v0.3j */
2870
  char STR1[256];
14179 bpr 2871
  /*  int FORLIM;*/
6785 bpr 2872
  atom_rec *WITH;
2873
  bond_rec *WITH1;
2874
 
2875
  /* v0.3j */
2876
  if (n_atoms > 0)
2877
    zap_molecule ();
2878
  /*cm_mdlmolfile := false; */
2879
  *rline = '\0';
2880
  ri = li;
2881
  strcpy (molname, molbuf[ri - 1]);     /* line 1 */
2882
  if (ri < molbufindex)         /* line 2 */
2883
    ri++;
2884
  strcpy (rline, molbuf[ri - 1]);
14179 bpr 2885
  if (strpos2 (rline, "CheckMol", 1) == 3) {
2886
    /*cm_mdlmolfile := true; */
2887
    found_arominfo = true;
2888
    tmfcode = 1;                /* v0.3m (begin) */
2889
    code = 0;
2890
    if ((strlen (rline) >= 39) && (strpos2 (rline, "TMF", 1) == 35)) {
2891
      /* v0.3m; encoding of tweaklevel */
2892
            strsub (tmpstr, rline, 38, 2);
2893
            code = (sscanf (tmpstr, "%d", &tmfcode) == 0);
2894
          }
2895
    if (code != 0 || tmfcode != tweaklevel)
2896
            tmfmismatch = true;
2897
    else
2898
            tmfmismatch = false;
6785 bpr 2899
      if ((strpos2 (rline, ":r0", 1) >= 40 && ringsearch_mode != rs_sar) |
14179 bpr 2900
                (strpos2 (rline, ":r1", 1) >= 40 && ringsearch_mode != rs_ssr))
2901
              tmfmismatch = true;
6785 bpr 2902
      if ((strpos2 (rline, ":m0", 1) >= 40 && opt_metalrings == true) |
14179 bpr 2903
                (strpos2 (rline, ":m1", 1) >= 40 && opt_metalrings == false))
2904
              tmfmismatch = true;
2905
      /* p2c: checkmol.pas, line 2128:
2906
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
2907
            /*$IFDEF debug */
2908
            //if (tmfmismatch)
2909
            //printf ("\"tweaked\" molfile: version mismatch!\n");
2910
            // else
2911
            //printf ("\"tweaked\" molfile: version OK");
2912
          }
2913
      /*$ENDIF */
2914
      /* v0.3m (end) */
2915
      if (ri < molbufindex)             /* line 3 */
2916
        ri++;
2917
      strcpy (rline, molbuf[ri - 1]);
2918
      strcpy (molcomment, rline);
2919
      if (ri < molbufindex)             /* line 4 */
2920
        ri++;
2921
      strcpy (rline, molbuf[ri - 1]);
2922
      sprintf (tmpstr, "%.3s", rline);
2923
      (void)sscanf (tmpstr, "%d", &n_atoms);
2924
      strsub (tmpstr, rline, 4, 3);
2925
      (void)sscanf (tmpstr, "%d", &n_bonds);
2926
      strsub (tmpstr, rline, 10, 3);
2927
      /* if it is a CheckMol-tweaked molfile, this is the number of rings */
2928
      n_cmrings = 0;
2929
      code = (sscanf (tmpstr, "%d", &n_cmrings) == 0);
2930
      if (code != 0)
2931
        n_cmrings = 0;
2932
      /* do some range checking for n_atoms, n_bonds; new in v0.3l */
2933
      tmp_n_atoms = n_atoms;
2934
      if (n_atoms > max_atoms)
2935
        n_atoms = max_atoms;
2936
      if (n_atoms < 0)
2937
        n_atoms = 0;
2938
      tmp_n_bonds = n_bonds;
2939
      if (n_bonds > max_bonds)
2940
        n_bonds = max_bonds;
2941
      if (n_bonds < 0)
2942
        n_bonds = 0;
2943
      if (n_atoms == 0
6785 bpr 2944
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 2945
        && opt_verbose
6785 bpr 2946
#endif
14179 bpr 2947
    ) {                                 /* v0.3l */
2948
        printf ("WARNING: Possible NoStruct read!\n");
2949
        printf ("NoStructs are proprietary, obsolete and dangerous.\n");
2950
      }
2951
      /* try */
2952
      atom = safe_calloc (n_atoms, sizeof (atom_rec));
2953
      bond = safe_calloc (n_bonds, sizeof (bond_rec));
2954
      /* this would be only one safe_calloc() in C;  v0.3l */
2955
      ring = safe_calloc (1, sizeof (ringlist));
2956
      ringprop = safe_calloc (1, sizeof (ringprop_type));
2957
      /* except
2958
      on e:Eoutofmemory do
2959
      begin
2960
      writeln('Not enough memory');
2961
      (* close(molfile);
2962
      halt(4);
2963
      exit;
2964
      end;
2965
      end; */
2966
      /* check for the chirality flag */
2967
      if (strlen (rline) > 14 && rline[14] == '1')      /* new in v0.3f */
2968
        chir_flag = true;
2969
      n_heavyatoms = 0;
2970
      n_heavybonds = 0;
2971
      n_Ctot = 0;                       /* v0.3g */
2972
      n_Otot = 0;                       /* v0.3g */
2973
      n_Ntot = 0;                       /* v0.3g */
2974
      if (n_atoms > 0) {                                /* v0.3l */
2975
        for (n = 1; n <= tmp_n_atoms; n++) {
2976
                if (n <= max_atoms)
2977
                  v = n;
2978
                else
2979
                  v = max_atoms;
2980
                /* just for safety; v0.3l */
2981
                /*
2982
                with atom^[v] do
2983
                begin
2984
                x := 0; y := 0; z := 0;  (* v0.3g
2985
                formal_charge  := 0;
2986
                real_charge    := 0;
2987
                Hexp           := 0;
2988
                Htot           := 0;
2989
                neighbor_count := 0;
2990
                ring_count     := 0;
2991
                arom           := false;
2992
                stereo_care    := false;
2993
                metal          := false;
2994
                heavy          := false;
2995
                tag            := false;
2996
                end;
2997
                */
2998
                /* replaced by fillchar() after getmem() (see above); v0.3l */
2999
                ri++;
3000
                strcpy (rline, molbuf[ri - 1]);
3001
                strsub (atomtype, rline, 32, 3);
3002
                get_MDLelement (elemstr, atomtype);
3003
                if (!strcmp (elemstr, "C "))
3004
                  n_Ctot++;
3005
                if (!strcmp (elemstr, "O "))
3006
                  n_Otot++;
3007
                if (!strcmp (elemstr, "N "))
3008
                  n_Ntot++;
6785 bpr 3009
 
14179 bpr 3010
                convert_MDLtype (newatomtype, atomtype);
3011
                strsub (xstr, rline, 1, 10);    /* fixed in v0.3k (was: 2,9 etc.) */
3012
                strsub (ystr, rline, 11, 10);
3013
                strsub (zstr, rline, 21, 10);
3014
                /*chgstr := '0'; */
3015
                strsub (chgstr, rline, 37, 3);  /* new in v0.3j */
3016
                (void)sscanf (chgstr, "%f", &chgval);
3017
                if (chgval != 0) {
3018
                  if (chgval >= 1 && chgval <= 7)
3019
                          chgval = 4.0 - chgval;
3020
                  else {
3021
                          chgval = 0.0;
3022
                        }
3023
                }                       /* end (v0.3j) */
3024
                (void)sscanf (xstr, "%f", &xval);
3025
                (void)sscanf (ystr, "%f", &yval);
3026
                (void)sscanf (zstr, "%f", &zval);
3027
                /* v0.3k: removed superfluous val(chgstr,chgval,code) */
3028
                WITH = &atom[v - 1];
3029
                strcpy (WITH->element, elemstr);
3030
                if (!strcmp (elemstr, "A ") || !strcmp (elemstr, "Q ") ||
3031
                    !strcmp (elemstr, "X "))
3032
                  /* 'X ' added in v0.3n */
3033
                  found_querymol = true;
6785 bpr 3034
 
14179 bpr 3035
                strcpy (WITH->atype, newatomtype);
6785 bpr 3036
 
14179 bpr 3037
                if (!strcmp (elemstr, "D ")) {
3038
                  strcpy (WITH->element, "H ");
3039
                  WITH->nucleon_number = 2;
3040
                }                       /* 0.3x */
3041
                if (!strcmp (elemstr, "T ")) {
3042
                  strcpy (WITH->element, "H ");
3043
                  WITH->nucleon_number = 3;
3044
                }                       /* 0.3x */
6785 bpr 3045
 
14179 bpr 3046
                WITH->x = xval;
3047
                WITH->y = yval;
3048
                WITH->z = zval;
3049
                WITH->formal_charge = (long) floor (chgval + 0.5);
3050
                WITH->real_charge = 0.0;        /* v0.3j */
3051
                /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3052
                if (strlen (rline) > 37 && rline[37] == '0') {
3053
                  WITH->arom = true;
3054
                  found_arominfo = true;
3055
                }
3056
                /* new in v0.3d: read stereo care flag */
3057
                if (strlen (rline) > 47 && rline[47] == '1')
3058
                  WITH->stereo_care = true;
3059
                if (is_heavyatom (n)) {
3060
                  n_heavyatoms++;
3061
                  WITH->heavy = true;
3062
                  if (is_metal (n))
3063
                          WITH->metal = true;
3064
                }
3065
                WITH->nvalences = get_nvalences (WITH->element);
3066
                /* v0.3m                 */
3067
              }
3068
      }                         /* if (n_atoms > 0)... */
3069
      if (n_bonds > 0) {                                /* v0.3l */
3070
        for (n = 1; n <= tmp_n_bonds; n++) {
3071
                if (n <= max_bonds)
3072
                  v = n;
3073
                else
3074
                  v = max_bonds;
3075
                /* just for safety; v0.3l */
3076
                ri++;
3077
                strcpy (rline, molbuf[ri - 1]);
3078
                sprintf (a1str, "%.3s", rline);
3079
                strsub (a2str, rline, 4, 3);
3080
                code = (sscanf (a1str, "%d", &a1val) == 0);
3081
                if (code != 0)  /* v0.3l */
3082
                  a1val = 1;
3083
                code = (sscanf (a2str, "%d", &a2val) == 0);
3084
                if (code != 0)  /* v0.3l */
3085
                  a2val = 1;
3086
                WITH1 = &bond[v - 1];
3087
                WITH1->a1 = a1val;
3088
                WITH1->a2 = a2val;
3089
                if (rline[8] == '1')    /* single */
3090
                  WITH1->btype = 'S';
3091
                if (rline[8] == '2')    /* double */
3092
                  WITH1->btype = 'D';
3093
                if (rline[8] == '3')    /* triple */
3094
                  WITH1->btype = 'T';
3095
                if (rline[8] == '4')    /* aromatic */
3096
                  WITH1->btype = 'A';
3097
                if (rline[8] == '5')    /* single or double */
3098
                  WITH1->btype = 'l';
3099
                if (rline[8] == '6')    /* single or aromatic */
3100
                  WITH1->btype = 's';
3101
                if (rline[8] == '7')    /* double or aromatic */
3102
                  WITH1->btype = 'd';
3103
                if (rline[8] == '8')    /* any */
3104
                  WITH1->btype = 'a';
3105
                sprintf (STR1, "%c", WITH1->btype);
3106
                if (strpos2 ("lsda", STR1, 1) > 0)
3107
                  found_querymol = true;
3108
                WITH1->arom = false;
3109
                WITH1->q_arom = false;  /* 0.3p */
3110
                /* read aromaticity flag from CheckMol-tweaked MDL molfile */
3111
                if (WITH1->btype == 'A' || rline[7] == '0') {
3112
                  WITH1->arom = true;
3113
                  if (rline[7] == '0')
3114
                          found_arominfo = true;
3115
                }
3116
                strsub (tmpstr, rline, 13, 3);
3117
                /* new in v0.3d: read ring_count from tweaked molfile */
3118
                code = (sscanf (tmpstr, "%d", &rc) == 0);
3119
                if (code != 0 || rc < 0 || progmode == pmCheckMol || tmfmismatch)
3120
                  WITH1->ring_count = 0;
3121
                else
3122
                 WITH1->ring_count = rc;
3123
                /* v0.3n: added tmfmismatch check */
3124
                strsub (tmpstr, rline, 16, 3);  /* new in v0.3d: read bond topology; */
3125
                code = (sscanf (tmpstr, "%d", &bt) == 0);
3126
                /* extended features are encoded by leading zero */
3127
                if (code != 0 || (unsigned long) bt > 2)
3128
                  WITH1->topo = btopo_any;
3129
                else {
3130
                  if (tmpstr[1] == '0')
3131
                          WITH1->topo = bt + 3;
3132
                  else
3133
                          WITH1->topo = bt;
3134
                }
3135
          /* v0.3n changed >5 into >2 */
3136
          /* new in v0.3d: add stereo property from MDL "stereo care" flag in atom block */
3137
          WITH1->stereo = bstereo_any;
3138
          if (WITH1->btype == 'D') {
3139
            if (atom[WITH1->a1 - 1].stereo_care
3140
                && atom[WITH1->a2 - 1].stereo_care) {           /* this is the MDL-conformant encoding, */
3141
              WITH1->stereo = bstereo_xyz;      /* for an alternative see below */
3142
              ez_flag = true;   /* v0.3f */
3143
            }
3144
                  else {                /* this extended feature is encoded by a leading zero */
3145
                          strsub (tmpstr, rline, 10, 3);
3146
                          /* new in v0.3d: read bond stereo specification; */
3147
                          code = (sscanf (tmpstr, "%d", &bs) == 0);
3148
                          WITH1->mdl_stereo = bs;       /* v0.3n */
3149
                          if (code != 0 || bs <= 0 || bs > 2)
3150
                            WITH1->stereo = bstereo_any;
3151
                          else
3152
                            WITH1->stereo = bstereo_xyz;
3153
                          if (tmpstr[1] == '0')
3154
                            WITH1->stereo = bstereo_xyz;
3155
                        }
3156
                }
3157
                /*if stereo <> bstereo_any then ez_search := true; */
3158
                if (WITH1->stereo != bstereo_any)       /* changed in v0.3f */
3159
                  ez_flag = true;
3160
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '1')
3161
                  WITH1->stereo = bstereo_up;
3162
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '6')
3163
                  WITH1->stereo = bstereo_down;
3164
                if (WITH1->btype == 'S' && strlen (rline) > 11 && rline[11] == '4')
3165
                  WITH1->stereo = bstereo_either;       /* 0.3x */
3166
                if (WITH1->btype == 'D' && strlen (rline) > 11 && rline[11] == '3')
3167
                  WITH1->stereo = bstereo_double_either;        /* 0.3x */
3168
                strsub (tmpstr, rline, 10, 3);
3169
                /* new in v0.3n: save original bond stereo specification; */
3170
                (void)sscanf (tmpstr, "%d", &bs);
3171
                /* v0.3n */
3172
          /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3173
                WITH1->mdl_stereo = bs; /* v0.3n */
3174
                if (atom[a1val - 1].heavy && atom[a2val - 1].heavy)
3175
                  n_heavybonds++;
3176
              }
3177
      }                         /* if (n_bonds > 0)... */
3178
      while (ri < molbufindex && sepcount < 1) {
3179
        ri++;
3180
        strcpy (rline, molbuf[ri - 1]);
3181
    if (strpos2 (rline, "M  CHG", 1) > 0) {                     /* new in v0.3j */
3182
            if (clearcharges) {                 /* "M  CHG" supersedes all "old-style" charge values */
6785 bpr 3183
 
3184
              for (i = 0; i < n_atoms; i++)
14179 bpr 3185
                atom[i].formal_charge = 0;
6785 bpr 3186
            }
14179 bpr 3187
            read_charges (rline);
3188
            clearcharges = false;
3189
            /* subsequent "M  CHG" lines must not clear previous values */
3190
          }
6785 bpr 3191
 
14179 bpr 3192
    if (strpos2 (rline, "M  ISO", 1) > 0)
3193
            read_isotopes (rline);      /* 0.3x */
6785 bpr 3194
 
14179 bpr 3195
    if (strpos2 (rline, "M  RAD", 1) > 0)
3196
            read_radicals (rline);      /* 0.3x */
6785 bpr 3197
 
14179 bpr 3198
    if (strpos2 (rline, "$$$$", 1) > 0) {
3199
            sepcount++;
3200
            if (molbufindex > ri + 2)   /* we assume this is an SDF file */
3201
              mol_in_queue = true;
3202
          }
3203
  }
6785 bpr 3204
  memset (ring, 0, sizeof (ringlist));
14179 bpr 3205
  for (n = 0; n < max_rings; n++) {                             /* new in v0.3 */
3206
    ringprop[n].size = 0;
3207
    ringprop[n].arom = false;
3208
    ringprop[n].envelope = false;
3209
  }
6785 bpr 3210
  li = ri + 1;
3211
}
3212
 
14179 bpr 3213
static void write_MDLmolfile ()
6785 bpr 3214
{
3215
  int i;
3216
  char tmpstr[256];
3217
  char wline[256];
3218
  int a_chg;
3219
  int a_iso;
3220
  int a_rad;
3221
  char tmflabel[256];           /* v0.3m */
3222
  char STR1[256];
3223
  /*char STR7[256];*/
3224
  int FORLIM;
3225
 
3226
  sprintf (tmflabel, "%d", (int) tweaklevel);   /* v0.3m */
3227
  while (strlen (tmflabel) < 2) /* v0.3m */
3228
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
3229
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
3230
  if (strlen (molname) > 80)
3231
    sprintf (molname, "%.80s", strcpy (STR1, molname));
3232
  puts (molname);
3233
  printf ("  CheckMol                        %s", tmflabel);    /* v0.3m */
3234
  if (ringsearch_mode == rs_sar)        /* v0.3m */
3235
    printf (":r0");
3236
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
3237
    printf (":r1");
3238
  if (opt_metalrings)
3239
    printf (":m1");
3240
  else
3241
    printf (":m0");
3242
  /* v0.3m */
3243
  printf ("\n%s\n", molcomment);
3244
  *wline = '\0';
3245
  *tmpstr = '\0';
3246
  sprintf (tmpstr, "%d", n_atoms);
3247
  lblank (3L, tmpstr);
3248
  strcat (wline, tmpstr);
3249
  *tmpstr = '\0';               /* first 3 digits: number of atoms */
3250
  sprintf (tmpstr, "%d", n_bonds);
3251
  lblank (3L, tmpstr);
3252
  strcat (wline, tmpstr);
3253
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
3254
  strcpy (tmpstr, "  0");
3255
  strcat (wline, tmpstr);
3256
  *tmpstr = '\0';               /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 3257
  /* p2c: checkmol.pas, line 2388:
3258
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3259
#ifdef REDUCED_SAR
3260
  sprintf (tmpstr, "%d", n_countablerings);
3261
  /* v0.3n; changed n_rings into n_countablerings */
3262
#else
3263
  sprintf (tmpstr, "%d", n_rings);
3264
#endif
3265
  lblank (3L, tmpstr);
3266
  strcat (wline, tmpstr);
3267
  *tmpstr = '\0';
3268
  /* officially "obsolete", we use it for the number of rings */
3269
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
3270
  if (chir_flag)
3271
    strcat (wline, "1");
3272
  else
3273
    strcat (wline, "0");
3274
  /* v0.3n */
3275
  strcat (wline, "               999 V2000");
3276
  /* v0.3n (adjust string length) */
3277
  puts (wline);
3278
  FORLIM = n_atoms;
14179 bpr 3279
  for (i = 0; i < FORLIM; i++) {
3280
    *wline = '\0';
3281
    sprintf (tmpstr, "%1.4f", atom[i].x);
3282
    lblank (10L, tmpstr);
3283
    strcat (wline, tmpstr);
3284
    sprintf (tmpstr, "%1.4f", atom[i].y);
3285
    lblank (10L, tmpstr);
3286
    strcat (wline, tmpstr);
3287
    sprintf (tmpstr, "%1.4f", atom[i].z);
3288
    lblank (10L, tmpstr);
3289
    strcat (wline, tmpstr);
3290
    strcpy (tmpstr, atom[i].element);
3291
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
3292
    //tmpstr[0] = toupper (tmpstr[0]);
3293
    all_lowercase (tmpstr);
3294
    tmpstr[0] = toupper (tmpstr[0]);
3295
    /*wline := wline + ' '+atom^[i].element+' '; */
3296
    sprintf (wline + strlen (wline), " %s ", tmpstr);
3297
    strcat (wline, " 0");       /* mass difference (isotopes) */
3298
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
3299
    if (atom[i].arom)
3300
            strcpy (tmpstr, " 00");
3301
    else
3302
            strcpy (tmpstr, "  0");
6785 bpr 3303
      strcat (wline, tmpstr);
3304
      strcat (wline, "  0  0  0  0  0  0  0  0  0  0");
3305
      puts (wline);
14179 bpr 3306
  }
6785 bpr 3307
  FORLIM = n_bonds;
14179 bpr 3308
  for (i = 0; i < FORLIM; i++) {
3309
    *wline = '\0';
3310
    sprintf (tmpstr, "%d", bond[i].a1);
3311
    lblank (3L, tmpstr);
3312
    strcat (wline, tmpstr);
3313
    sprintf (tmpstr, "%d", bond[i].a2);
3314
    lblank (3L, tmpstr);
3315
    strcat (wline, tmpstr);
3316
    if (bond[i].btype == 'S')
3317
            strcpy (tmpstr, "  1");
3318
    if (bond[i].btype == 'D')
3319
            strcpy (tmpstr, "  2");
3320
    if (bond[i].btype == 'T')
3321
            strcpy (tmpstr, "  3");
3322
    if (bond[i].btype == 'A')
3323
            strcpy (tmpstr, "  4");
3324
    if (bond[i].btype == 'l')
3325
            strcpy (tmpstr, "  5");
3326
    if (bond[i].btype == 's')
3327
            strcpy (tmpstr, "  6");
3328
    if (bond[i].btype == 'd')
3329
            strcpy (tmpstr, "  7");
3330
    if (bond[i].btype == 'a')
3331
            strcpy (tmpstr, "  8");
6785 bpr 3332
      /* now encode our own aromaticity information */
14179 bpr 3333
    if (bond[i].arom)
3334
            tmpstr[1] = '0';
3335
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
3336
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
3337
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
3338
    /*    wline := wline + '  0'; */
3339
    /* restore original value from MDL molfile (v0.3n) */
3340
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
3341
    *tmpstr = '\0';
3342
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
3343
    strcat (wline, "  ");
3344
    strcat (wline, tmpstr);
3345
    *tmpstr = '\0';
3346
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
3347
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
3348
    sprintf (tmpstr, "%i", bond[i].ring_count);
3349
    while (strlen (tmpstr) < 3)
3350
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
3351
    sprintf (wline + strlen (wline), "%s  0  0", tmpstr);
3352
    puts (wline);
3353
  }
6785 bpr 3354
  FORLIM = n_atoms;
14179 bpr 3355
  for (i = 1; i <= FORLIM; i++) {
3356
    a_chg = atom[i - 1].formal_charge;
3357
    if (a_chg != 0) {
3358
            strcpy (wline, "M  CHG  1 ");
3359
            sprintf (tmpstr, "%d", i);
3360
            lblank (3L, tmpstr);
3361
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3362
            sprintf (tmpstr, "%d", a_chg);
3363
            lblank (3L, tmpstr);
3364
            strcat (wline, tmpstr);
3365
            puts (wline);
3366
          }
3367
  }
3368
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
3369
    a_iso = atom[i - 1].nucleon_number;
3370
    if (a_iso != 0) {
3371
            strcpy (wline, "M  ISO  1 ");
3372
            sprintf (tmpstr, "%d", i);
3373
            lblank (3L, tmpstr);
3374
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3375
            sprintf (tmpstr, "%d", a_iso);
3376
            lblank (3L, tmpstr);
3377
            strcat (wline, tmpstr);
3378
            puts (wline);
3379
          }
3380
  }
3381
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
3382
    a_rad = atom[i - 1].radical_type;
3383
    if (a_rad != 0) {
3384
            strcpy (wline, "M  RAD  1 ");
3385
            sprintf (tmpstr, "%d", i);
3386
            lblank (3L, tmpstr);
3387
            sprintf (wline + strlen (wline), "%s ", tmpstr);
3388
            sprintf (tmpstr, "%d", a_rad);
3389
            lblank (3L, tmpstr);
3390
            strcat (wline, tmpstr);
3391
            puts (wline);
3392
          }
3393
  }
6785 bpr 3394
  printf ("M  END\n");
3395
}
3396
 
3397
/*============= chemical processing functions && procedures ============ */
3398
 
14179 bpr 3399
static boolean is_electroneg (a_el)
6785 bpr 3400
     char *a_el;
3401
{
3402
  /* new in v0.3j */
3403
  boolean res = false;
3404
 
3405
  if (!strcmp (a_el, "N "))
3406
    res = true;
3407
  if (!strcmp (a_el, "P "))
3408
    res = true;
3409
  if (!strcmp (a_el, "O "))
3410
    res = true;
3411
  if (!strcmp (a_el, "S "))
3412
    res = true;
3413
  if (!strcmp (a_el, "SE"))
3414
    res = true;
3415
  if (!strcmp (a_el, "TE"))
3416
    res = true;
3417
  if (!strcmp (a_el, "F "))
3418
    res = true;
3419
  if (!strcmp (a_el, "CL"))
3420
    res = true;
3421
  if (!strcmp (a_el, "BR"))
3422
    res = true;
3423
  if (!strcmp (a_el, "I "))
3424
    res = true;
3425
  if (!strcmp (a_el, "AT"))
3426
    res = true;
3427
  return res;
3428
}
3429
 
14179 bpr 3430
static void count_neighbors ()
6785 bpr 3431
{
3432
  /* counts heavy-atom neighbors and explicit hydrogens */
3433
  int i, FORLIM;
3434
 
3435
  if (n_atoms < 1 || n_bonds < 1)
3436
    return;
3437
  FORLIM = n_bonds;
14179 bpr 3438
  for (i = 0; i < FORLIM; i++) {
3439
    if (atom[bond[i].a1 - 1].heavy)
3440
            atom[bond[i].a2 - 1].neighbor_count++;
3441
    if (atom[bond[i].a2 - 1].heavy)
3442
            atom[bond[i].a1 - 1].neighbor_count++;
3443
    if (!strcmp (atom[bond[i].a1 - 1].element, "H "))
3444
            atom[bond[i].a2 - 1].Hexp++;
3445
    if (!strcmp (atom[bond[i].a2 - 1].element, "H "))
3446
            atom[bond[i].a1 - 1].Hexp++;
3447
    /* plausibility check (new in v02.i) */
3448
    if (atom[bond[i].a1 - 1].neighbor_count > max_neighbors ||
3449
              atom[bond[i].a2 - 1].neighbor_count > max_neighbors) {
3450
            mol_OK = false;
3451
            /*writeln('invalid molecule!'); */
3452
          }
3453
  }
6785 bpr 3454
}
3455
 
14179 bpr 3456
static void get_neighbors (Result, id)
3457
  int *Result;
3458
  int id;
6785 bpr 3459
{
6786 kbelabas 3460
  int i;
6785 bpr 3461
  //neighbor_rec nb_tmp;
3462
  int nb_count = 0;
3463
  //int FORLIM = n_bonds;
3464
 
3465
  //memset (Result, 0, sizeof (neighbor_rec));
3466
 
14179 bpr 3467
  for (i = 0; i < n_bonds; i++) {
3468
    if (bond[i].a1 == id && atom[bond[i].a2 - 1].heavy
3469
              && nb_count < max_neighbors) {
3470
            Result[nb_count++] = bond[i].a2;
3471
          }
3472
    if (bond[i].a2 == id && atom[bond[i].a1 - 1].heavy
3473
              && nb_count < max_neighbors) {
3474
            Result[nb_count++] = bond[i].a1;
3475
          }
3476
  }
6785 bpr 3477
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3478
}
3479
 
14179 bpr 3480
static void get_ndl_neighbors (int *Result, int id)
6785 bpr 3481
{
3482
  int i;
3483
  //neighbor_rec nb_tmp;
3484
  int nb_count = 0;
3485
  /* v0.3i: use max_neighbors instead of a fixed value of 8 */
3486
  //int FORLIM = ndl_n_bonds;
3487
 
3488
  //memset (nb_tmp, 0, sizeof (neighbor_rec));
3489
 
14179 bpr 3490
  for (i = 0; i < ndl_n_bonds; i++) {
3491
    if (ndl_bond[i].a1 == id && nb_count < max_neighbors &&
3492
              ndl_atom[ndl_bond[i].a2 - 1].heavy) {
3493
            nb_count++;
3494
            Result[nb_count - 1] = ndl_bond[i].a2;
3495
          }
3496
    if (ndl_bond[i].a2 == id && nb_count < max_neighbors &&
3497
              ndl_atom[ndl_bond[i].a1 - 1].heavy){
3498
            nb_count++;
3499
            Result[nb_count - 1] = ndl_bond[i].a1;
3500
          }
3501
  }
6785 bpr 3502
  //return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3503
}
3504
 
14179 bpr 3505
static int * get_nextneighbors (int *Result, int id, int prev_id)
6785 bpr 3506
{
3507
  int i;
3508
  neighbor_rec nb_tmp;
3509
  int nb_count = 0;
3510
  int FORLIM;
3511
 
3512
  /* gets all neighbors except prev_id (usually the atom where we came from */
3513
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3514
  FORLIM = n_bonds;
14179 bpr 3515
  for (i = 0; i < FORLIM; i++) {
3516
    if (bond[i].a1 == id && bond[i].a2 != prev_id &&
3517
              nb_count < max_neighbors && atom[bond[i].a2 - 1].heavy) {
3518
            nb_count++;
3519
            nb_tmp[nb_count - 1] = bond[i].a2;
3520
          }
3521
    if (bond[i].a2 == id && bond[i].a1 != prev_id &&
3522
              nb_count < max_neighbors && atom[bond[i].a1 - 1].heavy) {
3523
            nb_count++;
3524
            nb_tmp[nb_count - 1] = bond[i].a1;
3525
          }
3526
  }
6785 bpr 3527
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3528
}
3529
 
14179 bpr 3530
static int * get_ndl_nextneighbors (int *Result, int id, int prev_id)
6785 bpr 3531
{
3532
  int i;
3533
  neighbor_rec nb_tmp;
3534
  int nb_count = 0;
3535
  int FORLIM;
3536
 
3537
  /* gets all neighbors except prev_id (usually the atom where we came from */
3538
  memset (nb_tmp, 0, sizeof (neighbor_rec));
3539
  FORLIM = ndl_n_bonds;
14179 bpr 3540
  for (i = 0; i < FORLIM; i++) {
3541
    if (ndl_bond[i].a1 == id && ndl_bond[i].a2 != prev_id &&
3542
              nb_count < max_neighbors && ndl_atom[ndl_bond[i].a2 - 1].heavy) {
3543
            nb_count++;
3544
            nb_tmp[nb_count - 1] = ndl_bond[i].a2;
3545
          }
3546
    if (ndl_bond[i].a2 == id && ndl_bond[i].a1 != prev_id &&
3547
              nb_count < max_neighbors && ndl_atom[ndl_bond[i].a1 - 1].heavy) {
3548
            nb_count++;
3549
            nb_tmp[nb_count - 1] = ndl_bond[i].a1;
3550
          }
3551
  }
6785 bpr 3552
  return memcpy (Result, nb_tmp, sizeof (neighbor_rec));
3553
}
3554
 
3555
#if 0
3556
static int path_pos (id, a_path) int id;
14179 bpr 3557
  int *a_path;
3558
  {
3559
  /* new version in v0.3l */
3560
  int i;
3561
  int pp = 0;
6785 bpr 3562
 
14179 bpr 3563
  for (i = 1; i <= max_ringsize; i++)
3564
  {
3565
  if (a_path[i - 1] == id)
3566
  {
3567
  pp = i;
3568
  /* p2c: checkmol.pas, line 2620:
3569
  * Warning: Expected a '(', found a semicolon [227]  */
3570
  /* p2c: checkmol.pas, line 2620:
3571
  * Warning: Expected an expression, found a semicolon [227] */
3572
  fflush (0);
3573
  P_ioresult = 0;
3574
  }
3575
  }
3576
  return pp;
3577
  }
6785 bpr 3578
#endif
3579
 
14179 bpr 3580
static int matchpath_pos (int id, int *a_path)
6785 bpr 3581
{
3582
  int i;
3583
  int pp = 0;
3584
 
14179 bpr 3585
  for (i = max_matchpath_length; i >= 1; i--) {
3586
    if (a_path[i - 1] == id)
3587
            pp = i;
3588
  }
6785 bpr 3589
  return pp;
3590
}
3591
 
14179 bpr 3592
static int matchpath_length (int *a_path)
6785 bpr 3593
{
3594
  if (a_path[max_matchpath_length - 1] != 0)
3595
    return max_matchpath_length;
3596
  else
3597
    return (matchpath_pos (0L, a_path) - 1);
3598
}
3599
 
14179 bpr 3600
static int get_ndl_bond (int ba1, int ba2)
6785 bpr 3601
{
3602
  int i;
3603
  int b_id = 0;
3604
  int FORLIM;
3605
 
3606
  if (ndl_n_bonds <= 0)
3607
    return b_id;
3608
  FORLIM = ndl_n_bonds;
14179 bpr 3609
  for (i = 1; i <= FORLIM; i++) {
3610
    if ((ndl_bond[i - 1].a1 == ba1 && ndl_bond[i - 1].a2 == ba2) ||
3611
              (ndl_bond[i - 1].a1 == ba2 && ndl_bond[i - 1].a2 == ba1))
3612
          b_id = i;
3613
  }
6785 bpr 3614
  return b_id;
3615
}
3616
 
14179 bpr 3617
static int ringcompare (int *rp1, int *rp2)
6785 bpr 3618
{
3619
  int i, j;
3620
  int rc = 0;
3621
  int rs1, rs2;
3622
  int n_common = 0;
3623
  int max_cra;
3624
 
3625
  rs1 = path_length (rp1);
3626
  rs2 = path_length (rp2);
3627
  if (rs1 < rs2)
3628
    max_cra = rs1;
3629
  else
3630
    max_cra = rs2;
14179 bpr 3631
  for (i = 0; i < rs1; i++) {
3632
    for (j = 0; j < rs2; j++) {
3633
            if (rp1[i] == rp2[j])
3634
              n_common++;
3635
          }
3636
  }
3637
  if (rs1 == rs2 && n_common == max_cra) {
3638
    rc = 0;
3639
    return rc;
3640
  }
6785 bpr 3641
  if (n_common == 0)
3642
    rc += 8;
14179 bpr 3643
  if (n_common < max_cra) {
3644
    rc += 4;
3645
    return rc;
3646
  }
6785 bpr 3647
  if (rs1 < rs2)
3648
    rc++;
3649
  else
3650
    rc += 2;
3651
  return rc;
3652
}
3653
 
14179 bpr 3654
static boolean rc_identical (int rc_int)
6785 bpr 3655
{
3656
  if (rc_int == 0)
3657
    return true;
3658
  else
3659
    return false;
3660
}
3661
 
14179 bpr 3662
static boolean rc_1in2 (int rc_int)
6785 bpr 3663
{
3664
  if (rc_int & 1)
3665
    return true;
3666
  else
3667
    return false;
3668
}
3669
 
14179 bpr 3670
static boolean rc_2in1 (int rc_int)
6785 bpr 3671
{
3672
  rc_int /= 2;
3673
  if (rc_int & 1)
3674
    return true;
3675
  else
3676
    return false;
3677
}
3678
 
3679
#if 0
14179 bpr 3680
static boolean rc_different (int rc_int)
6785 bpr 3681
{
3682
  rc_int /= 4;
3683
  if (rc_int & 1)
3684
    return true;
3685
  else
3686
    return false;
3687
}
3688
#endif
3689
#if 0
14179 bpr 3690
static boolean rc_independent (int rc_int)
6785 bpr 3691
{
3692
  rc_int /= 8;
3693
  if (rc_int & 1)
3694
    return true;
3695
  else
3696
    return false;
3697
}
3698
#endif
3699
 
14179 bpr 3700
static boolean is_newring (int *n_path)
6785 bpr 3701
{
3702
  int i, j;
3703
  boolean nr = true;
3704
  boolean same_ring;
3705
  ringpath_type tmp_path;
3706
  int rc_result;
3707
  boolean found_ring;
3708
  int pl;                       /* new in v0.3 */
3709
  int FORLIM;
3710
 
3711
  pl = path_length (n_path);    /* new in v0.3 */
3712
  if (n_rings <= 0)
3713
    return true;
14179 bpr 3714
  switch (ringsearch_mode) {
6785 bpr 3715
    case rs_sar:
3716
      found_ring = false;
3717
      i = 0;
14179 bpr 3718
      while (i < n_rings && !found_ring) {
3719
              i++;
3720
              if (pl != ringprop[i - 1].size)   /* compare only rings of same size */
3721
                continue;
3722
              same_ring = true;
3723
              for (j = 0; j < max_ringsize; j++) {
3724
                if (ring[i - 1][j] != n_path[j])
3725
                        same_ring = false;
3726
              }
3727
              if (same_ring) {
3728
                nr = false;
3729
                found_ring = true;
3730
              }
6785 bpr 3731
            }
3732
      break;
3733
 
3734
    case rs_ssr:
3735
      FORLIM = n_rings;
14179 bpr 3736
      for (i = 0; i < FORLIM; i++) {
3737
              for (j = 0; j < max_ringsize; j++)
3738
                tmp_path[j] = ring[i][j];
3739
              rc_result = ringcompare (n_path, tmp_path);
3740
              if (rc_identical (rc_result))
3741
                nr = false;
3742
              if (rc_1in2 (rc_result)) {
6785 bpr 3743
              /* exchange existing ring by smaller one */
14179 bpr 3744
                for (j = 0; j < max_ringsize; j++)
3745
                        ring[i][j] = n_path[j];
3746
                /* update ring property record (new in v0.3) */
3747
                ringprop[i].size = pl;
3748
                nr = false;
3749
        /* p2c: checkmol.pas, line 2841:
3750
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3751
              /*$IFDEF debug */
3752
              /* debugoutput('replacing ring '+inttostr(i)+' by smaller one (ringsize: '+inttostr(path_length(n_path))+')'); */
3753
              /*$ENDIF */
3754
        }
3755
        if (rc_2in1 (rc_result)) {
3756
                  /* new ring contains existing one, but is larger ==> discard */
3757
                nr = false;
3758
              }
6785 bpr 3759
            }
14179 bpr 3760
    break;
3761
  }
6785 bpr 3762
  return nr;
3763
}
3764
 
14179 bpr 3765
static void add_ring (int *n_path)
6785 bpr 3766
{
3767
  /* new in v0.3: store rings in an ordered way (with ascending ring size) */
3768
  int i;
3769
  int j = 0;
3770
  int k, s, pl;
14179 bpr 3771
  /* p2c: checkmol.pas, line 2862:
3772
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3773
  /*$IFDEF debug */
3774
  /*char dstr[256];*/
3775
  int FORLIM;
3776
 
3777
  /*$ENDIF */
3778
  pl = path_length (n_path);
3779
 
3780
  if (pl < 1)
3781
    return;
3782
 
14179 bpr 3783
  if (n_rings >= max_rings) {
3784
    /* p2c: checkmol.pas, line 2906:
3785
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3786
          /*$IFDEF debug
3787
             debugoutput ("max_rings exceeded!");
3788
             $ENDIF */
3789
    return;
3790
  }
6785 bpr 3791
  n_rings++;
3792
 
14179 bpr 3793
  /* p2c: checkmol.pas, line 2871:
3794
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3795
    /*$IFDEF debug */
3796
    /* dstr := '';
3797
       for j := 1 to pl do dstr := dstr + inttostr((n_path[j])) + ' ';
3798
       debugoutput('adding ring '+inttostr(n_rings)+':  '+dstr); */
3799
    /*$ENDIF */
3800
  if (n_rings > 1) {
3801
    FORLIM = n_rings;
3802
    for (i = 1; i < FORLIM; i++) {
3803
            s = ringprop[i - 1].size;
3804
            if (pl >= s)
3805
              j = i;
3806
          }
3807
  }
6785 bpr 3808
  j++;                          /* the next position is ours */
14179 bpr 3809
  if (j < n_rings) {                            /* push up the remaining rings by one position */
3810
    for (k = n_rings; k > j; k--) {
3811
            ringprop[k - 1].size = ringprop[k - 2].size;
3812
            /*ringprop^[k].arom := ringprop^[(k-1)].arom; */
3813
            for (i = 0; i < max_ringsize; i++)
3814
              ring[k - 1][i] = ring[k - 2][i];
3815
          }
3816
  }
6785 bpr 3817
  ringprop[j - 1].size = pl;
14179 bpr 3818
  for (i = 0; i < max_ringsize; i++) {
3819
    ring[j - 1][i] = n_path[i];
3820
    /*inc(atom^[(n_path[i])].ring_count); */
3821
  }
6785 bpr 3822
}
3823
 
3824
#if 0
14179 bpr 3825
static boolean is_ringpath (s_path) int *s_path;
3826
   {
3827
   boolean Result;
3828
   int i, j;
3829
   neighbor_rec nb;
3830
   boolean rp = false;
3831
   boolean new_atom;
3832
   int a_last, pl;
3833
   ringpath_type l_path;
3834
   int FORLIM;
6785 bpr 3835
 
14179 bpr 3836
   /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3837
   memset (nb, 0, sizeof (neighbor_rec));
3838
   memset (l_path, 0, sizeof (ringpath_type));
3839
   pl = path_length (s_path);
3840
   if (pl < 1) {
3841
   /* p2c: checkmol.pas, line 2928:
6785 bpr 3842
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
14179 bpr 3843
     /*$IFDEF debug
6785 bpr 3844
     debugoutput ("Oops! Got zero-length s_path!");
3845
     $ENDIF */
3846
     return Result;
14179 bpr 3847
    }
3848
    for (i = 0; i < pl; i++)
3849
      l_path[i] = s_path[i];
3850
    /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
3851
    if (opt_metalrings == false) {
3852
      if (atom[l_path[pl - 1] - 1].metal){
3853
        /* p2c: checkmol.pas, line 2942:
3854
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3855
        /*$IFDEF debug
3856
        debugoutput ("skipping metal in ring search");
3857
         $ENDIF */
3858
        return false;
3859
      }
3860
    }
3861
    /* check if ring is already closed */
3862
    if (pl > 2 && l_path[pl - 1] == l_path[0]) {
3863
    l_path[pl - 1] = 0;        /* remove last entry (redundant!) */
3864
    order_ringpath (l_path);
3865
    if (is_newring (l_path)) {
3866
      if (n_rings >= max_rings) {
3867
        /* p2c: checkmol.pas, line 2958:
3868
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
3869
        /*$IFDEF debug
3870
        debugoutput ("maximum number of rings exceeded!");
3871
        $ENDIF */
3872
        return false;
3873
      }
3874
      add_ring (l_path);
3875
    }
3876
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3877
    return true;
3878
  }
3879
  /* any other case: ring is not (yet) closed */
3880
  a_last = l_path[pl - 1];
3881
  get_neighbors (nb, a_last);
3882
  if (atom[a_last - 1].neighbor_count <= 1)
3883
    return false;
3884
  if (n_rings >= max_rings)
3885
    /* added in v0.2: check if max_rings is reached **/
3886
  {                          /* if ring is not closed, continue searching */
3887
    return false;
3888
  }
3889
  FORLIM = atom[a_last - 1].neighbor_count;
3890
  for (i = 0; i < FORLIM; i++) {
3891
    new_atom = true;
3892
     for (j = 1; j < pl; j++) {
3893
      if (nb[i] == l_path[j]) {                    /* v0.3k */
3894
       new_atom = false;
3895
       /* p2c: checkmol.pas, line 2982:
3896
       * Warning: Expected a '(', found a semicolon [227] */
3897
       /* p2c: checkmol.pas, line 2982:
3898
       * Warning: Expected an expression, found a semicolon [227] */
3899
       fflush (0);
3900
       P_ioresult = 0;      /* v0.3k */
3901
      }
3902
    }
3903
    /* added in v0.1a: check if max_rings not yet reached */
3904
    /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
3905
    if (new_atom && pl < max_vringsize && n_rings < max_rings) {
3906
      l_path[pl] = nb[i];
3907
      if (pl < max_ringsize - 1)   /* just to be sure */
3908
      l_path[pl + 1] = 0;
3909
      if (is_ringpath (l_path))
3910
       rp = true;
3911
    }
3912
  }
3913
  return rp;
3914
}
6785 bpr 3915
#endif
3916
 
14179 bpr 3917
static boolean is_ringpath (int *s_path)
6785 bpr 3918
{
3919
  int i, j;
3920
  neighbor_rec nb;
3921
  boolean rp = false;
3922
  boolean new_atom;
3923
  int a_last, pl;
3924
  ringpath_type l_path;
3925
  int FORLIM, pl_prev, pl_next, max_ringsize_dec;
3926
 
3927
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
3928
  memset ((void *) nb, 0, sizeof (neighbor_rec));
3929
  memset ((void *) l_path, 0, sizeof (ringpath_type));
3930
  pl = path_length (s_path);
14179 bpr 3931
  if (pl < 1) {
3932
    /* p2c: checkmol.pas, line 2524:
3933
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3934
 
3935
      return false;
3936
    }
3937
 
3938
  pl_prev = pl - 1;
3939
  //memcpy (l_path, s_path, sizeof (ringpath_type));
3940
  memcpy (l_path, s_path, pl * sizeof (int));
3941
 
3942
  /* check if the last atom is a metal and stop if opt_metalrings is not set (v0.3) */
14179 bpr 3943
  if (opt_metalrings == false) {
3944
    if (atom[l_path[pl_prev] - 1].metal) {
3945
    /* p2c: checkmol.pas, line 2538:
3946
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3947
          return false;
14179 bpr 3948
          }
3949
  }
6785 bpr 3950
  /* check if ring is already closed */
14179 bpr 3951
  if (pl > 2 && l_path[pl_prev] == l_path[0]) {
3952
    l_path[pl_prev] = 0;        /* remove last entry (redundant!) */
3953
    order_ringpath (l_path);
3954
    if (is_newring (l_path)) {
3955
            if (n_rings >= max_rings) {
3956
        /* p2c: checkmol.pas, line 2554:
3957
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 3958
              return false;
3959
            }
14179 bpr 3960
            add_ring (l_path);
3961
          }
3962
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 3963
      return true;
14179 bpr 3964
  }
6785 bpr 3965
  /* any other case: ring is not (yet) closed */
3966
  a_last = l_path[pl_prev];
3967
  get_neighbors (nb, a_last);
3968
  if (atom[a_last - 1].neighbor_count <= 1)
3969
    return false;
3970
  if (n_rings >= max_rings)
14179 bpr 3971
    /* added in v0.2: check if max_rings is reached */ {                                /* if ring is not closed, continue searching */
3972
    return false;
3973
  }
6785 bpr 3974
  FORLIM = atom[a_last - 1].neighbor_count;
3975
  pl_next = pl + 1;
3976
  max_ringsize_dec = max_ringsize - 1;
14179 bpr 3977
  for (i = 0; i < FORLIM; i++) {
3978
    new_atom = true;
3979
    for (j = 1; j < pl; j++) {
3980
            if (nb[i] == l_path[j]) {
6785 bpr 3981
              new_atom = false;
3982
              break;
3983
            }
14179 bpr 3984
          }
3985
    /* added in v0.1a: check if max_rings not yet reached */
3986
    /* added in v0.2:  limit ring size to max_vringsize instead of max_ringsize */
3987
    if (new_atom && pl < max_vringsize && n_rings < max_rings) {
3988
            l_path[pl] = nb[i];
3989
            if (pl < max_ringsize_dec)  /* just to be sure */
3990
              l_path[pl_next] = 0;
6785 bpr 3991
 
14179 bpr 3992
            if (max_ringpath_recursion_depth != 0
3993
                && ++recursion_depth > max_ringpath_recursion_depth) {
6785 bpr 3994
#ifndef MAKE_SHARED_LIBRARY
3995
              if (opt_verbose)
3996
#endif
14179 bpr 3997
                    printf ("Warning: max. number of ringpath recursions (%i) reached\n",
3998
                    max_ringpath_recursion_depth);
6785 bpr 3999
              n_rings = max_rings;
4000
              return false;
4001
            }
4002
 
14179 bpr 4003
            /*printf("%i\n",recursion_depth);
4004
            fflush(stdout);*/
6785 bpr 4005
 
14179 bpr 4006
            if (is_ringpath (l_path))
4007
              rp = true;
4008
            /*return true;*/
4009
          }
4010
  }
6785 bpr 4011
  return rp;
4012
}
4013
 
14179 bpr 4014
static boolean is_ringbond (int b_id)
6785 bpr 4015
{
4016
  int i, ra1, ra2;
4017
  neighbor_rec nb;
4018
  ringpath_type search_path;
4019
  boolean rb = false;
4020
  int FORLIM;
4021
 
4022
  recursion_depth = 0;
4023
 
4024
  ra1 = bond[b_id - 1].a1;
4025
  ra2 = bond[b_id - 1].a2;
4026
  memset (nb, 0, sizeof (neighbor_rec));
4027
  memset (search_path, 0, sizeof (ringpath_type));
4028
  get_neighbors (nb, ra2);
4029
  if (atom[ra2 - 1].neighbor_count <= 1 || atom[ra1 - 1].neighbor_count <= 1)
4030
    return false;
4031
  search_path[0] = ra1;
4032
  search_path[1] = ra2;
4033
  FORLIM = atom[ra2 - 1].neighbor_count;
14179 bpr 4034
  for (i = 0; i < FORLIM; i++) {
4035
    if (nb[i] != ra1 && atom[nb[i] - 1].heavy) {
4036
            search_path[2] = nb[i];
4037
            if (is_ringpath (search_path))
4038
              rb = true;
4039
            //return true;
4040
          }
4041
  }
6785 bpr 4042
  return rb;
4043
}
4044
 
14179 bpr 4045
static void chk_ringbonds ()
6785 bpr 4046
{
4047
  int i, a1rc, a2rc;
4048
 
4049
  if (n_bonds < 1)
4050
    return;
4051
 
14179 bpr 4052
  for (i = 0; i < n_bonds; i++) {
4053
    a1rc = atom[bond[i].a1 - 1].ring_count;
4054
    a2rc = atom[bond[i].a2 - 1].ring_count;
4055
    if (n_rings == 0 || (a1rc < n_rings && a2rc < n_rings)) {
4056
            is_ringbond (i + 1);
6785 bpr 4057
          /*inc(bond^[i].ring_count); */
14179 bpr 4058
          }
4059
  }
6785 bpr 4060
}
4061
 
4062
/* v0.3d: moved procedure update_ringcount a bit down */
4063
 
14179 bpr 4064
static int raw_hetbond_count (int a)
6785 bpr 4065
{
4066
  /* new in v0.2j, ignores bond order */
4067
  int i;
4068
  neighbor_rec nb;
4069
  str2 nb_el;
4070
  int hbc = 0;
4071
  int FORLIM;
4072
 
4073
  if (a <= 0 || a > n_atoms)
4074
    return hbc;
4075
  memset (nb, 0, sizeof (neighbor_rec));
4076
  get_neighbors (nb, a);
4077
  if (atom[a - 1].neighbor_count <= 0)
4078
    return hbc;
4079
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4080
  for (i = 0; i < FORLIM; i++) {
4081
    strcpy (nb_el, atom[nb[i] - 1].element);
4082
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /* &&  strcmp (nb_el, "D ") */
4083
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4084
            /* added 'D ' in v0.3n */
4085
          hbc++;
4086
  }
6785 bpr 4087
  return hbc;
4088
}
4089
 
14179 bpr 4090
static int hetbond_count (int a)
6785 bpr 4091
{
4092
  int i;
4093
  neighbor_rec nb;
4094
  str2 nb_el;
4095
  float hbc = 0.0;
4096
  int FORLIM;
4097
 
4098
  if (a <= 0 || a > n_atoms)
4099
    return ((int) floor (hbc + 0.5));
4100
  memset (nb, 0, sizeof (neighbor_rec));
4101
  get_neighbors (nb, a);
4102
  if (atom[a - 1].neighbor_count <= 0)
4103
    return ((int) floor (hbc + 0.5));
4104
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4105
  for (i = 0; i < FORLIM; i++) {
4106
    strcpy (nb_el, atom[nb[i] - 1].element);
4107
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /*&& strcmp (nb_el, "D ") */
4108
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU")) {                        /* added 'D ' in v0.3n */
4109
            if (bond[get_bond (a, nb[i]) - 1].btype == 'S')
4110
              hbc += 1.0;
4111
            if (bond[get_bond (a, nb[i]) - 1].btype == 'A')
4112
              hbc += 1.5;
4113
            if (bond[get_bond (a, nb[i]) - 1].btype == 'D')
4114
              hbc += 2.0;
4115
            if (bond[get_bond (a, nb[i]) - 1].btype == 'T')
4116
              hbc += 3.0;
4117
          }
4118
  }
6785 bpr 4119
  return ((int) floor (hbc + 0.5));
4120
}
4121
 
14179 bpr 4122
static int hetatom_count (int a)
6785 bpr 4123
{
4124
  int i;
4125
  neighbor_rec nb;
4126
  str2 nb_el;
4127
  int hac = 0;
4128
  int FORLIM;
4129
 
4130
  if (a <= 0 || a > n_atoms)
4131
    return hac;
4132
  memset (nb, 0, sizeof (neighbor_rec));
4133
  get_neighbors (nb, a);
4134
  if (atom[a - 1].neighbor_count <= 0)
4135
    return hac;
4136
  FORLIM = atom[a - 1].neighbor_count;
14179 bpr 4137
  for (i = 0; i < FORLIM; i++) {
4138
    strcpy (nb_el, atom[nb[i] - 1].element);
4139
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4140
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4141
              && strcmp (nb_el, "DU"))
4142
            /* added 'D ' in v0.3n */
4143
            hac++;
4144
  }
6785 bpr 4145
  return hac;
4146
}
4147
 
4148
#if 0
14179 bpr 4149
static int ndl_hetbond_count (int a)
6785 bpr 4150
{
4151
  int i;
4152
  neighbor_rec nb;
4153
  str2 nb_el;
4154
  float hbc = 0.0;
4155
  int FORLIM;
4156
 
4157
  if (a <= 0 || a > n_atoms)
4158
    return ((int) floor (hbc + 0.5));
4159
  memset (nb, 0, sizeof (neighbor_rec));
4160
  get_ndl_neighbors (nb, a);
4161
  if (ndl_atom[a - 1].neighbor_count <= 0)
4162
    return ((int) floor (hbc + 0.5));
4163
  FORLIM = ndl_atom[a - 1].neighbor_count;
14179 bpr 4164
  for (i = 0; i < FORLIM; i++) {
4165
    strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4166
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4167
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP")
4168
              && strcmp (nb_el, "DU")) {                        /* added 'D ' in v0.3n */
4169
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'S')
4170
              hbc += 1.0;
4171
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'A')
4172
              hbc += 1.5;
4173
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'D')
4174
              hbc += 2.0;
4175
            if (ndl_bond[get_ndl_bond (a, nb[i]) - 1].btype == 'T')
4176
              hbc += 3.0;
4177
          }
4178
  }
6785 bpr 4179
  return ((int) floor (hbc + 0.5));
4180
}
4181
#endif
4182
 
14179 bpr 4183
static int ndl_hetatom_count (int a)
6785 bpr 4184
{
4185
  int i;
4186
  neighbor_rec nb;
4187
  str2 nb_el;
4188
  int hac = 0;
4189
  int FORLIM;
4190
 
4191
  if (a <= 0 || a > ndl_n_atoms)
4192
    return hac;
4193
  memset (nb, 0, sizeof (neighbor_rec));
4194
  get_ndl_neighbors (nb, a);
4195
  if (ndl_atom[a - 1].neighbor_count <= 0)
4196
    return hac;
4197
  FORLIM = ndl_atom[a - 1].neighbor_count;
14179 bpr 4198
  for (i = 0; i < FORLIM; i++) {                                /* note: query atoms like 'A' should be present only in the needle */
4199
    strcpy (nb_el, ndl_atom[nb[i] - 1].element);
4200
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "A ") && strcmp (nb_el, "H ")    /*&&  strcmp (nb_el, "D ") */
4201
              && strcmp (nb_el, "LP") && strcmp (nb_el, "DU"))
4202
            /* added 'D ' in v0.3n */
4203
          hac++;
4204
  }
6785 bpr 4205
  return hac;
4206
}
4207
 
14179 bpr 4208
static boolean is_oxo_C (int id)
6785 bpr 4209
{
4210
  int i;
4211
  boolean r = false;
4212
  neighbor_rec nb;
4213
  int FORLIM;
4214
 
4215
  memset (nb, 0, sizeof (neighbor_rec));
4216
  if (id < 1 || id > n_atoms)
6786 kbelabas 4217
    return false;
6785 bpr 4218
  get_neighbors (nb, id);
4219
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4220
    return false;
4221
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4222
  for (i = 0; i < FORLIM; i++) {
4223
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4224
              !strcmp (atom[nb[i] - 1].element, "O "))
4225
            /* no N, amidines are different... */
4226
            r = true;
6785 bpr 4227
      /* or
4228
         (atom^[(nb[i])].element = 'S ')  or
4229
         (atom^[(nb[i])].element = 'SE') */
14179 bpr 4230
  }
6785 bpr 4231
  return r;
4232
}
4233
 
14179 bpr 4234
static boolean is_thioxo_C (int id)
6785 bpr 4235
{
4236
  int i;
4237
  boolean r = false;
4238
  neighbor_rec nb;
4239
  int FORLIM;
4240
 
4241
  memset (nb, 0, sizeof (neighbor_rec));
4242
  if (id < 1 || id > n_atoms)
6786 kbelabas 4243
    return false;
6785 bpr 4244
  get_neighbors (nb, id);
4245
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4246
    return false;
4247
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4248
  for (i = 0; i < FORLIM; i++) {
4249
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4250
              (!strcmp (atom[nb[i] - 1].element, "S ") ||
4251
              !strcmp (atom[nb[i] - 1].element, "SE")))
4252
            /* no N, amidines are different... */
4253
          r = true;
4254
  }
6785 bpr 4255
  return r;
4256
}
4257
 
14179 bpr 4258
static boolean is_imino_C (int id)
6785 bpr 4259
{
4260
  int i;
4261
  boolean r = false;
4262
  neighbor_rec nb;
4263
  int FORLIM;
4264
 
4265
  memset (nb, 0, sizeof (neighbor_rec));
4266
  if (id < 1 || id > n_atoms)
6786 kbelabas 4267
    return false;
6785 bpr 4268
  get_neighbors (nb, id);
4269
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4270
    return false;
4271
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4272
  for (i = 0; i < FORLIM; i++) {
4273
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4274
              !strcmp (atom[nb[i] - 1].element, "N "))
4275
            r = true;
4276
  }
6785 bpr 4277
  return r;
4278
}
4279
 
14179 bpr 4280
static boolean is_true_imino_C (int id)
6785 bpr 4281
{
4282
  int i;
4283
  boolean r = true;
4284
  neighbor_rec nb;
4285
  str2 nb_el;
4286
  int a_n = 0;
4287
  int b;                        /* v0.3j */
4288
  int FORLIM;
4289
 
4290
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
4291
  memset (nb, 0, sizeof (neighbor_rec));
4292
  if (id < 1 || id > n_atoms)
6786 kbelabas 4293
    return false;
6785 bpr 4294
  get_neighbors (nb, id);
4295
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4296
    return false;
4297
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4298
  for (i = 0; i < FORLIM; i++) {
4299
    b = get_bond (id, nb[i]);   /* v0.3j */
4300
    if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4301
              !strcmp (atom[nb[i] - 1].element, "N "))
6785 bpr 4302
        /* v0.3j */
14179 bpr 4303
            a_n = nb[i];
4304
  }
6785 bpr 4305
  if (a_n <= 0)
4306
    return false;
4307
  memset (nb, 0, sizeof (neighbor_rec));
4308
  get_neighbors (nb, a_n);
4309
  FORLIM = atom[a_n - 1].neighbor_count;
14179 bpr 4310
  for (i = 0; i < FORLIM; i++) {
4311
    strcpy (nb_el, atom[nb[i] - 1].element);
4312
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4313
            /*&&  strcmp (nb_el, "D ") */ )
4314
            /* v0.3n: D */
4315
            r = false;
4316
  }
6785 bpr 4317
  return r;
4318
}
4319
 
14179 bpr 4320
static boolean is_true_exocyclic_imino_C (int id, int r_id)
6785 bpr 4321
{
4322
  /* v0.3j */
4323
  int i, j;
4324
  boolean r = false;
4325
  neighbor_rec nb;
4326
  ringpath_type testring;
4327
  int ring_size, b, FORLIM;
4328
 
4329
  memset (nb, 0, sizeof (neighbor_rec));
4330
  if (id < 1 || id > n_atoms)
6789 bpr 4331
    return false;
6785 bpr 4332
  get_neighbors (nb, id);
4333
  memset (testring, 0, sizeof (ringpath_type));
4334
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4335
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4336
    testring[j] = ring[r_id - 1][j];
4337
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4338
    return false;
4339
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4340
  for (i = 0; i < FORLIM; i++) {
4341
    b = get_bond (id, nb[i]);
4342
    if (bond[b - 1].btype == 'D' && bond[b - 1].arom == false &&
4343
              !strcmp (atom[nb[i] - 1].element, "N ")) {
4344
            r = true;
4345
            for (j = 0; j < ring_size; j++) {
6785 bpr 4346
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4347
                      r = false;
6785 bpr 4348
            }
14179 bpr 4349
          }
4350
  }
6785 bpr 4351
  return r;
4352
}
4353
 
14179 bpr 4354
static boolean is_exocyclic_imino_C (int id, int r_id)
6785 bpr 4355
{
4356
  int i, j;
4357
  boolean r = false;
4358
  neighbor_rec nb;
4359
  ringpath_type testring;
4360
  int ring_size, FORLIM;
4361
 
4362
  memset (nb, 0, sizeof (neighbor_rec));
4363
  if (id < 1 || id > n_atoms)
6789 bpr 4364
    return false;
6785 bpr 4365
  get_neighbors (nb, id);
4366
  memset (testring, 0, sizeof (ringpath_type));
4367
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4368
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4369
    testring[j] = ring[r_id - 1][j];
4370
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4371
    return false;
4372
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4373
  for (i = 0; i < FORLIM; i++) {
4374
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4375
              !strcmp (atom[nb[i] - 1].element, "N ")) {
4376
            r = true;
4377
            for (j = 0; j < ring_size; j++) {
6785 bpr 4378
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4379
                      r = false;
6785 bpr 4380
            }
14179 bpr 4381
          }
4382
  }
6785 bpr 4383
  return r;
4384
}
4385
 
14179 bpr 4386
static int find_exocyclic_methylene_C (int id, int r_id)
6785 bpr 4387
{
4388
  /* renamed and rewritten in v0.3j */
4389
  int i, j;
4390
  int r = 0;
4391
  neighbor_rec nb;
4392
  ringpath_type testring;
4393
  int ring_size, FORLIM;
4394
 
4395
  memset (nb, 0, sizeof (neighbor_rec));
4396
  if (id < 1 || id > n_atoms)
4397
    return 0;
4398
  get_neighbors (nb, id);
4399
  memset (testring, 0, sizeof (ringpath_type));
4400
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
4401
  for (j = 0; j < ring_size; j++)       /* v0.3j */
4402
    testring[j] = ring[r_id - 1][j];
4403
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
4404
    return r;
4405
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 4406
  for (i = 0; i < FORLIM; i++) {
4407
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
4408
              !strcmp (atom[nb[i] - 1].element, "C ")) {
4409
            r = nb[i];
4410
            for (j = 0; j < ring_size; j++) {
6785 bpr 4411
              if (nb[i] == ring[r_id - 1][j])
14179 bpr 4412
                    r = 0;
6785 bpr 4413
            }
14179 bpr 4414
          }
4415
  }
6785 bpr 4416
  return r;
4417
}
4418
 
14179 bpr 4419
static boolean is_hydroxy (int a_view, int a_ref)
6785 bpr 4420
{
4421
  boolean r = false;
4422
 
14179 bpr 4423
  if (atom[a_view - 1]. heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4424
    if (!strcmp (atom[a_ref - 1].atype, "O3 ") &&
4425
              atom[a_ref - 1].neighbor_count == 1)
4426
            r = true;
4427
  }
6785 bpr 4428
  return r;
4429
}
4430
 
14179 bpr 4431
static boolean is_sulfanyl (int a_view, int a_ref)
6785 bpr 4432
{
4433
  boolean r = false;
4434
 
4435
  if (atom[a_view - 1].
14179 bpr 4436
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4437
    if (!strcmp (atom[a_ref - 1].atype, "S3 ") &&
4438
              atom[a_ref - 1].neighbor_count == 1)
4439
            r = true;
4440
  }
6785 bpr 4441
  return r;
4442
}
4443
 
14179 bpr 4444
static boolean is_amino (int a_view, int a_ref)
6785 bpr 4445
{
4446
  boolean r = false;
4447
 
4448
  if (atom[a_view - 1].
14179 bpr 4449
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')) {
4450
    if ((!strcmp (atom[a_ref - 1].atype, "N3 ") ||
4451
              !strcmp (atom[a_ref - 1].atype, "N3+")) &&
4452
              atom[a_ref - 1].neighbor_count == 1)
4453
            r = true;
6785 bpr 4454
    }
4455
  return r;
4456
}
4457
 
14179 bpr 4458
static boolean is_alkyl (int a_view, int a_ref)
6785 bpr 4459
{
4460
  int i;
4461
  boolean r = false;
4462
  neighbor_rec nb;
4463
  str2 nb_el;
4464
  int het_count = 0;
4465
  int FORLIM;
4466
 
4467
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4468
  if (! (atom[a_view - 1].
4469
      heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
6785 bpr 4470
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4471
      || atom[a_ref - 1].arom != false)
4472
    return false;
4473
  get_nextneighbors (nb, a_ref, a_view);
4474
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4475
  for (i = 0; i <= FORLIM; i++) {
4476
    strcpy (nb_el, atom[nb[i] - 1].element);
4477
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4478
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4479
              && strcmp (nb_el, "LP"))
4480
            /* added 'D ' in v0.3n */
4481
            het_count++;
4482
  }
6785 bpr 4483
  if (het_count <= 1)           /* we consider (e.g.) alkoxyalkyl groups as alkyl */
4484
    r = true;
4485
  return r;
4486
}
4487
 
14179 bpr 4488
static boolean is_true_alkyl (int a_view, int a_ref)
6785 bpr 4489
{
4490
  int i;
4491
  boolean r = false;
4492
  neighbor_rec nb;
4493
  str2 nb_el;
4494
  int het_count = 0;
4495
  int FORLIM;
4496
 
4497
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4498
  if (!(atom[a_view - 1].
6785 bpr 4499
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4500
      || strcmp (atom[a_ref - 1].atype, "C3 ")
4501
      || atom[a_ref - 1].arom != false)
4502
    return false;
4503
  get_nextneighbors (nb, a_ref, a_view);
4504
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4505
  for (i = 0; i <= FORLIM; i++) {
4506
    strcpy (nb_el, atom[nb[i] - 1].element);
4507
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4508
             /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU"))
4509
             /* added 'D ' in v0.3n */
4510
             het_count++;
4511
  }
6785 bpr 4512
  if (het_count == 0)           /* */
4513
    r = true;
4514
  return r;
4515
}
4516
 
14179 bpr 4517
static boolean is_alkenyl (int a_view, int a_ref)
6785 bpr 4518
{
4519
  /* new in v0.3j */
4520
  int i;
4521
  boolean r = false;
4522
  neighbor_rec nb;
4523
  str2 nb_el;
4524
  str3 nb_at;
4525
  int c2_count = 0, het_count = 0;
4526
  int FORLIM;
4527
 
4528
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4529
  if (! (atom[a_view - 1].
6785 bpr 4530
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4531
      || strcmp (atom[a_ref - 1].atype, "C2 ")
14179 bpr 4532
      || atom[a_ref - 1].arom != false) {
4533
    return false;
4534
  }                             /* v0.3k: changed c2_count = 1 into c2_count >= 1 */
6785 bpr 4535
  get_nextneighbors (nb, a_ref, a_view);
4536
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4537
  for (i = 0; i <= FORLIM; i++) {
4538
    strcpy (nb_el, atom[nb[i] - 1].element);
4539
    strcpy (nb_at, atom[nb[i] - 1].atype);
4540
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
4541
            /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
4542
             && strcmp (nb_el, "LP"))
4543
            /* added 'D ' in v0.3n */
4544
            het_count++;
4545
    if (!strcmp (nb_at, "C2 "))
4546
            c2_count++;
4547
  }
6785 bpr 4548
  if (c2_count >= 1 && het_count <= 1)
4549
    /* we consider (e.g.) alkoxyalkenyl groups as alkenyl */
4550
    r = true;
4551
  return r;
4552
}
4553
 
14179 bpr 4554
static boolean is_alkynyl (int a_view, int a_ref)
6785 bpr 4555
{
4556
  /* new in v0.3j */
4557
  int i;
4558
  boolean r = false;
4559
  neighbor_rec nb;
4560
  str3 nb_at;
4561
  int c1_count = 0;
4562
  int FORLIM;
4563
 
4564
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4565
  if (!(atom[a_view - 1].
6785 bpr 4566
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4567
      || strcmp (atom[a_ref - 1].atype, "C1 ")
4568
      || atom[a_ref - 1].arom != false)
4569
    return false;
4570
  get_nextneighbors (nb, a_ref, a_view);
4571
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 4572
  for (i = 0; i <= FORLIM; i++) {
4573
    strcpy (nb_at, atom[nb[i] - 1].atype);
4574
    if (!strcmp (nb_at, "C1 "))
4575
            c1_count++;
4576
  }
6785 bpr 4577
  if (c1_count == 1)
4578
    r = true;
4579
  return r;
4580
}
4581
 
14179 bpr 4582
static boolean is_aryl (int a_view, int a_ref)
6785 bpr 4583
{
4584
  boolean r = false;
4585
 
4586
  if ((atom[a_view - 1].
4587
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S'))
4588
      && !strcmp (atom[a_ref - 1].element, "C ")
4589
      && atom[a_ref - 1].arom == true)
4590
    r = true;
4591
  return r;
4592
}
4593
 
14179 bpr 4594
static boolean is_alkoxy (int a_view, int a_ref)
6785 bpr 4595
{
4596
  boolean r = false;
4597
  neighbor_rec nb;
4598
 
4599
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4600
  if (!(atom[a_view - 1].
6785 bpr 4601
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4602
    return false;
4603
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4604
      || atom[a_ref - 1].neighbor_count != 2)
4605
    return false;
4606
  get_nextneighbors (nb, a_ref, a_view);
4607
  if (is_alkyl (a_ref, nb[0]))
4608
    r = true;
4609
  return r;
4610
}
4611
 
14179 bpr 4612
static boolean is_siloxy (int a_view, int a_ref)
6785 bpr 4613
{
4614
  boolean r = false;
4615
  neighbor_rec nb;
4616
 
4617
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4618
  if (!(atom[a_view - 1].
6785 bpr 4619
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4620
    return false;
4621
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4622
      || atom[a_ref - 1].neighbor_count != 2)
4623
    return false;
4624
  get_nextneighbors (nb, a_ref, a_view);
4625
  if (!strcmp (atom[nb[0] - 1].element, "SI"))
4626
    r = true;
4627
  return r;
4628
}
4629
 
14179 bpr 4630
static boolean is_true_alkoxy (int a_view, int a_ref)
6785 bpr 4631
{
4632
  boolean r = false;
4633
  neighbor_rec nb;
4634
 
4635
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4636
  if (!(atom[a_view - 1].
6785 bpr 4637
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4638
    return false;
4639
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4640
      || atom[a_ref - 1].neighbor_count != 2)
4641
    return false;
4642
  get_nextneighbors (nb, a_ref, a_view);
4643
  if (is_true_alkyl (a_ref, nb[0]))
4644
    r = true;
4645
  return r;
4646
}
4647
 
14179 bpr 4648
static boolean is_aryloxy (int a_view, int a_ref)
6785 bpr 4649
{
4650
  boolean r = false;
4651
  neighbor_rec nb;
4652
 
4653
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4654
  if (!(atom[a_view - 1].
6785 bpr 4655
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4656
    return false;
4657
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4658
      || atom[a_ref - 1].neighbor_count != 2)
4659
    return false;
4660
  get_nextneighbors (nb, a_ref, a_view);
4661
  if (is_aryl (a_ref, nb[0]))
4662
    r = true;
4663
  return r;
4664
}
4665
 
14179 bpr 4666
static boolean is_alkenyloxy (int a_view, int a_ref) {
6785 bpr 4667
  /* v0.3j */
4668
  boolean r = false;
4669
  neighbor_rec nb;
4670
 
4671
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4672
  if (!(atom[a_view - 1].
6785 bpr 4673
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4674
    return false;
4675
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4676
      || atom[a_ref - 1].neighbor_count != 2)
4677
    return false;
4678
  get_nextneighbors (nb, a_ref, a_view);
4679
  if (is_alkenyl (a_ref, nb[0]))
4680
    r = true;
4681
  return r;
4682
}
4683
 
14179 bpr 4684
static boolean is_alkynyloxy (int a_view, int a_ref)
6785 bpr 4685
{
4686
  /* v0.3j */
4687
  boolean r = false;
4688
  neighbor_rec nb;
4689
 
4690
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4691
  if (!(atom[a_view - 1].
6785 bpr 4692
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4693
    return false;
4694
  if (strcmp (atom[a_ref - 1].atype, "O3 ")
4695
      || atom[a_ref - 1].neighbor_count != 2)
4696
    return false;
4697
  get_nextneighbors (nb, a_ref, a_view);
4698
  if (is_alkynyl (a_ref, nb[0]))
4699
    r = true;
4700
  return r;
4701
}
4702
 
14179 bpr 4703
static boolean is_alkylsulfanyl (int a_view, int a_ref)
6785 bpr 4704
{
4705
  boolean r = false;
4706
  neighbor_rec nb;
4707
 
4708
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4709
  if (!(atom[a_view - 1].
6785 bpr 4710
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4711
    return false;
4712
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4713
      || atom[a_ref - 1].neighbor_count != 2)
4714
    return false;
4715
  get_nextneighbors (nb, a_ref, a_view);
4716
  if (is_alkyl (a_ref, nb[0]))
4717
    r = true;
4718
  return r;
4719
}
4720
 
14179 bpr 4721
static boolean is_true_alkylsulfanyl (int a_view, int a_ref)
6785 bpr 4722
{
4723
  boolean r = false;
4724
  neighbor_rec nb;
4725
 
4726
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4727
  if (!(atom[a_view - 1].
6785 bpr 4728
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4729
    return false;
4730
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4731
      || atom[a_ref - 1].neighbor_count != 2)
4732
    return false;
4733
  get_nextneighbors (nb, a_ref, a_view);
4734
  if (is_true_alkyl (a_ref, nb[0]))
4735
    r = true;
4736
  return r;
4737
}
4738
 
14179 bpr 4739
static boolean is_arylsulfanyl (int a_view, int a_ref)
6785 bpr 4740
{
4741
  boolean r = false;
4742
  neighbor_rec nb;
4743
 
4744
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4745
  if (!(atom[a_view - 1].
6785 bpr 4746
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4747
    return false;
4748
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4749
      || atom[a_ref - 1].neighbor_count != 2)
4750
    return false;
4751
  get_nextneighbors (nb, a_ref, a_view);
4752
  if (is_aryl (a_ref, nb[0]))
4753
    r = true;
4754
  return r;
4755
}
4756
 
14179 bpr 4757
static boolean is_alkenylsulfanyl (a_view, a_ref)
6785 bpr 4758
     int a_view, a_ref;
4759
{
4760
  /* v0.3j */
4761
  boolean r = false;
4762
  neighbor_rec nb;
4763
 
4764
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4765
  if (!(atom[a_view - 1].
6785 bpr 4766
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4767
    return false;
4768
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4769
      || atom[a_ref - 1].neighbor_count != 2)
4770
    return false;
4771
  get_nextneighbors (nb, a_ref, a_view);
4772
  if (is_alkenyl (a_ref, nb[0]))
4773
    r = true;
4774
  return r;
4775
}
4776
 
14179 bpr 4777
static boolean is_alkynylsulfanyl (a_view, a_ref)
6785 bpr 4778
     int a_view, a_ref;
4779
{
4780
  /* v0.3j */
4781
  boolean r = false;
4782
  neighbor_rec nb;
4783
 
4784
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4785
  if (!(atom[a_view - 1].
6785 bpr 4786
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4787
    return false;
4788
  if (strcmp (atom[a_ref - 1].atype, "S3 ")
4789
      || atom[a_ref - 1].neighbor_count != 2)
4790
    return false;
4791
  get_nextneighbors (nb, a_ref, a_view);
4792
  if (is_alkynyl (a_ref, nb[0]))
4793
    r = true;
4794
  return r;
4795
}
4796
 
14179 bpr 4797
static boolean is_alkylamino (a_view, a_ref)
6785 bpr 4798
     int a_view, a_ref;
4799
{
4800
  boolean r = false;
4801
  neighbor_rec nb;
4802
  int alkyl_count = 0;
4803
 
4804
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4805
  if (!(atom[a_view - 1].
6785 bpr 4806
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4807
    return false;
4808
  if (strcmp (atom[a_ref - 1].element, "N ")
4809
      || atom[a_ref - 1].neighbor_count != 2)
4810
    return false;
4811
  get_nextneighbors (nb, a_ref, a_view);
4812
  if (is_alkyl (a_ref, nb[0]))
4813
    alkyl_count++;
4814
  if (alkyl_count == 1)
4815
    r = true;
4816
  return r;
4817
}
4818
 
14179 bpr 4819
static boolean is_dialkylamino (a_view, a_ref)
6785 bpr 4820
     int a_view, a_ref;
4821
{
4822
  int i;
4823
  boolean r = false;
4824
  neighbor_rec nb;
4825
  int alkyl_count = 0;
4826
 
4827
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4828
  if (!(atom[a_view - 1].
6785 bpr 4829
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4830
    return false;
4831
  if (strcmp (atom[a_ref - 1].element, "N ")
4832
      || atom[a_ref - 1].neighbor_count != 3)
4833
    return false;
4834
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4835
  for (i = 0; i <= 1; i++) {
4836
    if (is_alkyl (a_ref, nb[i]))
4837
            alkyl_count++;
4838
  }
6785 bpr 4839
  if (alkyl_count == 2)
4840
    r = true;
4841
  return r;
4842
}
4843
 
14179 bpr 4844
static boolean is_arylamino (a_view, a_ref)
6785 bpr 4845
     int a_view, a_ref;
4846
{
4847
  boolean r = false;
4848
  neighbor_rec nb;
4849
  int aryl_count = 0;
4850
 
4851
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4852
  if (!(atom[a_view - 1].
6785 bpr 4853
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4854
    return false;
4855
  if (strcmp (atom[a_ref - 1].element, "N ")
4856
      || atom[a_ref - 1].neighbor_count != 2)
4857
    return false;
4858
  get_nextneighbors (nb, a_ref, a_view);
4859
  if (is_aryl (a_ref, nb[0]))
4860
    aryl_count++;
4861
  if (aryl_count == 1)
4862
    r = true;
4863
  return r;
4864
}
4865
 
14179 bpr 4866
static boolean is_diarylamino (a_view, a_ref)
6785 bpr 4867
     int a_view, a_ref;
4868
{
4869
  int i;
4870
  boolean r = false;
4871
  neighbor_rec nb;
4872
  int aryl_count = 0;
4873
 
4874
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4875
  if (!(atom[a_view - 1].
6785 bpr 4876
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4877
    return false;
4878
  if (strcmp (atom[a_ref - 1].element, "N ")
4879
      || atom[a_ref - 1].neighbor_count != 3)
4880
    return false;
4881
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4882
  for (i = 0; i <= 1; i++) {
4883
    if (is_aryl (a_ref, nb[i]))
4884
            aryl_count++;
4885
  }
6785 bpr 4886
  if (aryl_count == 2)
4887
    r = true;
4888
  return r;
4889
}
4890
 
14179 bpr 4891
static boolean is_alkylarylamino (a_view, a_ref)
6785 bpr 4892
     int a_view, a_ref;
4893
{
4894
  int i;
4895
  boolean r = false;
4896
  neighbor_rec nb;
4897
  int alkyl_count = 0, aryl_count = 0;
4898
 
4899
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4900
  if (!(atom[a_view - 1].
6785 bpr 4901
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4902
    return false;
4903
  if (strcmp (atom[a_ref - 1].element, "N ")
4904
      || atom[a_ref - 1].neighbor_count != 3)
4905
    return false;
4906
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4907
  for (i = 0; i <= 1; i++) {
4908
    if (is_alkyl (a_ref, nb[i]))
4909
            alkyl_count++;
4910
    if (is_aryl (a_ref, nb[i]))
4911
            aryl_count++;
4912
  }
6785 bpr 4913
  if (alkyl_count == 1 && aryl_count == 1)
4914
    r = true;
4915
  return r;
4916
}
4917
 
14179 bpr 4918
static boolean is_C_monosubst_amino (a_view, a_ref)
6785 bpr 4919
     int a_view, a_ref;
4920
{
4921
  /* new in v0.3j */
4922
  boolean r = false;
4923
  neighbor_rec nb;
4924
  int c_count = 0;
4925
 
4926
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4927
  if (! (atom[a_view - 1].
6785 bpr 4928
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4929
    return false;
4930
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4931
      && strcmp (atom[a_ref - 1].atype, "NAM"))
4932
      || atom[a_ref - 1].neighbor_count != 2)
4933
    return false;
4934
  get_nextneighbors (nb, a_ref, a_view);
4935
  if (!strcmp (atom[nb[0] - 1].element, "C "))
4936
    c_count++;
4937
  if (c_count == 1)
4938
    r = true;
4939
  return r;
4940
}
4941
 
14179 bpr 4942
static boolean is_C_disubst_amino (a_view, a_ref)
6785 bpr 4943
     int a_view, a_ref;
4944
{
4945
  /* new in v0.3j */
4946
  int i;
4947
  boolean r = false;
4948
  neighbor_rec nb;
4949
  int b;
4950
  int c_count = 0;
4951
 
4952
  b = get_bond (a_view, a_ref);
4953
  memset (nb, 0, sizeof (neighbor_rec));
4954
  if (!(atom[a_view - 1].heavy && bond[b - 1].btype == 'S' &&
14179 bpr 4955
            bond[b - 1].arom == false))
6785 bpr 4956
    return false;
4957
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4958
      && strcmp (atom[a_ref - 1].atype, "NAM"))
4959
      || atom[a_ref - 1].neighbor_count != 3)
4960
    return false;
4961
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 4962
  for (i = 0; i <= 1; i++) {
4963
    if (!strcmp (atom[nb[i] - 1].element, "C "))
4964
            c_count++;
4965
  }
6785 bpr 4966
  if (c_count == 2)
4967
    r = true;
4968
  return r;
4969
}
4970
 
14179 bpr 4971
static boolean is_subst_amino (a_view, a_ref)
6785 bpr 4972
     int a_view, a_ref;
4973
{
4974
  boolean r = false;
4975
 
4976
  if (is_amino (a_view, a_ref) || is_alkylamino (a_view, a_ref) |
4977
      is_arylamino (a_view, a_ref) || is_dialkylamino (a_view, a_ref) |
4978
      is_alkylarylamino (a_view, a_ref) || is_diarylamino (a_view, a_ref))
4979
    r = true;
4980
  return r;
4981
}
4982
 
14179 bpr 4983
static boolean is_true_alkylamino (a_view, a_ref)
6785 bpr 4984
     int a_view, a_ref;
4985
{
4986
  boolean r = false;
4987
  neighbor_rec nb;
4988
  int alkyl_count = 0;
4989
 
4990
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 4991
  if (!(atom[a_view - 1].
6785 bpr 4992
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
4993
    return false;
4994
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
4995
      && strcmp (atom[a_ref - 1].atype, "N3+"))
4996
      || atom[a_ref - 1].neighbor_count != 2)
4997
    return false;
4998
  get_nextneighbors (nb, a_ref, a_view);
4999
  if (is_true_alkyl (a_ref, nb[0]))
5000
    alkyl_count++;
5001
  if (alkyl_count == 1)
5002
    r = true;
5003
  return r;
5004
}
5005
 
14179 bpr 5006
static boolean is_true_dialkylamino (a_view, a_ref)
6785 bpr 5007
     int a_view, a_ref;
5008
{
5009
  int i;
5010
  boolean r = false;
5011
  neighbor_rec nb;
5012
  int alkyl_count = 0;
5013
 
5014
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5015
  if (!(atom[a_view - 1].
6785 bpr 5016
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5017
    return false;
5018
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5019
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5020
      || atom[a_ref - 1].neighbor_count != 3)
5021
    return false;
5022
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5023
  for (i = 0; i <= 1; i++) {
5024
    if (is_true_alkyl (a_ref, nb[i]))
5025
            alkyl_count++;
5026
  }
6785 bpr 5027
  if (alkyl_count == 2)
5028
    r = true;
5029
  return r;
5030
}
5031
 
5032
#if 0
14179 bpr 5033
static boolean is_true_alkylarylamino (a_view, a_ref)
6785 bpr 5034
     int a_view, a_ref;
5035
{
5036
  int i;
5037
  boolean r = false;
5038
  neighbor_rec nb;
5039
  int alkyl_count = 0, aryl_count = 0;
5040
 
5041
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5042
  if (!(atom[a_view - 1].
6785 bpr 5043
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5044
    return false;
5045
  if ((strcmp (atom[a_ref - 1].atype, "N3 ")
5046
      && strcmp (atom[a_ref - 1].atype, "N3+"))
5047
      || atom[a_ref - 1].neighbor_count != 3)
5048
    return false;
5049
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5050
  for (i = 0; i <= 1; i++) {
5051
    if (is_true_alkyl (a_ref, nb[i]))
5052
            alkyl_count++;
5053
    if (is_aryl (a_ref, nb[i]))
5054
            aryl_count++;
5055
  }
6785 bpr 5056
  if (alkyl_count == 1 && aryl_count == 1)
5057
    r = true;
5058
  return r;
5059
}
5060
#endif
5061
 
14179 bpr 5062
static boolean is_hydroxylamino (a_view, a_ref)
6785 bpr 5063
     int a_view, a_ref;
5064
{
5065
  int i;
5066
  boolean r = false;
5067
  neighbor_rec nb;
5068
  int oh_count = 0, het_count = 0;      /* v0.3k */
5069
  str2 nb_el;                   /* v0.3k */
5070
  int FORLIM;
5071
 
5072
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5073
  if (!(atom[a_view - 1].
6785 bpr 5074
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5075
    return false;
5076
  if (strcmp (atom[a_ref - 1].element, "N ")
5077
      || atom[a_ref - 1].neighbor_count < 2)
5078
    /* v0.3c */
5079
    return false;
5080
  get_nextneighbors (nb, a_ref, a_view);
5081
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5082
  for (i = 0; i <= FORLIM; i++) {                               /* v0.3c */
5083
    if (is_hydroxy (a_ref, nb[i]))
5084
            oh_count++;
5085
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
5086
    if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
5087
              /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
5088
              && strcmp (nb_el, "LP"))
5089
              /* v0.3k */
5090
            het_count++;
6785 bpr 5091
      /* v0.3n: D */
14179 bpr 5092
  }
6785 bpr 5093
  if (oh_count == 1 && het_count == 1)
5094
    r = true;
5095
  return r;
5096
}
5097
 
14179 bpr 5098
static boolean is_nitro (a_view, a_ref)
6785 bpr 5099
     int a_view, a_ref;
5100
{
5101
  int i;
5102
  boolean r = false;
5103
  neighbor_rec nb;
5104
  int o_count = 0, bond_count = 0;
5105
 
5106
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5107
  if (!(atom[a_view - 1].
6785 bpr 5108
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5109
    return false;
5110
  if (strcmp (atom[a_ref - 1].element, "N ")
5111
      || atom[a_ref - 1].neighbor_count != 3)
5112
    return false;
5113
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5114
  for (i = 0; i <= 1; i++) {
5115
    if (!strcmp (atom[nb[i] - 1].element, "O "))
5116
            o_count++;
5117
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S')
5118
            bond_count++;
5119
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
5120
            bond_count += 2;
5121
  }
6785 bpr 5122
  if (o_count == 2 && bond_count >= 3)
5123
    r = true;
5124
  return r;
5125
}
5126
 
14179 bpr 5127
static boolean is_azido (a_view, a_ref)
6785 bpr 5128
     int a_view, a_ref;
5129
{
5130
  boolean r = false;
5131
  neighbor_rec nb;
5132
  int bond_count = 0, n1 = 0, n2 = 0, n3 = 0;
5133
 
14179 bpr 5134
  if (!(atom[a_view - 1].
6785 bpr 5135
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5136
    return false;
5137
  if (strcmp (atom[a_ref - 1].element, "N ")
5138
      || atom[a_ref - 1].neighbor_count != 2)
5139
    return false;
5140
  n1 = a_ref;
5141
  memset (nb, 0, sizeof (neighbor_rec));
5142
  get_nextneighbors (nb, n1, a_view);
14179 bpr 5143
  if (!strcmp (atom[nb[0] - 1].element, "N ")) {
5144
    n2 = nb[0];
5145
    if (bond[get_bond (n1, n2) - 1].btype == 'S')
6785 bpr 5146
            bond_count++;
14179 bpr 5147
    if (bond[get_bond (n1, n2) - 1].btype == 'D')
6785 bpr 5148
            bond_count += 2;
14179 bpr 5149
    if (bond[get_bond (n1, n2) - 1].btype == 'T')
6785 bpr 5150
            bond_count += 3;
14179 bpr 5151
  }
5152
  if (n2 > 0 && atom[n2 - 1].neighbor_count == 2) {
5153
    memset (nb, 0, sizeof (neighbor_rec));
5154
    get_nextneighbors (nb, n2, n1);
5155
    if (!strcmp (atom[nb[0] - 1].element, "N ")){
5156
            n3 = nb[0];
5157
            if (bond[get_bond (n2, n3) - 1].btype == 'S')
5158
              bond_count++;
5159
            if (bond[get_bond (n2, n3) - 1].btype == 'D')
5160
              bond_count += 2;
5161
            if (bond[get_bond (n2, n3) - 1].btype == 'T')
5162
              bond_count += 3;
5163
          }
5164
  }
6785 bpr 5165
  if (n1 > 0 && n2 > 0 && n3 > 0 && atom[n3 - 1].neighbor_count == 1 &&
5166
      bond_count > 3)
5167
    r = true;
5168
  return r;
5169
}
5170
 
14179 bpr 5171
static boolean is_diazonium (a_view, a_ref)
6785 bpr 5172
     int a_view, a_ref;
5173
{
5174
  boolean r = false;
5175
  neighbor_rec nb;
5176
  int bond_count = 0, chg_count = 0, n1 = 0, n2 = 0;
5177
 
14179 bpr 5178
  if (!(atom[a_view - 1].
6785 bpr 5179
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5180
    return false;
5181
  if (strcmp (atom[a_ref - 1].element, "N ")
5182
      || atom[a_ref - 1].neighbor_count != 2)
5183
    return false;
5184
  n1 = a_ref;
5185
  chg_count = atom[n1 - 1].formal_charge;
5186
  memset (nb, 0, sizeof (neighbor_rec));
5187
  get_nextneighbors (nb, n1, a_view);
14179 bpr 5188
  if (!strcmp (atom[nb[0] - 1].element, "N ")) {
5189
    n2 = nb[0];
5190
    chg_count += atom[n2 - 1].formal_charge;
5191
    if (bond[get_bond (n1, n2) - 1].btype == 'S')
5192
            bond_count++;
5193
    if (bond[get_bond (n1, n2) - 1].btype == 'D')
5194
            bond_count += 2;
5195
    if (bond[get_bond (n1, n2) - 1].btype == 'T')
5196
            bond_count += 3;
5197
  }
6785 bpr 5198
  if (n1 > 0 && n2 > 0 && atom[n2 - 1].neighbor_count == 1
5199
      && bond_count >= 2 && chg_count > 0)
5200
    r = true;
5201
  return r;
5202
}
5203
 
14179 bpr 5204
static boolean is_hydroximino_C (id)
6785 bpr 5205
     int id;
5206
{
5207
  int i;
5208
  boolean r = false;
5209
  neighbor_rec nb;
5210
  int a_het = 0;
5211
  int FORLIM;
5212
 
5213
  memset (nb, 0, sizeof (neighbor_rec));
5214
  if (id < 1 || id > n_atoms)
6789 bpr 5215
    return false;
6785 bpr 5216
  get_neighbors (nb, id);
5217
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5218
    return false;
5219
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 5220
  for (i = 0; i < FORLIM; i++) {
5221
    if ((bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5222
              !strcmp (atom[nb[i] - 1].element, "N ")) && (hetbond_count (nb[i]) == 3))
5223
            a_het = nb[i];
5224
  }
6785 bpr 5225
  if (a_het <= 0)
5226
    return false;
5227
  memset (nb, 0, sizeof (neighbor_rec));
5228
  get_neighbors (nb, a_het);
5229
  if (strcmp (atom[a_het - 1].element, "N ")
5230
      || atom[a_het - 1].neighbor_count <= 0)
5231
    return false;
5232
  FORLIM = atom[a_het - 1].neighbor_count;
14179 bpr 5233
  for (i = 0; i < FORLIM; i++) {
5234
    if (is_hydroxy (a_het, nb[i]))
5235
          r = true;
5236
  }
6785 bpr 5237
  return r;
5238
}
5239
 
14179 bpr 5240
static boolean is_hydrazono_C (id)
6785 bpr 5241
     int id;
5242
{
5243
  int i;
5244
  boolean r = false;
5245
  neighbor_rec nb;
5246
  int a_het = 0;
5247
  int FORLIM;
5248
 
5249
  memset (nb, 0, sizeof (neighbor_rec));
5250
  if (id < 1 || id > n_atoms)
6789 bpr 5251
    return false;
6785 bpr 5252
  get_neighbors (nb, id);
5253
  if (strcmp (atom[id - 1].element, "C ") || atom[id - 1].neighbor_count <= 0)
5254
    return false;
5255
  FORLIM = atom[id - 1].neighbor_count;
14179 bpr 5256
  for (i = 0; i < FORLIM; i++) {
5257
    if (bond[get_bond (id, nb[i]) - 1].btype == 'D' &&
5258
              !strcmp (atom[nb[i] - 1].element, "N ")) {
6785 bpr 5259
          /* and
5260
             (hetbond_count(nb[i]) = 3)  */
5261
          a_het = nb[i];
14179 bpr 5262
          }
5263
  }
6785 bpr 5264
  if (a_het <= 0)
5265
    return false;
5266
  memset (nb, 0, sizeof (neighbor_rec));
5267
  get_neighbors (nb, a_het);
5268
  if (strcmp (atom[a_het - 1].element, "N ")
5269
      || atom[a_het - 1].neighbor_count <= 0)
5270
    return false;
5271
  FORLIM = atom[a_het - 1].neighbor_count;
14179 bpr 5272
  for (i = 0; i < FORLIM; i++) {
5273
    if (is_amino (a_het, nb[i]) || is_alkylamino (a_het, nb[i]) |
5274
              is_alkylarylamino (a_het, nb[i]) || is_arylamino (a_het, nb[i]) |
5275
              is_dialkylamino (a_het, nb[i]) || is_diarylamino (a_het, nb[i]))
5276
            r = true;
5277
  }
6785 bpr 5278
  return r;
5279
}
5280
 
14179 bpr 5281
static boolean is_alkoxycarbonyl (a_view, a_ref)
6785 bpr 5282
     int a_view, a_ref;
5283
{
5284
  int i;
5285
  boolean r = false;
5286
  neighbor_rec nb;
5287
 
5288
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5289
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6785 bpr 5290
    return false;
5291
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5292
    return false;
5293
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5294
  for (i = 0; i <= 1; i++) {
5295
    if (is_alkoxy (a_ref, nb[i]))
5296
            r = true;
5297
  }
6785 bpr 5298
  return r;
5299
}
5300
 
14179 bpr 5301
static boolean is_aryloxycarbonyl (a_view, a_ref)
6785 bpr 5302
     int a_view, a_ref;
5303
{
5304
  int i;
5305
  boolean r = false;
5306
  neighbor_rec nb;
5307
 
5308
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5309
  if (!(atom[a_view - 1].
6785 bpr 5310
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5311
    return false;
5312
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5313
    return false;
5314
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5315
  for (i = 0; i <= 1; i++) {
5316
    if (is_aryloxy (a_ref, nb[i]))
5317
            r = true;
5318
  }
6785 bpr 5319
  return r;
5320
}
5321
 
14179 bpr 5322
static boolean is_carbamoyl (a_view, a_ref)
6785 bpr 5323
     int a_view, a_ref;
5324
{
5325
  int i;
5326
  boolean r = false;
5327
  neighbor_rec nb;
5328
 
5329
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5330
  if (!(atom[a_view - 1].
6785 bpr 5331
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5332
    return false;
5333
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5334
    return false;
5335
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5336
  for (i = 0; i <= 1; i++) {
5337
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
5338
            r = true;
5339
  }
6785 bpr 5340
  return r;
5341
}
5342
 
14179 bpr 5343
static boolean is_alkoxythiocarbonyl (a_view, a_ref)
6785 bpr 5344
     int a_view, a_ref;
5345
{
5346
  int i;
5347
  boolean r = false;
5348
  neighbor_rec nb;
5349
 
5350
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5351
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6785 bpr 5352
    return false;
5353
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5354
    return false;
5355
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5356
  for (i = 0; i <= 1; i++) {
5357
    if (is_alkoxy (a_ref, nb[i]))
5358
            r = true;
5359
  }
6785 bpr 5360
  return r;
5361
}
5362
 
14179 bpr 5363
static boolean is_aryloxythiocarbonyl (a_view, a_ref)
6785 bpr 5364
     int a_view, a_ref;
5365
{
5366
  int i;
5367
  boolean r = false;
5368
  neighbor_rec nb;
5369
 
5370
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5371
  if (!(atom[a_view - 1].heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
6785 bpr 5372
    return false;
5373
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5374
    return false;
5375
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5376
  for (i = 0; i <= 1; i++) {
5377
    if (is_aryloxy (a_ref, nb[i]))
5378
            r = true;
5379
  }
6785 bpr 5380
  return r;
5381
}
5382
 
14179 bpr 5383
static boolean is_thiocarbamoyl (a_view, a_ref)
6785 bpr 5384
     int a_view, a_ref;
5385
{
5386
  int i;
5387
  boolean r = false;
5388
  neighbor_rec nb;
5389
 
5390
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5391
  if (!(atom[a_view - 1].
6785 bpr 5392
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5393
    return false;
5394
  if (!(is_thioxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5395
    return false;
5396
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5397
  for (i = 0; i <= 1; i++) {
5398
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
5399
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
5400
            r = true;
5401
  }
6785 bpr 5402
  return r;
5403
}
5404
 
14179 bpr 5405
static boolean is_alkanoyl (a_view, a_ref)
6785 bpr 5406
     int a_view, a_ref;
5407
{
5408
  int i;
5409
  boolean r = false;
5410
  neighbor_rec nb;
5411
 
5412
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5413
  if (!(atom[a_view - 1].
6785 bpr 5414
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5415
    return false;
5416
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5417
    return false;
5418
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5419
  for (i = 0; i <= 1; i++) {
5420
    if (is_alkyl (a_ref, nb[i]))
5421
            r = true;
5422
  }
6785 bpr 5423
  return r;
5424
}
5425
 
14179 bpr 5426
static boolean is_aroyl (a_view, a_ref)
6785 bpr 5427
     int a_view, a_ref;
5428
{
5429
  int i;
5430
  boolean r = false;
5431
  neighbor_rec nb;
5432
 
5433
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5434
  if (!(atom[a_view - 1].
6785 bpr 5435
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5436
    return false;
5437
  if (!(is_oxo_C (a_ref) && atom[a_ref - 1].neighbor_count == 3))
5438
    return false;
5439
  get_nextneighbors (nb, a_ref, a_view);
14179 bpr 5440
  for (i = 0; i <= 1; i++) {
5441
    if (is_aryl (a_ref, nb[i]))
5442
            r = true;
5443
  }
6785 bpr 5444
  return r;
5445
}
5446
 
14179 bpr 5447
static boolean is_acyl (a_view, a_ref)
6785 bpr 5448
     int a_view, a_ref;
5449
{
5450
  boolean r = false;
5451
 
5452
  if (is_alkanoyl (a_view, a_ref) || is_aroyl (a_view, a_ref))
5453
    r = true;
5454
  return r;
5455
}
5456
 
14179 bpr 5457
static boolean is_acyl_gen (a_view, a_ref)
6785 bpr 5458
     int a_view, a_ref;
5459
{
5460
  /* new in v0.3j */
5461
  boolean r = false;
5462
 
5463
  if (is_oxo_C (a_ref))
5464
    r = true;
5465
  return r;
5466
}
5467
 
14179 bpr 5468
static boolean is_acylamino (a_view, a_ref)
6785 bpr 5469
     int a_view, a_ref;
5470
{
5471
  boolean r = false;
5472
  neighbor_rec nb;
5473
  int acyl_count = 0;
5474
 
5475
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5476
  if (!(atom[a_view - 1].
6785 bpr 5477
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5478
    return false;
5479
  if (strcmp (atom[a_ref - 1].element, "N ")
5480
      || atom[a_ref - 1].neighbor_count != 2)
5481
    return false;
5482
  get_nextneighbors (nb, a_ref, a_view);
5483
  if (is_acyl (a_ref, nb[0]))
5484
    acyl_count++;
5485
  if (acyl_count == 1)
5486
    r = true;
5487
  return r;
5488
}
5489
 
14179 bpr 5490
static boolean is_subst_acylamino (a_view, a_ref)
6785 bpr 5491
     int a_view, a_ref;
5492
{
5493
  /* may be substituted _or_ unsubstituted acylamino group! */
5494
  int i;
5495
  boolean r = false;
5496
  neighbor_rec nb;
5497
  int acyl_count = 0;
5498
  int FORLIM;
5499
 
5500
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5501
  if (!(atom[a_view - 1].
6785 bpr 5502
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5503
    return false;
5504
  if (strcmp (atom[a_ref - 1].element, "N ")
5505
      || atom[a_ref - 1].neighbor_count < 2)
5506
    return false;
5507
  get_nextneighbors (nb, a_ref, a_view);
5508
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5509
  for (i = 0; i <= FORLIM; i++) {
5510
    if (is_acyl_gen (a_ref, nb[i]))     /* v0.3j */
5511
            acyl_count++;
5512
  }
6785 bpr 5513
  if (acyl_count > 0)
5514
    r = true;
5515
  return r;
5516
}
5517
 
14179 bpr 5518
static boolean is_hydrazino (a_view, a_ref)
6785 bpr 5519
     int a_view, a_ref;
5520
{
5521
  int i;
5522
  boolean r = false;
5523
  neighbor_rec nb;
5524
  int nr_count = 0;
5525
  int FORLIM;
5526
 
5527
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5528
  if (!(atom[a_view - 1].
6785 bpr 5529
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5530
    return false;
5531
  if (strcmp (atom[a_ref - 1].element, "N ")
5532
      || atom[a_ref - 1].neighbor_count < 2)
5533
    return false;
5534
  get_nextneighbors (nb, a_ref, a_view);
5535
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5536
  for (i = 0; i <= FORLIM; i++) {                               /* fixed in v0.3c */
5537
    if (is_amino (a_ref, nb[i]) || is_subst_amino (a_ref, nb[i]))
5538
            nr_count++;
5539
  }
6785 bpr 5540
  if (nr_count == 1)
5541
    r = true;
5542
  return r;
5543
}
5544
 
14179 bpr 5545
static boolean is_nitroso (a_view, a_ref)
6785 bpr 5546
     int a_view, a_ref;
5547
{
5548
  /* new in v0.3j */
5549
  boolean r = false;
5550
  neighbor_rec nb;
5551
  int o_count = 0;
5552
  int a2;
5553
 
5554
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5555
  if (!(atom[a_view - 1].
6785 bpr 5556
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5557
    return false;
5558
  if (strcmp (atom[a_ref - 1].element, "N ")
5559
      || atom[a_ref - 1].neighbor_count != 2)
5560
    return false;
5561
  get_nextneighbors (nb, a_ref, a_view);
5562
  a2 = nb[0];
5563
  if ((strcmp (atom[a2 - 1].element, "O ") == 0) &
5564
      (bond[get_bond (a_ref, a2) - 1].btype == 'D'))
5565
    o_count++;
5566
  if (o_count == 1)
5567
    r = true;
5568
  return r;
5569
}
5570
 
14179 bpr 5571
static boolean is_subst_hydrazino (a_view, a_ref)
6785 bpr 5572
     int a_view, a_ref;
5573
{
5574
  int i;
5575
  boolean r = false;
5576
  neighbor_rec nb;
5577
  int nr_count = 0;
5578
  int a2, FORLIM;
5579
 
5580
  memset (nb, 0, sizeof (neighbor_rec));
14179 bpr 5581
  if (!(atom[a_view - 1].
6785 bpr 5582
       heavy && (bond[get_bond (a_view, a_ref) - 1].btype == 'S')))
5583
    return false;
5584
  if (strcmp (atom[a_ref - 1].element, "N ")
5585
      || atom[a_ref - 1].neighbor_count < 2)
5586
    return false;
5587
  get_nextneighbors (nb, a_ref, a_view);
5588
  FORLIM = atom[a_ref - 1].neighbor_count - 2;
14179 bpr 5589
  for (i = 0; i <= FORLIM; i++) {
5590
    a2 = nb[i];
5591
    if ((strcmp (atom[a2 - 1].element, "N ") == 0) && (!is_nitroso (a_ref, a2)))
5592
            /* v0.3j */
5593
            nr_count++;
5594
  }
6785 bpr 5595
  if (nr_count == 1)
5596
    r = true;
5597
  return r;
5598
}
5599
 
14179 bpr 5600
static boolean is_cyano (a_view, a_ref)
6785 bpr 5601
     int a_view, a_ref;
5602
{
5603
  boolean r = false;
5604
 
5605
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
14179 bpr 5606
      (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
6785 bpr 5607
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
5608
      atom[a_ref - 1].neighbor_count == 1)
5609
    r = true;
5610
  return r;
5611
}
5612
 
14179 bpr 5613
static boolean is_cyano_c (a_ref)
6785 bpr 5614
     int a_ref;
5615
{
5616
  int i;
5617
  boolean r = false;
5618
  neighbor_rec nb;
5619
  int FORLIM;
5620
 
5621
  memset (nb, 0, sizeof (neighbor_rec));
5622
  if (strcmp (atom[a_ref - 1].atype, "C1 ")
5623
      || atom[a_ref - 1].neighbor_count <= 0)
5624
    return false;
5625
  get_neighbors (nb, a_ref);
5626
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 5627
  for (i = 0; i < FORLIM; i++) {
5628
    if (is_cyano (a_ref, nb[i]))
5629
            r = true;
5630
  }
6785 bpr 5631
  return r;
5632
}
5633
 
14179 bpr 5634
static boolean is_nitrile (a_view, a_ref)
6785 bpr 5635
     int a_view, a_ref;
5636
{
5637
  boolean r = false;
5638
  neighbor_rec nb;
5639
  str2 nb_el;
5640
 
5641
  if (!is_cyano (a_view, a_ref))
5642
    return false;
5643
  if (atom[a_view - 1].neighbor_count == 1
5644
      && atom[a_view - 1].formal_charge == 0)
5645
    return true;
5646
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
5647
  get_nextneighbors (nb, a_view, a_ref);
5648
  strcpy (nb_el, atom[nb[0] - 1].element);
5649
  if (!strcmp (nb_el, "C ")
5650
      || !strcmp (nb_el, "H ") /*|| !strcmp (nb_el, "D ") */ )
5651
    /* v0.3n: D */
5652
    r = true;
5653
  /* HCN is also a nitrile! */
5654
  return r;
5655
}
5656
 
14179 bpr 5657
static boolean is_isonitrile (a_view, a_ref)
6785 bpr 5658
     int a_view, a_ref;
5659
{
5660
  /* only recognized with CN triple bond! */
5661
  boolean r = false;
5662
 
5663
  if (((strcmp (atom[a_view - 1].atype, "C1 ") == 0) &
5664
       (bond[get_bond (a_view, a_ref) - 1].btype == 'T')) &&
5665
      !strcmp (atom[a_ref - 1].atype, "N1 ") &&
5666
      atom[a_ref - 1].neighbor_count == 2
5667
      && atom[a_view - 1].neighbor_count == 1)
5668
    r = true;
5669
  return r;
5670
}
5671
 
14179 bpr 5672
static boolean is_cyanate (a_view, a_ref)
6785 bpr 5673
     int a_view, a_ref;
5674
{
5675
  boolean r = false;
5676
  neighbor_rec nb;
5677
 
5678
  if (!is_cyano (a_view, a_ref))
5679
    return false;
5680
  if (atom[a_view - 1].neighbor_count != 2)
5681
    return false;
5682
  get_nextneighbors (nb, a_view, a_ref);
5683
  if (is_alkoxy (a_view, nb[0]) || is_aryloxy (a_view, nb[0]))
5684
    r = true;
5685
  return r;
5686
}
5687
 
14179 bpr 5688
static boolean is_thiocyanate (a_view, a_ref)
6785 bpr 5689
     int a_view, a_ref;
5690
{
5691
  boolean r = false;
5692
  neighbor_rec nb;
5693
 
5694
  if (!is_cyano (a_view, a_ref))
5695
    return false;
5696
  if (atom[a_view - 1].neighbor_count != 2)
5697
    return false;
5698
  get_nextneighbors (nb, a_view, a_ref);
5699
  if (is_alkylsulfanyl (a_view, nb[0]) || is_arylsulfanyl (a_view, nb[0]))
5700
    r = true;
5701
  return r;
5702
}
5703
 
14179 bpr 5704
static void update_Htotal ()
6785 bpr 5705
{
5706
  int i, j, b_id;
5707
  neighbor_rec nb;
5708
  int single_count, double_count, triple_count, arom_count, total_bonds,
5709
    Htotal, nval;
5710
  /* new in v0.3 */
5711
  boolean diazon = false;       /* new in v0.3j */
5712
  neighbor_rec nb2;             /* new in v0.3j */
5713
  int a1, a2, a3;               /* new in v0.3j */
5714
  int FORLIM, FORLIM1;
5715
 
5716
  if (n_atoms < 1)
5717
    return;
5718
  memset (nb, 0, sizeof (neighbor_rec));
5719
  FORLIM = n_atoms;
14179 bpr 5720
  for (i = 1; i <= FORLIM; i++) {
5721
    single_count = 0;
5722
    double_count = 0;
5723
    triple_count = 0;
5724
    arom_count = 0;
5725
    total_bonds = 0;
5726
    Htotal = 0;
5727
    get_neighbors (nb, i);
5728
    if (atom[i - 1].neighbor_count > 0) {
5729
            /* count single, double, triple, and aromatic bonds to all neighbor atoms */
5730
            FORLIM1 = atom[i - 1].neighbor_count;
5731
            for (j = 0; j < FORLIM1; j++) {
5732
                b_id = get_bond (i, nb[j]);
5733
              if (b_id > 0) {
5734
                      if (bond[b_id - 1].btype == 'S')
5735
                        single_count++;
5736
                      if (bond[b_id - 1].btype == 'D')
5737
                        double_count++;
5738
                      if (bond[b_id - 1].btype == 'T')
5739
                        triple_count++;
5740
                      if (bond[b_id - 1].btype == 'A')
5741
                        arom_count++;
5742
                    }
6785 bpr 5743
            }
14179 bpr 5744
            /*check for diazonium salts */
5745
            a1 = i;
5746
            a2 = nb[0];
5747
            if (!strcmp (atom[a1 - 1].element, "N ") && !strcmp (atom[a2 - 1].element, "N ")) {
5748
              if (atom[a2 - 1].neighbor_count == 2) {
5749
                      get_nextneighbors (nb2, a2, a1);
5750
                      a3 = nb2[0];
5751
                      if ((strcmp (atom[a3 - 1].element, "C ") == 0) && is_diazonium (a3, a2))
5752
                        diazon = true;
5753
                  }
6785 bpr 5754
            }
14179 bpr 5755
          }
5756
    total_bonds = single_count + double_count * 2 + triple_count * 3 + (int) (1.5 * arom_count);
6785 bpr 5757
      /* calculate number of total hydrogens per atom */
5758
      /*nval := nvalences(atom^[i].element);    (* new in v0.3 */
14179 bpr 5759
    nval = atom[i - 1].nvalences;       /* new in v0.3m */
5760
    if (!strcmp (atom[i - 1].element, "P ")) {
5761
            if (total_bonds - atom[i - 1].formal_charge > 3)    /* refined in v0.3n */
5762
              nval = 5;
5763
          }                     /*  */
5764
    if (!strcmp (atom[i - 1].element, "S ")) {                  /* v0.3h */
5765
            if (total_bonds > 2 && atom[i - 1].formal_charge < 1)
5766
              /* updated in v0.3j */
5767
              nval = 4;
5768
            if (total_bonds > 4)        /* this will need some refinement... */
5769
              nval = 6;
5770
          }                     /*  */
5771
    Htotal = nval - total_bonds + atom[i - 1].formal_charge;
5772
    if (diazon)         /* v0.3j */
5773
            Htotal = 0;
5774
    if (Htotal < 0)             /* e.g., N in nitro group */
5775
            Htotal = 0;
6785 bpr 5776
      atom[i - 1].Htot = Htotal;
14179 bpr 5777
    if (atom[i - 1].Hexp > atom[i - 1].Htot)    /* v0.3n; just to be sure... */
5778
            atom[i - 1].Htot = atom[i - 1].Hexp;
5779
  }
6785 bpr 5780
}
5781
 
14179 bpr 5782
static void update_atypes ()
6785 bpr 5783
{
5784
  int i, j, b_id;
5785
  neighbor_rec nb;
5786
  int single_count, double_count, triple_count, arom_count, acyl_count,
5787
    C_count, O_count, total_bonds, NdO_count, NdC_count, Htotal, FORLIM,
5788
    FORLIM1;
5789
 
5790
  if (n_atoms < 1)
5791
    return;
5792
  memset (nb, 0, sizeof (neighbor_rec));
5793
  FORLIM = n_atoms;
14179 bpr 5794
  for (i = 0; i < FORLIM; i++) {
5795
    single_count = 0;
5796
    double_count = 0;
5797
    triple_count = 0;
5798
    arom_count = 0;
5799
    total_bonds = 0;
5800
    acyl_count = 0;
5801
    C_count = 0;
5802
    O_count = 0;
5803
    NdO_count = 0;
5804
    NdC_count = 0;
5805
    Htotal = 0;
5806
    get_neighbors (nb, i + 1);
5807
    if (atom[i].neighbor_count > 0) {
5808
            /* count single, double, triple, and aromatic bonds to all neighbor atoms */
5809
            FORLIM1 = atom[i].neighbor_count;
5810
            for (j = 0; j < FORLIM1; j++) {
6785 bpr 5811
              if (is_oxo_C (nb[j]) || is_thioxo_C (nb[j]))
14179 bpr 5812
          acyl_count++;
6785 bpr 5813
              if (!strcmp (atom[nb[j] - 1].element, "C "))
14179 bpr 5814
                      C_count++;
6785 bpr 5815
              if (!strcmp (atom[nb[j] - 1].element, "O "))
14179 bpr 5816
                      O_count++;
6785 bpr 5817
              b_id = get_bond (i + 1, nb[j]);
14179 bpr 5818
              if (b_id > 0) {
5819
                      if (bond[b_id - 1].btype == 'S')
5820
                        single_count++;
6785 bpr 5821
                      if (bond[b_id - 1].btype == 'D')
14179 bpr 5822
                        double_count++;
5823
                      if (bond[b_id - 1].btype == 'T')
5824
                        triple_count++;
5825
                      if (bond[b_id - 1].btype == 'A'){
5826
                        /* v0.3n: special treatment for acyclic bonds */
5827
                           /* flagged as "aromatic" (in query structures) */
5828
                        if (bond[b_id - 1].ring_count > 0)
5829
                                arom_count++;
5830
                        else
5831
                                double_count++;
5832
                      }
5833
                      if ((!strcmp (atom[i].element, "N ") &&
5834
                          !strcmp (atom[nb[j] - 1].element, "O ")) ||
5835
                          (!strcmp (atom[i].element, "O ") &&
5836
                        !strcmp (atom[nb[j] - 1].element, "N "))) {
5837
                        /* check if it is an N-oxide drawn with a double bond ==> should be N3 */
5838
                        if (bond[b_id - 1].btype == 'D')
5839
                                NdO_count++;
5840
                     }
5841
                    if ((!strcmp (atom[i].element, "N ") &&
5842
                         !strcmp (atom[nb[j] - 1].element, "C ")) ||
5843
                        (!strcmp (atom[i].element, "C ") &&
5844
                         !strcmp (atom[nb[j] - 1].element, "N "))) {
6785 bpr 5845
                      if (bond[b_id - 1].btype == 'D')
14179 bpr 5846
                              NdC_count++;
6785 bpr 5847
                    }
14179 bpr 5848
                  }
5849
          }
6785 bpr 5850
          total_bonds = single_count + double_count * 2 + triple_count * 3 +
5851
            (int) (1.5 * arom_count);
5852
          /* calculate number of total hydrogens per atom */
5853
          /*Htotal := nvalences(atom^[i].element) - total_bonds + atom^[i].formal_charge; */
5854
          Htotal = atom[i].nvalences - total_bonds + atom[i].formal_charge;
5855
          if (Htotal < 0)       /* e.g., N in nitro group */
5856
            Htotal = 0;
5857
          atom[i].Htot = Htotal;
5858
          /* refine atom types, based on bond types */
14179 bpr 5859
          if (!strcmp (atom[i].element, "C ")) {
5860
            if (arom_count > 1)
5861
                    strcpy (atom[i].atype, "CAR");
5862
      if (triple_count == 1 || double_count == 2)
5863
                    strcpy (atom[i].atype, "C1 ");
5864
            if (double_count == 1)
5865
                    strcpy (atom[i].atype, "C2 ");
5866
            if (triple_count == 0 && double_count == 0 && arom_count < 2)
5867
                    strcpy (atom[i].atype, "C3 ");
5868
          }
5869
          if (!strcmp (atom[i].element, "O ")) {
5870
            if (double_count == 1)
5871
                    strcpy (atom[i].atype, "O2 ");
5872
            if (double_count == 0)
5873
                    strcpy (atom[i].atype, "O3 ");
5874
          }
5875
          if (!strcmp (atom[i].element, "N ")) {
5876
            if (total_bonds > 3) {
5877
                    if (O_count == 0) {
6785 bpr 5878
                      if (single_count > 3 ||
14179 bpr 5879
                                (single_count == 2 && double_count == 1 && C_count >= 2))
5880
                              atom[i].formal_charge = 1;
6785 bpr 5881
                    }
14179 bpr 5882
                    else {
6785 bpr 5883
                      if (O_count == 1 && atom[i].formal_charge == 0)   /* v0.3m */
14179 bpr 5884
                              strcpy (atom[i].atype, "N3 ");
5885
                      if (O_count == 2 && atom[i].formal_charge == 0) {
5886
                              if (atom[i].neighbor_count > 2)   /* nitro v0.3o */
5887
                                strcpy (atom[i].atype, "N2 ");
5888
                              if (atom[i].neighbor_count == 2)  /* NO2   v0.3o */
5889
                                strcpy (atom[i].atype, "N1 ");
5890
                            }
6785 bpr 5891
                      /* the rest is left empty, so far.... */
5892
                    }
14179 bpr 5893
                  }
5894
            /* could be an N-oxide -> should be found elsewhere  */
5895
            if (triple_count == 1 || (double_count == 2 && atom[i].neighbor_count == 2))
5896
                    /* v0.3n */
5897
                    strcpy (atom[i].atype, "N1 ");
5898
              if (double_count == 1) {
5899
                      /*if NdC_count > 0 then atom^[i].atype := 'N2 '; */
5900
                      if (NdC_count == 0 && NdO_count > 0 && C_count >= 2)
5901
                        strcpy (atom[i].atype, "N3 ");
5902
                      /* N-oxide is N3 except in hetarene etc. */
5903
                      else
5904
                        strcpy (atom[i].atype, "N2 ");
5905
                    }
6785 bpr 5906
              /* fallback, added in v0.3g  */
5907
              if (arom_count > 1 || atom[i].arom == true)       /* v0.3n */
14179 bpr 5908
                      strcpy (atom[i].atype, "NAR");
5909
              if (triple_count == 0 && double_count == 0) {
5910
                      if (atom[i].formal_charge == 0) {
5911
                        if (acyl_count == 0)
5912
                                strcpy (atom[i].atype, "N3 ");
5913
                        if (acyl_count > 0)
5914
                                strcpy (atom[i].atype, "NAM");
5915
                      }
5916
                      if (atom[i].formal_charge == 1)
5917
                        strcpy (atom[i].atype, "N3+");
5918
                      }
5919
              }
5920
              if (!strcmp (atom[i].element, "P ")) {
5921
                if (single_count > 4)
5922
                        strcpy (atom[i].atype, "P4 ");
5923
                if (single_count <= 4 && double_count == 0)
5924
                        strcpy (atom[i].atype, "P3 ");
5925
                if (double_count == 2)
5926
                        strcpy (atom[i].atype, "P3D");
5927
             }
5928
            if (!strcmp (atom[i].element, "S ")) {
6785 bpr 5929
              if (double_count == 1 && single_count == 0)
14179 bpr 5930
                      strcpy (atom[i].atype, "S2 ");
6785 bpr 5931
              if (double_count == 0)
14179 bpr 5932
                      strcpy (atom[i].atype, "S3 ");
6785 bpr 5933
              if (double_count == 1 && single_count > 0)
14179 bpr 5934
                      strcpy (atom[i].atype, "SO ");
6785 bpr 5935
              if (double_count == 2 && single_count > 0)
14179 bpr 5936
                      strcpy (atom[i].atype, "SO2");
6785 bpr 5937
            }
5938
          /* further atom types should go here */
14179 bpr 5939
          }
5940
  }
6785 bpr 5941
}
5942
 
14179 bpr 5943
static void chk_arom ()
6785 bpr 5944
{
5945
  int i, j, pi_count, ring_size, b, a1, a2;     /* v0.3n */
5946
  ringpath_type testring;
5947
  int a_ref, a_prev, a_next, b_bk, b_fw, b_exo;
5948
  char bt_bk, bt_fw;
5949
  boolean ar_bk, ar_fw, ar_exo; /* new in v0.3 */
5950
  boolean conj_intr, ko, aromatic, aromatic_bt; /* v0.3n */
5951
  int n_db, n_sb, n_ar;
5952
  boolean cumul;
5953
  int exo_mC;                   /* v0.3j */
5954
  int arom_pi_diff;             /* v0.3j */
5955
  int FORLIM;
5956
 
5957
  if (n_rings < 1)
5958
    return;
5959
  FORLIM = n_rings;
5960
  /* first, do a very quick check for benzene, pyridine, etc. */
14179 bpr 5961
  for (i = 0; i < FORLIM; i++) {
5962
    ring_size = ringprop[i].size;
5963
    if (ring_size == 6) {
5964
            memset (testring, 0, sizeof (ringpath_type));
5965
            for (j = 0; j < ring_size; j++)
5966
              testring[j] = ring[i][j];
5967
            cumul = false;
5968
            n_sb = 0;
5969
            n_db = 0;
5970
            n_ar = 0;
5971
            a_prev = testring[ring_size - 1];
5972
            for (j = 1; j <= ring_size; j++) {
6785 bpr 5973
              a_ref = testring[j - 1];
5974
              if (j < ring_size)
14179 bpr 5975
               a_next = testring[j];
6785 bpr 5976
              else
14179 bpr 5977
               a_next = testring[0];
6785 bpr 5978
              b_bk = get_bond (a_prev, a_ref);
5979
              b_fw = get_bond (a_ref, a_next);
5980
              bt_bk = bond[b_bk - 1].btype;
5981
              bt_fw = bond[b_fw - 1].btype;
5982
              if (bt_fw == 'S')
14179 bpr 5983
                n_sb++;
6785 bpr 5984
              if (bt_fw == 'D')
14179 bpr 5985
                n_db++;
6785 bpr 5986
              if (bt_fw == 'A')
14179 bpr 5987
                      n_ar++;
6785 bpr 5988
              if (bt_fw != 'A' && bt_bk == bt_fw)
14179 bpr 5989
                      cumul = true;
6785 bpr 5990
              a_prev = a_ref;
5991
            }
14179 bpr 5992
            if (n_ar == 6 || (n_sb == 3 && n_db == 3 && cumul == false)) {
5993
              /* this ring is aromatic */
6785 bpr 5994
              a_prev = testring[ring_size - 1];
14179 bpr 5995
              for (j = 0; j < ring_size; j++) {
5996
                      a_ref = testring[j];
5997
                      b_bk = get_bond (a_prev, a_ref);
5998
                      bond[b_bk - 1].arom = true;
5999
                      a_prev = a_ref;
6000
                    }
6785 bpr 6001
              ringprop[i].arom = true;
6002
            }
14179 bpr 6003
          }
6004
  }
6785 bpr 6005
  FORLIM = n_rings;
14179 bpr 6006
  for (i = 1; i <= FORLIM; i++) {
6007
    if (ringprop[i - 1].arom == false) {
6008
            /* do the hard work only for those rings which are not yet flagged aromatic */
6009
            memset (testring, 0, sizeof (ringpath_type));
6010
            ring_size = ringprop[i - 1].size;   /* v0.3j */
6011
            for (j = 0; j < ring_size; j++)     /* v0.3j */
6012
              testring[j] = ring[i - 1][j];
6013
            pi_count = 0;
6014
            arom_pi_diff = 0;   /* v0.3j */
6015
      /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6016
            ko = false;
6017
            a_prev = testring[ring_size - 1];
6018
            for (j = 1; j <= ring_size; j++) {
6785 bpr 6019
              a_ref = testring[j - 1];
6020
              if (j < ring_size)
14179 bpr 6021
                a_next = testring[j];
6785 bpr 6022
              else
14179 bpr 6023
                a_next = testring[0];
6785 bpr 6024
              b_bk = get_bond (a_prev, a_ref);
6025
              b_fw = get_bond (a_ref, a_next);
6026
              bt_bk = bond[b_bk - 1].btype;
6027
              bt_fw = bond[b_fw - 1].btype;
6028
              ar_bk = bond[b_bk - 1].arom;
6029
              ar_fw = bond[b_fw - 1].arom;
14179 bpr 6030
              if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == false && ar_fw == false) {
6031
                /* first, assume the worst case (interrupted conjugation) */
6032
                conj_intr = true;
6033
                /* conjugation can be restored by hetero atoms */
6034
                if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6035
                    !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6036
                          !strcmp (atom[a_ref - 1].element, "N ") ||
6037
                          !strcmp (atom[a_ref - 1].element, "SE")) {
6038
                        conj_intr = false;
6039
                        pi_count += 2;  /* lone pair adds for 2 pi electrons */
6040
                      }
6041
                      /* conjugation can be restored by a formal charge at a methylene group */
6785 bpr 6042
                      if (!strcmp (atom[a_ref - 1].element, "C ") &&
14179 bpr 6043
                          atom[a_ref - 1].formal_charge != 0) {
6044
                          conj_intr = false;
6045
                          pi_count -= atom[a_ref - 1].formal_charge;
6046
                          /* neg. charge increases pi_count! */
6047
                      }
6048
                      /* conjugation can be restored by carbonyl groups etc. */
6049
                      if (is_oxo_C (a_ref) || is_thioxo_C (a_ref) |
6050
                          is_exocyclic_imino_C (a_ref, i))
6051
                        conj_intr = false;
6052
                      /* conjugation can be restored by exocyclic C=C double bond, */
6053
                      /* adds 2 pi electrons to 5-membered rings, not to 7-membered rings (CAUTION!) */
6054
                      /* apply only to non-aromatic exocyclic C=C bonds */
6785 bpr 6055
                      exo_mC = find_exocyclic_methylene_C (a_ref, i);   /* v0.3j */
14179 bpr 6056
                      if (exo_mC > 0 && (ring_size & 1)) {              /* v0.3j */
6057
                          b_exo = get_bond (a_ref, exo_mC);     /* v0.3j  */
6058
                          ar_exo = bond[b_exo - 1].arom;
6059
                        if (((ring_size - 1) & 3) == 0) {       /* 5-membered rings and related */
6060
                                conj_intr = false;
6061
                                pi_count += 2;
6062
                              }
6063
                        else {
6064
                                if (!ar_exo)
6065
                                  conj_intr = false;
6066
                              }
6067
                      }
6068
                      /* 7-membered rings and related */
6069
                      /* if conjugation is still interrupted ==> knock-out */
6070
                      if (conj_intr)
6071
                        ko = true;
6785 bpr 6072
                    }
14179 bpr 6073
              else {
6074
                      if (bt_bk == 'S' && bt_fw == 'S' && ar_bk == true && ar_fw == true) {
6075
                        if (!strcmp (atom[a_ref - 1].atype, "O3 ") ||
6076
                                  !strcmp (atom[a_ref - 1].atype, "S3 ") ||
6077
                                  !strcmp (atom[a_ref - 1].element, "N ") ||
6078
                                  !strcmp (atom[a_ref - 1].element, "SE"))
6079
                                pi_count += 2;  /* lone pair adds for 2 pi electrons */
6080
                        if (!strcmp (atom[a_ref - 1].element, "C ") &&
6081
                                  atom[a_ref - 1].formal_charge != 0)
6082
                                pi_count -= atom[a_ref - 1].formal_charge;
6083
                          /* neg. charge increases pi_count! */
6084
                        exo_mC = find_exocyclic_methylene_C (a_ref, i); /* v0.3j */
6085
                        if (exo_mC > 0 && (ring_size & 1))  {   /* v0.3j */
6086
                                b_exo = get_bond (a_ref, exo_mC);       /* v0.3j */
6087
            /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6088
                                if (((ring_size - 1) & 3) == 0)
6089
                                  /* 5-membered rings and related */
6090
                                  pi_count += 2;
6091
                              }
6092
                      }
6093
                      else {
6094
                  pi_count++;   /* v0.3j; adjustment for bridgehead N: see below */
6095
                  if (bt_bk == 'S' && bt_fw == 'S' && ((ar_bk == true && ar_fw == false) ||
6096
                                  (ar_bk == false && ar_fw == true))) {
6097
                                /* v0.3j; if a bridgehead N were not aromatic, it could  */
6098
                                /* contribute 2 pi electrons --> try also this variant */
6099
                                /* (example: CAS 32278-54-9) */
6100
                                if (!strcmp (atom[a_ref - 1].element, "N ")) {
6101
                                  arom_pi_diff++;
6102
                                  /* any other case: increase pi count by one electron */
6103
                                }
6104
                              }
6105
                      }
6785 bpr 6106
                    }
14179 bpr 6107
        /* last command: */
6108
        a_prev = a_ref;
6785 bpr 6109
            }                   /* for j := 1 to ring_size */
14179 bpr 6110
            /* now we can draw our conclusion */
6111
            /*if not ((ko) or (odd(pi_count))) then */
6112
            if (!ko) {
6113
              /* v0.3j; odd pi_count might be compensated by arom_pi_diff */
6114
                          /* apply Hueckel's rule */
6785 bpr 6115
              if (labs (ring_size - pi_count) < 2 &&
14179 bpr 6116
                        (((pi_count - 2) & 3) == 0 || ((pi_count + arom_pi_diff - 2) & 3) == 0)) {
6117
                      /* this ring is aromatic */
6118
                      ringprop[i - 1].arom = true;
6119
                      /* now mark _all_ bonds in the ring as aromatic */
6120
                      a_prev = testring[ring_size - 1];
6121
                      for (j = 0; j < ring_size; j++) {
6122
                        a_ref = testring[j];
6123
                        bond[get_bond (a_prev, a_ref) - 1].arom = true;
6124
                        a_prev = a_ref;
6125
                      }
6785 bpr 6126
                    }
6127
            }
14179 bpr 6128
          }
6129
  }                             /* (for i := 1 to n_rings) */
6785 bpr 6130
  FORLIM = n_bonds;
6131
  /* finally, mark all involved atoms as aromatic */
14179 bpr 6132
  for (i = 0; i < FORLIM; i++) {
6133
    if (bond[i].arom) {
6134
            a1 = bond[i].a1;    /* v0.3n */
6135
            a2 = bond[i].a2;    /* v0.3n */
6136
            atom[a1 - 1].arom = true;
6137
            atom[a2 - 1].arom = true;
6138
            /* v0.3n: update atom types if applicable (C and N) */
6139
            if (!strcmp (atom[a1 - 1].element, "C "))
6140
              strcpy (atom[a1 - 1].atype, "CAR");
6141
            if (!strcmp (atom[a2 - 1].element, "C "))
6142
              strcpy (atom[a2 - 1].atype, "CAR");
6143
            if (!strcmp (atom[a1 - 1].element, "N "))
6144
              strcpy (atom[a1 - 1].atype, "NAR");
6145
            if (!strcmp (atom[a2 - 1].element, "N "))
6146
              strcpy (atom[a2 - 1].atype, "NAR");
6147
          }
6148
  }
6785 bpr 6149
  FORLIM = n_rings;
6150
  /* update aromaticity information in ringprop */
6151
  /* new in v0.3n: accept rings as aromatic if all bonds are of type 'A' */
14179 bpr 6152
  for (i = 0; i < FORLIM; i++) {
6153
    memcpy (testring, ring[i], sizeof (ringpath_type));
6154
    /*ring_size := path_length(testring); */
6155
    ring_size = ringprop[i].size;       /* v0.3j */
6156
    aromatic = true;
6157
    aromatic_bt = true; /* v0.3n */
6158
    a_prev = testring[ring_size - 1];
6159
    for (j = 0; j < ring_size; j++) {
6160
            a_ref = testring[j];
6161
            b = get_bond (a_prev, a_ref);       /* v0.3n */
6162
            if (!bond[b - 1].arom)
6163
              aromatic = false;
6164
            if (bond[b - 1].btype != 'A')       /* v0.3n */
6165
              aromatic_bt = false;
6166
            a_prev = a_ref;
6167
          }
6168
    if (aromatic_bt && !aromatic) {                     /* v0.3n: update aromaticity flag */
6169
            a_prev = testring[ring_size - 1];
6170
            for (j = 0; j < ring_size; j++) {
6785 bpr 6171
              a_ref = testring[j];
6172
              b = get_bond (a_prev, a_ref);
6173
              bond[b - 1].arom = true;
6174
              if (!strcmp (atom[a_ref - 1].element, "C "))
14179 bpr 6175
                      strcpy (atom[a_ref - 1].atype, "CAR");
6785 bpr 6176
              if (!strcmp (atom[a_ref - 1].element, "N "))
14179 bpr 6177
                      strcpy (atom[a_ref - 1].atype, "NAR");
6785 bpr 6178
              a_prev = a_ref;
6179
            }
14179 bpr 6180
            aromatic = true;
6181
          }                     /* end v0.3n block   */
6182
    if (aromatic)
6183
            ringprop[i].arom = true;
6184
    else
6185
            ringprop[i].arom = false;
6186
  }
6785 bpr 6187
}
6188
 
14179 bpr 6189
static void write_mol ()
6785 bpr 6190
{
6191
  int i, j;
6192
  ringpath_type testring;
6193
  int ring_size, FORLIM;
6194
 
6195
  /*aromatic : boolean; */
6196
  /*a_prev, a_ref : integer; */
6197
  if (progmode == pmCheckMol)
6198
    printf ("Molecule name: %s\n", molname);
6199
  else
6200
    printf ("Molecule name (haystack): %s\n", molname);
6201
  printf ("atoms: %d  bonds: %d  rings: %d\n", n_atoms, n_bonds, n_rings);
6202
  if (n_atoms < 1)
6203
    return;
6204
  if (n_bonds < 1)
6205
    return;
6206
  FORLIM = n_atoms;
14179 bpr 6207
  for (i = 1; i <= FORLIM; i++) {
6208
    if (i < 10) putchar (' ');
6209
    if (i < 100) putchar (' ');
6210
    if (i < 1000) putchar (' ');
6211
    printf ("%d %s %s %f %f ",
6785 bpr 6212
              i, atom[i - 1].element, atom[i - 1].atype, atom[i - 1].x,
6213
              atom[i - 1].y);
14179 bpr 6214
    printf ("%f", atom[i - 1].z);
6215
    printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6216
            atom[i - 1].neighbor_count, atom[i - 1].Hexp, atom[i - 1].Htot);
6217
    if (atom[i - 1].formal_charge != 0)
6218
            printf ("  charge: %d", atom[i - 1].formal_charge);
6219
    putchar ('\n');
6220
  }
6785 bpr 6221
  FORLIM = n_bonds;
14179 bpr 6222
  for (i = 1; i <= FORLIM; i++) {
6223
    if (i < 10) putchar (' ');
6224
    if (i < 100) putchar (' ');
6225
    if (i < 1000) putchar (' ');
6226
    printf ("%d %d %d %c", i, bond[i - 1].a1, bond[i - 1].a2, bond[i - 1].btype);
6227
    if (bond[i - 1].ring_count > 0)
6228
            printf (", contained in %d ring(s)", bond[i - 1].ring_count);
6229
    if (bond[i - 1].arom) printf (" (aromatic) ");
6230
    putchar ('\n');
6231
  }
6785 bpr 6232
  if (n_rings <= 0)
6233
    return;
6234
  FORLIM = n_rings;
14179 bpr 6235
  for (i = 0; i < FORLIM; i++) {
6236
    printf ("ring %d: ", i + 1);
6237
    /*aromatic := true; */
6238
    memset (testring, 0, sizeof (ringpath_type));
6239
    ring_size = ringprop[i].size;       /* v0.3j */
6240
    /*for j := 1 to max_ringsize do if ring^[i,j] > 0 then testring[j] := ring^[i,j]; */
6241
    for (j = 0; j < ring_size; j++)     /* v0.3j */
6242
            testring[j] = ring[i][j];
6243
    /*ring_size := path_length(testring); */
6244
    /*a_prev := testring[ring_size]; */
6245
    for (j = 0; j < ring_size; j++) {
6246
            printf ("%d ", testring[j]);
6247
            /*a_ref := testring[j]; */
6248
            /*if (not bond^[get_bond(a_prev,a_ref)].arom) then aromatic := false; */
6249
            /*a_prev := a_ref; */
6250
          }
6251
    /*if aromatic then write(' (aromatic)'); */
6252
    if (ringprop[i].arom) printf (" (aromatic)");
6253
    if (ringprop[i].envelope) printf (" (env)");
6254
    putchar ('\n');
6255
  }
6785 bpr 6256
}
6257
 
14179 bpr 6258
static void write_needle_mol ()
6785 bpr 6259
{
6260
  int i, j;
6261
  ringpath_type testring;
6262
  int ring_size;
6263
  boolean aromatic;
6264
  int a_prev, a_ref, FORLIM;
6265
 
6266
  printf ("Molecule name (needle): %s\n", ndl_molname);
6267
  printf ("atoms: %d  bonds: %d  rings: %d\n",
6268
          ndl_n_atoms, ndl_n_bonds, ndl_n_rings);
6269
  if (ndl_n_atoms < 1)
6270
    return;
6271
  if (ndl_n_bonds < 1)
6272
    return;
6273
  FORLIM = ndl_n_atoms;
14179 bpr 6274
  for (i = 1; i <= FORLIM; i++) {
6275
    if (i < 10) putchar (' ');
6276
    if (i < 100) putchar (' ');
6277
    if (i < 1000) putchar (' ');
6278
    printf ("%d %s %s %f %f ",
6785 bpr 6279
              i, ndl_atom[i - 1].element, ndl_atom[i - 1].atype,
6280
              ndl_atom[i - 1].x, atom[i - 1].y);
14179 bpr 6281
    printf ("%f", ndl_atom[i - 1].z);
6282
    printf ("  (%d heavy-atom neighbors, Hexp: %d Htot: %d)",
6283
            ndl_atom[i - 1].neighbor_count, ndl_atom[i - 1].Hexp,
6284
            ndl_atom[i - 1].Htot);
6285
    if (ndl_atom[i - 1].formal_charge != 0)
6286
            printf ("  charge: %d", ndl_atom[i - 1].formal_charge);
6287
    putchar ('\n');
6288
  }
6785 bpr 6289
  FORLIM = ndl_n_bonds;
14179 bpr 6290
  for (i = 1; i <= FORLIM; i++) {
6291
    if (i < 10) putchar (' ');
6292
    if (i < 100) putchar (' ');
6293
    if (i < 1000) putchar (' ');
6294
    printf ("%d %d %d %c", i, ndl_bond[i - 1].a1, ndl_bond[i - 1].a2,
6785 bpr 6295
              ndl_bond[i - 1].btype);
14179 bpr 6296
    if (ndl_bond[i - 1].ring_count > 0)
6297
            printf (", contained in %d ring(s)", ndl_bond[i - 1].ring_count);
6298
    if (ndl_bond[i - 1].arom)
6299
            printf (" (aromatic) ");
6300
    putchar ('\n');
6301
  }
6785 bpr 6302
  if (ndl_n_rings <= 0)
6303
    return;
6304
  FORLIM = ndl_n_rings;
14179 bpr 6305
  for (i = 0; i < FORLIM; i++) {
6306
    aromatic = true;
6307
    memset (testring, 0, sizeof (ringpath_type));
6308
    for (j = 0; j < max_ringsize; j++) {
6309
            if (ndl_ring[i][j] > 0)
6310
              testring[j] = ndl_ring[i][j];
6311
          }
6312
    ring_size = path_length (testring);
6313
    printf ("ring %d: ", i + 1);
6314
    a_prev = testring[ring_size - 1];
6315
    for (j = 0; j < ring_size; j++) {
6316
            printf ("%d ", testring[j]);
6317
            a_ref = testring[j];
6318
            if (!ndl_bond[get_ndl_bond (a_prev, a_ref) - 1].arom)       /* v0.3k */
6319
              aromatic = false;
6320
            a_prev = a_ref;
6321
          }
6322
    if (aromatic) printf (" (aromatic)");
6323
    putchar ('\n');
6324
  }
6785 bpr 6325
}
6326
 
14179 bpr 6327
static void chk_so2_deriv (a_ref)
6785 bpr 6328
     int a_ref;
6329
{
6330
  int i;
6331
  neighbor_rec nb;
6332
  str2 nb_el;
6333
  int het_count = 0, o_count = 0, or_count = 0, hal_count = 0, n_count = 0,
6334
    c_count = 0;
6335
  int FORLIM;
6336
 
6337
  memset (nb, 0, sizeof (neighbor_rec));
6338
  if (strcmp (atom[a_ref - 1].atype, "SO2"))
6339
    return;
6340
  get_neighbors (nb, a_ref);
6341
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6342
  for (i = 0; i < FORLIM; i++) {
6343
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6344
            strcpy (nb_el, atom[nb[i] - 1].element);
6345
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6346
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
6347
                && strcmp (nb_el, "LP"))
6348
              /* added 'D ' in v0.3n */
6349
              het_count++;
6350
            if (!strcmp (nb_el, "O ")) {
6785 bpr 6351
              o_count++;
6352
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
14179 bpr 6353
                      or_count++;
6785 bpr 6354
            }
14179 bpr 6355
            if (!strcmp (nb_el, "N "))
6356
              n_count++;
6357
            if (!strcmp (nb_el, "C "))
6358
              c_count++;
6359
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6360
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6361
                || !strcmp (nb_el, "AT"))
6362
              hal_count++;
6363
          }
6364
  }
6365
  if (het_count == 2) {                                 /* sulfuric acid derivative */
6366
    fg[fg_sulfuric_acid_deriv - 1] = true;
6367
    if (o_count == 2) {
6368
            if (or_count == 0)
6369
              fg[fg_sulfuric_acid - 1] = true;
6370
            if (or_count == 1)
6371
              fg[fg_sulfuric_acid_monoester - 1] = true;
6372
            if (or_count == 2)
6373
              fg[fg_sulfuric_acid_diester - 1] = true;
6374
          }
6375
    if (o_count == 1) {
6376
            if (or_count == 1 && n_count == 1)
6377
              fg[fg_sulfuric_acid_amide_ester - 1] = true;
6378
            if (or_count == 0 && n_count == 1)
6379
              fg[fg_sulfuric_acid_amide - 1] = true;
6380
          }
6381
    if (n_count == 2)
6382
            fg[fg_sulfuric_acid_diamide - 1] = true;
6383
    if (hal_count > 0)
6384
            fg[fg_sulfuryl_halide - 1] = true;
6385
  }
6386
  if (het_count == 1 && c_count == 1) {                                 /* sulfonic acid derivative */
6387
    fg[fg_sulfonic_acid_deriv - 1] = true;
6388
    if (o_count == 1 && or_count == 0)
6389
            fg[fg_sulfonic_acid - 1] = true;
6390
    if (o_count == 1 && or_count == 1)
6391
            fg[fg_sulfonic_acid_ester - 1] = true;
6392
    if (n_count == 1)
6393
            fg[fg_sulfonamide - 1] = true;
6394
    if (hal_count == 1)
6395
            fg[fg_sulfonyl_halide - 1] = true;
6396
  }
6785 bpr 6397
  if (het_count == 0 && c_count == 2)   /* sulfone */
6398
    fg[fg_sulfone - 1] = true;
6399
}
6400
 
14179 bpr 6401
static void chk_p_deriv (a_ref)
6785 bpr 6402
     int a_ref;
6403
{
6404
  int i;
6405
  neighbor_rec nb;
6406
  str2 nb_el, dbl_het;
6407
  int het_count;
6408
  int oh_count = 0, or_count = 0, hal_count = 0, n_count = 0, c_count = 0;
6409
  int FORLIM;
6410
 
6411
  if (strcmp (atom[a_ref - 1].element, "P "))
6412
    return;
6413
  memset (nb, 0, sizeof (neighbor_rec));
6414
  get_neighbors (nb, a_ref);
6415
  *dbl_het = '\0';
14179 bpr 6416
  /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
6785 bpr 6417
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6418
  for (i = 0; i < FORLIM; i++) {
6419
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'D')
6420
            strcpy (dbl_het, atom[nb[i] - 1].element);
6421
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6422
            strcpy (nb_el, atom[nb[i] - 1].element);
6423
            if (!strcmp (nb_el, "C "))
6424
              c_count++;
6425
            if (is_hydroxy (a_ref, nb[i]))
6426
              oh_count++;
6427
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6428
              or_count++;
6429
            if (!strcmp (nb_el, "N "))
6430
              n_count++;
6431
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6432
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6433
                || !strcmp (nb_el, "AT"))
6434
              hal_count++;
6435
          }
6436
  }
6785 bpr 6437
  het_count = oh_count + or_count + hal_count + n_count;
6438
  if (!strcmp (atom[a_ref - 1].atype, "P3D") ||
14179 bpr 6439
      !strcmp (atom[a_ref - 1].atype, "P4 ")) {
6440
    if (!strcmp (dbl_het, "O ")) {
6441
            if (c_count == 0) {
6785 bpr 6442
              fg[fg_phosphoric_acid_deriv - 1] = true;
6443
              if (oh_count == 3)
14179 bpr 6444
                fg[fg_phosphoric_acid - 1] = true;
6785 bpr 6445
              if (or_count > 0)
14179 bpr 6446
                fg[fg_phosphoric_acid_ester - 1] = true;
6785 bpr 6447
              if (hal_count > 0)
14179 bpr 6448
                fg[fg_phosphoric_acid_halide - 1] = true;
6785 bpr 6449
              if (n_count > 0)
14179 bpr 6450
                fg[fg_phosphoric_acid_amide - 1] = true;
6785 bpr 6451
            }
14179 bpr 6452
            if (c_count == 1) {
6785 bpr 6453
              fg[fg_phosphonic_acid_deriv - 1] = true;
6454
              if (oh_count == 2)
14179 bpr 6455
                fg[fg_phosphonic_acid - 1] = true;
6785 bpr 6456
              if (or_count > 0)
14179 bpr 6457
                fg[fg_phosphonic_acid_ester - 1] = true;
6785 bpr 6458
              /*if (hal_count > 0)  then fg[fg_phosphonic_acid_halide] := true;             */
6459
              /*if (n_count > 0)    then fg[fg_phosphonic_acid_amide]  := true; */
6460
            }
14179 bpr 6461
            if (c_count == 3)
6462
              fg[fg_phosphinoxide - 1] = true;
6463
          }
6464
    if (!strcmp (dbl_het, "S ")) {
6465
      if (c_count == 0) {
6466
        fg[fg_thiophosphoric_acid_deriv - 1] = true;
6467
        if (oh_count == 3)
6468
            fg[fg_thiophosphoric_acid - 1] = true;
6469
        if (or_count > 0)
6470
            fg[fg_thiophosphoric_acid_ester - 1] = true;
6471
        if (hal_count > 0)
6472
            fg[fg_thiophosphoric_acid_halide - 1] = true;
6473
        if (n_count > 0)
6474
            fg[fg_thiophosphoric_acid_amide - 1] = true;
6475
      }
6785 bpr 6476
    }
14179 bpr 6477
  }
6785 bpr 6478
  /*  if (atom^[a_ref].atype = 'P4 ') then fg[fg_phosphoric_acid_deriv] := true; */
6479
  if (strcmp (atom[a_ref - 1].atype, "P3 "))    /* changed P3D into P3 in v0.3b */
6480
    return;
6481
  if (c_count == 3 && het_count == 0)
6482
    fg[fg_phosphine - 1] = true;
6483
  if (c_count == 3 && oh_count == 1)
6484
    fg[fg_phosphinoxide - 1] = true;
6485
}
6486
 
14179 bpr 6487
static void chk_b_deriv (a_ref)
6785 bpr 6488
     int a_ref;
6489
{
6490
  int i;
6491
  neighbor_rec nb;
6492
  str2 nb_el;
6493
  int het_count = 0, oh_count = 0, or_count = 0, hal_count = 0, n_count = 0,
6494
    c_count = 0;
6495
  int FORLIM;
6496
 
6497
  if (strcmp (atom[a_ref - 1].element, "B "))
6498
    return;
6499
  memset (nb, 0, sizeof (neighbor_rec));
6500
  get_neighbors (nb, a_ref);
6501
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6502
  for (i = 0; i < FORLIM; i++) {
6503
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6504
            strcpy (nb_el, atom[nb[i] - 1].element);
6505
            if (!strcmp (nb_el, "C "))
6506
              c_count++;
6507
            else
14249 bpr 6508
              if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  && strcmp (nb_el, "LP"))
14179 bpr 6509
                /* v0.3n: D */
14249 bpr 6510
                het_count++;
6511
            if (is_hydroxy (a_ref, nb[i]))
6512
              oh_count++;
6513
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6514
              /* fixed in v0.3b */
6515
              or_count++;
6516
            if (!strcmp (nb_el, "N "))
6517
              n_count++;
6518
            if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6519
                !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6520
                || !strcmp (nb_el, "AT"))
6521
              hal_count++;
14179 bpr 6522
          }
6523
  }
6785 bpr 6524
  het_count = oh_count + or_count + hal_count + n_count;
6525
  /* fixed in v0.3b */
6526
  if (c_count != 1 || het_count != 2)
6527
    return;
6528
  fg[fg_boronic_acid_deriv - 1] = true;
6529
  if (oh_count == 2)
6530
    fg[fg_boronic_acid - 1] = true;
6531
  if (or_count > 0)
6532
    fg[fg_boronic_acid_ester - 1] = true;
6533
}
6534
 
14179 bpr 6535
static void chk_ammon (a_ref)
6785 bpr 6536
     int a_ref;
6537
{
6538
  int i;
6539
  neighbor_rec nb;
6540
  str2 nb_el;
6541
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
6542
  char bt;                      /* v0.3k */
6543
  float bo_sum = 0.0;
6544
  boolean ha;
6545
  int FORLIM;
6546
 
6547
  memset (nb, 0, sizeof (neighbor_rec));
6548
  if (strcmp (atom[a_ref - 1].atype, "N3+")
6549
      && atom[a_ref - 1].formal_charge == 0)
6550
    return;
6551
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
6552
    return;
6553
  get_neighbors (nb, a_ref);
6554
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6555
  for (i = 0; i < FORLIM; i++) {
6556
    bt = bond[get_bond (a_ref, nb[i]) - 1].btype;       /* v0.3k */
6557
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
6558
    ha = atom[nb[i] - 1].heavy; /* v0.3k */
6559
    if (bt == 'S') {
6560
            if (ha)
6561
              bo_sum += 1.0;
6562
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6563
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")) {
6564
                /* added 'D ' in v0.3n */
6785 bpr 6565
              het_count++;
14179 bpr 6566
              if (!strcmp (nb_el, "O ")) {
6567
                      o_count++;
6568
                      if (atom[nb[i] - 1].neighbor_count > 1)
6569
                        or_count++;
6570
                    }
6785 bpr 6571
            }
14179 bpr 6572
            if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
6573
                is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
6574
              /* v0.3k */
6575
              r_count++;
6576
          }
6577
    if (bt == 'D') {
6578
            if (ha)
6579
              bo_sum += 2.0;
6580
            if (strcmp (nb_el, "C ")) {
6785 bpr 6581
              het_count += 2;
6582
              if (!strcmp (nb_el, "O "))
14179 bpr 6583
                      o_count += 2;
6785 bpr 6584
            }
14179 bpr 6585
            if (!strcmp (nb_el, "C "))
6586
              r_count++;
6587
          }
6588
    if (bt == 'A' && ha)
6589
            bo_sum += 1.5;
6590
  }                             /* v0.3k: corrected end of "for ..." loop */
6785 bpr 6591
  if (het_count == 0 && r_count == 4)
6592
    fg[fg_quart_ammonium - 1] = true;
6593
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
6594
    return;
6595
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
6596
    fg[fg_n_oxide - 1] = true;  /* finds only aliphatic N-oxides! */
6597
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
6598
      atom[a_ref - 1].arom == true)
6599
    fg[fg_quart_ammonium - 1] = true;
6600
}
6601
 
14179 bpr 6602
static void swap_atoms (a1, a2)
6785 bpr 6603
     int *a1, *a2;
6604
{
6605
  int a_tmp;
6606
 
6607
  a_tmp = *a1;
6608
  *a1 = *a2;
6609
  *a2 = a_tmp;
6610
}
6611
 
14179 bpr 6612
static void orient_bond (a1, a2)
6785 bpr 6613
     int *a1, *a2;
6614
{
6615
  str2 a1_el, a2_el;
6616
 
6617
  strcpy (a1_el, atom[*a1 - 1].element);
6618
  strcpy (a2_el, atom[*a2 - 1].element);
6619
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
6620
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
6621
    /* v0.3n: D */
6622
    return;
6623
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
6624
    swap_atoms (a1, a2);
14179 bpr 6625
  if (!strcmp (a2_el, a1_el)) {
6626
    if (hetbond_count (*a1) > hetbond_count (*a2))
6785 bpr 6627
            swap_atoms (a1, a2);
14179 bpr 6628
  }
6629
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el)) {
6630
    if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O ")) {
6631
            if (!strcmp (a1_el, "O "))
6632
              swap_atoms (a1, a2);
6633
          }
6634
  }
6635
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el)) {
6785 bpr 6636
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
14179 bpr 6637
              atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
6638
          swap_atoms (a1, a2);
6639
  }
6785 bpr 6640
}
6641
 
14179 bpr 6642
static void chk_imine (a_ref, a_view)
6785 bpr 6643
     int a_ref, a_view;
6644
{
6645
  /* a_ref = C, a_view = N */
6646
  int i;
6647
  neighbor_rec nb;
6648
  str2 nb_el;
6788 kbelabas 6649
  int a_het = 0, a_c;
6785 bpr 6650
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
6651
  int FORLIM;
6652
 
6653
  /* v0.3k */
14179 bpr 6654
  if (atom[a_view - 1].neighbor_count == 1) {
6785 bpr 6655
      if (atom[a_ref - 1].arom == false)
6656
        fg[fg_imine - 1] = true;
6657
      return;
6658
    }
6659
  memset (nb, 0, sizeof (neighbor_rec));
6660
  get_neighbors (nb, a_view);
6661
  if (atom[a_view - 1].neighbor_count <= 1)
6662
    return;
6663
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6664
  for (i = 0; i < FORLIM; i++) {
6665
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')){
6666
            strcpy (nb_el, atom[nb[i] - 1].element);
6667
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6668
              a_c = nb[i];
6669
              c_count++;
6670
            }
14179 bpr 6671
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")) {
6785 bpr 6672
              a_het = nb[i];
6673
              het_count++;
6674
            }
14179 bpr 6675
            if ((!strcmp (nb_el, "O ")
6785 bpr 6676
               && atom[nb[i] - 1].neighbor_count ==
6677
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
14179 bpr 6678
              /* v0.3k */
6679
              o_count++;
6680
          }
6681
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')){
6682
      /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
6683
            strcpy (nb_el, atom[nb[i] - 1].element);
6684
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ") || !strcmp (nb_el, "S ")) {
6785 bpr 6685
              a_het = nb[i];    /* v0.3m */
6686
              het_count++;
6687
            }
14179 bpr 6688
            if ((!strcmp (nb_el, "O ")
6689
                && atom[nb[i] - 1].neighbor_count == 1) &&
6690
                  (bond[get_bond (a_view, nb[i]) - 1].arom == false))
6691
              /* v0.3k */
6692
              o_count++;
6693
          }
6694
  }
6695
  if (c_count == 1) {
6696
    if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
6697
              is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
6698
              && atom[a_ref - 1].arom == false && het_count == 0)
6785 bpr 6699
            /* v0.3k */
14179 bpr 6700
            fg[fg_imine - 1] = true;
6701
  }
6702
  if (het_count == 1) {
6703
    strcpy (nb_el, atom[a_het - 1].element);
6704
    if (!strcmp (nb_el, "O ")) {
6705
            if (is_hydroxy (a_view, a_het))
6706
              fg[fg_oxime - 1] = true;
6785 bpr 6707
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
6708
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
6709
            fg[fg_oxime_ether - 1] = true;
14179 bpr 6710
          }
6711
    if (!strcmp (nb_el, "N ")) {
6712
            if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
6713
                is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,a_het) |
6714
                is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
6715
              fg[fg_hydrazone - 1] = true;
6716
            else {
6785 bpr 6717
              memset (nb, 0, sizeof (neighbor_rec));
6718
              get_neighbors (nb, a_het);
14179 bpr 6719
              if (atom[a_het - 1].neighbor_count > 1) {
6720
                      FORLIM = atom[a_het - 1].neighbor_count;
6721
                      for (i = 0; i < FORLIM; i++) {
6722
                        if (nb[i] != a_view) {
6723
                                if (is_carbamoyl (a_het, nb[i]))
6724
                                  fg[fg_semicarbazone - 1] = true;
6725
                                if (is_thiocarbamoyl (a_het, nb[i]))
6726
                                  fg[fg_thiosemicarbazone - 1] = true;
6727
                              }
6728
                      }
6785 bpr 6729
                    }
6730
            }
14179 bpr 6731
          }
6732
  }                             /* v0.3k: nitro groups in "azi" form */
6785 bpr 6733
  /* check for semicarbazone or thiosemicarbazone */
6734
  if (het_count == 2 && o_count == 2)
6735
    fg[fg_nitro_compound - 1] = true;
6736
}
6737
 
14179 bpr 6738
static void chk_carbonyl_deriv (a_view, a_ref)
6785 bpr 6739
     int a_view, a_ref;
6740
{
6741
  /* a_view = C */
6742
  int i;
6743
  neighbor_rec nb;
6744
  str2 nb_el;
6745
  int c_count = 0, cn_count = 0;
6746
  char bt;                      /* new in v0.3b */
6747
  int n_db = 0;                 /* new in v0.3b */
6748
  int FORLIM;
6749
 
6750
  memset (nb, 0, sizeof (neighbor_rec));
6751
  get_neighbors (nb, a_view);
6752
  FORLIM = atom[a_view - 1].neighbor_count;
6753
  /* new in v0.3b */
14179 bpr 6754
  for (i = 0; i < FORLIM; i++) {
6755
    bt = bond[get_bond (a_view, nb[i]) - 1].btype;
6756
    if (bt == 'S') {
6757
            strcpy (nb_el, atom[nb[i] - 1].element);
6758
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6759
              if (is_cyano_c (nb[i]))
14179 bpr 6760
                      cn_count++;
6785 bpr 6761
              else
14179 bpr 6762
                      c_count++;
6785 bpr 6763
            }
14179 bpr 6764
          }
6765
    else {
6766
            if (bt == 'D')
6767
              n_db++;
6768
          }
6769
  }
6785 bpr 6770
  /* new in v0.3b */
14179 bpr 6771
  if (is_oxo_C (a_view)) {
6772
    fg[fg_carbonyl - 1] = true;
6773
    if (c_count + cn_count < 2) {                       /* new in v0.3b (detection of ketenes) */
6774
            if (n_db <= 1)
6775
              fg[fg_aldehyde - 1] = true;
6776
            else
6777
              fg[fg_ketene - 1] = true;
6778
          }
6779
    if (c_count == 2) {
6780
            if (atom[a_view - 1].arom)
6781
              fg[fg_oxohetarene - 1] = true;
6782
            else
6783
              fg[fg_ketone - 1] = true;
6784
          }
6785
    if (cn_count > 0)
6786
            fg[fg_acyl_cyanide - 1] = true;
6787
  }
6788
  if (is_thioxo_C (a_view)) {
6789
    fg[fg_thiocarbonyl - 1] = true;
6790
    if (c_count < 2)
6791
            fg[fg_thioaldehyde - 1] = true;
6792
    if (c_count == 2) {
6793
            if (atom[a_view - 1].arom)
6794
              fg[fg_thioxohetarene - 1] = true;
6795
            else
6796
              fg[fg_thioketone - 1] = true;
6797
          }
6798
  }
6785 bpr 6799
  if (is_imino_C (a_view))
6800
    chk_imine (a_view, a_ref);
6801
}
6802
 
14179 bpr 6803
static void chk_carboxyl_deriv (a_view, a_ref)
6785 bpr 6804
     int a_view, a_ref;
6805
{
6806
  int i;
6807
  neighbor_rec nb;
6808
  str2 nb_el;
6809
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 6810
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 6811
 
6812
  memset (nb, 0, sizeof (neighbor_rec));
6813
  get_neighbors (nb, a_view);
6814
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6815
  for (i = 0; i < FORLIM; i++) {
6816
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
6817
            strcpy (nb_el, atom[nb[i] - 1].element);
6818
            if (strcmp (nb_el, "C ")) {
6819
              if (!strcmp (nb_el, "O ")) {
6820
                      o_count++;
6821
                      a_o = nb[i];
6822
                    }
6823
              if (!strcmp (nb_el, "N ")) {
6824
                      n_count++;
6825
                      a_n = nb[i];
6826
                    }
6827
              if (!strcmp (nb_el, "S ")) {
6828
                      s_count++;
6829
                      a_s = nb[i];
6830
                    }
6785 bpr 6831
            }
14179 bpr 6832
          }
6833
  }
6834
  if (is_oxo_C (a_view)) {
6835
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
6836
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
6837
              fg[fg_carboxylic_acid_deriv - 1] = true;
6838
            if (is_hydroxy (a_view, a_o)) {
6785 bpr 6839
              if (atom[a_o - 1].formal_charge == 0)
14179 bpr 6840
                      fg[fg_carboxylic_acid - 1] = true;
6785 bpr 6841
              if (atom[a_o - 1].formal_charge == -1)
14179 bpr 6842
                      fg[fg_carboxylic_acid_salt - 1] = true;
6785 bpr 6843
            }
14179 bpr 6844
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
6845
                is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o)) {
6785 bpr 6846
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
14179 bpr 6847
                      fg[fg_carboxylic_acid_ester - 1] = true;
6848
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
6849
                      if (bond[get_bond (a_view, a_o) - 1].arom == true) {
6850
                        /*fg[fg_lactone_heteroarom] := true else fg[fg_lactone] := true; */
6851
                        fg[fg_oxohetarene - 1] = true;
6852
                      }
6853
                    else
6854
                      fg[fg_lactone - 1] = true;
6785 bpr 6855
                    }
6856
            }
14179 bpr 6857
          }
6858
    if (n_count == 1) {
6859
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6860
              fg[fg_carboxylic_acid_deriv - 1] = true;
6861
            else {
6785 bpr 6862
              /*fg[fg_lactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6863
              fg[fg_oxohetarene - 1] = true;
6864
            }
14179 bpr 6865
            if (is_amino (a_view, a_n) || (!strcmp (atom[a_n - 1].atype, "NAM")
6866
                      && atom[a_n - 1].neighbor_count == 1)) {
6785 bpr 6867
              fg[fg_carboxylic_acid_amide - 1] = true;
6868
              fg[fg_carboxylic_acid_prim_amide - 1] = true;
6869
            }
14179 bpr 6870
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6871
            if (is_C_monosubst_amino (a_view, a_n) &
6872
                (!is_subst_acylamino (a_view, a_n))) {                  /* v0.3j */
6785 bpr 6873
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6874
                      fg[fg_carboxylic_acid_amide - 1] = true;
6785 bpr 6875
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6876
                      fg[fg_carboxylic_acid_sec_amide - 1] = true;
6877
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6878
                      if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6879
                        /*fg[fg_lactam_heteroarom]    := true else  */
6880
                        fg[fg_oxohetarene - 1] = true;
6881
                      }
6882
                      else
6883
                        fg[fg_lactam - 1] = true;
6785 bpr 6884
                    }
6885
            }
14179 bpr 6886
            /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6887
            /*   (is_diarylamino(a_view,a_n)) then  */
6888
            if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6889
              /* v0.3j */
6785 bpr 6890
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6891
                fg[fg_carboxylic_acid_amide - 1] = true;
6785 bpr 6892
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6893
                fg[fg_carboxylic_acid_tert_amide - 1] = true;
6894
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6895
                if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6896
                        /*fg[fg_lactam_heteroarom]    := true else  */
6897
                        fg[fg_oxohetarene - 1] = true;
6898
                      }
6899
                      else
6900
                        fg[fg_lactam - 1] = true;
6785 bpr 6901
                    }
6902
            }
14179 bpr 6903
            if (is_hydroxylamino (a_view, a_n))
6904
              fg[fg_hydroxamic_acid - 1] = true;
6905
            if (is_hydrazino (a_view, a_n))
6906
              fg[fg_carboxylic_acid_hydrazide - 1] = true;
6907
            if (is_azido (a_view, a_n))
6908
              fg[fg_carboxylic_acid_azide - 1] = true;
6909
          }
6910
    if (s_count == 1) {                 /* anhydride is checked somewhere else */
6911
            if (bond[get_bond (a_view, a_s) - 1].arom == false)
6912
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6913
            if (is_sulfanyl (a_view, a_s))
6914
              fg[fg_thiocarboxylic_acid - 1] = true;
6915
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6785 bpr 6916
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 6917
                      fg[fg_thiocarboxylic_acid_ester - 1] = true;
6918
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
6919
                      if (bond[get_bond (a_view, a_s) - 1].arom == true) {
6920
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6921
                        fg[fg_oxohetarene - 1] = true;
6922
                      }
6923
                      else
6924
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6925
                    }
6926
            }
14179 bpr 6927
          }
6928
  }                             /* end Oxo-C */
6929
  if (is_thioxo_C (a_view)) {
6930
    /* fg[fg_thiocarboxylic_acid_deriv]  := true; */
6931
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
6932
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
6933
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6934
            if (is_hydroxy (a_view, a_o))
6935
              fg[fg_thiocarboxylic_acid - 1] = true;    /* fixed in v0.3c */
6936
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
6785 bpr 6937
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 6938
                      fg[fg_thiocarboxylic_acid_ester - 1] = true;
6939
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
6940
                      if (bond[get_bond (a_view, a_o) - 1].arom == true) {
6941
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6942
                        fg[fg_thioxohetarene - 1] = true;
6943
                      }
6944
                      else
6945
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6946
                    }
6947
            }
14179 bpr 6948
          }
6949
    if (n_count == 1) {
6950
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6951
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6952
            else {
6785 bpr 6953
              /*fg[fg_thiolactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6954
              fg[fg_thioxohetarene - 1] = true;
6955
            }
14179 bpr 6956
            /* catches also pyridazines, 1,2,3-triazines, etc. */
6957
            if (is_amino (a_view, a_n)){
6785 bpr 6958
              fg[fg_thiocarboxylic_acid_amide - 1] = true;
6959
              /* fg[fg_thiocarboxylic_acid_prim_amide] := true; */
6960
            }
14179 bpr 6961
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6962
            if (is_C_monosubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6963
              /* v0.3j */
6785 bpr 6964
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6965
                      fg[fg_thiocarboxylic_acid_amide - 1] = true;
6785 bpr 6966
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := true; */
14179 bpr 6967
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6968
                      if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6969
                        /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
6970
                        fg[fg_thioxohetarene - 1] = true;
6785 bpr 6971
                    }
14179 bpr 6972
                    else
6973
                      fg[fg_thiolactam - 1] = true;
6974
                  }
6975
          }
6785 bpr 6976
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6977
          /*   (is_diarylamino(a_view,a_n)) then  */
14179 bpr 6978
          if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6979
            /* v0.3j */
6980
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6981
                    fg[fg_thiocarboxylic_acid_amide - 1] = true;
6785 bpr 6982
              /*fg[fg_thiocarboxylic_acid_tert_amide] := true; */
14179 bpr 6983
            if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6984
                    if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6785 bpr 6985
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
6986
                      fg[fg_thioxohetarene - 1] = true;
6987
                    }
14179 bpr 6988
                    else
6989
                      fg[fg_thiolactam - 1] = true;
6990
                  }
6991
          }
6785 bpr 6992
        }
14179 bpr 6993
  if (s_count == 1) {                   /* anhydride is checked somewhere else */
6785 bpr 6994
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
6995
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6996
          if (is_sulfanyl (a_view, a_s))
6997
            fg[fg_thiocarboxylic_acid - 1] = true;
14179 bpr 6998
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6999
      if (bond[get_bond (a_view, a_s) - 1].arom == false)
7000
                    fg[fg_thiocarboxylic_acid_ester - 1] = true;
7001
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
7002
                      if (bond[get_bond (a_view, a_s) - 1].arom == true) {
7003
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7004
                        fg[fg_thioxohetarene - 1] = true;
7005
                      }
7006
                      else
7007
                        fg[fg_thiolactone - 1] = true;
6785 bpr 7008
                    }
7009
            }
14179 bpr 7010
          }
7011
  }                             /* end Thioxo-C */
7012
  if (is_true_imino_C (a_view)) {
7013
    if (o_count == 1) {
7014
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
7015
              fg[fg_carboxylic_acid_deriv - 1] = true;
7016
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
6785 bpr 7017
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
14179 bpr 7018
                      fg[fg_imido_ester - 1] = true;
6785 bpr 7019
            }
14179 bpr 7020
          }
7021
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == false)) {
7022
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
7023
              fg[fg_carboxylic_acid_deriv - 1] = true;
7024
            if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n)) {
6785 bpr 7025
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 7026
                      fg[fg_carboxylic_acid_deriv - 1] = true;
6785 bpr 7027
              fg[fg_carboxylic_acid_amidine - 1] = true;
7028
            }
14179 bpr 7029
            if (is_hydrazino (a_view, a_n)) {
6785 bpr 7030
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 7031
                      fg[fg_carboxylic_acid_amidrazone - 1] = true;
6785 bpr 7032
            }
14179 bpr 7033
          }
7034
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == true))
7035
            /* catches also pyridazines, 1,2,3-triazines, etc. */
7036
          fg[fg_iminohetarene - 1] = true;
7037
    if (s_count == 1) {
7038
            if (bond[get_bond (a_view, a_s) - 1].arom == false)
7039
              fg[fg_carboxylic_acid_deriv - 1] = true;
7040
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6785 bpr 7041
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 7042
                 fg[fg_imido_thioester - 1] = true;
6785 bpr 7043
            }
14179 bpr 7044
          }
7045
  }
7046
  if (is_hydroximino_C (a_view)) {
7047
    if (bond[get_bond (a_view, a_n) - 1].arom == false)
7048
            fg[fg_carboxylic_acid_deriv - 1] = true;
7049
      if (o_count == 1) {
7050
              if (is_hydroxy (a_view, a_o))
7051
                fg[fg_hydroxamic_acid - 1] = true;
7052
            }
6785 bpr 7053
    }
14179 bpr 7054
    if (!is_hydrazono_C (a_view))
7055
      return;
7056
    if (bond[get_bond (a_view, a_n) - 1].arom == false)
7057
      fg[fg_carboxylic_acid_deriv - 1] = true;
7058
    if (n_count == 1) {
7059
        if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7060
          fg[fg_carboxylic_acid_amidrazone - 1] = true;
7061
  }
6785 bpr 7062
}
7063
 
14179 bpr 7064
static void chk_co2_sp2 (a_view, a_ref)
6785 bpr 7065
     int a_view, a_ref;
7066
{
7067
  int i;
7068
  neighbor_rec nb;
7069
  str2 nb_el;
7070
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
7071
    s_count = 0, sr_count = 0;
7072
  int FORLIM;
7073
 
7074
  memset (nb, 0, sizeof (neighbor_rec));
7075
  get_neighbors (nb, a_view);
7076
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7077
  for (i = 0; i < FORLIM; i++) {
7078
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7079
           strcpy (nb_el, atom[nb[i] - 1].element);
7080
            if (strcmp (nb_el, "C ")) {
7081
              if (!strcmp (nb_el, "O ")) {
7082
                      o_count++;
7083
                      if (is_alkoxy (a_view, nb[i]) |
7084
                          is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,nb[i]))
7085
                        /* v0.3j */
7086
                        or_count++;
7087
                    }
7088
              if (!strcmp (nb_el, "N ")) {
7089
                      n_count++;
7090
                      if (is_hydrazino (a_view, nb[i]))
7091
                        nn_count++;
7092
                      if (is_subst_hydrazino (a_view, nb[i]))   /* more general... */
7093
                        nnx_count++;
7094
                    }
7095
              if (!strcmp (nb_el, "S ")) {
7096
                      s_count++;
7097
                      if (is_alkylsulfanyl (a_view, nb[i]) | is_arylsulfanyl (a_view, nb[i]))
7098
                        sr_count++;
7099
                    }
6785 bpr 7100
            }
14179 bpr 7101
          }
7102
  }
7103
  if (is_oxo_C (a_view)) {
7104
      if (o_count == 2) {
7105
              fg[fg_carbonic_acid_deriv - 1] = true;
7106
              if (or_count == 1)
7107
                fg[fg_carbonic_acid_monoester - 1] = true;
7108
              if (or_count == 2)
7109
                fg[fg_carbonic_acid_diester - 1] = true;
7110
            }
7111
      if (o_count == 1 && s_count == 1) {
7112
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7113
              if (or_count + sr_count == 1)
7114
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7115
              if (or_count + sr_count == 2)
7116
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7117
            }
7118
      if (s_count == 2) {
7119
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7120
              if (sr_count == 1)
7121
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7122
              if (sr_count == 2)
7123
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7124
            }
7125
      if (o_count == 1 && n_count == 1) {
7126
              fg[fg_carbamic_acid_deriv - 1] = true;
7127
              if (or_count == 0)
7128
                fg[fg_carbamic_acid - 1] = true;
7129
              if (or_count == 1)
7130
                fg[fg_carbamic_acid_ester - 1] = true;
7131
            }
7132
      if (s_count == 1 && n_count == 1) {
7133
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7134
              if (sr_count == 0)
7135
                fg[fg_thiocarbamic_acid - 1] = true;
7136
              if (sr_count == 1)
7137
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7138
            }
7139
      if (n_count == 2) {
7140
            if (nn_count == 1)
7141
              fg[fg_semicarbazide - 1] = true;
7142
            else {
6785 bpr 7143
              if (nnx_count == 0)       /* excludes semicarbazones */
14179 bpr 7144
                      fg[fg_urea - 1] = true;
6785 bpr 7145
            }
14179 bpr 7146
          }
7147
  }                             /* end Oxo-C */
7148
  if (is_thioxo_C (a_view)) {
7149
      if (o_count == 2) {
7150
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7151
              if (or_count == 1)
7152
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7153
              if (or_count == 2)
7154
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7155
            }
7156
      if (o_count == 1 && s_count == 1) {
7157
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7158
              if (or_count + sr_count == 1)
7159
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7160
              if (or_count + sr_count == 2)
7161
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7162
            }
7163
      if (s_count == 2) {
7164
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7165
              if (sr_count == 1)
7166
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7167
              if (sr_count == 2)
7168
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7169
            }
7170
      if (o_count == 1 && n_count == 1) {
7171
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7172
              if (or_count == 0)
7173
                fg[fg_thiocarbamic_acid - 1] = true;
7174
              if (or_count == 1)
7175
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7176
            }
7177
      if (s_count == 1 && n_count == 1) {
7178
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7179
              if (sr_count == 0)
7180
                fg[fg_thiocarbamic_acid - 1] = true;
7181
              if (sr_count == 1)
7182
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7183
            }
7184
      if (n_count == 2) {
7185
            if (nn_count == 1)
7186
              fg[fg_thiosemicarbazide - 1] = true;
7187
            else {
6785 bpr 7188
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
14179 bpr 7189
                      fg[fg_thiourea - 1] = true;
6785 bpr 7190
            }
14179 bpr 7191
          }
7192
  }                             /* end Thioxo-C */
7193
  if (!(is_true_imino_C (a_view) &
7194
       (bond[get_bond (a_view, a_ref) - 1].arom == false))) {
6785 bpr 7195
      return;
14179 bpr 7196
  }                             /* end Imino-C */
6785 bpr 7197
  if (o_count == 1 && n_count == 1)
7198
    fg[fg_isourea - 1] = true;
7199
  if (s_count == 1 && n_count == 1)
7200
    fg[fg_isothiourea - 1] = true;
7201
  if (n_count == 2)
7202
    fg[fg_guanidine - 1] = true;
7203
}
7204
 
14179 bpr 7205
static void chk_co2_sp (a_view, a_ref)
6785 bpr 7206
     int a_view, a_ref;
7207
{
7208
  int i;
7209
  neighbor_rec nb;
7210
  str2 nb_el;
7211
  int o_count = 0, n_count = 0, s_count = 0;
7212
  int FORLIM;
7213
 
7214
  memset (nb, 0, sizeof (neighbor_rec));
7215
  get_neighbors (nb, a_view);
7216
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7217
  for (i = 0; i < FORLIM; i++) {
7218
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D') {
7219
            strcpy (nb_el, atom[nb[i] - 1].element);
7220
            if (strcmp (nb_el, "C ")) {
6785 bpr 7221
              if (!strcmp (nb_el, "O "))
14179 bpr 7222
                      o_count++;
6785 bpr 7223
              if (!strcmp (nb_el, "N "))
14179 bpr 7224
                      n_count++;
6785 bpr 7225
              if (!strcmp (nb_el, "S "))
14179 bpr 7226
                      s_count++;
6785 bpr 7227
            }
14179 bpr 7228
          }
7229
  }
6785 bpr 7230
  if (o_count + s_count == 2)   /* new in v0.3b */
7231
    fg[fg_co2_deriv - 1] = true;
7232
  if (o_count == 1 && n_count == 1)
7233
    fg[fg_isocyanate - 1] = true;
7234
  if (s_count == 1 && n_count == 1)
7235
    fg[fg_isothiocyanate - 1] = true;
7236
  if (n_count == 2)
7237
    fg[fg_carbodiimide - 1] = true;
7238
}
7239
 
14179 bpr 7240
static void chk_triple (a1, a2)
6785 bpr 7241
     int a1, a2;
7242
{
7243
  str2 a1_el, a2_el;
7244
 
7245
  strcpy (a1_el, atom[a1 - 1].element);
7246
  strcpy (a2_el, atom[a2 - 1].element);
7247
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &
7248
      (bond[get_bond (a1, a2) - 1].arom == false))
7249
    fg[fg_alkyne - 1] = true;
7250
  if (is_nitrile (a1, a2))
7251
    fg[fg_nitrile - 1] = true;
7252
  if (is_isonitrile (a1, a2))
7253
    fg[fg_isonitrile - 1] = true;
7254
  if (is_cyanate (a1, a2))
7255
    fg[fg_cyanate - 1] = true;
7256
  if (is_thiocyanate (a1, a2))
7257
    fg[fg_thiocyanate - 1] = true;
7258
}
7259
 
14179 bpr 7260
static void chk_ccx (a_view, a_ref)
6785 bpr 7261
     int a_view, a_ref;
7262
{
7263
  int i;
7264
  neighbor_rec nb;
7265
  int oh_count = 0, or_count = 0, n_count = 0;
7266
  int FORLIM;
7267
 
7268
  memset (nb, 0, sizeof (neighbor_rec));
7269
  get_neighbors (nb, a_ref);
7270
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7271
  for (i = 0; i < FORLIM; i++) {
7272
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6785 bpr 7273
          if (is_hydroxy (a_ref, nb[i]))
7274
            oh_count++;
7275
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7276
              is_siloxy (a_ref, nb[i]))
7277
            or_count++;
7278
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7279
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7280
            n_count++;
14179 bpr 7281
          }
7282
  }
6785 bpr 7283
  if (oh_count == 1)
7284
    fg[fg_enol - 1] = true;
7285
  if (or_count == 1)
7286
    fg[fg_enolether - 1] = true;
7287
  if (n_count == 1)
7288
    fg[fg_enamine - 1] = true;
7289
  /* new in v0.2f   (regard anything else as an alkene) */
7290
  if (oh_count + or_count + n_count == 0)
7291
    fg[fg_alkene - 1] = true;
7292
}
7293
 
14179 bpr 7294
static void chk_xccx (a_view, a_ref)
6785 bpr 7295
     int a_view, a_ref;
7296
{
7297
  int i;
7298
  neighbor_rec nb;
7299
  int oh_count = 0, or_count = 0, n_count = 0;
7300
  int FORLIM;
7301
 
7302
  memset (nb, 0, sizeof (neighbor_rec));
7303
  get_neighbors (nb, a_view);
7304
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7305
  for (i = 0; i < FORLIM; i++) {
7306
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7307
            if (is_hydroxy (a_view, nb[i]))
7308
              oh_count++;
7309
            if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
7310
                is_siloxy (a_view, nb[i]))
7311
              or_count++;
7312
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7313
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7314
              n_count++;
7315
          }
7316
  }
6785 bpr 7317
  memset (nb, 0, sizeof (neighbor_rec));
7318
  get_neighbors (nb, a_ref);
7319
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7320
  for (i = 0; i < FORLIM; i++) {
7321
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
7322
            if (is_hydroxy (a_ref, nb[i]))
7323
              oh_count++;
7324
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7325
                is_siloxy (a_ref, nb[i]))
7326
              or_count++;
7327
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7328
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7329
              n_count++;
7330
          }
7331
  }
6785 bpr 7332
  if (oh_count == 2)
7333
    fg[fg_enediol - 1] = true;
7334
  /* new in v0.2f   (regard anything else as an alkene) */
7335
  if (oh_count + or_count + n_count == 0)
7336
    fg[fg_alkene - 1] = true;
7337
}
7338
 
14179 bpr 7339
static void chk_n_o_dbl (a1, a2)
6785 bpr 7340
     int a1, a2;
7341
{
7342
  int i;
7343
  neighbor_rec nb;
7344
  str2 nb_el;
7345
  int or_count = 0, n_count = 0, c_count = 0;
7346
  int b;                        /* v0.3j */
7347
  int het_count = 0;            /* v0.3k */
7348
  char bt;                      /* v0.3k */
7349
  float bo_sum = 0.0;           /* v0.3k */
7350
  int FORLIM;
7351
 
7352
  memset (nb, 0, sizeof (neighbor_rec));
7353
  get_neighbors (nb, a1);
7354
  FORLIM = atom[a1 - 1].neighbor_count;
7355
  /* v0.3k */
7356
  /* v0.3k */
14179 bpr 7357
  for (i = 0; i < FORLIM; i++) {
7358
    if (nb[i] != a2) {
7359
            b = get_bond (a1, nb[i]);   /* v0.3j */
7360
            strcpy (nb_el, atom[nb[i] - 1].element);
7361
            bt = bond[b - 1].btype;     /* v0.3k */
7362
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7363
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
7364
                && strcmp (nb_el, "LP") && bond[b - 1].arom == false)
7365
                /* added 'D ' in v0.3n */
7366
              het_count++;
7367
            /* v0.3k: ignore hetero atoms */
7368
            /* in aromatic rings like isoxazole  */
7369
            if (bt == 'S')
7370
              bo_sum += 1.0;
7371
            if (bt == 'D')
7372
              bo_sum += 2.0;
7373
            if (bt == 'A')
7374
              bo_sum += 1.5;
7375
            if (!strcmp (nb_el, "O "))
7376
              or_count++;
7377
            if (!strcmp (nb_el, "N "))
7378
              n_count++;
7379
            if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')      /* v0.3k */
7380
              c_count++;
7381
            /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
7382
          }
7383
  }
7384
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2) {
7385
    /* excludes nitro etc. */
7386
    if (or_count == 1)
7387
            fg[fg_nitrite - 1] = true;
7388
    if (c_count == 1)
7389
            fg[fg_nitroso_compound - 1] = true;
7390
    if (n_count == 1)           /* instead of nitrosamine  v0.3j */
7391
            fg[fg_nitroso_compound - 1] = true;
7392
    /*if (n_count = 1) then fg[fg_nitrosamine]   := true;  (* still missing */
7393
  }
6785 bpr 7394
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
7395
  /*  begin */
7396
  /*    fg[fg_n_oxide] := true; */
7397
  /*  end; */
7398
  /* new approach in v0.3k */
7399
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
7400
    fg[fg_n_oxide - 1] = true;
7401
}
7402
 
14179 bpr 7403
static void chk_sulfoxide (a1, a2)
6785 bpr 7404
     int a1, a2;
7405
{
7406
  int i;
7407
  neighbor_rec nb;
7408
  str2 nb_el;
7409
  int o_count = 0, c_count = 0;
7410
  int FORLIM;
7411
 
7412
  memset (nb, 0, sizeof (neighbor_rec));
7413
  get_neighbors (nb, a1);
7414
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7415
  for (i = 0; i < FORLIM; i++) {
7416
    strcpy (nb_el, atom[nb[i] - 1].element);
7417
    if (!strcmp (nb_el, "O "))
7418
            o_count++;
7419
    if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
7420
            c_count++;
7421
  }
6785 bpr 7422
  if (o_count == 1 && c_count == 2)
7423
    fg[fg_sulfoxide - 1] = true;
7424
}
7425
 
14179 bpr 7426
static void chk_double (a1, a2)
6785 bpr 7427
     int a1, a2;
7428
{
7429
  str2 a1_el, a2_el;
7430
 
7431
  strcpy (a1_el, atom[a1 - 1].element);
7432
  strcpy (a2_el, atom[a2 - 1].element);
7433
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &
14179 bpr 7434
      (bond[get_bond (a1, a2) - 1].arom == false)) {
7435
    if (hetbond_count (a1) == 2)
7436
            chk_carbonyl_deriv (a1, a2);
7437
    if (hetbond_count (a1) == 3)
7438
            chk_carboxyl_deriv (a1, a2);
7439
    if (hetbond_count (a1) == 4) {
7440
            if (!strcmp (atom[a1 - 1].atype, "C2 "))
7441
              chk_co2_sp2 (a1, a2);
7442
            if (!strcmp (atom[a1 - 1].atype, "C1 "))
7443
              chk_co2_sp (a1, a2);
7444
          }
7445
  }                             /* end C=X */
6785 bpr 7446
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
7447
       && !strcmp (atom[a2 - 1].atype,
14179 bpr 7448
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == false)) {
7449
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
7450
            fg[fg_ketene_acetal_deriv - 1] = true;
7451
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
7452
            chk_ccx (a1, a2);
7453
    if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
7454
            chk_xccx (a1, a2);
7455
    if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
7456
              atom[a1 - 1].arom == false && atom[a2 - 1].arom == false)
7457
            fg[fg_alkene - 1] = true;
7458
  }
7459
  if (((!strcmp (a1_el, "N ") && !strcmp (a2_el, "N "))
7460
      && (hetbond_count (a1) == 2) && (hetbond_count (a2) == 2)
7461
      && (bond[get_bond (a1, a2) - 1].arom == false))
6785 bpr 7462
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
7463
    fg[fg_azo_compound - 1] = true;
7464
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
7465
    chk_n_o_dbl (a1, a2);
7466
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
7467
    chk_sulfoxide (a1, a2);
7468
}
7469
 
14179 bpr 7470
static void chk_c_hal (a1, a2)
6785 bpr 7471
     int a1, a2;
7472
{
7473
  str2 a2_el;
7474
 
7475
  strcpy (a2_el, atom[a2 - 1].element);
7476
  fg[fg_halogen_deriv - 1] = true;
14179 bpr 7477
  if (atom[a1 - 1].arom) {
7478
    fg[fg_aryl_halide - 1] = true;
7479
    if (!strcmp (a2_el, "F "))
7480
            fg[fg_aryl_fluoride - 1] = true;
7481
    if (!strcmp (a2_el, "CL"))
7482
            fg[fg_aryl_chloride - 1] = true;
7483
    if (!strcmp (a2_el, "BR"))
7484
            fg[fg_aryl_bromide - 1] = true;
7485
    if (!strcmp (a2_el, "I "))
7486
            fg[fg_aryl_iodide - 1] = true;
7487
    return;
7488
  }
7489
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2)) {
7490
    /* alkyl halides */
7491
    fg[fg_alkyl_halide - 1] = true;
7492
    if (!strcmp (a2_el, "F "))
7493
            fg[fg_alkyl_fluoride - 1] = true;
7494
    if (!strcmp (a2_el, "CL"))
7495
            fg[fg_alkyl_chloride - 1] = true;
7496
    if (!strcmp (a2_el, "BR"))
7497
            fg[fg_alkyl_bromide - 1] = true;
7498
    if (!strcmp (a2_el, "I "))
7499
            fg[fg_alkyl_iodide - 1] = true;
7500
  }
7501
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3)) {
7502
    /* acyl halides and related compounds */
7503
    if (is_oxo_C (a1)) {
7504
            fg[fg_acyl_halide - 1] = true;
7505
            if (!strcmp (a2_el, "F "))
7506
              fg[fg_acyl_fluoride - 1] = true;
7507
            if (!strcmp (a2_el, "CL"))
7508
              fg[fg_acyl_chloride - 1] = true;
7509
            if (!strcmp (a2_el, "BR"))
7510
              fg[fg_acyl_bromide - 1] = true;
7511
            if (!strcmp (a2_el, "I "))
7512
              fg[fg_acyl_iodide - 1] = true;
7513
          }
7514
    if (is_thioxo_C (a1))
7515
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7516
    if (is_imino_C (a1))
7517
            fg[fg_imidoyl_halide - 1] = true;
7518
  }
7519
  if (!((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
6785 bpr 7520
       && (hetbond_count (a1) == 4)))
7521
    /* chloroformates etc. */
7522
    return;
7523
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
7524
  fg[fg_co2_deriv - 1] = true;
14179 bpr 7525
  if (is_oxo_C (a1)) {
6785 bpr 7526
      fg[fg_carbonic_acid_deriv - 1] = true;
14179 bpr 7527
    if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
7528
            fg[fg_carbonic_acid_ester_halide - 1] = true;
7529
    if (is_carbamoyl (a2, a1)) {
7530
            fg[fg_carbamic_acid_deriv - 1] = true;
7531
            fg[fg_carbamic_acid_halide - 1] = true;
7532
          }
7533
  }
6785 bpr 7534
  if (!is_thioxo_C (a1))
7535
    return;
7536
  fg[fg_thiocarbonic_acid_deriv - 1] = true;
7537
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
7538
    fg[fg_thiocarbonic_acid_ester_halide - 1] = true;
14179 bpr 7539
  if (is_thiocarbamoyl (a2, a1)) {
7540
    fg[fg_thiocarbamic_acid_deriv - 1] = true;
7541
    fg[fg_thiocarbamic_acid_halide - 1] = true;
6785 bpr 7542
      /* end of non-aromatic halogen compounds */
14179 bpr 7543
  }
6785 bpr 7544
}
7545
 
14179 bpr 7546
static void chk_c_o (a1, a2)
6785 bpr 7547
     int a1, a2;
7548
{
7549
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
7550
  if (bond[get_bond (a1, a2) - 1].arom == true)
7551
    return;
14179 bpr 7552
  if (is_true_alkyl (a2, a1) && is_hydroxy (a1, a2)) {
7553
    fg[fg_hydroxy - 1] = true;
7554
    fg[fg_alcohol - 1] = true;
7555
    if (atom[a1 - 1].neighbor_count <= 2)
7556
            fg[fg_prim_alcohol - 1] = true;
7557
    if (atom[a1 - 1].neighbor_count == 3)
7558
            fg[fg_sec_alcohol - 1] = true;
7559
    if (atom[a1 - 1].neighbor_count == 4)
7560
            fg[fg_tert_alcohol - 1] = true;
7561
  }
7562
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2)) {
7563
    fg[fg_hydroxy - 1] = true;
7564
    fg[fg_phenol - 1] = true;
7565
  }
7566
  if (is_true_alkyl (a2, a1) && is_true_alkoxy (a1, a2)) {
7567
    fg[fg_ether - 1] = true;
7568
    fg[fg_dialkylether - 1] = true;
7569
  }
6785 bpr 7570
  if ((is_true_alkyl (a2, a1) && is_aryloxy (a1, a2)) |
14179 bpr 7571
      (is_aryl (a2, a1) && is_true_alkoxy (a1, a2))) {
7572
    fg[fg_ether - 1] = true;
7573
    fg[fg_alkylarylether - 1] = true;
7574
  }
7575
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2)) {
7576
    fg[fg_ether - 1] = true;
7577
    fg[fg_diarylether - 1] = true;
7578
  }
7579
  if ((is_true_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2)) {
7580
    fg[fg_ether - 1] = true;
7581
    ether_generic = true;
7582
  }
7583
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2)) {
7584
    fg[fg_hydroxy - 1] = true;
7585
    hydroxy_generic = true;
7586
  }
6785 bpr 7587
}
7588
 
14179 bpr 7589
static void chk_c_s (a1, a2)
6785 bpr 7590
     int a1, a2;
7591
{
7592
  int i;
7593
  neighbor_rec nb;
7594
  str2 nb_el;
7595
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
7596
    hal_count = 0;
7597
  int FORLIM;
7598
 
7599
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
7600
  if (bond[get_bond (a1, a2) - 1].arom == true)
7601
    return;
14179 bpr 7602
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2)) {
7603
    fg[fg_thiol - 1] = true;
7604
    fg[fg_alkylthiol - 1] = true;
7605
  }
7606
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2)) {
7607
    fg[fg_thiol - 1] = true;
7608
    fg[fg_arylthiol - 1] = true;
7609
  }
6785 bpr 7610
  if (is_true_alkyl (a2, a1) && is_true_alkylsulfanyl (a1, a2))
7611
    fg[fg_thioether - 1] = true;
7612
  if ((is_true_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) |
14179 bpr 7613
        (is_aryl (a2, a1) && is_true_alkylsulfanyl (a1, a2)))
6785 bpr 7614
    fg[fg_thioether - 1] = true;
7615
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
7616
    fg[fg_thioether - 1] = true;
7617
  /* check for sulfinic/sulfenic acid derivatives */
7618
  memset (nb, 0, sizeof (neighbor_rec));
7619
  get_neighbors (nb, a2);
7620
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7621
  for (i = 0; i < FORLIM; i++) {
7622
    strcpy (nb_el, atom[nb[i] - 1].element);
7623
    if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
7624
            c_count++;
7625
    if (is_hydroxy (a2, nb[i]))
7626
            oh_count++;
7627
    if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
7628
            or_count++;
7629
    if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
7630
            n_count++;
7631
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7632
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
7633
            hal_count++;
7634
    if (!strcmp (nb_el, "O "))
7635
            o_count++;
7636
  }
6785 bpr 7637
  if (c_count != 1)
7638
    return;
14179 bpr 7639
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1) {
7640
    /* sulfinic acid && derivs */
7641
    fg[fg_sulfinic_acid_deriv - 1] = true;
7642
    if (oh_count == 1)
7643
            fg[fg_sulfinic_acid - 1] = true;
7644
    if (or_count == 1)
7645
            fg[fg_sulfinic_acid_ester - 1] = true;
7646
    if (hal_count == 1)
7647
            fg[fg_sulfinic_acid_halide - 1] = true;
7648
    if (n_count == 1)
7649
            fg[fg_sulfinic_acid_amide - 1] = true;
7650
  }
6785 bpr 7651
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
7652
    /* sulfenic acid && derivs */
7653
    return;
7654
 
7655
  fg[fg_sulfenic_acid_deriv - 1] = true;
7656
  if (oh_count == 1)
7657
    fg[fg_sulfenic_acid - 1] = true;
7658
  if (or_count == 1)
7659
    fg[fg_sulfenic_acid_ester - 1] = true;
7660
  if (hal_count == 1)
7661
    fg[fg_sulfenic_acid_halide - 1] = true;
7662
  if (n_count == 1)
7663
    fg[fg_sulfenic_acid_amide - 1] = true;
7664
}
7665
 
14179 bpr 7666
static void chk_c_n (a1, a2)
6785 bpr 7667
     int a1, a2;
7668
{
7669
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
7670
  if (atom[a2 - 1].arom == true)
7671
    return;
14179 bpr 7672
  if (is_true_alkyl (a2, a1) && is_amino (a1, a2)) {
7673
    fg[fg_amine - 1] = true;
7674
    fg[fg_prim_amine - 1] = true;
7675
    fg[fg_prim_aliph_amine - 1] = true;
6785 bpr 7676
    }
14179 bpr 7677
  if (is_aryl (a2, a1) && is_amino (a1, a2)) {
7678
    fg[fg_amine - 1] = true;
7679
    fg[fg_prim_amine - 1] = true;
7680
    fg[fg_prim_arom_amine - 1] = true;
7681
  }
7682
  if (is_true_alkyl (a2, a1) && is_true_alkylamino (a1, a2)) {
7683
    fg[fg_amine - 1] = true;
7684
    fg[fg_sec_amine - 1] = true;
7685
    fg[fg_sec_aliph_amine - 1] = true;
7686
  }
7687
  if (is_aryl (a2, a1) && is_true_alkylamino (a1, a2)) {
7688
    fg[fg_amine - 1] = true;
7689
    fg[fg_sec_amine - 1] = true;
7690
    fg[fg_sec_mixed_amine - 1] = true;
7691
  }
7692
  if (is_aryl (a2, a1) && is_arylamino (a1, a2)) {
7693
    fg[fg_amine - 1] = true;
7694
    fg[fg_sec_amine - 1] = true;
7695
    fg[fg_sec_arom_amine - 1] = true;
7696
  }
7697
  if (is_true_alkyl (a2, a1) && is_true_dialkylamino (a1, a2)) {
7698
    fg[fg_amine - 1] = true;
7699
    fg[fg_tert_amine - 1] = true;
7700
    fg[fg_tert_aliph_amine - 1] = true;
7701
  }
6785 bpr 7702
  if ((is_true_alkyl (a2, a1) && is_diarylamino (a1, a2)) |
14179 bpr 7703
      (is_aryl (a2, a1) && is_true_dialkylamino (a1, a2))) {
7704
    fg[fg_amine - 1] = true;
7705
    fg[fg_tert_amine - 1] = true;
7706
    fg[fg_tert_mixed_amine - 1] = true;
7707
  }
7708
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2)) {
7709
    fg[fg_amine - 1] = true;
7710
    fg[fg_tert_amine - 1] = true;
7711
    fg[fg_tert_arom_amine - 1] = true;
7712
  }
6785 bpr 7713
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
14179 bpr 7714
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2, a1) == false))
6785 bpr 7715
    /* v0.3k */
7716
    fg[fg_hydroxylamine - 1] = true;
7717
  /* v0.3k */
7718
  /* v0.3k  */
7719
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) |
7720
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
7721
    fg[fg_hydrazine - 1] = true;
7722
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7723
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
7724
    /* v0.3k */
7725
    fg[fg_azide - 1] = true;
7726
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7727
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
7728
    /* v0.3k */
7729
    fg[fg_diazonium_salt - 1] = true;
7730
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7731
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
7732
    /* v0.3k */
7733
    fg[fg_nitro_compound - 1] = true;
7734
  if (is_alkynyl (a2, a1) &
14179 bpr 7735
        (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
7736
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2))))) {
6785 bpr 7737
      fg[fg_amine - 1] = true;
7738
      amine_generic = true;
14179 bpr 7739
  }
6785 bpr 7740
}
7741
 
14179 bpr 7742
static void chk_c_c (a1, a2)
6785 bpr 7743
     int a1, a2;
7744
{
7745
  int i;
7746
  neighbor_rec nb;
7747
  int oh_count, nhr_count, FORLIM;
7748
 
7749
  /* ignore aromatic rings */
7750
  if (atom[a2 - 1].arom == true)
7751
    return;
7752
  /*check for 1,2-diols and 1,2-aminoalcoholes */
7753
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
14179 bpr 7754
        && !strcmp (atom[a2 - 1].atype, "C3 ")) {
7755
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1)) {
7756
            oh_count = 0;
7757
            nhr_count = 0;
7758
            memset (nb, 0, sizeof (neighbor_rec));
7759
            get_neighbors (nb, a1);
7760
            FORLIM = atom[a1 - 1].neighbor_count;
7761
            for (i = 0; i < FORLIM; i++) {
7762
              if (nb[i] != a2) {
7763
                      if (is_hydroxy (a1, nb[i]))
7764
                        oh_count++;
7765
                      if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7766
                        is_arylamino (a1, nb[i]))
7767
                      nhr_count++;
7768
                    }
6785 bpr 7769
            }
14179 bpr 7770
            memset (nb, 0, sizeof (neighbor_rec));
7771
            get_neighbors (nb, a2);
7772
            FORLIM = atom[a2 - 1].neighbor_count;
7773
            for (i = 0; i < FORLIM; i++) {
7774
              if (nb[i] != a1) {
7775
                      if (is_hydroxy (a2, nb[i]))
7776
                        oh_count++;
7777
                      if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
7778
                          is_arylamino (a2, nb[i]))
7779
                        nhr_count++;
7780
                    }
6785 bpr 7781
            }
14179 bpr 7782
            if (oh_count == 2)
7783
              fg[fg_1_2_diol - 1] = true;
7784
            if (oh_count == 1 && nhr_count == 1)
7785
              fg[fg_1_2_aminoalcohol - 1] = true;
7786
          }
7787
  }
6785 bpr 7788
  /* check for alpha-aminoacids and alpha-hydroxyacids */
7789
  if (strcmp (atom[a1 - 1].atype, "C3 ")
7790
      || strcmp (atom[a2 - 1].atype, "C2 "))
7791
    return;
7792
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
7793
    return;
7794
  oh_count = 0;
7795
  nhr_count = 0;
7796
  memset (nb, 0, sizeof (neighbor_rec));
7797
  get_neighbors (nb, a1);
7798
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7799
  for (i = 0; i < FORLIM; i++) {
7800
    if (nb[i] != a2) {
7801
            if (is_hydroxy (a1, nb[i]))
7802
              oh_count++;
7803
            if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7804
                is_arylamino (a1, nb[i]))
7805
              nhr_count++;
7806
          }
7807
  }
6785 bpr 7808
  memset (nb, 0, sizeof (neighbor_rec));
7809
  get_neighbors (nb, a2);
7810
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7811
  for (i = 0; i < FORLIM; i++) {
7812
    if (nb[i] != a1) {
7813
            if (is_hydroxy (a2, nb[i]))
7814
              oh_count++;
7815
          }
7816
  }
6785 bpr 7817
  if ((oh_count == 2) && is_oxo_C (a2))
7818
    fg[fg_alpha_hydroxyacid - 1] = true;
7819
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
7820
    fg[fg_alpha_aminoacid - 1] = true;
7821
}
7822
 
14179 bpr 7823
static void chk_x_y_single (a_view, a_ref)
6785 bpr 7824
     int a_view, a_ref;
7825
{
7826
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
14179 bpr 7827
        !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7828
    if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
7829
            fg[fg_hydroperoxide - 1] = true;
7830
    if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
7831
              is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,a_ref) |
7832
                        is_aryloxy (a_view, a_ref) |
7833
                        is_siloxy (a_view, a_ref)))
7834
            fg[fg_peroxide - 1] = true;
7835
  }                             /* still missing: peracid */
6785 bpr 7836
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
14179 bpr 7837
      !strcmp (atom[a_ref - 1].atype, "S3 ")) {
6785 bpr 7838
      if (atom[a_view - 1].neighbor_count == 2 &&
7839
          atom[a_ref - 1].neighbor_count == 2)
14179 bpr 7840
          fg[fg_disulfide - 1] = true;
7841
  }
6785 bpr 7842
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7843
       !strcmp (atom[a_ref - 1].element, "N ")) && (hetbond_count (a_view) == 1)
7844
      && (hetbond_count (a_ref) == 1)) {
6785 bpr 7845
      /*if ((is_amino(a_ref,a_view)) or  */
7846
      /*    (is_subst_amino(a_ref,a_view)) or */
7847
      /*    (is_acylamino(a_ref,a_view))) and */
7848
      /*   ((is_amino(a_view,a_ref)) or  */
7849
      /*    (is_subst_amino(a_view,a_ref)) or */
7850
      /*    (is_acylamino(a_ref,a_view))) then  */
7851
      if (bond[get_bond (a_view, a_ref) - 1].arom == false)
14179 bpr 7852
              fg[fg_hydrazine - 1] = true;
7853
  }
6785 bpr 7854
  if (!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7855
      !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7856
    /* bond is in "opposite" direction */
7857
    if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &
7858
              is_nitro (a_ref, a_view))
7859
            fg[fg_nitrate - 1] = true;
7860
    if ((is_nitro (a_ref, a_view) == false
7861
              && atom[a_view - 1].arom == false) && (is_amino (a_ref, a_view) |
7862
                    is_subst_amino (a_ref, a_view)) &
7863
              (is_acylamino (a_ref, a_view) == false))
7864
            fg[fg_hydroxylamine - 1] = true;    /* new in v0.3c */
7865
  }
6785 bpr 7866
  if (!strcmp (atom[a_view - 1].element, "S ") &&
7867
      !strcmp (atom[a_ref - 1].element, "O "))
7868
    chk_sulfoxide (a_view, a_ref);
7869
}
7870
 
14179 bpr 7871
static void chk_single (a1, a2)
6785 bpr 7872
     int a1, a2;
7873
{
7874
  str2 a1_el, a2_el;
7875
 
7876
  strcpy (a1_el, atom[a1 - 1].element);
7877
  strcpy (a2_el, atom[a2 - 1].element);
7878
  if (!strcmp (a1_el, "C ") &&
7879
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
7880
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
7881
    chk_c_hal (a1, a2);
7882
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
7883
    chk_c_o (a1, a2);
7884
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
7885
    chk_c_s (a1, a2);
7886
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
7887
    chk_c_n (a1, a2);
14179 bpr 7888
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) == false)) {
6785 bpr 7889
      fg[fg_organometallic - 1] = true;
7890
      if (!strcmp (a2_el, "LI"))
14179 bpr 7891
              fg[fg_organolithium - 1] = true;
6785 bpr 7892
      if (!strcmp (a2_el, "MG"))
14179 bpr 7893
              fg[fg_organomagnesium - 1] = true;
7894
  }
6785 bpr 7895
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
7896
    chk_c_c (a1, a2);
7897
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
7898
    chk_x_y_single (a1, a2);
7899
}
7900
 
14179 bpr 7901
static void chk_carbonyl_deriv_sp3 (a_ref)
6785 bpr 7902
     int a_ref;
7903
{
7904
  int i;
7905
  neighbor_rec nb;
7906
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
7907
  int FORLIM;
7908
 
7909
  memset (nb, 0, sizeof (neighbor_rec));
7910
  get_neighbors (nb, a_ref);
7911
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7912
  for (i = 0; i < FORLIM; i++) {
7913
    if (is_hydroxy (a_ref, nb[i]))
7914
            oh_count++;
7915
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7916
              is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
7917
            or_count++;
7918
    if (is_sulfanyl (a_ref, nb[i]))
7919
            sh_count++;
7920
    if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
7921
              is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref, nb[i]))
7922
            sr_count++;
7923
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
7924
            n_count++;
7925
  }
6785 bpr 7926
  if (oh_count == 2)
7927
    fg[fg_carbonyl_hydrate - 1] = true;
7928
  if (oh_count == 1 && or_count == 1)
7929
    fg[fg_hemiacetal - 1] = true;
7930
  if (or_count == 2)
7931
    fg[fg_acetal - 1] = true;
7932
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
7933
    fg[fg_hemiaminal - 1] = true;
7934
  if (n_count == 2)
7935
    fg[fg_aminal - 1] = true;
7936
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
7937
    fg[fg_thiohemiaminal - 1] = true;
7938
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
7939
    fg[fg_thioacetal - 1] = true;
7940
}
7941
 
14179 bpr 7942
static void chk_carboxyl_deriv_sp3 (a_ref)
6785 bpr 7943
     int a_ref;
7944
{
7945
  int i;
7946
  neighbor_rec nb;
7947
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
7948
  int electroneg_count = 0;     /* new in v0.3j */
7949
  int hal_count = 0;
7950
  str2 nb_el;
7951
  int FORLIM;
7952
 
7953
  memset (nb, 0, sizeof (neighbor_rec));
7954
  get_neighbors (nb, a_ref);
7955
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7956
  for (i = 0; i < FORLIM; i++) {
7957
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3j */
7958
    if (is_electroneg (nb_el))
7959
            electroneg_count++;
7960
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7961
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7962
              || !strcmp (nb_el, "AT"))
7963
            hal_count++;
7964
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7965
              is_siloxy (a_ref, nb[i]))
7966
            or_count++;
7967
    if (is_hydroxy (a_ref, nb[i]))      /* new in v0.3c    */
7968
            oh_count++;
7969
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7970
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7971
            n_count++;
7972
  }
6785 bpr 7973
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := true;  (* until v0.3i */
7974
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
7975
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
7976
  if (or_count == 3)
7977
    fg[fg_carboxylic_acid_orthoester - 1] = true;
7978
  if (or_count == 2 && n_count == 1)
7979
    fg[fg_carboxylic_acid_amide_acetal - 1] = true;
7980
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
7981
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
7982
}
7983
 
14179 bpr 7984
static void chk_anhydride (a_ref)
6785 bpr 7985
     int a_ref;
7986
{
7987
  int i;
7988
  neighbor_rec nb;
7989
  int acyl_count = 0;
7990
  int FORLIM;
7991
 
7992
  memset (nb, 0, sizeof (neighbor_rec));
7993
  get_neighbors (nb, a_ref);
7994
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7995
  for (i = 0; i < FORLIM; i++) {
7996
    if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
7997
            acyl_count++;
7998
  }
7999
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 ")) {
8000
    fg[fg_carboxylic_acid_deriv - 1] = true;
8001
    fg[fg_carboxylic_acid_anhydride - 1] = true;
8002
  }
6785 bpr 8003
}
8004
 
14179 bpr 8005
static void chk_imide (a_ref)
6785 bpr 8006
     int a_ref;
8007
{
8008
  int i;
8009
  neighbor_rec nb;
8010
  int acyl_count = 0;
8011
  int FORLIM;
8012
 
8013
  memset (nb, 0, sizeof (neighbor_rec));
8014
  get_neighbors (nb, a_ref);
8015
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 8016
  for (i = 0; i < FORLIM; i++) {
8017
    if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))      /* v0.3j */
8018
            acyl_count++;
8019
  }
6785 bpr 8020
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
8021
    /* v0.3j: accept also N-acyl-imides */
8022
    return;
8023
  fg[fg_carboxylic_acid_deriv - 1] = true;
8024
  fg[fg_carboxylic_acid_imide - 1] = true;
8025
  if (atom[a_ref - 1].neighbor_count == 2)
8026
    fg[fg_carboxylic_acid_unsubst_imide - 1] = true;
8027
  if (atom[a_ref - 1].neighbor_count == 3)
8028
    fg[fg_carboxylic_acid_subst_imide - 1] = true;
8029
}
8030
 
14179 bpr 8031
static void chk_12diphenol (a_view, a_ref)
6785 bpr 8032
     int a_view, a_ref;
8033
{
8034
  int i;
8035
  neighbor_rec nb;
8036
  int oh_count = 0;
8037
  int FORLIM;
8038
 
8039
  memset (nb, 0, sizeof (neighbor_rec));
8040
  get_neighbors (nb, a_view);
8041
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 8042
  for (i = 0; i < FORLIM; i++) {
8043
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
8044
            if (is_hydroxy (a_view, nb[i]))
8045
              oh_count++;
8046
          }
8047
  }
6785 bpr 8048
  memset (nb, 0, sizeof (neighbor_rec));
8049
  get_neighbors (nb, a_ref);
8050
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 8051
  for (i = 0; i < FORLIM; i++) {
8052
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
8053
            if (is_hydroxy (a_ref, nb[i]))
8054
              oh_count++;
8055
          }
8056
  }
6785 bpr 8057
  if (oh_count == 2)
8058
    fg[fg_1_2_diphenol - 1] = true;
8059
}
8060
 
14179 bpr 8061
static void chk_arom_fg (a1, a2)
6785 bpr 8062
     int a1, a2;
8063
{
8064
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8065
    chk_12diphenol (a1, a2);
8066
}
8067
 
14179 bpr 8068
static boolean is_arene (r_id)
6785 bpr 8069
     int r_id;
8070
{
8071
  int i, j;
8072
  boolean r = true;
8073
  ringpath_type testring;
8074
  int ring_size, a_prev, a_ref;
8075
 
8076
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
8077
  if (r_id < 1 || r_id > n_rings)
8078
    return false;
8079
  memset (testring, 0, sizeof (ringpath_type));
8080
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8081
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8082
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8083
    testring[j] = ring[r_id - 1][j];
8084
  /*ring_size := path_length(testring); */
8085
  if (ring_size <= 2)
8086
    return false;
8087
  a_prev = testring[ring_size - 1];
14179 bpr 8088
  for (i = 0; i < ring_size; i++) {
8089
    a_ref = testring[i];
8090
    if (bond[get_bond (a_prev, a_ref) - 1].arom == false)
8091
            r = false;
8092
    a_prev = a_ref;
8093
  }
6785 bpr 8094
  return r;
8095
}
8096
 
14179 bpr 8097
static boolean is_heterocycle (r_id)
6785 bpr 8098
     int r_id;
8099
{
8100
  int i, j;
8101
  boolean r = false;
8102
  ringpath_type testring;
8103
  int ring_size, a_ref;
8104
 
8105
  if (r_id < 1 || r_id > n_rings)
8106
    return false;
8107
  memset (testring, 0, sizeof (ringpath_type));
8108
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8109
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8110
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8111
    testring[j] = ring[r_id - 1][j];
8112
  /*ring_size := path_length(testring); */
8113
  if (ring_size <= 2)
8114
    return false;
14179 bpr 8115
  for (i = 0; i < ring_size; i++) {
8116
    a_ref = testring[i];
8117
    if (strcmp (atom[a_ref - 1].element, "C "))
8118
            r = true;
8119
  }
6785 bpr 8120
  return r;
8121
}
8122
 
14179 bpr 8123
static void chk_oxo_thioxo_imino_hetarene (r_id)
6785 bpr 8124
     int r_id;
8125
{
8126
  int i, j;
8127
  ringpath_type testring;
8128
  int ring_size, a_ref;
8129
 
8130
  if (r_id < 1 || r_id > n_rings)
8131
    return;
8132
  memset (testring, 0, sizeof (ringpath_type));
8133
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8134
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8135
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8136
    testring[j] = ring[r_id - 1][j];
8137
  /*ring_size := path_length(testring); */
8138
  /*if (is_arene(r_id)) and (odd(ring_size) = false) then */
8139
  if (!is_arene (r_id))         /* v0.3j */
8140
    return;
14179 bpr 8141
  for (i = 0; i < ring_size; i++) {
8142
    a_ref = testring[i];
8143
    if (is_oxo_C (a_ref))
8144
            fg[fg_oxohetarene - 1] = true;
8145
    if (is_thioxo_C (a_ref))
8146
            fg[fg_thioxohetarene - 1] = true;
8147
    if (is_true_exocyclic_imino_C (a_ref, r_id))        /* v0.3j */
8148
            fg[fg_iminohetarene - 1] = true;
8149
  }
6785 bpr 8150
}
8151
 
14179 bpr 8152
static void chk_ion (a_ref)
6785 bpr 8153
     int a_ref;
8154
{
8155
  int i;
8156
  neighbor_rec nb;
8157
  int charge, FORLIM;
8158
 
8159
  memset (nb, 0, sizeof (neighbor_rec));
8160
  get_neighbors (nb, a_ref);
8161
  charge = atom[a_ref - 1].formal_charge;
8162
  if (charge == 0)
8163
    /* check if charge is neutralized by an adjacent opposite charge */
8164
    return;
8165
  FORLIM = atom[a_ref - 1].neighbor_count;
8166
  for (i = 0; i < FORLIM; i++)
8167
    charge += atom[nb[i] - 1].formal_charge;
8168
  if (charge > 0)
8169
    fg[fg_cation - 1] = true;
8170
  if (charge < 0)
8171
    fg[fg_anion - 1] = true;
8172
}
8173
 
14179 bpr 8174
static void chk_functionalgroups ()
6785 bpr 8175
{
8176
  int i, a1, a2;
8177
  char bt;
8178
  int pos_chg = 0, neg_chg = 0;
8179
  int FORLIM;
8180
 
8181
  if (n_atoms < 1 || n_bonds < 1)
8182
    return;
8183
  FORLIM = n_atoms;
14179 bpr 8184
  for (i = 1; i <= FORLIM; i++) {                               /* a few groups are best discovered in the atom list */
8185
    if (!strcmp (atom[i - 1].atype, "SO2"))
8186
            chk_so2_deriv (i);
8187
    /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := true;  (* do another check in the bond list!! */
8188
    if (!strcmp (atom[i - 1].element, "P "))
8189
            chk_p_deriv (i);
8190
    if (!strcmp (atom[i - 1].element, "B "))
8191
            chk_b_deriv (i);
8192
    if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
8193
            chk_ammon (i);
8194
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 2))
8195
            chk_carbonyl_deriv_sp3 (i);
8196
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 3))
8197
            chk_carboxyl_deriv_sp3 (i);
8198
    if (!strcmp (atom[i - 1].atype, "O3 ") && atom[i - 1].neighbor_count == 2)
8199
            chk_anhydride (i);
8200
    if ((!strcmp (atom[i - 1].atype, "N3 ") || !strcmp (atom[i - 1].atype, "NAM"))
8201
              && atom[i - 1].neighbor_count >= 2)
8202
            chk_imide (i);
8203
    if (atom[i - 1].formal_charge > 0)
8204
            pos_chg += atom[i - 1].formal_charge;
8205
    if (atom[i - 1].formal_charge < 0)
8206
            neg_chg += atom[i - 1].formal_charge;
8207
    chk_ion (i);
8208
  }
6785 bpr 8209
  FORLIM = n_bonds;
14179 bpr 8210
  for (i = 0; i < FORLIM; i++) {                                /* most groups are best discovered in the bond list */
8211
    a1 = bond[i].a1;
8212
    a2 = bond[i].a2;
8213
    bt = bond[i].btype;
8214
    if (atom[a1 - 1].heavy && atom[a2 - 1].heavy) {
8215
            orient_bond (&a1, &a2);
8216
            if (bt == 'T')
8217
              chk_triple (a1, a2);
8218
            if (bt == 'D')
8219
              chk_double (a1, a2);
8220
            if (bt == 'S')
8221
              chk_single (a1, a2);
8222
            if (bond[i].arom)
8223
              chk_arom_fg (a1, a2);
8224
          }
8225
  }
8226
  if (n_rings > 0) {
8227
    FORLIM = n_rings;
8228
    for (i = 1; i <= FORLIM; i++) {
8229
            chk_oxo_thioxo_imino_hetarene (i);
8230
            if (is_arene (i))
8231
              fg[fg_aromatic - 1] = true;
8232
            if (is_heterocycle (i))
8233
              fg[fg_heterocycle - 1] = true;
8234
          }
8235
  }
6785 bpr 8236
  if (pos_chg + neg_chg > 0)
8237
    fg[fg_cation - 1] = true;
8238
  if (pos_chg + neg_chg < 0)
8239
    fg[fg_anion - 1] = true;
8240
}
8241
 
14179 bpr 8242
static void write_fg_text ()
6785 bpr 8243
{
8244
  if (fg[fg_cation - 1])
8245
    printf ("cation\n");
8246
  if (fg[fg_anion - 1])
8247
    printf ("anion\n");
8248
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
8249
  if (fg[fg_aldehyde - 1])
8250
    printf ("aldehyde\n");
8251
  if (fg[fg_ketone - 1])
8252
    printf ("ketone\n");
8253
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
8254
  if (fg[fg_thioaldehyde - 1])
8255
    printf ("thioaldehyde\n");
8256
  if (fg[fg_thioketone - 1])
8257
    printf ("thioketone\n");
8258
  if (fg[fg_imine - 1])
8259
    printf ("imine\n");
8260
  if (fg[fg_hydrazone - 1])
8261
    printf ("hydrazone\n");
8262
  if (fg[fg_semicarbazone - 1])
8263
    printf ("semicarbazone\n");
8264
  if (fg[fg_thiosemicarbazone - 1])
8265
    printf ("thiosemicarbazone\n");
8266
  if (fg[fg_oxime - 1])
8267
    printf ("oxime\n");
8268
  if (fg[fg_oxime_ether - 1])
8269
    printf ("oxime ether\n");
8270
  if (fg[fg_ketene - 1])
8271
    printf ("ketene\n");
8272
  if (fg[fg_ketene_acetal_deriv - 1])
8273
    printf ("ketene acetal or derivative\n");
8274
  if (fg[fg_carbonyl_hydrate - 1])
8275
    printf ("carbonyl hydrate\n");
8276
  if (fg[fg_hemiacetal - 1])
8277
    printf ("hemiacetal\n");
8278
  if (fg[fg_acetal - 1])
8279
    printf ("acetal\n");
8280
  if (fg[fg_hemiaminal - 1])
8281
    printf ("hemiaminal\n");
8282
  if (fg[fg_aminal - 1])
8283
    printf ("aminal\n");
8284
  if (fg[fg_thiohemiaminal - 1])
8285
    printf ("hemithioaminal\n");
8286
  if (fg[fg_thioacetal - 1])
8287
    printf ("thioacetal\n");
8288
  if (fg[fg_enamine - 1])
8289
    printf ("enamine\n");
8290
  if (fg[fg_enol - 1])
8291
    printf ("enol\n");
8292
  if (fg[fg_enolether - 1])
8293
    printf ("enol ether\n");
8294
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8295
    printf ("hydroxy compound\n");
8296
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
8297
  if (fg[fg_prim_alcohol - 1])
8298
    printf ("primary alcohol\n");
8299
  if (fg[fg_sec_alcohol - 1])
8300
    printf ("secondary alcohol\n");
8301
  if (fg[fg_tert_alcohol - 1])
8302
    printf ("tertiary alcohol\n");
8303
  if (fg[fg_1_2_diol - 1])
8304
    printf ("1,2-diol\n");
8305
  if (fg[fg_1_2_aminoalcohol - 1])
8306
    printf ("1,2-aminoalcohol\n");
8307
  if (fg[fg_phenol - 1])
8308
    printf ("phenol or hydroxyhetarene\n");
8309
  if (fg[fg_1_2_diphenol - 1])
8310
    printf ("1,2-diphenol\n");
8311
  if (fg[fg_enediol - 1])
8312
    printf ("enediol\n");
8313
  if (fg[fg_ether - 1] && ether_generic)
8314
    printf ("ether\n");
8315
  if (fg[fg_dialkylether - 1])
8316
    printf ("dialkyl ether\n");
8317
  if (fg[fg_alkylarylether - 1])
8318
    printf ("alkyl aryl ether \n");
8319
  if (fg[fg_diarylether - 1])
8320
    printf ("diaryl ether\n");
8321
  if (fg[fg_thioether - 1])
8322
    printf ("thioether\n");
8323
  if (fg[fg_disulfide - 1])
8324
    printf ("disulfide\n");
8325
  if (fg[fg_peroxide - 1])
8326
    printf ("peroxide\n");
8327
  if (fg[fg_hydroperoxide - 1])
8328
    printf ("hydroperoxide \n");
8329
  if (fg[fg_hydrazine - 1])
8330
    printf ("hydrazine derivative\n");
8331
  if (fg[fg_hydroxylamine - 1])
8332
    printf ("hydroxylamine\n");
8333
  if (fg[fg_amine - 1] && amine_generic)
8334
    printf ("amine\n");
8335
  if (fg[fg_prim_amine - 1])
8336
    printf ("primary amine\n");
8337
  if (fg[fg_prim_aliph_amine - 1])
8338
    printf ("primary aliphatic amine (alkylamine)\n");
8339
  if (fg[fg_prim_arom_amine - 1])
8340
    printf ("primary aromatic amine\n");
8341
  if (fg[fg_sec_amine - 1])
8342
    printf ("secondary amine\n");
8343
  if (fg[fg_sec_aliph_amine - 1])
8344
    printf ("secondary aliphatic amine (dialkylamine)\n");
8345
  if (fg[fg_sec_mixed_amine - 1])
8346
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
8347
  if (fg[fg_sec_arom_amine - 1])
8348
    printf ("secondary aromatic amine (diarylamine)\n");
8349
  if (fg[fg_tert_amine - 1])
8350
    printf ("tertiary amine\n");
8351
  if (fg[fg_tert_aliph_amine - 1])
8352
    printf ("tertiary aliphatic amine (trialkylamine)\n");
8353
  if (fg[fg_tert_mixed_amine - 1])
8354
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
8355
  if (fg[fg_tert_arom_amine - 1])
8356
    printf ("tertiary aromatic amine (triarylamine)\n");
8357
  if (fg[fg_quart_ammonium - 1])
8358
    printf ("quaternary ammonium salt\n");
8359
  if (fg[fg_n_oxide - 1])
8360
    printf ("N-oxide\n");
8361
  /* new in v0.2f */
14179 bpr 8362
  if (fg[fg_halogen_deriv - 1]) {
6785 bpr 8363
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
14179 bpr 8364
              !fg[fg_acyl_halide - 1])
8365
            printf ("halogen derivative\n");
8366
  }
6785 bpr 8367
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
8368
  if (fg[fg_alkyl_fluoride - 1])
8369
    printf ("alkyl fluoride\n");
8370
  if (fg[fg_alkyl_chloride - 1])
8371
    printf ("alkyl chloride\n");
8372
  if (fg[fg_alkyl_bromide - 1])
8373
    printf ("alkyl bromide\n");
8374
  if (fg[fg_alkyl_iodide - 1])
8375
    printf ("alkyl iodide\n");
8376
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
8377
  if (fg[fg_aryl_fluoride - 1])
8378
    printf ("aryl fluoride\n");
8379
  if (fg[fg_aryl_chloride - 1])
8380
    printf ("aryl chloride\n");
8381
  if (fg[fg_aryl_bromide - 1])
8382
    printf ("aryl bromide\n");
8383
  if (fg[fg_aryl_iodide - 1])
8384
    printf ("aryl iodide\n");
8385
  if (fg[fg_organometallic - 1])
8386
    printf ("organometallic compound\n");
8387
  if (fg[fg_organolithium - 1])
8388
    printf ("organolithium compound\n");
8389
  if (fg[fg_organomagnesium - 1])
8390
    printf ("organomagnesium compound\n");
8391
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
8392
  if (fg[fg_carboxylic_acid - 1])
8393
    printf ("carboxylic acid\n");
8394
  if (fg[fg_carboxylic_acid_salt - 1])
8395
    printf ("carboxylic acid salt\n");
8396
  if (fg[fg_carboxylic_acid_ester - 1])
8397
    printf ("carboxylic acid ester\n");
8398
  if (fg[fg_lactone - 1])
8399
    printf ("lactone\n");
8400
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
8401
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8402
    printf ("primary carboxylic acid amide\n");
8403
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8404
    printf ("secondary carboxylic acid amide\n");
8405
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8406
    printf ("tertiary carboxylic acid amide\n");
8407
  if (fg[fg_lactam - 1])
8408
    printf ("lactam\n");
8409
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8410
    printf ("carboxylic acid hydrazide\n");
8411
  if (fg[fg_carboxylic_acid_azide - 1])
8412
    printf ("carboxylic acid azide\n");
8413
  if (fg[fg_hydroxamic_acid - 1])
8414
    printf ("hydroxamic acid\n");
8415
  if (fg[fg_carboxylic_acid_amidine - 1])
8416
    printf ("carboxylic acid amidine\n");
8417
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8418
    printf ("carboxylic acid amidrazone\n");
8419
  if (fg[fg_nitrile - 1])
8420
    printf ("carbonitrile\n");
8421
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
8422
  if (fg[fg_acyl_fluoride - 1])
8423
    printf ("acyl fluoride\n");
8424
  if (fg[fg_acyl_chloride - 1])
8425
    printf ("acyl chloride\n");
8426
  if (fg[fg_acyl_bromide - 1])
8427
    printf ("acyl bromide\n");
8428
  if (fg[fg_acyl_iodide - 1])
8429
    printf ("acyl iodide\n");
8430
  if (fg[fg_acyl_cyanide - 1])
8431
    printf ("acyl cyanide\n");
8432
  if (fg[fg_imido_ester - 1])
8433
    printf ("imido ester\n");
8434
  if (fg[fg_imidoyl_halide - 1])
8435
    printf ("imidoyl halide\n");
8436
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
8437
  if (fg[fg_thiocarboxylic_acid - 1])
8438
    printf ("thiocarboxylic acid\n");
8439
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8440
    printf ("thiocarboxylic acid ester\n");
8441
  if (fg[fg_thiolactone - 1])
8442
    printf ("thiolactone\n");
8443
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8444
    printf ("thiocarboxylic acid amide\n");
8445
  if (fg[fg_thiolactam - 1])
8446
    printf ("thiolactam\n");
8447
  if (fg[fg_imido_thioester - 1])
8448
    printf ("imidothioester\n");
8449
  if (fg[fg_oxohetarene - 1])
8450
    printf ("oxo(het)arene\n");
8451
  if (fg[fg_thioxohetarene - 1])
8452
    printf ("thioxo(het)arene\n");
8453
  if (fg[fg_iminohetarene - 1])
8454
    printf ("imino(het)arene\n");
8455
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8456
    printf ("orthocarboxylic acid derivative\n");
8457
  if (fg[fg_carboxylic_acid_orthoester - 1])
8458
    printf ("orthoester\n");
8459
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8460
    printf ("amide acetal\n");
8461
  if (fg[fg_carboxylic_acid_anhydride - 1])
8462
    printf ("carboxylic acid anhydride\n");
8463
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
8464
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8465
    printf ("carboxylic acid imide, N-unsubstituted\n");
8466
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8467
    printf ("carboxylic acid imide, N-substituted\n");
8468
  if (fg[fg_co2_deriv - 1])
8469
    printf ("CO2 derivative (general)\n");
8470
  if (fg[fg_carbonic_acid_deriv - 1] &&
8471
      !(fg[fg_carbonic_acid_monoester - 1]
8472
        || fg[fg_carbonic_acid_diester - 1]
8473
        || fg[fg_carbonic_acid_ester_halide - 1]))
8474
    /* changed in v0.3c */
8475
    printf ("carbonic acid derivative\n");
8476
  if (fg[fg_carbonic_acid_monoester - 1])
8477
    printf ("carbonic acid monoester\n");
8478
  if (fg[fg_carbonic_acid_diester - 1])
8479
    printf ("carbonic acid diester\n");
8480
  if (fg[fg_carbonic_acid_ester_halide - 1])
8481
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
8482
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8483
    printf ("thiocarbonic acid derivative\n");
8484
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8485
    printf ("thiocarbonic acid monoester\n");
8486
  if (fg[fg_thiocarbonic_acid_diester - 1])
8487
    printf ("thiocarbonic acid diester\n");
8488
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
8489
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
8490
  if (fg[fg_carbamic_acid_deriv - 1]
8491
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
8492
           || fg[fg_carbamic_acid_halide - 1]))
8493
    /* changed in v0.3c */
8494
    printf ("carbamic acid derivative\n");
8495
  if (fg[fg_carbamic_acid - 1])
8496
    printf ("carbamic acid\n");
8497
  if (fg[fg_carbamic_acid_ester - 1])
8498
    printf ("carbamic acid ester (urethane)\n");
8499
  if (fg[fg_carbamic_acid_halide - 1])
8500
    printf ("carbamic acid halide (haloformic acid amide)\n");
8501
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8502
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
8503
        || fg[fg_thiocarbamic_acid_halide - 1]))
8504
    /* changed in v0.3c */
8505
    printf ("thiocarbamic acid derivative\n");
8506
  if (fg[fg_thiocarbamic_acid - 1])
8507
    printf ("thiocarbamic acid\n");
8508
  if (fg[fg_thiocarbamic_acid_ester - 1])
8509
    printf ("thiocarbamic acid ester\n");
8510
  if (fg[fg_thiocarbamic_acid_halide - 1])
8511
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
8512
  if (fg[fg_urea - 1])
8513
    printf ("urea\n");
8514
  if (fg[fg_isourea - 1])
8515
    printf ("isourea\n");
8516
  if (fg[fg_thiourea - 1])
8517
    printf ("thiourea\n");
8518
  if (fg[fg_isothiourea - 1])
8519
    printf ("isothiourea\n");
8520
  if (fg[fg_guanidine - 1])
8521
    printf ("guanidine\n");
8522
  if (fg[fg_semicarbazide - 1])
8523
    printf ("semicarbazide\n");
8524
  if (fg[fg_thiosemicarbazide - 1])
8525
    printf ("thiosemicarbazide\n");
8526
  if (fg[fg_azide - 1])
8527
    printf ("azide\n");
8528
  if (fg[fg_azo_compound - 1])
8529
    printf ("azo compound\n");
8530
  if (fg[fg_diazonium_salt - 1])
8531
    printf ("diazonium salt\n");
8532
  if (fg[fg_isonitrile - 1])
8533
    printf ("isonitrile\n");
8534
  if (fg[fg_cyanate - 1])
8535
    printf ("cyanate\n");
8536
  if (fg[fg_isocyanate - 1])
8537
    printf ("isocyanate\n");
8538
  if (fg[fg_thiocyanate - 1])
8539
    printf ("thiocyanate\n");
8540
  if (fg[fg_isothiocyanate - 1])
8541
    printf ("isothiocyanate\n");
8542
  if (fg[fg_carbodiimide - 1])
8543
    printf ("carbodiimide\n");
8544
  if (fg[fg_nitroso_compound - 1])
8545
    printf ("nitroso compound\n");
8546
  if (fg[fg_nitro_compound - 1])
8547
    printf ("nitro compound\n");
8548
  if (fg[fg_nitrite - 1])
8549
    printf ("nitrite\n");
8550
  if (fg[fg_nitrate - 1])
8551
    printf ("nitrate\n");
8552
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
8553
  if (fg[fg_sulfuric_acid - 1])
8554
    printf ("sulfuric acid\n");
8555
  if (fg[fg_sulfuric_acid_monoester - 1])
8556
    printf ("sulfuric acid monoester\n");
8557
  if (fg[fg_sulfuric_acid_diester - 1])
8558
    printf ("sulfuric acid diester\n");
8559
  if (fg[fg_sulfuric_acid_amide_ester - 1])
8560
    printf ("sulfuric acid amide ester\n");
8561
  if (fg[fg_sulfuric_acid_amide - 1])
8562
    printf ("sulfuric acid amide\n");
8563
  if (fg[fg_sulfuric_acid_diamide - 1])
8564
    printf ("sulfuric acid diamide\n");
8565
  if (fg[fg_sulfuryl_halide - 1])
8566
    printf ("sulfuryl halide\n");
8567
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
8568
  if (fg[fg_sulfonic_acid - 1])
8569
    printf ("sulfonic acid\n");
8570
  if (fg[fg_sulfonic_acid_ester - 1])
8571
    printf ("sulfonic acid ester\n");
8572
  if (fg[fg_sulfonamide - 1])
8573
    printf ("sulfonamide\n");
8574
  if (fg[fg_sulfonyl_halide - 1])
8575
    printf ("sulfonyl halide\n");
8576
  if (fg[fg_sulfone - 1])
8577
    printf ("sulfone\n");
8578
  if (fg[fg_sulfoxide - 1])
8579
    printf ("sulfoxide\n");
8580
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
8581
  if (fg[fg_sulfinic_acid - 1])
8582
    printf ("sulfinic acid\n");
8583
  if (fg[fg_sulfinic_acid_ester - 1])
8584
    printf ("sulfinic acid ester\n");
8585
  if (fg[fg_sulfinic_acid_halide - 1])
8586
    printf ("sulfinic acid halide\n");
8587
  if (fg[fg_sulfinic_acid_amide - 1])
8588
    printf ("sulfinic acid amide\n");
8589
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
8590
  if (fg[fg_sulfenic_acid - 1])
8591
    printf ("sulfenic acid\n");
8592
  if (fg[fg_sulfenic_acid_ester - 1])
8593
    printf ("sulfenic acid ester\n");
8594
  if (fg[fg_sulfenic_acid_halide - 1])
8595
    printf ("sulfenic acid halide\n");
8596
  if (fg[fg_sulfenic_acid_amide - 1])
8597
    printf ("sulfenic acid amide\n");
8598
  if (fg[fg_thiol - 1])
8599
    printf ("thiol (sulfanyl compound)\n");
8600
  if (fg[fg_alkylthiol - 1])
8601
    printf ("alkylthiol\n");
8602
  if (fg[fg_arylthiol - 1])
8603
    printf ("arylthiol\n");
8604
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
8605
  if (fg[fg_phosphoric_acid - 1])
8606
    printf ("phosphoric acid\n");
8607
  if (fg[fg_phosphoric_acid_ester - 1])
8608
    printf ("phosphoric acid ester\n");
8609
  if (fg[fg_phosphoric_acid_halide - 1])
8610
    printf ("phosphoric acid halide\n");
8611
  if (fg[fg_phosphoric_acid_amide - 1])
8612
    printf ("phosphoric acid amide\n");
8613
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
8614
  if (fg[fg_thiophosphoric_acid - 1])
8615
    printf ("thiophosphoric acid\n");
8616
  if (fg[fg_thiophosphoric_acid_ester - 1])
8617
    printf ("thiophosphoric acid ester\n");
8618
  if (fg[fg_thiophosphoric_acid_halide - 1])
8619
    printf ("thiophosphoric acid halide\n");
8620
  if (fg[fg_thiophosphoric_acid_amide - 1])
8621
    printf ("thiophosphoric acid amide\n");
8622
  if (fg[fg_phosphonic_acid_deriv - 1])
8623
    printf ("phosphonic acid derivative \n");
8624
  if (fg[fg_phosphonic_acid - 1])
8625
    printf ("phosphonic acid\n");
8626
  if (fg[fg_phosphonic_acid_ester - 1])
8627
    printf ("phosphonic acid ester\n");
8628
  if (fg[fg_phosphine - 1])
8629
    printf ("phosphine\n");
8630
  if (fg[fg_phosphinoxide - 1])
8631
    printf ("phosphine oxide\n");
8632
  if (fg[fg_boronic_acid_deriv - 1])
8633
    printf ("boronic acid derivative\n");
8634
  if (fg[fg_boronic_acid - 1])
8635
    printf ("boronic acid\n");
8636
  if (fg[fg_boronic_acid_ester - 1])
8637
    printf ("boronic acid ester\n");
8638
  if (fg[fg_alkene - 1])
8639
    printf ("alkene\n");
8640
  if (fg[fg_alkyne - 1])
8641
    printf ("alkyne\n");
8642
  if (fg[fg_aromatic - 1])
8643
    printf ("aromatic compound\n");
8644
  if (fg[fg_heterocycle - 1])
8645
    printf ("heterocyclic compound\n");
8646
  if (fg[fg_alpha_aminoacid - 1])
8647
    printf ("alpha-aminoacid\n");
8648
  if (fg[fg_alpha_hydroxyacid - 1])
8649
    printf ("alpha-hydroxyacid\n");
8650
}
8651
 
14179 bpr 8652
static void write_fg_text_de ()
6785 bpr 8653
{
8654
  if (fg[fg_cation - 1])
8655
    printf ("Kation\n");
8656
  if (fg[fg_anion - 1])
8657
    printf ("Anion\n");
8658
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
8659
  if (fg[fg_aldehyde - 1])
8660
    printf ("Aldehyd\n");
8661
  if (fg[fg_ketone - 1])
8662
    printf ("Keton\n");
8663
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
8664
  if (fg[fg_thioaldehyde - 1])
8665
    printf ("Thioaldehyd\n");
8666
  if (fg[fg_thioketone - 1])
8667
    printf ("Thioketon\n");
8668
  if (fg[fg_imine - 1])
8669
    printf ("Imin\n");
8670
  if (fg[fg_hydrazone - 1])
8671
    printf ("Hydrazon\n");
8672
  if (fg[fg_semicarbazone - 1])
8673
    printf ("Semicarbazon\n");
8674
  if (fg[fg_thiosemicarbazone - 1])
8675
    printf ("Thiosemicarbazon\n");
8676
  if (fg[fg_oxime - 1])
8677
    printf ("Oxim\n");
8678
  if (fg[fg_oxime_ether - 1])
8679
    printf ("Oximether\n");
8680
  if (fg[fg_ketene - 1])
8681
    printf ("Keten\n");
8682
  if (fg[fg_ketene_acetal_deriv - 1])
8683
    printf ("Keten-Acetal oder Derivat\n");
8684
  if (fg[fg_carbonyl_hydrate - 1])
8685
    printf ("Carbonyl-Hydrat\n");
8686
  if (fg[fg_hemiacetal - 1])
8687
    printf ("Halbacetal\n");
8688
  if (fg[fg_acetal - 1])
8689
    printf ("Acetal\n");
8690
  if (fg[fg_hemiaminal - 1])
8691
    printf ("Halbaminal\n");
8692
  if (fg[fg_aminal - 1])
8693
    printf ("Aminal\n");
8694
  if (fg[fg_thiohemiaminal - 1])
8695
    printf ("Thiohalbaminal\n");
8696
  if (fg[fg_thioacetal - 1])
8697
    printf ("Thioacetal\n");
8698
  if (fg[fg_enamine - 1])
8699
    printf ("Enamin\n");
8700
  if (fg[fg_enol - 1])
8701
    printf ("Enol\n");
8702
  if (fg[fg_enolether - 1])
8703
    printf ("Enolether\n");
8704
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8705
    printf ("Hydroxy-Verbindung\n");
8706
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
8707
  if (fg[fg_prim_alcohol - 1])
8708
    printf ("prim\344rer Alkohol\n");
14179 bpr 8709
  /* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
6785 bpr 8710
  if (fg[fg_sec_alcohol - 1])
8711
    printf ("sekund\344rer Alkohol\n");
14179 bpr 8712
  /* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
6785 bpr 8713
  if (fg[fg_tert_alcohol - 1])
8714
    printf ("terti\344rer Alkohol\n");
14179 bpr 8715
  /* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
6785 bpr 8716
  if (fg[fg_1_2_diol - 1])
8717
    printf ("1,2-Diol\n");
8718
  if (fg[fg_1_2_aminoalcohol - 1])
8719
    printf ("1,2-Aminoalkohol\n");
8720
  if (fg[fg_phenol - 1])
8721
    printf ("Phenol oder Hydroxyhetaren\n");
8722
  if (fg[fg_1_2_diphenol - 1])
8723
    printf ("1,2-Diphenol\n");
8724
  if (fg[fg_enediol - 1])
8725
    printf ("Endiol\n");
8726
  if (fg[fg_ether - 1] && ether_generic)
8727
    printf ("Ether\n");
8728
  if (fg[fg_dialkylether - 1])
8729
    printf ("Dialkylether\n");
8730
  if (fg[fg_alkylarylether - 1])
8731
    printf ("Alkylarylether \n");
8732
  if (fg[fg_diarylether - 1])
8733
    printf ("Diarylether\n");
8734
  if (fg[fg_thioether - 1])
8735
    printf ("Thioether\n");
8736
  if (fg[fg_disulfide - 1])
8737
    printf ("Disulfid\n");
8738
  if (fg[fg_peroxide - 1])
8739
    printf ("Peroxid\n");
8740
  if (fg[fg_hydroperoxide - 1])
8741
    printf ("Hydroperoxid\n");
8742
  if (fg[fg_hydrazine - 1])
8743
    printf ("Hydrazin-Derivat\n");
8744
  if (fg[fg_hydroxylamine - 1])
8745
    printf ("Hydroxylamin\n");
8746
  if (fg[fg_amine - 1] && amine_generic)
8747
    printf ("Amin\n");
8748
  if (fg[fg_prim_amine - 1])
8749
    printf ("prim\344res Amin\n");
14179 bpr 8750
  /* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
6785 bpr 8751
  if (fg[fg_prim_aliph_amine - 1])
8752
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
14179 bpr 8753
  /* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
6785 bpr 8754
  if (fg[fg_prim_arom_amine - 1])
8755
    printf ("prim\344res aromatisches Amin\n");
14179 bpr 8756
  /* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
6785 bpr 8757
  if (fg[fg_sec_amine - 1])
8758
    printf ("sekund\344res Amin\n");
14179 bpr 8759
  /* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
6785 bpr 8760
  if (fg[fg_sec_aliph_amine - 1])
8761
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
14179 bpr 8762
  /* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
6785 bpr 8763
  if (fg[fg_sec_mixed_amine - 1])
8764
    printf
8765
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8766
  /* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
6785 bpr 8767
  if (fg[fg_sec_arom_amine - 1])
8768
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
14179 bpr 8769
  /* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
6785 bpr 8770
  if (fg[fg_tert_amine - 1])
8771
    printf ("terti\344res Amin\n");
14179 bpr 8772
  /* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
6785 bpr 8773
  if (fg[fg_tert_aliph_amine - 1])
8774
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
14179 bpr 8775
  /* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
6785 bpr 8776
  if (fg[fg_tert_mixed_amine - 1])
8777
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8778
  /* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
6785 bpr 8779
  if (fg[fg_tert_arom_amine - 1])
8780
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
14179 bpr 8781
  /* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
6785 bpr 8782
  if (fg[fg_quart_ammonium - 1])
8783
    printf ("quart\344res Ammoniumsalz\n");
14179 bpr 8784
  /* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
6785 bpr 8785
  if (fg[fg_n_oxide - 1])
8786
    printf ("N-Oxid\n");
8787
  /* new in v0.2f */
14179 bpr 8788
  if (fg[fg_halogen_deriv - 1]) {
8789
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
8790
              !fg[fg_acyl_halide - 1])
8791
            printf ("Halogenverbindung\n");
8792
  }
6785 bpr 8793
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
8794
  if (fg[fg_alkyl_fluoride - 1])
8795
    printf ("Alkylfluorid\n");
8796
  if (fg[fg_alkyl_chloride - 1])
8797
    printf ("Alkylchlorid\n");
8798
  if (fg[fg_alkyl_bromide - 1])
8799
    printf ("Alkylbromid\n");
8800
  if (fg[fg_alkyl_iodide - 1])
8801
    printf ("Alkyliodid\n");
8802
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
8803
  if (fg[fg_aryl_fluoride - 1])
8804
    printf ("Arylfluorid\n");
8805
  if (fg[fg_aryl_chloride - 1])
8806
    printf ("Arylchlorid\n");
8807
  if (fg[fg_aryl_bromide - 1])
8808
    printf ("Arylbromid\n");
8809
  if (fg[fg_aryl_iodide - 1])
8810
    printf ("Aryliodid\n");
8811
  if (fg[fg_organometallic - 1])
8812
    printf ("Organometall-Verbindung\n");
8813
  if (fg[fg_organolithium - 1])
8814
    printf ("Organolithium-Verbindung\n");
8815
  if (fg[fg_organomagnesium - 1])
8816
    printf ("Organomagnesium-Verbindung\n");
8817
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
8818
  if (fg[fg_carboxylic_acid - 1])
8819
    printf ("Carbons\344ure\n");
14179 bpr 8820
  /* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
6785 bpr 8821
  if (fg[fg_carboxylic_acid_salt - 1])
8822
    printf ("Carbons\344uresalz\n");
14179 bpr 8823
  /* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
6785 bpr 8824
  if (fg[fg_carboxylic_acid_ester - 1])
8825
    printf ("Carbons\344ureester\n");
14179 bpr 8826
  /* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
6785 bpr 8827
  if (fg[fg_lactone - 1])
8828
    printf ("Lacton\n");
8829
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
8830
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8831
    printf ("prim\344res Carbons\344ureamid\n");
14179 bpr 8832
  /* p2c: checkmol.pas, line 7340:
8833
  * Note: characters >= 128 encountered [281] */
6785 bpr 8834
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8835
    printf ("sekund\344res Carbons\344ureamid\n");
14179 bpr 8836
  /* p2c: checkmol.pas, line 7341:
8837
  * Note: characters >= 128 encountered [281] */
6785 bpr 8838
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8839
    printf ("terti\344res Carbons\344ureamid\n");
14179 bpr 8840
  /* p2c: checkmol.pas, line 7342:
8841
  * Note: characters >= 128 encountered [281] */
6785 bpr 8842
  if (fg[fg_lactam - 1])
8843
    printf ("Lactam\n");
8844
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8845
    printf ("Carbons\344urehydrazid\n");
14179 bpr 8846
  /* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
6785 bpr 8847
  if (fg[fg_carboxylic_acid_azide - 1])
8848
    printf ("Carbons\344ureazid\n");
14179 bpr 8849
  /* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
6785 bpr 8850
  if (fg[fg_hydroxamic_acid - 1])
8851
    printf ("Hydroxams\344ure\n");
14179 bpr 8852
  /* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
6785 bpr 8853
  if (fg[fg_carboxylic_acid_amidine - 1])
8854
    printf ("Carbons\344ureamidin\n");
14179 bpr 8855
  /* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
6785 bpr 8856
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8857
    printf ("Carbons\344ureamidrazon\n");
14179 bpr 8858
  /* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
6785 bpr 8859
  if (fg[fg_nitrile - 1])
8860
    printf ("Carbonitril\n");
8861
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
8862
  if (fg[fg_acyl_fluoride - 1])
8863
    printf ("Acylfluorid\n");
8864
  if (fg[fg_acyl_chloride - 1])
8865
    printf ("Acylchlorid\n");
8866
  if (fg[fg_acyl_bromide - 1])
8867
    printf ("Acylbromid\n");
8868
  if (fg[fg_acyl_iodide - 1])
8869
    printf ("Acyliodid\n");
8870
  if (fg[fg_acyl_cyanide - 1])
8871
    printf ("Acylcyanid\n");
8872
  if (fg[fg_imido_ester - 1])
8873
    printf ("Imidoester\n");
8874
  if (fg[fg_imidoyl_halide - 1])
8875
    printf ("Imidoylhalogenid\n");
8876
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
8877
  if (fg[fg_thiocarboxylic_acid - 1])
8878
    printf ("Thiocarbons\344ure\n");
14179 bpr 8879
  /* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
6785 bpr 8880
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8881
    printf ("Thiocarbons\344ureester\n");
14179 bpr 8882
  /* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
6785 bpr 8883
  if (fg[fg_thiolactone - 1])
8884
    printf ("Thiolacton\n");
8885
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8886
    printf ("Thiocarbons\344ureamid\n");
14179 bpr 8887
  /* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
6785 bpr 8888
  if (fg[fg_thiolactam - 1])
8889
    printf ("Thiolactam\n");
8890
  if (fg[fg_imido_thioester - 1])
8891
    printf ("Imidothioester\n");
8892
  if (fg[fg_oxohetarene - 1])
8893
    printf ("Oxo(het)aren\n");
8894
  if (fg[fg_thioxohetarene - 1])
8895
    printf ("Thioxo(het)aren\n");
8896
  if (fg[fg_iminohetarene - 1])
8897
    printf ("Imino(het)aren\n");
8898
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8899
    printf ("Orthocarbons\344ure-Derivat\n");
14179 bpr 8900
  /* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
6785 bpr 8901
  if (fg[fg_carboxylic_acid_orthoester - 1])
8902
    printf ("Orthoester\n");
8903
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8904
    printf ("Amidacetal\n");
8905
  if (fg[fg_carboxylic_acid_anhydride - 1])
8906
    printf ("Carbons\344ureanhydrid\n");
14179 bpr 8907
  /* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
6785 bpr 8908
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
8909
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8910
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
14179 bpr 8911
  /* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
6785 bpr 8912
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8913
    printf ("Carbons\344ureimid, N-substituiert\n");
14179 bpr 8914
  /* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
6785 bpr 8915
  if (fg[fg_co2_deriv - 1])
8916
    printf ("CO2-Derivat (allgemein)\n");
14179 bpr 8917
  if (fg[fg_carbonic_acid_deriv - 1] && !(fg[fg_carbonic_acid_monoester - 1]
8918
            || fg[fg_carbonic_acid_diester - 1] || fg[fg_carbonic_acid_ester_halide - 1]))
6785 bpr 8919
    /* changed in v0.3c */
8920
    printf ("Kohlens\344ure-Derivat\n");
14179 bpr 8921
  /* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
6785 bpr 8922
  if (fg[fg_carbonic_acid_monoester - 1])
8923
    printf ("Kohlens\344uremonoester\n");
14179 bpr 8924
  /* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
6785 bpr 8925
  if (fg[fg_carbonic_acid_diester - 1])
8926
    printf ("Kohlens\344urediester\n");
14179 bpr 8927
  /* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
6785 bpr 8928
  if (fg[fg_carbonic_acid_ester_halide - 1])
8929
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
14179 bpr 8930
  /* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
6785 bpr 8931
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8932
    printf ("Thiokohlens\344ure-Derivat\n");
14179 bpr 8933
  /* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
6785 bpr 8934
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8935
    printf ("Thiokohlens\344uremonoester\n");
14179 bpr 8936
  /* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
6785 bpr 8937
  if (fg[fg_thiocarbonic_acid_diester - 1])
8938
    printf ("Thiokohlens\344urediester\n");
14179 bpr 8939
  /* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
6785 bpr 8940
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
14179 bpr 8941
    printf ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
8942
  /* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
6785 bpr 8943
  if (fg[fg_carbamic_acid_deriv - 1] &&
8944
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
14179 bpr 8945
            fg[fg_carbamic_acid_halide - 1]))
6785 bpr 8946
    /* changed in v0.3c */
8947
    printf ("Carbamins\344ure-Derivat\n");
14179 bpr 8948
  /* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
6785 bpr 8949
  if (fg[fg_carbamic_acid - 1])
8950
    printf ("Carbamins\344ure\n");
14179 bpr 8951
  /* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
6785 bpr 8952
  if (fg[fg_carbamic_acid_ester - 1])
8953
    printf ("Carbamins\344ureester (Urethan)\n");
14179 bpr 8954
  /* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
6785 bpr 8955
  if (fg[fg_carbamic_acid_halide - 1])
8956
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
14179 bpr 8957
  /* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
6785 bpr 8958
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8959
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
14179 bpr 8960
            || fg[fg_thiocarbamic_acid_halide - 1]))
6785 bpr 8961
    /* changed in v0.3c */
8962
    printf ("Thiocarbamins\344ure-Derivat\n");
14179 bpr 8963
  /* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
6785 bpr 8964
  if (fg[fg_thiocarbamic_acid - 1])
8965
    printf ("Thiocarbamins\344ure\n");
14179 bpr 8966
  /* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
6785 bpr 8967
  if (fg[fg_thiocarbamic_acid_ester - 1])
8968
    printf ("Thiocarbamins\344ureester\n");
14179 bpr 8969
  /* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
6785 bpr 8970
  if (fg[fg_thiocarbamic_acid_halide - 1])
8971
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
14179 bpr 8972
  /* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
6785 bpr 8973
  if (fg[fg_urea - 1])
8974
    printf ("Harnstoff\n");
8975
  if (fg[fg_isourea - 1])
8976
    printf ("Isoharnstoff\n");
8977
  if (fg[fg_thiourea - 1])
8978
    printf ("Thioharnstoff\n");
8979
  if (fg[fg_isothiourea - 1])
8980
    printf ("Isothioharnstoff\n");
8981
  if (fg[fg_guanidine - 1])
8982
    printf ("Guanidin\n");
8983
  if (fg[fg_semicarbazide - 1])
8984
    printf ("Semicarbazid\n");
8985
  if (fg[fg_thiosemicarbazide - 1])
8986
    printf ("Thiosemicarbazid\n");
8987
  if (fg[fg_azide - 1])
8988
    printf ("Azid\n");
8989
  if (fg[fg_azo_compound - 1])
8990
    printf ("Azoverbindung\n");
8991
  if (fg[fg_diazonium_salt - 1])
8992
    printf ("Diazoniumsalz\n");
8993
  if (fg[fg_isonitrile - 1])
8994
    printf ("Isonitril\n");
8995
  if (fg[fg_cyanate - 1])
8996
    printf ("Cyanat\n");
8997
  if (fg[fg_isocyanate - 1])
8998
    printf ("Isocyanat\n");
8999
  if (fg[fg_thiocyanate - 1])
9000
    printf ("Thiocyanat\n");
9001
  if (fg[fg_isothiocyanate - 1])
9002
    printf ("Isothiocyanat\n");
9003
  if (fg[fg_carbodiimide - 1])
9004
    printf ("Carbodiimid\n");
9005
  if (fg[fg_nitroso_compound - 1])
9006
    printf ("Nitroso-Verbindung\n");
9007
  if (fg[fg_nitro_compound - 1])
9008
    printf ("Nitro-Verbindung\n");
9009
  if (fg[fg_nitrite - 1])
9010
    printf ("Nitrit\n");
9011
  if (fg[fg_nitrate - 1])
9012
    printf ("Nitrat\n");
9013
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
9014
  if (fg[fg_sulfuric_acid - 1])
9015
    printf ("Schwefels\344ure\n");
14179 bpr 9016
  /* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
6785 bpr 9017
  if (fg[fg_sulfuric_acid_monoester - 1])
9018
    printf ("Schwefels\344uremonoester\n");
14179 bpr 9019
  /* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
6785 bpr 9020
  if (fg[fg_sulfuric_acid_diester - 1])
9021
    printf ("Schwefels\344urediester\n");
14179 bpr 9022
  /* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
6785 bpr 9023
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9024
    printf ("Schwefels\344ureamidester\n");
14179 bpr 9025
  /* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
6785 bpr 9026
  if (fg[fg_sulfuric_acid_amide - 1])
9027
    printf ("Schwefels\344ureamid\n");
14179 bpr 9028
  /* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
6785 bpr 9029
  if (fg[fg_sulfuric_acid_diamide - 1])
9030
    printf ("Schwefels\344urediamid\n");
14179 bpr 9031
  /* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
6785 bpr 9032
  if (fg[fg_sulfuryl_halide - 1])
9033
    printf ("Sulfurylhalogenid\n");
9034
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
9035
  if (fg[fg_sulfonic_acid - 1])
9036
    printf ("Sulfons\344ure\n");
14179 bpr 9037
  /* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
6785 bpr 9038
  if (fg[fg_sulfonic_acid_ester - 1])
9039
    printf ("Sulfons\344ureester\n");
14179 bpr 9040
  /* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
6785 bpr 9041
  if (fg[fg_sulfonamide - 1])
9042
    printf ("Sulfonamid\n");
9043
  if (fg[fg_sulfonyl_halide - 1])
9044
    printf ("Sulfonylhalogenid\n");
9045
  if (fg[fg_sulfone - 1])
9046
    printf ("Sulfon\n");
9047
  if (fg[fg_sulfoxide - 1])
9048
    printf ("Sulfoxid\n");
9049
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
9050
  if (fg[fg_sulfinic_acid - 1])
9051
    printf ("Sulfins\344ure\n");
14179 bpr 9052
  /* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
6785 bpr 9053
  if (fg[fg_sulfinic_acid_ester - 1])
9054
    printf ("Sulfins\344ureester\n");
14179 bpr 9055
  /* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
6785 bpr 9056
  if (fg[fg_sulfinic_acid_halide - 1])
9057
    printf ("Sulfins\344urehalogenid\n");
14179 bpr 9058
  /* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
6785 bpr 9059
  if (fg[fg_sulfinic_acid_amide - 1])
9060
    printf ("Sulfins\344ureamid\n");
14179 bpr 9061
  /* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
6785 bpr 9062
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
9063
  if (fg[fg_sulfenic_acid - 1])
9064
    printf ("Sulfens\344ure\n");
14179 bpr 9065
  /* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
6785 bpr 9066
  if (fg[fg_sulfenic_acid_ester - 1])
9067
    printf ("Sulfens\344ureester\n");
14179 bpr 9068
  /* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
6785 bpr 9069
  if (fg[fg_sulfenic_acid_halide - 1])
9070
    printf ("Sulfens\344urehalogenid\n");
14179 bpr 9071
  /* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
6785 bpr 9072
  if (fg[fg_sulfenic_acid_amide - 1])
9073
    printf ("Sulfens\344ureamid\n");
14179 bpr 9074
  /* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
6785 bpr 9075
  if (fg[fg_thiol - 1])
9076
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
9077
  if (fg[fg_alkylthiol - 1])
9078
    printf ("Alkylthiol\n");
9079
  if (fg[fg_arylthiol - 1])
9080
    printf ("Arylthiol\n");
9081
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
9082
  if (fg[fg_phosphoric_acid - 1])
9083
    printf ("Phosphors\344ure\n");
14179 bpr 9084
  /* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
6785 bpr 9085
  if (fg[fg_phosphoric_acid_ester - 1])
9086
    printf ("Phosphors\344ureester\n");
14179 bpr 9087
  /* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
6785 bpr 9088
  if (fg[fg_phosphoric_acid_halide - 1])
9089
    printf ("Phosphors\344urehalogenid\n");
14179 bpr 9090
  /* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
6785 bpr 9091
  if (fg[fg_phosphoric_acid_amide - 1])
9092
    printf ("Phosphors\344ureamid\n");
14179 bpr 9093
  /* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
6785 bpr 9094
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
9095
  if (fg[fg_thiophosphoric_acid - 1])
9096
    printf ("Thiophosphors\344ure\n");
14179 bpr 9097
  /* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
6785 bpr 9098
  if (fg[fg_thiophosphoric_acid_ester - 1])
9099
    printf ("Thiophosphors\344ureester\n");
14179 bpr 9100
  /* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
6785 bpr 9101
  if (fg[fg_thiophosphoric_acid_halide - 1])
9102
    printf ("Thiophosphors\344urehalogenid\n");
14179 bpr 9103
  /* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
6785 bpr 9104
  if (fg[fg_thiophosphoric_acid_amide - 1])
9105
    printf ("Thiophosphors\344ureamid\n");
14179 bpr 9106
  /* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
6785 bpr 9107
  if (fg[fg_phosphonic_acid_deriv - 1])
9108
    printf ("Phosphons\344ure-Derivat \n");
14179 bpr 9109
  /* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
6785 bpr 9110
  if (fg[fg_phosphonic_acid - 1])
9111
    printf ("Phosphons\344ure\n");
14179 bpr 9112
  /* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
6785 bpr 9113
  if (fg[fg_phosphonic_acid_ester - 1])
9114
    printf ("Phosphons\344ureester\n");
14179 bpr 9115
  /* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
6785 bpr 9116
  if (fg[fg_phosphine - 1])
9117
    printf ("Phosphin\n");
9118
  if (fg[fg_phosphinoxide - 1])
9119
    printf ("Phosphinoxid\n");
9120
  if (fg[fg_boronic_acid_deriv - 1])
9121
    printf ("Borons\344ure-Derivat\n");
14179 bpr 9122
  /* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
6785 bpr 9123
  if (fg[fg_boronic_acid - 1])
9124
    printf ("Borons\344ure\n");
14179 bpr 9125
  /* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
6785 bpr 9126
  if (fg[fg_boronic_acid_ester - 1])
9127
    printf ("Borons\344ureester\n");
14179 bpr 9128
  /* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
6785 bpr 9129
  if (fg[fg_alkene - 1])
9130
    printf ("Alken\n");
9131
  if (fg[fg_alkyne - 1])
9132
    printf ("Alkin\n");
9133
  if (fg[fg_aromatic - 1])
9134
    printf ("aromatische Verbindung\n");
9135
  if (fg[fg_heterocycle - 1])
9136
    printf ("heterocyclische Verbindung\n");
9137
  if (fg[fg_alpha_aminoacid - 1])
9138
    printf ("alpha-Aminos\344ure\n");
14179 bpr 9139
  /* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
6785 bpr 9140
  if (fg[fg_alpha_hydroxyacid - 1])
9141
    printf ("alpha-Hydroxys\344ure\n");
14179 bpr 9142
  /* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
6785 bpr 9143
}
9144
 
9145
#define sc              ';'
9146
 
14179 bpr 9147
static void write_fg_code ()
6785 bpr 9148
{
9149
  if (fg[fg_cation - 1])
9150
    printf ("000000T2%c", sc);
9151
  if (fg[fg_anion - 1])
9152
    printf ("000000T1%c", sc);
9153
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
9154
  if (fg[fg_aldehyde - 1])
9155
    printf ("C2O1H000%c", sc);
9156
  if (fg[fg_ketone - 1])
9157
    printf ("C2O1C000%c", sc);
9158
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
9159
  if (fg[fg_thioaldehyde - 1])
9160
    printf ("C2S1H000%c", sc);
9161
  if (fg[fg_thioketone - 1])
9162
    printf ("C2S1C000%c", sc);
9163
  if (fg[fg_imine - 1])
9164
    printf ("C2N10000%c", sc);
9165
  if (fg[fg_hydrazone - 1])
9166
    printf ("C2N1N000%c", sc);
9167
  if (fg[fg_semicarbazone - 1])
9168
    printf ("C2NNC4ON%c", sc);
9169
  if (fg[fg_thiosemicarbazone - 1])
9170
    printf ("C2NNC4SN%c", sc);
9171
  if (fg[fg_oxime - 1])
9172
    printf ("C2N1OH00%c", sc);
9173
  if (fg[fg_oxime_ether - 1])
9174
    printf ("C2N1OC00%c", sc);
9175
  if (fg[fg_ketene - 1])
9176
    printf ("C3OC0000%c", sc);
9177
  if (fg[fg_ketene_acetal_deriv - 1])
9178
    printf ("C3OCC000%c", sc);
9179
  if (fg[fg_carbonyl_hydrate - 1])
9180
    printf ("C2O2H200%c", sc);
9181
  if (fg[fg_hemiacetal - 1])
9182
    printf ("C2O2HC00%c", sc);
9183
  if (fg[fg_acetal - 1])
9184
    printf ("C2O2CC00%c", sc);
9185
  if (fg[fg_hemiaminal - 1])
9186
    printf ("C2NOHC10%c", sc);
9187
  if (fg[fg_aminal - 1])
9188
    printf ("C2N2CC10%c", sc);
9189
  if (fg[fg_thiohemiaminal - 1])
9190
    printf ("C2NSHC10%c", sc);
9191
  if (fg[fg_thioacetal - 1])
9192
    printf ("C2S2CC00%c", sc);
9193
  if (fg[fg_enamine - 1])
9194
    printf ("C2CNH000%c", sc);
9195
  if (fg[fg_enol - 1])
9196
    printf ("C2COH000%c", sc);
9197
  if (fg[fg_enolether - 1])
9198
    printf ("C2COC000%c", sc);
9199
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9200
    printf ("O1H00000%c", sc);
9201
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
9202
  if (fg[fg_prim_alcohol - 1])
9203
    printf ("O1H1C000%c", sc);
9204
  if (fg[fg_sec_alcohol - 1])
9205
    printf ("O1H2C000%c", sc);
9206
  if (fg[fg_tert_alcohol - 1])
9207
    printf ("O1H3C000%c", sc);
9208
  if (fg[fg_1_2_diol - 1])
9209
    printf ("O1H0CO1H%c", sc);
9210
  if (fg[fg_1_2_aminoalcohol - 1])
9211
    printf ("O1H0CN1C%c", sc);
9212
  if (fg[fg_phenol - 1])
9213
    printf ("O1H1A000%c", sc);
9214
  if (fg[fg_1_2_diphenol - 1])
9215
    printf ("O1H2A000%c", sc);
9216
  if (fg[fg_enediol - 1])
9217
    printf ("C2COH200%c", sc);
9218
  if (fg[fg_ether - 1] && ether_generic)
9219
    printf ("O1C00000%c", sc);
9220
  if (fg[fg_dialkylether - 1])
9221
    printf ("O1C0CC00%c", sc);
9222
  if (fg[fg_alkylarylether - 1])
9223
    printf ("O1C0CA00%c", sc);
9224
  if (fg[fg_diarylether - 1])
9225
    printf ("O1C0AA00%c", sc);
9226
  if (fg[fg_thioether - 1])
9227
    printf ("S1C00000%c", sc);
9228
  if (fg[fg_disulfide - 1])
9229
    printf ("S1S1C000%c", sc);
9230
  if (fg[fg_peroxide - 1])
9231
    printf ("O1O1C000%c", sc);
9232
  if (fg[fg_hydroperoxide - 1])
9233
    printf ("O1O1H000%c", sc);
9234
  if (fg[fg_hydrazine - 1])
9235
    printf ("N1N10000%c", sc);
9236
  if (fg[fg_hydroxylamine - 1])
9237
    printf ("N1O1H000%c", sc);
9238
  if (fg[fg_amine - 1] && amine_generic)
9239
    printf ("N1C00000%c", sc);
9240
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
9241
  if (fg[fg_prim_aliph_amine - 1])
9242
    printf ("N1C1C000%c", sc);
9243
  if (fg[fg_prim_arom_amine - 1])
9244
    printf ("N1C1A000%c", sc);
9245
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
9246
  if (fg[fg_sec_aliph_amine - 1])
9247
    printf ("N1C2CC00%c", sc);
9248
  if (fg[fg_sec_mixed_amine - 1])
9249
    printf ("N1C2AC00%c", sc);
9250
  if (fg[fg_sec_arom_amine - 1])
9251
    printf ("N1C2AA00%c", sc);
9252
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
9253
  if (fg[fg_tert_aliph_amine - 1])
9254
    printf ("N1C3CC00%c", sc);
9255
  if (fg[fg_tert_mixed_amine - 1])
9256
    printf ("N1C3AC00%c", sc);
9257
  if (fg[fg_tert_arom_amine - 1])
9258
    printf ("N1C3AA00%c", sc);
9259
  if (fg[fg_quart_ammonium - 1])
9260
    printf ("N1C400T2%c", sc);
9261
  if (fg[fg_n_oxide - 1])
9262
    printf ("N0O10000%c", sc);
9263
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
9264
  /* new in v0.2f */
14179 bpr 9265
  if (fg[fg_halogen_deriv - 1]) {
9266
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1])
9267
              printf ("XX000000%c", sc);
9268
  }
6785 bpr 9269
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
9270
  if (fg[fg_alkyl_fluoride - 1])
9271
    printf ("XF00C000%c", sc);
9272
  if (fg[fg_alkyl_chloride - 1])
9273
    printf ("XC00C000%c", sc);
9274
  if (fg[fg_alkyl_bromide - 1])
9275
    printf ("XB00C000%c", sc);
9276
  if (fg[fg_alkyl_iodide - 1])
9277
    printf ("XI00C000%c", sc);
9278
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
9279
  if (fg[fg_aryl_fluoride - 1])
9280
    printf ("XF00A000%c", sc);
9281
  if (fg[fg_aryl_chloride - 1])
9282
    printf ("XC00A000%c", sc);
9283
  if (fg[fg_aryl_bromide - 1])
9284
    printf ("XB00A000%c", sc);
9285
  if (fg[fg_aryl_iodide - 1])
9286
    printf ("XI00A000%c", sc);
9287
  if (fg[fg_organometallic - 1])
9288
    printf ("000000MX%c", sc);
9289
  if (fg[fg_organolithium - 1])
9290
    printf ("000000ML%c", sc);
9291
  if (fg[fg_organomagnesium - 1])
9292
    printf ("000000MM%c", sc);
9293
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
9294
  if (fg[fg_carboxylic_acid - 1])
9295
    printf ("C3O2H000%c", sc);
9296
  if (fg[fg_carboxylic_acid_salt - 1])
9297
    printf ("C3O200T1%c", sc);
9298
  if (fg[fg_carboxylic_acid_ester - 1])
9299
    printf ("C3O2C000%c", sc);
9300
  if (fg[fg_lactone - 1])
9301
    printf ("C3O2CZ00%c", sc);
9302
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
9303
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9304
    printf ("C3ONC100%c", sc);
9305
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9306
    printf ("C3ONC200%c", sc);
9307
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9308
    printf ("C3ONC300%c", sc);
9309
  if (fg[fg_lactam - 1])
9310
    printf ("C3ONCZ00%c", sc);
9311
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9312
    printf ("C3ONN100%c", sc);
9313
  if (fg[fg_carboxylic_acid_azide - 1])
9314
    printf ("C3ONN200%c", sc);
9315
  if (fg[fg_hydroxamic_acid - 1])
9316
    printf ("C3ONOH00%c", sc);
9317
  if (fg[fg_carboxylic_acid_amidine - 1])
9318
    printf ("C3N2H000%c", sc);
9319
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9320
    printf ("C3NNN100%c", sc);
9321
  if (fg[fg_nitrile - 1])
9322
    printf ("C3N00000%c", sc);
9323
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
9324
  if (fg[fg_acyl_fluoride - 1])
9325
    printf ("C3OXF000%c", sc);
9326
  if (fg[fg_acyl_chloride - 1])
9327
    printf ("C3OXC000%c", sc);
9328
  if (fg[fg_acyl_bromide - 1])
9329
    printf ("C3OXB000%c", sc);
9330
  if (fg[fg_acyl_iodide - 1])
9331
    printf ("C3OXI000%c", sc);
9332
  if (fg[fg_acyl_cyanide - 1])
9333
    printf ("C2OC3N00%c", sc);
9334
  if (fg[fg_imido_ester - 1])
9335
    printf ("C3NOC000%c", sc);
9336
  if (fg[fg_imidoyl_halide - 1])
9337
    printf ("C3NXX000%c", sc);
9338
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
9339
  if (fg[fg_thiocarboxylic_acid - 1])
9340
    printf ("C3SOH000%c", sc);
9341
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9342
    printf ("C3SOC000%c", sc);
9343
  if (fg[fg_thiolactone - 1])
9344
    printf ("C3SOCZ00%c", sc);
9345
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9346
    printf ("C3SNH000%c", sc);
9347
  if (fg[fg_thiolactam - 1])
9348
    printf ("C3SNCZ00%c", sc);
9349
  if (fg[fg_imido_thioester - 1])
9350
    printf ("C3NSC000%c", sc);
9351
  if (fg[fg_oxohetarene - 1])
9352
    printf ("C3ONAZ00%c", sc);
9353
  if (fg[fg_thioxohetarene - 1])
9354
    printf ("C3SNAZ00%c", sc);
9355
  if (fg[fg_iminohetarene - 1])
9356
    printf ("C3NNAZ00%c", sc);
9357
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9358
    printf ("C3O30000%c", sc);
9359
  if (fg[fg_carboxylic_acid_orthoester - 1])
9360
    printf ("C3O3C000%c", sc);
9361
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9362
    printf ("C3O3NC00%c", sc);
9363
  if (fg[fg_carboxylic_acid_anhydride - 1])
9364
    printf ("C3O2C3O2%c", sc);
9365
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
9366
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9367
    printf ("C3ONCH10%c", sc);
9368
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9369
    printf ("C3ONCC10%c", sc);
9370
  if (fg[fg_co2_deriv - 1])
9371
    printf ("C4000000%c", sc);
9372
  if (fg[fg_carbonic_acid_deriv - 1])
9373
    printf ("C4O30000%c", sc);
9374
  if (fg[fg_carbonic_acid_monoester - 1])
9375
    printf ("C4O3C100%c", sc);
9376
  if (fg[fg_carbonic_acid_diester - 1])
9377
    printf ("C4O3C200%c", sc);
9378
  if (fg[fg_carbonic_acid_ester_halide - 1])
9379
    printf ("C4O3CX00%c", sc);
9380
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9381
    printf ("C4SO0000%c", sc);
9382
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9383
    printf ("C4SOC100%c", sc);
9384
  if (fg[fg_thiocarbonic_acid_diester - 1])
9385
    printf ("C4SOC200%c", sc);
9386
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9387
    printf ("C4SOX_00%c", sc);
9388
  if (fg[fg_carbamic_acid_deriv - 1])
9389
    printf ("C4O2N000%c", sc);
9390
  if (fg[fg_carbamic_acid - 1])
9391
    printf ("C4O2NH00%c", sc);
9392
  if (fg[fg_carbamic_acid_ester - 1])
9393
    printf ("C4O2NC00%c", sc);
9394
  if (fg[fg_carbamic_acid_halide - 1])
9395
    printf ("C4O2NX00%c", sc);
9396
  if (fg[fg_thiocarbamic_acid_deriv - 1])
9397
    printf ("C4SN0000%c", sc);
9398
  if (fg[fg_thiocarbamic_acid - 1])
9399
    printf ("C4SNOH00%c", sc);
9400
  if (fg[fg_thiocarbamic_acid_ester - 1])
9401
    printf ("C4SNOC00%c", sc);
9402
  if (fg[fg_thiocarbamic_acid_halide - 1])
9403
    printf ("C4SNXX00%c", sc);
9404
  if (fg[fg_urea - 1])
9405
    printf ("C4O1N200%c", sc);
9406
  if (fg[fg_isourea - 1])
9407
    printf ("C4N2O100%c", sc);
9408
  if (fg[fg_thiourea - 1])
9409
    printf ("C4S1N200%c", sc);
9410
  if (fg[fg_isothiourea - 1])
9411
    printf ("C4N2S100%c", sc);
9412
  if (fg[fg_guanidine - 1])
9413
    printf ("C4N30000%c", sc);
9414
  if (fg[fg_semicarbazide - 1])
9415
    printf ("C4ON2N00%c", sc);
9416
  if (fg[fg_thiosemicarbazide - 1])
9417
    printf ("C4SN2N00%c", sc);
9418
  if (fg[fg_azide - 1])
9419
    printf ("N4N20000%c", sc);
9420
  if (fg[fg_azo_compound - 1])
9421
    printf ("N2N10000%c", sc);
9422
  if (fg[fg_diazonium_salt - 1])
9423
    printf ("N3N100T2%c", sc);
9424
  if (fg[fg_isonitrile - 1])
9425
    printf ("N3C10000%c", sc);
9426
  if (fg[fg_cyanate - 1])
9427
    printf ("C4NO1000%c", sc);
9428
  if (fg[fg_isocyanate - 1])
9429
    printf ("C4NO2000%c", sc);
9430
  if (fg[fg_thiocyanate - 1])
9431
    printf ("C4NS1000%c", sc);
9432
  if (fg[fg_isothiocyanate - 1])
9433
    printf ("C4NS2000%c", sc);
9434
  if (fg[fg_carbodiimide - 1])
9435
    printf ("C4N20000%c", sc);
9436
  if (fg[fg_nitroso_compound - 1])
9437
    printf ("N2O10000%c", sc);
9438
  if (fg[fg_nitro_compound - 1])
9439
    printf ("N4O20000%c", sc);
9440
  if (fg[fg_nitrite - 1])
9441
    printf ("N3O20000%c", sc);
9442
  if (fg[fg_nitrate - 1])
9443
    printf ("N4O30000%c", sc);
9444
  if (fg[fg_sulfuric_acid_deriv - 1])
9445
    printf ("S6O00000%c", sc);
9446
  if (fg[fg_sulfuric_acid - 1])
9447
    printf ("S6O4H000%c", sc);
9448
  if (fg[fg_sulfuric_acid_monoester - 1])
9449
    printf ("S6O4HC00%c", sc);
9450
  if (fg[fg_sulfuric_acid_diester - 1])
9451
    printf ("S6O4CC00%c", sc);
9452
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9453
    printf ("S6O3NC00%c", sc);
9454
  if (fg[fg_sulfuric_acid_amide - 1])
9455
    printf ("S6O3N100%c", sc);
9456
  if (fg[fg_sulfuric_acid_diamide - 1])
9457
    printf ("S6O2N200%c", sc);
9458
  if (fg[fg_sulfuryl_halide - 1])
9459
    printf ("S6O3XX00%c", sc);
9460
  if (fg[fg_sulfonic_acid_deriv - 1])
9461
    printf ("S5O00000%c", sc);
9462
  if (fg[fg_sulfonic_acid - 1])
9463
    printf ("S5O3H000%c", sc);
9464
  if (fg[fg_sulfonic_acid_ester - 1])
9465
    printf ("S5O3C000%c", sc);
9466
  if (fg[fg_sulfonamide - 1])
9467
    printf ("S5O2N000%c", sc);
9468
  if (fg[fg_sulfonyl_halide - 1])
9469
    printf ("S5O2XX00%c", sc);
9470
  if (fg[fg_sulfone - 1])
9471
    printf ("S4O20000%c", sc);
9472
  if (fg[fg_sulfoxide - 1])
9473
    printf ("S2O10000%c", sc);
9474
  if (fg[fg_sulfinic_acid_deriv - 1])
9475
    printf ("S3O00000%c", sc);
9476
  if (fg[fg_sulfinic_acid - 1])
9477
    printf ("S3O2H000%c", sc);
9478
  if (fg[fg_sulfinic_acid_ester - 1])
9479
    printf ("S3O2C000%c", sc);
9480
  if (fg[fg_sulfinic_acid_halide - 1])
9481
    printf ("S3O1XX00%c", sc);
9482
  if (fg[fg_sulfinic_acid_amide - 1])
9483
    printf ("S3O1N000%c", sc);
9484
  if (fg[fg_sulfenic_acid_deriv - 1])
9485
    printf ("S1O00000%c", sc);
9486
  if (fg[fg_sulfenic_acid - 1])
9487
    printf ("S1O1H000%c", sc);
9488
  if (fg[fg_sulfenic_acid_ester - 1])
9489
    printf ("S1O1C000%c", sc);
9490
  if (fg[fg_sulfenic_acid_halide - 1])
9491
    printf ("S1O0XX00%c", sc);
9492
  if (fg[fg_sulfenic_acid_amide - 1])
9493
    printf ("S1O0N100%c", sc);
9494
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
9495
  if (fg[fg_alkylthiol - 1])
9496
    printf ("S1H1C000%c", sc);
9497
  if (fg[fg_arylthiol - 1])
9498
    printf ("S1H1A000%c", sc);
9499
  if (fg[fg_phosphoric_acid_deriv - 1])
9500
    printf ("P5O0H000%c", sc);
9501
  if (fg[fg_phosphoric_acid - 1])
9502
    printf ("P5O4H200%c", sc);
9503
  if (fg[fg_phosphoric_acid_ester - 1])
9504
    printf ("P5O4HC00%c", sc);
9505
  if (fg[fg_phosphoric_acid_halide - 1])
9506
    printf ("P5O3HX00%c", sc);
9507
  if (fg[fg_phosphoric_acid_amide - 1])
9508
    printf ("P5O3HN00%c", sc);
9509
  if (fg[fg_thiophosphoric_acid_deriv - 1])
9510
    printf ("P5O0S000%c", sc);
9511
  if (fg[fg_thiophosphoric_acid - 1])
9512
    printf ("P5O3SH00%c", sc);
9513
  if (fg[fg_thiophosphoric_acid_ester - 1])
9514
    printf ("P5O3SC00%c", sc);
9515
  if (fg[fg_thiophosphoric_acid_halide - 1])
9516
    printf ("P5O2SX00%c", sc);
9517
  if (fg[fg_thiophosphoric_acid_amide - 1])
9518
    printf ("P5O2SN00%c", sc);
9519
  if (fg[fg_phosphonic_acid_deriv - 1])
9520
    printf ("P4O30000%c", sc);
9521
  if (fg[fg_phosphonic_acid - 1])
9522
    printf ("P4O3H000%c", sc);
9523
  if (fg[fg_phosphonic_acid_ester - 1])
9524
    printf ("P4O3C000%c", sc);
9525
  if (fg[fg_phosphine - 1])
9526
    printf ("P3000000%c", sc);
9527
  if (fg[fg_phosphinoxide - 1])
9528
    printf ("P2O00000%c", sc);
9529
  if (fg[fg_boronic_acid_deriv - 1])
9530
    printf ("B2O20000%c", sc);
9531
  if (fg[fg_boronic_acid - 1])
9532
    printf ("B2O2H000%c", sc);
9533
  if (fg[fg_boronic_acid_ester - 1])
9534
    printf ("B2O2C000%c", sc);
9535
  if (fg[fg_alkene - 1])
9536
    printf ("000C2C00%c", sc);
9537
  if (fg[fg_alkyne - 1])
9538
    printf ("000C3C00%c", sc);
9539
  if (fg[fg_aromatic - 1])
9540
    printf ("0000A000%c", sc);
9541
  if (fg[fg_heterocycle - 1])
9542
    printf ("0000CZ00%c", sc);
9543
  if (fg[fg_alpha_aminoacid - 1])
9544
    printf ("C3O2HN1C%c", sc);
9545
  if (fg[fg_alpha_hydroxyacid - 1])
9546
    printf ("C3O2HO1H%c", sc);
9547
}
9548
 
9549
#undef sc
9550
 
14179 bpr 9551
static void write_fg_binary ()
6785 bpr 9552
{
9553
  int i, n;
9554
  char o;
9555
 
14179 bpr 9556
  for (i = 1; i <= max_fg / 8; i++) {
9557
    n = 0;
9558
    if (fg[i * 8 - 1])
9559
            n++;
9560
    if (fg[i * 8 - 2])
9561
            n += 2;
9562
    if (fg[i * 8 - 3])
9563
            n += 4;
9564
    if (fg[i * 8 - 4])
9565
            n += 8;
9566
    if (fg[i * 8 - 5])
9567
            n += 16;
9568
    if (fg[i * 8 - 6])
9569
            n += 32;
9570
    if (fg[i * 8 - 7])
9571
            n += 64;
9572
    if (fg[i * 8 - 8])
9573
            n += 128;
9574
    o = (char) n;
9575
    putchar (o);
9576
  }
6785 bpr 9577
}
9578
 
14179 bpr 9579
static void write_fg_bitstring ()
6785 bpr 9580
{
9581
  int i;
9582
 
14179 bpr 9583
  for (i = 0; i < max_fg; i++) {
9584
    if (fg[i])
9585
            putchar ('1');
9586
    else
9587
            putchar ('0');
9588
  }
6785 bpr 9589
}
9590
 
9591
#if 0
9592
static void readinputfile (molfilename) char *molfilename;
14179 bpr 9593
  {
9594
  /* new version in v0.2g */
9595
  char rline[256];
9596
  char *TEMP;
6785 bpr 9597
 
14179 bpr 9598
  molbufindex = 0;
9599
  if (!opt_stdin)
9600
  {
9601
  if (!rfile_is_open)
9602
  {
9603
  assign (rfile, molfilename);
9604
  rewind (rfile);
9605
  rfile_is_open = true;
9606
  }
9607
  /* p2c: checkmol.pas, line 7733: Warning:
9608
  * Don't know how to ASSIGN to a non-explicit file variable [207] */
9609
  *rline = '\0';
9610
  mol_in_queue = false;
9611
  while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
9612
  {
9613
  fgets (rline, 256, rfile);
9614
  TEMP = strchr (rline, '\n');
9615
  if (TEMP != NULL)
9616
  *TEMP = 0;
9617
  /*mol_in_queue := false; */
9618
  if (molbufindex >= max_atoms + max_bonds + 64)
9619
  {
9620
  printf ("Not enough memory for molfile! %12ld\n",
9621
  molbufindex);
9622
  if (rfile != NULL)
9623
  fclose (rfile);
9624
  rfile = NULL;
9625
  _Escape (1);
9626
  }
9627
  molbufindex++;
9628
  strcpy (molbuf[molbufindex - 1], rline);
9629
  if (strpos2 (rline, "$$$$", 1) > 0)
9630
  mol_in_queue = true;
9631
  }
9632
  if (!P_eof (rfile))
9633
  return;
9634
  if (rfile != NULL)
9635
  fclose (rfile);
9636
  rfile = NULL;
9637
  rfile_is_open = false;
9638
  mol_in_queue = false;
9639
  return;
9640
  }
9641
  *rline = '\0';
9642
  mol_in_queue = false;
9643
  while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
9644
  {
9645
  gets (rline);
9646
  if (molbufindex >= max_atoms + max_bonds + 64)
9647
  {
9648
  printf ("Not enough memory!\n");
9649
  _Escape (1);
9650
  }
9651
  molbufindex++;
9652
  strcpy (molbuf[molbufindex - 1], rline);
9653
  if (strpos2 (rline, "$$$$", 1) > 0)
9654
  {
9655
  mol_in_queue = true;
9656
  /* read from standard input
9657
  }
9658
  }
9659
  } */
6785 bpr 9660
#endif
9661
 
14179 bpr 9662
static void readinputfile (char *molfilename)
6785 bpr 9663
{
9664
  /* new version in v0.2g */
9665
  char rline[256];
9666
  char *TEMP;
9667
 
9668
  molbufindex = 0;
14179 bpr 9669
  if (!opt_stdin) {
9670
    if (!rfile_is_open) {
9671
            rfile = fopen (molfilename, "r");
9672
            rewind (rfile);
9673
            rfile_is_open = true;
9674
          }
9675
    /* p2c: checkmol.pas, line 7226: Warning:
9676
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
9677
    *rline = '\0';
9678
    mol_in_queue = false;
9679
    while ((fgets (rline, 256, rfile) != NULL) && (strstr (rline, "$$$$") == NULL)) {
9680
            TEMP = strchr (rline, '\n');
9681
            if (TEMP != NULL)
9682
              *TEMP = 0;
9683
            /*mol_in_queue := false; */
9684
            if (molbufindex >= max_atoms + max_bonds + 64) {
6785 bpr 9685
              printf ("Not enough memory for molfile! %d\n", molbufindex);
9686
              if (rfile != NULL)
14179 bpr 9687
                      fclose (rfile);
6785 bpr 9688
              rfile = NULL;
9689
              exit (1);
9690
            }
14179 bpr 9691
            //molbufindex++;
9692
            strcpy (molbuf[molbufindex++], rline);
9693
            if (strstr (rline, "$$$$") != NULL)
9694
              mol_in_queue = true;
9695
          }
9696
    if (!feof (rfile))
9697
            return;
9698
    if (rfile != NULL)
9699
            fclose (rfile);
9700
    rfile = NULL;
9701
    rfile_is_open = false;
9702
    mol_in_queue = false;
9703
    return;
9704
  }
6785 bpr 9705
  *rline = '\0';
9706
  mol_in_queue = false;
14179 bpr 9707
  do {
9708
    if(fgets (rline, 256, stdin)==NULL || feof (stdin))
9709
            return;
9710
    TEMP = strchr (rline, '\n');
9711
    if (TEMP != NULL)
9712
            *TEMP = '\0';
9713
    if (molbufindex >= max_atoms + max_bonds + 64) {
9714
            printf ("Not enough memory!\n");
9715
            exit (1);
9716
          }
9717
    //molbufindex++;
9718
    strcpy (molbuf[molbufindex++], rline);
9719
    if (strstr (rline, "$$$$") != NULL) {
9720
            mol_in_queue = true;
9721
            /* read from standard input */
9722
          }
9723
  }
6785 bpr 9724
  while (strstr (rline, "$$$$") == NULL);
9725
}
9726
 
9727
#if 0
9728
static void copy_mol_to_needle()
9729
{
9730
  int i, j, FORLIM;
9731
 
9732
  if (n_atoms == 0)
9733
    return;
9734
  /* try */
9735
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9736
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9737
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9738
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9739
  /* except*/
9740
    on e:Eoutofmemory do
9741
      begin
9742
        writeln('Not enough memory');
9743
        halt(4);
9744
      end;
14179 bpr 9745
  end;
6785 bpr 9746
  ndl_n_atoms = n_atoms;
9747
  ndl_n_bonds = n_bonds;
9748
  ndl_n_rings = n_rings;
9749
  ndl_n_heavyatoms = n_heavyatoms;
9750
  ndl_n_heavybonds = n_heavybonds;
9751
  strcpy(ndl_molname, molname);
9752
  ndl_n_Ctot = n_Ctot;
9753
  ndl_n_Otot = n_Otot;
9754
  ndl_n_Ntot = n_Ntot;
9755
  FORLIM = n_atoms;
9756
  for (i = 0; i < FORLIM; i++) {
9757
    strcpy(ndl_atom[i].element, atom[i].element);
9758
    strcpy(ndl_atom[i].atype, atom[i].atype);
9759
    ndl_atom[i].x = atom[i].x;
9760
    ndl_atom[i].y = atom[i].y;
9761
    ndl_atom[i].z = atom[i].z;
9762
    ndl_atom[i].formal_charge = atom[i].formal_charge;
9763
    ndl_atom[i].real_charge = atom[i].real_charge;
9764
    ndl_atom[i].Hexp = atom[i].Hexp;
9765
    ndl_atom[i].Htot = atom[i].Htot;
9766
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
9767
    ndl_atom[i].ring_count = atom[i].ring_count;
9768
    ndl_atom[i].arom = atom[i].arom;
9769
    ndl_atom[i].stereo_care = atom[i].stereo_care;
9770
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
9771
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
9772
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
14179 bpr 9773
        }
9774
        if (n_bonds > 0) {
9775
          FORLIM = n_bonds;
9776
          for (i = 0; i < FORLIM; i++) {
9777
            ndl_bond[i].a1 = bond[i].a1;
9778
            ndl_bond[i].a2 = bond[i].a2;
9779
            ndl_bond[i].btype = bond[i].btype;
9780
            ndl_bond[i].arom = bond[i].arom;
9781
            ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
9782
            ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
9783
            ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
9784
          }
9785
        }
9786
        if (n_rings > 0) {
9787
          FORLIM = n_rings;
9788
          for (i = 0; i < FORLIM; i++) {
9789
            for (j = 0; j < max_ringsize; j++)
9790
              ndl_ring[i][j] = ring[i][j];
9791
          }
9792
          for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
9793
            ndl_ringprop[i].size = ringprop[i].size;
9794
            ndl_ringprop[i].arom = ringprop[i].arom;
9795
            ndl_ringprop[i].envelope = ringprop[i].envelope;
9796
          }
9797
        }
9798
        ndl_molstat.n_QA = molstat.n_QA;
9799
  ndl_molstat.n_QB = molstat.n_QB;
9800
  ndl_molstat.n_chg = molstat.n_chg;
9801
  ndl_molstat.n_C1 = molstat.n_C1;
9802
  ndl_molstat.n_C2 = molstat.n_C2;
9803
  ndl_molstat.n_C = molstat.n_C;
9804
  ndl_molstat.n_CHB1p = molstat.n_CHB1p;
9805
  ndl_molstat.n_CHB2p = molstat.n_CHB2p;
9806
  ndl_molstat.n_CHB3p = molstat.n_CHB3p;
9807
  ndl_molstat.n_CHB4 = molstat.n_CHB4;
9808
  ndl_molstat.n_O2 = molstat.n_O2;
9809
  ndl_molstat.n_O3 = molstat.n_O3;
9810
  ndl_molstat.n_N1 = molstat.n_N1;
9811
  ndl_molstat.n_N2 = molstat.n_N2;
9812
  ndl_molstat.n_N3 = molstat.n_N3;
9813
  ndl_molstat.n_S = molstat.n_S;
9814
  ndl_molstat.n_SeTe = molstat.n_SeTe;
9815
  ndl_molstat.n_F = molstat.n_F;
9816
  ndl_molstat.n_Cl = molstat.n_Cl;
9817
  ndl_molstat.n_Br = molstat.n_Br;
9818
  ndl_molstat.n_I = molstat.n_I;
9819
  ndl_molstat.n_P = molstat.n_P;
9820
  ndl_molstat.n_B = molstat.n_B;
9821
  ndl_molstat.n_Met = molstat.n_Met;
9822
  ndl_molstat.n_X = molstat.n_X;
9823
  ndl_molstat.n_b1 = molstat.n_b1;
9824
  ndl_molstat.n_b2 = molstat.n_b2;
9825
  ndl_molstat.n_b3 = molstat.n_b3;
9826
  ndl_molstat.n_bar = molstat.n_bar;
9827
  ndl_molstat.n_C1O = molstat.n_C1O;
9828
  ndl_molstat.n_C2O = molstat.n_C2O;
9829
  ndl_molstat.n_CN = molstat.n_CN;
9830
  ndl_molstat.n_XY = molstat.n_XY;
9831
  ndl_molstat.n_r3 = molstat.n_r3;
9832
  ndl_molstat.n_r4 = molstat.n_r4;
9833
  ndl_molstat.n_r5 = molstat.n_r5;
9834
  ndl_molstat.n_r6 = molstat.n_r6;
9835
  ndl_molstat.n_r7 = molstat.n_r7;
9836
        ndl_molstat.n_r8 = molstat.n_r8;
9837
        ndl_molstat.n_r9 = molstat.n_r9;
9838
        ndl_molstat.n_r10 = molstat.n_r10;
9839
        ndl_molstat.n_r11 = molstat.n_r11;
9840
        ndl_molstat.n_r12 = molstat.n_r12;
9841
        ndl_molstat.n_r13p = molstat.n_r13p;
9842
        ndl_molstat.n_rN = molstat.n_rN;
9843
        ndl_molstat.n_rN1 = molstat.n_rN1;
9844
        ndl_molstat.n_rN2 = molstat.n_rN2;
9845
        ndl_molstat.n_rN3p = molstat.n_rN3p;
9846
        ndl_molstat.n_rO = molstat.n_rO;
9847
        ndl_molstat.n_rO1 = molstat.n_rO1;
9848
        ndl_molstat.n_rO2p = molstat.n_rO2p;
9849
        ndl_molstat.n_rS = molstat.n_rS;
9850
        ndl_molstat.n_rX = molstat.n_rX;
9851
        ndl_molstat.n_rAr = molstat.n_rAr;
9852
        ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
9853
        ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
9854
        /* p2c: checkmol.pas, line 7875:
9855
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
9856
        /*$IFDEF extended_molstat
9857
         v0.3m */
9858
        ndl_molstat.n_psg01 = molstat.n_psg01;
9859
        ndl_molstat.n_psg02 = molstat.n_psg02;
9860
        ndl_molstat.n_psg13 = molstat.n_psg13;
9861
        ndl_molstat.n_psg14 = molstat.n_psg14;
9862
        ndl_molstat.n_psg15 = molstat.n_psg15;
9863
        ndl_molstat.n_psg16 = molstat.n_psg16;
9864
        ndl_molstat.n_psg17 = molstat.n_psg17;
9865
        ndl_molstat.n_psg18 = molstat.n_psg18;
9866
        ndl_molstat.n_pstm = molstat.n_pstm;
9867
        ndl_molstat.n_psla = molstat.n_psla;
9868
        $ENDIF*/
9869
  /* make sure some modes can be switched on only by the query file *M*/
9870
  /* and not by subsequent haystack file(s) */
9871
  if (ez_flag)   /* new in v0.3f */
9872
   ez_search = true;
9873
  if (chir_flag)   /* new in v0.3f */
9874
    rs_search = true;
9875
}
6785 bpr 9876
#endif
9877
 
14179 bpr 9878
static void copy_mol_to_needle ()
6785 bpr 9879
{
9880
  //int i, j, FORLIM;
9881
 
9882
  /*if (n_atoms == 0)
9883
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9884
 
9885
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9886
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9887
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9888
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9889
 
9890
  ndl_n_atoms = n_atoms;
9891
  ndl_n_bonds = n_bonds;
9892
  ndl_n_rings = n_rings;
9893
  ndl_n_heavyatoms = n_heavyatoms;
9894
  ndl_n_heavybonds = n_heavybonds;
9895
  strcpy (ndl_molname, molname);
9896
  ndl_n_Ctot = n_Ctot;
9897
  ndl_n_Otot = n_Otot;
9898
  ndl_n_Ntot = n_Ntot;
9899
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
9900
 
9901
  if (n_bonds > 0)
9902
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
9903
 
14179 bpr 9904
  if (n_rings > 0) {
9905
    memcpy (ndl_ring, ring, sizeof (ringlist));
9906
    memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
9907
  }
6785 bpr 9908
 
9909
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
9910
 
14179 bpr 9911
  // make sure some modes can be switched on only by the query file
9912
  // and not by subsequent haystack file(s)
9913
  if (ez_flag)                  // new in v0.3f
6785 bpr 9914
    ez_search = true;
9915
 
14179 bpr 9916
  if (chir_flag)                // new in v0.3f
6785 bpr 9917
    rs_search = true;
9918
 
9919
  ndl_querymol = found_querymol;        /* 0.3p */
9920
 
9921
}
9922
 
14179 bpr 9923
static void copy_mol_to_tmp ()
6785 bpr 9924
{
9925
  //int i, j, FORLIM;
9926
 
9927
  /*if (n_atoms == 0)
9928
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9929
 
9930
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9931
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9932
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9933
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9934
 
9935
  tmp_n_atoms = n_atoms;
9936
  tmp_n_bonds = n_bonds;
9937
  tmp_n_rings = n_rings;
9938
  tmp_n_heavyatoms = n_heavyatoms;
9939
  tmp_n_heavybonds = n_heavybonds;
9940
  strcpy (tmp_molname, molname);
9941
  tmp_n_Ctot = n_Ctot;
9942
  tmp_n_Otot = n_Otot;
9943
  tmp_n_Ntot = n_Ntot;
9944
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
9945
 
9946
  if (n_bonds > 0)
9947
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
9948
 
14179 bpr 9949
  if (n_rings > 0) {
6785 bpr 9950
      memcpy (tmp_ring, ring, sizeof (ringlist));
9951
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
14179 bpr 9952
  }
6785 bpr 9953
 
9954
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
9955
 
14179 bpr 9956
  // make sure some modes can be switched on only by the query file
9957
  // and not by subsequent haystack file(s)
9958
  if (ez_flag)                  // new in v0.3f
6785 bpr 9959
    ez_search = true;
9960
 
14179 bpr 9961
  if (chir_flag)                // new in v0.3f
6785 bpr 9962
    rs_search = true;
9963
 
9964
  ndl_querymol = found_querymol;        /* 0.3p */
9965
 
9966
}
9967
 
9968
#if 0
9969
static void copy_mol_to_tmp()
9970
{
9971
  int i, j, FORLIM;
9972
 
9973
  if (n_atoms == 0)
9974
    return;
9975
  /* try */
9976
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9977
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9978
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9979
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9980
  /* except */
9981
    on e:Eoutofmemory do
9982
      begin
9983
        writeln('Not enough memory');
9984
        halt(4);
9985
      end;
9986
  end;
9987
  tmp_n_atoms = n_atoms;
9988
  tmp_n_bonds = n_bonds;
9989
  tmp_n_rings = n_rings;
9990
  tmp_n_heavyatoms = n_heavyatoms;
9991
  tmp_n_heavybonds = n_heavybonds;
9992
  strcpy(tmp_molname, molname);
9993
  tmp_n_Ctot = n_Ctot;
9994
  tmp_n_Otot = n_Otot;
9995
  tmp_n_Ntot = n_Ntot;
9996
  FORLIM = n_atoms;
9997
  for (i = 0; i < FORLIM; i++) {
9998
    strcpy(tmp_atom[i].element, atom[i].element);
9999
    strcpy(tmp_atom[i].atype, atom[i].atype);
10000
    tmp_atom[i].x = atom[i].x;
10001
    tmp_atom[i].y = atom[i].y;
10002
    tmp_atom[i].z = atom[i].z;
10003
    tmp_atom[i].formal_charge = atom[i].formal_charge;
10004
    tmp_atom[i].real_charge = atom[i].real_charge;
10005
    tmp_atom[i].Hexp = atom[i].Hexp;
10006
    tmp_atom[i].Htot = atom[i].Htot;
10007
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
10008
    tmp_atom[i].ring_count = atom[i].ring_count;
10009
    tmp_atom[i].arom = atom[i].arom;
10010
    tmp_atom[i].stereo_care = atom[i].stereo_care;
10011
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
10012
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
10013
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
10014
  }
10015
  if (n_bonds > 0) {
10016
    FORLIM = n_bonds;
10017
    for (i = 0; i < FORLIM; i++) {
10018
      tmp_bond[i].a1 = bond[i].a1;
10019
      tmp_bond[i].a2 = bond[i].a2;
10020
      tmp_bond[i].btype = bond[i].btype;
10021
      tmp_bond[i].arom = bond[i].arom;
10022
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
10023
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
10024
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
10025
    }
10026
  }
10027
  if (n_rings > 0) {
10028
    FORLIM = n_rings;
10029
    for (i = 0; i < FORLIM; i++) {
10030
      for (j = 0; j < max_ringsize; j++)
10031
        tmp_ring[i][j] = ring[i][j];
10032
    }
10033
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10034
      tmp_ringprop[i].size = ringprop[i].size;
10035
      tmp_ringprop[i].arom = ringprop[i].arom;
10036
      tmp_ringprop[i].envelope = ringprop[i].envelope;
10037
    }
10038
  }
10039
  tmp_molstat.n_QA = molstat.n_QA;
10040
  tmp_molstat.n_QB = molstat.n_QB;
10041
  tmp_molstat.n_chg = molstat.n_chg;
10042
  tmp_molstat.n_C1 = molstat.n_C1;
10043
  tmp_molstat.n_C2 = molstat.n_C2;
10044
  tmp_molstat.n_C = molstat.n_C;
10045
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
10046
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
10047
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
10048
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
10049
  tmp_molstat.n_O2 = molstat.n_O2;
10050
  tmp_molstat.n_O3 = molstat.n_O3;
10051
  tmp_molstat.n_N1 = molstat.n_N1;
10052
  tmp_molstat.n_N2 = molstat.n_N2;
10053
  tmp_molstat.n_N3 = molstat.n_N3;
10054
  tmp_molstat.n_S = molstat.n_S;
10055
  tmp_molstat.n_SeTe = molstat.n_SeTe;
10056
  tmp_molstat.n_F = molstat.n_F;
10057
  tmp_molstat.n_Cl = molstat.n_Cl;
10058
  tmp_molstat.n_Br = molstat.n_Br;
10059
  tmp_molstat.n_I = molstat.n_I;
10060
  tmp_molstat.n_P = molstat.n_P;
10061
  tmp_molstat.n_B = molstat.n_B;
10062
  tmp_molstat.n_Met = molstat.n_Met;
10063
  tmp_molstat.n_X = molstat.n_X;
10064
  tmp_molstat.n_b1 = molstat.n_b1;
10065
  tmp_molstat.n_b2 = molstat.n_b2;
10066
  tmp_molstat.n_b3 = molstat.n_b3;
10067
  tmp_molstat.n_bar = molstat.n_bar;
10068
  tmp_molstat.n_C1O = molstat.n_C1O;
10069
  tmp_molstat.n_C2O = molstat.n_C2O;
10070
  tmp_molstat.n_CN = molstat.n_CN;
10071
  tmp_molstat.n_XY = molstat.n_XY;
10072
  tmp_molstat.n_r3 = molstat.n_r3;
10073
  tmp_molstat.n_r4 = molstat.n_r4;
10074
  tmp_molstat.n_r5 = molstat.n_r5;
10075
  tmp_molstat.n_r6 = molstat.n_r6;
10076
  tmp_molstat.n_r7 = molstat.n_r7;
10077
  tmp_molstat.n_r8 = molstat.n_r8;
10078
  tmp_molstat.n_r9 = molstat.n_r9;
10079
  tmp_molstat.n_r10 = molstat.n_r10;
10080
  tmp_molstat.n_r11 = molstat.n_r11;
10081
  tmp_molstat.n_r12 = molstat.n_r12;
10082
  tmp_molstat.n_r13p = molstat.n_r13p;
10083
  tmp_molstat.n_rN = molstat.n_rN;
10084
  tmp_molstat.n_rN1 = molstat.n_rN1;
10085
  tmp_molstat.n_rN2 = molstat.n_rN2;
10086
  tmp_molstat.n_rN3p = molstat.n_rN3p;
10087
  tmp_molstat.n_rO = molstat.n_rO;
10088
  tmp_molstat.n_rO1 = molstat.n_rO1;
10089
  tmp_molstat.n_rO2p = molstat.n_rO2p;
10090
  tmp_molstat.n_rS = molstat.n_rS;
10091
  tmp_molstat.n_rX = molstat.n_rX;
10092
  tmp_molstat.n_rAr = molstat.n_rAr;
10093
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
10094
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
10095
/* p2c: checkmol.pas, line 8022:
10096
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10097
  /*$IFDEF extended_molstat
14179 bpr 10098
   v0.3m
6785 bpr 10099
  tmp_molstat.n_psg01 = molstat.n_psg01;
10100
  tmp_molstat.n_psg02 = molstat.n_psg02;
10101
  tmp_molstat.n_psg13 = molstat.n_psg13;
10102
  tmp_molstat.n_psg14 = molstat.n_psg14;
10103
  tmp_molstat.n_psg15 = molstat.n_psg15;
10104
  tmp_molstat.n_psg16 = molstat.n_psg16;
10105
  tmp_molstat.n_psg17 = molstat.n_psg17;
10106
  tmp_molstat.n_psg18 = molstat.n_psg18;
10107
  tmp_molstat.n_pstm = molstat.n_pstm;
10108
  tmp_molstat.n_psla = molstat.n_psla;
10109
  $ENDIF*/
10110
  /* make sure some modes can be switched on only by the query file */
10111
  /* and not by subsequent haystack file(s) */
10112
  if (ez_flag)   /* new in v0.3f */
10113
    ez_search = true;
10114
  if (chir_flag)   /* new in v0.3f */
10115
    rs_search = true;
10116
}
10117
#endif
10118
 
14179 bpr 10119
static void copy_tmp_to_mol ()
6785 bpr 10120
{
10121
  //int i, j, FORLIM;
10122
 
10123
  /*if (n_atoms == 0)
10124
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10125
 
10126
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10127
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10128
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10129
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10130
 
10131
  n_atoms = tmp_n_atoms;
10132
  n_bonds = tmp_n_bonds;
10133
  n_rings = tmp_n_rings;
10134
  n_heavyatoms = tmp_n_heavyatoms;
10135
  n_heavybonds = tmp_n_heavybonds;
10136
  strcpy (molname, tmp_molname);
10137
  n_Ctot = tmp_n_Ctot;
10138
  n_Otot = tmp_n_Otot;
10139
  n_Ntot = tmp_n_Ntot;
10140
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
10141
 
10142
  if (tmp_n_bonds > 0)
10143
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
10144
 
14179 bpr 10145
  if (tmp_n_rings > 0) {
6785 bpr 10146
      memcpy (ring, tmp_ring, sizeof (ringlist));
10147
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
14179 bpr 10148
  }
6785 bpr 10149
 
10150
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
10151
 
14179 bpr 10152
  // make sure some modes can be switched on only by the query file
10153
  // and not by subsequent haystack file(s)
10154
  if (ez_flag)                  // new in v0.3f
6785 bpr 10155
    ez_search = true;
10156
 
14179 bpr 10157
  if (chir_flag)                // new in v0.3f
6785 bpr 10158
    rs_search = true;
10159
 
10160
}
10161
 
10162
#if 0
10163
static void copy_tmp_to_mol()
10164
{
10165
  int i, j, FORLIM;
10166
 
10167
  if (tmp_n_atoms == 0)
10168
    return;
10169
  n_atoms = tmp_n_atoms;
10170
  n_bonds = tmp_n_bonds;
10171
  n_rings = tmp_n_rings;
10172
  n_heavyatoms = tmp_n_heavyatoms;
10173
  n_heavybonds = tmp_n_heavybonds;
10174
  strcpy(molname, tmp_molname);
10175
  n_Ctot = tmp_n_Ctot;
10176
  n_Otot = tmp_n_Otot;
10177
  n_Ntot = tmp_n_Ntot;
10178
  /* try */
10179
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10180
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10181
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10182
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10183
  FORLIM = tmp_n_atoms;
10184
  /* except*/
10185
    on e:Eoutofmemory do
10186
      begin
10187
        writeln('Not enough memory');
10188
        halt(4);
10189
      end;
14179 bpr 10190
  end;
6785 bpr 10191
  for (i = 0; i < FORLIM; i++) {
10192
    strcpy(atom[i].element, tmp_atom[i].element);
10193
    strcpy(atom[i].atype, tmp_atom[i].atype);
10194
    atom[i].x = tmp_atom[i].x;
10195
    atom[i].y = tmp_atom[i].y;
10196
    atom[i].z = tmp_atom[i].z;
10197
    atom[i].formal_charge = tmp_atom[i].formal_charge;
10198
    atom[i].real_charge = tmp_atom[i].real_charge;
10199
    atom[i].Hexp = tmp_atom[i].Hexp;
10200
    atom[i].Htot = tmp_atom[i].Htot;
10201
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
10202
    atom[i].ring_count = tmp_atom[i].ring_count;
10203
    atom[i].arom = tmp_atom[i].arom;
10204
    atom[i].stereo_care = tmp_atom[i].stereo_care;
10205
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
10206
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
10207
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
10208
  }
10209
  if (tmp_n_bonds > 0) {
10210
    FORLIM = tmp_n_bonds;
10211
    for (i = 0; i < FORLIM; i++) {
10212
      bond[i].a1 = tmp_bond[i].a1;
10213
      bond[i].a2 = tmp_bond[i].a2;
10214
      bond[i].btype = tmp_bond[i].btype;
10215
      bond[i].arom = tmp_bond[i].arom;
10216
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
10217
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
10218
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
10219
    }
10220
  }
10221
  if (tmp_n_rings > 0) {
10222
    FORLIM = tmp_n_rings;
10223
    for (i = 0; i < FORLIM; i++) {
10224
      for (j = 0; j < max_ringsize; j++)
10225
        ring[i][j] = tmp_ring[i][j];
10226
    }
10227
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10228
      ringprop[i].size = tmp_ringprop[i].size;
10229
      ringprop[i].arom = tmp_ringprop[i].arom;
10230
      ringprop[i].envelope = tmp_ringprop[i].envelope;
10231
    }
10232
  }
10233
  molstat.n_QA = tmp_molstat.n_QA;
10234
  molstat.n_QB = tmp_molstat.n_QB;
10235
  molstat.n_chg = tmp_molstat.n_chg;
10236
  molstat.n_C1 = tmp_molstat.n_C1;
10237
  molstat.n_C2 = tmp_molstat.n_C2;
10238
  molstat.n_C = tmp_molstat.n_C;
10239
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
10240
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
10241
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
10242
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
10243
  molstat.n_O2 = tmp_molstat.n_O2;
10244
  molstat.n_O3 = tmp_molstat.n_O3;
10245
  molstat.n_N1 = tmp_molstat.n_N1;
10246
  molstat.n_N2 = tmp_molstat.n_N2;
10247
  molstat.n_N3 = tmp_molstat.n_N3;
10248
  molstat.n_S = tmp_molstat.n_S;
10249
  molstat.n_SeTe = tmp_molstat.n_SeTe;
10250
  molstat.n_F = tmp_molstat.n_F;
10251
  molstat.n_Cl = tmp_molstat.n_Cl;
10252
  molstat.n_Br = tmp_molstat.n_Br;
10253
  molstat.n_I = tmp_molstat.n_I;
10254
  molstat.n_P = tmp_molstat.n_P;
10255
  molstat.n_B = tmp_molstat.n_B;
10256
  molstat.n_Met = tmp_molstat.n_Met;
10257
  molstat.n_X = tmp_molstat.n_X;
10258
  molstat.n_b1 = tmp_molstat.n_b1;
10259
  molstat.n_b2 = tmp_molstat.n_b2;
10260
  molstat.n_b3 = tmp_molstat.n_b3;
10261
  molstat.n_bar = tmp_molstat.n_bar;
10262
  molstat.n_C1O = tmp_molstat.n_C1O;
10263
  molstat.n_C2O = tmp_molstat.n_C2O;
10264
  molstat.n_CN = tmp_molstat.n_CN;
10265
  molstat.n_XY = tmp_molstat.n_XY;
10266
  molstat.n_r3 = tmp_molstat.n_r3;
10267
  molstat.n_r4 = tmp_molstat.n_r4;
10268
  molstat.n_r5 = tmp_molstat.n_r5;
10269
  molstat.n_r6 = tmp_molstat.n_r6;
10270
  molstat.n_r7 = tmp_molstat.n_r7;
10271
  molstat.n_r8 = tmp_molstat.n_r8;
10272
  molstat.n_r9 = tmp_molstat.n_r9;
10273
  molstat.n_r10 = tmp_molstat.n_r10;
10274
  molstat.n_r11 = tmp_molstat.n_r11;
10275
  molstat.n_r12 = tmp_molstat.n_r12;
10276
  molstat.n_r13p = tmp_molstat.n_r13p;
10277
  molstat.n_rN = tmp_molstat.n_rN;
10278
  molstat.n_rN1 = tmp_molstat.n_rN1;
10279
  molstat.n_rN2 = tmp_molstat.n_rN2;
10280
  molstat.n_rN3p = tmp_molstat.n_rN3p;
10281
  molstat.n_rO = tmp_molstat.n_rO;
10282
  molstat.n_rO1 = tmp_molstat.n_rO1;
10283
  molstat.n_rO2p = tmp_molstat.n_rO2p;
10284
  molstat.n_rS = tmp_molstat.n_rS;
10285
  molstat.n_rX = tmp_molstat.n_rX;
10286
  molstat.n_rAr = tmp_molstat.n_rAr;
10287
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
10288
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
10289
/* p2c: checkmol.pas, line 8169:
10290
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10291
  /*$IFDEF extended_molstat
10292
     molstat.n_psg01 = tmp_molstat.n_psg01;
10293
     molstat.n_psg02 = tmp_molstat.n_psg02;
10294
     molstat.n_psg13 = tmp_molstat.n_psg13;
10295
     molstat.n_psg14 = tmp_molstat.n_psg14;
10296
     molstat.n_psg15 = tmp_molstat.n_psg15;
10297
     molstat.n_psg16 = tmp_molstat.n_psg16;
10298
     molstat.n_psg17 = tmp_molstat.n_psg17;
10299
     molstat.n_psg18 = tmp_molstat.n_psg18;
10300
     molstat.n_pstm = tmp_molstat.n_pstm;
10301
     molstat.n_psla = tmp_molstat.n_psla;
10302
     $ENDIF */
10303
  /* make sure some modes can be switched on only by the query file */
10304
  /* and not by subsequent haystack file(s) */
10305
     if (ez_flag)
10306
     ez_search = true;
10307
     if (chir_flag)
10308
     rs_search = true;
10309
     }
10310
#endif
10311
 
14179 bpr 10312
static void get_ringstat (r_id)
6785 bpr 10313
     int r_id;
10314
{
10315
  int i, j;
10316
  ringpath_type testring;
10317
  int ring_size, a_ref;
10318
  str2 elem;
10319
  int nN = 0, nO = 0, nS = 0, nX = 0;
10320
 
10321
  if (r_id < 1 || r_id > n_rings)
10322
    return;
10323
  memset (testring, 0, sizeof (ringpath_type));
10324
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
10325
  for (j = 0; j < ring_size; j++)       /* v0.3j */
10326
    testring[j] = ring[r_id - 1][j];
14179 bpr 10327
    /* p2c: checkmol.pas, line 8238:
10328
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10329
#ifdef reduced_SAR
10330
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != false)
10331
    /* v0.3n: ignore envelope rings */
10332
    return;
10333
#else
10334
  if (ring_size <= 2)
10335
    return;
10336
#endif
14179 bpr 10337
  for (i = 0; i < ring_size; i++) {
10338
    a_ref = testring[i];
10339
    strcpy (elem, atom[a_ref - 1].element);
10340
    if (strcmp (elem, "C ") && strcmp (elem, "A ")) {
10341
            nX++;                       /* general heteroatom count */
10342
            if (!strcmp (elem, "N "))
10343
              nN++;
10344
            if (!strcmp (elem, "O "))
10345
              nO++;
10346
            if (!strcmp (elem, "S "))
10347
              nS++;
10348
          }
10349
  }
10350
  if (nN > 0) {
10351
    molstat.n_rN++;
10352
    if (nN == 1)
10353
            molstat.n_rN1++;
10354
    if (nN == 2)
10355
            molstat.n_rN2++;
10356
    if (nN > 2)
10357
            molstat.n_rN3p++;
10358
  }
10359
  if (nO > 0) {
10360
    molstat.n_rO++;
10361
    if (nO == 1)
10362
            molstat.n_rO1++;
10363
    if (nO == 2)
10364
            molstat.n_rO2p++;
10365
  }
6785 bpr 10366
  if (nS > 0)
10367
    molstat.n_rS++;
10368
  if (nX > 0)
10369
    molstat.n_rX++;
10370
  /* general ringsize descriptors; v0.3m */
14179 bpr 10371
  switch (ring_size) {
6785 bpr 10372
    case 3:
10373
      molstat.n_r3++;
10374
      break;
10375
 
10376
    case 4:
10377
      molstat.n_r4++;
10378
      break;
10379
 
10380
    case 5:
10381
      molstat.n_r5++;
10382
      break;
10383
 
10384
    case 6:
10385
      molstat.n_r6++;
10386
      break;
10387
 
10388
    case 7:
10389
      molstat.n_r7++;
10390
      break;
10391
 
10392
    case 8:
10393
      molstat.n_r8++;
10394
      break;
10395
 
10396
    case 9:
10397
      molstat.n_r9++;
10398
      break;
10399
 
10400
    case 10:
10401
      molstat.n_r10++;
10402
      break;
10403
 
10404
    case 11:
10405
      molstat.n_r11++;
10406
      break;
10407
 
10408
    case 12:
10409
      molstat.n_r12++;
10410
      break;
10411
 
10412
    default:
10413
      molstat.n_r13p++;
10414
      break;
14179 bpr 10415
  }                             /* end v0.3m        */
6785 bpr 10416
}
10417
 
14179 bpr 10418
static void get_molstat ()
6785 bpr 10419
{
10420
  int i;
10421
  str2 elem;
10422
  str3 atype;
10423
  int a1, a2;
10424
  str2 a1el, a2el;
10425
  char btype;
10426
  int hbc;
10427
  int n_b2formal = 0;           /* new in v0.2e */
10428
  int FORLIM;
10429
 
10430
  if (n_atoms == 0)
10431
    return;
10432
  FORLIM = n_atoms;
14179 bpr 10433
  for (i = 0; i < FORLIM; i++) {
10434
    if (atom[i].heavy) {
10435
            strcpy (elem, atom[i].element);
10436
            strcpy (atype, atom[i].atype);
10437
            if (!strcmp (atype, "C1 "))
10438
              molstat.n_C1++;
10439
            if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
10440
              molstat.n_C2++;
10441
            if (!strcmp (elem, "C "))
10442
              molstat.n_C++;
10443
            if (!strcmp (atype, "O2 "))
10444
              molstat.n_O2++;
10445
            if (!strcmp (atype, "O3 "))
10446
              molstat.n_O3++;
10447
            if (!strcmp (atype, "N1 "))
10448
              molstat.n_N1++;
10449
            if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
10450
                (!strcmp (atype, "NAM") && atom[i].arom == true))
10451
              /* v0.3n */
10452
              molstat.n_N2++;
10453
            if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
10454
                !strcmp (atype, "N3+") ||
10455
                (!strcmp (atype, "NAM") && atom[i].arom == false))
10456
              /* v0.3n */
10457
              molstat.n_N3++;
10458
            if (!strcmp (elem, "A "))   /* query atom */
10459
              molstat.n_QA++;
10460
            if (!strcmp (elem, "Q "))   /* query atom */
10461
              molstat.n_QA++;
10462
            if (!strcmp (elem, "X "))   /* query atom */
10463
              molstat.n_QA++;
10464
            if (!strcmp (elem, "S "))
10465
              molstat.n_S++;
10466
            if (!strcmp (elem, "SE"))
6785 bpr 10467
            molstat.n_SeTe++;
14179 bpr 10468
            if (!strcmp (elem, "TE"))
10469
              molstat.n_SeTe++;
10470
            if (!strcmp (elem, "F "))
10471
              molstat.n_F++;
10472
            if (!strcmp (elem, "CL"))
10473
              molstat.n_Cl++;
10474
            if (!strcmp (elem, "BR"))
10475
              molstat.n_Br++;
10476
            if (!strcmp (elem, "I "))
10477
              molstat.n_I++;
10478
            if (!strcmp (elem, "P "))
10479
              molstat.n_P++;
10480
            if (!strcmp (elem, "B "))
10481
              molstat.n_B++;
10482
            /* check for known metals */
10483
            if (atom[i].metal)  /* v0.3l */
10484
              molstat.n_Met++;
10485
            /* still missing: unknown elements */
6785 bpr 10486
 
14179 bpr 10487
            /* check number of heteroatom bonds per C atom */
10488
            if (!strcmp (elem, "C ")) {
6785 bpr 10489
              hbc = raw_hetbond_count (i + 1);
10490
              /* new in v0.2j (replaces hetbond_count) */
10491
              if (hbc >= 1)
14179 bpr 10492
                      molstat.n_CHB1p++;
6785 bpr 10493
              if (hbc >= 2)
14179 bpr 10494
                      molstat.n_CHB2p++;
6785 bpr 10495
              if (hbc >= 3)
14179 bpr 10496
                      molstat.n_CHB3p++;
6785 bpr 10497
              if (hbc == 4)
14179 bpr 10498
                      molstat.n_CHB4++;
6785 bpr 10499
            }
14179 bpr 10500
            if (atom[i].formal_charge != 0) {
6785 bpr 10501
              molstat.n_chg++;
10502
              //n_charges++;
10503
            }
14179 bpr 10504
            if (atom[i].nucleon_number != 0) {
6785 bpr 10505
              molstat.n_iso++;
10506
            }
14179 bpr 10507
            if (atom[i].radical_type != 0) {
6785 bpr 10508
              molstat.n_rad++;
10509
            }
14179 bpr 10510
            /* check for "other" elements;  v0.3l */
10511
            if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
10512
                && strcmp (elem, "O ") && strcmp (elem, "S ")
10513
                && strcmp (elem, "SE") && strcmp (elem, "TE")
10514
                && strcmp (elem, "P ") && strcmp (elem, "B ")
10515
                && strcmp (elem, "A ") && strcmp (elem, "Q "))
10516
              molstat.n_X++;
10517
            /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
10518
      /* p2c: checkmol.pas, line 8353:
10519
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10520
            /*$IFDEF extended_molstat */
10521
            if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
10522
                || !strcmp (elem, "K ") || !strcmp (elem, "RB")
10523
                || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
10524
              molstat.n_psg01++;
10525
            if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
10526
                || !strcmp (elem, "CA") || !strcmp (elem, "SR")
10527
                || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
10528
              molstat.n_psg02++;
10529
            if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
10530
                || !strcmp (elem, "GA") || !strcmp (elem, "IN")
10531
                || !strcmp (elem, "TL"))
10532
              molstat.n_psg13++;
10533
            if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
10534
                || !strcmp (elem, "GE") || !strcmp (elem, "SN")
10535
                || !strcmp (elem, "PB"))
10536
              molstat.n_psg14++;
10537
            if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
6785 bpr 10538
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
10539
              || !strcmp (elem, "BI"))
10540
            molstat.n_psg15++;
14179 bpr 10541
            if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
10542
                || !strcmp (elem, "SE") || !strcmp (elem, "TE")
10543
                || !strcmp (elem, "PO"))
10544
              molstat.n_psg16++;
10545
            if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
10546
                || !strcmp (elem, "BR") || !strcmp (elem, "I ")
10547
                || !strcmp (elem, "AT"))
10548
              molstat.n_psg17++;
10549
            if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
10550
                || !strcmp (elem, "AR") || !strcmp (elem, "KR")
10551
                || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
10552
              molstat.n_psg18++;
10553
            if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
10554
                || !strcmp (elem, "LU") || !strcmp (elem, "LR")
10555
                || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
10556
                || !strcmp (elem, "HF") || !strcmp (elem, "RF")
10557
                || !strcmp (elem, "V ") || !strcmp (elem, "NB")
10558
                || !strcmp (elem, "TA") || !strcmp (elem, "DB")
10559
                || !strcmp (elem, "CR") || !strcmp (elem, "MO")
10560
                || !strcmp (elem, "W ") || !strcmp (elem, "SG")
10561
                || !strcmp (elem, "MN") || !strcmp (elem, "TC")
10562
                || !strcmp (elem, "RE") || !strcmp (elem, "BH")
10563
                || !strcmp (elem, "FE") || !strcmp (elem, "RU")
10564
                || !strcmp (elem, "OS") || !strcmp (elem, "HS")
10565
                || !strcmp (elem, "CO") || !strcmp (elem, "RH")
10566
                || !strcmp (elem, "IR") || !strcmp (elem, "MT")
10567
                || !strcmp (elem, "NI") || !strcmp (elem, "PD")
10568
                || !strcmp (elem, "PT") || !strcmp (elem, "DS")
10569
                || !strcmp (elem, "CU") || !strcmp (elem, "AG")
10570
                || !strcmp (elem, "AU") || !strcmp (elem, "RG")
10571
                || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
10572
                || !strcmp (elem, "HG"))
10573
        /* p2c: checkmol.pas, line 8439:
10574
        * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
10575
              molstat.n_pstm++;
10576
            if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
10577
                || !strcmp (elem, "PR") || !strcmp (elem, "ND")
10578
                || !strcmp (elem, "PM") || !strcmp (elem, "SM")
10579
                || !strcmp (elem, "EU") || !strcmp (elem, "GD")
10580
                || !strcmp (elem, "TB") || !strcmp (elem, "DY")
10581
                || !strcmp (elem, "HO") || !strcmp (elem, "ER")
10582
                || !strcmp (elem, "TM") || !strcmp (elem, "YB")
10583
                || !strcmp (elem, "AC") || !strcmp (elem, "TH")
10584
                || !strcmp (elem, "PA") || !strcmp (elem, "U ")
10585
                || !strcmp (elem, "NP") || !strcmp (elem, "PU")
10586
                || !strcmp (elem, "AM") || !strcmp (elem, "CM")
10587
                || !strcmp (elem, "BK") || !strcmp (elem, "CF")
10588
                || !strcmp (elem, "ES") || !strcmp (elem, "FM")
10589
                || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
10590
      /* p2c: checkmol.pas, line 8439:
10591
      * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
10592
              molstat.n_psla++;
10593
            /*$ENDIF */
10594
          }                     /* is heavy */
10595
  }                             /* atoms */
10596
  if (n_bonds > 0) {
10597
    FORLIM = n_bonds;
10598
    for (i = 0; i < FORLIM; i++) {
10599
            a1 = bond[i].a1;
10600
            a2 = bond[i].a2;
10601
            strcpy (a1el, atom[a1 - 1].element);
10602
            strcpy (a2el, atom[a2 - 1].element);
10603
            btype = bond[i].btype;
10604
            if (bond[i].arom)
10605
              molstat.n_bar++;
10606
            else {
6785 bpr 10607
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
14179 bpr 10608
                      molstat.n_b1++;
6785 bpr 10609
              if (btype == 'D')
14179 bpr 10610
                     molstat.n_b2++;
6785 bpr 10611
              if (btype == 'T')
14179 bpr 10612
                      molstat.n_b3++;
6785 bpr 10613
            }
14179 bpr 10614
            /* v0.3n: ignore bonds to (explicit) hydrogens */
10615
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
10616
                (!strcmp (a1el, "O ") && !strcmp (a2el, "C "))) {
6785 bpr 10617
              if (btype == 'S')
14179 bpr 10618
                      molstat.n_C1O++;
6785 bpr 10619
              if (btype == 'D')
14179 bpr 10620
                      molstat.n_C2O++;
6785 bpr 10621
            }
14179 bpr 10622
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
10623
                (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
10624
              molstat.n_CN++;
10625
            if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
10626
                && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
10627
              molstat.n_XY++;
10628
            /* new in v0.3n: number of bonds belonging to more than one ring */
10629
            if (bond[i].ring_count > 1)
10630
              molstat.n_br2p++;
10631
          }
10632
  }                             /* bonds */
10633
  if (n_rings <= 0) {
6785 bpr 10634
      return;
14179 bpr 10635
  }                             /* rings */
6785 bpr 10636
  /* v0.3n */
10637
  n_countablerings = 0;         /* v0.3n */
10638
  FORLIM = n_rings;
14179 bpr 10639
  for (i = 1; i <= FORLIM; i++) {
10640
    if (ringprop[i - 1].envelope == false)      /* v0.3n */
10641
            n_countablerings++;
10642
    if (is_arene (i) && ringprop[i - 1].envelope == false) {
10643
      /* v0.3n: ignore envelope rings */
10644
            molstat.n_rAr++;
10645
            if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == false))
10646
              /* v0.3l */
10647
              molstat.n_rBz++;
10648
          }
10649
    get_ringstat (i);
10650
    if (ringprop[i - 1].arom == true && ringprop[i - 1].envelope == false)
10651
            /* new in v0.3n; replaces assignment below */
10652
            n_b2formal++;
10653
  }
6785 bpr 10654
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
10655
  /* in order to allow an isolated double bond in the needle */
10656
  /* to be matched as a ring fragment of an aromatic ring */
10657
  if (n_b2formal > molstat.n_bar / 2)
10658
    n_b2formal = molstat.n_bar / 2;
10659
  molstat.n_b2 += n_b2formal;
10660
}
10661
 
14179 bpr 10662
static void fix_ssr_ringcounts ()
6785 bpr 10663
{
10664
  /* new in v0.3n */
10665
  /* if SAR -> SSR fallback happens, set some molstat values */
10666
  /* to a maximum (ring counts for various ring sizes); */
10667
  /* this should be necessary only for ring sizes which */
10668
  /* are a) too large for the SSR (depending on ssr_vringsize) */
10669
  /* and b) which are likely to contain "envelope rings" */
10670
  /* (size 6 and above) */
10671
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
10672
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
10673
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
10674
  if (molstat.n_r6 == 0)
10675
    molstat.n_r6 = max_rings;
10676
  if (molstat.n_r7 == 0)
10677
    molstat.n_r7 = max_rings;
10678
  if (molstat.n_r8 == 0)
10679
    molstat.n_r8 = max_rings;
10680
  if (molstat.n_r9 == 0)
10681
    molstat.n_r9 = max_rings;
10682
  if (molstat.n_r10 == 0)
10683
    molstat.n_r10 = max_rings;
10684
  if (molstat.n_r11 == 0)
10685
    molstat.n_r11 = max_rings;
10686
  if (molstat.n_r12 == 0)
10687
    molstat.n_r12 = max_rings;
10688
  if (molstat.n_r13p == 0)
10689
    molstat.n_r13p = max_rings;
10690
}
10691
 
14179 bpr 10692
static void write_molstat ()
6785 bpr 10693
{
10694
  if (auto_ssr)                 /* v0.3n */
10695
    fix_ssr_ringcounts ();
10696
  printf ("n_atoms:%d;", n_heavyatoms);
10697
  /* count only non-H atoms (some molfiles contain explicit H's) */
10698
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
10699
    printf ("n_bonds:%d;", n_heavybonds);
14179 bpr 10700
  /* p2c: checkmol.pas, line 8471:
10701
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10702
#ifdef REDUCED_SAR
10703
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10704
    printf ("n_rings:%d;", n_countablerings);
10705
#else
10706
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10707
    printf ("n_rings:%d;", n_rings);
10708
#endif
10709
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
10710
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
10711
  if (molstat.n_chg > 0)        /* 0.3x */
10712
    printf ("n_chg:%d;", molstat.n_chg);
10713
 
10714
  if (molstat.n_C1 > 0)
10715
    printf ("n_C1:%d;", molstat.n_C1);
10716
  if (molstat.n_C2 > 0)
10717
    printf ("n_C2:%d;", molstat.n_C2);
10718
  /* requirement of a given number of sp3 carbons might be too restrictive, */
10719
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
10720
  if (molstat.n_C > 0)
10721
    printf ("n_C:%d;", molstat.n_C);
10722
  if (molstat.n_CHB1p > 0)
10723
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
10724
  if (molstat.n_CHB2p > 0)
10725
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
10726
  if (molstat.n_CHB3p > 0)
10727
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
10728
  if (molstat.n_CHB4 > 0)
10729
    printf ("n_CHB4:%d;", molstat.n_CHB4);
10730
  if (molstat.n_O2 > 0)
10731
    printf ("n_O2:%d;", molstat.n_O2);
10732
  if (molstat.n_O3 > 0)
10733
    printf ("n_O3:%d;", molstat.n_O3);
10734
  if (molstat.n_N1 > 0)
10735
    printf ("n_N1:%d;", molstat.n_N1);
10736
  if (molstat.n_N2 > 0)
10737
    printf ("n_N2:%d;", molstat.n_N2);
10738
  if (molstat.n_N3 > 0)
10739
    printf ("n_N3:%d;", molstat.n_N3);
10740
  if (molstat.n_S > 0)
10741
    printf ("n_S:%d;", molstat.n_S);
10742
  if (molstat.n_SeTe > 0)
10743
    printf ("n_SeTe:%d;", molstat.n_SeTe);
10744
  if (molstat.n_F > 0)
10745
    printf ("n_F:%d;", molstat.n_F);
10746
  if (molstat.n_Cl > 0)
10747
    printf ("n_Cl:%d;", molstat.n_Cl);
10748
  if (molstat.n_Br > 0)
10749
    printf ("n_Br:%d;", molstat.n_Br);
10750
  if (molstat.n_I > 0)
10751
    printf ("n_I:%d;", molstat.n_I);
10752
  if (molstat.n_P > 0)
10753
    printf ("n_P:%d;", molstat.n_P);
10754
  if (molstat.n_B > 0)
10755
    printf ("n_B:%d;", molstat.n_B);
10756
  if (molstat.n_Met > 0)
10757
    printf ("n_Met:%d;", molstat.n_Met);
10758
  if (molstat.n_X > 0)
10759
    printf ("n_X:%d;", molstat.n_X);
10760
  if (molstat.n_b1 > 0)
10761
    printf ("n_b1:%d;", molstat.n_b1);
10762
  if (molstat.n_b2 > 0)
10763
    printf ("n_b2:%d;", molstat.n_b2);
10764
  if (molstat.n_b3 > 0)
10765
    printf ("n_b3:%d;", molstat.n_b3);
10766
  if (molstat.n_bar > 0)
10767
    printf ("n_bar:%d;", molstat.n_bar);
10768
  if (molstat.n_C1O > 0)
10769
    printf ("n_C1O:%d;", molstat.n_C1O);
10770
  if (molstat.n_C2O > 0)
10771
    printf ("n_C2O:%d;", molstat.n_C2O);
10772
  if (molstat.n_CN > 0)
10773
    printf ("n_CN:%d;", molstat.n_CN);
10774
  if (molstat.n_XY > 0)
10775
    printf ("n_XY:%d;", molstat.n_XY);
10776
  if (molstat.n_r3 > 0)
10777
    printf ("n_r3:%d;", molstat.n_r3);
10778
  if (molstat.n_r4 > 0)
10779
    printf ("n_r4:%d;", molstat.n_r4);
10780
  if (molstat.n_r5 > 0)
10781
    printf ("n_r5:%d;", molstat.n_r5);
10782
  if (molstat.n_r6 > 0)
10783
    printf ("n_r6:%d;", molstat.n_r6);
10784
  if (molstat.n_r7 > 0)
10785
    printf ("n_r7:%d;", molstat.n_r7);
10786
  if (molstat.n_r8 > 0)
10787
    printf ("n_r8:%d;", molstat.n_r8);
10788
  if (molstat.n_r9 > 0)
10789
    printf ("n_r9:%d;", molstat.n_r9);
10790
  if (molstat.n_r10 > 0)
10791
    printf ("n_r10:%d;", molstat.n_r10);
10792
  if (molstat.n_r11 > 0)
10793
    printf ("n_r11:%d;", molstat.n_r11);
10794
  if (molstat.n_r12 > 0)
10795
    printf ("n_r12:%d;", molstat.n_r12);
10796
  if (molstat.n_r13p > 0)
10797
    printf ("n_r13p:%d;", molstat.n_r13p);
10798
  if (molstat.n_rN > 0)
10799
    printf ("n_rN:%d;", molstat.n_rN);
10800
  if (molstat.n_rN1 > 0)
10801
    printf ("n_rN1:%d;", molstat.n_rN1);
10802
  if (molstat.n_rN2 > 0)
10803
    printf ("n_rN2:%d;", molstat.n_rN2);
10804
  if (molstat.n_rN3p > 0)
10805
    printf ("n_rN3p:%d;", molstat.n_rN3p);
10806
  if (molstat.n_rO > 0)
10807
    printf ("n_rO:%d;", molstat.n_rO);
10808
  if (molstat.n_rO1 > 0)
10809
    printf ("n_rO1:%d;", molstat.n_rO1);
10810
  if (molstat.n_rO2p > 0)
10811
    printf ("n_rO2p:%d;", molstat.n_rO2p);
10812
  if (molstat.n_rS > 0)
10813
    printf ("n_rS:%d;", molstat.n_rS);
10814
  if (molstat.n_rX > 0)
10815
    printf ("n_rX:%d;", molstat.n_rX);
10816
  if (molstat.n_rAr > 0)
10817
    printf ("n_rar:%d;", molstat.n_rAr);
10818
/* p2c: checkmol.pas, line 8532:
10819
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10820
  /*$IFDEF extended_molstat */
10821
  if (molstat.n_rBz > 0)
10822
    printf ("n_rbz:%d;", molstat.n_rBz);
10823
  if (molstat.n_br2p > 0)
10824
    printf ("n_br2p:%d;", molstat.n_br2p);
10825
  if (molstat.n_psg01 > 0)
10826
    printf ("n_psg01:%d;", molstat.n_psg01);
10827
  if (molstat.n_psg02 > 0)
10828
    printf ("n_psg02:%d;", molstat.n_psg02);
10829
  if (molstat.n_psg13 > 0)
10830
    printf ("n_psg13:%d;", molstat.n_psg13);
10831
  if (molstat.n_psg14 > 0)
10832
    printf ("n_psg14:%d;", molstat.n_psg14);
10833
  if (molstat.n_psg15 > 0)
10834
    printf ("n_psg15:%d;", molstat.n_psg15);
10835
  if (molstat.n_psg16 > 0)
10836
    printf ("n_psg16:%d;", molstat.n_psg16);
10837
  if (molstat.n_psg17 > 0)
10838
    printf ("n_psg17:%d;", molstat.n_psg17);
10839
  if (molstat.n_psg18 > 0)
10840
    printf ("n_psg18:%d;", molstat.n_psg18);
10841
  if (molstat.n_pstm > 0)
10842
    printf ("n_pstm:%d;", molstat.n_pstm);
10843
  if (molstat.n_psla > 0)
10844
    printf ("n_psla:%d;", molstat.n_psla);
10845
  if (molstat.n_iso > 0)
10846
    printf ("n_iso:%d;", molstat.n_iso);
10847
  if (molstat.n_rad > 0)
10848
    printf ("n_rad:%d;", molstat.n_rad);
10849
  /*$ENDIF */
10850
  putchar ('\n');
10851
}
10852
 
14179 bpr 10853
static void write_molstat_X ()
6785 bpr 10854
{
10855
  if (auto_ssr)                 /* v0.3n */
10856
    fix_ssr_ringcounts ();
14179 bpr 10857
    /* p2c: checkmol.pas, line 8556:
10858
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10859
#ifdef REDUCED_SAR
10860
  printf ("%d,", n_heavyatoms);
10861
  printf ("%d,", n_heavybonds);
10862
  printf ("%d,", n_countablerings);
14179 bpr 10863
    /* v0.3n: n_rings =?> n_countablerings */
6785 bpr 10864
#else
10865
  printf ("%d,", n_heavyatoms);
10866
  printf ("%d,", n_heavybonds);
10867
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
10868
#endif
10869
  printf ("%d,", molstat.n_QA);
10870
  printf ("%d,", molstat.n_QB);
10871
 
10872
  /* 0.3x */
10873
  printf ("%d,", molstat.n_chg);
10874
 
10875
  printf ("%d,", molstat.n_C1);
10876
  printf ("%d,", molstat.n_C2);
10877
  printf ("%d,", molstat.n_C);
10878
  printf ("%d,", molstat.n_CHB1p);
10879
  printf ("%d,", molstat.n_CHB2p);
10880
  printf ("%d,", molstat.n_CHB3p);
10881
  printf ("%d,", molstat.n_CHB4);
10882
  printf ("%d,", molstat.n_O2);
10883
  printf ("%d,", molstat.n_O3);
10884
  printf ("%d,", molstat.n_N1);
10885
  printf ("%d,", molstat.n_N2);
10886
  printf ("%d,", molstat.n_N3);
10887
  printf ("%d,", molstat.n_S);
10888
  printf ("%d,", molstat.n_SeTe);
10889
  printf ("%d,", molstat.n_F);
10890
  printf ("%d,", molstat.n_Cl);
10891
  printf ("%d,", molstat.n_Br);
10892
  printf ("%d,", molstat.n_I);
10893
  printf ("%d,", molstat.n_P);
10894
  printf ("%d,", molstat.n_B);
10895
  printf ("%d,", molstat.n_Met);
10896
  printf ("%d,", molstat.n_X);
10897
  printf ("%d,", molstat.n_b1);
10898
  printf ("%d,", molstat.n_b2);
10899
  printf ("%d,", molstat.n_b3);
10900
  printf ("%d,", molstat.n_bar);
10901
  printf ("%d,", molstat.n_C1O);
10902
  printf ("%d,", molstat.n_C2O);
10903
  printf ("%d,", molstat.n_CN);
10904
  printf ("%d,", molstat.n_XY);
10905
  printf ("%d,", molstat.n_r3);
10906
  printf ("%d,", molstat.n_r4);
10907
  printf ("%d,", molstat.n_r5);
10908
  printf ("%d,", molstat.n_r6);
10909
  printf ("%d,", molstat.n_r7);
10910
  printf ("%d,", molstat.n_r8);
10911
  printf ("%d,", molstat.n_r9);
10912
  printf ("%d,", molstat.n_r10);
10913
  printf ("%d,", molstat.n_r11);
10914
  printf ("%d,", molstat.n_r12);
10915
  printf ("%d,", molstat.n_r13p);
10916
  printf ("%d,", molstat.n_rN);
10917
  printf ("%d,", molstat.n_rN1);
10918
  printf ("%d,", molstat.n_rN2);
10919
  printf ("%d,", molstat.n_rN3p);
10920
  printf ("%d,", molstat.n_rO);
10921
  printf ("%d,", molstat.n_rO1);
10922
  printf ("%d,", molstat.n_rO2p);
10923
  printf ("%d,", molstat.n_rS);
10924
  printf ("%d,", molstat.n_rX);
10925
  printf ("%d", molstat.n_rAr);
14179 bpr 10926
  /* p2c: checkmol.pas, line 8579:
10927
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10928
  /*$IFDEF extended_molstat */
10929
  printf (",%d", molstat.n_rBz);
10930
  printf (",%d", molstat.n_br2p);
10931
  printf (",%d", molstat.n_psg01);
10932
  printf (",%d", molstat.n_psg02);
10933
  printf (",%d", molstat.n_psg13);
10934
  printf (",%d", molstat.n_psg14);
10935
  printf (",%d", molstat.n_psg15);
10936
  printf (",%d", molstat.n_psg16);
10937
  printf (",%d", molstat.n_psg17);
10938
  printf (",%d", molstat.n_psg18);
10939
  printf (",%d", molstat.n_pstm);
10940
  printf (",%d", molstat.n_psla);
10941
  printf (",%d", molstat.n_iso);
10942
  printf (",%d\n", molstat.n_rad);
10943
  /*$ENDIF */
10944
}
10945
 
10946
/* routines for substructure matching */
10947
 
14179 bpr 10948
static int find_ndl_ref_atom ()
6785 bpr 10949
{
6786 kbelabas 10950
  int i;
6785 bpr 10951
  int score = -1, index = 0;
10952
  int n_nb, n_hc, FORLIM;
10953
 
10954
  /* finds a characteristic atom in the needle molecule, */
10955
  /* i.e., one with as many substituents as possible and */
10956
  /* with as many heteroatom substitutents as possible; */
10957
  /* added in v0.2d: make sure that reference atom is a heavy atom */
10958
  /* and not (accidentally) an explicit hydrogen; */
10959
  /* new in v0.3d: special treatment in case of E/Z geometry search */
10960
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
10961
  /* matchpath, regardless where the recursive search starts; */
10962
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
10963
  /* added in v0.3o: needle atom must be "tagged" in order to be */
10964
  /* selected (prevents unconnected fragments from being overlooked) */
10965
  if (ndl_n_atoms == 0)
6786 kbelabas 10966
    return false;
14179 bpr 10967
  if (ez_search && ndl_n_heavyatoms > 2) {
10968
    FORLIM = ndl_n_atoms;
10969
    for (i = 1; i <= FORLIM; i++) {                     /* ignore sp2-carbons if not aromatic */
10970
           /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = true)) then */
10971
            if (ndl_alkene_C (i) == false && ndl_atom[i - 1].tag) {                     /* v0.3o */
6785 bpr 10972
              n_nb = ndl_atom[i - 1].neighbor_count;
10973
              n_hc = ndl_hetatom_count (i);
14179 bpr 10974
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy) {
10975
                /* v0.3j */
10976
                index = i;
10977
                score = n_nb * 11 + n_hc * 7;   /* changed in v0.3j */
10978
              }
6785 bpr 10979
            }
14179 bpr 10980
          }
10981
  }
6785 bpr 10982
  /* it is possible that no suitable reference atom has been found here */
10983
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
14179 bpr 10984
  if (index == 0) {
10985
    ez_search = false;  /* just in case it was true */
10986
    opt_geom = false;           /* just in case it was true */
10987
    FORLIM = ndl_n_atoms;
10988
    for (i = 1; i <= FORLIM; i++) {
10989
            n_nb = ndl_atom[i - 1].neighbor_count;
10990
            n_hc = ndl_hetatom_count (i);
10991
            if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
10992
                ndl_atom[i - 1].tag) {                  /* v0.3j */
6785 bpr 10993
              index = i;
10994
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
10995
            }
14179 bpr 10996
            /* v0.3o */
10997
          }
10998
  }
6785 bpr 10999
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
11000
  if (index == 0)               /* just to be sure... */
11001
    index++;
11002
  return index;
11003
}
11004
 
14179 bpr 11005
static void cv_init ()
6785 bpr 11006
{
11007
  /* new in v0.3j */
11008
  int i;
11009
 
11010
  if (cv == NULL)
11011
    return;
11012
  memset (cv, 0, sizeof (connval_type));
11013
 
11014
  for (i = 0; i < ndl_n_atoms; i++)
11015
    cv[i].def = ndl_atom[i].neighbor_count;
11016
}
11017
 
14179 bpr 11018
static int cv_count ()
6785 bpr 11019
{
11020
  /* new in v0.3j, modified in v0.3m */
11021
  int i, j;
11022
  int cvlist[max_atoms];
11023
  int cvdef;
11024
  boolean isnew;
11025
  int entries = 0;
11026
  int FORLIM;
11027
 
11028
  if (cv == NULL)
11029
    return 0;
11030
  memset (cvlist, 0, sizeof (int) * max_atoms);
11031
  FORLIM = ndl_n_atoms;
14179 bpr 11032
  for (i = 0; i < FORLIM; i++) {
11033
    if (ndl_atom[i].heavy == true) {
11034
            cvdef = cv[i].def;
11035
            isnew = true;
11036
            if (entries > 0) {
11037
              for (j = 0; j < entries; j++) {
11038
                      if (cvlist[j] == cvdef)
11039
                        isnew = false;
11040
                    }
6785 bpr 11041
            }
14179 bpr 11042
            if (isnew) {
11043
                entries++;
11044
                cvlist[entries - 1] = cvdef;
6785 bpr 11045
            }
14179 bpr 11046
            /* now we have a list of unique connection values */
11047
          }
11048
  }
6785 bpr 11049
  return entries;
11050
}
11051
 
14179 bpr 11052
static int cv_iterate (n_cv_prev)
6785 bpr 11053
     int n_cv_prev;
11054
{
11055
  /* new in v0.3j, modified in v0.3m */
6788 kbelabas 11056
  int i, j;
6785 bpr 11057
  neighbor_rec nb;
11058
  int nnb, nsum, n_cv, FORLIM;
11059
 
11060
  if (cv == NULL || ndl_n_atoms == 0)
6788 kbelabas 11061
    return false;
6785 bpr 11062
  FORLIM = ndl_n_atoms;
11063
  /* update the connection values (Morgan algorithm) */
11064
 
11065
  memset (nb, 0, sizeof (neighbor_rec));
11066
 
14179 bpr 11067
  for (i = 1; i <= FORLIM; i++) {
11068
    if (ndl_atom[i - 1].heavy == true) {
11069
            get_ndl_neighbors (nb, i);
11070
            nnb = ndl_atom[i - 1].neighbor_count;
11071
            nsum = 0;
11072
            if (nnb > 0) {
11073
              for (j = 0; j < nnb; j++) {
11074
                if (ndl_atom[nb[j] - 1].heavy == true)
11075
                  nsum += cv[nb[j] - 1].def;
11076
              }
6785 bpr 11077
            }
14179 bpr 11078
            cv[i - 1].tmp = nsum;
11079
          }
11080
  }
6785 bpr 11081
  n_cv = cv_count ();
14179 bpr 11082
  if (n_cv > n_cv_prev) {
11083
    FORLIM = ndl_n_atoms;
11084
    for (i = 0; i < FORLIM; i++)
11085
            cv[i].def = cv[i].tmp;
11086
  }
6785 bpr 11087
  return n_cv;
11088
}
11089
 
14179 bpr 11090
static int find_ndl_ref_atom_cv ()
6785 bpr 11091
{
11092
  /* new in v0.3j, modified in v0.3m */
11093
  int Result, i;
11094
  int res = 1, it = 0;
11095
  int n_cv;
11096
  int n_cv_prev = 0;
11097
  boolean finished = false;
11098
  int cvmax = 0;
11099
  int FORLIM;
11100
 
11101
  if (ndl_n_atoms == 0)
11102
    return 0;
11103
  /* try */
11104
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
11105
  /* except
11106
     on e:Eoutofmemory do
11107
     begin
11108
     res := find_ndl_ref_atom;
11109
     $IFDEF debug
11110
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
11111
     $ENDIF
11112
     end;
11113
     end; */
11114
  cv_init ();
14179 bpr 11115
  do {
11116
    it++;                       /* iteration counter (a safeguard against infinite loops) */
11117
    n_cv = cv_iterate (n_cv_prev);
11118
    if (n_cv <= n_cv_prev)
11119
            finished = true;
11120
    n_cv_prev = n_cv;
11121
  }
6785 bpr 11122
  while (!(finished || it > 10000));
11123
  FORLIM = ndl_n_atoms;
11124
  /* now that we have canonical connection values (Morgan algorithm), */
11125
  /* pick the atom with the highest value */
11126
  /* added in v0.3o: atom must be "tagged" */
14179 bpr 11127
  for (i = 1; i <= FORLIM; i++) {
6785 bpr 11128
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
14179 bpr 11129
    if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == false || ez_search == false))
11130
              && ndl_atom[i - 1].tag) {                 /* v0.3o */
11131
            cvmax = cv[i - 1].def;
11132
            res = i;
11133
          }
11134
  }
6785 bpr 11135
  Result = res;
11136
  /* try */
14179 bpr 11137
  if (cv != NULL) {
6785 bpr 11138
      free (cv);
11139
      cv = NULL;
11140
    }
11141
  /* except
11142
     on e:Einvalidpointer do begin end;
11143
     end; */
11144
  return Result;
11145
}
11146
 
14179 bpr 11147
static boolean atomtypes_OK_strict (ndl_a, hst_a)
6785 bpr 11148
     int ndl_a, hst_a;
11149
{
11150
  /* new in v0.2f */
11151
  str2 ndl_el;
11152
  str3 ndl_atype;
11153
  str2 hst_el;
11154
  str3 hst_atype;
11155
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
11156
  boolean res = false;
11157
 
11158
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11159
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
11160
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11161
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11162
  strcpy (hst_el, atom[hst_a - 1].element);
11163
  strcpy (hst_atype, atom[hst_a - 1].atype);
11164
  hst_nbc = atom[hst_a - 1].neighbor_count;
11165
  hst_Htot = atom[hst_a - 1].Htot;
11166
  /* v0.3o: formal charges must be the same */
11167
 
11168
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
11169
    return false;
11170
 
11171
  /* v0.3x: isotope nucleon numbers must be the same */
11172
 
11173
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
11174
    return false;
11175
 
11176
  /* v0.3x: radicals must be the same */
11177
 
11178
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11179
    return false;
11180
 
11181
  if (!strcmp (ndl_atype, hst_atype))
11182
    res = true;
14179 bpr 11183
  else {
11184
    if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom && atom[hst_a - 1].arom)
11185
            res = true;
11186
    if (ndl_querymol && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
11187
            res = true;         /* 0.3 p */
11188
  }
6785 bpr 11189
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
11190
    res = true;
14179 bpr 11191
  if (!strcmp (ndl_el, "Q ")) {
11192
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
11193
            res = true;
11194
  }
11195
  if (!strcmp (ndl_el, "X ")) {
11196
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11197
            !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11198
            || !strcmp (hst_el, "AT"))
11199
          res = true;
11200
  }
6785 bpr 11201
  /* if needle atom has more substituents than haystack atom ==> no match */
11202
  if (ndl_nbc > hst_nbc)
11203
    res = false;
11204
  /* check for explicit hydrogens */
11205
  if (ndl_Hexp > hst_Htot)
11206
    res = false;
14179 bpr 11207
    /* p2c: checkmol.pas, line 8859:
11208
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11209
    /*$IFDEF debug */
11210
    /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
6785 bpr 11211
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
14179 bpr 11212
    /*$ENDIF */
11213
    /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
11214
  if (opt_fp) {
11215
    if (strcmp (ndl_el, hst_el))
11216
            res = false;
11217
  }
6785 bpr 11218
  return res;
11219
}
11220
 
14179 bpr 11221
static boolean atomtypes_OK (ndl_a, hst_a)
6785 bpr 11222
     int ndl_a, hst_a;
11223
{
11224
  str2 ndl_el, hst_el;
11225
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
11226
  boolean res = false;
11227
 
11228
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
11229
    return false;
11230
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
11231
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
11232
  /* are tolerated (this is a feature, not a bug) */
14179 bpr 11233
  if (opt_chg) {
11234
    if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
6785 bpr 11235
        return false;
14179 bpr 11236
  }
11237
  //  else
11238
  //    {
11239
  //      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
11240
  //        atom[hst_a - 1].formal_charge != 0 &&
11241
  //        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
11242
  //      return false;
11243
  //    }
11244
  //
11245
  //  /* v0.3x: isotopes must be the same */
11246
  if (opt_iso) {
11247
    if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
11248
            return false;
11249
  }
11250
  //  else
11251
  //    {
11252
  //      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
11253
  //        atom[hst_a - 1].nucleon_number != 0 &&
11254
  //        ndl_atom[ndl_a - 1].nucleon_number !=
11255
  //        atom[hst_a - 1].nucleon_number)
11256
  //      return false;
11257
  //    }
11258
  //
11259
  //  /* v0.3x: radicals must be the same */
11260
  if (opt_rad) {
11261
    if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11262
            return false;
11263
  }
11264
  //  else
11265
  //    {
11266
  //      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
11267
  //        atom[hst_a - 1].radical_type != 0 &&
11268
  //        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11269
  //      return false;
11270
  //    }
6785 bpr 11271
 
11272
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
14179 bpr 11273
  if (opt_exact && atom[hst_a - 1].tag == true) {
11274
    /* p2c: checkmol.pas, line 8899:
11275
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11276
      /*$IFDEF debug */
11277
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
11278
      /*$ENDIF */
11279
      return false;
14179 bpr 11280
  }
6785 bpr 11281
  if (opt_strict)               /* new in v0.2f */
11282
    return (atomtypes_OK_strict (ndl_a, hst_a));
11283
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11284
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11285
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11286
  strcpy (hst_el, atom[hst_a - 1].element);
11287
  hst_nbc = atom[hst_a - 1].neighbor_count;
11288
  hst_Htot = atom[hst_a - 1].Htot;
11289
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
11290
    res = true;
11291
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
11292
    res = true;
14179 bpr 11293
  if (!strcmp (ndl_el, "Q ")) {
11294
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
11295
            res = true;
11296
  }
11297
  if (!strcmp (ndl_el, "X ")) {
11298
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11299
              !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11300
              || !strcmp (hst_el, "AT"))
11301
            res = true;
11302
  }
6785 bpr 11303
  /* v0.3o: in exact mode, check for identical neighbor_count */
14179 bpr 11304
  if (opt_exact) {
11305
    if (ndl_nbc != hst_nbc) {
6785 bpr 11306
          res = false;
14179 bpr 11307
    /* p2c: checkmol.pas, line 8934:
11308
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11309
          /*$IFDEF debug */
11310
          //debugoutput
11311
          //  ("exact match failed: different number of neighbor atoms");
11312
          /*$ENDIF */
11313
          }
11314
  }
6785 bpr 11315
  /* if needle atom has more substituents than haystack atom ==> no match */
11316
  if (ndl_nbc > hst_nbc)
11317
    res = false;
11318
  /* check for explicit hydrogens */
11319
  if (ndl_Hexp > hst_Htot)
11320
    res = false;
14179 bpr 11321
  /* p2c: checkmol.pas, line 8943:
11322
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11323
  /*$IFDEF debug */
11324
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
11325
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
11326
  /*$ENDIF */
11327
  return res;
11328
}
11329
 
14179 bpr 11330
static boolean bondtypes_OK_strict (ndl_b, hst_b)
6785 bpr 11331
     int ndl_b, hst_b;
11332
{
11333
  boolean ndl_arom, hst_arom;
11334
  char ndl_btype, hst_btype;
11335
  int ndl_rc;                   /* new in v0.3d */
11336
  int hst_rc;                   /* new in v0.3d */
11337
  int ndl_btopo;                /* new in v0.3d */
11338
  boolean res = false;
14179 bpr 11339
  /* p2c: checkmol.pas, line 8960:
11340
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11341
  /*$IFDEF debug */
11342
  /*char na[256]; char ha[256];*/
11343
  char tstr[256];
11344
 
11345
  /*$ENDIF */
14179 bpr 11346
  /* p2c: checkmol.pas, line 8966:
11347
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11348
  /*$IFDEF debug */
11349
  *tstr = '\0';                 /* for debugging purposes only */
11350
  /*$ENDIF */
11351
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11352
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11353
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11354
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
11355
  hst_arom = bond[hst_b - 1].arom;
11356
  hst_btype = bond[hst_b - 1].btype;
11357
  hst_rc = bond[hst_b - 1].ring_count;
14179 bpr 11358
  /* p2c: checkmol.pas, line 8976:
11359
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11360
   /*$IFDEF debug */
11361
   /*if (ndl_arom)
11362
     strcpy (na, "(ar)");
11363
   else
11364
     *na = '\0';
11365
   if (hst_arom)
11366
     strcpy (ha, "(ar)");
11367
   else
11368
     *ha = '\0';*/
11369
   /*$ENDIF */
6785 bpr 11370
  if (ndl_arom == true && hst_arom == true)
11371
    res = true;
14179 bpr 11372
  if (ndl_arom == false && hst_arom == false) {
11373
    if (ndl_btype == hst_btype)
11374
            res = true;
11375
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
11376
            res = true;
11377
    if (ndl_btype == 's' && hst_btype == 'S')
11378
            res = true;
11379
    if (ndl_btype == 'd' && hst_btype == 'D')
11380
            res = true;
11381
  }
6785 bpr 11382
  /* a little exception: */
14179 bpr 11383
  if (ndl_arom == false && hst_arom == true) {
11384
    if (ndl_btype == 'A')
11385
            res = true;
11386
    if (ndl_btype == 's' || ndl_btype == 'd')
11387
            res = true;
11388
    if (ndl_bond[ndl_b - 1].q_arom)
11389
            res = true;         /* 0.3p */
11390
  }
6785 bpr 11391
  if (ndl_btype == 'a')
11392
    res = true;
11393
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
14179 bpr 11394
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc) {
11395
    if (ndl_rc != hst_rc) {
11396
            res = false;                /* this excludes further ring annulations as well as */
11397
      /* p2c: checkmol.pas, line 9001:
11398
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11399
            /*$IFDEF debug */
11400
            /* open-chains query structures to be found in rings */
11401
            /*
11402
               tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
11403
            /*$ENDIF */
11404
          }
11405
  }
11406
  else {
11407
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc) {
11408
            res = false;
11409
    /* p2c: checkmol.pas, line 9010:
11410
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11411
          /*$IFDEF debug */
11412
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
11413
          /*$ENDIF */
14179 bpr 11414
          }
11415
  }
11416
  /* p2c: checkmol.pas, line 9015:
11417
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11418
    /*$IFDEF debug */
11419
    /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11420
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11421
    /*$ENDIF */
6785 bpr 11422
  return res;
11423
}
11424
 
14179 bpr 11425
static boolean bondtypes_OK (ndl_b, hst_b)
6785 bpr 11426
     int ndl_b, hst_b;
11427
{
11428
  boolean ndl_arom, hst_arom;
11429
  char ndl_btype, hst_btype;
11430
  int ndl_rc;                   /* new in v0.3d */
11431
  int hst_rc;                   /* new in v0.3d */
11432
  int ndl_btopo;                /* new in v0.3d */
11433
  boolean res = false;
14179 bpr 11434
  /* p2c: checkmol.pas, line 9032:
11435
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11436
  /*$IFDEF debug */
11437
  /*char na[256], ha[256];*/
11438
  char tstr[256];
11439
  /*$ENDIF */
11440
  int a1, a2;
11441
  str2 a1_el, a2_el;
11442
 
11443
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
11444
    return false;
11445
  if (opt_strict)               /* new in v0.2f */
11446
    return (bondtypes_OK_strict (ndl_b, hst_b));
14179 bpr 11447
  /* p2c: checkmol.pas, line 9051:
11448
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11449
  /*$IFDEF debug */
11450
  *tstr = '\0';                 /* for debug purposes only */
11451
  /*$ENDIF */
11452
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11453
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11454
  hst_arom = bond[hst_b - 1].arom;
11455
  hst_btype = bond[hst_b - 1].btype;
11456
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11457
  hst_rc = bond[hst_b - 1].ring_count;
11458
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
14179 bpr 11459
  /* p2c: checkmol.pas, line 9061:
11460
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11461
    /*$IFDEF debug */
11462
    //if (ndl_arom)
11463
  //    strcpy (na, "(ar)");
11464
  //  else
11465
  //    *na = '\0';
11466
  //  if (hst_arom)
11467
  //    strcpy (ha, "(ar)");
11468
  //  else
11469
  //    *ha = '\0';
6785 bpr 11470
  /*$ENDIF */
11471
  if (ndl_arom == true && hst_arom == true)
11472
    res = true;
14179 bpr 11473
  if (ndl_arom == false && hst_arom == false) {
11474
    if (ndl_btype == hst_btype)
11475
            res = true;
11476
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
11477
            res = true;
11478
    if (ndl_btype == 's' && hst_btype == 'S')
11479
            res = true;
11480
    if (ndl_btype == 'd' && hst_btype == 'D')
11481
            res = true;
11482
  }
6785 bpr 11483
  /* a little exception: */
14179 bpr 11484
  if (ndl_arom == false && hst_arom == true) {
11485
    if (ndl_btype == 'A')
6785 bpr 11486
            res = true;
14179 bpr 11487
    if (ndl_btype == 's' || ndl_btype == 'd')
11488
            res = true;
11489
    if (ndl_btype == 'D') {                     /* added in 0.2d: do not accept C=O etc. as C-O/arom */
11490
            a1 = ndl_bond[ndl_b - 1].a1;
11491
            a2 = ndl_bond[ndl_b - 1].a2;
11492
            strcpy (a1_el, ndl_atom[a1 - 1].element);
11493
            strcpy (a2_el, ndl_atom[a2 - 1].element);
11494
            if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
11495
                && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
11496
                && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
11497
                && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
11498
              res = true;
11499
          }
11500
    if (ndl_bond[ndl_b - 1].q_arom)
11501
            res = true;         /* 0.3p */
11502
  }
6785 bpr 11503
  if (ndl_btype == 'a')
11504
    res = true;
11505
  /* new in v0.3d: obey topology requirements in query structure */
14179 bpr 11506
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any) {
11507
    if (ndl_btopo == btopo_ring && hst_rc == 0)
11508
      res = false;
11509
    if (ndl_btopo == btopo_chain && hst_rc > 0)
11510
      res = false;
11511
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
11512
      res = false;
11513
    if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
11514
      res = false;
11515
  }
11516
  /* p2c: checkmol.pas, line 9098:
11517
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11518
    /*$IFDEF debug */
11519
    /* if res = false then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
11520
    /*$ENDIF */
11521
  /* p2c: checkmol.pas, line 9102:
11522
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11523
    /*$IFDEF debug */
11524
    /*
11525
       if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11526
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11527
    /*$ENDIF */
6785 bpr 11528
  return res;
11529
}
11530
 
14179 bpr 11531
static boolean matrix_OK (m, ndl_dim, hst_dim)
6785 bpr 11532
boolean (*m)[max_neighbors];
11533
     int ndl_dim, hst_dim;
11534
{
11535
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
11536
  boolean mr = false;
11537
  matchmatrix lm;
11538
  int i, ii, j, lndl_dim, lhst_dim;
11539
 
11540
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
11541
      hst_dim > max_neighbors || ndl_dim > hst_dim)
11542
    return false;
14179 bpr 11543
  if (ndl_dim == 1) {
11544
    for (i = 0; i < hst_dim; i++) {
11545
            if (m[0][i])
11546
              mr = true;
11547
          }
11548
    return mr;
11549
  }
11550
  for (i = 1; i <= hst_dim; i++) {
11551
    if (m[0][i - 1]) {
11552
            /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
11553
            memset (lm, false, sizeof (matchmatrix));
11554
            for (j = 2; j <= ndl_dim; j++) {
6785 bpr 11555
              lhst_dim = 0;
14179 bpr 11556
              for (ii = 1; ii <= hst_dim; ii++) {
11557
                if (ii != i) {
11558
                  lhst_dim++;
11559
                  lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
11560
                }
11561
              }
6785 bpr 11562
            }
14179 bpr 11563
            lndl_dim = ndl_dim - 1;
11564
            if (matrix_OK (lm, lndl_dim, lhst_dim)) {                   /* recursive call to matrix_OK */
6785 bpr 11565
              return true;
14179 bpr 11566
            /* stop any further work immediately */
6785 bpr 11567
            }
14179 bpr 11568
          }
11569
  }
6785 bpr 11570
  return false;
11571
}
11572
 
14179 bpr 11573
static boolean is_flat (angle_deg)
6785 bpr 11574
     double angle_deg;
11575
{
11576
  /* new in v0.3j */
11577
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
11578
    return false;
11579
  else
11580
    return true;
11581
}
11582
 
14179 bpr 11583
static boolean chirality_OK (ndl_cp, hst_cp)
6785 bpr 11584
     int *ndl_cp, *hst_cp;
11585
{
11586
  boolean res = true;
11587
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
11588
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
11589
  int level = 0;
11590
  int i;
11591
  boolean up = false, down = false, updown = false;
11592
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
11593
 
11594
  /* fill temporary atom variables */
11595
  ta1 = ndl_cp[0];              /* this is the central atom */
11596
  ta2 = ndl_cp[1];
11597
  ta3 = ndl_cp[2];
11598
  ta4 = ndl_cp[3];
11599
  /* first, get the central atom of the needle */
11600
  np2.x = ndl_atom[ta1 - 1].x;
11601
  np2.y = ndl_atom[ta1 - 1].y;
11602
  np2.z = ndl_atom[ta1 - 1].z;
11603
  /* next, do the same for all 3 substituent atoms */
11604
  np1.x = ndl_atom[ta2 - 1].x;
11605
  np1.y = ndl_atom[ta2 - 1].y;
11606
  np1.z = ndl_atom[ta2 - 1].z;
11607
  np3.x = ndl_atom[ta3 - 1].x;
11608
  np3.y = ndl_atom[ta3 - 1].y;
11609
  np3.z = ndl_atom[ta3 - 1].z;
11610
  np4.x = ndl_atom[ta4 - 1].x;
11611
  np4.y = ndl_atom[ta4 - 1].y;
11612
  np4.z = ndl_atom[ta4 - 1].z;
11613
  /* now check all needle bonds if we should care about up/down bonds */
14179 bpr 11614
  if (ndl_n_bonds > 0) {
11615
    FORLIM = ndl_n_bonds;
11616
    for (i = 0; i < FORLIM; i++) {
11617
            if (ndl_bond[i].stereo == bstereo_up ||
11618
                  ndl_bond[i].stereo == bstereo_down) {
6785 bpr 11619
              ba1 = ndl_bond[i].a1;
11620
              ba2 = ndl_bond[i].a2;
14179 bpr 11621
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up) {
11622
                      up = true;
11623
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11624
                        updown = true;
11625
                        if (ba2 == ta2)
11626
                                np1.z += 0.8;
11627
                        if (ba2 == ta3)
11628
                                np3.z += 0.8;
11629
                        if (ba2 == ta4)
11630
                                np4.z += 0.8;
11631
                      }
11632
                      else
11633
                        level++;
6785 bpr 11634
                    }
14179 bpr 11635
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down) {
11636
                      down = true;
11637
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11638
                        updown = true;
11639
                        if (ba2 == ta2)
11640
                                np1.z -= 0.8;
11641
                        if (ba2 == ta3)
11642
                                np3.z -= 0.8;
11643
                        if (ba2 == ta4)
11644
                                np4.z -= 0.8;
11645
                      }
11646
                      else
11647
                        level--;
6785 bpr 11648
                    }
14179 bpr 11649
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up) {
11650
                      down = true;
11651
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11652
                        updown = true;
11653
                        if (ba1 == ta2)
11654
                          np1.z -= 0.8;
11655
                        if (ba1 == ta3)
11656
                          np3.z -= 0.8;
11657
                        if (ba1 == ta4)
11658
                          np4.z -= 0.8;
11659
                      }
11660
                      else
11661
                        level--;
6785 bpr 11662
                    }
14179 bpr 11663
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down) {
11664
                      up = true;
11665
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11666
                        updown = true;
11667
                        if (ba1 == ta2)
11668
                                np1.z += 0.8;
11669
                        if (ba1 == ta3)
11670
                                np3.z += 0.8;
11671
                        if (ba1 == ta4)
11672
                                np4.z += 0.8;
11673
                      }
11674
                      else
11675
                        level++;
6785 bpr 11676
                    }
11677
            }
14179 bpr 11678
          }                     /* for i ... */
11679
    if (updown == false && level != 0) {
11680
            if (level > 0)
11681
              np2.z += 0.3;
11682
            if (level < 0)
11683
              np2.z -= 0.3;
11684
          }
11685
    else {
11686
            if (up)
11687
              np2.z += 0.1;
11688
            if (down)
11689
              np2.z -= 0.1;
11690
          }
11691
  }
6785 bpr 11692
  /* fill temporary atom variables again */
11693
  ta1 = hst_cp[0];
11694
  ta2 = hst_cp[1];
11695
  ta3 = hst_cp[2];
11696
  ta4 = hst_cp[3];
11697
  /* then, get the central atom of the haystack */
11698
  hp2.x = atom[ta1 - 1].x;
11699
  hp2.y = atom[ta1 - 1].y;
11700
  hp2.z = atom[ta1 - 1].z;
11701
  /* next, do the same for all 3 substituent atoms */
11702
  hp1.x = atom[ta2 - 1].x;
11703
  hp1.y = atom[ta2 - 1].y;
11704
  hp1.z = atom[ta2 - 1].z;
11705
  hp3.x = atom[ta3 - 1].x;
11706
  hp3.y = atom[ta3 - 1].y;
11707
  hp3.z = atom[ta3 - 1].z;
11708
  hp4.x = atom[ta4 - 1].x;
11709
  hp4.y = atom[ta4 - 1].y;
11710
  hp4.z = atom[ta4 - 1].z;
11711
  /* now check all haystack bonds if we should care about up/down bonds */
11712
  level = 0;
11713
  updown = false;
11714
  up = false;
11715
  down = false;
14179 bpr 11716
  if (n_bonds > 0) {
11717
    FORLIM = n_bonds;
11718
    for (i = 0; i < FORLIM; i++) {
11719
            if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down) {
6785 bpr 11720
              ba1 = bond[i].a1;
11721
              ba2 = bond[i].a2;
14179 bpr 11722
              if (ba1 == ta1 && bond[i].stereo == bstereo_up) {
11723
                      up = true;
11724
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11725
                        updown = true;
11726
                        if (ba2 == ta2)
11727
                                hp1.z += 0.8;
11728
                        if (ba2 == ta3)
11729
                                hp3.z += 0.8;
11730
                        if (ba2 == ta4)
11731
                                hp4.z += 0.8;
11732
                      }
11733
                      else
11734
                        level++;
6785 bpr 11735
                    }
14179 bpr 11736
              if (ba1 == ta1 && bond[i].stereo == bstereo_down) {
11737
                      down = true;
11738
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11739
                        updown = true;
11740
                        if (ba2 == ta2)
11741
                              hp1.z -= 0.8;
11742
                        if (ba2 == ta3)
11743
                                hp3.z -= 0.8;
11744
                        if (ba2 == ta4)
11745
                              hp4.z -= 0.8;
11746
                     }
11747
                    else
11748
                      level--;
6785 bpr 11749
                    }
14179 bpr 11750
              if (ba2 == ta1 && bond[i].stereo == bstereo_up) {
11751
                      down = true;
11752
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11753
                        updown = true;
11754
                        if (ba1 == ta2)
11755
                               hp1.z -= 0.8;
11756
                        if (ba1 == ta3)
11757
                                hp3.z -= 0.8;
11758
                        if (ba1 == ta4)
11759
                                hp4.z -= 0.8;
11760
                      }
11761
                      else
11762
                        level--;
6785 bpr 11763
                    }
14179 bpr 11764
              if (ba2 == ta1 && bond[i].stereo == bstereo_down) {
11765
                      up = true;
11766
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11767
                        updown = true;
11768
                        if (ba1 == ta2)
11769
                                hp1.z += 0.8;
11770
                        if (ba1 == ta3)
11771
                                hp3.z += 0.8;
11772
                        if (ba1 == ta4)
11773
                                hp4.z += 0.8;
11774
                      }
11775
                      else
11776
                        level++;
6785 bpr 11777
                    }
11778
            }
14179 bpr 11779
          }                     /* for i ... */
11780
    if (updown == false && level != 0) {
11781
            if (level > 0)
11782
              hp2.z += 0.3;
11783
            if (level < 0)
11784
              hp2.z -= 0.3;
11785
          }
11786
    else {
11787
            if (up)
11788
              hp2.z += 0.1;
11789
            if (down)
11790
              hp2.z -= 0.1;
11791
          }
11792
  }
6785 bpr 11793
  /* get the pseudo-torsion angles */
11794
  ndl_ct = ctorsion (np1, np2, np3, np4);
11795
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
11796
  ndl_ct_deg = radtodeg (ndl_ct);
11797
  hst_ct_deg = radtodeg (hst_ct);
11798
  /* now do a plausibility check and finally check the sense */
11799
  /* (clockwise or counterclockwise) */
11800
  /*
11801
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
11802
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
11803
     (ndl_ct_deg * hst_ct_deg < 0) then res := false;
11804
   */
11805
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
11806
      ndl_ct_deg * hst_ct_deg < 0)
11807
    res = false;
14179 bpr 11808
  if (rs_strict) {
6785 bpr 11809
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) |
14179 bpr 11810
                (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
11811
                ndl_ct_deg * hst_ct_deg < 0)
11812
              res = false;
11813
  }
6785 bpr 11814
  return res;
11815
}
11816
 
14179 bpr 11817
static boolean ndl_maybe_chiral (na)
6785 bpr 11818
     int na;
11819
{
11820
  /* new in v0.3h */
11821
  boolean res = false;
11822
  str2 el;
11823
  str3 at;
11824
  int n_nb;
11825
 
11826
  strcpy (el, ndl_atom[na - 1].element);
11827
  strcpy (at, ndl_atom[na - 1].atype);
11828
  n_nb = ndl_atom[na - 1].neighbor_count;
11829
  if (!strcmp (at, "C3 ") && n_nb > 2)
11830
    res = true;
14179 bpr 11831
  if (!strcmp (el, "N ")) {
11832
    if (!strcmp (at, "N3+") && n_nb == 4)
11833
            res = true;
11834
  }
11835
  if (!strcmp (el, "S ")) {                             /* sulfoxide */
11836
    if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
11837
            res = true;
11838
  }
6785 bpr 11839
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
11840
    return res;
11841
  if (n_nb > 3)                 /* are we missing something here? */
11842
    res = true;
11843
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
11844
    res = false;
11845
  return res;
11846
}
11847
 
14179 bpr 11848
static boolean is_matching (ndl_xmp, hst_xmp)
6785 bpr 11849
     int *ndl_xmp, *hst_xmp;
11850
{
11851
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
11852
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
11853
  int next_ndl_a, next_hst_a;
11854
  neighbor_rec ndl_nb, hst_nb;
11855
  matchmatrix mm;
11856
  int ndl_mp_len, hst_mp_len;
11857
  matchpath_type ndl_mp, hst_mp;
11858
  boolean emptyline, res, ndl_cis, hst_cis;
11859
  int na1, na2, na3, na4;       /* v0.3d */
11860
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
11861
  int prev_ndl_b;
11862
  int prev_hst_b;
11863
  p_3d p1, p2, p3, p4;
11864
  /*hst_torsion, ndl_torsion : double; */
11865
  chirpath_type ncp, hcp;
11866
  int n_hits, n_singlehits;
14179 bpr 11867
  /* p2c: checkmol.pas, line 9433:
11868
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11869
  /*$IFDEF debug */
11870
  //char tmpstr[256];
11871
 
11872
  /*$ENDIF */
11873
  /* initialize local matchpath variables */
11874
  //memset (ndl_mp, 0, sizeof (matchpath_type));
11875
  //memset (hst_mp, 0, sizeof (matchpath_type));
11876
  /* copy content of external variables into local ones */
11877
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
11878
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
11879
 
11880
  /*for (i = 0; i < max_matchpath_length; i++)
11881
     {
11882
     ndl_mp[i] = ndl_xmp[i];
11883
     hst_mp[i] = hst_xmp[i];
11884
     } */
11885
 
11886
  ndl_mp_len = matchpath_length (ndl_mp);
11887
  hst_mp_len = matchpath_length (hst_mp);
14179 bpr 11888
  if (ndl_mp_len != hst_mp_len) {
6785 bpr 11889
      /* this should never happen.... */
14179 bpr 11890
  /* p2c: checkmol.pas, line 9451:
11891
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11892
      /*$IFDEF debug */
11893
      //debugoutput ("needle and haystack matchpaths are of different length");
11894
      /*$ENDIF */
14179 bpr 11895
    return false;
11896
  }
6785 bpr 11897
  ndl_a = ndl_mp[ndl_mp_len - 1];
11898
  hst_a = hst_mp[hst_mp_len - 1];
11899
  ndl_atom[ndl_a - 1].tag = false;
11900
  /* new in v0.3o: mark the last needle atom as "visited" */
14179 bpr 11901
  if (ndl_mp_len > 1) {
11902
    prev_ndl_a = ndl_mp[ndl_mp_len - 2];
11903
    prev_hst_a = hst_mp[hst_mp_len - 2];
6785 bpr 11904
    }
11905
  /* if geometry checking is on, check it here */
14179 bpr 11906
  if (ez_search == true && ndl_mp_len > 3) {
11907
    na1 = ndl_mp[ndl_mp_len - 1];
11908
    na2 = ndl_mp[ndl_mp_len - 2];
11909
    na3 = ndl_mp[ndl_mp_len - 3];
11910
    na4 = ndl_mp[ndl_mp_len - 4];
11911
    ha1 = hst_mp[hst_mp_len - 1];
11912
    ha2 = hst_mp[hst_mp_len - 2];
11913
    ha3 = hst_mp[hst_mp_len - 3];
11914
    ha4 = hst_mp[hst_mp_len - 4];
11915
    prev_ndl_b = get_ndl_bond (na2, na3);
11916
    prev_hst_b = get_bond (ha2, ha3);
11917
    if (ndl_bond[prev_ndl_b - 1].btype == 'D' && bond[prev_hst_b - 1].arom == false
11918
              && (ndl_bond[prev_ndl_b - 1].stereo != bstereo_double_either
11919
              && bond[prev_hst_b - 1].stereo != bstereo_double_either)
11920
              /* 0.3x always match if needle and/or haystack bond is double_either */
11921
              && (!strcmp (atom[ha2 - 1].element, "C ")
11922
              || !strcmp (atom[ha2 - 1].element, "N "))
11923
              && (!strcmp (atom[ha3 - 1].element, "C ")
11924
              || !strcmp (atom[ha3 - 1].element, "N "))){
11925
                /* v0.3g; check C=C, C=N, N=N bonds */
11926
            p1.x = atom[ha1 - 1].x;
11927
            p1.y = atom[ha1 - 1].y;
11928
            p1.z = atom[ha1 - 1].z;
11929
            p2.x = atom[ha2 - 1].x;
11930
            p2.y = atom[ha2 - 1].y;
11931
            p2.z = atom[ha2 - 1].z;
11932
            p3.x = atom[ha3 - 1].x;
11933
            p3.y = atom[ha3 - 1].y;
11934
            p3.z = atom[ha3 - 1].z;
11935
            p4.x = atom[ha4 - 1].x;
11936
            p4.y = atom[ha4 - 1].y;
11937
            p4.z = atom[ha4 - 1].z;
11938
            hst_cis = is_cis (p1, p2, p3, p4);
11939
            /*hst_torsion := torsion(p1,p2,p3,p4); */
11940
            p1.x = ndl_atom[na1 - 1].x;
11941
            p1.y = ndl_atom[na1 - 1].y;
11942
            p1.z = ndl_atom[na1 - 1].z;
11943
            p2.x = ndl_atom[na2 - 1].x;
11944
            p2.y = ndl_atom[na2 - 1].y;
11945
            p2.z = ndl_atom[na2 - 1].z;
11946
            p3.x = ndl_atom[na3 - 1].x;
11947
            p3.y = ndl_atom[na3 - 1].y;
11948
            p3.z = ndl_atom[na3 - 1].z;
11949
            p4.x = ndl_atom[na4 - 1].x;
11950
            p4.y = ndl_atom[na4 - 1].y;
11951
            p4.z = ndl_atom[na4 - 1].z;
11952
            /*ndl_torsion := torsion(p1,p2,p3,p4); */
11953
            ndl_cis = is_cis (p1, p2, p3, p4);
11954
            if (ndl_cis != hst_cis) {
11955
        /* p2c: checkmol.pas, line 9501:
11956
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11957
              /*$IFDEF debug */
11958
              //debugoutput ("E/Z geometry mismatch");
11959
              /*$ENDIF */
11960
              return false;
11961
            }
14179 bpr 11962
          }
11963
  }                             /* end of E/Z geometry check */
6785 bpr 11964
  /* check whatever can be checked as early as now: */
11965
  /* e.g. different elements or more substituents on needle atom than on haystack */
11966
  if (!atomtypes_OK (ndl_a, hst_a))
11967
    return false;
11968
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
14179 bpr 11969
  if (atom[hst_a - 1].neighbor_count == 0 && ndl_atom[ndl_a - 1].neighbor_count == 0) {
11970
    if (!atomtypes_OK (ndl_a, hst_a))
11971
            return false;
11972
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
11973
    atom[hst_a - 1].tag = true;
11974
    return true;
11975
  }
6785 bpr 11976
  /* and other possibilities: */
11977
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
11978
  hst_b = get_bond (prev_hst_a, hst_a);
14179 bpr 11979
  /* p2c: checkmol.pas, line 9529:
11980
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11981
  /*$IFDEF debug */
11982
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
11983
  /*$ENDIF */
14179 bpr 11984
  if (ndl_b > 0 && hst_b > 0) {
11985
    /* do a quick check if bond types match */
11986
    if (!bondtypes_OK (ndl_b, hst_b)) {
11987
      /* p2c: checkmol.pas, line 9537:
11988
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11989
            /*$IFDEF debug */
11990
            /*
6785 bpr 11991
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
14179 bpr 11992
           /*$ENDIF */
11993
            return false;
11994
          }
11995
  }
6785 bpr 11996
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
14179 bpr 11997
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a, hst_a) &&
11998
      bondtypes_OK (ndl_b, hst_b)) {
11999
    return true;
12000
  /* p2c: checkmol.pas, line 9549:
12001
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12002
      /*$IFDEF debug */
12003
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
12004
      /*$ENDIF */
14179 bpr 12005
  }
6785 bpr 12006
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
12007
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
14179 bpr 12008
        (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp))) {
12009
    return false;
12010
    /* p2c: checkmol.pas, line 9559:
12011
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12012
      /*$IFDEF debug */
12013
      /*
12014
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
12015
         {$ENDIF */
14179 bpr 12016
  }
6785 bpr 12017
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
12018
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
14179 bpr 12019
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp))) {
12020
    if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
12021
              atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b)) {
12022
              /* 1st chirality check */
12023
            if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
12024
                                                       ndl_atom[ndl_a -1].stereo_care)) && ndl_maybe_chiral (ndl_a))) {
12025
                                        /* new in v0.3h */
6785 bpr 12026
              return true;
12027
            }                   /* end of 1st chirality check */
14179 bpr 12028
            na1 = ndl_a;                /* the (potential) chiral center (v0.3f) */
12029
            na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
12030
            na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
12031
            na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
12032
            ha1 = hst_a;
12033
            ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
12034
            ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
12035
            ha4 = hst_mp[matchpath_length (hst_mp) - 2];
12036
            memset (ncp, 0, sizeof (chirpath_type));
12037
            memset (hcp, 0, sizeof (chirpath_type));
12038
            ncp[0] = na1;
12039
            ncp[1] = na2;
12040
            ncp[2] = na3;
12041
            ncp[3] = na4;
12042
            hcp[0] = ha1;
12043
            hcp[1] = ha2;
12044
            hcp[2] = ha3;
12045
            hcp[3] = ha4;
12046
            if (!chirality_OK (ncp, hcp)) {
12047
        /* p2c: checkmol.pas, line 9589:
12048
         * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12049
                      /*$IFDEF debug */
12050
                      //debugoutput ("chirality check failed at ring junction");
12051
                      /*$ENDIF */
12052
        return false;
12053
      }
12054
      /* p2c: checkmol.pas, line 9596:
12055
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12056
          /*$IFDEF debug */
12057
          //debugoutput ("chirality check succeeded at ring junction");
12058
          /*$ENDIF */
12059
      return true;
12060
      /* p2c: checkmol.pas, line 9602:
12061
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12062
            /*$IFDEF debug */
12063
            /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
12064
            /*$ENDIF */
12065
          }
12066
    else {
12067
            return false;
12068
      /* p2c: checkmol.pas, line 9609:
12069
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12070
            /*$IFDEF debug */
12071
            /*
12072
               debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
12073
            /*$ENDIF */
12074
          }
12075
  }
6785 bpr 12076
  /* in all other cases, do the hard work: */
12077
  /* first, get all heavy-atom neighbors of needle and haystack; */
12078
  /* at the beginning of the search, this means all neighbors, then it means */
12079
  /* all but the previous atom (where we came from) */
12080
  memset (ndl_nb, 0, sizeof (neighbor_rec));
12081
  memset (hst_nb, 0, sizeof (neighbor_rec));
12082
 
14179 bpr 12083
  if (matchpath_length (ndl_mp) == 1) {
12084
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
12085
    n_nb = atom[hst_a - 1].neighbor_count;
12086
    get_ndl_neighbors (ndl_nb, ndl_a);
12087
    get_neighbors (hst_nb, hst_a);
12088
  }
12089
  else {
12090
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
12091
    n_nb = atom[hst_a - 1].neighbor_count - 1;
12092
    get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
12093
    get_nextneighbors (hst_nb, hst_a, prev_hst_a);
12094
  }
6785 bpr 12095
  /* v0.3o: mark all neighbor atoms as "visited" */
12096
  for (i = 0; i < ndl_n_nb; i++)
12097
    ndl_atom[ndl_nb[i] - 1].tag = false;
12098
  /* now that the neighbor-arrays are filled, get all */
12099
  /* combinations of matches recursively; */
12100
  /* first, initialize the match matrix */
12101
  memset (mm, false, sizeof (matchmatrix));     /* new in v0.2i */
12102
  /* make sure there are not too many neighbors (max. max_neighbors)   */
14179 bpr 12103
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors) {                               /* updated in v0.2i */
12104
    /* p2c: checkmol.pas, line 9644:
12105
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12106
      /*$IFDEF debug */
12107
      //debugoutput ("too many neighbors - exiting");
12108
      /*$ENDIF */
14179 bpr 12109
    return false;
12110
  }
6785 bpr 12111
  /* check if matchpath is not already filled up */
14179 bpr 12112
  if (matchpath_length (ndl_mp) == max_matchpath_length) {
12113
    /* p2c: checkmol.pas, line 9653:
12114
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12115
      /*$IFDEF debug */
12116
      //debugoutput ("matchpath too int - exiting");
12117
      /*$ENDIF */
14179 bpr 12118
    return false;
12119
  }
6785 bpr 12120
  /* next, check which chain of the needle matches which chain of the haystack  */
14179 bpr 12121
  for (i = 0; i < ndl_n_nb; i++) {
12122
    emptyline = true;
12123
    next_ndl_a = ndl_nb[i];
12124
    for (j = 0; j < n_nb; j++) {
12125
            next_hst_a = hst_nb[j];
12126
            ndl_mp[ndl_mp_len] = next_ndl_a;
12127
            hst_mp[hst_mp_len] = next_hst_a;
12128
            if (is_matching (ndl_mp, hst_mp)) {                 /* recursive function call */
6785 bpr 12129
              if (max_match_recursion_depth != 0
14179 bpr 12130
                          && ++recursion_depth > max_match_recursion_depth) {
6785 bpr 12131
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 12132
                      if (opt_verbose)
6785 bpr 12133
#endif
14179 bpr 12134
                        printf
6785 bpr 12135
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
14179 bpr 12136
                      max_match_recursion_depth);
12137
                      //n_rings = max_rings;
12138
                     return true;
12139
                    }
6785 bpr 12140
              mm[i][j] = true;
12141
              emptyline = false;
12142
            }
14179 bpr 12143
          }
12144
    /* if a needle substituent does not match any of the haystack substituents, */
12145
    /* stop any further work immediately */
12146
    if (emptyline)
12147
            return false;
12148
  }
6785 bpr 12149
  /* finally, check the content of the matrix */
12150
  res = matrix_OK (mm, ndl_n_nb, n_nb);
12151
  /* optional: chirality check */
14179 bpr 12152
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) && ndl_maybe_chiral (ndl_a)))
6785 bpr 12153
    return res;
12154
  /* first, we have to clean up the match matrix in order to remove */
12155
  /* "impossible" multiple matches (new in v0.3h) */
14179 bpr 12156
  for (i = 1; i <= 3; i++) {
12157
    for (j = 1; j <= max_neighbors; j++) {                      /* haystack dimension */
12158
            n_hits = 0;
12159
            l = 0;
12160
            for (k = 1; k <= max_neighbors; k++) {                      /* needle dimension */
12161
              if (mm[k - 1][j - 1]) {
12162
                      n_hits++;
12163
                      l = k;
12164
                    }
6785 bpr 12165
            }
14179 bpr 12166
            if (n_hits == 1) {                  /* a unique match ==> kick out any other match at this pos. */
12167
              for (m = 1; m <= max_neighbors; m++) {
12168
                      if (m != j)
12169
                        mm[l - 1][m - 1] = false;
12170
                    }
6785 bpr 12171
            }
14179 bpr 12172
          }
12173
  }
6785 bpr 12174
  /* end of match matrix clean-up */
14179 bpr 12175
  if (prev_ndl_a > 0) {
12176
    n_singlehits = 1;
12177
    ncp[1] = prev_ndl_a;
12178
    hcp[1] = prev_hst_a;
12179
  }
6785 bpr 12180
  else
12181
    n_singlehits = 0;
12182
  ncp[0] = ndl_a;
12183
  hcp[0] = hst_a;
12184
  i = 0;
12185
  l = 0;
14179 bpr 12186
  while (n_singlehits < 3 && i < 4) {
12187
    i++;
12188
    n_hits = 0;
12189
    for (k = 1; k <= n_nb; k++) {
12190
            if (mm[i - 1][k - 1]) {
6785 bpr 12191
              n_hits++;
12192
              l = k;
12193
            }
14179 bpr 12194
          }
12195
    if (n_hits == 1) {
12196
            n_singlehits++;
12197
            ncp[n_singlehits] = ndl_nb[i - 1];
12198
            hcp[n_singlehits] = hst_nb[l - 1];
12199
          }
12200
  }
6785 bpr 12201
  if (n_singlehits != 3)
12202
    return res;
14179 bpr 12203
  if (!chirality_OK (ncp, hcp)) {
12204
    /* p2c: checkmol.pas, line 9749:
12205
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12206
          /*$IFDEF debug */
12207
          //debugoutput ("chirality check failed");
12208
          /*$ENDIF */
12209
          res = false;
12210
  }
12211
  else {
6785 bpr 12212
/* p2c: checkmol.pas, line 9755:
12213
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12214
      /*$IFDEF debug */
12215
      //debugoutput ("chirality check OK");
12216
      /*$ENDIF */
14179 bpr 12217
  }
6785 bpr 12218
  return res;
14179 bpr 12219
  /* p2c: checkmol.pas, line 9762:
12220
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12221
    /*$IFDEF debug */
12222
    /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
12223
       debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
12224
    /*$ENDIF */
6785 bpr 12225
}
12226
 
14179 bpr 12227
static boolean quick_match ()
6785 bpr 12228
{
12229
  /* added in v0.2c */
12230
  int i;
12231
  boolean res = true;
14179 bpr 12232
  /* str3 ndl_atype;*/
6785 bpr 12233
  str2 ndl_el;                  /* v0.3l */
6788 kbelabas 12234
  int ndl_chg = 0;              /* v0.3l */
12235
  int ndl_rad = 0;              /* v0.3x */
12236
  int ndl_iso = 0;              /* v0.3x */
6785 bpr 12237
 
12238
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
12239
    /* v0.3f, v0.3m, v0.3o */
12240
    return false;
12241
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
14179 bpr 12242
        ndl_n_bonds > n_bonds) {                                /* just to be sure... */
12243
    /* p2c: checkmol.pas, line 9786:
12244
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12245
          /*$IFDEF debug */
12246
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
12247
          //debugoutput (" ==> quick_match failed");
12248
          /*$ENDIF */
12249
    return false;
12250
  }
6785 bpr 12251
 
14179 bpr 12252
  if (ndl_n_heavyatoms > 1) {
12253
    for (i = 0; i < ndl_n_atoms; i++) {
12254
            /*if atom^[i].atype <> ndl_atom^[i].atype then res := false;    (* changed in */
12255
            if (strcmp (atom[i].element, ndl_atom[i].element))  /* v0.2k */
12256
              return false;
12257
            //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
12258
            //res = false;
6785 bpr 12259
 
14179 bpr 12260
            if (opt_chg) {
6785 bpr 12261
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
14179 bpr 12262
                      return false;
6785 bpr 12263
            }
14179 bpr 12264
      /*  else {
12265
            if (ndl_atom[i].formal_charge != 0 &&
12266
          atom[i].formal_charge != 0 &&
12267
          ndl_atom[i].formal_charge != atom[i].formal_charge)
12268
        return false;
12269
          } */
6785 bpr 12270
 
14179 bpr 12271
          /* v0.3x: isotopes must be the same */
12272
            if (opt_iso) {
6785 bpr 12273
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
14179 bpr 12274
                      return false;
6785 bpr 12275
            }
14179 bpr 12276
          /*  else {
12277
          if (ndl_atom[i].nucleon_number != 0 &&
12278
          atom[i].nucleon_number != 0 &&
12279
          ndl_atom[i].nucleon_number !=
12280
          atom[i].nucleon_number)
12281
        return false;
12282
        }*/
6785 bpr 12283
 
14179 bpr 12284
            /* v0.3x: radicals must be the same */
12285
            if (opt_rad) {
6785 bpr 12286
              if (ndl_atom[i].radical_type != atom[i].radical_type)
14179 bpr 12287
                      return false;
6785 bpr 12288
            }
14179 bpr 12289
      /*  else {
12290
         if (ndl_atom[i].radical_type != 0 &&
12291
             atom[i].radical_type != 0 &&
12292
             ndl_atom[i].radical_type != atom[i].radical_type)
12293
           return false;
12294
       }*/
6785 bpr 12295
 
12296
        }
14179 bpr 12297
  /* p2c: checkmol.pas, line 9798:
12298
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12299
      /*$IFDEF debug */
12300
      //if (res)
12301
      //debugoutput (" ==> quick_match: atoms OK");
12302
      //else
12303
      //  debugoutput (" ==> quick_match: atoms not OK");
12304
      /*$ENDIF */
14179 bpr 12305
    if (ndl_n_bonds > 0) {
12306
            for (i = 0; i < ndl_n_bonds; i++) {
6785 bpr 12307
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
14179 bpr 12308
                        || ndl_bond[i].btype != bond[i].btype)
12309
                      return false;
6785 bpr 12310
            }
14179 bpr 12311
          }
12312
    /* p2c: checkmol.pas, line 9810:
12313
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12314
         /*$IFDEF debug */
12315
         //if (res)
12316
         //  debugoutput (" ==> quick_match: bonds OK");
12317
         //else
12318
         //  debugoutput (" ==> quick_match: bonds not OK");
12319
         /*$ENDIF */
12320
         /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
12321
   }
12322
  else {
12323
    /* first, find out the element and atom type of the only heavy atom       */
12324
    for (i = 0; i < ndl_n_atoms; i++) {
12325
            if (ndl_atom[i].heavy) {
6785 bpr 12326
              //strcpy (ndl_atype, ndl_atom[i].atype);
12327
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
12328
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
12329
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
12330
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
12331
            }
14179 bpr 12332
          }
12333
    for (i = 0; i < n_atoms; i++) {                     /* v0.3l, v0.3o */
12334
            if (                //      !strcmp (atom[i].atype, ndl_atype) &&
12335
                !strcmp (atom[i].element, ndl_el)) {
12336
              if (opt_chg || opt_strict) {
12337
                      if (ndl_chg != atom[i].formal_charge)
12338
                        return false;
12339
                    }
12340
              if (opt_iso || opt_strict) {
12341
                      if (ndl_iso != atom[i].nucleon_number)
12342
                        return false;
12343
                    }
6785 bpr 12344
 
14179 bpr 12345
              if (opt_rad || opt_strict) {
12346
                      if (ndl_rad != atom[i].radical_type)
12347
                        return false;
12348
                    }
12349
                    return true;
12350
            }
12351
            else {
12352
              res=false;
12353
            }
12354
          }
12355
  }
12356
  /* p2c: checkmol.pas, line 9828:
12357
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12358
  /*$IFDEF debug */
12359
  //if (res)
12360
  //  debugoutput (" ==> quick_match succeeded");
12361
  //else
12362
  //  debugoutput (" ==> quick_match failed (2)");
12363
  /*$ENDIF */
12364
  return res;
12365
}
12366
 
14179 bpr 12367
static void perform_match ()
6785 bpr 12368
{
12369
  int i = 0;
12370
  int j;
12371
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
12372
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
12373
  boolean qm;                   /* v0.3l */
12374
  /* check for NoStruct (0 atoms);  v0.3l */
14179 bpr 12375
  if (n_atoms == 0 || ndl_n_atoms == 0) {
6785 bpr 12376
      matchresult = false;
14179 bpr 12377
  /* p2c: checkmol.pas, line 9849:
12378
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12379
      /*$IFDEF debug */
12380
      //debugoutput ("NoStruct encountered - aborted match routine");
12381
      /*$ENDIF */
14179 bpr 12382
    return;
12383
  }
6785 bpr 12384
  /* if we perform an exact match, needle and haystack must have */
12385
  /* the same number of atoms, bonds, and rings */
14179 bpr 12386
  if (opt_exact && opt_iso)     /* 0.3x */ {
12387
      if (n_heavyatoms != ndl_n_heavyatoms || n_heavybonds != ndl_n_heavybonds) {
12388
              matchresult = false;
12389
      /* p2c: checkmol.pas, line 9861:
12390
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12391
          /*$IFDEF debug */
12392
          //debugoutput ("different number of heavy atoms and/or bonds");
12393
          /*$ENDIF */
12394
          //return;
12395
          }
12396
  }
6785 bpr 12397
 
12398
  /* have a quick look if needle and haystack are identical molfiles */
12399
  qm = quick_match ();          /* v0.3l */
14179 bpr 12400
  if (qm) {
12401
    matchresult = true;
12402
    clear_ndl_atom_tags ();     /* v0.3o */
12403
    return;
12404
  }
6785 bpr 12405
  /* if we have only one heavy atom and quick_match fails, return "false";  v0.3l */
14179 bpr 12406
  if (ndl_n_heavyatoms == 1) {
12407
    matchresult = false;
12408
    return;
12409
  }
12410
  /* p2c: checkmol.pas, line 9881:
12411
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12412
  /*$IFDEF debug */
12413
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
12414
  /*$ENDIF */
12415
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
12416
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
14179 bpr 12417
  /* p2c: checkmol.pas, line 9886:
12418
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12419
  /*$IFDEF debug */
12420
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
12421
  /*$ENDIF */
12422
  matchresult = false;
14179 bpr 12423
  for (j = 0; j < max_matchpath_length; j++) {
12424
    ndl_matchpath[j] = 0;
12425
    hst_matchpath[j] = 0;
12426
  }
6785 bpr 12427
  ndl_matchpath[0] = ndl_ref_atom;
14179 bpr 12428
  while (i < n_atoms && matchresult == false) {
12429
    i++;
12430
    n_nb = atom[i - 1].neighbor_count;
12431
    n_hc = hetatom_count (i);
12432
    if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc) {
12433
      /* p2c: checkmol.pas, line 9904:
12434
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12435
              /*$IFDEF debug */
12436
              /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
12437
              /*$ENDIF */
6785 bpr 12438
 
14179 bpr 12439
            recursion_depth = 0;
12440
            hst_matchpath[0] = i;
12441
            matchresult = is_matching (ndl_matchpath, hst_matchpath);
12442
      /* p2c: checkmol.pas, line 9909:
12443
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12444
          /*$IFDEF debug */
12445
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
12446
          /*$ENDIF */
12447
      if (matchresult)  /* v0.3o; mark this fragment as matched */
12448
        atom[i - 1].tag = true;
12449
          }
12450
  }
6785 bpr 12451
}
12452
 
14179 bpr 12453
static void clear_rings ()
6785 bpr 12454
{
12455
  int i, FORLIM;
12456
  n_rings = 0;
12457
  memset (ring, 0, sizeof (ringlist));
14179 bpr 12458
  for (i = 0; i < max_rings; i++) {                             /* new in v0.3 */
12459
    ringprop[i].size = 0;
12460
    ringprop[i].arom = false;
12461
    ringprop[i].envelope = false;
12462
  }
12463
  if (n_atoms > 0) {
12464
    FORLIM = n_atoms;
12465
    for (i = 0; i < FORLIM; i++)
12466
            atom[i].ring_count = 0;
12467
  }
12468
  if (n_bonds > 0) {
12469
    FORLIM = n_bonds;
12470
    for (i = 0; i < FORLIM; i++)
12471
            bond[i].ring_count = 0;
12472
  }
6785 bpr 12473
}
12474
 
14179 bpr 12475
static int ring_lastpos (s)
6785 bpr 12476
     int *s;
12477
{
12478
  int i, rc;
12479
  int rlp = 0;
12480
  int FORLIM;
12481
  if (n_rings <= 0)
12482
    return rlp;
12483
  FORLIM = n_rings;
14179 bpr 12484
  for (i = 1; i <= FORLIM; i++) {
12485
    rc = ringcompare (s, ring[i - 1]);
12486
    if (rc_identical (rc))
12487
            rlp = i;
12488
  }
6785 bpr 12489
  return rlp;
12490
}
12491
 
14179 bpr 12492
static void remove_redundant_rings ()
6785 bpr 12493
{
12494
  int i, j, k, rlp;
12495
  ringpath_type tmp_path;
12496
  int FORLIM, FORLIM1;
12497
  if (n_rings < 2)
12498
    return;
12499
  FORLIM = n_rings;
14179 bpr 12500
  for (i = 1; i < FORLIM; i++) {
12501
    memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
12502
    rlp = ring_lastpos (tmp_path);
12503
    while (rlp > i) {
12504
           FORLIM1 = n_rings;
12505
      /* p2c: checkmol.pas, line 9970:
12506
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12507
          /*$IFDEF debug */
12508
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
12509
          /*$ENDIF */
14179 bpr 12510
            for (j = rlp; j < FORLIM1; j++) {
6785 bpr 12511
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
12512
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
12513
              ringprop[j - 1].arom = ringprop[j].arom;
12514
              ringprop[j - 1].envelope = ringprop[j].envelope;
12515
            }
14179 bpr 12516
            for (k = 0; k < max_ringsize; k++)
12517
              ring[n_rings - 1][k] = 0;
12518
            n_rings--;
12519
            rlp = ring_lastpos (tmp_path);
12520
          }
12521
  }
6785 bpr 12522
}
12523
 
14179 bpr 12524
static int count_aromatic_rings ()
6785 bpr 12525
{
12526
  int i;
12527
  int n = 0;
12528
  int FORLIM;
12529
  if (n_rings <= 0)
12530
    return n;
12531
  FORLIM = n_rings;
14179 bpr 12532
  for (i = 0; i < FORLIM; i++) {
12533
    if (ringprop[i].arom)
12534
            n++;
12535
  }
6785 bpr 12536
  return n;
12537
}
12538
 
14179 bpr 12539
static void chk_envelopes ()
6785 bpr 12540
{
12541
  /* new in v0.3d */
12542
  /* checks if a ring completely contains one or more other rings */
12543
  int a, i, j, k, l, pl, pli;
12544
  boolean found_atom, found_all_atoms, found_ring;
12545
  int FORLIM;
12546
  if (n_rings < 2)
12547
    return;
12548
  FORLIM = n_rings;
14179 bpr 12549
  for (i = 1; i < FORLIM; i++) {
12550
    found_ring = false;
12551
    j = 0;
12552
    pli = ringprop[i].size;     /* path_length(ring^[i]); */
12553
    while (j < i && found_ring == false) {
12554
            j++;
12555
            found_all_atoms = true;
12556
            pl = ringprop[j - 1].size;  /* path_length(ring^[j]); */
12557
            for (k = 0; k < pl; k++) {
6785 bpr 12558
              found_atom = false;
12559
              a = ring[j - 1][k];
14179 bpr 12560
              for (l = 0; l < pli; l++) {
12561
                      if (ring[i][l] == a)
12562
                        found_atom = true;
12563
                    }
6785 bpr 12564
              if (found_atom == false)
14179 bpr 12565
                      found_all_atoms = false;
6785 bpr 12566
            }
14179 bpr 12567
            if (found_all_atoms)
12568
              found_ring = true;
12569
          }
12570
    if (found_ring)
12571
            ringprop[i].envelope = true;
12572
  }
6785 bpr 12573
}
12574
 
14179 bpr 12575
static void update_ringcount ()
6785 bpr 12576
{
12577
  int i, j, a1, a2, b, pl, FORLIM;
12578
  if (n_rings <= 0)
12579
    return;
12580
  chk_envelopes ();
12581
  FORLIM = n_rings;
14179 bpr 12582
  for (i = 0; i < FORLIM; i++) {
12583
      if (ringprop[i].envelope == false) {
12584
            pl = ringprop[i].size;      /* path_length(ring^[i]);  (* v0.3d */
12585
            a2 = ring[i][pl - 1];
12586
            for (j = 0; j < pl; j++) {
6785 bpr 12587
              a1 = ring[i][j];
12588
              atom[a1 - 1].ring_count++;
12589
              b = get_bond (a1, a2);
12590
              bond[b - 1].ring_count++;
12591
              a2 = a1;
12592
            }
14179 bpr 12593
          }
12594
  }
6785 bpr 12595
}
12596
 
14179 bpr 12597
static boolean normalize_ionic_bonds ()
6785 bpr 12598
{
12599
  /* v0.3k */
12600
  /* changed from a procedure into a function in v0.3m */
12601
  int i, a1, a2, fc1, fc2;
12602
  char bt;
12603
  boolean res = false;          /* v0.3m */
12604
  int FORLIM;
12605
  /* v0.3m */
12606
  if (n_bonds == 0)
12607
    return false;
12608
  FORLIM = n_bonds;
14179 bpr 12609
  for (i = 0; i < FORLIM; i++) {
12610
    a1 = bond[i].a1;
12611
    a2 = bond[i].a2;
12612
    bt = bond[i].btype;
12613
    fc1 = atom[a1 - 1].formal_charge;
12614
    fc2 = atom[a2 - 1].formal_charge;
12615
    if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D')) {
12616
            atom[a1 - 1].formal_charge = 0;
12617
            atom[a2 - 1].formal_charge = 0;
12618
            if (!strcmp (atom[a1 - 1].atype, "N3+"))    /* v0.3m */
12619
              strcpy (atom[a1 - 1].atype, "N3 ");
12620
            if (!strcmp (atom[a2 - 1].atype, "N3+"))    /* v0.3m */
12621
              strcpy (atom[a2 - 1].atype, "N3 ");
12622
            if (bt == 'D')
12623
              bond[i].btype = 'T';
12624
            if (bt == 'S')
12625
              bond[i].btype = 'D';
12626
            res = true;         /* v0.3m */
12627
          }
12628
  }
6785 bpr 12629
  return res;                   /* v0.3m (return true if any change was made */
12630
}
12631
 
12632
#if 0
14179 bpr 12633
static void chk_wildcard_rings ()               // new in v0.3p
6785 bpr 12634
// checks if there are any wildcard atom types or bond types
12635
// in a ring of the needle; if yes ==> set the q_arom flag in the
14179 bpr 12636
// atom and bond record of all ring members in order to perform the
6785 bpr 12637
// match a bit more generously
12638
{
12639
 
12640
  int i, j, rs;
12641
  int a1, a2, b;
12642
  boolean wcr;
12643
  str3 at;
12644
  char bt;
12645
 
12646
  if (ndl_querymol == false)
12647
    return;
12648
  if (ndl_n_rings == 0)
12649
    return;
12650
  // now look for any not-yet-aromatic rings which contain a wildcard
14179 bpr 12651
  for (i = 0; i < ndl_n_rings; i++) {
12652
    wcr = false;
12653
    if (ndl_ringprop[i].arom == false) {
12654
            rs = ndl_ringprop[i].size;
12655
            a2 = ndl_ring[i][rs];
12656
            for (j = 0; j < rs; j++) {
6785 bpr 12657
              a1 = ndl_ring[i][j];
12658
              b = get_ndl_bond (a1, a2);
12659
              strcpy (at, ndl_atom[a1].atype);
12660
              bt = ndl_bond[b].btype;
12661
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
14179 bpr 12662
                      wcr = true;
6785 bpr 12663
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
14179 bpr 12664
                      wcr = true;
6785 bpr 12665
              a2 = a1;
12666
            }
14179 bpr 12667
            if (wcr) {                  // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
6785 bpr 12668
              // {$IFDEF debug}
12669
              // debugoutput('wildcard ring found');
12670
              // {$ENDIF}
12671
              a2 = ndl_ring[i][rs];
14179 bpr 12672
              for (j = 0; j < rs; j++) {
12673
                      a1 = ndl_ring[i][j];
12674
                      b = get_ndl_bond (a1, a2);
12675
                      strcpy (at, ndl_atom[a1].atype);
12676
                      bt = ndl_bond[b].btype;
12677
                      ndl_atom[a1].q_arom = true;
12678
                      ndl_bond[b].q_arom = true;
12679
                      a2 = a1;
12680
                    }
6785 bpr 12681
            }
14179 bpr 12682
          }
12683
  }
6785 bpr 12684
  // and now undo this flagging for all rings which contain no wildcard
14179 bpr 12685
  for (i = 0; i < ndl_n_rings; i++) {
12686
    wcr = false;
12687
    rs = ndl_ringprop[i].size;
12688
    a2 = ndl_ring[i][rs];
12689
    for (j = 0; j < rs; j++) {
12690
            a1 = ndl_ring[i][j];
12691
            b = get_ndl_bond (a1, a2);
12692
            strcpy (at, ndl_atom[a1].atype);
12693
            bt = ndl_bond[b].btype;
12694
            if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
12695
              wcr = true;
12696
            if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
12697
              wcr = true;
12698
            a2 = a1;
12699
          }
12700
    if (!wcr) {                 // if yes, unflag all atoms and bonds in this ring
12701
            a2 = ndl_ring[i][rs];
12702
            for (j = 0; j < rs; j++) {
6785 bpr 12703
              a1 = ndl_ring[i][j];
12704
              b = get_ndl_bond (a1, a2);
12705
              strcpy (at, ndl_atom[a1].atype);
12706
              bt = ndl_bond[b].btype;
12707
              ndl_atom[a1].q_arom = false;
12708
              ndl_bond[b].q_arom = false;
12709
              a2 = a1;
12710
            }
14179 bpr 12711
          }
12712
  }
6785 bpr 12713
  // some further refinement would be necessary here in order to unflag everything
12714
  // which contains a wildcard but which definitely cannot be aromatic
12715
}
12716
#endif
12717
 
12718
#ifndef MAKE_SHARED_LIBRARY
12719
 
14179 bpr 12720
int main (int argc, char *argv[])
6785 bpr 12721
{                               /* main routine */
12722
  char STR1[256], STR6[256];
12723
  int FORLIM;
12724
  /* progmode = pmMatchMol */
12725
  rfile = NULL;
12726
  strcpy (progname, argv[0]);
12727
  strncpy (STR1, progname, 253);
12728
  if (strstr (STR1, "matchmol") != NULL)
12729
    progmode = pmMatchMol;
14179 bpr 12730
  else {
12731
    strncpy (STR6, progname, 253);
12732
    if (strstr (STR6, "checkmol") == NULL) {
12733
            printf ("THOU SHALLST NOT RENAME ME!\n");
12734
            exit (9);
12735
          }
12736
    progmode = pmCheckMol;
12737
  }
12738
  if (argc == 1) {
12739
    show_usage ();
12740
    exit (1);
12741
  }
6785 bpr 12742
  init_globals ();
12743
  init_molstat (&molstat);
12744
  parse_args (argc, argv);
12745
  if (ringsearch_mode == rs_sar)
12746
    max_vringsize = max_ringsize;
12747
  else
12748
    max_vringsize = ssr_vringsize;
12749
  /* v0.3n (was: 10) */
12750
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14179 bpr 12751
  if (progmode == pmMatchMol) {
12752
    left_trim (ndl_molfilename);
12753
    left_trim (molfilename);
12754
    if ((*molfilename == '\0' || *ndl_molfilename == '\0' || argc < 3) && !opt_stdin) {
6785 bpr 12755
            show_usage ();
14179 bpr 12756
            exit (2);           /* new in v0.2k */
12757
          }
12758
    if (!(file_exists (ndl_molfilename)) && !opt_stdin) {
12759
      /*not  fileexists(ndl_molfilename) REPLACE!!! */
12760
                  printf("2");
12761
                  /* p2c: checkmol.pas, line 10128:
12762
                  * Warning: Expected an expression, found a ')' [227] */
12763
            if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
12764
              show_usage ();
12765
            else
12766
              printf ("file %s not found!\n", ndl_molfilename);
12767
            /* new in v0.2k */
12768
            exit (2);
12769
          }
12770
  }
6785 bpr 12771
 
14179 bpr 12772
  if (!(file_exists (molfilename)) && !opt_stdin) {                             /*not  fileexists(ndl_molfilename) REPLACE!!! */
12773
    /* p2c: checkmol.pas, line 10128:
12774
    * Warning: Expected an expression, found a ')' [227] */
6785 bpr 12775
 
14179 bpr 12776
    if (strlen (molfilename) > 1 && molfilename[0] == '-')
12777
            show_usage ();
12778
    else
12779
            printf ("file %s not found!\n", molfilename);
6785 bpr 12780
      /* new in v0.2k */
12781
      exit (2);
14179 bpr 12782
  }
6785 bpr 12783
 
12784
  /* read the first molecule and process it; if we are in "matchmol" mode, */
12785
  /* this is the "needle" */
12786
  if (progmode == pmMatchMol)
12787
    readinputfile (ndl_molfilename);
12788
  else
12789
    readinputfile (molfilename);
12790
  li = 1;                       /* initialize line pointer for input buffer */
12791
  get_filetype (filetype, ndl_molfilename);
14179 bpr 12792
  if (!strcmp (filetype, "unknown")) {
12793
    printf ("unknown query file format!\n");
12794
    if (!opt_verbose)
12795
            exit (3);
12796
    printf ("===========================================\n");
12797
    FORLIM = molbufindex;
12798
    for (i = 1; i <= FORLIM; i++)
12799
            puts (molbuf[i - 1]);
12800
    exit (3);
12801
  }
6785 bpr 12802
  mol_OK = true;                /* added in v0.2i */
12803
  if (!strcmp (filetype, "alchemy"))
12804
    read_molfile (ndl_molfilename);
12805
  if (!strcmp (filetype, "sybyl"))
12806
    read_mol2file (ndl_molfilename);
12807
  if (!strcmp (filetype, "mdl"))
12808
    read_MDLmolfile (ndl_molfilename);
12809
  count_neighbors ();
14179 bpr 12810
  if (!mol_OK || n_atoms < 1) {                                 /* v0.3g; check if this is a valid query structure */
12811
    printf ("invalid molecule\n");
12812
    exit (3);
12813
  }
12814
  if (!found_arominfo || progmode == pmCheckMol) {                              /* added in v0.2b/0.2c */
12815
  /* p2c: checkmol.pas, line 10172:
12816
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12817
      /*$IFDEF debug
6785 bpr 12818
         if (!found_arominfo)
12819
         debugoutput
12820
         ("no aromaticity information found - checking myself...");
12821
         else
12822
         debugoutput ("performing full aromaticity check");
14179 bpr 12823
         // new in v0.3d
6785 bpr 12824
      $ENDIF */
14179 bpr 12825
    chk_ringbonds ();
12826
    if (ringsearch_mode == rs_ssr)
12827
            remove_redundant_rings ();
12828
    if (n_rings >= max_rings) {
12829
            if (opt_verbose)
12830
              printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12831
                 max_rings);
12832
            ringsearch_mode = rs_ssr;
12833
            auto_ssr = true;    /* v0.3n */
12834
            clear_rings ();
12835
            max_vringsize = ssr_vringsize;      /* v0.3n (was: 10) */
12836
            chk_ringbonds ();
12837
            remove_redundant_rings ();
12838
          }
12839
    update_ringcount ();
12840
    /* new in v0.3k: if output is a molfile, leave the original */
12841
    /* representation of N-oxides, S-oxides, nitro groups, etc. */
12842
    /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
12843
    if (!opt_xmdlout)           /* v0.3k */
12844
            normalize_ionic_bonds ();
12845
    update_atypes ();
12846
    update_Htotal ();           /* added in v0.3 */
12847
    chk_arom ();
12848
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
12849
            do {
6785 bpr 12850
              prev_n_ar = count_aromatic_rings ();
12851
              chk_arom ();
12852
              n_ar = count_aromatic_rings ();
12853
            }
14179 bpr 12854
            while (prev_n_ar - n_ar != 0);
12855
          }
12856
  }
12857
  else {                                /* v0.3k */
12858
    /* p2c: checkmol.pas, line 10206:
12859
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12860
      /*$IFDEF debug
6785 bpr 12861
         debugoutput ("found aromaticity information in input file");
12862
         $ENDIF */
14179 bpr 12863
    if (!opt_xmdlout)
12864
            normalize_ionic_bonds ();
12865
    update_atypes ();           /* added in v0.2f */
12866
    update_Htotal ();           /* end v0.2b snippet */
12867
  }
12868
  if (progmode == pmCheckMol) {
12869
    if (opt_verbose)
12870
            write_mol ();
12871
    get_molstat ();
12872
    if (opt_molstat) {
12873
            if (opt_molstat_X)
12874
              write_molstat_X ();
12875
            else
12876
              write_molstat ();
12877
          }
12878
    else {
12879
            if (found_querymol) {
12880
                printf ("input structure contains query atom or query bond!\n");
12881
                exit (1);
6785 bpr 12882
            }
14179 bpr 12883
            chk_functionalgroups ();
12884
            if (opt_none)
12885
              opt_text = true;
12886
            if (opt_text)
12887
              write_fg_text ();
12888
            if (opt_text_de)
12889
              write_fg_text_de ();
12890
            if (opt_code)
12891
              write_fg_code ();
12892
            if (opt_bin)
12893
              write_fg_binary ();
12894
            if (opt_bitstring)
12895
              write_fg_bitstring ();
12896
            if (opt_xmdlout)
12897
              write_MDLmolfile ();
12898
          }
6785 bpr 12899
      /*if opt_verbose   then write_mol; */
14179 bpr 12900
    zap_molecule ();
12901
  }
12902
  else {
6785 bpr 12903
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14179 bpr 12904
    if (!opt_fp) {                      /* v0.3m */
12905
            copy_mol_to_needle ();
12906
            //chk_wildcard_rings (); /* 0.3p */
12907
            set_ndl_atom_tags ();       /* v0.3o */
12908
            if (opt_verbose)
12909
              write_needle_mol ();
12910
            if (rs_strict)      /* v0.3j */
12911
              ndl_ref_atom = find_ndl_ref_atom_cv ();
12912
            else
12913
              ndl_ref_atom = find_ndl_ref_atom ();
12914
          }
12915
    else {
12916
            copy_mol_to_tmp (); /* v0.3m */
12917
            if (opt_verbose)
12918
              printf ("1st molecule stored in buffer: %s\n", tmp_molname);
12919
          }
12920
    /* next, read the "haystack" file and process it */
12921
    li = 1;
12922
    mol_count = 0;
12923
    fpdecimal = 0;              /* v0.3m */
12924
    fpindex = 0;                /* v0.3m */
12925
    do {
12926
            /* new in v0.3i: reset ringsearch_mode to its initial value */
12927
            /* for each new molecule */
12928
            ringsearch_mode = opt_rs;
12929
            if (ringsearch_mode == rs_sar)
12930
              max_vringsize = max_ringsize;
12931
            else
12932
              max_vringsize = ssr_vringsize;
12933
            /* v0.3n (was: 10) */
12934
            readinputfile (molfilename);
12935
            li = 1;
12936
            get_filetype (filetype, molfilename);
12937
            if (strcmp (filetype, "unknown")) {
6785 bpr 12938
              found_arominfo = false;   /* added in v0.2b */
12939
              mol_OK = true;    /* added in v0.2i */
12940
              if (!strcmp (filetype, "alchemy"))
14179 bpr 12941
                      read_molfile (molfilename);
6785 bpr 12942
              if (!strcmp (filetype, "sybyl"))
14179 bpr 12943
                      read_mol2file (molfilename);
6785 bpr 12944
              if (!strcmp (filetype, "mdl"))
14179 bpr 12945
                      read_MDLmolfile (molfilename);
6785 bpr 12946
              mol_count++;
12947
              fpindex++;
12948
              count_neighbors ();
12949
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14179 bpr 12950
              if (!mol_OK || (n_atoms < 1 && !(opt_fp && fpformat == fpf_decimal)))
12951
                      printf ("%i:F\n", mol_count);
12952
              else {
12953
                      if (opt_exact && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
12954
                                || n_Ntot != ndl_n_Ntot)) {             /* new in v0.3g */
12955
                        if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
12956
                                printf ("%i:F\n", mol_count);
12957
                      }
12958
                      else {
12959
                        if (!found_arominfo || (opt_strict && tmfmismatch)) {   /* added in v0.3m */
12960
              /* p2c: checkmol.pas, line 10294:
12961
               * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12962
                                  /*$IFDEF debug
12963
                              debugoutput
12964
                              ("no aromaticity information found (or tweak mismatch) - checking myself...");
12965
                              *$ENDIF */
6785 bpr 12966
                              chk_ringbonds ();
14179 bpr 12967
                              if (ringsearch_mode == rs_ssr)
12968
                                remove_redundant_rings ();
12969
                               if (n_rings == max_rings) {
12970
                                if (opt_verbose)
12971
                                        printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12972
                                         max_rings);
12973
                                ringsearch_mode = rs_ssr;
12974
                                clear_rings ();
12975
                                max_vringsize = ssr_vringsize;  /* v0.3n (was: 10) */
12976
                                chk_ringbonds ();
12977
                                remove_redundant_rings ();
12978
                              }
12979
                              update_ringcount ();
12980
                              update_atypes ();
12981
                              update_Htotal (); /* added in v0.3 */
12982
                              chk_arom ();
12983
                              if (ringsearch_mode == rs_ssr) {  /* new in v0.3 */
12984
                                do {
12985
                                        prev_n_ar = count_aromatic_rings ();
12986
                                        chk_arom ();
12987
                                        n_ar = count_aromatic_rings ();
12988
                                      }
12989
                                while (prev_n_ar - n_ar != 0);
12990
                              }
6785 bpr 12991
                            }
14179 bpr 12992
                      else {    /* added in v0.2f */
12993
            /* p2c: checkmol.pas, line 10322:
12994
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12995
                            /*$IFDEF debug
6785 bpr 12996
                             debugoutput
12997
                             ("found aromaticity information in input file");
12998
                             $ENDIF */
14179 bpr 12999
                              if (opt_strict)
13000
                                update_atypes ();
13001
                              update_Htotal ();
13002
                            }
6785 bpr 13003
                      init_molstat (&ndl_molstat);
13004
                      if (normalize_ionic_bonds ())
14179 bpr 13005
                              /* new in v0.3k, modified in v0.3m */
13006
                              update_atypes ();
6785 bpr 13007
                      if (opt_verbose && !opt_fp)
14179 bpr 13008
                              write_mol ();
6785 bpr 13009
                      /* if in "fingerprint mode", exchange needle and haystack */
14179 bpr 13010
                      if (opt_fp) {     /* v0.3m */
13011
                              zap_needle ();
13012
                              copy_mol_to_needle ();
13013
                              //chk_wildcard_rings (); /* 0.3p */
13014
                              zap_molecule ();
13015
                              copy_tmp_to_mol ();
13016
                              if (opt_verbose)
13017
                                write_needle_mol ();
13018
                              if (rs_strict)    /* v0.3j */
13019
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
13020
                              else
13021
                                ndl_ref_atom = find_ndl_ref_atom ();
13022
                              if (opt_verbose)
13023
                                write_mol ();
13024
                            }   /* v0.3m */
6785 bpr 13025
                      /* now that we have both molecules, perform the comparison */
13026
                      /* v0.3o: takes care of disconnected fragment... */
13027
                      clear_atom_tags ();
13028
                      set_ndl_atom_tags ();
13029
                      matchsummary = true;
13030
                      perform_match ();
13031
                      matchsummary = matchresult;
14179 bpr 13032
                      if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true) {
13033
                              do {
13034
                                if (rs_strict)
13035
                                        ndl_ref_atom = find_ndl_ref_atom_cv ();
13036
                                else
13037
                                        ndl_ref_atom = find_ndl_ref_atom ();
13038
                                perform_match ();
13039
                                if (matchresult == false)
13040
                                        matchsummary = false;
13041
                              }
13042
                              while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
6785 bpr 13043
                            }
13044
                      /* end of disconnected-fragment matching (v0.3o) */
14179 bpr 13045
                      if (matchsummary == true) {       /* v0.3o */
13046
                              if (opt_molout) {
13047
                                FORLIM = molbufindex;
13048
                                for (i = 1; i <= FORLIM; i++)
13049
                                        puts (molbuf[i - 1]);
13050
                              }
13051
                              else {
13052
                                if (!opt_fp)    /* inttostr(mol_count) REPLACE!!!, */
13053
                                        printf ("%i:T\n", mol_count);
13054
                                else {
13055
                                        if (ndl_n_heavyatoms == n_heavyatoms &&
13056
                                            ndl_n_heavybonds == n_heavybonds)
13057
                                          fp_exacthit = true;
13058
                                        else
13059
                                          fp_exacthit = false;
13060
                                        if (fp_exacthit)
13061
                                          fp_exactblock = true;
13062
                                        if (fpformat == fpf_boolean) {
13063
                                          if (fp_exacthit)      /* inttostr(mol_count), REPACE!!! */
13064
                                                  printf ("%i:TX\n", mol_count);
13065
                                          else
13066
                                                  printf ("%i:T\n", mol_count);
13067
                                        }
13068
                                        /* inttostr(mol_count), REPLACE!!! */
13069
                                        if (fpformat == fpf_decimal) {
13070
                                          fpincrement = 1;
13071
                                          FORLIM = fpindex;
13072
                                          for (i = 1; i <= FORLIM; i++)
13073
                                                  fpincrement <<= 1;
13074
                                          fpdecimal += fpincrement;
13075
                                        }
13076
                                      }
13077
                              }
6785 bpr 13078
                            }
14179 bpr 13079
                      else {
13080
                              if (!(opt_molout || (opt_fp && fpformat == fpf_decimal)))
13081
                                /* inttostr(mol_count), REPLACE!!! */
13082
                               printf ("%i:F\n", mol_count);
6785 bpr 13083
                            }
14179 bpr 13084
                      if (opt_fp && fpformat == fpf_decimal && fpindex == fp_blocksize) {
13085
                              if (fp_exactblock)
13086
                                fpdecimal++;
13087
                              printf ("%lld\n", fpdecimal);
13088
                              fpindex = 0;
13089
                              fpdecimal = 0;
13090
                              fp_exactblock = false;
13091
                            }
6785 bpr 13092
                      zap_molecule ();
13093
                      molbufindex = 0;
13094
                    }
14179 bpr 13095
                  }
13096
          }
13097
          else {
13098
            /* v0.3l */
13099
            /* mol_OK */
13100
            printf ("%i:unknown file format\n", mol_count);
13101
          }
6785 bpr 13102
        }
14179 bpr 13103
  while (mol_in_queue != false);
13104
    /* if filetype <> 'unknown' */
13105
    if (opt_fp && fpformat == fpf_decimal && fpindex > 0) {
13106
            if (fp_exactblock)
13107
              fpdecimal++;
13108
            printf ("%lld\n", fpdecimal);
13109
          }
13110
    zap_needle ();
13111
    if (rfile_is_open){                 /* new in v0.2g */
13112
            if (rfile != NULL)
13113
              fclose (rfile);
13114
            rfile = NULL;
13115
          }
13116
  }
6785 bpr 13117
  if (rfile != NULL)
13118
    fclose (rfile);
13119
  exit (0);
13120
}
13121
 
13122
#else
13123
 
14179 bpr 13124
static void init_globals_dll (void)
6785 bpr 13125
{
13126
 
13127
//printf("init_globals_dll\n");
13128
 
13129
  int i;
13130
  opt_verbose = false;
13131
  opt_debug = false;
13132
  opt_stdin = false;
13133
  opt_text = false;
13134
  opt_code = false;
13135
  opt_bin = false;
13136
  opt_bitstring = false;
13137
  opt_molout = false;
13138
  opt_molstat = false;
13139
  opt_molstat_X = false;
13140
  opt_xmdlout = false;
13141
  opt_fp = false;               /* new in v0.3m */
13142
  /*cm_mdlmolfile   := false; */
13143
  found_arominfo = false;
13144
  found_querymol = false;
13145
  ndl_querymol = false;
13146
  opt_rs = rs_sar;              /* v0.3i */
13147
  ringsearch_mode = opt_rs;
13148
  rfile_is_open = false;        /* new in v0.2g */
13149
  ez_flag = false;              /* new in v0.3f */
13150
  chir_flag = false;            /* new in v0.3f */
13151
  n_Ctot = 0;
13152
  n_Otot = 0;
13153
  n_Ntot = 0;                   /* new in v0.3g */
13154
  //for (i = 0; i < max_fg; i++)
13155
  //  fg[i] = false;
13156
  memset (fg, 0, sizeof (fglist));
13157
 
14179 bpr 13158
  if (!yet_initialized) {
13159
    molbuf = (void *) safe_malloc (sizeof (molbuftype));
13160
    opt_exact = false;
13161
    opt_strict = false; /* new in v0.2f */
13162
    opt_metalrings = false;     /* new in v0.3 */
13163
    opt_geom = false;           /* new in v0.3d */
13164
    opt_chiral = false; /* new in v0.3f */
13165
    opt_iso = false;            /* new in v0.3x */
13166
    opt_chg = false;            /* new in v0.3x */
13167
    opt_rad = false;            /* new in v0.3x */
13168
    ez_search = false;  /* new in v0.3d */
13169
    rs_search = false;  /* new in v0.3f */
13170
    rs_strict = false;  /* new in v0.3j */
13171
    ndl_n_Ctot = 0;
13172
    ndl_n_Otot = 0;
13173
    ndl_n_Ntot = 0;             /* new in v0.3g */
13174
    yet_initialized = true;
13175
  }
6785 bpr 13176
 
13177
  ether_generic = false;        /* v0.3j */
13178
  amine_generic = false;        /* v0.3j */
13179
  hydroxy_generic = false;      /* v0.3j */
13180
  fpformat = fpf_decimal;       /* v0.3m */
13181
  fpindex = 0;                  /* v0.3m */
13182
  fp_exacthit = false;          /* v0.3m */
13183
  fp_exactblock = false;        /* v0.3m */
13184
  tmfcode = 0;                  /* v0.3m */
13185
  tmfmismatch = false;          /* v0.3m */
13186
  auto_ssr = false;
13187
  recursion_depth = 0;
13188
}
13189
 
14179 bpr 13190
static void mm_init_mol (void)
6785 bpr 13191
{
13192
//printf("mm_init_mol\n");
13193
  init_globals_dll ();
13194
  init_molstat (&molstat);
14179 bpr 13195
  if (opt_rs_dll == RPA_DEFAULT) {
13196
    ringsearch_mode = opt_rs;
13197
    //printf("DEFAULT: %i\n",ringsearch_mode);
13198
  }
13199
  else {
13200
    ringsearch_mode = opt_rs_dll;
13201
  }
6785 bpr 13202
  //printf("RPA: %i\n",ringsearch_mode);
13203
 
14179 bpr 13204
  if (ringsearch_mode == rs_sar) {
6785 bpr 13205
      max_vringsize = max_ringsize;
14179 bpr 13206
  }
13207
  else {
6785 bpr 13208
      max_vringsize = ssr_vringsize;
14179 bpr 13209
  }
6785 bpr 13210
  zap_molecule ();
13211
  molbufindex = 0;
13212
  mol_count = 0;
13213
//printf("mm_init_mol\n");
13214
}
13215
 
14179 bpr 13216
static void mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
6785 bpr 13217
{
13218
//printf("mm_elab_mol\n");
13219
 
13220
  li = 1;                       // initialize line pointer for input buffer
13221
  get_filetype (filetype, ndl_molfilename);
14179 bpr 13222
  if (strcmp (filetype, "unknown") == 0) {
13223
    //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
13224
    exit (3);
13225
  }
6785 bpr 13226
 
13227
  if (checkmol_mode == true)
13228
    progmode = pmCheckMol;
13229
  else
13230
    progmode = pmMatchMol;
13231
  if (strcmp (filetype, "alchemy") == 0)
13232
    read_molfile (ndl_molfilename);
13233
  if (strcmp (filetype, "sybyl") == 0)
13234
    read_mol2file (ndl_molfilename);
13235
  if (strcmp (filetype, "mdl") == 0)
13236
    read_MDLmolfile (ndl_molfilename);
14179 bpr 13237
  if (checkmol_mode) {
13238
    if (found_querymol) {
13239
            printf ("Warning: Input structure contains query atom or query bond.\n");
13240
          }
13241
  }
6785 bpr 13242
 
13243
  count_neighbors ();
14179 bpr 13244
  if (!found_arominfo || checkmol_mode || opt_strict) {
13245
    //printf("No arom found or checkmol mode\n");
13246
    chk_ringbonds ();
13247
    if (ringsearch_mode == rs_ssr)
13248
            remove_redundant_rings ();
13249
    if (n_rings >= max_rings) {
13250
            printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
13251
               max_rings);
13252
            ringsearch_mode = rs_ssr;
13253
            auto_ssr = true;
13254
            clear_rings ();
13255
            max_vringsize = ssr_vringsize;
13256
            chk_ringbonds ();
13257
            remove_redundant_rings ();
13258
          }
6785 bpr 13259
 
14179 bpr 13260
    update_ringcount ();
13261
    if (normalize_ionic_bnds)   /* v0.3k */
13262
            normalize_ionic_bonds ();
13263
    update_atypes ();
13264
    update_Htotal ();
13265
    chk_arom ();
13266
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
13267
            do {
6785 bpr 13268
              prev_n_ar = count_aromatic_rings ();
13269
              chk_arom ();
13270
              n_ar = count_aromatic_rings ();
13271
            }
14179 bpr 13272
            while (prev_n_ar - n_ar != 0);
13273
          }
13274
  }
13275
  else {
13276
    if (normalize_ionic_bnds)   /* v0.3k  */
13277
            normalize_ionic_bonds ();
13278
    //if (opt_strict)
13279
    update_atypes ();
13280
    update_Htotal ();
13281
  }
13282
  //printf("mm_elab_mol\n");
6785 bpr 13283
}
13284
 
14179 bpr 13285
DLLEXPORT void mm_set_current_mol_as_query (void)
6785 bpr 13286
{
14179 bpr 13287
  //printf("mm_set_current_mol_as_query\n");
6785 bpr 13288
  zap_needle ();
14179 bpr 13289
  //mm_ElabMol;
6785 bpr 13290
  copy_mol_to_needle ();
13291
  //chk_wildcard_rings (); /* 0.3p */
13292
  set_ndl_atom_tags ();         /* v0.3o */
13293
  if (opt_geom)                 /* v0.3d */
13294
    ez_search = true;
13295
  else if (!ez_flag && ez_search)
13296
    ez_search = false;          //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14179 bpr 13297
  if (opt_chiral) {                             /* v0.3f */
6785 bpr 13298
      rs_search = true;
13299
      //printf("%i\n",rs_search);
14179 bpr 13300
  }
13301
  else
13302
    if (!chir_flag && rs_search) {
6785 bpr 13303
      rs_search = false;        //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
13304
      //printf("%i\n",rs_search);
13305
    }
13306
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
13307
    rs_strict = true;
13308
  else
13309
    rs_strict = false;
14179 bpr 13310
    /* if (rs_strict)              // v0.3j
13311
       ndl_ref_atom = find_ndl_ref_atom_cv ();
13312
       //ndl_ref_atom = find_ndl_ref_atom ();
13313
       else
13314
       ndl_ref_atom = find_ndl_ref_atom (); */
6785 bpr 13315
 
13316
  molbufindex = 0;
13317
  mol_count = 0;
14179 bpr 13318
  /*printf("mm_set_current_mol_as_query\n");*/
6785 bpr 13319
}
13320
 
14179 bpr 13321
DLLEXPORT int mm_get_rings (void)
6785 bpr 13322
{
13323
  return n_rings;
13324
}
13325
 
14179 bpr 13326
DLLEXPORT void xm_version (char *buffer)
6785 bpr 13327
{
13328
  buffer[0] = '\0';
13329
  strncpy (buffer, version, 255);
13330
}
13331
 
14179 bpr 13332
DLLEXPORT int mm_get_atom_ring (int atom_number)
6785 bpr 13333
{
13334
 
13335
  int i, j, a1, pl;
13336
  int ret = 0;
13337
  a1 = atom[atom_number].ring_count;
14179 bpr 13338
  if (n_rings > 0) {
13339
    for (i = 1; i < n_rings; i++) {
13340
            pl = path_length (ring[i]);
13341
      //          a2 := ring^[i,pl];
13342
            for (j = 1; j < pl; j++) {
6785 bpr 13343
              a1 = ring[i][j];
13344
              if (atom_number == a1)
14179 bpr 13345
                      ret = i;
13346
          //
13347
          //              inc(atom^[a1].ring_count);
13348
          //              b := get_bond(a1,a2);
13349
          //              inc(bond^[b].ring_count);
13350
          //              a2 := a1;
6785 bpr 13351
            }
14179 bpr 13352
          }
13353
  }
6785 bpr 13354
  return ret;
13355
}
13356
 
14179 bpr 13357
static void mm_read_input_line (char *st)
6785 bpr 13358
{
13359
//printf("mm_read_input_line_in\n");
13360
//var
13361
//yyy:pchar;
13362
 
13363
  mol_in_queue = false;
14179 bpr 13364
  if (molbufindex < (max_atoms + max_bonds + slack)) {
6785 bpr 13365
 
14179 bpr 13366
    //yyy:=Pchar(IntToStr(molbufindex));
13367
    //messagebox (0,yyy,'',0);
13368
    //printf("%i\n",molbufindex);
13369
    //printf("B:%s\n",st);
13370
          strcpy (molbuf[molbufindex++], st);
13371
    //printf("%x %x\n",&molbuf,molbuf);
13372
    //printf("%s\n",molbuf[molbufindex-1]);
13373
          //  molbufindex++;
13374
  }
13375
  else {
13376
    //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
13377
    printf ("Not enough memory for molfile! %i\n", molbufindex);
13378
    exit (1);
13379
  }
6785 bpr 13380
//printf("mm_read_input_line_out\n");
13381
}
13382
 
14179 bpr 13383
static void mm_set_mol_dll (const char *st, boolean checkmol_mode,
6785 bpr 13384
                boolean normalize_ionic_bnds)
13385
{
14179 bpr 13386
  //printf("mm_set_mol\n");
13387
  //printf("%s\n",st);
6785 bpr 13388
  char bb;
13389
  char aa;
13390
  int i;
13391
  int k;
13392
  int J;
13393
  int spt = 0;
13394
  char tt[256];
13395
  char bb10 = '\n';
13396
  char bb13 = '\r';
13397
  char bb0 = '\0';
13398
  int lenst;
14179 bpr 13399
  //char d[256];
6785 bpr 13400
  lenst = strlen (st);
14179 bpr 13401
  //tt=(char*)safe_malloc(256*sizeof(char));
6785 bpr 13402
  tt[0] = '\0';
14179 bpr 13403
  //messagebox(0,st,'',0);
6785 bpr 13404
  mm_init_mol ();
14179 bpr 13405
  for (i = spt; i < lenst; i++) {
13406
    bb = st[i];
13407
    if ((bb == bb10) || (i == lenst)) {
13408
            J = 0;
13409
            // d:='';
13410
            for (k = spt; k < i; k++) {
6785 bpr 13411
              aa = st[k];
14179 bpr 13412
              if ((aa != bb10) && (aa != bb13)) {
13413
                      //d:=d+aa;
13414
                      tt[J] = aa;
13415
                      J++;
13416
                    }
6785 bpr 13417
            }
14179 bpr 13418
            tt[J] = bb0;
13419
            spt = i;
13420
            //messagebox (0,tt,tt,0);
13421
      //printf("A:%s\n",tt);
13422
            mm_read_input_line (tt);
13423
          }
13424
  }
6785 bpr 13425
//free(tt);
13426
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
13427
//printf("mm_set_mol\n");
13428
}
13429
 
14179 bpr 13430
DLLEXPORT void cm_set_mol (const char *st, int normalize_ionic_bnds)
6785 bpr 13431
{
13432
  mm_set_mol_dll (st, true, (normalize_ionic_bnds != FEATURE_OFF));
13433
}
13434
 
14179 bpr 13435
DLLEXPORT void mm_set_mol (const char *st)
6785 bpr 13436
{
13437
  mm_set_mol_dll (st, false, true);
13438
}
13439
 
14179 bpr 13440
DLLEXPORT void xm_set_strict_typing (int strict_typing)
6785 bpr 13441
{
13442
  if (!yet_initialized)
13443
    init_globals_dll ();
13444
  opt_strict = (strict_typing != FEATURE_OFF);
13445
  //opt_strict=false; //This never worked right and is harmful
13446
}
13447
 
14179 bpr 13448
DLLEXPORT void mm_set_r_s_check (int r_s_check)
6785 bpr 13449
{
13450
  if (!yet_initialized)
13451
    init_globals_dll ();
13452
  opt_chiral = (r_s_check != FEATURE_OFF);
13453
}
13454
 
14179 bpr 13455
DLLEXPORT void mm_set_e_z_check (int e_z_check)
6785 bpr 13456
{
13457
  if (!yet_initialized)
13458
    init_globals_dll ();
13459
  opt_geom = (e_z_check != FEATURE_OFF);
13460
}
13461
 
14179 bpr 13462
DLLEXPORT void mm_set_chg_check (int chg_check)
6785 bpr 13463
{
13464
  if (!yet_initialized)
13465
    init_globals_dll ();
13466
  opt_chg = (chg_check != FEATURE_OFF);
13467
}
13468
 
14179 bpr 13469
DLLEXPORT void mm_set_iso_check (int iso_check)
6785 bpr 13470
{
13471
  if (!yet_initialized)
13472
    init_globals_dll ();
13473
  opt_iso = (iso_check != FEATURE_OFF);
13474
}
13475
 
14179 bpr 13476
DLLEXPORT void mm_set_rad_check (int rad_check)
6785 bpr 13477
{
13478
  if (!yet_initialized)
13479
    init_globals_dll ();
13480
  opt_rad = (rad_check != FEATURE_OFF);
13481
}
13482
 
14179 bpr 13483
DLLEXPORT void mm_set_exact_match (int exact)
6785 bpr 13484
{
13485
  if (!yet_initialized)
13486
    init_globals_dll ();
13487
  opt_exact = (exact != FEATURE_OFF);
13488
}
13489
 
14179 bpr 13490
DLLEXPORT int mm_match ()
6785 bpr 13491
{
13492
  mol_count = 1;
14179 bpr 13493
  //     mm_ElabMol;
13494
  /*printf("%i\n",opt_exact);
13495
  printf("%i\n",n_Ctot);
13496
  printf("%i\n",ndl_n_Ctot);
13497
  printf("%i\n",n_Otot);
13498
  printf("%i\n",ndl_n_Otot);
13499
  printf("%i\n",n_Ntot);
13500
  printf("%i\n",ndl_n_Ntot);*/
6785 bpr 13501
  if (opt_exact
13502
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14179 bpr 13503
            || n_Ntot != ndl_n_Ntot))
6785 bpr 13504
    return 0;
13505
  init_molstat (&ndl_molstat);
13506
  //perform_match ();
13507
  //---------------------------------------------------- 0.3o
13508
  if (rs_strict)                /* v0.3j */
13509
    ndl_ref_atom = find_ndl_ref_atom_cv ();
13510
  //ndl_ref_atom = find_ndl_ref_atom ();
13511
  else
13512
    ndl_ref_atom = find_ndl_ref_atom ();
13513
  clear_atom_tags ();
13514
  set_ndl_atom_tags ();
13515
  matchsummary = true;
13516
  perform_match ();
13517
  matchsummary = matchresult;
14179 bpr 13518
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true) {
13519
    do {
13520
            if (rs_strict)
13521
              ndl_ref_atom = find_ndl_ref_atom_cv ();
13522
            else
13523
              ndl_ref_atom = find_ndl_ref_atom ();
13524
            perform_match ();
13525
            if (matchresult == false)
13526
             matchsummary = false;
13527
          }
13528
    while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
13529
  }
6785 bpr 13530
 
13531
  //-----------------------------------------------------
13532
 
13533
  //mol_count = 0;
13534
 
13535
  //molbufindex = 0;
13536
 
13537
  //return matchresult ? 1 : 0;
13538
 
13539
  return matchsummary ? 1 : 0;
13540
}
13541
 
13542
//-------------------------
13543
 
14179 bpr 13544
DLLEXPORT void xm_set_ring_perception_algorithm (int algo)
6785 bpr 13545
{
14179 bpr 13546
  switch (algo) {
6785 bpr 13547
    case RPA_SAR:
13548
      opt_rs_dll = rs_sar;
13549
      break;
13550
    case RPA_SSR:
13551
      opt_rs_dll = rs_ssr;
13552
      break;
13553
    default:
13554
      opt_rs_dll = RPA_DEFAULT;
13555
      break;
13556
    }
13557
  //printf("RPA_SET: %i\n",opt_rs_dll);
13558
}
13559
 
14179 bpr 13560
static void write_molstat_X_dll (char *out_buffer)
6785 bpr 13561
{
13562
  char tmp_buf[256];
13563
  out_buffer[0] = '\0';
13564
  if (auto_ssr)                 /* v0.3n */
13565
    fix_ssr_ringcounts ();
13566
  sprintf (tmp_buf, "%d,", n_heavyatoms);
13567
  strcat (out_buffer, tmp_buf);
13568
  sprintf (tmp_buf, "%d,", n_heavybonds);
13569
  strcat (out_buffer, tmp_buf);
13570
#ifdef REDUCED_SAR
13571
  sprintf (tmp_buf, "%d,", n_countablerings);
13572
  strcat (out_buffer, tmp_buf);
13573
#else
13574
  sprintf (tmp_buf, "%d,", n_rings);
13575
  strcat (out_buffer, tmp_buf);
13576
#endif
13577
  sprintf (tmp_buf, "%d,", molstat.n_QA);
13578
  strcat (out_buffer, tmp_buf);
13579
  sprintf (tmp_buf, "%d,", molstat.n_QB);
13580
  strcat (out_buffer, tmp_buf);
13581
  //if (opt_chg)
13582
//    {                         /* 0.3x */
13583
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
13584
//    }
13585
//  else
13586
//    {
13587
  sprintf (tmp_buf, "%d,", molstat.n_chg);
13588
  //   }
13589
  strcat (out_buffer, tmp_buf);
13590
  sprintf (tmp_buf, "%d,", molstat.n_C1);
13591
  strcat (out_buffer, tmp_buf);
13592
  sprintf (tmp_buf, "%d,", molstat.n_C2);
13593
  strcat (out_buffer, tmp_buf);
13594
  sprintf (tmp_buf, "%d,", molstat.n_C);
13595
  strcat (out_buffer, tmp_buf);
13596
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
13597
  strcat (out_buffer, tmp_buf);
13598
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
13599
  strcat (out_buffer, tmp_buf);
13600
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
13601
  strcat (out_buffer, tmp_buf);
13602
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
13603
  strcat (out_buffer, tmp_buf);
13604
  sprintf (tmp_buf, "%d,", molstat.n_O2);
13605
  strcat (out_buffer, tmp_buf);
13606
  sprintf (tmp_buf, "%d,", molstat.n_O3);
13607
  strcat (out_buffer, tmp_buf);
13608
  sprintf (tmp_buf, "%d,", molstat.n_N1);
13609
  strcat (out_buffer, tmp_buf);
13610
  sprintf (tmp_buf, "%d,", molstat.n_N2);
13611
  strcat (out_buffer, tmp_buf);
13612
  sprintf (tmp_buf, "%d,", molstat.n_N3);
13613
  strcat (out_buffer, tmp_buf);
13614
  sprintf (tmp_buf, "%d,", molstat.n_S);
13615
  strcat (out_buffer, tmp_buf);
13616
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
13617
  strcat (out_buffer, tmp_buf);
13618
  sprintf (tmp_buf, "%d,", molstat.n_F);
13619
  strcat (out_buffer, tmp_buf);
13620
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
13621
  strcat (out_buffer, tmp_buf);
13622
  sprintf (tmp_buf, "%d,", molstat.n_Br);
13623
  strcat (out_buffer, tmp_buf);
13624
  sprintf (tmp_buf, "%d,", molstat.n_I);
13625
  strcat (out_buffer, tmp_buf);
13626
  sprintf (tmp_buf, "%d,", molstat.n_P);
13627
  strcat (out_buffer, tmp_buf);
13628
  sprintf (tmp_buf, "%d,", molstat.n_B);
13629
  strcat (out_buffer, tmp_buf);
13630
  sprintf (tmp_buf, "%d,", molstat.n_Met);
13631
  strcat (out_buffer, tmp_buf);
13632
  sprintf (tmp_buf, "%d,", molstat.n_X);
13633
  strcat (out_buffer, tmp_buf);
13634
  sprintf (tmp_buf, "%d,", molstat.n_b1);
13635
  strcat (out_buffer, tmp_buf);
13636
  sprintf (tmp_buf, "%d,", molstat.n_b2);
13637
  strcat (out_buffer, tmp_buf);
13638
  sprintf (tmp_buf, "%d,", molstat.n_b3);
13639
  strcat (out_buffer, tmp_buf);
13640
  sprintf (tmp_buf, "%d,", molstat.n_bar);
13641
  strcat (out_buffer, tmp_buf);
13642
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
13643
  strcat (out_buffer, tmp_buf);
13644
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
13645
  strcat (out_buffer, tmp_buf);
13646
  sprintf (tmp_buf, "%d,", molstat.n_CN);
13647
  strcat (out_buffer, tmp_buf);
13648
  sprintf (tmp_buf, "%d,", molstat.n_XY);
13649
  strcat (out_buffer, tmp_buf);
13650
  sprintf (tmp_buf, "%d,", molstat.n_r3);
13651
  strcat (out_buffer, tmp_buf);
13652
  sprintf (tmp_buf, "%d,", molstat.n_r4);
13653
  strcat (out_buffer, tmp_buf);
13654
  sprintf (tmp_buf, "%d,", molstat.n_r5);
13655
  strcat (out_buffer, tmp_buf);
13656
  sprintf (tmp_buf, "%d,", molstat.n_r6);
13657
  strcat (out_buffer, tmp_buf);
13658
  sprintf (tmp_buf, "%d,", molstat.n_r7);
13659
  strcat (out_buffer, tmp_buf);
13660
  sprintf (tmp_buf, "%d,", molstat.n_r8);
13661
  strcat (out_buffer, tmp_buf);
13662
  sprintf (tmp_buf, "%d,", molstat.n_r9);
13663
  strcat (out_buffer, tmp_buf);
13664
  sprintf (tmp_buf, "%d,", molstat.n_r10);
13665
  strcat (out_buffer, tmp_buf);
13666
  sprintf (tmp_buf, "%d,", molstat.n_r11);
13667
  strcat (out_buffer, tmp_buf);
13668
  sprintf (tmp_buf, "%d,", molstat.n_r12);
13669
  strcat (out_buffer, tmp_buf);
13670
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
13671
  strcat (out_buffer, tmp_buf);
13672
  sprintf (tmp_buf, "%d,", molstat.n_rN);
13673
  strcat (out_buffer, tmp_buf);
13674
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
13675
  strcat (out_buffer, tmp_buf);
13676
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
13677
  strcat (out_buffer, tmp_buf);
13678
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
13679
  strcat (out_buffer, tmp_buf);
13680
  sprintf (tmp_buf, "%d,", molstat.n_rO);
13681
  strcat (out_buffer, tmp_buf);
13682
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
13683
  strcat (out_buffer, tmp_buf);
13684
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
13685
  strcat (out_buffer, tmp_buf);
13686
  sprintf (tmp_buf, "%d,", molstat.n_rS);
13687
  strcat (out_buffer, tmp_buf);
13688
  sprintf (tmp_buf, "%d,", molstat.n_rX);
13689
  strcat (out_buffer, tmp_buf);
13690
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
13691
  strcat (out_buffer, tmp_buf);
13692
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
13693
  strcat (out_buffer, tmp_buf);
13694
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
13695
  strcat (out_buffer, tmp_buf);
13696
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
13697
  strcat (out_buffer, tmp_buf);
13698
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
13699
  strcat (out_buffer, tmp_buf);
13700
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
13701
  strcat (out_buffer, tmp_buf);
13702
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
13703
  strcat (out_buffer, tmp_buf);
13704
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
13705
  strcat (out_buffer, tmp_buf);
13706
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
13707
  strcat (out_buffer, tmp_buf);
13708
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
13709
  strcat (out_buffer, tmp_buf);
13710
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
13711
  strcat (out_buffer, tmp_buf);
13712
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
13713
  strcat (out_buffer, tmp_buf);
13714
  sprintf (tmp_buf, "%d,", molstat.n_psla);
13715
  strcat (out_buffer, tmp_buf);
13716
  sprintf (tmp_buf, "%d,", molstat.n_iso);
13717
  strcat (out_buffer, tmp_buf);
13718
  sprintf (tmp_buf, "%d", molstat.n_rad);
13719
  strcat (out_buffer, tmp_buf);
13720
}
13721
 
14179 bpr 13722
static void write_molstat_dll (char *out_buffer, int mode) {
6785 bpr 13723
  char tmp_buf[256];
13724
  char *sep1;
13725
  char *sep2;
14179 bpr 13726
  switch (mode) {
6785 bpr 13727
    case 1:
13728
      sep1 = "=";
13729
      sep2 = " AND ";
13730
      break;
13731
    case 2:
13732
      sep1 = "<=";
13733
      sep2 = " AND ";
13734
      break;
13735
    default:
13736
      sep1 = ":";
13737
      sep2 = ";";
13738
      break;
13739
    }
13740
 
13741
  out_buffer[0] = '\0';
13742
 
13743
  if (auto_ssr)                 /* v0.3n */
13744
    fix_ssr_ringcounts ();
13745
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
13746
  strcat (out_buffer, tmp_buf);
14179 bpr 13747
  if (n_bonds > 0) {
6785 bpr 13748
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
13749
      strcat (out_buffer, tmp_buf);
13750
    }
13751
 
13752
#ifdef REDUCED_SAR
14179 bpr 13753
  if (n_rings > 0) {
6785 bpr 13754
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
13755
      strcat (out_buffer, tmp_buf);
13756
    }
13757
#else
14179 bpr 13758
  if (n_rings > 0) {
6785 bpr 13759
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
13760
      strcat (out_buffer, tmp_buf);
13761
    }
13762
#endif
13763
 
14179 bpr 13764
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */ {
13765
    sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
13766
    strcat (out_buffer, tmp_buf);
13767
  }
13768
  if (molstat.n_C1 > 0) {
13769
    sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
13770
    strcat (out_buffer, tmp_buf);
13771
  }
13772
  if (molstat.n_C2 > 0) {
13773
    sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
13774
    strcat (out_buffer, tmp_buf);
13775
  }
6785 bpr 13776
 
14179 bpr 13777
  if (molstat.n_C > 0) {
13778
    sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
13779
    strcat (out_buffer, tmp_buf);
13780
  }
13781
  if (molstat.n_CHB1p > 0) {
13782
    sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
13783
    strcat (out_buffer, tmp_buf);
13784
  }
13785
  if (molstat.n_CHB2p > 0) {
13786
    sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
13787
    strcat (out_buffer, tmp_buf);
13788
  }
13789
  if (molstat.n_CHB3p > 0) {
13790
    sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
13791
    strcat (out_buffer, tmp_buf);
13792
  }
13793
  if (molstat.n_CHB4 > 0) {
13794
    sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
13795
    strcat (out_buffer, tmp_buf);
13796
  }
13797
  if (molstat.n_O2 > 0) {
13798
    sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
13799
    strcat (out_buffer, tmp_buf);
13800
  }
13801
  if (molstat.n_O3 > 0) {
13802
    sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
13803
    strcat (out_buffer, tmp_buf);
13804
  }
13805
  if (molstat.n_N1 > 0) {
13806
    sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
13807
    strcat (out_buffer, tmp_buf);
13808
  }
13809
  if (molstat.n_N2 > 0) {
13810
    sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
13811
    strcat (out_buffer, tmp_buf);
13812
  }
13813
  if (molstat.n_N3 > 0) {
13814
    sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
13815
    strcat (out_buffer, tmp_buf);
13816
  }
13817
  if (molstat.n_S > 0) {
13818
    sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
13819
    strcat (out_buffer, tmp_buf);
13820
  }
13821
  if (molstat.n_SeTe > 0) {
13822
    sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
13823
    strcat (out_buffer, tmp_buf);
13824
  }
13825
  if (molstat.n_F > 0) {
13826
    sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
13827
    strcat (out_buffer, tmp_buf);
13828
  }
13829
  if (molstat.n_Cl > 0) {
13830
    sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
13831
    strcat (out_buffer, tmp_buf);
13832
  }
13833
  if (molstat.n_Br > 0) {
13834
    sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
13835
    strcat (out_buffer, tmp_buf);
13836
  }
13837
  if (molstat.n_I > 0) {
13838
    sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
13839
    strcat (out_buffer, tmp_buf);
13840
  }
13841
  if (molstat.n_P > 0) {
13842
    sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
13843
    strcat (out_buffer, tmp_buf);
13844
  }
13845
  if (molstat.n_B > 0) {
13846
    sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
13847
    strcat (out_buffer, tmp_buf);
13848
  }
13849
  if (molstat.n_Met > 0) {
13850
    sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
13851
    strcat (out_buffer, tmp_buf);
13852
  }
13853
  if (molstat.n_X > 0) {
13854
    sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
13855
    strcat (out_buffer, tmp_buf);
13856
  }
13857
  if (molstat.n_b1 > 0) {
13858
    sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
13859
    strcat (out_buffer, tmp_buf);
13860
  }
13861
  if (molstat.n_b2 > 0) {
13862
    sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
13863
    strcat (out_buffer, tmp_buf);
13864
  }
13865
  if (molstat.n_b3 > 0) {
13866
    sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
13867
    strcat (out_buffer, tmp_buf);
13868
  }
13869
  if (molstat.n_bar > 0) {
13870
   sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
13871
   strcat (out_buffer, tmp_buf);
13872
  }
13873
  if (molstat.n_C1O > 0) {
13874
    sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
13875
    strcat (out_buffer, tmp_buf);
13876
  }
13877
  if (molstat.n_C2O > 0) {
6785 bpr 13878
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
13879
      strcat (out_buffer, tmp_buf);
13880
    }
14179 bpr 13881
  if (molstat.n_CN > 0) {
6785 bpr 13882
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
13883
      strcat (out_buffer, tmp_buf);
13884
    }
14179 bpr 13885
  if (molstat.n_XY > 0) {
13886
    sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
13887
    strcat (out_buffer, tmp_buf);
13888
  }
13889
  if (molstat.n_r3 > 0) {
13890
    sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
13891
    strcat (out_buffer, tmp_buf);
13892
  }
13893
  if (molstat.n_r4 > 0) {
13894
    sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
13895
    strcat (out_buffer, tmp_buf);
13896
  }
13897
  if (molstat.n_r5 > 0) {
13898
    sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
13899
    strcat (out_buffer, tmp_buf);
13900
  }
13901
  if (molstat.n_r6 > 0) {
13902
    sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
13903
    strcat (out_buffer, tmp_buf);
13904
  }
13905
  if (molstat.n_r7 > 0) {
13906
    sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
13907
    strcat (out_buffer, tmp_buf);
13908
  }
13909
  if (molstat.n_r8 > 0) {
13910
    sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
13911
    strcat (out_buffer, tmp_buf);
13912
  }
13913
  if (molstat.n_r9 > 0) {
13914
    sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
13915
    strcat (out_buffer, tmp_buf);
13916
  }
13917
  if (molstat.n_r10 > 0) {
13918
    sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
13919
    strcat (out_buffer, tmp_buf);
13920
  }
13921
  if (molstat.n_r11 > 0) {
13922
    sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
13923
    strcat (out_buffer, tmp_buf);
13924
  }
13925
  if (molstat.n_r12 > 0) {
13926
    sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
13927
    strcat (out_buffer, tmp_buf);
13928
  }
13929
  if (molstat.n_r13p > 0) {
6785 bpr 13930
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
13931
      strcat (out_buffer, tmp_buf);
13932
    }
14179 bpr 13933
  if (molstat.n_rN > 0) {
13934
    sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
13935
    strcat (out_buffer, tmp_buf);
13936
  }
13937
  if (molstat.n_rN1 > 0) {
13938
    sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
13939
    strcat (out_buffer, tmp_buf);
13940
  }
13941
  if (molstat.n_rN2 > 0) {
13942
    sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
13943
    strcat (out_buffer, tmp_buf);
13944
  }
13945
  if (molstat.n_rN3p > 0) {
13946
    sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
13947
    strcat (out_buffer, tmp_buf);
13948
  }
13949
  if (molstat.n_rO > 0) {
13950
    sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
13951
    strcat (out_buffer, tmp_buf);
13952
  }
13953
  if (molstat.n_rO1 > 0) {
13954
    sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
13955
    strcat (out_buffer, tmp_buf);
13956
  }
13957
  if (molstat.n_rO2p > 0) {
13958
    sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
13959
    strcat (out_buffer, tmp_buf);
13960
  }
13961
  if (molstat.n_rS > 0) {
13962
    sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
13963
    strcat (out_buffer, tmp_buf);
13964
  }
13965
  if (molstat.n_rX > 0) {
13966
    sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
13967
    strcat (out_buffer, tmp_buf);
13968
  }
13969
  if (molstat.n_rAr > 0) {
13970
    sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
13971
    strcat (out_buffer, tmp_buf);
13972
  }
6785 bpr 13973
 
14179 bpr 13974
  if (molstat.n_rBz > 0) {
13975
    sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
13976
    strcat (out_buffer, tmp_buf);
13977
  }
6785 bpr 13978
 
14179 bpr 13979
  if (molstat.n_br2p > 0) {
13980
    sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
13981
    strcat (out_buffer, tmp_buf);
13982
  }
6785 bpr 13983
 
14179 bpr 13984
  if (molstat.n_psg01 > 0) {
13985
    sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
13986
    strcat (out_buffer, tmp_buf);
13987
  }
6785 bpr 13988
 
14179 bpr 13989
  if (molstat.n_psg02 > 0) {
13990
    sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
13991
    strcat (out_buffer, tmp_buf);
13992
  }
6785 bpr 13993
 
14179 bpr 13994
  if (molstat.n_psg13 > 0) {
13995
    sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
13996
    strcat (out_buffer, tmp_buf);
13997
  }
6785 bpr 13998
 
14179 bpr 13999
  if (molstat.n_psg14 > 0) {
14000
    sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
14001
    strcat (out_buffer, tmp_buf);
14002
  }
6785 bpr 14003
 
14179 bpr 14004
  if (molstat.n_psg15 > 0) {
14005
    sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
14006
    strcat (out_buffer, tmp_buf);
14007
  }
6785 bpr 14008
 
14179 bpr 14009
  if (molstat.n_psg16 > 0) {
14010
    sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
14011
    strcat (out_buffer, tmp_buf);
14012
  }
6785 bpr 14013
 
14179 bpr 14014
  if (molstat.n_psg17 > 0) {
14015
    sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
14016
    strcat (out_buffer, tmp_buf);
14017
  }
6785 bpr 14018
 
14179 bpr 14019
  if (molstat.n_psg18 > 0) {
14020
    sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
14021
    strcat (out_buffer, tmp_buf);
14022
  }
6785 bpr 14023
 
14179 bpr 14024
  if (molstat.n_pstm > 0) {
6785 bpr 14025
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
14026
      strcat (out_buffer, tmp_buf);
14027
    }
14028
 
14179 bpr 14029
  if (molstat.n_psla > 0) {
6785 bpr 14030
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
14031
      strcat (out_buffer, tmp_buf);
14032
    }
14033
 
14179 bpr 14034
  if (opt_iso && molstat.n_iso > 0) {
14035
    sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
14036
    strcat (out_buffer, tmp_buf);
14037
  }
6785 bpr 14038
 
14179 bpr 14039
  if (opt_rad && molstat.n_rad > 0) {
14040
    sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
14041
    strcat (out_buffer, tmp_buf);
14042
  }
6785 bpr 14043
}
14044
 
14045
static void
14046
write_fg_code_dll (char *out_buffer)
14047
{
14048
  char tmp_buf[256];
14049
  out_buffer[0] = '\0';
14179 bpr 14050
  if (fg[fg_cation - 1]) {
14051
    sprintf (tmp_buf, "000000T2;");
14052
    strcat (out_buffer, tmp_buf);
14053
  }
14054
  if (fg[fg_anion - 1]) {
14055
    sprintf (tmp_buf, "000000T1;");
14056
    strcat (out_buffer, tmp_buf);
14057
  }
6785 bpr 14058
 
14179 bpr 14059
  if (fg[fg_aldehyde - 1]) {
14060
    sprintf (tmp_buf, "C2O1H000;");
14061
    strcat (out_buffer, tmp_buf);
14062
  }
14063
  if (fg[fg_ketone - 1]) {
14064
    sprintf (tmp_buf, "C2O1C000;");
14065
    strcat (out_buffer, tmp_buf);
14066
  }
6785 bpr 14067
 
14179 bpr 14068
  if (fg[fg_thioaldehyde - 1]) {
14069
    sprintf (tmp_buf, "C2S1H000;");
14070
    strcat (out_buffer, tmp_buf);
14071
  }
14072
  if (fg[fg_thioketone - 1]) {
14073
    sprintf (tmp_buf, "C2S1C000;");
14074
    strcat (out_buffer, tmp_buf);
14075
  }
14076
  if (fg[fg_imine - 1]) {
14077
    sprintf (tmp_buf, "C2N10000;");
14078
    strcat (out_buffer, tmp_buf);
14079
  }
14080
  if (fg[fg_hydrazone - 1]) {
14081
    sprintf (tmp_buf, "C2N1N000;");
14082
    strcat (out_buffer, tmp_buf);
14083
  }
14084
  if (fg[fg_semicarbazone - 1]) {
14085
    sprintf (tmp_buf, "C2NNC4ON;");
14086
    strcat (out_buffer, tmp_buf);
14087
  }
14088
  if (fg[fg_thiosemicarbazone - 1]) {
14089
    sprintf (tmp_buf, "C2NNC4SN;");
14090
    strcat (out_buffer, tmp_buf);
14091
  }
14092
  if (fg[fg_oxime - 1]) {
14093
    sprintf (tmp_buf, "C2N1OH00;");
14094
    strcat (out_buffer, tmp_buf);
14095
  }
14096
  if (fg[fg_oxime_ether - 1]) {
14097
    sprintf (tmp_buf, "C2N1OC00;");
14098
    strcat (out_buffer, tmp_buf);
14099
  }
14100
  if (fg[fg_ketene - 1]) {
14101
    sprintf (tmp_buf, "C3OC0000;");
14102
    strcat (out_buffer, tmp_buf);
14103
  }
14104
  if (fg[fg_ketene_acetal_deriv - 1]) {
14105
    sprintf (tmp_buf, "C3OCC000;");
14106
    strcat (out_buffer, tmp_buf);
14107
  }
14108
  if (fg[fg_carbonyl_hydrate - 1]) {
14109
    sprintf (tmp_buf, "C2O2H200;");
14110
    strcat (out_buffer, tmp_buf);
14111
  }
14112
  if (fg[fg_hemiacetal - 1]) {
14113
    sprintf (tmp_buf, "C2O2HC00;");
14114
    strcat (out_buffer, tmp_buf);
14115
  }
14116
  if (fg[fg_acetal - 1]) {
14117
   sprintf (tmp_buf, "C2O2CC00;");
14118
   strcat (out_buffer, tmp_buf);
14119
  }
14120
  if (fg[fg_hemiaminal - 1]) {
14121
    sprintf (tmp_buf, "C2NOHC10;");
14122
    strcat (out_buffer, tmp_buf);
14123
  }
14124
  if (fg[fg_aminal - 1]) {
14125
    sprintf (tmp_buf, "C2N2CC10;");
14126
    strcat (out_buffer, tmp_buf);
14127
  }
14128
  if (fg[fg_thiohemiaminal - 1]) {
14129
    sprintf (tmp_buf, "C2NSHC10;");
14130
    strcat (out_buffer, tmp_buf);
14131
  }
14132
  if (fg[fg_thioacetal - 1]) {
14133
    sprintf (tmp_buf, "C2S2CC00;");
14134
    strcat (out_buffer, tmp_buf);
14135
  }
14136
  if (fg[fg_enamine - 1]) {
14137
    sprintf (tmp_buf, "C2CNH000;");
14138
    strcat (out_buffer, tmp_buf);
14139
  }
14140
  if (fg[fg_enol - 1]) {
14141
    sprintf (tmp_buf, "C2COH000;");
14142
    strcat (out_buffer, tmp_buf);
14143
  }
14144
  if (fg[fg_enolether - 1]) {
14145
    sprintf (tmp_buf, "C2COC000;");
14146
    strcat (out_buffer, tmp_buf);
14147
  }
6785 bpr 14148
 
14179 bpr 14149
  if (fg[fg_prim_alcohol - 1]) {
14150
    sprintf (tmp_buf, "O1H1C000;");
14151
    strcat (out_buffer, tmp_buf);
14152
  }
14153
  if (fg[fg_sec_alcohol - 1]) {
14154
    sprintf (tmp_buf, "O1H2C000;");
14155
    strcat (out_buffer, tmp_buf);
14156
  }
14157
  if (fg[fg_tert_alcohol - 1]) {
14158
    sprintf (tmp_buf, "O1H3C000;");
14159
    strcat (out_buffer, tmp_buf);
14160
  }
14161
  if (fg[fg_1_2_diol - 1]) {
14162
    sprintf (tmp_buf, "O1H0CO1H;");
14163
    strcat (out_buffer, tmp_buf);
14164
  }
14165
  if (fg[fg_1_2_aminoalcohol - 1]) {
14166
    sprintf (tmp_buf, "O1H0CN1C;");
14167
    strcat (out_buffer, tmp_buf);
14168
  }
14169
  if (fg[fg_phenol - 1]) {
14170
    sprintf (tmp_buf, "O1H1A000;");
14171
    strcat (out_buffer, tmp_buf);
14172
  }
14173
  if (fg[fg_1_2_diphenol - 1]) {
14174
    sprintf (tmp_buf, "O1H2A000;");
14175
    strcat (out_buffer, tmp_buf);
14176
  }
14177
  if (fg[fg_enediol - 1]) {
14178
    sprintf (tmp_buf, "C2COH200;");
14179
    strcat (out_buffer, tmp_buf);
14180
  }
6785 bpr 14181
 
14179 bpr 14182
  if (fg[fg_dialkylether - 1]) {
14183
    sprintf (tmp_buf, "O1C0CC00;");
14184
    strcat (out_buffer, tmp_buf);
14185
  }
14186
  if (fg[fg_alkylarylether - 1]) {
14187
    sprintf (tmp_buf, "O1C0CA00;");
14188
    strcat (out_buffer, tmp_buf);
14189
  }
14190
  if (fg[fg_diarylether - 1]) {
14191
    sprintf (tmp_buf, "O1C0AA00;");
14192
    strcat (out_buffer, tmp_buf);
14193
  }
14194
  if (fg[fg_thioether - 1]) {
14195
    sprintf (tmp_buf, "S1C00000;");
14196
    strcat (out_buffer, tmp_buf);
14197
  }
14198
  if (fg[fg_disulfide - 1]) {
14199
    sprintf (tmp_buf, "S1S1C000;");
14200
    strcat (out_buffer, tmp_buf);
14201
  }
14202
  if (fg[fg_peroxide - 1]) {
14203
    sprintf (tmp_buf, "O1O1C000;");
14204
    strcat (out_buffer, tmp_buf);
14205
  }
14206
  if (fg[fg_hydroperoxide - 1]) {
14207
    sprintf (tmp_buf, "O1O1H000;");
14208
    strcat (out_buffer, tmp_buf);
14209
  }
14210
  if (fg[fg_hydrazine - 1]) {
14211
    sprintf (tmp_buf, "N1N10000;");
14212
    strcat (out_buffer, tmp_buf);
14213
  }
14214
  if (fg[fg_hydroxylamine - 1]) {
14215
    sprintf (tmp_buf, "N1O1H000;");
14216
    strcat (out_buffer, tmp_buf);
14217
  }
6785 bpr 14218
 
14179 bpr 14219
  if (fg[fg_prim_aliph_amine - 1]) {
14220
    sprintf (tmp_buf, "N1C1C000;");
14221
    strcat (out_buffer, tmp_buf);
14222
  }
14223
  if (fg[fg_prim_arom_amine - 1]) {
14224
    sprintf (tmp_buf, "N1C1A000;");
14225
    strcat (out_buffer, tmp_buf);
14226
  }
6785 bpr 14227
 
14179 bpr 14228
  if (fg[fg_sec_aliph_amine - 1]) {
14229
    sprintf (tmp_buf, "N1C2CC00;");
14230
    strcat (out_buffer, tmp_buf);
14231
  }
14232
  if (fg[fg_sec_mixed_amine - 1]) {
14233
    sprintf (tmp_buf, "N1C2AC00;");
14234
    strcat (out_buffer, tmp_buf);
14235
  }
14236
  if (fg[fg_sec_arom_amine - 1]) {
14237
    sprintf (tmp_buf, "N1C2AA00;");
14238
    strcat (out_buffer, tmp_buf);
14239
  }
6785 bpr 14240
 
14179 bpr 14241
  if (fg[fg_tert_aliph_amine - 1]) {
14242
    sprintf (tmp_buf, "N1C3CC00;");
14243
    strcat (out_buffer, tmp_buf);
14244
  }
14245
  if (fg[fg_tert_mixed_amine - 1]) {
14246
    sprintf (tmp_buf, "N1C3AC00;");
14247
    strcat (out_buffer, tmp_buf);
14248
  }
14249
  if (fg[fg_tert_arom_amine - 1]) {
14250
    sprintf (tmp_buf, "N1C3AA00;");
14251
    strcat (out_buffer, tmp_buf);
14252
  }
14253
  if (fg[fg_quart_ammonium - 1]) {
14254
    sprintf (tmp_buf, "N1C400T2;");
14255
    strcat (out_buffer, tmp_buf);
14256
  }
14257
  if (fg[fg_n_oxide - 1]) {
14258
    sprintf (tmp_buf, "N0O10000;");
14259
    strcat (out_buffer, tmp_buf);
14260
  }
6785 bpr 14261
 
14179 bpr 14262
  if (fg[fg_halogen_deriv - 1]) {
14263
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1]) {
14264
            sprintf (tmp_buf, "XX000000;");
14265
            strcat (out_buffer, tmp_buf);
14266
          }
14267
  }
6785 bpr 14268
 
14179 bpr 14269
  if (fg[fg_alkyl_fluoride - 1]) {
14270
    sprintf (tmp_buf, "XF00C000;");
14271
    strcat (out_buffer, tmp_buf);
14272
  }
14273
  if (fg[fg_alkyl_chloride - 1]) {
14274
    sprintf (tmp_buf, "XC00C000;");
14275
    strcat (out_buffer, tmp_buf);
14276
  }
14277
  if (fg[fg_alkyl_bromide - 1]) {
14278
    sprintf (tmp_buf, "XB00C000;");
14279
    strcat (out_buffer, tmp_buf);
14280
  }
14281
  if (fg[fg_alkyl_iodide - 1]) {
14282
    sprintf (tmp_buf, "XI00C000;");
14283
    strcat (out_buffer, tmp_buf);
14284
  }
6785 bpr 14285
 
14179 bpr 14286
  if (fg[fg_aryl_fluoride - 1]) {
14287
    sprintf (tmp_buf, "XF00A000;");
14288
    strcat (out_buffer, tmp_buf);
14289
  }
14290
  if (fg[fg_aryl_chloride - 1]) {
14291
    sprintf (tmp_buf, "XC00A000;");
14292
    strcat (out_buffer, tmp_buf);
14293
  }
14294
  if (fg[fg_aryl_bromide - 1]) {
14295
    sprintf (tmp_buf, "XB00A000;");
14296
    strcat (out_buffer, tmp_buf);
14297
  }
14298
  if (fg[fg_aryl_iodide - 1]) {
14299
    sprintf (tmp_buf, "XI00A000;");
14300
    strcat (out_buffer, tmp_buf);
14301
  }
14302
  if (fg[fg_organometallic - 1]) {
14303
    sprintf (tmp_buf, "000000MX;");
14304
    strcat (out_buffer, tmp_buf);
14305
  }
14306
  if (fg[fg_organolithium - 1]) {
14307
    sprintf (tmp_buf, "000000ML;");
14308
    strcat (out_buffer, tmp_buf);
14309
  }
14310
  if (fg[fg_organomagnesium - 1]) {
14311
    sprintf (tmp_buf, "000000MM;");
14312
    strcat (out_buffer, tmp_buf);
14313
  }
6785 bpr 14314
 
14179 bpr 14315
  if (fg[fg_carboxylic_acid - 1]) {
14316
    sprintf (tmp_buf, "C3O2H000;");
14317
    strcat (out_buffer, tmp_buf);
14318
  }
14319
  if (fg[fg_carboxylic_acid_salt - 1]) {
14320
    sprintf (tmp_buf, "C3O200T1;");
14321
    strcat (out_buffer, tmp_buf);
14322
  }
14323
  if (fg[fg_carboxylic_acid_ester - 1]) {
14324
    sprintf (tmp_buf, "C3O2C000;");
14325
    strcat (out_buffer, tmp_buf);
14326
  }
14327
  if (fg[fg_lactone - 1]) {
14328
    sprintf (tmp_buf, "C3O2CZ00;");
14329
    strcat (out_buffer, tmp_buf);
14330
  }
6785 bpr 14331
 
14179 bpr 14332
  if (fg[fg_carboxylic_acid_prim_amide - 1]) {
14333
    sprintf (tmp_buf, "C3ONC100;");
14334
    strcat (out_buffer, tmp_buf);
14335
  }
14336
  if (fg[fg_carboxylic_acid_sec_amide - 1]) {
14337
    sprintf (tmp_buf, "C3ONC200;");
14338
    strcat (out_buffer, tmp_buf);
14339
  }
14340
  if (fg[fg_carboxylic_acid_tert_amide - 1]) {
14341
    sprintf (tmp_buf, "C3ONC300;");
14342
    strcat (out_buffer, tmp_buf);
14343
  }
14344
  if (fg[fg_lactam - 1]) {
14345
    sprintf (tmp_buf, "C3ONCZ00;");
14346
    strcat (out_buffer, tmp_buf);
14347
  }
14348
  if (fg[fg_carboxylic_acid_hydrazide - 1]) {
14349
    sprintf (tmp_buf, "C3ONN100;");
14350
    strcat (out_buffer, tmp_buf);
14351
  }
14352
  if (fg[fg_carboxylic_acid_azide - 1]) {
14353
    sprintf (tmp_buf, "C3ONN200;");
14354
    strcat (out_buffer, tmp_buf);
14355
  }
14356
  if (fg[fg_hydroxamic_acid - 1]) {
14357
    sprintf (tmp_buf, "C3ONOH00;");
14358
    strcat (out_buffer, tmp_buf);
14359
  }
14360
  if (fg[fg_carboxylic_acid_amidine - 1]) {
14361
    sprintf (tmp_buf, "C3N2H000;");
14362
    strcat (out_buffer, tmp_buf);
14363
  }
14364
  if (fg[fg_carboxylic_acid_amidrazone - 1]) {
14365
    sprintf (tmp_buf, "C3NNN100;");
14366
    strcat (out_buffer, tmp_buf);
14367
  }
14368
  if (fg[fg_nitrile - 1]) {
14369
    sprintf (tmp_buf, "C3N00000;");
14370
    strcat (out_buffer, tmp_buf);
14371
  }
6785 bpr 14372
 
14179 bpr 14373
  if (fg[fg_acyl_fluoride - 1]) {
14374
    sprintf (tmp_buf, "C3OXF000;");
14375
    strcat (out_buffer, tmp_buf);
14376
  }
14377
  if (fg[fg_acyl_chloride - 1]) {
14378
    sprintf (tmp_buf, "C3OXC000;");
14379
    strcat (out_buffer, tmp_buf);
14380
  }
14381
  if (fg[fg_acyl_bromide - 1]) {
14382
    sprintf (tmp_buf, "C3OXB000;");
14383
    strcat (out_buffer, tmp_buf);
14384
  }
14385
  if (fg[fg_acyl_iodide - 1]) {
14386
    sprintf (tmp_buf, "C3OXI000;");
14387
    strcat (out_buffer, tmp_buf);
14388
  }
14389
  if (fg[fg_acyl_cyanide - 1]) {
14390
    sprintf (tmp_buf, "C2OC3N00;");
14391
    strcat (out_buffer, tmp_buf);
14392
  }
14393
  if (fg[fg_imido_ester - 1]) {
14394
    sprintf (tmp_buf, "C3NOC000;");
14395
    strcat (out_buffer, tmp_buf);
14396
  }
14397
  if (fg[fg_imidoyl_halide - 1]) {
14398
    sprintf (tmp_buf, "C3NXX000;");
14399
    strcat (out_buffer, tmp_buf);
14400
  }
6785 bpr 14401
 
14179 bpr 14402
  if (fg[fg_thiocarboxylic_acid - 1]) {
14403
    sprintf (tmp_buf, "C3SOH000;");
14404
    strcat (out_buffer, tmp_buf);
14405
  }
14406
  if (fg[fg_thiocarboxylic_acid_ester - 1]) {
14407
    sprintf (tmp_buf, "C3SOC000;");
14408
    strcat (out_buffer, tmp_buf);
14409
  }
14410
  if (fg[fg_thiolactone - 1]) {
14411
    sprintf (tmp_buf, "C3SOCZ00;");
14412
    strcat (out_buffer, tmp_buf);
14413
  }
14414
  if (fg[fg_thiocarboxylic_acid_amide - 1]) {
14415
    sprintf (tmp_buf, "C3SNH000;");
14416
    strcat (out_buffer, tmp_buf);
14417
  }
14418
  if (fg[fg_thiolactam - 1]) {
14419
    sprintf (tmp_buf, "C3SNCZ00;");
14420
    strcat (out_buffer, tmp_buf);
14421
  }
14422
  if (fg[fg_imido_thioester - 1]) {
14423
    sprintf (tmp_buf, "C3NSC000;");
14424
    strcat (out_buffer, tmp_buf);
14425
  }
14426
  if (fg[fg_oxohetarene - 1]) {
14427
    sprintf (tmp_buf, "C3ONAZ00;");
14428
    strcat (out_buffer, tmp_buf);
14429
  }
14430
  if (fg[fg_thioxohetarene - 1]) {
14431
    sprintf (tmp_buf, "C3SNAZ00;");
14432
    strcat (out_buffer, tmp_buf);
14433
  }
14434
  if (fg[fg_iminohetarene - 1]) {
14435
    sprintf (tmp_buf, "C3NNAZ00;");
14436
    strcat (out_buffer, tmp_buf);
14437
  }
14438
  if (fg[fg_orthocarboxylic_acid_deriv - 1]) {
14439
    sprintf (tmp_buf, "C3O30000;");
14440
    strcat (out_buffer, tmp_buf);
14441
  }
14442
  if (fg[fg_carboxylic_acid_orthoester - 1]) {
14443
    sprintf (tmp_buf, "C3O3C000;");
14444
    strcat (out_buffer, tmp_buf);
14445
  }
14446
  if (fg[fg_carboxylic_acid_amide_acetal - 1]) {
14447
    sprintf (tmp_buf, "C3O3NC00;");
14448
    strcat (out_buffer, tmp_buf);
14449
  }
14450
  if (fg[fg_carboxylic_acid_anhydride - 1]) {
14451
    sprintf (tmp_buf, "C3O2C3O2;");
14452
    strcat (out_buffer, tmp_buf);
14453
  }
6785 bpr 14454
 
14179 bpr 14455
  if (fg[fg_carboxylic_acid_unsubst_imide - 1]) {
14456
    sprintf (tmp_buf, "C3ONCH10;");
14457
    strcat (out_buffer, tmp_buf);
14458
  }
14459
  if (fg[fg_carboxylic_acid_subst_imide - 1]) {
14460
    sprintf (tmp_buf, "C3ONCC10;");
14461
    strcat (out_buffer, tmp_buf);
14462
  }
14463
  if (fg[fg_co2_deriv - 1]) {
14464
    sprintf (tmp_buf, "C4000000;");
14465
    strcat (out_buffer, tmp_buf);
14466
  }
14467
  if (fg[fg_carbonic_acid_deriv - 1]) {
14468
    sprintf (tmp_buf, "C4O30000;");
14469
    strcat (out_buffer, tmp_buf);
14470
  }
14471
  if (fg[fg_carbonic_acid_monoester - 1]) {
14472
    sprintf (tmp_buf, "C4O3C100;");
14473
    strcat (out_buffer, tmp_buf);
14474
  }
14475
  if (fg[fg_carbonic_acid_diester - 1]) {
14476
    sprintf (tmp_buf, "C4O3C200;");
14477
    strcat (out_buffer, tmp_buf);
14478
  }
14479
  if (fg[fg_carbonic_acid_ester_halide - 1]) {
14480
    sprintf (tmp_buf, "C4O3CX00;");
14481
    strcat (out_buffer, tmp_buf);
14482
  }
14483
  if (fg[fg_thiocarbonic_acid_deriv - 1]) {
14484
    sprintf (tmp_buf, "C4SO0000;");
14485
    strcat (out_buffer, tmp_buf);
14486
  }
14487
  if (fg[fg_thiocarbonic_acid_monoester - 1]) {
14488
    sprintf (tmp_buf, "C4SOC100;");
14489
    strcat (out_buffer, tmp_buf);
14490
  }
14491
  if (fg[fg_thiocarbonic_acid_diester - 1]) {
14492
    sprintf (tmp_buf, "C4SOC200;");
14493
    strcat (out_buffer, tmp_buf);
14494
  }
14495
  if (fg[fg_thiocarbonic_acid_ester_halide - 1]) {
14496
    sprintf (tmp_buf, "C4SOX_00;");
14497
    strcat (out_buffer, tmp_buf);
14498
  }
14499
  if (fg[fg_carbamic_acid_deriv - 1]) {
14500
    sprintf (tmp_buf, "C4O2N000;");
14501
    strcat (out_buffer, tmp_buf);
14502
  }
14503
  if (fg[fg_carbamic_acid - 1]) {
14504
    sprintf (tmp_buf, "C4O2NH00;");
14505
    strcat (out_buffer, tmp_buf);
14506
  }
14507
  if (fg[fg_carbamic_acid_ester - 1]) {
14508
    sprintf (tmp_buf, "C4O2NC00;");
14509
    strcat (out_buffer, tmp_buf);
14510
  }
14511
  if (fg[fg_carbamic_acid_halide - 1]) {
14512
    sprintf (tmp_buf, "C4O2NX00;");
14513
    strcat (out_buffer, tmp_buf);
14514
  }
14515
  if (fg[fg_thiocarbamic_acid_deriv - 1]) {
14516
    sprintf (tmp_buf, "C4SN0000;");
14517
    strcat (out_buffer, tmp_buf);
14518
  }
14519
  if (fg[fg_thiocarbamic_acid - 1]) {
14520
    sprintf (tmp_buf, "C4SNOH00;");
14521
    strcat (out_buffer, tmp_buf);
14522
  }
14523
  if (fg[fg_thiocarbamic_acid_ester - 1]) {
14524
    sprintf (tmp_buf, "C4SNOC00;");
14525
    strcat (out_buffer, tmp_buf);
14526
  }
14527
  if (fg[fg_thiocarbamic_acid_halide - 1]) {
14528
    sprintf (tmp_buf, "C4SNXX00;");
14529
    strcat (out_buffer, tmp_buf);
14530
  }
14531
  if (fg[fg_urea - 1]) {
14532
    sprintf (tmp_buf, "C4O1N200;");
14533
    strcat (out_buffer, tmp_buf);
14534
  }
14535
  if (fg[fg_isourea - 1]) {
14536
    sprintf (tmp_buf, "C4N2O100;");
14537
    strcat (out_buffer, tmp_buf);
14538
  }
14539
  if (fg[fg_thiourea - 1]) {
14540
    sprintf (tmp_buf, "C4S1N200;");
14541
    strcat (out_buffer, tmp_buf);
14542
  }
14543
  if (fg[fg_isothiourea - 1]) {
14544
    sprintf (tmp_buf, "C4N2S100;");
14545
    strcat (out_buffer, tmp_buf);
14546
  }
14547
  if (fg[fg_guanidine - 1]) {
14548
    sprintf (tmp_buf, "C4N30000;");
14549
    strcat (out_buffer, tmp_buf);
14550
  }
14551
  if (fg[fg_semicarbazide - 1]) {
14552
    sprintf (tmp_buf, "C4ON2N00;");
14553
    strcat (out_buffer, tmp_buf);
14554
  }
14555
  if (fg[fg_thiosemicarbazide - 1]) {
14556
    sprintf (tmp_buf, "C4SN2N00;");
14557
    strcat (out_buffer, tmp_buf);
14558
  }
14559
  if (fg[fg_azide - 1]) {
14560
    sprintf (tmp_buf, "N4N20000;");
14561
    strcat (out_buffer, tmp_buf);
14562
  }
14563
  if (fg[fg_azo_compound - 1]) {
14564
    sprintf (tmp_buf, "N2N10000;");
14565
    strcat (out_buffer, tmp_buf);
14566
  }
14567
  if (fg[fg_diazonium_salt - 1]) {
14568
    sprintf (tmp_buf, "N3N100T2;");
14569
    strcat (out_buffer, tmp_buf);
14570
  }
14571
  if (fg[fg_isonitrile - 1]) {
14572
    sprintf (tmp_buf, "N3C10000;");
14573
    strcat (out_buffer, tmp_buf);
14574
  }
14575
  if (fg[fg_cyanate - 1]) {
14576
    sprintf (tmp_buf, "C4NO1000;");
14577
    strcat (out_buffer, tmp_buf);
14578
  }
14579
  if (fg[fg_isocyanate - 1]) {
14580
    sprintf (tmp_buf, "C4NO2000;");
14581
    strcat (out_buffer, tmp_buf);
14582
  }
14583
  if (fg[fg_thiocyanate - 1]) {
14584
    sprintf (tmp_buf, "C4NS1000;");
14585
    strcat (out_buffer, tmp_buf);
14586
  }
14587
  if (fg[fg_isothiocyanate - 1]) {
14588
    sprintf (tmp_buf, "C4NS2000;");
14589
    strcat (out_buffer, tmp_buf);
14590
  }
14591
  if (fg[fg_carbodiimide - 1]) {
14592
    sprintf (tmp_buf, "C4N20000;");
14593
    strcat (out_buffer, tmp_buf);
14594
  }
14595
  if (fg[fg_nitroso_compound - 1]) {
14596
    sprintf (tmp_buf, "N2O10000;");
14597
    strcat (out_buffer, tmp_buf);
14598
  }
14599
  if (fg[fg_nitro_compound - 1]) {
14600
    sprintf (tmp_buf, "N4O20000;");
14601
    strcat (out_buffer, tmp_buf);
14602
  }
14603
  if (fg[fg_nitrite - 1]) {
14604
    sprintf (tmp_buf, "N3O20000;");
14605
    strcat (out_buffer, tmp_buf);
14606
  }
14607
  if (fg[fg_nitrate - 1]) {
14608
    sprintf (tmp_buf, "N4O30000;");
14609
    strcat (out_buffer, tmp_buf);
14610
  }
14611
  if (fg[fg_sulfuric_acid_deriv - 1]) {
14612
    sprintf (tmp_buf, "S6O00000;");
14613
    strcat (out_buffer, tmp_buf);
14614
  }
14615
  if (fg[fg_sulfuric_acid - 1]) {
14616
    sprintf (tmp_buf, "S6O4H000;");
14617
    strcat (out_buffer, tmp_buf);
14618
  }
14619
  if (fg[fg_sulfuric_acid_monoester - 1]) {
14620
    sprintf (tmp_buf, "S6O4HC00;");
14621
    strcat (out_buffer, tmp_buf);
14622
  }
14623
  if (fg[fg_sulfuric_acid_diester - 1]) {
14624
    sprintf (tmp_buf, "S6O4CC00;");
14625
    strcat (out_buffer, tmp_buf);
14626
  }
14627
  if (fg[fg_sulfuric_acid_amide_ester - 1]) {
14628
    sprintf (tmp_buf, "S6O3NC00;");
14629
    strcat (out_buffer, tmp_buf);
14630
  }
14631
  if (fg[fg_sulfuric_acid_amide - 1]) {
14632
    sprintf (tmp_buf, "S6O3N100;");
14633
    strcat (out_buffer, tmp_buf);
14634
  }
14635
  if (fg[fg_sulfuric_acid_diamide - 1]) {
14636
    sprintf (tmp_buf, "S6O2N200;");
14637
    strcat (out_buffer, tmp_buf);
14638
  }
14639
  if (fg[fg_sulfuryl_halide - 1]) {
14640
    sprintf (tmp_buf, "S6O3XX00;");
14641
    strcat (out_buffer, tmp_buf);
14642
  }
14643
  if (fg[fg_sulfonic_acid_deriv - 1]) {
14644
    sprintf (tmp_buf, "S5O00000;");
14645
    strcat (out_buffer, tmp_buf);
14646
  }
14647
  if (fg[fg_sulfonic_acid - 1]) {
14648
    sprintf (tmp_buf, "S5O3H000;");
14649
    strcat (out_buffer, tmp_buf);
14650
  }
14651
  if (fg[fg_sulfonic_acid_ester - 1]) {
14652
    sprintf (tmp_buf, "S5O3C000;");
14653
    strcat (out_buffer, tmp_buf);
14654
  }
14655
  if (fg[fg_sulfonamide - 1]) {
14656
    sprintf (tmp_buf, "S5O2N000;");
14657
    strcat (out_buffer, tmp_buf);
14658
  }
14659
  if (fg[fg_sulfonyl_halide - 1]) {
14660
    sprintf (tmp_buf, "S5O2XX00;");
14661
    strcat (out_buffer, tmp_buf);
14662
  }
14663
  if (fg[fg_sulfone - 1]) {
14664
    sprintf (tmp_buf, "S4O20000;");
14665
    strcat (out_buffer, tmp_buf);
14666
  }
14667
  if (fg[fg_sulfoxide - 1]) {
14668
    sprintf (tmp_buf, "S2O10000;");
14669
    strcat (out_buffer, tmp_buf);
14670
  }
14671
  if (fg[fg_sulfinic_acid_deriv - 1]) {
14672
    sprintf (tmp_buf, "S3O00000;");
14673
    strcat (out_buffer, tmp_buf);
14674
  }
14675
  if (fg[fg_sulfinic_acid - 1]) {
14676
    sprintf (tmp_buf, "S3O2H000;");
14677
    strcat (out_buffer, tmp_buf);
14678
  }
14679
  if (fg[fg_sulfinic_acid_ester - 1]) {
14680
    sprintf (tmp_buf, "S3O2C000;");
14681
    strcat (out_buffer, tmp_buf);
14682
  }
14683
  if (fg[fg_sulfinic_acid_halide - 1]) {
14684
    sprintf (tmp_buf, "S3O1XX00;");
14685
    strcat (out_buffer, tmp_buf);
14686
  }
14687
  if (fg[fg_sulfinic_acid_amide - 1]) {
6785 bpr 14688
      sprintf (tmp_buf, "S3O1N000;");
14689
      strcat (out_buffer, tmp_buf);
14690
    }
14179 bpr 14691
  if (fg[fg_sulfenic_acid_deriv - 1]) {
14692
    sprintf (tmp_buf, "S1O00000;");
14693
    strcat (out_buffer, tmp_buf);
14694
  }
14695
  if (fg[fg_sulfenic_acid - 1]) {
14696
    sprintf (tmp_buf, "S1O1H000;");
14697
    strcat (out_buffer, tmp_buf);
14698
  }
14699
  if (fg[fg_sulfenic_acid_ester - 1]) {
14700
    sprintf (tmp_buf, "S1O1C000;");
14701
    strcat (out_buffer, tmp_buf);
14702
  }
14703
  if (fg[fg_sulfenic_acid_halide - 1]) {
14704
    sprintf (tmp_buf, "S1O0XX00;");
14705
    strcat (out_buffer, tmp_buf);
14706
  }
14707
  if (fg[fg_sulfenic_acid_amide - 1]) {
14708
    sprintf (tmp_buf, "S1O0N100;");
14709
    strcat (out_buffer, tmp_buf);
14710
  }
6785 bpr 14711
 
14179 bpr 14712
  if (fg[fg_alkylthiol - 1]) {
14713
    sprintf (tmp_buf, "S1H1C000;");
14714
    strcat (out_buffer, tmp_buf);
14715
  }
14716
  if (fg[fg_arylthiol - 1]) {
14717
    sprintf (tmp_buf, "S1H1A000;");
14718
    strcat (out_buffer, tmp_buf);
14719
  }
14720
  if (fg[fg_phosphoric_acid_deriv - 1]) {
14721
    sprintf (tmp_buf, "P5O0H000;");
14722
    strcat (out_buffer, tmp_buf);
14723
  }
14724
  if (fg[fg_phosphoric_acid - 1]) {
14725
    sprintf (tmp_buf, "P5O4H200;");
14726
    strcat (out_buffer, tmp_buf);
14727
  }
14728
  if (fg[fg_phosphoric_acid_ester - 1]) {
14729
    sprintf (tmp_buf, "P5O4HC00;");
14730
    strcat (out_buffer, tmp_buf);
14731
  }
14732
  if (fg[fg_phosphoric_acid_halide - 1]) {
14733
    sprintf (tmp_buf, "P5O3HX00;");
14734
    strcat (out_buffer, tmp_buf);
14735
  }
14736
  if (fg[fg_phosphoric_acid_amide - 1]) {
14737
    sprintf (tmp_buf, "P5O3HN00;");
14738
    strcat (out_buffer, tmp_buf);
14739
  }
14740
  if (fg[fg_thiophosphoric_acid_deriv - 1]) {
14741
    sprintf (tmp_buf, "P5O0S000;");
14742
    strcat (out_buffer, tmp_buf);
14743
  }
14744
  if (fg[fg_thiophosphoric_acid - 1]) {
14745
    sprintf (tmp_buf, "P5O3SH00;");
14746
    strcat (out_buffer, tmp_buf);
14747
  }
14748
  if (fg[fg_thiophosphoric_acid_ester - 1]) {
14749
    sprintf (tmp_buf, "P5O3SC00;");
14750
    strcat (out_buffer, tmp_buf);
14751
  }
14752
  if (fg[fg_thiophosphoric_acid_halide - 1]) {
14753
    sprintf (tmp_buf, "P5O2SX00;");
14754
    strcat (out_buffer, tmp_buf);
14755
  }
14756
  if (fg[fg_thiophosphoric_acid_amide - 1]) {
14757
    sprintf (tmp_buf, "P5O2SN00;");
14758
    strcat (out_buffer, tmp_buf);
14759
  }
14760
  if (fg[fg_phosphonic_acid_deriv - 1]) {
14761
    sprintf (tmp_buf, "P4O30000;");
14762
    strcat (out_buffer, tmp_buf);
14763
  }
14764
  if (fg[fg_phosphonic_acid - 1]) {
14765
    sprintf (tmp_buf, "P4O3H000;");
14766
    strcat (out_buffer, tmp_buf);
14767
  }
14768
  if (fg[fg_phosphonic_acid_ester - 1]) {
14769
    sprintf (tmp_buf, "P4O3C000;");
14770
    strcat (out_buffer, tmp_buf);
14771
  }
14772
  if (fg[fg_phosphine - 1]) {
14773
    sprintf (tmp_buf, "P3000000;");
14774
    strcat (out_buffer, tmp_buf);
14775
  }
14776
  if (fg[fg_phosphinoxide - 1]) {
14777
    sprintf (tmp_buf, "P2O00000;");
14778
    strcat (out_buffer, tmp_buf);
14779
  }
14780
  if (fg[fg_boronic_acid_deriv - 1]) {
14781
    sprintf (tmp_buf, "B2O20000;");
14782
    strcat (out_buffer, tmp_buf);
14783
  }
14784
  if (fg[fg_boronic_acid - 1]) {
14785
    sprintf (tmp_buf, "B2O2H000;");
14786
    strcat (out_buffer, tmp_buf);
14787
  }
14788
  if (fg[fg_boronic_acid_ester - 1]) {
14789
    sprintf (tmp_buf, "B2O2C000;");
14790
    strcat (out_buffer, tmp_buf);
14791
  }
14792
  if (fg[fg_alkene - 1]) {
14793
    sprintf (tmp_buf, "000C2C00;");
14794
    strcat (out_buffer, tmp_buf);
14795
  }
14796
  if (fg[fg_alkyne - 1]) {
14797
    sprintf (tmp_buf, "000C3C00;");
14798
    strcat (out_buffer, tmp_buf);
14799
  }
14800
  if (fg[fg_aromatic - 1]) {
14801
    sprintf (tmp_buf, "0000A000;");
14802
    strcat (out_buffer, tmp_buf);
14803
  }
14804
  if (fg[fg_heterocycle - 1]) {
14805
    sprintf (tmp_buf, "0000CZ00;");
14806
    strcat (out_buffer, tmp_buf);
14807
  }
14808
  if (fg[fg_alpha_aminoacid - 1]) {
14809
    sprintf (tmp_buf, "C3O2HN1C;");
14810
    strcat (out_buffer, tmp_buf);
14811
  }
14812
  if (fg[fg_alpha_hydroxyacid - 1]) {
14813
    sprintf (tmp_buf, "C3O2HO1H;");
14814
    strcat (out_buffer, tmp_buf);
14815
  }
6785 bpr 14816
}
14817
 
14818
/*static void mm_elab_molstat(void)
14819
{
14820
                count_neighbors();
14821
//      init_molstat(&molstat);
14822
        if (!found_arominfo) {
14823
    chk_ringbonds();
14824
    if (ringsearch_mode == rs_ssr)
14825
      remove_redundant_rings();
14826
    if (n_rings == max_rings) {
14827
      if (opt_verbose)
14828
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
14829
      ringsearch_mode = rs_ssr;
14830
      clear_rings();
14831
      max_vringsize = 10;
14832
      chk_ringbonds();
14833
      remove_redundant_rings();
14834
    }
14179 bpr 14835
 
6785 bpr 14836
    update_ringcount();
14837
    update_atypes();
14838
    update_Htotal();
14839
    chk_arom();
14840
 
14841
    if (ringsearch_mode == rs_ssr) {
14842
      do {
14843
        prev_n_ar = count_aromatic_rings();
14844
        chk_arom();
14845
        n_ar = count_aromatic_rings();
14846
      } while (prev_n_ar - n_ar != 0);
14847
    }
14848
        } else {
14849
 update_atypes();
14179 bpr 14850
    update_Htotal();
14851
 
6785 bpr 14852
        }
14179 bpr 14853
 
6785 bpr 14854
 // get_molstat();
14855
}*/
14856
 
14857
DLLEXPORT void
14858
cm_molstat_X (char *buf)
14859
{
14860
  init_molstat (&molstat);
14861
//mm_elab_molstat();
14862
  get_molstat ();
14863
  write_molstat_X_dll (buf);
14864
}
14865
 
14866
DLLEXPORT void
14867
cm_molstat (char *buf)
14868
{
14869
  init_molstat (&molstat);
14870
//mm_elab_molstat();
14871
  get_molstat ();
14872
  write_molstat_dll (buf, 0);
14873
}
14874
 
14875
DLLEXPORT void
14876
cm_molstat_sql_exact (char *buf)
14877
{
14878
  init_molstat (&molstat);
14879
//mm_elab_molstat();
14880
  get_molstat ();
14881
  write_molstat_dll (buf, 1);
14882
}
14883
 
14884
DLLEXPORT void
14885
cm_molstat_sql_substruct (char *buf)
14886
{
14887
  init_molstat (&molstat);
14888
//mm_elab_molstat();
14889
  get_molstat ();
14890
  write_molstat_dll (buf, 2);
14891
}
14892
 
14893
DLLEXPORT void
14894
cm_fg_codes (char *buf)
14895
{
14896
//mm_elab_molstat();
14897
  chk_functionalgroups ();
14898
  write_fg_code_dll (buf);
14899
}
14900
 
14179 bpr 14901
static void write_MDLmolfile_dll (char *out_buffer)
6785 bpr 14902
{
14903
  int i;
14904
  char tmpstr[256];
14905
  char wline[256];
14906
  int a_chg;
14907
  int a_iso;
14908
  int a_rad;
14909
  char tmflabel[256];           /* v0.3m */
14910
  char STR1[256], STR7[256];
14911
  int FORLIM;
14912
  *out_buffer = '\0';
14913
  *tmpstr = '\0';
14914
  *wline = '\0';
14915
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
14916
  while (strlen (tmflabel) < 2) /* v0.3m */
14917
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
14918
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
14919
  if (strlen (molname) > 80)
14920
    sprintf (molname, "%.80s", strcpy (STR1, molname));
14921
  strncat (out_buffer, molname, 80);
14922
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
14923
  if (ringsearch_mode == rs_sar)        /* v0.3m */
14924
    strcat (wline, ":r0");
14925
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
14926
    strcat (wline, ":r1");
14927
  if (opt_metalrings)
14928
    strcat (wline, ":m1");
14929
  else
14930
    strcat (wline, ":m0");
14931
  /* v0.3m */
14932
  sprintf (tmpstr, "\n%s\n", molcomment);
14933
  strcat (wline, tmpstr);
14934
  sprintf (tmpstr, "%d", n_atoms);
14935
  lblank (3L, tmpstr);
14936
  strcat (wline, tmpstr);
14937
  /* first 3 digits: number of atoms */
14938
  sprintf (tmpstr, "%d", n_bonds);
14939
  lblank (3L, tmpstr);
14940
  strcat (wline, tmpstr);
14941
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
14942
  strcpy (tmpstr, "  0");
14943
  strcat (wline, tmpstr);
14944
  /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 14945
  /* p2c: checkmol.pas, line 2388:
14946
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 14947
#ifdef REDUCED_SAR
14948
  sprintf (tmpstr, "%d", n_countablerings);
14949
  /* v0.3n; changed n_rings into n_countablerings */
14950
#else
14951
  sprintf (tmpstr, "%d", n_rings);
14952
#endif
14953
  lblank (3L, tmpstr);
14954
  strcat (wline, tmpstr);
14955
  /* officially "obsolete", we use it for the number of rings */
14956
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
14957
  if (chir_flag)
14958
    strcat (wline, "1");
14959
  else
14960
    strcat (wline, "0");
14961
  /* v0.3n */
14962
  strcat (wline, "               999 V2000\n");
14963
  /* v0.3n (adjust string length) */
14964
  strcat (out_buffer, wline);
14965
  FORLIM = n_atoms;
14179 bpr 14966
  for (i = 0; i < FORLIM; i++) {
14967
    *wline = '\0';
14968
    *tmpstr = '\0';
14969
    sprintf (tmpstr, "%1.4f", atom[i].x);
14970
    lblank (10L, tmpstr);
14971
    strcat (wline, tmpstr);
14972
    sprintf (tmpstr, "%1.4f", atom[i].y);
14973
    lblank (10L, tmpstr);
14974
    strcat (wline, tmpstr);
14975
    sprintf (tmpstr, "%1.4f", atom[i].z);
14976
    lblank (10L, tmpstr);
14977
    strcat (wline, tmpstr);
14978
    strcpy (tmpstr, atom[i].element);
14979
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
14980
    //tmpstr[0] = toupper (tmpstr[0]);
14981
    all_lowercase (tmpstr);
14982
    tmpstr[0] = toupper (tmpstr[0]);
14983
    /*wline := wline + ' '+atom^[i].element+' '; */
14984
    sprintf (wline + strlen (wline), " %s ", tmpstr);
14985
    strcat (wline, " 0");       /* mass difference (isotopes) */
14986
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
14987
    if (atom[i].arom)
14988
            strcpy (tmpstr, " 00");
14989
    else
14990
            strcpy (tmpstr, "  0");
14991
    strcat (wline, tmpstr);
14992
    strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
14993
    strcat (out_buffer, wline);
14994
  }
6785 bpr 14995
  FORLIM = n_bonds;
14179 bpr 14996
  for (i = 0; i < FORLIM; i++) {
14997
    *wline = '\0';
14998
    *tmpstr = '\0';
14999
    sprintf (tmpstr, "%d", bond[i].a1);
15000
    lblank (3L, tmpstr);
15001
    strcat (wline, tmpstr);
15002
    sprintf (tmpstr, "%d", bond[i].a2);
15003
    lblank (3L, tmpstr);
15004
    strcat (wline, tmpstr);
15005
    if (bond[i].btype == 'S')
15006
            strcpy (tmpstr, "  1");
15007
    if (bond[i].btype == 'D')
15008
            strcpy (tmpstr, "  2");
15009
    if (bond[i].btype == 'T')
15010
            strcpy (tmpstr, "  3");
15011
    if (bond[i].btype == 'A')
15012
            strcpy (tmpstr, "  4");
15013
    if (bond[i].btype == 'l')
15014
            strcpy (tmpstr, "  5");
15015
    if (bond[i].btype == 's')
15016
            strcpy (tmpstr, "  6");
15017
    if (bond[i].btype == 'd')
15018
            strcpy (tmpstr, "  7");
15019
    if (bond[i].btype == 'a')
15020
            strcpy (tmpstr, "  8");
15021
        /* now encode our own aromaticity information */
15022
    if (bond[i].arom)
15023
            tmpstr[1] = '0';
15024
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
15025
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
15026
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
15027
    /*    wline := wline + '  0'; */
15028
    /* restore original value from MDL molfile (v0.3n) */
15029
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
15030
    *tmpstr = '\0';
15031
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
15032
    strcat (wline, "  ");
15033
    strcat (wline, tmpstr);
15034
    *tmpstr = '\0';
15035
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
15036
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
15037
    sprintf (tmpstr, "%i", bond[i].ring_count);
15038
    while (strlen (tmpstr) < 3)
15039
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
15040
    sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
15041
    strcat (out_buffer, wline);
15042
  }
6785 bpr 15043
  FORLIM = n_atoms;
14179 bpr 15044
  for (i = 1; i <= FORLIM; i++) {
15045
    a_chg = atom[i - 1].formal_charge;
15046
    if (a_chg != 0) {
15047
            strcpy (wline, "M  CHG  1 ");
15048
            sprintf (tmpstr, "%d", i);
15049
            lblank (3L, tmpstr);
15050
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15051
            sprintf (tmpstr, "%d", a_chg);
15052
            lblank (3L, tmpstr);
15053
            strcat (wline, tmpstr);
15054
            strcat (out_buffer, wline);
15055
            strcat (out_buffer, "\n");
15056
          }
15057
  }
15058
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
15059
    a_iso = atom[i - 1].nucleon_number;
15060
    if (a_iso != 0) {
15061
            strcpy (wline, "M  ISO  1 ");
15062
            sprintf (tmpstr, "%d", i);
15063
            lblank (3L, tmpstr);
15064
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15065
            sprintf (tmpstr, "%d", a_iso);
15066
            lblank (3L, tmpstr);
15067
            strcat (wline, tmpstr);
15068
            strcat (out_buffer, wline);
15069
            strcat (out_buffer, "\n");
15070
          }
15071
  }
15072
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
15073
    a_rad = atom[i - 1].radical_type;
15074
    if (a_rad != 0) {
15075
            strcpy (wline, "M  RAD  1 ");
15076
            sprintf (tmpstr, "%d", i);
15077
            lblank (3L, tmpstr);
15078
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15079
            sprintf (tmpstr, "%d", a_rad);
15080
            lblank (3L, tmpstr);
15081
            strcat (wline, tmpstr);
15082
            strcat (out_buffer, wline);
15083
            strcat (out_buffer, "\n");
15084
          }
15085
  }
6785 bpr 15086
  strcat (out_buffer, "M  END\n");
15087
}
15088
 
15089
DLLEXPORT void
15090
cm_tweak_molfile (char *buf)
15091
{
15092
//chk_functionalgroups();
15093
  write_MDLmolfile_dll (buf);
15094
}
15095
#endif