Subversion Repositories wimsdev

Rev

Rev 11128 | Rev 14249 | 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
6508
              if (strcmp (nb_el, "H ") /*&& strcmp (nb_el, "D ") */  &&
6509
                      strcmp (nb_el, "LP"))
6510
                /* v0.3n: D */
6511
              het_count++;
6512
              if (is_hydroxy (a_ref, nb[i]))
6513
                oh_count++;
6514
              if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]))
6515
                /* fixed in v0.3b */
6516
                or_count++;
6517
              if (!strcmp (nb_el, "N "))
6518
                n_count++;
6519
              if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
6520
                  !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
6521
                  || !strcmp (nb_el, "AT"))
6522
                hal_count++;
6523
          }
6524
  }
6785 bpr 6525
  het_count = oh_count + or_count + hal_count + n_count;
6526
  /* fixed in v0.3b */
6527
  if (c_count != 1 || het_count != 2)
6528
    return;
6529
  fg[fg_boronic_acid_deriv - 1] = true;
6530
  if (oh_count == 2)
6531
    fg[fg_boronic_acid - 1] = true;
6532
  if (or_count > 0)
6533
    fg[fg_boronic_acid_ester - 1] = true;
6534
}
6535
 
14179 bpr 6536
static void chk_ammon (a_ref)
6785 bpr 6537
     int a_ref;
6538
{
6539
  int i;
6540
  neighbor_rec nb;
6541
  str2 nb_el;
6542
  int het_count = 0, o_count = 0, or_count = 0, r_count = 0;
6543
  char bt;                      /* v0.3k */
6544
  float bo_sum = 0.0;
6545
  boolean ha;
6546
  int FORLIM;
6547
 
6548
  memset (nb, 0, sizeof (neighbor_rec));
6549
  if (strcmp (atom[a_ref - 1].atype, "N3+")
6550
      && atom[a_ref - 1].formal_charge == 0)
6551
    return;
6552
  if (strcmp (atom[a_ref - 1].element, "N "))   /* just to be sure;  v0.3i */
6553
    return;
6554
  get_neighbors (nb, a_ref);
6555
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 6556
  for (i = 0; i < FORLIM; i++) {
6557
    bt = bond[get_bond (a_ref, nb[i]) - 1].btype;       /* v0.3k */
6558
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3k */
6559
    ha = atom[nb[i] - 1].heavy; /* v0.3k */
6560
    if (bt == 'S') {
6561
            if (ha)
6562
              bo_sum += 1.0;
6563
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
6564
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")) {
6565
                /* added 'D ' in v0.3n */
6785 bpr 6566
              het_count++;
14179 bpr 6567
              if (!strcmp (nb_el, "O ")) {
6568
                      o_count++;
6569
                      if (atom[nb[i] - 1].neighbor_count > 1)
6570
                        or_count++;
6571
                    }
6785 bpr 6572
            }
14179 bpr 6573
            if (is_alkyl (a_ref, nb[i]) || is_aryl (a_ref, nb[i]) |
6574
                is_alkenyl (a_ref, nb[i]) || is_alkynyl (a_ref, nb[i]))
6575
              /* v0.3k */
6576
              r_count++;
6577
          }
6578
    if (bt == 'D') {
6579
            if (ha)
6580
              bo_sum += 2.0;
6581
            if (strcmp (nb_el, "C ")) {
6785 bpr 6582
              het_count += 2;
6583
              if (!strcmp (nb_el, "O "))
14179 bpr 6584
                      o_count += 2;
6785 bpr 6585
            }
14179 bpr 6586
            if (!strcmp (nb_el, "C "))
6587
              r_count++;
6588
          }
6589
    if (bt == 'A' && ha)
6590
            bo_sum += 1.5;
6591
  }                             /* v0.3k: corrected end of "for ..." loop */
6785 bpr 6592
  if (het_count == 0 && r_count == 4)
6593
    fg[fg_quart_ammonium - 1] = true;
6594
  if (het_count != 1 || atom[a_ref - 1].neighbor_count < 3)
6595
    return;
6596
  if (o_count == 1 && or_count == 0 && bo_sum > 3)
6597
    fg[fg_n_oxide - 1] = true;  /* finds only aliphatic N-oxides! */
6598
  if (((o_count == 1 && or_count == 1) || o_count == 0) &&
6599
      atom[a_ref - 1].arom == true)
6600
    fg[fg_quart_ammonium - 1] = true;
6601
}
6602
 
14179 bpr 6603
static void swap_atoms (a1, a2)
6785 bpr 6604
     int *a1, *a2;
6605
{
6606
  int a_tmp;
6607
 
6608
  a_tmp = *a1;
6609
  *a1 = *a2;
6610
  *a2 = a_tmp;
6611
}
6612
 
14179 bpr 6613
static void orient_bond (a1, a2)
6785 bpr 6614
     int *a1, *a2;
6615
{
6616
  str2 a1_el, a2_el;
6617
 
6618
  strcpy (a1_el, atom[*a1 - 1].element);
6619
  strcpy (a2_el, atom[*a2 - 1].element);
6620
  if (!strcmp (a1_el, "H ") || !strcmp (a2_el, "H ")
6621
      || !strcmp (a1_el, "D ") || !strcmp (a2_el, "D "))
6622
    /* v0.3n: D */
6623
    return;
6624
  if (!strcmp (a2_el, "C ") && strcmp (a1_el, "C "))
6625
    swap_atoms (a1, a2);
14179 bpr 6626
  if (!strcmp (a2_el, a1_el)) {
6627
    if (hetbond_count (*a1) > hetbond_count (*a2))
6785 bpr 6628
            swap_atoms (a1, a2);
14179 bpr 6629
  }
6630
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && strcmp (a1_el, a2_el)) {
6631
    if (!strcmp (a1_el, "O ") || !strcmp (a2_el, "O ")) {
6632
            if (!strcmp (a1_el, "O "))
6633
              swap_atoms (a1, a2);
6634
          }
6635
  }
6636
  if (strcmp (a2_el, "C ") && strcmp (a1_el, "C ") && !strcmp (a1_el, a2_el)) {
6785 bpr 6637
      if (atom[*a2 - 1].neighbor_count - hetbond_count (*a2) >
14179 bpr 6638
              atom[*a1 - 1].neighbor_count - hetbond_count (*a1))
6639
          swap_atoms (a1, a2);
6640
  }
6785 bpr 6641
}
6642
 
14179 bpr 6643
static void chk_imine (a_ref, a_view)
6785 bpr 6644
     int a_ref, a_view;
6645
{
6646
  /* a_ref = C, a_view = N */
6647
  int i;
6648
  neighbor_rec nb;
6649
  str2 nb_el;
6788 kbelabas 6650
  int a_het = 0, a_c;
6785 bpr 6651
  int het_count = 0, c_count = 0, o_count = 0;  /* v0.3k */
6652
  int FORLIM;
6653
 
6654
  /* v0.3k */
14179 bpr 6655
  if (atom[a_view - 1].neighbor_count == 1) {
6785 bpr 6656
      if (atom[a_ref - 1].arom == false)
6657
        fg[fg_imine - 1] = true;
6658
      return;
6659
    }
6660
  memset (nb, 0, sizeof (neighbor_rec));
6661
  get_neighbors (nb, a_view);
6662
  if (atom[a_view - 1].neighbor_count <= 1)
6663
    return;
6664
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6665
  for (i = 0; i < FORLIM; i++) {
6666
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'S')){
6667
            strcpy (nb_el, atom[nb[i] - 1].element);
6668
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6669
              a_c = nb[i];
6670
              c_count++;
6671
            }
14179 bpr 6672
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ")) {
6785 bpr 6673
              a_het = nb[i];
6674
              het_count++;
6675
            }
14179 bpr 6676
            if ((!strcmp (nb_el, "O ")
6785 bpr 6677
               && atom[nb[i] - 1].neighbor_count ==
6678
               1) && (bond[get_bond (a_view, nb[i]) - 1].arom == false))
14179 bpr 6679
              /* v0.3k */
6680
              o_count++;
6681
          }
6682
    if ((nb[i] != a_ref) && (bond[get_bond (a_view, nb[i]) - 1].btype == 'D')){
6683
      /* v0.3k; make sure we do not count nitro groups in "azi" form etc. */
6684
            strcpy (nb_el, atom[nb[i] - 1].element);
6685
            if (!strcmp (nb_el, "O ") || !strcmp (nb_el, "N ") || !strcmp (nb_el, "S ")) {
6785 bpr 6686
              a_het = nb[i];    /* v0.3m */
6687
              het_count++;
6688
            }
14179 bpr 6689
            if ((!strcmp (nb_el, "O ")
6690
                && atom[nb[i] - 1].neighbor_count == 1) &&
6691
                  (bond[get_bond (a_view, nb[i]) - 1].arom == false))
6692
              /* v0.3k */
6693
              o_count++;
6694
          }
6695
  }
6696
  if (c_count == 1) {
6697
    if ((is_alkyl (a_view, a_c) || is_aryl (a_view, a_c) |
6698
              is_alkenyl (a_view, a_c) || is_alkynyl (a_view, a_c))
6699
              && atom[a_ref - 1].arom == false && het_count == 0)
6785 bpr 6700
            /* v0.3k */
14179 bpr 6701
            fg[fg_imine - 1] = true;
6702
  }
6703
  if (het_count == 1) {
6704
    strcpy (nb_el, atom[a_het - 1].element);
6705
    if (!strcmp (nb_el, "O ")) {
6706
            if (is_hydroxy (a_view, a_het))
6707
              fg[fg_oxime - 1] = true;
6785 bpr 6708
          if (is_alkoxy (a_view, a_het) || is_aryloxy (a_view, a_het) |
6709
              is_alkenyloxy (a_view, a_het) || is_alkynyloxy (a_view, a_het))
6710
            fg[fg_oxime_ether - 1] = true;
14179 bpr 6711
          }
6712
    if (!strcmp (nb_el, "N ")) {
6713
            if (is_amino (a_view, a_het) || is_alkylamino (a_view, a_het) |
6714
                is_dialkylamino (a_view, a_het) || is_alkylarylamino (a_view,a_het) |
6715
                is_arylamino (a_view, a_het) || is_diarylamino (a_view, a_het))
6716
              fg[fg_hydrazone - 1] = true;
6717
            else {
6785 bpr 6718
              memset (nb, 0, sizeof (neighbor_rec));
6719
              get_neighbors (nb, a_het);
14179 bpr 6720
              if (atom[a_het - 1].neighbor_count > 1) {
6721
                      FORLIM = atom[a_het - 1].neighbor_count;
6722
                      for (i = 0; i < FORLIM; i++) {
6723
                        if (nb[i] != a_view) {
6724
                                if (is_carbamoyl (a_het, nb[i]))
6725
                                  fg[fg_semicarbazone - 1] = true;
6726
                                if (is_thiocarbamoyl (a_het, nb[i]))
6727
                                  fg[fg_thiosemicarbazone - 1] = true;
6728
                              }
6729
                      }
6785 bpr 6730
                    }
6731
            }
14179 bpr 6732
          }
6733
  }                             /* v0.3k: nitro groups in "azi" form */
6785 bpr 6734
  /* check for semicarbazone or thiosemicarbazone */
6735
  if (het_count == 2 && o_count == 2)
6736
    fg[fg_nitro_compound - 1] = true;
6737
}
6738
 
14179 bpr 6739
static void chk_carbonyl_deriv (a_view, a_ref)
6785 bpr 6740
     int a_view, a_ref;
6741
{
6742
  /* a_view = C */
6743
  int i;
6744
  neighbor_rec nb;
6745
  str2 nb_el;
6746
  int c_count = 0, cn_count = 0;
6747
  char bt;                      /* new in v0.3b */
6748
  int n_db = 0;                 /* new in v0.3b */
6749
  int FORLIM;
6750
 
6751
  memset (nb, 0, sizeof (neighbor_rec));
6752
  get_neighbors (nb, a_view);
6753
  FORLIM = atom[a_view - 1].neighbor_count;
6754
  /* new in v0.3b */
14179 bpr 6755
  for (i = 0; i < FORLIM; i++) {
6756
    bt = bond[get_bond (a_view, nb[i]) - 1].btype;
6757
    if (bt == 'S') {
6758
            strcpy (nb_el, atom[nb[i] - 1].element);
6759
            if (!strcmp (nb_el, "C ")) {
6785 bpr 6760
              if (is_cyano_c (nb[i]))
14179 bpr 6761
                      cn_count++;
6785 bpr 6762
              else
14179 bpr 6763
                      c_count++;
6785 bpr 6764
            }
14179 bpr 6765
          }
6766
    else {
6767
            if (bt == 'D')
6768
              n_db++;
6769
          }
6770
  }
6785 bpr 6771
  /* new in v0.3b */
14179 bpr 6772
  if (is_oxo_C (a_view)) {
6773
    fg[fg_carbonyl - 1] = true;
6774
    if (c_count + cn_count < 2) {                       /* new in v0.3b (detection of ketenes) */
6775
            if (n_db <= 1)
6776
              fg[fg_aldehyde - 1] = true;
6777
            else
6778
              fg[fg_ketene - 1] = true;
6779
          }
6780
    if (c_count == 2) {
6781
            if (atom[a_view - 1].arom)
6782
              fg[fg_oxohetarene - 1] = true;
6783
            else
6784
              fg[fg_ketone - 1] = true;
6785
          }
6786
    if (cn_count > 0)
6787
            fg[fg_acyl_cyanide - 1] = true;
6788
  }
6789
  if (is_thioxo_C (a_view)) {
6790
    fg[fg_thiocarbonyl - 1] = true;
6791
    if (c_count < 2)
6792
            fg[fg_thioaldehyde - 1] = true;
6793
    if (c_count == 2) {
6794
            if (atom[a_view - 1].arom)
6795
              fg[fg_thioxohetarene - 1] = true;
6796
            else
6797
              fg[fg_thioketone - 1] = true;
6798
          }
6799
  }
6785 bpr 6800
  if (is_imino_C (a_view))
6801
    chk_imine (a_view, a_ref);
6802
}
6803
 
14179 bpr 6804
static void chk_carboxyl_deriv (a_view, a_ref)
6785 bpr 6805
     int a_view, a_ref;
6806
{
6807
  int i;
6808
  neighbor_rec nb;
6809
  str2 nb_el;
6810
  int o_count = 0, n_count = 0, s_count = 0;
6786 kbelabas 6811
  int a_o = 0, a_n = 0, a_s = 0, FORLIM;
6785 bpr 6812
 
6813
  memset (nb, 0, sizeof (neighbor_rec));
6814
  get_neighbors (nb, a_view);
6815
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 6816
  for (i = 0; i < FORLIM; i++) {
6817
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
6818
            strcpy (nb_el, atom[nb[i] - 1].element);
6819
            if (strcmp (nb_el, "C ")) {
6820
              if (!strcmp (nb_el, "O ")) {
6821
                      o_count++;
6822
                      a_o = nb[i];
6823
                    }
6824
              if (!strcmp (nb_el, "N ")) {
6825
                      n_count++;
6826
                      a_n = nb[i];
6827
                    }
6828
              if (!strcmp (nb_el, "S ")) {
6829
                      s_count++;
6830
                      a_s = nb[i];
6831
                    }
6785 bpr 6832
            }
14179 bpr 6833
          }
6834
  }
6835
  if (is_oxo_C (a_view)) {
6836
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
6837
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
6838
              fg[fg_carboxylic_acid_deriv - 1] = true;
6839
            if (is_hydroxy (a_view, a_o)) {
6785 bpr 6840
              if (atom[a_o - 1].formal_charge == 0)
14179 bpr 6841
                      fg[fg_carboxylic_acid - 1] = true;
6785 bpr 6842
              if (atom[a_o - 1].formal_charge == -1)
14179 bpr 6843
                      fg[fg_carboxylic_acid_salt - 1] = true;
6785 bpr 6844
            }
14179 bpr 6845
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o) |
6846
                is_alkenyloxy (a_view, a_o) || is_alkynyloxy (a_view, a_o)) {
6785 bpr 6847
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
14179 bpr 6848
                      fg[fg_carboxylic_acid_ester - 1] = true;
6849
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
6850
                      if (bond[get_bond (a_view, a_o) - 1].arom == true) {
6851
                        /*fg[fg_lactone_heteroarom] := true else fg[fg_lactone] := true; */
6852
                        fg[fg_oxohetarene - 1] = true;
6853
                      }
6854
                    else
6855
                      fg[fg_lactone - 1] = true;
6785 bpr 6856
                    }
6857
            }
14179 bpr 6858
          }
6859
    if (n_count == 1) {
6860
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6861
              fg[fg_carboxylic_acid_deriv - 1] = true;
6862
            else {
6785 bpr 6863
              /*fg[fg_lactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6864
              fg[fg_oxohetarene - 1] = true;
6865
            }
14179 bpr 6866
            if (is_amino (a_view, a_n) || (!strcmp (atom[a_n - 1].atype, "NAM")
6867
                      && atom[a_n - 1].neighbor_count == 1)) {
6785 bpr 6868
              fg[fg_carboxylic_acid_amide - 1] = true;
6869
              fg[fg_carboxylic_acid_prim_amide - 1] = true;
6870
            }
14179 bpr 6871
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6872
            if (is_C_monosubst_amino (a_view, a_n) &
6873
                (!is_subst_acylamino (a_view, a_n))) {                  /* v0.3j */
6785 bpr 6874
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6875
                      fg[fg_carboxylic_acid_amide - 1] = true;
6785 bpr 6876
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6877
                      fg[fg_carboxylic_acid_sec_amide - 1] = true;
6878
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6879
                      if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6880
                        /*fg[fg_lactam_heteroarom]    := true else  */
6881
                        fg[fg_oxohetarene - 1] = true;
6882
                      }
6883
                      else
6884
                        fg[fg_lactam - 1] = true;
6785 bpr 6885
                    }
6886
            }
14179 bpr 6887
            /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6888
            /*   (is_diarylamino(a_view,a_n)) then  */
6889
            if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6890
              /* v0.3j */
6785 bpr 6891
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6892
                fg[fg_carboxylic_acid_amide - 1] = true;
6785 bpr 6893
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6894
                fg[fg_carboxylic_acid_tert_amide - 1] = true;
6895
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6896
                if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6897
                        /*fg[fg_lactam_heteroarom]    := true else  */
6898
                        fg[fg_oxohetarene - 1] = true;
6899
                      }
6900
                      else
6901
                        fg[fg_lactam - 1] = true;
6785 bpr 6902
                    }
6903
            }
14179 bpr 6904
            if (is_hydroxylamino (a_view, a_n))
6905
              fg[fg_hydroxamic_acid - 1] = true;
6906
            if (is_hydrazino (a_view, a_n))
6907
              fg[fg_carboxylic_acid_hydrazide - 1] = true;
6908
            if (is_azido (a_view, a_n))
6909
              fg[fg_carboxylic_acid_azide - 1] = true;
6910
          }
6911
    if (s_count == 1) {                 /* anhydride is checked somewhere else */
6912
            if (bond[get_bond (a_view, a_s) - 1].arom == false)
6913
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6914
            if (is_sulfanyl (a_view, a_s))
6915
              fg[fg_thiocarboxylic_acid - 1] = true;
6916
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6785 bpr 6917
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 6918
                      fg[fg_thiocarboxylic_acid_ester - 1] = true;
6919
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
6920
                      if (bond[get_bond (a_view, a_s) - 1].arom == true) {
6921
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6922
                        fg[fg_oxohetarene - 1] = true;
6923
                      }
6924
                      else
6925
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6926
                    }
6927
            }
14179 bpr 6928
          }
6929
  }                             /* end Oxo-C */
6930
  if (is_thioxo_C (a_view)) {
6931
    /* fg[fg_thiocarboxylic_acid_deriv]  := true; */
6932
    if (o_count == 1) {                 /* anhydride is checked somewhere else */
6933
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
6934
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6935
            if (is_hydroxy (a_view, a_o))
6936
              fg[fg_thiocarboxylic_acid - 1] = true;    /* fixed in v0.3c */
6937
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
6785 bpr 6938
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 6939
                      fg[fg_thiocarboxylic_acid_ester - 1] = true;
6940
              if (bond[get_bond (a_view, a_o) - 1].ring_count > 0) {
6941
                      if (bond[get_bond (a_view, a_o) - 1].arom == true) {
6942
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
6943
                        fg[fg_thioxohetarene - 1] = true;
6944
                      }
6945
                      else
6946
                        fg[fg_thiolactone - 1] = true;
6785 bpr 6947
                    }
6948
            }
14179 bpr 6949
          }
6950
    if (n_count == 1) {
6951
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6952
              fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6953
            else {
6785 bpr 6954
              /*fg[fg_thiolactam_heteroarom] := true;  (* catches also pyridazines, 1,2,3-triazines, etc. */
6955
              fg[fg_thioxohetarene - 1] = true;
6956
            }
14179 bpr 6957
            /* catches also pyridazines, 1,2,3-triazines, etc. */
6958
            if (is_amino (a_view, a_n)){
6785 bpr 6959
              fg[fg_thiocarboxylic_acid_amide - 1] = true;
6960
              /* fg[fg_thiocarboxylic_acid_prim_amide] := true; */
6961
            }
14179 bpr 6962
            /*if (is_alkylamino(a_view,a_n)) or (is_arylamino(a_view,a_n)) then  */
6963
            if (is_C_monosubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6964
              /* v0.3j */
6785 bpr 6965
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 6966
                      fg[fg_thiocarboxylic_acid_amide - 1] = true;
6785 bpr 6967
              /*fg[fg_thiocarboxylic_acid_sec_amide]  := true; */
14179 bpr 6968
              if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6969
                      if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6970
                        /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
6971
                        fg[fg_thioxohetarene - 1] = true;
6785 bpr 6972
                    }
14179 bpr 6973
                    else
6974
                      fg[fg_thiolactam - 1] = true;
6975
                  }
6976
          }
6785 bpr 6977
          /*if (is_dialkylamino(a_view,a_n)) or (is_alkylarylamino(a_view,a_n)) or */
6978
          /*   (is_diarylamino(a_view,a_n)) then  */
14179 bpr 6979
          if (is_C_disubst_amino (a_view, a_n) & (!is_subst_acylamino (a_view, a_n))) {
6980
            /* v0.3j */
6981
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
6982
                    fg[fg_thiocarboxylic_acid_amide - 1] = true;
6785 bpr 6983
              /*fg[fg_thiocarboxylic_acid_tert_amide] := true; */
14179 bpr 6984
            if (bond[get_bond (a_view, a_n) - 1].ring_count > 0) {
6985
                    if (bond[get_bond (a_view, a_n) - 1].arom == true) {
6785 bpr 6986
                      /*fg[fg_thiolactam_heteroarom] := true else fg[fg_thiolactam] := true; */
6987
                      fg[fg_thioxohetarene - 1] = true;
6988
                    }
14179 bpr 6989
                    else
6990
                      fg[fg_thiolactam - 1] = true;
6991
                  }
6992
          }
6785 bpr 6993
        }
14179 bpr 6994
  if (s_count == 1) {                   /* anhydride is checked somewhere else */
6785 bpr 6995
          if (bond[get_bond (a_view, a_s) - 1].arom == false)
6996
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
6997
          if (is_sulfanyl (a_view, a_s))
6998
            fg[fg_thiocarboxylic_acid - 1] = true;
14179 bpr 6999
          if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
7000
      if (bond[get_bond (a_view, a_s) - 1].arom == false)
7001
                    fg[fg_thiocarboxylic_acid_ester - 1] = true;
7002
              if (bond[get_bond (a_view, a_s) - 1].ring_count > 0) {
7003
                      if (bond[get_bond (a_view, a_s) - 1].arom == true) {
7004
                        /*fg[fg_thiolactone_heteroarom] := true else fg[fg_thiolactone] := true; */
7005
                        fg[fg_thioxohetarene - 1] = true;
7006
                      }
7007
                      else
7008
                        fg[fg_thiolactone - 1] = true;
6785 bpr 7009
                    }
7010
            }
14179 bpr 7011
          }
7012
  }                             /* end Thioxo-C */
7013
  if (is_true_imino_C (a_view)) {
7014
    if (o_count == 1) {
7015
            if (bond[get_bond (a_view, a_o) - 1].arom == false)
7016
              fg[fg_carboxylic_acid_deriv - 1] = true;
7017
            if (is_alkoxy (a_view, a_o) || is_aryloxy (a_view, a_o)) {
6785 bpr 7018
              if (bond[get_bond (a_view, a_o) - 1].arom == false)
14179 bpr 7019
                      fg[fg_imido_ester - 1] = true;
6785 bpr 7020
            }
14179 bpr 7021
          }
7022
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == false)) {
7023
            if (bond[get_bond (a_view, a_n) - 1].arom == false)
7024
              fg[fg_carboxylic_acid_deriv - 1] = true;
7025
            if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n)) {
6785 bpr 7026
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 7027
                      fg[fg_carboxylic_acid_deriv - 1] = true;
6785 bpr 7028
              fg[fg_carboxylic_acid_amidine - 1] = true;
7029
            }
14179 bpr 7030
            if (is_hydrazino (a_view, a_n)) {
6785 bpr 7031
              if (bond[get_bond (a_view, a_n) - 1].arom == false)
14179 bpr 7032
                      fg[fg_carboxylic_acid_amidrazone - 1] = true;
6785 bpr 7033
            }
14179 bpr 7034
          }
7035
    if ((n_count == 1) && (bond[get_bond (a_view, a_n) - 1].arom == true))
7036
            /* catches also pyridazines, 1,2,3-triazines, etc. */
7037
          fg[fg_iminohetarene - 1] = true;
7038
    if (s_count == 1) {
7039
            if (bond[get_bond (a_view, a_s) - 1].arom == false)
7040
              fg[fg_carboxylic_acid_deriv - 1] = true;
7041
            if (is_alkylsulfanyl (a_view, a_s) || is_arylsulfanyl (a_view, a_s)) {
6785 bpr 7042
              if (bond[get_bond (a_view, a_s) - 1].arom == false)
14179 bpr 7043
                 fg[fg_imido_thioester - 1] = true;
6785 bpr 7044
            }
14179 bpr 7045
          }
7046
  }
7047
  if (is_hydroximino_C (a_view)) {
7048
    if (bond[get_bond (a_view, a_n) - 1].arom == false)
7049
            fg[fg_carboxylic_acid_deriv - 1] = true;
7050
      if (o_count == 1) {
7051
              if (is_hydroxy (a_view, a_o))
7052
                fg[fg_hydroxamic_acid - 1] = true;
7053
            }
6785 bpr 7054
    }
14179 bpr 7055
    if (!is_hydrazono_C (a_view))
7056
      return;
7057
    if (bond[get_bond (a_view, a_n) - 1].arom == false)
7058
      fg[fg_carboxylic_acid_deriv - 1] = true;
7059
    if (n_count == 1) {
7060
        if (is_amino (a_view, a_n) || is_subst_amino (a_view, a_n))
7061
          fg[fg_carboxylic_acid_amidrazone - 1] = true;
7062
  }
6785 bpr 7063
}
7064
 
14179 bpr 7065
static void chk_co2_sp2 (a_view, a_ref)
6785 bpr 7066
     int a_view, a_ref;
7067
{
7068
  int i;
7069
  neighbor_rec nb;
7070
  str2 nb_el;
7071
  int o_count = 0, or_count = 0, n_count = 0, nn_count = 0, nnx_count = 0,
7072
    s_count = 0, sr_count = 0;
7073
  int FORLIM;
7074
 
7075
  memset (nb, 0, sizeof (neighbor_rec));
7076
  get_neighbors (nb, a_view);
7077
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7078
  for (i = 0; i < FORLIM; i++) {
7079
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7080
           strcpy (nb_el, atom[nb[i] - 1].element);
7081
            if (strcmp (nb_el, "C ")) {
7082
              if (!strcmp (nb_el, "O ")) {
7083
                      o_count++;
7084
                      if (is_alkoxy (a_view, nb[i]) |
7085
                          is_alkenyloxy (a_view, nb[i]) || is_aryloxy (a_view,nb[i]))
7086
                        /* v0.3j */
7087
                        or_count++;
7088
                    }
7089
              if (!strcmp (nb_el, "N ")) {
7090
                      n_count++;
7091
                      if (is_hydrazino (a_view, nb[i]))
7092
                        nn_count++;
7093
                      if (is_subst_hydrazino (a_view, nb[i]))   /* more general... */
7094
                        nnx_count++;
7095
                    }
7096
              if (!strcmp (nb_el, "S ")) {
7097
                      s_count++;
7098
                      if (is_alkylsulfanyl (a_view, nb[i]) | is_arylsulfanyl (a_view, nb[i]))
7099
                        sr_count++;
7100
                    }
6785 bpr 7101
            }
14179 bpr 7102
          }
7103
  }
7104
  if (is_oxo_C (a_view)) {
7105
      if (o_count == 2) {
7106
              fg[fg_carbonic_acid_deriv - 1] = true;
7107
              if (or_count == 1)
7108
                fg[fg_carbonic_acid_monoester - 1] = true;
7109
              if (or_count == 2)
7110
                fg[fg_carbonic_acid_diester - 1] = true;
7111
            }
7112
      if (o_count == 1 && s_count == 1) {
7113
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7114
              if (or_count + sr_count == 1)
7115
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7116
              if (or_count + sr_count == 2)
7117
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7118
            }
7119
      if (s_count == 2) {
7120
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7121
              if (sr_count == 1)
7122
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7123
              if (sr_count == 2)
7124
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7125
            }
7126
      if (o_count == 1 && n_count == 1) {
7127
              fg[fg_carbamic_acid_deriv - 1] = true;
7128
              if (or_count == 0)
7129
                fg[fg_carbamic_acid - 1] = true;
7130
              if (or_count == 1)
7131
                fg[fg_carbamic_acid_ester - 1] = true;
7132
            }
7133
      if (s_count == 1 && n_count == 1) {
7134
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7135
              if (sr_count == 0)
7136
                fg[fg_thiocarbamic_acid - 1] = true;
7137
              if (sr_count == 1)
7138
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7139
            }
7140
      if (n_count == 2) {
7141
            if (nn_count == 1)
7142
              fg[fg_semicarbazide - 1] = true;
7143
            else {
6785 bpr 7144
              if (nnx_count == 0)       /* excludes semicarbazones */
14179 bpr 7145
                      fg[fg_urea - 1] = true;
6785 bpr 7146
            }
14179 bpr 7147
          }
7148
  }                             /* end Oxo-C */
7149
  if (is_thioxo_C (a_view)) {
7150
      if (o_count == 2) {
7151
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7152
              if (or_count == 1)
7153
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7154
              if (or_count == 2)
7155
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7156
            }
7157
      if (o_count == 1 && s_count == 1) {
7158
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7159
              if (or_count + sr_count == 1)
7160
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7161
              if (or_count + sr_count == 2)
7162
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7163
            }
7164
      if (s_count == 2) {
7165
              fg[fg_thiocarbonic_acid_deriv - 1] = true;
7166
              if (sr_count == 1)
7167
                fg[fg_thiocarbonic_acid_monoester - 1] = true;
7168
              if (sr_count == 2)
7169
                fg[fg_thiocarbonic_acid_diester - 1] = true;
7170
            }
7171
      if (o_count == 1 && n_count == 1) {
7172
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7173
              if (or_count == 0)
7174
                fg[fg_thiocarbamic_acid - 1] = true;
7175
              if (or_count == 1)
7176
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7177
            }
7178
      if (s_count == 1 && n_count == 1) {
7179
              fg[fg_thiocarbamic_acid_deriv - 1] = true;
7180
              if (sr_count == 0)
7181
                fg[fg_thiocarbamic_acid - 1] = true;
7182
              if (sr_count == 1)
7183
                fg[fg_thiocarbamic_acid_ester - 1] = true;
7184
            }
7185
      if (n_count == 2) {
7186
            if (nn_count == 1)
7187
              fg[fg_thiosemicarbazide - 1] = true;
7188
            else {
6785 bpr 7189
              if (nnx_count == 0)       /* excludes thiosemicarbazones */
14179 bpr 7190
                      fg[fg_thiourea - 1] = true;
6785 bpr 7191
            }
14179 bpr 7192
          }
7193
  }                             /* end Thioxo-C */
7194
  if (!(is_true_imino_C (a_view) &
7195
       (bond[get_bond (a_view, a_ref) - 1].arom == false))) {
6785 bpr 7196
      return;
14179 bpr 7197
  }                             /* end Imino-C */
6785 bpr 7198
  if (o_count == 1 && n_count == 1)
7199
    fg[fg_isourea - 1] = true;
7200
  if (s_count == 1 && n_count == 1)
7201
    fg[fg_isothiourea - 1] = true;
7202
  if (n_count == 2)
7203
    fg[fg_guanidine - 1] = true;
7204
}
7205
 
14179 bpr 7206
static void chk_co2_sp (a_view, a_ref)
6785 bpr 7207
     int a_view, a_ref;
7208
{
7209
  int i;
7210
  neighbor_rec nb;
7211
  str2 nb_el;
7212
  int o_count = 0, n_count = 0, s_count = 0;
7213
  int FORLIM;
7214
 
7215
  memset (nb, 0, sizeof (neighbor_rec));
7216
  get_neighbors (nb, a_view);
7217
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7218
  for (i = 0; i < FORLIM; i++) {
7219
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'D') {
7220
            strcpy (nb_el, atom[nb[i] - 1].element);
7221
            if (strcmp (nb_el, "C ")) {
6785 bpr 7222
              if (!strcmp (nb_el, "O "))
14179 bpr 7223
                      o_count++;
6785 bpr 7224
              if (!strcmp (nb_el, "N "))
14179 bpr 7225
                      n_count++;
6785 bpr 7226
              if (!strcmp (nb_el, "S "))
14179 bpr 7227
                      s_count++;
6785 bpr 7228
            }
14179 bpr 7229
          }
7230
  }
6785 bpr 7231
  if (o_count + s_count == 2)   /* new in v0.3b */
7232
    fg[fg_co2_deriv - 1] = true;
7233
  if (o_count == 1 && n_count == 1)
7234
    fg[fg_isocyanate - 1] = true;
7235
  if (s_count == 1 && n_count == 1)
7236
    fg[fg_isothiocyanate - 1] = true;
7237
  if (n_count == 2)
7238
    fg[fg_carbodiimide - 1] = true;
7239
}
7240
 
14179 bpr 7241
static void chk_triple (a1, a2)
6785 bpr 7242
     int a1, a2;
7243
{
7244
  str2 a1_el, a2_el;
7245
 
7246
  strcpy (a1_el, atom[a1 - 1].element);
7247
  strcpy (a2_el, atom[a2 - 1].element);
7248
  if ((!strcmp (a1_el, "C ") && !strcmp (a2_el, "C ")) &
7249
      (bond[get_bond (a1, a2) - 1].arom == false))
7250
    fg[fg_alkyne - 1] = true;
7251
  if (is_nitrile (a1, a2))
7252
    fg[fg_nitrile - 1] = true;
7253
  if (is_isonitrile (a1, a2))
7254
    fg[fg_isonitrile - 1] = true;
7255
  if (is_cyanate (a1, a2))
7256
    fg[fg_cyanate - 1] = true;
7257
  if (is_thiocyanate (a1, a2))
7258
    fg[fg_thiocyanate - 1] = true;
7259
}
7260
 
14179 bpr 7261
static void chk_ccx (a_view, a_ref)
6785 bpr 7262
     int a_view, a_ref;
7263
{
7264
  int i;
7265
  neighbor_rec nb;
7266
  int oh_count = 0, or_count = 0, n_count = 0;
7267
  int FORLIM;
7268
 
7269
  memset (nb, 0, sizeof (neighbor_rec));
7270
  get_neighbors (nb, a_ref);
7271
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7272
  for (i = 0; i < FORLIM; i++) {
7273
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
6785 bpr 7274
          if (is_hydroxy (a_ref, nb[i]))
7275
            oh_count++;
7276
          if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7277
              is_siloxy (a_ref, nb[i]))
7278
            or_count++;
7279
          if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7280
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7281
            n_count++;
14179 bpr 7282
          }
7283
  }
6785 bpr 7284
  if (oh_count == 1)
7285
    fg[fg_enol - 1] = true;
7286
  if (or_count == 1)
7287
    fg[fg_enolether - 1] = true;
7288
  if (n_count == 1)
7289
    fg[fg_enamine - 1] = true;
7290
  /* new in v0.2f   (regard anything else as an alkene) */
7291
  if (oh_count + or_count + n_count == 0)
7292
    fg[fg_alkene - 1] = true;
7293
}
7294
 
14179 bpr 7295
static void chk_xccx (a_view, a_ref)
6785 bpr 7296
     int a_view, a_ref;
7297
{
7298
  int i;
7299
  neighbor_rec nb;
7300
  int oh_count = 0, or_count = 0, n_count = 0;
7301
  int FORLIM;
7302
 
7303
  memset (nb, 0, sizeof (neighbor_rec));
7304
  get_neighbors (nb, a_view);
7305
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 7306
  for (i = 0; i < FORLIM; i++) {
7307
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
7308
            if (is_hydroxy (a_view, nb[i]))
7309
              oh_count++;
7310
            if (is_alkoxy (a_view, nb[i]) || is_aryloxy (a_view, nb[i]) |
7311
                is_siloxy (a_view, nb[i]))
7312
              or_count++;
7313
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7314
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7315
              n_count++;
7316
          }
7317
  }
6785 bpr 7318
  memset (nb, 0, sizeof (neighbor_rec));
7319
  get_neighbors (nb, a_ref);
7320
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7321
  for (i = 0; i < FORLIM; i++) {
7322
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
7323
            if (is_hydroxy (a_ref, nb[i]))
7324
              oh_count++;
7325
            if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7326
                is_siloxy (a_ref, nb[i]))
7327
              or_count++;
7328
            if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7329
                !strcmp (atom[nb[i] - 1].atype, "NAM"))
7330
              n_count++;
7331
          }
7332
  }
6785 bpr 7333
  if (oh_count == 2)
7334
    fg[fg_enediol - 1] = true;
7335
  /* new in v0.2f   (regard anything else as an alkene) */
7336
  if (oh_count + or_count + n_count == 0)
7337
    fg[fg_alkene - 1] = true;
7338
}
7339
 
14179 bpr 7340
static void chk_n_o_dbl (a1, a2)
6785 bpr 7341
     int a1, a2;
7342
{
7343
  int i;
7344
  neighbor_rec nb;
7345
  str2 nb_el;
7346
  int or_count = 0, n_count = 0, c_count = 0;
7347
  int b;                        /* v0.3j */
7348
  int het_count = 0;            /* v0.3k */
7349
  char bt;                      /* v0.3k */
7350
  float bo_sum = 0.0;           /* v0.3k */
7351
  int FORLIM;
7352
 
7353
  memset (nb, 0, sizeof (neighbor_rec));
7354
  get_neighbors (nb, a1);
7355
  FORLIM = atom[a1 - 1].neighbor_count;
7356
  /* v0.3k */
7357
  /* v0.3k */
14179 bpr 7358
  for (i = 0; i < FORLIM; i++) {
7359
    if (nb[i] != a2) {
7360
            b = get_bond (a1, nb[i]);   /* v0.3j */
7361
            strcpy (nb_el, atom[nb[i] - 1].element);
7362
            bt = bond[b - 1].btype;     /* v0.3k */
7363
            if (strcmp (nb_el, "C ") && strcmp (nb_el, "H ")
7364
                /*&&  strcmp (nb_el, "D ") */  && strcmp (nb_el, "DU")
7365
                && strcmp (nb_el, "LP") && bond[b - 1].arom == false)
7366
                /* added 'D ' in v0.3n */
7367
              het_count++;
7368
            /* v0.3k: ignore hetero atoms */
7369
            /* in aromatic rings like isoxazole  */
7370
            if (bt == 'S')
7371
              bo_sum += 1.0;
7372
            if (bt == 'D')
7373
              bo_sum += 2.0;
7374
            if (bt == 'A')
7375
              bo_sum += 1.5;
7376
            if (!strcmp (nb_el, "O "))
7377
              or_count++;
7378
            if (!strcmp (nb_el, "N "))
7379
              n_count++;
7380
            if (!strcmp (nb_el, "C ") && bond[b - 1].btype == 'S')      /* v0.3k */
7381
              c_count++;
7382
            /* if (is_alkyl(a1,nb[i])) or (is_aryl(a1,nb[i])) then inc(c_count); */
7383
          }
7384
  }
7385
  if (or_count + n_count + c_count == 1 && atom[a1 - 1].neighbor_count == 2) {
7386
    /* excludes nitro etc. */
7387
    if (or_count == 1)
7388
            fg[fg_nitrite - 1] = true;
7389
    if (c_count == 1)
7390
            fg[fg_nitroso_compound - 1] = true;
7391
    if (n_count == 1)           /* instead of nitrosamine  v0.3j */
7392
            fg[fg_nitroso_compound - 1] = true;
7393
    /*if (n_count = 1) then fg[fg_nitrosamine]   := true;  (* still missing */
7394
  }
6785 bpr 7395
  /*if ((c_count > 1) and (or_count = 0) and (n_count = 0)) then */
7396
  /*  begin */
7397
  /*    fg[fg_n_oxide] := true; */
7398
  /*  end; */
7399
  /* new approach in v0.3k */
7400
  if (het_count == 0 && bo_sum > 2)     /* =O does not count! */
7401
    fg[fg_n_oxide - 1] = true;
7402
}
7403
 
14179 bpr 7404
static void chk_sulfoxide (a1, a2)
6785 bpr 7405
     int a1, a2;
7406
{
7407
  int i;
7408
  neighbor_rec nb;
7409
  str2 nb_el;
7410
  int o_count = 0, c_count = 0;
7411
  int FORLIM;
7412
 
7413
  memset (nb, 0, sizeof (neighbor_rec));
7414
  get_neighbors (nb, a1);
7415
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7416
  for (i = 0; i < FORLIM; i++) {
7417
    strcpy (nb_el, atom[nb[i] - 1].element);
7418
    if (!strcmp (nb_el, "O "))
7419
            o_count++;
7420
    if (is_alkyl (a1, nb[i]) || is_aryl (a1, nb[i]))
7421
            c_count++;
7422
  }
6785 bpr 7423
  if (o_count == 1 && c_count == 2)
7424
    fg[fg_sulfoxide - 1] = true;
7425
}
7426
 
14179 bpr 7427
static void chk_double (a1, a2)
6785 bpr 7428
     int a1, a2;
7429
{
7430
  str2 a1_el, a2_el;
7431
 
7432
  strcpy (a1_el, atom[a1 - 1].element);
7433
  strcpy (a2_el, atom[a2 - 1].element);
7434
  if ((!strcmp (a1_el, "C ") && strcmp (a2_el, "C ")) &
14179 bpr 7435
      (bond[get_bond (a1, a2) - 1].arom == false)) {
7436
    if (hetbond_count (a1) == 2)
7437
            chk_carbonyl_deriv (a1, a2);
7438
    if (hetbond_count (a1) == 3)
7439
            chk_carboxyl_deriv (a1, a2);
7440
    if (hetbond_count (a1) == 4) {
7441
            if (!strcmp (atom[a1 - 1].atype, "C2 "))
7442
              chk_co2_sp2 (a1, a2);
7443
            if (!strcmp (atom[a1 - 1].atype, "C1 "))
7444
              chk_co2_sp (a1, a2);
7445
          }
7446
  }                             /* end C=X */
6785 bpr 7447
  if ((!strcmp (atom[a1 - 1].atype, "C2 ")
7448
       && !strcmp (atom[a2 - 1].atype,
14179 bpr 7449
                   "C2 ")) && (bond[get_bond (a1, a2) - 1].arom == false)) {
7450
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 2))
7451
            fg[fg_ketene_acetal_deriv - 1] = true;
7452
    if ((hetbond_count (a1) == 0) && (hetbond_count (a2) == 1))
7453
            chk_ccx (a1, a2);
7454
    if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
7455
            chk_xccx (a1, a2);
7456
    if (((hetbond_count (a1) == 0) && (hetbond_count (a2) == 0)) &&
7457
              atom[a1 - 1].arom == false && atom[a2 - 1].arom == false)
7458
            fg[fg_alkene - 1] = true;
7459
  }
7460
  if (((!strcmp (a1_el, "N ") && !strcmp (a2_el, "N "))
7461
      && (hetbond_count (a1) == 2) && (hetbond_count (a2) == 2)
7462
      && (bond[get_bond (a1, a2) - 1].arom == false))
6785 bpr 7463
      && atom[a1 - 1].neighbor_count == 2 && atom[a2 - 1].neighbor_count == 2)
7464
    fg[fg_azo_compound - 1] = true;
7465
  if (!strcmp (a1_el, "N ") && !strcmp (a2_el, "O "))
7466
    chk_n_o_dbl (a1, a2);
7467
  if (!strcmp (a1_el, "S ") && !strcmp (a2_el, "O "))
7468
    chk_sulfoxide (a1, a2);
7469
}
7470
 
14179 bpr 7471
static void chk_c_hal (a1, a2)
6785 bpr 7472
     int a1, a2;
7473
{
7474
  str2 a2_el;
7475
 
7476
  strcpy (a2_el, atom[a2 - 1].element);
7477
  fg[fg_halogen_deriv - 1] = true;
14179 bpr 7478
  if (atom[a1 - 1].arom) {
7479
    fg[fg_aryl_halide - 1] = true;
7480
    if (!strcmp (a2_el, "F "))
7481
            fg[fg_aryl_fluoride - 1] = true;
7482
    if (!strcmp (a2_el, "CL"))
7483
            fg[fg_aryl_chloride - 1] = true;
7484
    if (!strcmp (a2_el, "BR"))
7485
            fg[fg_aryl_bromide - 1] = true;
7486
    if (!strcmp (a2_el, "I "))
7487
            fg[fg_aryl_iodide - 1] = true;
7488
    return;
7489
  }
7490
  if ((strcmp (atom[a1 - 1].atype, "C3 ") == 0) && (hetbond_count (a1) <= 2)) {
7491
    /* alkyl halides */
7492
    fg[fg_alkyl_halide - 1] = true;
7493
    if (!strcmp (a2_el, "F "))
7494
            fg[fg_alkyl_fluoride - 1] = true;
7495
    if (!strcmp (a2_el, "CL"))
7496
            fg[fg_alkyl_chloride - 1] = true;
7497
    if (!strcmp (a2_el, "BR"))
7498
            fg[fg_alkyl_bromide - 1] = true;
7499
    if (!strcmp (a2_el, "I "))
7500
            fg[fg_alkyl_iodide - 1] = true;
7501
  }
7502
  if ((strcmp (atom[a1 - 1].atype, "C2 ") == 0) && (hetbond_count (a1) == 3)) {
7503
    /* acyl halides and related compounds */
7504
    if (is_oxo_C (a1)) {
7505
            fg[fg_acyl_halide - 1] = true;
7506
            if (!strcmp (a2_el, "F "))
7507
              fg[fg_acyl_fluoride - 1] = true;
7508
            if (!strcmp (a2_el, "CL"))
7509
              fg[fg_acyl_chloride - 1] = true;
7510
            if (!strcmp (a2_el, "BR"))
7511
              fg[fg_acyl_bromide - 1] = true;
7512
            if (!strcmp (a2_el, "I "))
7513
              fg[fg_acyl_iodide - 1] = true;
7514
          }
7515
    if (is_thioxo_C (a1))
7516
            fg[fg_thiocarboxylic_acid_deriv - 1] = true;
7517
    if (is_imino_C (a1))
7518
            fg[fg_imidoyl_halide - 1] = true;
7519
  }
7520
  if (!((strcmp (atom[a1 - 1].atype, "C2 ") == 0)
6785 bpr 7521
       && (hetbond_count (a1) == 4)))
7522
    /* chloroformates etc. */
7523
    return;
7524
  /* still missing: polyhalogen compounds (-CX2H, -CX3) */
7525
  fg[fg_co2_deriv - 1] = true;
14179 bpr 7526
  if (is_oxo_C (a1)) {
6785 bpr 7527
      fg[fg_carbonic_acid_deriv - 1] = true;
14179 bpr 7528
    if (is_alkoxycarbonyl (a2, a1) || is_aryloxycarbonyl (a2, a1))
7529
            fg[fg_carbonic_acid_ester_halide - 1] = true;
7530
    if (is_carbamoyl (a2, a1)) {
7531
            fg[fg_carbamic_acid_deriv - 1] = true;
7532
            fg[fg_carbamic_acid_halide - 1] = true;
7533
          }
7534
  }
6785 bpr 7535
  if (!is_thioxo_C (a1))
7536
    return;
7537
  fg[fg_thiocarbonic_acid_deriv - 1] = true;
7538
  if (is_alkoxythiocarbonyl (a2, a1) || is_aryloxythiocarbonyl (a2, a1))
7539
    fg[fg_thiocarbonic_acid_ester_halide - 1] = true;
14179 bpr 7540
  if (is_thiocarbamoyl (a2, a1)) {
7541
    fg[fg_thiocarbamic_acid_deriv - 1] = true;
7542
    fg[fg_thiocarbamic_acid_halide - 1] = true;
6785 bpr 7543
      /* end of non-aromatic halogen compounds */
14179 bpr 7544
  }
6785 bpr 7545
}
7546
 
14179 bpr 7547
static void chk_c_o (a1, a2)
6785 bpr 7548
     int a1, a2;
7549
{
7550
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
7551
  if (bond[get_bond (a1, a2) - 1].arom == true)
7552
    return;
14179 bpr 7553
  if (is_true_alkyl (a2, a1) && is_hydroxy (a1, a2)) {
7554
    fg[fg_hydroxy - 1] = true;
7555
    fg[fg_alcohol - 1] = true;
7556
    if (atom[a1 - 1].neighbor_count <= 2)
7557
            fg[fg_prim_alcohol - 1] = true;
7558
    if (atom[a1 - 1].neighbor_count == 3)
7559
            fg[fg_sec_alcohol - 1] = true;
7560
    if (atom[a1 - 1].neighbor_count == 4)
7561
            fg[fg_tert_alcohol - 1] = true;
7562
  }
7563
  if (is_aryl (a2, a1) && is_hydroxy (a1, a2)) {
7564
    fg[fg_hydroxy - 1] = true;
7565
    fg[fg_phenol - 1] = true;
7566
  }
7567
  if (is_true_alkyl (a2, a1) && is_true_alkoxy (a1, a2)) {
7568
    fg[fg_ether - 1] = true;
7569
    fg[fg_dialkylether - 1] = true;
7570
  }
6785 bpr 7571
  if ((is_true_alkyl (a2, a1) && is_aryloxy (a1, a2)) |
14179 bpr 7572
      (is_aryl (a2, a1) && is_true_alkoxy (a1, a2))) {
7573
    fg[fg_ether - 1] = true;
7574
    fg[fg_alkylarylether - 1] = true;
7575
  }
7576
  if (is_aryl (a2, a1) && is_aryloxy (a1, a2)) {
7577
    fg[fg_ether - 1] = true;
7578
    fg[fg_diarylether - 1] = true;
7579
  }
7580
  if ((is_true_alkyl (a2, a1) || is_aryl (a2, a1)) && is_alkynyloxy (a1, a2)) {
7581
    fg[fg_ether - 1] = true;
7582
    ether_generic = true;
7583
  }
7584
  if (is_alkynyl (a2, a1) && is_hydroxy (a1, a2)) {
7585
    fg[fg_hydroxy - 1] = true;
7586
    hydroxy_generic = true;
7587
  }
6785 bpr 7588
}
7589
 
14179 bpr 7590
static void chk_c_s (a1, a2)
6785 bpr 7591
     int a1, a2;
7592
{
7593
  int i;
7594
  neighbor_rec nb;
7595
  str2 nb_el;
7596
  int o_count = 0, oh_count = 0, or_count = 0, n_count = 0, c_count = 0,
7597
    hal_count = 0;
7598
  int FORLIM;
7599
 
7600
  /* ignore heteroaromatic rings (like furan, thiophene, etc.) */
7601
  if (bond[get_bond (a1, a2) - 1].arom == true)
7602
    return;
14179 bpr 7603
  if (is_alkyl (a2, a1) && is_sulfanyl (a1, a2)) {
7604
    fg[fg_thiol - 1] = true;
7605
    fg[fg_alkylthiol - 1] = true;
7606
  }
7607
  if (is_aryl (a2, a1) && is_sulfanyl (a1, a2)) {
7608
    fg[fg_thiol - 1] = true;
7609
    fg[fg_arylthiol - 1] = true;
7610
  }
6785 bpr 7611
  if (is_true_alkyl (a2, a1) && is_true_alkylsulfanyl (a1, a2))
7612
    fg[fg_thioether - 1] = true;
7613
  if ((is_true_alkyl (a2, a1) && is_arylsulfanyl (a1, a2)) |
14179 bpr 7614
        (is_aryl (a2, a1) && is_true_alkylsulfanyl (a1, a2)))
6785 bpr 7615
    fg[fg_thioether - 1] = true;
7616
  if (is_aryl (a2, a1) && is_arylsulfanyl (a1, a2))
7617
    fg[fg_thioether - 1] = true;
7618
  /* check for sulfinic/sulfenic acid derivatives */
7619
  memset (nb, 0, sizeof (neighbor_rec));
7620
  get_neighbors (nb, a2);
7621
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7622
  for (i = 0; i < FORLIM; i++) {
7623
    strcpy (nb_el, atom[nb[i] - 1].element);
7624
    if (is_alkyl (a2, nb[i]) || is_aryl (a2, nb[i]))
7625
            c_count++;
7626
    if (is_hydroxy (a2, nb[i]))
7627
            oh_count++;
7628
    if (is_alkoxy (a2, nb[i]) || is_aryloxy (a2, nb[i]))
7629
            or_count++;
7630
    if (is_amino (a2, nb[i]) || is_subst_amino (a2, nb[i]))
7631
            n_count++;
7632
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7633
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I "))
7634
            hal_count++;
7635
    if (!strcmp (nb_el, "O "))
7636
            o_count++;
7637
  }
6785 bpr 7638
  if (c_count != 1)
7639
    return;
14179 bpr 7640
  if (atom[a2 - 1].neighbor_count == 3 && o_count - oh_count - or_count == 1) {
7641
    /* sulfinic acid && derivs */
7642
    fg[fg_sulfinic_acid_deriv - 1] = true;
7643
    if (oh_count == 1)
7644
            fg[fg_sulfinic_acid - 1] = true;
7645
    if (or_count == 1)
7646
            fg[fg_sulfinic_acid_ester - 1] = true;
7647
    if (hal_count == 1)
7648
            fg[fg_sulfinic_acid_halide - 1] = true;
7649
    if (n_count == 1)
7650
            fg[fg_sulfinic_acid_amide - 1] = true;
7651
  }
6785 bpr 7652
  if (atom[a2 - 1].neighbor_count != 2 || o_count - oh_count - or_count != 0)
7653
    /* sulfenic acid && derivs */
7654
    return;
7655
 
7656
  fg[fg_sulfenic_acid_deriv - 1] = true;
7657
  if (oh_count == 1)
7658
    fg[fg_sulfenic_acid - 1] = true;
7659
  if (or_count == 1)
7660
    fg[fg_sulfenic_acid_ester - 1] = true;
7661
  if (hal_count == 1)
7662
    fg[fg_sulfenic_acid_halide - 1] = true;
7663
  if (n_count == 1)
7664
    fg[fg_sulfenic_acid_amide - 1] = true;
7665
}
7666
 
14179 bpr 7667
static void chk_c_n (a1, a2)
6785 bpr 7668
     int a1, a2;
7669
{
7670
  /* ignore heteroaromatic rings (like furan, thiophene, pyrrol, etc.) */
7671
  if (atom[a2 - 1].arom == true)
7672
    return;
14179 bpr 7673
  if (is_true_alkyl (a2, a1) && is_amino (a1, a2)) {
7674
    fg[fg_amine - 1] = true;
7675
    fg[fg_prim_amine - 1] = true;
7676
    fg[fg_prim_aliph_amine - 1] = true;
6785 bpr 7677
    }
14179 bpr 7678
  if (is_aryl (a2, a1) && is_amino (a1, a2)) {
7679
    fg[fg_amine - 1] = true;
7680
    fg[fg_prim_amine - 1] = true;
7681
    fg[fg_prim_arom_amine - 1] = true;
7682
  }
7683
  if (is_true_alkyl (a2, a1) && is_true_alkylamino (a1, a2)) {
7684
    fg[fg_amine - 1] = true;
7685
    fg[fg_sec_amine - 1] = true;
7686
    fg[fg_sec_aliph_amine - 1] = true;
7687
  }
7688
  if (is_aryl (a2, a1) && is_true_alkylamino (a1, a2)) {
7689
    fg[fg_amine - 1] = true;
7690
    fg[fg_sec_amine - 1] = true;
7691
    fg[fg_sec_mixed_amine - 1] = true;
7692
  }
7693
  if (is_aryl (a2, a1) && is_arylamino (a1, a2)) {
7694
    fg[fg_amine - 1] = true;
7695
    fg[fg_sec_amine - 1] = true;
7696
    fg[fg_sec_arom_amine - 1] = true;
7697
  }
7698
  if (is_true_alkyl (a2, a1) && is_true_dialkylamino (a1, a2)) {
7699
    fg[fg_amine - 1] = true;
7700
    fg[fg_tert_amine - 1] = true;
7701
    fg[fg_tert_aliph_amine - 1] = true;
7702
  }
6785 bpr 7703
  if ((is_true_alkyl (a2, a1) && is_diarylamino (a1, a2)) |
14179 bpr 7704
      (is_aryl (a2, a1) && is_true_dialkylamino (a1, a2))) {
7705
    fg[fg_amine - 1] = true;
7706
    fg[fg_tert_amine - 1] = true;
7707
    fg[fg_tert_mixed_amine - 1] = true;
7708
  }
7709
  if (is_aryl (a2, a1) && is_diarylamino (a1, a2)) {
7710
    fg[fg_amine - 1] = true;
7711
    fg[fg_tert_amine - 1] = true;
7712
    fg[fg_tert_arom_amine - 1] = true;
7713
  }
6785 bpr 7714
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
14179 bpr 7715
       is_alkynyl (a2, a1)) && is_hydroxylamino (a1, a2) && (is_acyl_gen (a2, a1) == false))
6785 bpr 7716
    /* v0.3k */
7717
    fg[fg_hydroxylamine - 1] = true;
7718
  /* v0.3k */
7719
  /* v0.3k  */
7720
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_acyl (a2, a1) |
7721
       is_alkenyl (a2, a1) || is_alkynyl (a2, a1)) && is_hydrazino (a1, a2))
7722
    fg[fg_hydrazine - 1] = true;
7723
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7724
       is_alkynyl (a2, a1)) && is_azido (a1, a2))
7725
    /* v0.3k */
7726
    fg[fg_azide - 1] = true;
7727
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7728
       is_alkynyl (a2, a1)) && is_diazonium (a1, a2))
7729
    /* v0.3k */
7730
    fg[fg_diazonium_salt - 1] = true;
7731
  if ((is_alkyl (a2, a1) || is_aryl (a2, a1) || is_alkenyl (a2, a1) |
7732
       is_alkynyl (a2, a1)) && is_nitro (a1, a2))
7733
    /* v0.3k */
7734
    fg[fg_nitro_compound - 1] = true;
7735
  if (is_alkynyl (a2, a1) &
14179 bpr 7736
        (is_amino (a1, a2) || is_C_monosubst_amino (a1, a2) |
7737
       (is_C_disubst_amino (a1, a2) && (!is_acylamino (a1, a2))))) {
6785 bpr 7738
      fg[fg_amine - 1] = true;
7739
      amine_generic = true;
14179 bpr 7740
  }
6785 bpr 7741
}
7742
 
14179 bpr 7743
static void chk_c_c (a1, a2)
6785 bpr 7744
     int a1, a2;
7745
{
7746
  int i;
7747
  neighbor_rec nb;
7748
  int oh_count, nhr_count, FORLIM;
7749
 
7750
  /* ignore aromatic rings */
7751
  if (atom[a2 - 1].arom == true)
7752
    return;
7753
  /*check for 1,2-diols and 1,2-aminoalcoholes */
7754
  if (!strcmp (atom[a1 - 1].atype, "C3 ")
14179 bpr 7755
        && !strcmp (atom[a2 - 1].atype, "C3 ")) {
7756
      if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1)) {
7757
            oh_count = 0;
7758
            nhr_count = 0;
7759
            memset (nb, 0, sizeof (neighbor_rec));
7760
            get_neighbors (nb, a1);
7761
            FORLIM = atom[a1 - 1].neighbor_count;
7762
            for (i = 0; i < FORLIM; i++) {
7763
              if (nb[i] != a2) {
7764
                      if (is_hydroxy (a1, nb[i]))
7765
                        oh_count++;
7766
                      if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7767
                        is_arylamino (a1, nb[i]))
7768
                      nhr_count++;
7769
                    }
6785 bpr 7770
            }
14179 bpr 7771
            memset (nb, 0, sizeof (neighbor_rec));
7772
            get_neighbors (nb, a2);
7773
            FORLIM = atom[a2 - 1].neighbor_count;
7774
            for (i = 0; i < FORLIM; i++) {
7775
              if (nb[i] != a1) {
7776
                      if (is_hydroxy (a2, nb[i]))
7777
                        oh_count++;
7778
                      if (is_amino (a2, nb[i]) || is_alkylamino (a2, nb[i]) |
7779
                          is_arylamino (a2, nb[i]))
7780
                        nhr_count++;
7781
                    }
6785 bpr 7782
            }
14179 bpr 7783
            if (oh_count == 2)
7784
              fg[fg_1_2_diol - 1] = true;
7785
            if (oh_count == 1 && nhr_count == 1)
7786
              fg[fg_1_2_aminoalcohol - 1] = true;
7787
          }
7788
  }
6785 bpr 7789
  /* check for alpha-aminoacids and alpha-hydroxyacids */
7790
  if (strcmp (atom[a1 - 1].atype, "C3 ")
7791
      || strcmp (atom[a2 - 1].atype, "C2 "))
7792
    return;
7793
  if (!((hetbond_count (a1) == 1) && (hetbond_count (a2) == 3)))
7794
    return;
7795
  oh_count = 0;
7796
  nhr_count = 0;
7797
  memset (nb, 0, sizeof (neighbor_rec));
7798
  get_neighbors (nb, a1);
7799
  FORLIM = atom[a1 - 1].neighbor_count;
14179 bpr 7800
  for (i = 0; i < FORLIM; i++) {
7801
    if (nb[i] != a2) {
7802
            if (is_hydroxy (a1, nb[i]))
7803
              oh_count++;
7804
            if (is_amino (a1, nb[i]) || is_alkylamino (a1, nb[i]) |
7805
                is_arylamino (a1, nb[i]))
7806
              nhr_count++;
7807
          }
7808
  }
6785 bpr 7809
  memset (nb, 0, sizeof (neighbor_rec));
7810
  get_neighbors (nb, a2);
7811
  FORLIM = atom[a2 - 1].neighbor_count;
14179 bpr 7812
  for (i = 0; i < FORLIM; i++) {
7813
    if (nb[i] != a1) {
7814
            if (is_hydroxy (a2, nb[i]))
7815
              oh_count++;
7816
          }
7817
  }
6785 bpr 7818
  if ((oh_count == 2) && is_oxo_C (a2))
7819
    fg[fg_alpha_hydroxyacid - 1] = true;
7820
  if ((oh_count == 1 && nhr_count == 1) && is_oxo_C (a2))
7821
    fg[fg_alpha_aminoacid - 1] = true;
7822
}
7823
 
14179 bpr 7824
static void chk_x_y_single (a_view, a_ref)
6785 bpr 7825
     int a_view, a_ref;
7826
{
7827
  if (!strcmp (atom[a_view - 1].atype, "O3 ") &&
14179 bpr 7828
        !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7829
    if (is_hydroxy (a_ref, a_view) || is_hydroxy (a_view, a_ref))
7830
            fg[fg_hydroperoxide - 1] = true;
7831
    if ((is_alkoxy (a_ref, a_view) || is_aryloxy (a_ref, a_view) |
7832
              is_siloxy (a_ref, a_view)) && (is_alkoxy (a_view,a_ref) |
7833
                        is_aryloxy (a_view, a_ref) |
7834
                        is_siloxy (a_view, a_ref)))
7835
            fg[fg_peroxide - 1] = true;
7836
  }                             /* still missing: peracid */
6785 bpr 7837
  if (!strcmp (atom[a_view - 1].atype, "S3 ") &&
14179 bpr 7838
      !strcmp (atom[a_ref - 1].atype, "S3 ")) {
6785 bpr 7839
      if (atom[a_view - 1].neighbor_count == 2 &&
7840
          atom[a_ref - 1].neighbor_count == 2)
14179 bpr 7841
          fg[fg_disulfide - 1] = true;
7842
  }
6785 bpr 7843
  if ((!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7844
       !strcmp (atom[a_ref - 1].element, "N ")) && (hetbond_count (a_view) == 1)
7845
      && (hetbond_count (a_ref) == 1)) {
6785 bpr 7846
      /*if ((is_amino(a_ref,a_view)) or  */
7847
      /*    (is_subst_amino(a_ref,a_view)) or */
7848
      /*    (is_acylamino(a_ref,a_view))) and */
7849
      /*   ((is_amino(a_view,a_ref)) or  */
7850
      /*    (is_subst_amino(a_view,a_ref)) or */
7851
      /*    (is_acylamino(a_ref,a_view))) then  */
7852
      if (bond[get_bond (a_view, a_ref) - 1].arom == false)
14179 bpr 7853
              fg[fg_hydrazine - 1] = true;
7854
  }
6785 bpr 7855
  if (!strcmp (atom[a_view - 1].element, "N ") &&
14179 bpr 7856
      !strcmp (atom[a_ref - 1].atype, "O3 ")) {
7857
    /* bond is in "opposite" direction */
7858
    if ((is_alkoxy (a_view, a_ref) || is_aryloxy (a_view, a_ref)) &
7859
              is_nitro (a_ref, a_view))
7860
            fg[fg_nitrate - 1] = true;
7861
    if ((is_nitro (a_ref, a_view) == false
7862
              && atom[a_view - 1].arom == false) && (is_amino (a_ref, a_view) |
7863
                    is_subst_amino (a_ref, a_view)) &
7864
              (is_acylamino (a_ref, a_view) == false))
7865
            fg[fg_hydroxylamine - 1] = true;    /* new in v0.3c */
7866
  }
6785 bpr 7867
  if (!strcmp (atom[a_view - 1].element, "S ") &&
7868
      !strcmp (atom[a_ref - 1].element, "O "))
7869
    chk_sulfoxide (a_view, a_ref);
7870
}
7871
 
14179 bpr 7872
static void chk_single (a1, a2)
6785 bpr 7873
     int a1, a2;
7874
{
7875
  str2 a1_el, a2_el;
7876
 
7877
  strcpy (a1_el, atom[a1 - 1].element);
7878
  strcpy (a2_el, atom[a2 - 1].element);
7879
  if (!strcmp (a1_el, "C ") &&
7880
      (!strcmp (a2_el, "F ") || !strcmp (a2_el, "CL")
7881
       || !strcmp (a2_el, "BR") || !strcmp (a2_el, "I ")))
7882
    chk_c_hal (a1, a2);
7883
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "O "))
7884
    chk_c_o (a1, a2);
7885
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "S "))
7886
    chk_c_s (a1, a2);
7887
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "N "))
7888
    chk_c_n (a1, a2);
14179 bpr 7889
  if ((strcmp (a1_el, "C ") == 0) && atom[a2 - 1].metal && (is_cyano_c (a1) == false)) {
6785 bpr 7890
      fg[fg_organometallic - 1] = true;
7891
      if (!strcmp (a2_el, "LI"))
14179 bpr 7892
              fg[fg_organolithium - 1] = true;
6785 bpr 7893
      if (!strcmp (a2_el, "MG"))
14179 bpr 7894
              fg[fg_organomagnesium - 1] = true;
7895
  }
6785 bpr 7896
  if (!strcmp (a1_el, "C ") && !strcmp (a2_el, "C "))
7897
    chk_c_c (a1, a2);
7898
  if (strcmp (a1_el, "C ") && strcmp (a2_el, "C "))
7899
    chk_x_y_single (a1, a2);
7900
}
7901
 
14179 bpr 7902
static void chk_carbonyl_deriv_sp3 (a_ref)
6785 bpr 7903
     int a_ref;
7904
{
7905
  int i;
7906
  neighbor_rec nb;
7907
  int oh_count = 0, or_count = 0, n_count = 0, sh_count = 0, sr_count = 0;
7908
  int FORLIM;
7909
 
7910
  memset (nb, 0, sizeof (neighbor_rec));
7911
  get_neighbors (nb, a_ref);
7912
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7913
  for (i = 0; i < FORLIM; i++) {
7914
    if (is_hydroxy (a_ref, nb[i]))
7915
            oh_count++;
7916
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7917
              is_alkenyloxy (a_ref, nb[i]) || is_alkynyloxy (a_ref, nb[i]))
7918
            or_count++;
7919
    if (is_sulfanyl (a_ref, nb[i]))
7920
            sh_count++;
7921
    if (is_alkylsulfanyl (a_ref, nb[i]) || is_arylsulfanyl (a_ref, nb[i]) |
7922
              is_alkenylsulfanyl (a_ref, nb[i]) || is_alkynylsulfanyl (a_ref, nb[i]))
7923
            sr_count++;
7924
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") || !strcmp (atom[nb[i] - 1].atype, "NAM"))
7925
            n_count++;
7926
  }
6785 bpr 7927
  if (oh_count == 2)
7928
    fg[fg_carbonyl_hydrate - 1] = true;
7929
  if (oh_count == 1 && or_count == 1)
7930
    fg[fg_hemiacetal - 1] = true;
7931
  if (or_count == 2)
7932
    fg[fg_acetal - 1] = true;
7933
  if ((oh_count == 1 || or_count == 1) && n_count == 1)
7934
    fg[fg_hemiaminal - 1] = true;
7935
  if (n_count == 2)
7936
    fg[fg_aminal - 1] = true;
7937
  if ((sh_count == 1 || sr_count == 1) && n_count == 1)
7938
    fg[fg_thiohemiaminal - 1] = true;
7939
  if (sr_count == 2 || (or_count == 1 && sr_count == 1))
7940
    fg[fg_thioacetal - 1] = true;
7941
}
7942
 
14179 bpr 7943
static void chk_carboxyl_deriv_sp3 (a_ref)
6785 bpr 7944
     int a_ref;
7945
{
7946
  int i;
7947
  neighbor_rec nb;
7948
  int or_count = 0, oh_count = 0, n_count = 0;  /* oh_count new in v0.3c */
7949
  int electroneg_count = 0;     /* new in v0.3j */
7950
  int hal_count = 0;
7951
  str2 nb_el;
7952
  int FORLIM;
7953
 
7954
  memset (nb, 0, sizeof (neighbor_rec));
7955
  get_neighbors (nb, a_ref);
7956
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7957
  for (i = 0; i < FORLIM; i++) {
7958
    strcpy (nb_el, atom[nb[i] - 1].element);    /* v0.3j */
7959
    if (is_electroneg (nb_el))
7960
            electroneg_count++;
7961
    if (!strcmp (nb_el, "F ") || !strcmp (nb_el, "CL") ||
7962
              !strcmp (nb_el, "BR") || !strcmp (nb_el, "I ")
7963
              || !strcmp (nb_el, "AT"))
7964
            hal_count++;
7965
    if (is_alkoxy (a_ref, nb[i]) || is_aryloxy (a_ref, nb[i]) |
7966
              is_siloxy (a_ref, nb[i]))
7967
            or_count++;
7968
    if (is_hydroxy (a_ref, nb[i]))      /* new in v0.3c    */
7969
            oh_count++;
7970
    if (!strcmp (atom[nb[i] - 1].atype, "N3 ") ||
7971
              !strcmp (atom[nb[i] - 1].atype, "NAM"))
7972
            n_count++;
7973
  }
6785 bpr 7974
  /*if (or_count + n_count > 1) then fg[fg_orthocarboxylic_acid_deriv] := true;  (* until v0.3i */
7975
  if (electroneg_count == 3 && hal_count < 3)   /* v0.3j */
7976
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
7977
  if (or_count == 3)
7978
    fg[fg_carboxylic_acid_orthoester - 1] = true;
7979
  if (or_count == 2 && n_count == 1)
7980
    fg[fg_carboxylic_acid_amide_acetal - 1] = true;
7981
  if (oh_count > 0 && oh_count + or_count + n_count == 3)       /* new in v0.3c */
7982
    fg[fg_orthocarboxylic_acid_deriv - 1] = true;
7983
}
7984
 
14179 bpr 7985
static void chk_anhydride (a_ref)
6785 bpr 7986
     int a_ref;
7987
{
7988
  int i;
7989
  neighbor_rec nb;
7990
  int acyl_count = 0;
7991
  int FORLIM;
7992
 
7993
  memset (nb, 0, sizeof (neighbor_rec));
7994
  get_neighbors (nb, a_ref);
7995
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 7996
  for (i = 0; i < FORLIM; i++) {
7997
    if (is_acyl (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))
7998
            acyl_count++;
7999
  }
8000
  if (acyl_count == 2 && !strcmp (atom[a_ref - 1].atype, "O3 ")) {
8001
    fg[fg_carboxylic_acid_deriv - 1] = true;
8002
    fg[fg_carboxylic_acid_anhydride - 1] = true;
8003
  }
6785 bpr 8004
}
8005
 
14179 bpr 8006
static void chk_imide (a_ref)
6785 bpr 8007
     int a_ref;
8008
{
8009
  int i;
8010
  neighbor_rec nb;
8011
  int acyl_count = 0;
8012
  int FORLIM;
8013
 
8014
  memset (nb, 0, sizeof (neighbor_rec));
8015
  get_neighbors (nb, a_ref);
8016
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 8017
  for (i = 0; i < FORLIM; i++) {
8018
    if (is_acyl_gen (a_ref, nb[i]) || is_carbamoyl (a_ref, nb[i]))      /* v0.3j */
8019
            acyl_count++;
8020
  }
6785 bpr 8021
  if (acyl_count < 2 || strcmp (atom[a_ref - 1].element, "N "))
8022
    /* v0.3j: accept also N-acyl-imides */
8023
    return;
8024
  fg[fg_carboxylic_acid_deriv - 1] = true;
8025
  fg[fg_carboxylic_acid_imide - 1] = true;
8026
  if (atom[a_ref - 1].neighbor_count == 2)
8027
    fg[fg_carboxylic_acid_unsubst_imide - 1] = true;
8028
  if (atom[a_ref - 1].neighbor_count == 3)
8029
    fg[fg_carboxylic_acid_subst_imide - 1] = true;
8030
}
8031
 
14179 bpr 8032
static void chk_12diphenol (a_view, a_ref)
6785 bpr 8033
     int a_view, a_ref;
8034
{
8035
  int i;
8036
  neighbor_rec nb;
8037
  int oh_count = 0;
8038
  int FORLIM;
8039
 
8040
  memset (nb, 0, sizeof (neighbor_rec));
8041
  get_neighbors (nb, a_view);
8042
  FORLIM = atom[a_view - 1].neighbor_count;
14179 bpr 8043
  for (i = 0; i < FORLIM; i++) {
8044
    if (bond[get_bond (a_view, nb[i]) - 1].btype == 'S') {
8045
            if (is_hydroxy (a_view, nb[i]))
8046
              oh_count++;
8047
          }
8048
  }
6785 bpr 8049
  memset (nb, 0, sizeof (neighbor_rec));
8050
  get_neighbors (nb, a_ref);
8051
  FORLIM = atom[a_ref - 1].neighbor_count;
14179 bpr 8052
  for (i = 0; i < FORLIM; i++) {
8053
    if (bond[get_bond (a_ref, nb[i]) - 1].btype == 'S') {
8054
            if (is_hydroxy (a_ref, nb[i]))
8055
              oh_count++;
8056
          }
8057
  }
6785 bpr 8058
  if (oh_count == 2)
8059
    fg[fg_1_2_diphenol - 1] = true;
8060
}
8061
 
14179 bpr 8062
static void chk_arom_fg (a1, a2)
6785 bpr 8063
     int a1, a2;
8064
{
8065
  if ((hetbond_count (a1) == 1) && (hetbond_count (a2) == 1))
8066
    chk_12diphenol (a1, a2);
8067
}
8068
 
14179 bpr 8069
static boolean is_arene (r_id)
6785 bpr 8070
     int r_id;
8071
{
8072
  int i, j;
8073
  boolean r = true;
8074
  ringpath_type testring;
8075
  int ring_size, a_prev, a_ref;
8076
 
8077
/* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
8078
  if (r_id < 1 || r_id > n_rings)
8079
    return false;
8080
  memset (testring, 0, sizeof (ringpath_type));
8081
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8082
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8083
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8084
    testring[j] = ring[r_id - 1][j];
8085
  /*ring_size := path_length(testring); */
8086
  if (ring_size <= 2)
8087
    return false;
8088
  a_prev = testring[ring_size - 1];
14179 bpr 8089
  for (i = 0; i < ring_size; i++) {
8090
    a_ref = testring[i];
8091
    if (bond[get_bond (a_prev, a_ref) - 1].arom == false)
8092
            r = false;
8093
    a_prev = a_ref;
8094
  }
6785 bpr 8095
  return r;
8096
}
8097
 
14179 bpr 8098
static boolean is_heterocycle (r_id)
6785 bpr 8099
     int r_id;
8100
{
8101
  int i, j;
8102
  boolean r = false;
8103
  ringpath_type testring;
8104
  int ring_size, a_ref;
8105
 
8106
  if (r_id < 1 || r_id > n_rings)
8107
    return false;
8108
  memset (testring, 0, sizeof (ringpath_type));
8109
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8110
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8111
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8112
    testring[j] = ring[r_id - 1][j];
8113
  /*ring_size := path_length(testring); */
8114
  if (ring_size <= 2)
8115
    return false;
14179 bpr 8116
  for (i = 0; i < ring_size; i++) {
8117
    a_ref = testring[i];
8118
    if (strcmp (atom[a_ref - 1].element, "C "))
8119
            r = true;
8120
  }
6785 bpr 8121
  return r;
8122
}
8123
 
14179 bpr 8124
static void chk_oxo_thioxo_imino_hetarene (r_id)
6785 bpr 8125
     int r_id;
8126
{
8127
  int i, j;
8128
  ringpath_type testring;
8129
  int ring_size, a_ref;
8130
 
8131
  if (r_id < 1 || r_id > n_rings)
8132
    return;
8133
  memset (testring, 0, sizeof (ringpath_type));
8134
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
8135
  /*for j := 1 to max_ringsize do if ring^[r_id,j] > 0 then testring[j] := ring^[r_id,j]; */
8136
  for (j = 0; j < ring_size; j++)       /* v0.3j */
8137
    testring[j] = ring[r_id - 1][j];
8138
  /*ring_size := path_length(testring); */
8139
  /*if (is_arene(r_id)) and (odd(ring_size) = false) then */
8140
  if (!is_arene (r_id))         /* v0.3j */
8141
    return;
14179 bpr 8142
  for (i = 0; i < ring_size; i++) {
8143
    a_ref = testring[i];
8144
    if (is_oxo_C (a_ref))
8145
            fg[fg_oxohetarene - 1] = true;
8146
    if (is_thioxo_C (a_ref))
8147
            fg[fg_thioxohetarene - 1] = true;
8148
    if (is_true_exocyclic_imino_C (a_ref, r_id))        /* v0.3j */
8149
            fg[fg_iminohetarene - 1] = true;
8150
  }
6785 bpr 8151
}
8152
 
14179 bpr 8153
static void chk_ion (a_ref)
6785 bpr 8154
     int a_ref;
8155
{
8156
  int i;
8157
  neighbor_rec nb;
8158
  int charge, FORLIM;
8159
 
8160
  memset (nb, 0, sizeof (neighbor_rec));
8161
  get_neighbors (nb, a_ref);
8162
  charge = atom[a_ref - 1].formal_charge;
8163
  if (charge == 0)
8164
    /* check if charge is neutralized by an adjacent opposite charge */
8165
    return;
8166
  FORLIM = atom[a_ref - 1].neighbor_count;
8167
  for (i = 0; i < FORLIM; i++)
8168
    charge += atom[nb[i] - 1].formal_charge;
8169
  if (charge > 0)
8170
    fg[fg_cation - 1] = true;
8171
  if (charge < 0)
8172
    fg[fg_anion - 1] = true;
8173
}
8174
 
14179 bpr 8175
static void chk_functionalgroups ()
6785 bpr 8176
{
8177
  int i, a1, a2;
8178
  char bt;
8179
  int pos_chg = 0, neg_chg = 0;
8180
  int FORLIM;
8181
 
8182
  if (n_atoms < 1 || n_bonds < 1)
8183
    return;
8184
  FORLIM = n_atoms;
14179 bpr 8185
  for (i = 1; i <= FORLIM; i++) {                               /* a few groups are best discovered in the atom list */
8186
    if (!strcmp (atom[i - 1].atype, "SO2"))
8187
            chk_so2_deriv (i);
8188
    /*if (atom^[i].atype = 'SO ') then fg[fg_sulfoxide] := true;  (* do another check in the bond list!! */
8189
    if (!strcmp (atom[i - 1].element, "P "))
8190
            chk_p_deriv (i);
8191
    if (!strcmp (atom[i - 1].element, "B "))
8192
            chk_b_deriv (i);
8193
    if (!strcmp (atom[i - 1].atype, "N3+") || atom[i - 1].formal_charge > 0)
8194
            chk_ammon (i);
8195
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 2))
8196
            chk_carbonyl_deriv_sp3 (i);
8197
    if ((strcmp (atom[i - 1].atype, "C3 ") == 0) && (hetbond_count (i) == 3))
8198
            chk_carboxyl_deriv_sp3 (i);
8199
    if (!strcmp (atom[i - 1].atype, "O3 ") && atom[i - 1].neighbor_count == 2)
8200
            chk_anhydride (i);
8201
    if ((!strcmp (atom[i - 1].atype, "N3 ") || !strcmp (atom[i - 1].atype, "NAM"))
8202
              && atom[i - 1].neighbor_count >= 2)
8203
            chk_imide (i);
8204
    if (atom[i - 1].formal_charge > 0)
8205
            pos_chg += atom[i - 1].formal_charge;
8206
    if (atom[i - 1].formal_charge < 0)
8207
            neg_chg += atom[i - 1].formal_charge;
8208
    chk_ion (i);
8209
  }
6785 bpr 8210
  FORLIM = n_bonds;
14179 bpr 8211
  for (i = 0; i < FORLIM; i++) {                                /* most groups are best discovered in the bond list */
8212
    a1 = bond[i].a1;
8213
    a2 = bond[i].a2;
8214
    bt = bond[i].btype;
8215
    if (atom[a1 - 1].heavy && atom[a2 - 1].heavy) {
8216
            orient_bond (&a1, &a2);
8217
            if (bt == 'T')
8218
              chk_triple (a1, a2);
8219
            if (bt == 'D')
8220
              chk_double (a1, a2);
8221
            if (bt == 'S')
8222
              chk_single (a1, a2);
8223
            if (bond[i].arom)
8224
              chk_arom_fg (a1, a2);
8225
          }
8226
  }
8227
  if (n_rings > 0) {
8228
    FORLIM = n_rings;
8229
    for (i = 1; i <= FORLIM; i++) {
8230
            chk_oxo_thioxo_imino_hetarene (i);
8231
            if (is_arene (i))
8232
              fg[fg_aromatic - 1] = true;
8233
            if (is_heterocycle (i))
8234
              fg[fg_heterocycle - 1] = true;
8235
          }
8236
  }
6785 bpr 8237
  if (pos_chg + neg_chg > 0)
8238
    fg[fg_cation - 1] = true;
8239
  if (pos_chg + neg_chg < 0)
8240
    fg[fg_anion - 1] = true;
8241
}
8242
 
14179 bpr 8243
static void write_fg_text ()
6785 bpr 8244
{
8245
  if (fg[fg_cation - 1])
8246
    printf ("cation\n");
8247
  if (fg[fg_anion - 1])
8248
    printf ("anion\n");
8249
  /*  if fg[fg_carbonyl]                       then writeln('carbonyl compound'); */
8250
  if (fg[fg_aldehyde - 1])
8251
    printf ("aldehyde\n");
8252
  if (fg[fg_ketone - 1])
8253
    printf ("ketone\n");
8254
  /*  if fg[fg_thiocarbonyl]                   then writeln('thiocarbonyl compound'); */
8255
  if (fg[fg_thioaldehyde - 1])
8256
    printf ("thioaldehyde\n");
8257
  if (fg[fg_thioketone - 1])
8258
    printf ("thioketone\n");
8259
  if (fg[fg_imine - 1])
8260
    printf ("imine\n");
8261
  if (fg[fg_hydrazone - 1])
8262
    printf ("hydrazone\n");
8263
  if (fg[fg_semicarbazone - 1])
8264
    printf ("semicarbazone\n");
8265
  if (fg[fg_thiosemicarbazone - 1])
8266
    printf ("thiosemicarbazone\n");
8267
  if (fg[fg_oxime - 1])
8268
    printf ("oxime\n");
8269
  if (fg[fg_oxime_ether - 1])
8270
    printf ("oxime ether\n");
8271
  if (fg[fg_ketene - 1])
8272
    printf ("ketene\n");
8273
  if (fg[fg_ketene_acetal_deriv - 1])
8274
    printf ("ketene acetal or derivative\n");
8275
  if (fg[fg_carbonyl_hydrate - 1])
8276
    printf ("carbonyl hydrate\n");
8277
  if (fg[fg_hemiacetal - 1])
8278
    printf ("hemiacetal\n");
8279
  if (fg[fg_acetal - 1])
8280
    printf ("acetal\n");
8281
  if (fg[fg_hemiaminal - 1])
8282
    printf ("hemiaminal\n");
8283
  if (fg[fg_aminal - 1])
8284
    printf ("aminal\n");
8285
  if (fg[fg_thiohemiaminal - 1])
8286
    printf ("hemithioaminal\n");
8287
  if (fg[fg_thioacetal - 1])
8288
    printf ("thioacetal\n");
8289
  if (fg[fg_enamine - 1])
8290
    printf ("enamine\n");
8291
  if (fg[fg_enol - 1])
8292
    printf ("enol\n");
8293
  if (fg[fg_enolether - 1])
8294
    printf ("enol ether\n");
8295
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8296
    printf ("hydroxy compound\n");
8297
  /*  if fg[fg_alcohol]                        then writeln('alcohol'); */
8298
  if (fg[fg_prim_alcohol - 1])
8299
    printf ("primary alcohol\n");
8300
  if (fg[fg_sec_alcohol - 1])
8301
    printf ("secondary alcohol\n");
8302
  if (fg[fg_tert_alcohol - 1])
8303
    printf ("tertiary alcohol\n");
8304
  if (fg[fg_1_2_diol - 1])
8305
    printf ("1,2-diol\n");
8306
  if (fg[fg_1_2_aminoalcohol - 1])
8307
    printf ("1,2-aminoalcohol\n");
8308
  if (fg[fg_phenol - 1])
8309
    printf ("phenol or hydroxyhetarene\n");
8310
  if (fg[fg_1_2_diphenol - 1])
8311
    printf ("1,2-diphenol\n");
8312
  if (fg[fg_enediol - 1])
8313
    printf ("enediol\n");
8314
  if (fg[fg_ether - 1] && ether_generic)
8315
    printf ("ether\n");
8316
  if (fg[fg_dialkylether - 1])
8317
    printf ("dialkyl ether\n");
8318
  if (fg[fg_alkylarylether - 1])
8319
    printf ("alkyl aryl ether \n");
8320
  if (fg[fg_diarylether - 1])
8321
    printf ("diaryl ether\n");
8322
  if (fg[fg_thioether - 1])
8323
    printf ("thioether\n");
8324
  if (fg[fg_disulfide - 1])
8325
    printf ("disulfide\n");
8326
  if (fg[fg_peroxide - 1])
8327
    printf ("peroxide\n");
8328
  if (fg[fg_hydroperoxide - 1])
8329
    printf ("hydroperoxide \n");
8330
  if (fg[fg_hydrazine - 1])
8331
    printf ("hydrazine derivative\n");
8332
  if (fg[fg_hydroxylamine - 1])
8333
    printf ("hydroxylamine\n");
8334
  if (fg[fg_amine - 1] && amine_generic)
8335
    printf ("amine\n");
8336
  if (fg[fg_prim_amine - 1])
8337
    printf ("primary amine\n");
8338
  if (fg[fg_prim_aliph_amine - 1])
8339
    printf ("primary aliphatic amine (alkylamine)\n");
8340
  if (fg[fg_prim_arom_amine - 1])
8341
    printf ("primary aromatic amine\n");
8342
  if (fg[fg_sec_amine - 1])
8343
    printf ("secondary amine\n");
8344
  if (fg[fg_sec_aliph_amine - 1])
8345
    printf ("secondary aliphatic amine (dialkylamine)\n");
8346
  if (fg[fg_sec_mixed_amine - 1])
8347
    printf ("secondary aliphatic/aromatic amine (alkylarylamine)\n");
8348
  if (fg[fg_sec_arom_amine - 1])
8349
    printf ("secondary aromatic amine (diarylamine)\n");
8350
  if (fg[fg_tert_amine - 1])
8351
    printf ("tertiary amine\n");
8352
  if (fg[fg_tert_aliph_amine - 1])
8353
    printf ("tertiary aliphatic amine (trialkylamine)\n");
8354
  if (fg[fg_tert_mixed_amine - 1])
8355
    printf ("tertiary aliphatic/aromatic amine (alkylarylamine)\n");
8356
  if (fg[fg_tert_arom_amine - 1])
8357
    printf ("tertiary aromatic amine (triarylamine)\n");
8358
  if (fg[fg_quart_ammonium - 1])
8359
    printf ("quaternary ammonium salt\n");
8360
  if (fg[fg_n_oxide - 1])
8361
    printf ("N-oxide\n");
8362
  /* new in v0.2f */
14179 bpr 8363
  if (fg[fg_halogen_deriv - 1]) {
6785 bpr 8364
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
14179 bpr 8365
              !fg[fg_acyl_halide - 1])
8366
            printf ("halogen derivative\n");
8367
  }
6785 bpr 8368
  /*  if fg[fg_alkyl_halide]                   then writeln('alkyl halide'); */
8369
  if (fg[fg_alkyl_fluoride - 1])
8370
    printf ("alkyl fluoride\n");
8371
  if (fg[fg_alkyl_chloride - 1])
8372
    printf ("alkyl chloride\n");
8373
  if (fg[fg_alkyl_bromide - 1])
8374
    printf ("alkyl bromide\n");
8375
  if (fg[fg_alkyl_iodide - 1])
8376
    printf ("alkyl iodide\n");
8377
  /*  if fg[fg_aryl_halide]                    then writeln('aryl halide'); */
8378
  if (fg[fg_aryl_fluoride - 1])
8379
    printf ("aryl fluoride\n");
8380
  if (fg[fg_aryl_chloride - 1])
8381
    printf ("aryl chloride\n");
8382
  if (fg[fg_aryl_bromide - 1])
8383
    printf ("aryl bromide\n");
8384
  if (fg[fg_aryl_iodide - 1])
8385
    printf ("aryl iodide\n");
8386
  if (fg[fg_organometallic - 1])
8387
    printf ("organometallic compound\n");
8388
  if (fg[fg_organolithium - 1])
8389
    printf ("organolithium compound\n");
8390
  if (fg[fg_organomagnesium - 1])
8391
    printf ("organomagnesium compound\n");
8392
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('carboxylic acid derivative'); */
8393
  if (fg[fg_carboxylic_acid - 1])
8394
    printf ("carboxylic acid\n");
8395
  if (fg[fg_carboxylic_acid_salt - 1])
8396
    printf ("carboxylic acid salt\n");
8397
  if (fg[fg_carboxylic_acid_ester - 1])
8398
    printf ("carboxylic acid ester\n");
8399
  if (fg[fg_lactone - 1])
8400
    printf ("lactone\n");
8401
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('carboxylic acid amide'); */
8402
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8403
    printf ("primary carboxylic acid amide\n");
8404
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8405
    printf ("secondary carboxylic acid amide\n");
8406
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8407
    printf ("tertiary carboxylic acid amide\n");
8408
  if (fg[fg_lactam - 1])
8409
    printf ("lactam\n");
8410
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8411
    printf ("carboxylic acid hydrazide\n");
8412
  if (fg[fg_carboxylic_acid_azide - 1])
8413
    printf ("carboxylic acid azide\n");
8414
  if (fg[fg_hydroxamic_acid - 1])
8415
    printf ("hydroxamic acid\n");
8416
  if (fg[fg_carboxylic_acid_amidine - 1])
8417
    printf ("carboxylic acid amidine\n");
8418
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8419
    printf ("carboxylic acid amidrazone\n");
8420
  if (fg[fg_nitrile - 1])
8421
    printf ("carbonitrile\n");
8422
  /*  if fg[fg_acyl_halide]                    then writeln('acyl halide'); */
8423
  if (fg[fg_acyl_fluoride - 1])
8424
    printf ("acyl fluoride\n");
8425
  if (fg[fg_acyl_chloride - 1])
8426
    printf ("acyl chloride\n");
8427
  if (fg[fg_acyl_bromide - 1])
8428
    printf ("acyl bromide\n");
8429
  if (fg[fg_acyl_iodide - 1])
8430
    printf ("acyl iodide\n");
8431
  if (fg[fg_acyl_cyanide - 1])
8432
    printf ("acyl cyanide\n");
8433
  if (fg[fg_imido_ester - 1])
8434
    printf ("imido ester\n");
8435
  if (fg[fg_imidoyl_halide - 1])
8436
    printf ("imidoyl halide\n");
8437
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('thiocarboxylic acid derivative'); */
8438
  if (fg[fg_thiocarboxylic_acid - 1])
8439
    printf ("thiocarboxylic acid\n");
8440
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8441
    printf ("thiocarboxylic acid ester\n");
8442
  if (fg[fg_thiolactone - 1])
8443
    printf ("thiolactone\n");
8444
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8445
    printf ("thiocarboxylic acid amide\n");
8446
  if (fg[fg_thiolactam - 1])
8447
    printf ("thiolactam\n");
8448
  if (fg[fg_imido_thioester - 1])
8449
    printf ("imidothioester\n");
8450
  if (fg[fg_oxohetarene - 1])
8451
    printf ("oxo(het)arene\n");
8452
  if (fg[fg_thioxohetarene - 1])
8453
    printf ("thioxo(het)arene\n");
8454
  if (fg[fg_iminohetarene - 1])
8455
    printf ("imino(het)arene\n");
8456
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8457
    printf ("orthocarboxylic acid derivative\n");
8458
  if (fg[fg_carboxylic_acid_orthoester - 1])
8459
    printf ("orthoester\n");
8460
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8461
    printf ("amide acetal\n");
8462
  if (fg[fg_carboxylic_acid_anhydride - 1])
8463
    printf ("carboxylic acid anhydride\n");
8464
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('carboxylic acid imide'); */
8465
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8466
    printf ("carboxylic acid imide, N-unsubstituted\n");
8467
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8468
    printf ("carboxylic acid imide, N-substituted\n");
8469
  if (fg[fg_co2_deriv - 1])
8470
    printf ("CO2 derivative (general)\n");
8471
  if (fg[fg_carbonic_acid_deriv - 1] &&
8472
      !(fg[fg_carbonic_acid_monoester - 1]
8473
        || fg[fg_carbonic_acid_diester - 1]
8474
        || fg[fg_carbonic_acid_ester_halide - 1]))
8475
    /* changed in v0.3c */
8476
    printf ("carbonic acid derivative\n");
8477
  if (fg[fg_carbonic_acid_monoester - 1])
8478
    printf ("carbonic acid monoester\n");
8479
  if (fg[fg_carbonic_acid_diester - 1])
8480
    printf ("carbonic acid diester\n");
8481
  if (fg[fg_carbonic_acid_ester_halide - 1])
8482
    printf ("carbonic acid ester halide (alkyl/aryl haloformate)\n");
8483
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8484
    printf ("thiocarbonic acid derivative\n");
8485
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8486
    printf ("thiocarbonic acid monoester\n");
8487
  if (fg[fg_thiocarbonic_acid_diester - 1])
8488
    printf ("thiocarbonic acid diester\n");
8489
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
8490
    printf ("thiocarbonic acid ester halide (alkyl/aryl halothioformate)\n");
8491
  if (fg[fg_carbamic_acid_deriv - 1]
8492
      && !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1]
8493
           || fg[fg_carbamic_acid_halide - 1]))
8494
    /* changed in v0.3c */
8495
    printf ("carbamic acid derivative\n");
8496
  if (fg[fg_carbamic_acid - 1])
8497
    printf ("carbamic acid\n");
8498
  if (fg[fg_carbamic_acid_ester - 1])
8499
    printf ("carbamic acid ester (urethane)\n");
8500
  if (fg[fg_carbamic_acid_halide - 1])
8501
    printf ("carbamic acid halide (haloformic acid amide)\n");
8502
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8503
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
8504
        || fg[fg_thiocarbamic_acid_halide - 1]))
8505
    /* changed in v0.3c */
8506
    printf ("thiocarbamic acid derivative\n");
8507
  if (fg[fg_thiocarbamic_acid - 1])
8508
    printf ("thiocarbamic acid\n");
8509
  if (fg[fg_thiocarbamic_acid_ester - 1])
8510
    printf ("thiocarbamic acid ester\n");
8511
  if (fg[fg_thiocarbamic_acid_halide - 1])
8512
    printf ("thiocarbamic acid halide (halothioformic acid amide)\n");
8513
  if (fg[fg_urea - 1])
8514
    printf ("urea\n");
8515
  if (fg[fg_isourea - 1])
8516
    printf ("isourea\n");
8517
  if (fg[fg_thiourea - 1])
8518
    printf ("thiourea\n");
8519
  if (fg[fg_isothiourea - 1])
8520
    printf ("isothiourea\n");
8521
  if (fg[fg_guanidine - 1])
8522
    printf ("guanidine\n");
8523
  if (fg[fg_semicarbazide - 1])
8524
    printf ("semicarbazide\n");
8525
  if (fg[fg_thiosemicarbazide - 1])
8526
    printf ("thiosemicarbazide\n");
8527
  if (fg[fg_azide - 1])
8528
    printf ("azide\n");
8529
  if (fg[fg_azo_compound - 1])
8530
    printf ("azo compound\n");
8531
  if (fg[fg_diazonium_salt - 1])
8532
    printf ("diazonium salt\n");
8533
  if (fg[fg_isonitrile - 1])
8534
    printf ("isonitrile\n");
8535
  if (fg[fg_cyanate - 1])
8536
    printf ("cyanate\n");
8537
  if (fg[fg_isocyanate - 1])
8538
    printf ("isocyanate\n");
8539
  if (fg[fg_thiocyanate - 1])
8540
    printf ("thiocyanate\n");
8541
  if (fg[fg_isothiocyanate - 1])
8542
    printf ("isothiocyanate\n");
8543
  if (fg[fg_carbodiimide - 1])
8544
    printf ("carbodiimide\n");
8545
  if (fg[fg_nitroso_compound - 1])
8546
    printf ("nitroso compound\n");
8547
  if (fg[fg_nitro_compound - 1])
8548
    printf ("nitro compound\n");
8549
  if (fg[fg_nitrite - 1])
8550
    printf ("nitrite\n");
8551
  if (fg[fg_nitrate - 1])
8552
    printf ("nitrate\n");
8553
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('sulfuric acid derivative'); */
8554
  if (fg[fg_sulfuric_acid - 1])
8555
    printf ("sulfuric acid\n");
8556
  if (fg[fg_sulfuric_acid_monoester - 1])
8557
    printf ("sulfuric acid monoester\n");
8558
  if (fg[fg_sulfuric_acid_diester - 1])
8559
    printf ("sulfuric acid diester\n");
8560
  if (fg[fg_sulfuric_acid_amide_ester - 1])
8561
    printf ("sulfuric acid amide ester\n");
8562
  if (fg[fg_sulfuric_acid_amide - 1])
8563
    printf ("sulfuric acid amide\n");
8564
  if (fg[fg_sulfuric_acid_diamide - 1])
8565
    printf ("sulfuric acid diamide\n");
8566
  if (fg[fg_sulfuryl_halide - 1])
8567
    printf ("sulfuryl halide\n");
8568
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('sulfonic acid derivative '); */
8569
  if (fg[fg_sulfonic_acid - 1])
8570
    printf ("sulfonic acid\n");
8571
  if (fg[fg_sulfonic_acid_ester - 1])
8572
    printf ("sulfonic acid ester\n");
8573
  if (fg[fg_sulfonamide - 1])
8574
    printf ("sulfonamide\n");
8575
  if (fg[fg_sulfonyl_halide - 1])
8576
    printf ("sulfonyl halide\n");
8577
  if (fg[fg_sulfone - 1])
8578
    printf ("sulfone\n");
8579
  if (fg[fg_sulfoxide - 1])
8580
    printf ("sulfoxide\n");
8581
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('sulfinic acid derivative'); */
8582
  if (fg[fg_sulfinic_acid - 1])
8583
    printf ("sulfinic acid\n");
8584
  if (fg[fg_sulfinic_acid_ester - 1])
8585
    printf ("sulfinic acid ester\n");
8586
  if (fg[fg_sulfinic_acid_halide - 1])
8587
    printf ("sulfinic acid halide\n");
8588
  if (fg[fg_sulfinic_acid_amide - 1])
8589
    printf ("sulfinic acid amide\n");
8590
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('sulfenic acid derivative'); */
8591
  if (fg[fg_sulfenic_acid - 1])
8592
    printf ("sulfenic acid\n");
8593
  if (fg[fg_sulfenic_acid_ester - 1])
8594
    printf ("sulfenic acid ester\n");
8595
  if (fg[fg_sulfenic_acid_halide - 1])
8596
    printf ("sulfenic acid halide\n");
8597
  if (fg[fg_sulfenic_acid_amide - 1])
8598
    printf ("sulfenic acid amide\n");
8599
  if (fg[fg_thiol - 1])
8600
    printf ("thiol (sulfanyl compound)\n");
8601
  if (fg[fg_alkylthiol - 1])
8602
    printf ("alkylthiol\n");
8603
  if (fg[fg_arylthiol - 1])
8604
    printf ("arylthiol\n");
8605
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('phosphoric acid derivative'); */
8606
  if (fg[fg_phosphoric_acid - 1])
8607
    printf ("phosphoric acid\n");
8608
  if (fg[fg_phosphoric_acid_ester - 1])
8609
    printf ("phosphoric acid ester\n");
8610
  if (fg[fg_phosphoric_acid_halide - 1])
8611
    printf ("phosphoric acid halide\n");
8612
  if (fg[fg_phosphoric_acid_amide - 1])
8613
    printf ("phosphoric acid amide\n");
8614
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('thiophosphoric acid derivative'); */
8615
  if (fg[fg_thiophosphoric_acid - 1])
8616
    printf ("thiophosphoric acid\n");
8617
  if (fg[fg_thiophosphoric_acid_ester - 1])
8618
    printf ("thiophosphoric acid ester\n");
8619
  if (fg[fg_thiophosphoric_acid_halide - 1])
8620
    printf ("thiophosphoric acid halide\n");
8621
  if (fg[fg_thiophosphoric_acid_amide - 1])
8622
    printf ("thiophosphoric acid amide\n");
8623
  if (fg[fg_phosphonic_acid_deriv - 1])
8624
    printf ("phosphonic acid derivative \n");
8625
  if (fg[fg_phosphonic_acid - 1])
8626
    printf ("phosphonic acid\n");
8627
  if (fg[fg_phosphonic_acid_ester - 1])
8628
    printf ("phosphonic acid ester\n");
8629
  if (fg[fg_phosphine - 1])
8630
    printf ("phosphine\n");
8631
  if (fg[fg_phosphinoxide - 1])
8632
    printf ("phosphine oxide\n");
8633
  if (fg[fg_boronic_acid_deriv - 1])
8634
    printf ("boronic acid derivative\n");
8635
  if (fg[fg_boronic_acid - 1])
8636
    printf ("boronic acid\n");
8637
  if (fg[fg_boronic_acid_ester - 1])
8638
    printf ("boronic acid ester\n");
8639
  if (fg[fg_alkene - 1])
8640
    printf ("alkene\n");
8641
  if (fg[fg_alkyne - 1])
8642
    printf ("alkyne\n");
8643
  if (fg[fg_aromatic - 1])
8644
    printf ("aromatic compound\n");
8645
  if (fg[fg_heterocycle - 1])
8646
    printf ("heterocyclic compound\n");
8647
  if (fg[fg_alpha_aminoacid - 1])
8648
    printf ("alpha-aminoacid\n");
8649
  if (fg[fg_alpha_hydroxyacid - 1])
8650
    printf ("alpha-hydroxyacid\n");
8651
}
8652
 
14179 bpr 8653
static void write_fg_text_de ()
6785 bpr 8654
{
8655
  if (fg[fg_cation - 1])
8656
    printf ("Kation\n");
8657
  if (fg[fg_anion - 1])
8658
    printf ("Anion\n");
8659
  /*  if fg[fg_carbonyl]                       then writeln('Carbonylverbindung'); */
8660
  if (fg[fg_aldehyde - 1])
8661
    printf ("Aldehyd\n");
8662
  if (fg[fg_ketone - 1])
8663
    printf ("Keton\n");
8664
  /*  if fg[fg_thiocarbonyl]                   then writeln('Thiocarbonylverbindung'); */
8665
  if (fg[fg_thioaldehyde - 1])
8666
    printf ("Thioaldehyd\n");
8667
  if (fg[fg_thioketone - 1])
8668
    printf ("Thioketon\n");
8669
  if (fg[fg_imine - 1])
8670
    printf ("Imin\n");
8671
  if (fg[fg_hydrazone - 1])
8672
    printf ("Hydrazon\n");
8673
  if (fg[fg_semicarbazone - 1])
8674
    printf ("Semicarbazon\n");
8675
  if (fg[fg_thiosemicarbazone - 1])
8676
    printf ("Thiosemicarbazon\n");
8677
  if (fg[fg_oxime - 1])
8678
    printf ("Oxim\n");
8679
  if (fg[fg_oxime_ether - 1])
8680
    printf ("Oximether\n");
8681
  if (fg[fg_ketene - 1])
8682
    printf ("Keten\n");
8683
  if (fg[fg_ketene_acetal_deriv - 1])
8684
    printf ("Keten-Acetal oder Derivat\n");
8685
  if (fg[fg_carbonyl_hydrate - 1])
8686
    printf ("Carbonyl-Hydrat\n");
8687
  if (fg[fg_hemiacetal - 1])
8688
    printf ("Halbacetal\n");
8689
  if (fg[fg_acetal - 1])
8690
    printf ("Acetal\n");
8691
  if (fg[fg_hemiaminal - 1])
8692
    printf ("Halbaminal\n");
8693
  if (fg[fg_aminal - 1])
8694
    printf ("Aminal\n");
8695
  if (fg[fg_thiohemiaminal - 1])
8696
    printf ("Thiohalbaminal\n");
8697
  if (fg[fg_thioacetal - 1])
8698
    printf ("Thioacetal\n");
8699
  if (fg[fg_enamine - 1])
8700
    printf ("Enamin\n");
8701
  if (fg[fg_enol - 1])
8702
    printf ("Enol\n");
8703
  if (fg[fg_enolether - 1])
8704
    printf ("Enolether\n");
8705
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
8706
    printf ("Hydroxy-Verbindung\n");
8707
  /*  if fg[fg_alcohol]                        then writeln('Alkohol'); */
8708
  if (fg[fg_prim_alcohol - 1])
8709
    printf ("prim\344rer Alkohol\n");
14179 bpr 8710
  /* p2c: checkmol.pas, line 7283: Note: character >= 128 encountered [281] */
6785 bpr 8711
  if (fg[fg_sec_alcohol - 1])
8712
    printf ("sekund\344rer Alkohol\n");
14179 bpr 8713
  /* p2c: checkmol.pas, line 7284: Note: character >= 128 encountered [281] */
6785 bpr 8714
  if (fg[fg_tert_alcohol - 1])
8715
    printf ("terti\344rer Alkohol\n");
14179 bpr 8716
  /* p2c: checkmol.pas, line 7285: Note: character >= 128 encountered [281] */
6785 bpr 8717
  if (fg[fg_1_2_diol - 1])
8718
    printf ("1,2-Diol\n");
8719
  if (fg[fg_1_2_aminoalcohol - 1])
8720
    printf ("1,2-Aminoalkohol\n");
8721
  if (fg[fg_phenol - 1])
8722
    printf ("Phenol oder Hydroxyhetaren\n");
8723
  if (fg[fg_1_2_diphenol - 1])
8724
    printf ("1,2-Diphenol\n");
8725
  if (fg[fg_enediol - 1])
8726
    printf ("Endiol\n");
8727
  if (fg[fg_ether - 1] && ether_generic)
8728
    printf ("Ether\n");
8729
  if (fg[fg_dialkylether - 1])
8730
    printf ("Dialkylether\n");
8731
  if (fg[fg_alkylarylether - 1])
8732
    printf ("Alkylarylether \n");
8733
  if (fg[fg_diarylether - 1])
8734
    printf ("Diarylether\n");
8735
  if (fg[fg_thioether - 1])
8736
    printf ("Thioether\n");
8737
  if (fg[fg_disulfide - 1])
8738
    printf ("Disulfid\n");
8739
  if (fg[fg_peroxide - 1])
8740
    printf ("Peroxid\n");
8741
  if (fg[fg_hydroperoxide - 1])
8742
    printf ("Hydroperoxid\n");
8743
  if (fg[fg_hydrazine - 1])
8744
    printf ("Hydrazin-Derivat\n");
8745
  if (fg[fg_hydroxylamine - 1])
8746
    printf ("Hydroxylamin\n");
8747
  if (fg[fg_amine - 1] && amine_generic)
8748
    printf ("Amin\n");
8749
  if (fg[fg_prim_amine - 1])
8750
    printf ("prim\344res Amin\n");
14179 bpr 8751
  /* p2c: checkmol.pas, line 7302: Note: character >= 128 encountered [281] */
6785 bpr 8752
  if (fg[fg_prim_aliph_amine - 1])
8753
    printf ("prim\344res aliphatisches Amin (Alkylamin)\n");
14179 bpr 8754
  /* p2c: checkmol.pas, line 7303: Note: character >= 128 encountered [281] */
6785 bpr 8755
  if (fg[fg_prim_arom_amine - 1])
8756
    printf ("prim\344res aromatisches Amin\n");
14179 bpr 8757
  /* p2c: checkmol.pas, line 7304: Note: character >= 128 encountered [281] */
6785 bpr 8758
  if (fg[fg_sec_amine - 1])
8759
    printf ("sekund\344res Amin\n");
14179 bpr 8760
  /* p2c: checkmol.pas, line 7305: Note: character >= 128 encountered [281] */
6785 bpr 8761
  if (fg[fg_sec_aliph_amine - 1])
8762
    printf ("sekund\344res aliphatisches Amin (Dialkylamin)\n");
14179 bpr 8763
  /* p2c: checkmol.pas, line 7306: Note: character >= 128 encountered [281] */
6785 bpr 8764
  if (fg[fg_sec_mixed_amine - 1])
8765
    printf
8766
      ("sekund\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8767
  /* p2c: checkmol.pas, line 7307: Note: character >= 128 encountered [281] */
6785 bpr 8768
  if (fg[fg_sec_arom_amine - 1])
8769
    printf ("sekund\344res aromatisches Amin (Diarylamin)\n");
14179 bpr 8770
  /* p2c: checkmol.pas, line 7308: Note: character >= 128 encountered [281] */
6785 bpr 8771
  if (fg[fg_tert_amine - 1])
8772
    printf ("terti\344res Amin\n");
14179 bpr 8773
  /* p2c: checkmol.pas, line 7309: Note: character >= 128 encountered [281] */
6785 bpr 8774
  if (fg[fg_tert_aliph_amine - 1])
8775
    printf ("terti\344res aliphatisches Amin (Trialkylamin)\n");
14179 bpr 8776
  /* p2c: checkmol.pas, line 7310: Note: character >= 128 encountered [281] */
6785 bpr 8777
  if (fg[fg_tert_mixed_amine - 1])
8778
    printf ("terti\344res aliphatisches/aromatisches Amin (Alkylarylamin)\n");
14179 bpr 8779
  /* p2c: checkmol.pas, line 7311: Note: character >= 128 encountered [281] */
6785 bpr 8780
  if (fg[fg_tert_arom_amine - 1])
8781
    printf ("terti\344res aromatisches Amin (Triarylamin)\n");
14179 bpr 8782
  /* p2c: checkmol.pas, line 7312: Note: character >= 128 encountered [281] */
6785 bpr 8783
  if (fg[fg_quart_ammonium - 1])
8784
    printf ("quart\344res Ammoniumsalz\n");
14179 bpr 8785
  /* p2c: checkmol.pas, line 7313: Note: character >= 128 encountered [281] */
6785 bpr 8786
  if (fg[fg_n_oxide - 1])
8787
    printf ("N-Oxid\n");
8788
  /* new in v0.2f */
14179 bpr 8789
  if (fg[fg_halogen_deriv - 1]) {
8790
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] &&
8791
              !fg[fg_acyl_halide - 1])
8792
            printf ("Halogenverbindung\n");
8793
  }
6785 bpr 8794
  /*  if fg[fg_alkyl_halide]                   then writeln('Alkylhalogenid'); */
8795
  if (fg[fg_alkyl_fluoride - 1])
8796
    printf ("Alkylfluorid\n");
8797
  if (fg[fg_alkyl_chloride - 1])
8798
    printf ("Alkylchlorid\n");
8799
  if (fg[fg_alkyl_bromide - 1])
8800
    printf ("Alkylbromid\n");
8801
  if (fg[fg_alkyl_iodide - 1])
8802
    printf ("Alkyliodid\n");
8803
  /*  if fg[fg_aryl_halide]                    then writeln('Arylhalogenid'); */
8804
  if (fg[fg_aryl_fluoride - 1])
8805
    printf ("Arylfluorid\n");
8806
  if (fg[fg_aryl_chloride - 1])
8807
    printf ("Arylchlorid\n");
8808
  if (fg[fg_aryl_bromide - 1])
8809
    printf ("Arylbromid\n");
8810
  if (fg[fg_aryl_iodide - 1])
8811
    printf ("Aryliodid\n");
8812
  if (fg[fg_organometallic - 1])
8813
    printf ("Organometall-Verbindung\n");
8814
  if (fg[fg_organolithium - 1])
8815
    printf ("Organolithium-Verbindung\n");
8816
  if (fg[fg_organomagnesium - 1])
8817
    printf ("Organomagnesium-Verbindung\n");
8818
  /*  if fg[fg_carboxylic_acid_deriv]          then writeln('Carbonsäure-Derivat'); */
8819
  if (fg[fg_carboxylic_acid - 1])
8820
    printf ("Carbons\344ure\n");
14179 bpr 8821
  /* p2c: checkmol.pas, line 7335: Note: character >= 128 encountered [281] */
6785 bpr 8822
  if (fg[fg_carboxylic_acid_salt - 1])
8823
    printf ("Carbons\344uresalz\n");
14179 bpr 8824
  /* p2c: checkmol.pas, line 7336: Note: character >= 128 encountered [281] */
6785 bpr 8825
  if (fg[fg_carboxylic_acid_ester - 1])
8826
    printf ("Carbons\344ureester\n");
14179 bpr 8827
  /* p2c: checkmol.pas, line 7337: Note: character >= 128 encountered [281] */
6785 bpr 8828
  if (fg[fg_lactone - 1])
8829
    printf ("Lacton\n");
8830
  /*  if fg[fg_carboxylic_acid_amide]          then writeln('Carbonsäureamid'); */
8831
  if (fg[fg_carboxylic_acid_prim_amide - 1])
8832
    printf ("prim\344res Carbons\344ureamid\n");
14179 bpr 8833
  /* p2c: checkmol.pas, line 7340:
8834
  * Note: characters >= 128 encountered [281] */
6785 bpr 8835
  if (fg[fg_carboxylic_acid_sec_amide - 1])
8836
    printf ("sekund\344res Carbons\344ureamid\n");
14179 bpr 8837
  /* p2c: checkmol.pas, line 7341:
8838
  * Note: characters >= 128 encountered [281] */
6785 bpr 8839
  if (fg[fg_carboxylic_acid_tert_amide - 1])
8840
    printf ("terti\344res Carbons\344ureamid\n");
14179 bpr 8841
  /* p2c: checkmol.pas, line 7342:
8842
  * Note: characters >= 128 encountered [281] */
6785 bpr 8843
  if (fg[fg_lactam - 1])
8844
    printf ("Lactam\n");
8845
  if (fg[fg_carboxylic_acid_hydrazide - 1])
8846
    printf ("Carbons\344urehydrazid\n");
14179 bpr 8847
  /* p2c: checkmol.pas, line 7344: Note: character >= 128 encountered [281] */
6785 bpr 8848
  if (fg[fg_carboxylic_acid_azide - 1])
8849
    printf ("Carbons\344ureazid\n");
14179 bpr 8850
  /* p2c: checkmol.pas, line 7345: Note: character >= 128 encountered [281] */
6785 bpr 8851
  if (fg[fg_hydroxamic_acid - 1])
8852
    printf ("Hydroxams\344ure\n");
14179 bpr 8853
  /* p2c: checkmol.pas, line 7346: Note: character >= 128 encountered [281] */
6785 bpr 8854
  if (fg[fg_carboxylic_acid_amidine - 1])
8855
    printf ("Carbons\344ureamidin\n");
14179 bpr 8856
  /* p2c: checkmol.pas, line 7347: Note: character >= 128 encountered [281] */
6785 bpr 8857
  if (fg[fg_carboxylic_acid_amidrazone - 1])
8858
    printf ("Carbons\344ureamidrazon\n");
14179 bpr 8859
  /* p2c: checkmol.pas, line 7348: Note: character >= 128 encountered [281] */
6785 bpr 8860
  if (fg[fg_nitrile - 1])
8861
    printf ("Carbonitril\n");
8862
  /*  if fg[fg_acyl_halide]                    then writeln('Acylhalogenid'); */
8863
  if (fg[fg_acyl_fluoride - 1])
8864
    printf ("Acylfluorid\n");
8865
  if (fg[fg_acyl_chloride - 1])
8866
    printf ("Acylchlorid\n");
8867
  if (fg[fg_acyl_bromide - 1])
8868
    printf ("Acylbromid\n");
8869
  if (fg[fg_acyl_iodide - 1])
8870
    printf ("Acyliodid\n");
8871
  if (fg[fg_acyl_cyanide - 1])
8872
    printf ("Acylcyanid\n");
8873
  if (fg[fg_imido_ester - 1])
8874
    printf ("Imidoester\n");
8875
  if (fg[fg_imidoyl_halide - 1])
8876
    printf ("Imidoylhalogenid\n");
8877
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then writeln('Thiocarbonsäure-Derivat'); */
8878
  if (fg[fg_thiocarboxylic_acid - 1])
8879
    printf ("Thiocarbons\344ure\n");
14179 bpr 8880
  /* p2c: checkmol.pas, line 7359: Note: character >= 128 encountered [281] */
6785 bpr 8881
  if (fg[fg_thiocarboxylic_acid_ester - 1])
8882
    printf ("Thiocarbons\344ureester\n");
14179 bpr 8883
  /* p2c: checkmol.pas, line 7360: Note: character >= 128 encountered [281] */
6785 bpr 8884
  if (fg[fg_thiolactone - 1])
8885
    printf ("Thiolacton\n");
8886
  if (fg[fg_thiocarboxylic_acid_amide - 1])
8887
    printf ("Thiocarbons\344ureamid\n");
14179 bpr 8888
  /* p2c: checkmol.pas, line 7362: Note: character >= 128 encountered [281] */
6785 bpr 8889
  if (fg[fg_thiolactam - 1])
8890
    printf ("Thiolactam\n");
8891
  if (fg[fg_imido_thioester - 1])
8892
    printf ("Imidothioester\n");
8893
  if (fg[fg_oxohetarene - 1])
8894
    printf ("Oxo(het)aren\n");
8895
  if (fg[fg_thioxohetarene - 1])
8896
    printf ("Thioxo(het)aren\n");
8897
  if (fg[fg_iminohetarene - 1])
8898
    printf ("Imino(het)aren\n");
8899
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
8900
    printf ("Orthocarbons\344ure-Derivat\n");
14179 bpr 8901
  /* p2c: checkmol.pas, line 7368: Note: character >= 128 encountered [281] */
6785 bpr 8902
  if (fg[fg_carboxylic_acid_orthoester - 1])
8903
    printf ("Orthoester\n");
8904
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
8905
    printf ("Amidacetal\n");
8906
  if (fg[fg_carboxylic_acid_anhydride - 1])
8907
    printf ("Carbons\344ureanhydrid\n");
14179 bpr 8908
  /* p2c: checkmol.pas, line 7371: Note: character >= 128 encountered [281] */
6785 bpr 8909
  /*  if fg[fg_carboxylic_acid_imide]          then writeln('Carbonsäureimid'); */
8910
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
8911
    printf ("Carbons\344ureimid, N-unsubstituiert\n");
14179 bpr 8912
  /* p2c: checkmol.pas, line 7373: Note: character >= 128 encountered [281] */
6785 bpr 8913
  if (fg[fg_carboxylic_acid_subst_imide - 1])
8914
    printf ("Carbons\344ureimid, N-substituiert\n");
14179 bpr 8915
  /* p2c: checkmol.pas, line 7374: Note: character >= 128 encountered [281] */
6785 bpr 8916
  if (fg[fg_co2_deriv - 1])
8917
    printf ("CO2-Derivat (allgemein)\n");
14179 bpr 8918
  if (fg[fg_carbonic_acid_deriv - 1] && !(fg[fg_carbonic_acid_monoester - 1]
8919
            || fg[fg_carbonic_acid_diester - 1] || fg[fg_carbonic_acid_ester_halide - 1]))
6785 bpr 8920
    /* changed in v0.3c */
8921
    printf ("Kohlens\344ure-Derivat\n");
14179 bpr 8922
  /* p2c: checkmol.pas, line 7379: Note: character >= 128 encountered [281] */
6785 bpr 8923
  if (fg[fg_carbonic_acid_monoester - 1])
8924
    printf ("Kohlens\344uremonoester\n");
14179 bpr 8925
  /* p2c: checkmol.pas, line 7380: Note: character >= 128 encountered [281] */
6785 bpr 8926
  if (fg[fg_carbonic_acid_diester - 1])
8927
    printf ("Kohlens\344urediester\n");
14179 bpr 8928
  /* p2c: checkmol.pas, line 7381: Note: character >= 128 encountered [281] */
6785 bpr 8929
  if (fg[fg_carbonic_acid_ester_halide - 1])
8930
    printf ("Kohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenformiat)\n");
14179 bpr 8931
  /* p2c: checkmol.pas, line 7382: Note: character >= 128 encountered [281] */
6785 bpr 8932
  if (fg[fg_thiocarbonic_acid_deriv - 1])
8933
    printf ("Thiokohlens\344ure-Derivat\n");
14179 bpr 8934
  /* p2c: checkmol.pas, line 7383: Note: character >= 128 encountered [281] */
6785 bpr 8935
  if (fg[fg_thiocarbonic_acid_monoester - 1])
8936
    printf ("Thiokohlens\344uremonoester\n");
14179 bpr 8937
  /* p2c: checkmol.pas, line 7384: Note: character >= 128 encountered [281] */
6785 bpr 8938
  if (fg[fg_thiocarbonic_acid_diester - 1])
8939
    printf ("Thiokohlens\344urediester\n");
14179 bpr 8940
  /* p2c: checkmol.pas, line 7385: Note: character >= 128 encountered [281] */
6785 bpr 8941
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
14179 bpr 8942
    printf ("Thiokohlens\344ureesterhalogenid (Alkyl/Aryl-Halogenthioformiat)\n");
8943
  /* p2c: checkmol.pas, line 7386: Note: character >= 128 encountered [281] */
6785 bpr 8944
  if (fg[fg_carbamic_acid_deriv - 1] &&
8945
      !(fg[fg_carbamic_acid - 1] || fg[fg_carbamic_acid_ester - 1] ||
14179 bpr 8946
            fg[fg_carbamic_acid_halide - 1]))
6785 bpr 8947
    /* changed in v0.3c */
8948
    printf ("Carbamins\344ure-Derivat\n");
14179 bpr 8949
  /* p2c: checkmol.pas, line 7390: Note: character >= 128 encountered [281] */
6785 bpr 8950
  if (fg[fg_carbamic_acid - 1])
8951
    printf ("Carbamins\344ure\n");
14179 bpr 8952
  /* p2c: checkmol.pas, line 7391: Note: character >= 128 encountered [281] */
6785 bpr 8953
  if (fg[fg_carbamic_acid_ester - 1])
8954
    printf ("Carbamins\344ureester (Urethan)\n");
14179 bpr 8955
  /* p2c: checkmol.pas, line 7392: Note: character >= 128 encountered [281] */
6785 bpr 8956
  if (fg[fg_carbamic_acid_halide - 1])
8957
    printf ("Carbamins\344urehalogenid (Halogenformamid)\n");
14179 bpr 8958
  /* p2c: checkmol.pas, line 7393: Note: character >= 128 encountered [281] */
6785 bpr 8959
  if (fg[fg_thiocarbamic_acid_deriv - 1] &&
8960
      !(fg[fg_thiocarbamic_acid - 1] || fg[fg_thiocarbamic_acid_ester - 1]
14179 bpr 8961
            || fg[fg_thiocarbamic_acid_halide - 1]))
6785 bpr 8962
    /* changed in v0.3c */
8963
    printf ("Thiocarbamins\344ure-Derivat\n");
14179 bpr 8964
  /* p2c: checkmol.pas, line 7397: Note: character >= 128 encountered [281] */
6785 bpr 8965
  if (fg[fg_thiocarbamic_acid - 1])
8966
    printf ("Thiocarbamins\344ure\n");
14179 bpr 8967
  /* p2c: checkmol.pas, line 7398: Note: character >= 128 encountered [281] */
6785 bpr 8968
  if (fg[fg_thiocarbamic_acid_ester - 1])
8969
    printf ("Thiocarbamins\344ureester\n");
14179 bpr 8970
  /* p2c: checkmol.pas, line 7399: Note: character >= 128 encountered [281] */
6785 bpr 8971
  if (fg[fg_thiocarbamic_acid_halide - 1])
8972
    printf ("Thiocarbamins\344urehalogenid (Halogenthioformamid)\n");
14179 bpr 8973
  /* p2c: checkmol.pas, line 7400: Note: character >= 128 encountered [281] */
6785 bpr 8974
  if (fg[fg_urea - 1])
8975
    printf ("Harnstoff\n");
8976
  if (fg[fg_isourea - 1])
8977
    printf ("Isoharnstoff\n");
8978
  if (fg[fg_thiourea - 1])
8979
    printf ("Thioharnstoff\n");
8980
  if (fg[fg_isothiourea - 1])
8981
    printf ("Isothioharnstoff\n");
8982
  if (fg[fg_guanidine - 1])
8983
    printf ("Guanidin\n");
8984
  if (fg[fg_semicarbazide - 1])
8985
    printf ("Semicarbazid\n");
8986
  if (fg[fg_thiosemicarbazide - 1])
8987
    printf ("Thiosemicarbazid\n");
8988
  if (fg[fg_azide - 1])
8989
    printf ("Azid\n");
8990
  if (fg[fg_azo_compound - 1])
8991
    printf ("Azoverbindung\n");
8992
  if (fg[fg_diazonium_salt - 1])
8993
    printf ("Diazoniumsalz\n");
8994
  if (fg[fg_isonitrile - 1])
8995
    printf ("Isonitril\n");
8996
  if (fg[fg_cyanate - 1])
8997
    printf ("Cyanat\n");
8998
  if (fg[fg_isocyanate - 1])
8999
    printf ("Isocyanat\n");
9000
  if (fg[fg_thiocyanate - 1])
9001
    printf ("Thiocyanat\n");
9002
  if (fg[fg_isothiocyanate - 1])
9003
    printf ("Isothiocyanat\n");
9004
  if (fg[fg_carbodiimide - 1])
9005
    printf ("Carbodiimid\n");
9006
  if (fg[fg_nitroso_compound - 1])
9007
    printf ("Nitroso-Verbindung\n");
9008
  if (fg[fg_nitro_compound - 1])
9009
    printf ("Nitro-Verbindung\n");
9010
  if (fg[fg_nitrite - 1])
9011
    printf ("Nitrit\n");
9012
  if (fg[fg_nitrate - 1])
9013
    printf ("Nitrat\n");
9014
  /*  if fg[fg_sulfuric_acid_deriv]            then writeln('Schwefelsäure-Derivat'); */
9015
  if (fg[fg_sulfuric_acid - 1])
9016
    printf ("Schwefels\344ure\n");
14179 bpr 9017
  /* p2c: checkmol.pas, line 7422: Note: character >= 128 encountered [281] */
6785 bpr 9018
  if (fg[fg_sulfuric_acid_monoester - 1])
9019
    printf ("Schwefels\344uremonoester\n");
14179 bpr 9020
  /* p2c: checkmol.pas, line 7423: Note: character >= 128 encountered [281] */
6785 bpr 9021
  if (fg[fg_sulfuric_acid_diester - 1])
9022
    printf ("Schwefels\344urediester\n");
14179 bpr 9023
  /* p2c: checkmol.pas, line 7424: Note: character >= 128 encountered [281] */
6785 bpr 9024
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9025
    printf ("Schwefels\344ureamidester\n");
14179 bpr 9026
  /* p2c: checkmol.pas, line 7425: Note: character >= 128 encountered [281] */
6785 bpr 9027
  if (fg[fg_sulfuric_acid_amide - 1])
9028
    printf ("Schwefels\344ureamid\n");
14179 bpr 9029
  /* p2c: checkmol.pas, line 7426: Note: character >= 128 encountered [281] */
6785 bpr 9030
  if (fg[fg_sulfuric_acid_diamide - 1])
9031
    printf ("Schwefels\344urediamid\n");
14179 bpr 9032
  /* p2c: checkmol.pas, line 7427: Note: character >= 128 encountered [281] */
6785 bpr 9033
  if (fg[fg_sulfuryl_halide - 1])
9034
    printf ("Sulfurylhalogenid\n");
9035
  /*  if fg[fg_sulfonic_acid_deriv]            then writeln('Sulfonsäure-Derivat '); */
9036
  if (fg[fg_sulfonic_acid - 1])
9037
    printf ("Sulfons\344ure\n");
14179 bpr 9038
  /* p2c: checkmol.pas, line 7430: Note: character >= 128 encountered [281] */
6785 bpr 9039
  if (fg[fg_sulfonic_acid_ester - 1])
9040
    printf ("Sulfons\344ureester\n");
14179 bpr 9041
  /* p2c: checkmol.pas, line 7431: Note: character >= 128 encountered [281] */
6785 bpr 9042
  if (fg[fg_sulfonamide - 1])
9043
    printf ("Sulfonamid\n");
9044
  if (fg[fg_sulfonyl_halide - 1])
9045
    printf ("Sulfonylhalogenid\n");
9046
  if (fg[fg_sulfone - 1])
9047
    printf ("Sulfon\n");
9048
  if (fg[fg_sulfoxide - 1])
9049
    printf ("Sulfoxid\n");
9050
  /*  if fg[fg_sulfinic_acid_deriv]            then writeln('Sulfinsäure-Derivat'); */
9051
  if (fg[fg_sulfinic_acid - 1])
9052
    printf ("Sulfins\344ure\n");
14179 bpr 9053
  /* p2c: checkmol.pas, line 7437: Note: character >= 128 encountered [281] */
6785 bpr 9054
  if (fg[fg_sulfinic_acid_ester - 1])
9055
    printf ("Sulfins\344ureester\n");
14179 bpr 9056
  /* p2c: checkmol.pas, line 7438: Note: character >= 128 encountered [281] */
6785 bpr 9057
  if (fg[fg_sulfinic_acid_halide - 1])
9058
    printf ("Sulfins\344urehalogenid\n");
14179 bpr 9059
  /* p2c: checkmol.pas, line 7439: Note: character >= 128 encountered [281] */
6785 bpr 9060
  if (fg[fg_sulfinic_acid_amide - 1])
9061
    printf ("Sulfins\344ureamid\n");
14179 bpr 9062
  /* p2c: checkmol.pas, line 7440: Note: character >= 128 encountered [281] */
6785 bpr 9063
  /*  if fg[fg_sulfenic_acid_deriv]            then writeln('Sulfensäure-Derivat'); */
9064
  if (fg[fg_sulfenic_acid - 1])
9065
    printf ("Sulfens\344ure\n");
14179 bpr 9066
  /* p2c: checkmol.pas, line 7442: Note: character >= 128 encountered [281] */
6785 bpr 9067
  if (fg[fg_sulfenic_acid_ester - 1])
9068
    printf ("Sulfens\344ureester\n");
14179 bpr 9069
  /* p2c: checkmol.pas, line 7443: Note: character >= 128 encountered [281] */
6785 bpr 9070
  if (fg[fg_sulfenic_acid_halide - 1])
9071
    printf ("Sulfens\344urehalogenid\n");
14179 bpr 9072
  /* p2c: checkmol.pas, line 7444: Note: character >= 128 encountered [281] */
6785 bpr 9073
  if (fg[fg_sulfenic_acid_amide - 1])
9074
    printf ("Sulfens\344ureamid\n");
14179 bpr 9075
  /* p2c: checkmol.pas, line 7445: Note: character >= 128 encountered [281] */
6785 bpr 9076
  if (fg[fg_thiol - 1])
9077
    printf ("Thiol (Sulfanyl-Verbindung, Mercaptan)\n");
9078
  if (fg[fg_alkylthiol - 1])
9079
    printf ("Alkylthiol\n");
9080
  if (fg[fg_arylthiol - 1])
9081
    printf ("Arylthiol\n");
9082
  /*  if fg[fg_phosphoric_acid_deriv]          then writeln('Phosphorsäure-Derivat'); */
9083
  if (fg[fg_phosphoric_acid - 1])
9084
    printf ("Phosphors\344ure\n");
14179 bpr 9085
  /* p2c: checkmol.pas, line 7450: Note: character >= 128 encountered [281] */
6785 bpr 9086
  if (fg[fg_phosphoric_acid_ester - 1])
9087
    printf ("Phosphors\344ureester\n");
14179 bpr 9088
  /* p2c: checkmol.pas, line 7451: Note: character >= 128 encountered [281] */
6785 bpr 9089
  if (fg[fg_phosphoric_acid_halide - 1])
9090
    printf ("Phosphors\344urehalogenid\n");
14179 bpr 9091
  /* p2c: checkmol.pas, line 7452: Note: character >= 128 encountered [281] */
6785 bpr 9092
  if (fg[fg_phosphoric_acid_amide - 1])
9093
    printf ("Phosphors\344ureamid\n");
14179 bpr 9094
  /* p2c: checkmol.pas, line 7453: Note: character >= 128 encountered [281] */
6785 bpr 9095
  /*  if fg[fg_thiophosphoric_acid_deriv]      then writeln('Thiophosphorsäure-Derivat'); */
9096
  if (fg[fg_thiophosphoric_acid - 1])
9097
    printf ("Thiophosphors\344ure\n");
14179 bpr 9098
  /* p2c: checkmol.pas, line 7455: Note: character >= 128 encountered [281] */
6785 bpr 9099
  if (fg[fg_thiophosphoric_acid_ester - 1])
9100
    printf ("Thiophosphors\344ureester\n");
14179 bpr 9101
  /* p2c: checkmol.pas, line 7456: Note: character >= 128 encountered [281] */
6785 bpr 9102
  if (fg[fg_thiophosphoric_acid_halide - 1])
9103
    printf ("Thiophosphors\344urehalogenid\n");
14179 bpr 9104
  /* p2c: checkmol.pas, line 7457: Note: character >= 128 encountered [281] */
6785 bpr 9105
  if (fg[fg_thiophosphoric_acid_amide - 1])
9106
    printf ("Thiophosphors\344ureamid\n");
14179 bpr 9107
  /* p2c: checkmol.pas, line 7458: Note: character >= 128 encountered [281] */
6785 bpr 9108
  if (fg[fg_phosphonic_acid_deriv - 1])
9109
    printf ("Phosphons\344ure-Derivat \n");
14179 bpr 9110
  /* p2c: checkmol.pas, line 7459: Note: character >= 128 encountered [281] */
6785 bpr 9111
  if (fg[fg_phosphonic_acid - 1])
9112
    printf ("Phosphons\344ure\n");
14179 bpr 9113
  /* p2c: checkmol.pas, line 7460: Note: character >= 128 encountered [281] */
6785 bpr 9114
  if (fg[fg_phosphonic_acid_ester - 1])
9115
    printf ("Phosphons\344ureester\n");
14179 bpr 9116
  /* p2c: checkmol.pas, line 7461: Note: character >= 128 encountered [281] */
6785 bpr 9117
  if (fg[fg_phosphine - 1])
9118
    printf ("Phosphin\n");
9119
  if (fg[fg_phosphinoxide - 1])
9120
    printf ("Phosphinoxid\n");
9121
  if (fg[fg_boronic_acid_deriv - 1])
9122
    printf ("Borons\344ure-Derivat\n");
14179 bpr 9123
  /* p2c: checkmol.pas, line 7464: Note: character >= 128 encountered [281] */
6785 bpr 9124
  if (fg[fg_boronic_acid - 1])
9125
    printf ("Borons\344ure\n");
14179 bpr 9126
  /* p2c: checkmol.pas, line 7465: Note: character >= 128 encountered [281] */
6785 bpr 9127
  if (fg[fg_boronic_acid_ester - 1])
9128
    printf ("Borons\344ureester\n");
14179 bpr 9129
  /* p2c: checkmol.pas, line 7466: Note: character >= 128 encountered [281] */
6785 bpr 9130
  if (fg[fg_alkene - 1])
9131
    printf ("Alken\n");
9132
  if (fg[fg_alkyne - 1])
9133
    printf ("Alkin\n");
9134
  if (fg[fg_aromatic - 1])
9135
    printf ("aromatische Verbindung\n");
9136
  if (fg[fg_heterocycle - 1])
9137
    printf ("heterocyclische Verbindung\n");
9138
  if (fg[fg_alpha_aminoacid - 1])
9139
    printf ("alpha-Aminos\344ure\n");
14179 bpr 9140
  /* p2c: checkmol.pas, line 7471: Note: character >= 128 encountered [281] */
6785 bpr 9141
  if (fg[fg_alpha_hydroxyacid - 1])
9142
    printf ("alpha-Hydroxys\344ure\n");
14179 bpr 9143
  /* p2c: checkmol.pas, line 7472: Note: character >= 128 encountered [281] */
6785 bpr 9144
}
9145
 
9146
#define sc              ';'
9147
 
14179 bpr 9148
static void write_fg_code ()
6785 bpr 9149
{
9150
  if (fg[fg_cation - 1])
9151
    printf ("000000T2%c", sc);
9152
  if (fg[fg_anion - 1])
9153
    printf ("000000T1%c", sc);
9154
  /*  if fg[fg_carbonyl]                       then write('C2O10000',sc); */
9155
  if (fg[fg_aldehyde - 1])
9156
    printf ("C2O1H000%c", sc);
9157
  if (fg[fg_ketone - 1])
9158
    printf ("C2O1C000%c", sc);
9159
  /*  if fg[fg_thiocarbonyl]                   then write('C2S10000',sc); */
9160
  if (fg[fg_thioaldehyde - 1])
9161
    printf ("C2S1H000%c", sc);
9162
  if (fg[fg_thioketone - 1])
9163
    printf ("C2S1C000%c", sc);
9164
  if (fg[fg_imine - 1])
9165
    printf ("C2N10000%c", sc);
9166
  if (fg[fg_hydrazone - 1])
9167
    printf ("C2N1N000%c", sc);
9168
  if (fg[fg_semicarbazone - 1])
9169
    printf ("C2NNC4ON%c", sc);
9170
  if (fg[fg_thiosemicarbazone - 1])
9171
    printf ("C2NNC4SN%c", sc);
9172
  if (fg[fg_oxime - 1])
9173
    printf ("C2N1OH00%c", sc);
9174
  if (fg[fg_oxime_ether - 1])
9175
    printf ("C2N1OC00%c", sc);
9176
  if (fg[fg_ketene - 1])
9177
    printf ("C3OC0000%c", sc);
9178
  if (fg[fg_ketene_acetal_deriv - 1])
9179
    printf ("C3OCC000%c", sc);
9180
  if (fg[fg_carbonyl_hydrate - 1])
9181
    printf ("C2O2H200%c", sc);
9182
  if (fg[fg_hemiacetal - 1])
9183
    printf ("C2O2HC00%c", sc);
9184
  if (fg[fg_acetal - 1])
9185
    printf ("C2O2CC00%c", sc);
9186
  if (fg[fg_hemiaminal - 1])
9187
    printf ("C2NOHC10%c", sc);
9188
  if (fg[fg_aminal - 1])
9189
    printf ("C2N2CC10%c", sc);
9190
  if (fg[fg_thiohemiaminal - 1])
9191
    printf ("C2NSHC10%c", sc);
9192
  if (fg[fg_thioacetal - 1])
9193
    printf ("C2S2CC00%c", sc);
9194
  if (fg[fg_enamine - 1])
9195
    printf ("C2CNH000%c", sc);
9196
  if (fg[fg_enol - 1])
9197
    printf ("C2COH000%c", sc);
9198
  if (fg[fg_enolether - 1])
9199
    printf ("C2COC000%c", sc);
9200
  if (fg[fg_hydroxy - 1] && hydroxy_generic)
9201
    printf ("O1H00000%c", sc);
9202
  /*  if fg[fg_alcohol]                        then write('O1H0C000',sc); */
9203
  if (fg[fg_prim_alcohol - 1])
9204
    printf ("O1H1C000%c", sc);
9205
  if (fg[fg_sec_alcohol - 1])
9206
    printf ("O1H2C000%c", sc);
9207
  if (fg[fg_tert_alcohol - 1])
9208
    printf ("O1H3C000%c", sc);
9209
  if (fg[fg_1_2_diol - 1])
9210
    printf ("O1H0CO1H%c", sc);
9211
  if (fg[fg_1_2_aminoalcohol - 1])
9212
    printf ("O1H0CN1C%c", sc);
9213
  if (fg[fg_phenol - 1])
9214
    printf ("O1H1A000%c", sc);
9215
  if (fg[fg_1_2_diphenol - 1])
9216
    printf ("O1H2A000%c", sc);
9217
  if (fg[fg_enediol - 1])
9218
    printf ("C2COH200%c", sc);
9219
  if (fg[fg_ether - 1] && ether_generic)
9220
    printf ("O1C00000%c", sc);
9221
  if (fg[fg_dialkylether - 1])
9222
    printf ("O1C0CC00%c", sc);
9223
  if (fg[fg_alkylarylether - 1])
9224
    printf ("O1C0CA00%c", sc);
9225
  if (fg[fg_diarylether - 1])
9226
    printf ("O1C0AA00%c", sc);
9227
  if (fg[fg_thioether - 1])
9228
    printf ("S1C00000%c", sc);
9229
  if (fg[fg_disulfide - 1])
9230
    printf ("S1S1C000%c", sc);
9231
  if (fg[fg_peroxide - 1])
9232
    printf ("O1O1C000%c", sc);
9233
  if (fg[fg_hydroperoxide - 1])
9234
    printf ("O1O1H000%c", sc);
9235
  if (fg[fg_hydrazine - 1])
9236
    printf ("N1N10000%c", sc);
9237
  if (fg[fg_hydroxylamine - 1])
9238
    printf ("N1O1H000%c", sc);
9239
  if (fg[fg_amine - 1] && amine_generic)
9240
    printf ("N1C00000%c", sc);
9241
  /*  if fg[fg_prim_amine]                     then write('N1C10000',sc); */
9242
  if (fg[fg_prim_aliph_amine - 1])
9243
    printf ("N1C1C000%c", sc);
9244
  if (fg[fg_prim_arom_amine - 1])
9245
    printf ("N1C1A000%c", sc);
9246
  /*  if fg[fg_sec_amine]                      then write('N1C20000',sc); */
9247
  if (fg[fg_sec_aliph_amine - 1])
9248
    printf ("N1C2CC00%c", sc);
9249
  if (fg[fg_sec_mixed_amine - 1])
9250
    printf ("N1C2AC00%c", sc);
9251
  if (fg[fg_sec_arom_amine - 1])
9252
    printf ("N1C2AA00%c", sc);
9253
  /*  if fg[fg_tert_amine]                     then write('N1C30000',sc); */
9254
  if (fg[fg_tert_aliph_amine - 1])
9255
    printf ("N1C3CC00%c", sc);
9256
  if (fg[fg_tert_mixed_amine - 1])
9257
    printf ("N1C3AC00%c", sc);
9258
  if (fg[fg_tert_arom_amine - 1])
9259
    printf ("N1C3AA00%c", sc);
9260
  if (fg[fg_quart_ammonium - 1])
9261
    printf ("N1C400T2%c", sc);
9262
  if (fg[fg_n_oxide - 1])
9263
    printf ("N0O10000%c", sc);
9264
  /*  if fg[fg_halogen_deriv]                  then write('XX000000',sc); */
9265
  /* new in v0.2f */
14179 bpr 9266
  if (fg[fg_halogen_deriv - 1]) {
9267
      if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1])
9268
              printf ("XX000000%c", sc);
9269
  }
6785 bpr 9270
  /*  if fg[fg_alkyl_halide]                   then write('XX00C000',sc); */
9271
  if (fg[fg_alkyl_fluoride - 1])
9272
    printf ("XF00C000%c", sc);
9273
  if (fg[fg_alkyl_chloride - 1])
9274
    printf ("XC00C000%c", sc);
9275
  if (fg[fg_alkyl_bromide - 1])
9276
    printf ("XB00C000%c", sc);
9277
  if (fg[fg_alkyl_iodide - 1])
9278
    printf ("XI00C000%c", sc);
9279
  /*  if fg[fg_aryl_halide]                    then write('XX00A000',sc); */
9280
  if (fg[fg_aryl_fluoride - 1])
9281
    printf ("XF00A000%c", sc);
9282
  if (fg[fg_aryl_chloride - 1])
9283
    printf ("XC00A000%c", sc);
9284
  if (fg[fg_aryl_bromide - 1])
9285
    printf ("XB00A000%c", sc);
9286
  if (fg[fg_aryl_iodide - 1])
9287
    printf ("XI00A000%c", sc);
9288
  if (fg[fg_organometallic - 1])
9289
    printf ("000000MX%c", sc);
9290
  if (fg[fg_organolithium - 1])
9291
    printf ("000000ML%c", sc);
9292
  if (fg[fg_organomagnesium - 1])
9293
    printf ("000000MM%c", sc);
9294
  /*  if fg[fg_carboxylic_acid_deriv]          then write('C3O20000',sc); */
9295
  if (fg[fg_carboxylic_acid - 1])
9296
    printf ("C3O2H000%c", sc);
9297
  if (fg[fg_carboxylic_acid_salt - 1])
9298
    printf ("C3O200T1%c", sc);
9299
  if (fg[fg_carboxylic_acid_ester - 1])
9300
    printf ("C3O2C000%c", sc);
9301
  if (fg[fg_lactone - 1])
9302
    printf ("C3O2CZ00%c", sc);
9303
  /*  if fg[fg_carboxylic_acid_amide]          then write('C3ONC000',sc); */
9304
  if (fg[fg_carboxylic_acid_prim_amide - 1])
9305
    printf ("C3ONC100%c", sc);
9306
  if (fg[fg_carboxylic_acid_sec_amide - 1])
9307
    printf ("C3ONC200%c", sc);
9308
  if (fg[fg_carboxylic_acid_tert_amide - 1])
9309
    printf ("C3ONC300%c", sc);
9310
  if (fg[fg_lactam - 1])
9311
    printf ("C3ONCZ00%c", sc);
9312
  if (fg[fg_carboxylic_acid_hydrazide - 1])
9313
    printf ("C3ONN100%c", sc);
9314
  if (fg[fg_carboxylic_acid_azide - 1])
9315
    printf ("C3ONN200%c", sc);
9316
  if (fg[fg_hydroxamic_acid - 1])
9317
    printf ("C3ONOH00%c", sc);
9318
  if (fg[fg_carboxylic_acid_amidine - 1])
9319
    printf ("C3N2H000%c", sc);
9320
  if (fg[fg_carboxylic_acid_amidrazone - 1])
9321
    printf ("C3NNN100%c", sc);
9322
  if (fg[fg_nitrile - 1])
9323
    printf ("C3N00000%c", sc);
9324
  /*  if fg[fg_acyl_halide]                    then write('C3OXX000',sc); */
9325
  if (fg[fg_acyl_fluoride - 1])
9326
    printf ("C3OXF000%c", sc);
9327
  if (fg[fg_acyl_chloride - 1])
9328
    printf ("C3OXC000%c", sc);
9329
  if (fg[fg_acyl_bromide - 1])
9330
    printf ("C3OXB000%c", sc);
9331
  if (fg[fg_acyl_iodide - 1])
9332
    printf ("C3OXI000%c", sc);
9333
  if (fg[fg_acyl_cyanide - 1])
9334
    printf ("C2OC3N00%c", sc);
9335
  if (fg[fg_imido_ester - 1])
9336
    printf ("C3NOC000%c", sc);
9337
  if (fg[fg_imidoyl_halide - 1])
9338
    printf ("C3NXX000%c", sc);
9339
  /*  if fg[fg_thiocarboxylic_acid_deriv]      then write('C3SO0000',sc); */
9340
  if (fg[fg_thiocarboxylic_acid - 1])
9341
    printf ("C3SOH000%c", sc);
9342
  if (fg[fg_thiocarboxylic_acid_ester - 1])
9343
    printf ("C3SOC000%c", sc);
9344
  if (fg[fg_thiolactone - 1])
9345
    printf ("C3SOCZ00%c", sc);
9346
  if (fg[fg_thiocarboxylic_acid_amide - 1])
9347
    printf ("C3SNH000%c", sc);
9348
  if (fg[fg_thiolactam - 1])
9349
    printf ("C3SNCZ00%c", sc);
9350
  if (fg[fg_imido_thioester - 1])
9351
    printf ("C3NSC000%c", sc);
9352
  if (fg[fg_oxohetarene - 1])
9353
    printf ("C3ONAZ00%c", sc);
9354
  if (fg[fg_thioxohetarene - 1])
9355
    printf ("C3SNAZ00%c", sc);
9356
  if (fg[fg_iminohetarene - 1])
9357
    printf ("C3NNAZ00%c", sc);
9358
  if (fg[fg_orthocarboxylic_acid_deriv - 1])
9359
    printf ("C3O30000%c", sc);
9360
  if (fg[fg_carboxylic_acid_orthoester - 1])
9361
    printf ("C3O3C000%c", sc);
9362
  if (fg[fg_carboxylic_acid_amide_acetal - 1])
9363
    printf ("C3O3NC00%c", sc);
9364
  if (fg[fg_carboxylic_acid_anhydride - 1])
9365
    printf ("C3O2C3O2%c", sc);
9366
  /*  if fg[fg_carboxylic_acid_imide]          then write('C3ONC000',sc); */
9367
  if (fg[fg_carboxylic_acid_unsubst_imide - 1])
9368
    printf ("C3ONCH10%c", sc);
9369
  if (fg[fg_carboxylic_acid_subst_imide - 1])
9370
    printf ("C3ONCC10%c", sc);
9371
  if (fg[fg_co2_deriv - 1])
9372
    printf ("C4000000%c", sc);
9373
  if (fg[fg_carbonic_acid_deriv - 1])
9374
    printf ("C4O30000%c", sc);
9375
  if (fg[fg_carbonic_acid_monoester - 1])
9376
    printf ("C4O3C100%c", sc);
9377
  if (fg[fg_carbonic_acid_diester - 1])
9378
    printf ("C4O3C200%c", sc);
9379
  if (fg[fg_carbonic_acid_ester_halide - 1])
9380
    printf ("C4O3CX00%c", sc);
9381
  if (fg[fg_thiocarbonic_acid_deriv - 1])
9382
    printf ("C4SO0000%c", sc);
9383
  if (fg[fg_thiocarbonic_acid_monoester - 1])
9384
    printf ("C4SOC100%c", sc);
9385
  if (fg[fg_thiocarbonic_acid_diester - 1])
9386
    printf ("C4SOC200%c", sc);
9387
  if (fg[fg_thiocarbonic_acid_ester_halide - 1])
9388
    printf ("C4SOX_00%c", sc);
9389
  if (fg[fg_carbamic_acid_deriv - 1])
9390
    printf ("C4O2N000%c", sc);
9391
  if (fg[fg_carbamic_acid - 1])
9392
    printf ("C4O2NH00%c", sc);
9393
  if (fg[fg_carbamic_acid_ester - 1])
9394
    printf ("C4O2NC00%c", sc);
9395
  if (fg[fg_carbamic_acid_halide - 1])
9396
    printf ("C4O2NX00%c", sc);
9397
  if (fg[fg_thiocarbamic_acid_deriv - 1])
9398
    printf ("C4SN0000%c", sc);
9399
  if (fg[fg_thiocarbamic_acid - 1])
9400
    printf ("C4SNOH00%c", sc);
9401
  if (fg[fg_thiocarbamic_acid_ester - 1])
9402
    printf ("C4SNOC00%c", sc);
9403
  if (fg[fg_thiocarbamic_acid_halide - 1])
9404
    printf ("C4SNXX00%c", sc);
9405
  if (fg[fg_urea - 1])
9406
    printf ("C4O1N200%c", sc);
9407
  if (fg[fg_isourea - 1])
9408
    printf ("C4N2O100%c", sc);
9409
  if (fg[fg_thiourea - 1])
9410
    printf ("C4S1N200%c", sc);
9411
  if (fg[fg_isothiourea - 1])
9412
    printf ("C4N2S100%c", sc);
9413
  if (fg[fg_guanidine - 1])
9414
    printf ("C4N30000%c", sc);
9415
  if (fg[fg_semicarbazide - 1])
9416
    printf ("C4ON2N00%c", sc);
9417
  if (fg[fg_thiosemicarbazide - 1])
9418
    printf ("C4SN2N00%c", sc);
9419
  if (fg[fg_azide - 1])
9420
    printf ("N4N20000%c", sc);
9421
  if (fg[fg_azo_compound - 1])
9422
    printf ("N2N10000%c", sc);
9423
  if (fg[fg_diazonium_salt - 1])
9424
    printf ("N3N100T2%c", sc);
9425
  if (fg[fg_isonitrile - 1])
9426
    printf ("N3C10000%c", sc);
9427
  if (fg[fg_cyanate - 1])
9428
    printf ("C4NO1000%c", sc);
9429
  if (fg[fg_isocyanate - 1])
9430
    printf ("C4NO2000%c", sc);
9431
  if (fg[fg_thiocyanate - 1])
9432
    printf ("C4NS1000%c", sc);
9433
  if (fg[fg_isothiocyanate - 1])
9434
    printf ("C4NS2000%c", sc);
9435
  if (fg[fg_carbodiimide - 1])
9436
    printf ("C4N20000%c", sc);
9437
  if (fg[fg_nitroso_compound - 1])
9438
    printf ("N2O10000%c", sc);
9439
  if (fg[fg_nitro_compound - 1])
9440
    printf ("N4O20000%c", sc);
9441
  if (fg[fg_nitrite - 1])
9442
    printf ("N3O20000%c", sc);
9443
  if (fg[fg_nitrate - 1])
9444
    printf ("N4O30000%c", sc);
9445
  if (fg[fg_sulfuric_acid_deriv - 1])
9446
    printf ("S6O00000%c", sc);
9447
  if (fg[fg_sulfuric_acid - 1])
9448
    printf ("S6O4H000%c", sc);
9449
  if (fg[fg_sulfuric_acid_monoester - 1])
9450
    printf ("S6O4HC00%c", sc);
9451
  if (fg[fg_sulfuric_acid_diester - 1])
9452
    printf ("S6O4CC00%c", sc);
9453
  if (fg[fg_sulfuric_acid_amide_ester - 1])
9454
    printf ("S6O3NC00%c", sc);
9455
  if (fg[fg_sulfuric_acid_amide - 1])
9456
    printf ("S6O3N100%c", sc);
9457
  if (fg[fg_sulfuric_acid_diamide - 1])
9458
    printf ("S6O2N200%c", sc);
9459
  if (fg[fg_sulfuryl_halide - 1])
9460
    printf ("S6O3XX00%c", sc);
9461
  if (fg[fg_sulfonic_acid_deriv - 1])
9462
    printf ("S5O00000%c", sc);
9463
  if (fg[fg_sulfonic_acid - 1])
9464
    printf ("S5O3H000%c", sc);
9465
  if (fg[fg_sulfonic_acid_ester - 1])
9466
    printf ("S5O3C000%c", sc);
9467
  if (fg[fg_sulfonamide - 1])
9468
    printf ("S5O2N000%c", sc);
9469
  if (fg[fg_sulfonyl_halide - 1])
9470
    printf ("S5O2XX00%c", sc);
9471
  if (fg[fg_sulfone - 1])
9472
    printf ("S4O20000%c", sc);
9473
  if (fg[fg_sulfoxide - 1])
9474
    printf ("S2O10000%c", sc);
9475
  if (fg[fg_sulfinic_acid_deriv - 1])
9476
    printf ("S3O00000%c", sc);
9477
  if (fg[fg_sulfinic_acid - 1])
9478
    printf ("S3O2H000%c", sc);
9479
  if (fg[fg_sulfinic_acid_ester - 1])
9480
    printf ("S3O2C000%c", sc);
9481
  if (fg[fg_sulfinic_acid_halide - 1])
9482
    printf ("S3O1XX00%c", sc);
9483
  if (fg[fg_sulfinic_acid_amide - 1])
9484
    printf ("S3O1N000%c", sc);
9485
  if (fg[fg_sulfenic_acid_deriv - 1])
9486
    printf ("S1O00000%c", sc);
9487
  if (fg[fg_sulfenic_acid - 1])
9488
    printf ("S1O1H000%c", sc);
9489
  if (fg[fg_sulfenic_acid_ester - 1])
9490
    printf ("S1O1C000%c", sc);
9491
  if (fg[fg_sulfenic_acid_halide - 1])
9492
    printf ("S1O0XX00%c", sc);
9493
  if (fg[fg_sulfenic_acid_amide - 1])
9494
    printf ("S1O0N100%c", sc);
9495
  /*  if fg[fg_thiol]                          then write('S1H10000',sc); */
9496
  if (fg[fg_alkylthiol - 1])
9497
    printf ("S1H1C000%c", sc);
9498
  if (fg[fg_arylthiol - 1])
9499
    printf ("S1H1A000%c", sc);
9500
  if (fg[fg_phosphoric_acid_deriv - 1])
9501
    printf ("P5O0H000%c", sc);
9502
  if (fg[fg_phosphoric_acid - 1])
9503
    printf ("P5O4H200%c", sc);
9504
  if (fg[fg_phosphoric_acid_ester - 1])
9505
    printf ("P5O4HC00%c", sc);
9506
  if (fg[fg_phosphoric_acid_halide - 1])
9507
    printf ("P5O3HX00%c", sc);
9508
  if (fg[fg_phosphoric_acid_amide - 1])
9509
    printf ("P5O3HN00%c", sc);
9510
  if (fg[fg_thiophosphoric_acid_deriv - 1])
9511
    printf ("P5O0S000%c", sc);
9512
  if (fg[fg_thiophosphoric_acid - 1])
9513
    printf ("P5O3SH00%c", sc);
9514
  if (fg[fg_thiophosphoric_acid_ester - 1])
9515
    printf ("P5O3SC00%c", sc);
9516
  if (fg[fg_thiophosphoric_acid_halide - 1])
9517
    printf ("P5O2SX00%c", sc);
9518
  if (fg[fg_thiophosphoric_acid_amide - 1])
9519
    printf ("P5O2SN00%c", sc);
9520
  if (fg[fg_phosphonic_acid_deriv - 1])
9521
    printf ("P4O30000%c", sc);
9522
  if (fg[fg_phosphonic_acid - 1])
9523
    printf ("P4O3H000%c", sc);
9524
  if (fg[fg_phosphonic_acid_ester - 1])
9525
    printf ("P4O3C000%c", sc);
9526
  if (fg[fg_phosphine - 1])
9527
    printf ("P3000000%c", sc);
9528
  if (fg[fg_phosphinoxide - 1])
9529
    printf ("P2O00000%c", sc);
9530
  if (fg[fg_boronic_acid_deriv - 1])
9531
    printf ("B2O20000%c", sc);
9532
  if (fg[fg_boronic_acid - 1])
9533
    printf ("B2O2H000%c", sc);
9534
  if (fg[fg_boronic_acid_ester - 1])
9535
    printf ("B2O2C000%c", sc);
9536
  if (fg[fg_alkene - 1])
9537
    printf ("000C2C00%c", sc);
9538
  if (fg[fg_alkyne - 1])
9539
    printf ("000C3C00%c", sc);
9540
  if (fg[fg_aromatic - 1])
9541
    printf ("0000A000%c", sc);
9542
  if (fg[fg_heterocycle - 1])
9543
    printf ("0000CZ00%c", sc);
9544
  if (fg[fg_alpha_aminoacid - 1])
9545
    printf ("C3O2HN1C%c", sc);
9546
  if (fg[fg_alpha_hydroxyacid - 1])
9547
    printf ("C3O2HO1H%c", sc);
9548
}
9549
 
9550
#undef sc
9551
 
14179 bpr 9552
static void write_fg_binary ()
6785 bpr 9553
{
9554
  int i, n;
9555
  char o;
9556
 
14179 bpr 9557
  for (i = 1; i <= max_fg / 8; i++) {
9558
    n = 0;
9559
    if (fg[i * 8 - 1])
9560
            n++;
9561
    if (fg[i * 8 - 2])
9562
            n += 2;
9563
    if (fg[i * 8 - 3])
9564
            n += 4;
9565
    if (fg[i * 8 - 4])
9566
            n += 8;
9567
    if (fg[i * 8 - 5])
9568
            n += 16;
9569
    if (fg[i * 8 - 6])
9570
            n += 32;
9571
    if (fg[i * 8 - 7])
9572
            n += 64;
9573
    if (fg[i * 8 - 8])
9574
            n += 128;
9575
    o = (char) n;
9576
    putchar (o);
9577
  }
6785 bpr 9578
}
9579
 
14179 bpr 9580
static void write_fg_bitstring ()
6785 bpr 9581
{
9582
  int i;
9583
 
14179 bpr 9584
  for (i = 0; i < max_fg; i++) {
9585
    if (fg[i])
9586
            putchar ('1');
9587
    else
9588
            putchar ('0');
9589
  }
6785 bpr 9590
}
9591
 
9592
#if 0
9593
static void readinputfile (molfilename) char *molfilename;
14179 bpr 9594
  {
9595
  /* new version in v0.2g */
9596
  char rline[256];
9597
  char *TEMP;
6785 bpr 9598
 
14179 bpr 9599
  molbufindex = 0;
9600
  if (!opt_stdin)
9601
  {
9602
  if (!rfile_is_open)
9603
  {
9604
  assign (rfile, molfilename);
9605
  rewind (rfile);
9606
  rfile_is_open = true;
9607
  }
9608
  /* p2c: checkmol.pas, line 7733: Warning:
9609
  * Don't know how to ASSIGN to a non-explicit file variable [207] */
9610
  *rline = '\0';
9611
  mol_in_queue = false;
9612
  while ((!P_eof (rfile)) && (strpos2 (rline, "$$$$", 1) == 0))
9613
  {
9614
  fgets (rline, 256, rfile);
9615
  TEMP = strchr (rline, '\n');
9616
  if (TEMP != NULL)
9617
  *TEMP = 0;
9618
  /*mol_in_queue := false; */
9619
  if (molbufindex >= max_atoms + max_bonds + 64)
9620
  {
9621
  printf ("Not enough memory for molfile! %12ld\n",
9622
  molbufindex);
9623
  if (rfile != NULL)
9624
  fclose (rfile);
9625
  rfile = NULL;
9626
  _Escape (1);
9627
  }
9628
  molbufindex++;
9629
  strcpy (molbuf[molbufindex - 1], rline);
9630
  if (strpos2 (rline, "$$$$", 1) > 0)
9631
  mol_in_queue = true;
9632
  }
9633
  if (!P_eof (rfile))
9634
  return;
9635
  if (rfile != NULL)
9636
  fclose (rfile);
9637
  rfile = NULL;
9638
  rfile_is_open = false;
9639
  mol_in_queue = false;
9640
  return;
9641
  }
9642
  *rline = '\0';
9643
  mol_in_queue = false;
9644
  while ((!P_eof (stdin)) && (strpos2 (rline, "$$$$", 1) == 0))
9645
  {
9646
  gets (rline);
9647
  if (molbufindex >= max_atoms + max_bonds + 64)
9648
  {
9649
  printf ("Not enough memory!\n");
9650
  _Escape (1);
9651
  }
9652
  molbufindex++;
9653
  strcpy (molbuf[molbufindex - 1], rline);
9654
  if (strpos2 (rline, "$$$$", 1) > 0)
9655
  {
9656
  mol_in_queue = true;
9657
  /* read from standard input
9658
  }
9659
  }
9660
  } */
6785 bpr 9661
#endif
9662
 
14179 bpr 9663
static void readinputfile (char *molfilename)
6785 bpr 9664
{
9665
  /* new version in v0.2g */
9666
  char rline[256];
9667
  char *TEMP;
9668
 
9669
  molbufindex = 0;
14179 bpr 9670
  if (!opt_stdin) {
9671
    if (!rfile_is_open) {
9672
            rfile = fopen (molfilename, "r");
9673
            rewind (rfile);
9674
            rfile_is_open = true;
9675
          }
9676
    /* p2c: checkmol.pas, line 7226: Warning:
9677
     * Don't know how to ASSIGN to a non-explicit file variable [207] */
9678
    *rline = '\0';
9679
    mol_in_queue = false;
9680
    while ((fgets (rline, 256, rfile) != NULL) && (strstr (rline, "$$$$") == NULL)) {
9681
            TEMP = strchr (rline, '\n');
9682
            if (TEMP != NULL)
9683
              *TEMP = 0;
9684
            /*mol_in_queue := false; */
9685
            if (molbufindex >= max_atoms + max_bonds + 64) {
6785 bpr 9686
              printf ("Not enough memory for molfile! %d\n", molbufindex);
9687
              if (rfile != NULL)
14179 bpr 9688
                      fclose (rfile);
6785 bpr 9689
              rfile = NULL;
9690
              exit (1);
9691
            }
14179 bpr 9692
            //molbufindex++;
9693
            strcpy (molbuf[molbufindex++], rline);
9694
            if (strstr (rline, "$$$$") != NULL)
9695
              mol_in_queue = true;
9696
          }
9697
    if (!feof (rfile))
9698
            return;
9699
    if (rfile != NULL)
9700
            fclose (rfile);
9701
    rfile = NULL;
9702
    rfile_is_open = false;
9703
    mol_in_queue = false;
9704
    return;
9705
  }
6785 bpr 9706
  *rline = '\0';
9707
  mol_in_queue = false;
14179 bpr 9708
  do {
9709
    if(fgets (rline, 256, stdin)==NULL || feof (stdin))
9710
            return;
9711
    TEMP = strchr (rline, '\n');
9712
    if (TEMP != NULL)
9713
            *TEMP = '\0';
9714
    if (molbufindex >= max_atoms + max_bonds + 64) {
9715
            printf ("Not enough memory!\n");
9716
            exit (1);
9717
          }
9718
    //molbufindex++;
9719
    strcpy (molbuf[molbufindex++], rline);
9720
    if (strstr (rline, "$$$$") != NULL) {
9721
            mol_in_queue = true;
9722
            /* read from standard input */
9723
          }
9724
  }
6785 bpr 9725
  while (strstr (rline, "$$$$") == NULL);
9726
}
9727
 
9728
#if 0
9729
static void copy_mol_to_needle()
9730
{
9731
  int i, j, FORLIM;
9732
 
9733
  if (n_atoms == 0)
9734
    return;
9735
  /* try */
9736
  ndl_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9737
  ndl_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9738
  ndl_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9739
  ndl_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9740
  /* except*/
9741
    on e:Eoutofmemory do
9742
      begin
9743
        writeln('Not enough memory');
9744
        halt(4);
9745
      end;
14179 bpr 9746
  end;
6785 bpr 9747
  ndl_n_atoms = n_atoms;
9748
  ndl_n_bonds = n_bonds;
9749
  ndl_n_rings = n_rings;
9750
  ndl_n_heavyatoms = n_heavyatoms;
9751
  ndl_n_heavybonds = n_heavybonds;
9752
  strcpy(ndl_molname, molname);
9753
  ndl_n_Ctot = n_Ctot;
9754
  ndl_n_Otot = n_Otot;
9755
  ndl_n_Ntot = n_Ntot;
9756
  FORLIM = n_atoms;
9757
  for (i = 0; i < FORLIM; i++) {
9758
    strcpy(ndl_atom[i].element, atom[i].element);
9759
    strcpy(ndl_atom[i].atype, atom[i].atype);
9760
    ndl_atom[i].x = atom[i].x;
9761
    ndl_atom[i].y = atom[i].y;
9762
    ndl_atom[i].z = atom[i].z;
9763
    ndl_atom[i].formal_charge = atom[i].formal_charge;
9764
    ndl_atom[i].real_charge = atom[i].real_charge;
9765
    ndl_atom[i].Hexp = atom[i].Hexp;
9766
    ndl_atom[i].Htot = atom[i].Htot;
9767
    ndl_atom[i].neighbor_count = atom[i].neighbor_count;
9768
    ndl_atom[i].ring_count = atom[i].ring_count;
9769
    ndl_atom[i].arom = atom[i].arom;
9770
    ndl_atom[i].stereo_care = atom[i].stereo_care;
9771
    ndl_atom[i].heavy = atom[i].heavy;   /* v0.3l */
9772
    ndl_atom[i].metal = atom[i].metal;   /* v0.3l */
9773
    ndl_atom[i].tag = atom[i].tag;      /* v0.3o */
14179 bpr 9774
        }
9775
        if (n_bonds > 0) {
9776
          FORLIM = n_bonds;
9777
          for (i = 0; i < FORLIM; i++) {
9778
            ndl_bond[i].a1 = bond[i].a1;
9779
            ndl_bond[i].a2 = bond[i].a2;
9780
            ndl_bond[i].btype = bond[i].btype;
9781
            ndl_bond[i].arom = bond[i].arom;
9782
            ndl_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
9783
            ndl_bond[i].topo = bond[i].topo;   /* new in v0.3d */
9784
            ndl_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
9785
          }
9786
        }
9787
        if (n_rings > 0) {
9788
          FORLIM = n_rings;
9789
          for (i = 0; i < FORLIM; i++) {
9790
            for (j = 0; j < max_ringsize; j++)
9791
              ndl_ring[i][j] = ring[i][j];
9792
          }
9793
          for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
9794
            ndl_ringprop[i].size = ringprop[i].size;
9795
            ndl_ringprop[i].arom = ringprop[i].arom;
9796
            ndl_ringprop[i].envelope = ringprop[i].envelope;
9797
          }
9798
        }
9799
        ndl_molstat.n_QA = molstat.n_QA;
9800
  ndl_molstat.n_QB = molstat.n_QB;
9801
  ndl_molstat.n_chg = molstat.n_chg;
9802
  ndl_molstat.n_C1 = molstat.n_C1;
9803
  ndl_molstat.n_C2 = molstat.n_C2;
9804
  ndl_molstat.n_C = molstat.n_C;
9805
  ndl_molstat.n_CHB1p = molstat.n_CHB1p;
9806
  ndl_molstat.n_CHB2p = molstat.n_CHB2p;
9807
  ndl_molstat.n_CHB3p = molstat.n_CHB3p;
9808
  ndl_molstat.n_CHB4 = molstat.n_CHB4;
9809
  ndl_molstat.n_O2 = molstat.n_O2;
9810
  ndl_molstat.n_O3 = molstat.n_O3;
9811
  ndl_molstat.n_N1 = molstat.n_N1;
9812
  ndl_molstat.n_N2 = molstat.n_N2;
9813
  ndl_molstat.n_N3 = molstat.n_N3;
9814
  ndl_molstat.n_S = molstat.n_S;
9815
  ndl_molstat.n_SeTe = molstat.n_SeTe;
9816
  ndl_molstat.n_F = molstat.n_F;
9817
  ndl_molstat.n_Cl = molstat.n_Cl;
9818
  ndl_molstat.n_Br = molstat.n_Br;
9819
  ndl_molstat.n_I = molstat.n_I;
9820
  ndl_molstat.n_P = molstat.n_P;
9821
  ndl_molstat.n_B = molstat.n_B;
9822
  ndl_molstat.n_Met = molstat.n_Met;
9823
  ndl_molstat.n_X = molstat.n_X;
9824
  ndl_molstat.n_b1 = molstat.n_b1;
9825
  ndl_molstat.n_b2 = molstat.n_b2;
9826
  ndl_molstat.n_b3 = molstat.n_b3;
9827
  ndl_molstat.n_bar = molstat.n_bar;
9828
  ndl_molstat.n_C1O = molstat.n_C1O;
9829
  ndl_molstat.n_C2O = molstat.n_C2O;
9830
  ndl_molstat.n_CN = molstat.n_CN;
9831
  ndl_molstat.n_XY = molstat.n_XY;
9832
  ndl_molstat.n_r3 = molstat.n_r3;
9833
  ndl_molstat.n_r4 = molstat.n_r4;
9834
  ndl_molstat.n_r5 = molstat.n_r5;
9835
  ndl_molstat.n_r6 = molstat.n_r6;
9836
  ndl_molstat.n_r7 = molstat.n_r7;
9837
        ndl_molstat.n_r8 = molstat.n_r8;
9838
        ndl_molstat.n_r9 = molstat.n_r9;
9839
        ndl_molstat.n_r10 = molstat.n_r10;
9840
        ndl_molstat.n_r11 = molstat.n_r11;
9841
        ndl_molstat.n_r12 = molstat.n_r12;
9842
        ndl_molstat.n_r13p = molstat.n_r13p;
9843
        ndl_molstat.n_rN = molstat.n_rN;
9844
        ndl_molstat.n_rN1 = molstat.n_rN1;
9845
        ndl_molstat.n_rN2 = molstat.n_rN2;
9846
        ndl_molstat.n_rN3p = molstat.n_rN3p;
9847
        ndl_molstat.n_rO = molstat.n_rO;
9848
        ndl_molstat.n_rO1 = molstat.n_rO1;
9849
        ndl_molstat.n_rO2p = molstat.n_rO2p;
9850
        ndl_molstat.n_rS = molstat.n_rS;
9851
        ndl_molstat.n_rX = molstat.n_rX;
9852
        ndl_molstat.n_rAr = molstat.n_rAr;
9853
        ndl_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
9854
        ndl_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
9855
        /* p2c: checkmol.pas, line 7875:
9856
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
9857
        /*$IFDEF extended_molstat
9858
         v0.3m */
9859
        ndl_molstat.n_psg01 = molstat.n_psg01;
9860
        ndl_molstat.n_psg02 = molstat.n_psg02;
9861
        ndl_molstat.n_psg13 = molstat.n_psg13;
9862
        ndl_molstat.n_psg14 = molstat.n_psg14;
9863
        ndl_molstat.n_psg15 = molstat.n_psg15;
9864
        ndl_molstat.n_psg16 = molstat.n_psg16;
9865
        ndl_molstat.n_psg17 = molstat.n_psg17;
9866
        ndl_molstat.n_psg18 = molstat.n_psg18;
9867
        ndl_molstat.n_pstm = molstat.n_pstm;
9868
        ndl_molstat.n_psla = molstat.n_psla;
9869
        $ENDIF*/
9870
  /* make sure some modes can be switched on only by the query file *M*/
9871
  /* and not by subsequent haystack file(s) */
9872
  if (ez_flag)   /* new in v0.3f */
9873
   ez_search = true;
9874
  if (chir_flag)   /* new in v0.3f */
9875
    rs_search = true;
9876
}
6785 bpr 9877
#endif
9878
 
14179 bpr 9879
static void copy_mol_to_needle ()
6785 bpr 9880
{
9881
  //int i, j, FORLIM;
9882
 
9883
  /*if (n_atoms == 0)
9884
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9885
 
9886
  ndl_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9887
  ndl_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9888
  ndl_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9889
  ndl_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9890
 
9891
  ndl_n_atoms = n_atoms;
9892
  ndl_n_bonds = n_bonds;
9893
  ndl_n_rings = n_rings;
9894
  ndl_n_heavyatoms = n_heavyatoms;
9895
  ndl_n_heavybonds = n_heavybonds;
9896
  strcpy (ndl_molname, molname);
9897
  ndl_n_Ctot = n_Ctot;
9898
  ndl_n_Otot = n_Otot;
9899
  ndl_n_Ntot = n_Ntot;
9900
  memcpy (ndl_atom, atom, n_atoms * sizeof (atom_rec));
9901
 
9902
  if (n_bonds > 0)
9903
    memcpy (ndl_bond, bond, n_bonds * sizeof (bond_rec));
9904
 
14179 bpr 9905
  if (n_rings > 0) {
9906
    memcpy (ndl_ring, ring, sizeof (ringlist));
9907
    memcpy (ndl_ringprop, ringprop, sizeof (ringprop_type));
9908
  }
6785 bpr 9909
 
9910
  memcpy (&ndl_molstat, &molstat, sizeof (molstat));
9911
 
14179 bpr 9912
  // make sure some modes can be switched on only by the query file
9913
  // and not by subsequent haystack file(s)
9914
  if (ez_flag)                  // new in v0.3f
6785 bpr 9915
    ez_search = true;
9916
 
14179 bpr 9917
  if (chir_flag)                // new in v0.3f
6785 bpr 9918
    rs_search = true;
9919
 
9920
  ndl_querymol = found_querymol;        /* 0.3p */
9921
 
9922
}
9923
 
14179 bpr 9924
static void copy_mol_to_tmp ()
6785 bpr 9925
{
9926
  //int i, j, FORLIM;
9927
 
9928
  /*if (n_atoms == 0)
9929
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
9930
 
9931
  tmp_atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
9932
  tmp_bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
9933
  tmp_ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
9934
  tmp_ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
9935
 
9936
  tmp_n_atoms = n_atoms;
9937
  tmp_n_bonds = n_bonds;
9938
  tmp_n_rings = n_rings;
9939
  tmp_n_heavyatoms = n_heavyatoms;
9940
  tmp_n_heavybonds = n_heavybonds;
9941
  strcpy (tmp_molname, molname);
9942
  tmp_n_Ctot = n_Ctot;
9943
  tmp_n_Otot = n_Otot;
9944
  tmp_n_Ntot = n_Ntot;
9945
  memcpy (tmp_atom, atom, n_atoms * sizeof (atom_rec));
9946
 
9947
  if (n_bonds > 0)
9948
    memcpy (tmp_bond, bond, n_bonds * sizeof (bond_rec));
9949
 
14179 bpr 9950
  if (n_rings > 0) {
6785 bpr 9951
      memcpy (tmp_ring, ring, sizeof (ringlist));
9952
      memcpy (tmp_ringprop, ringprop, sizeof (ringprop_type));
14179 bpr 9953
  }
6785 bpr 9954
 
9955
  memcpy (&tmp_molstat, &molstat, sizeof (molstat));
9956
 
14179 bpr 9957
  // make sure some modes can be switched on only by the query file
9958
  // and not by subsequent haystack file(s)
9959
  if (ez_flag)                  // new in v0.3f
6785 bpr 9960
    ez_search = true;
9961
 
14179 bpr 9962
  if (chir_flag)                // new in v0.3f
6785 bpr 9963
    rs_search = true;
9964
 
9965
  ndl_querymol = found_querymol;        /* 0.3p */
9966
 
9967
}
9968
 
9969
#if 0
9970
static void copy_mol_to_tmp()
9971
{
9972
  int i, j, FORLIM;
9973
 
9974
  if (n_atoms == 0)
9975
    return;
9976
  /* try */
9977
  tmp_atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
9978
  tmp_bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
9979
  tmp_ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
9980
  tmp_ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
9981
  /* except */
9982
    on e:Eoutofmemory do
9983
      begin
9984
        writeln('Not enough memory');
9985
        halt(4);
9986
      end;
9987
  end;
9988
  tmp_n_atoms = n_atoms;
9989
  tmp_n_bonds = n_bonds;
9990
  tmp_n_rings = n_rings;
9991
  tmp_n_heavyatoms = n_heavyatoms;
9992
  tmp_n_heavybonds = n_heavybonds;
9993
  strcpy(tmp_molname, molname);
9994
  tmp_n_Ctot = n_Ctot;
9995
  tmp_n_Otot = n_Otot;
9996
  tmp_n_Ntot = n_Ntot;
9997
  FORLIM = n_atoms;
9998
  for (i = 0; i < FORLIM; i++) {
9999
    strcpy(tmp_atom[i].element, atom[i].element);
10000
    strcpy(tmp_atom[i].atype, atom[i].atype);
10001
    tmp_atom[i].x = atom[i].x;
10002
    tmp_atom[i].y = atom[i].y;
10003
    tmp_atom[i].z = atom[i].z;
10004
    tmp_atom[i].formal_charge = atom[i].formal_charge;
10005
    tmp_atom[i].real_charge = atom[i].real_charge;
10006
    tmp_atom[i].Hexp = atom[i].Hexp;
10007
    tmp_atom[i].Htot = atom[i].Htot;
10008
    tmp_atom[i].neighbor_count = atom[i].neighbor_count;
10009
    tmp_atom[i].ring_count = atom[i].ring_count;
10010
    tmp_atom[i].arom = atom[i].arom;
10011
    tmp_atom[i].stereo_care = atom[i].stereo_care;
10012
    tmp_atom[i].heavy = atom[i].heavy;   /* v0.3l */
10013
    tmp_atom[i].metal = atom[i].metal;   /* v0.3l */
10014
    tmp_atom[i].tag = atom[i].tag;   /* v0.3o */
10015
  }
10016
  if (n_bonds > 0) {
10017
    FORLIM = n_bonds;
10018
    for (i = 0; i < FORLIM; i++) {
10019
      tmp_bond[i].a1 = bond[i].a1;
10020
      tmp_bond[i].a2 = bond[i].a2;
10021
      tmp_bond[i].btype = bond[i].btype;
10022
      tmp_bond[i].arom = bond[i].arom;
10023
      tmp_bond[i].ring_count = bond[i].ring_count;   /* new in v0.3d */
10024
      tmp_bond[i].topo = bond[i].topo;   /* new in v0.3d */
10025
      tmp_bond[i].stereo = bond[i].stereo;   /* new in v0.3d */
10026
    }
10027
  }
10028
  if (n_rings > 0) {
10029
    FORLIM = n_rings;
10030
    for (i = 0; i < FORLIM; i++) {
10031
      for (j = 0; j < max_ringsize; j++)
10032
        tmp_ring[i][j] = ring[i][j];
10033
    }
10034
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10035
      tmp_ringprop[i].size = ringprop[i].size;
10036
      tmp_ringprop[i].arom = ringprop[i].arom;
10037
      tmp_ringprop[i].envelope = ringprop[i].envelope;
10038
    }
10039
  }
10040
  tmp_molstat.n_QA = molstat.n_QA;
10041
  tmp_molstat.n_QB = molstat.n_QB;
10042
  tmp_molstat.n_chg = molstat.n_chg;
10043
  tmp_molstat.n_C1 = molstat.n_C1;
10044
  tmp_molstat.n_C2 = molstat.n_C2;
10045
  tmp_molstat.n_C = molstat.n_C;
10046
  tmp_molstat.n_CHB1p = molstat.n_CHB1p;
10047
  tmp_molstat.n_CHB2p = molstat.n_CHB2p;
10048
  tmp_molstat.n_CHB3p = molstat.n_CHB3p;
10049
  tmp_molstat.n_CHB4 = molstat.n_CHB4;
10050
  tmp_molstat.n_O2 = molstat.n_O2;
10051
  tmp_molstat.n_O3 = molstat.n_O3;
10052
  tmp_molstat.n_N1 = molstat.n_N1;
10053
  tmp_molstat.n_N2 = molstat.n_N2;
10054
  tmp_molstat.n_N3 = molstat.n_N3;
10055
  tmp_molstat.n_S = molstat.n_S;
10056
  tmp_molstat.n_SeTe = molstat.n_SeTe;
10057
  tmp_molstat.n_F = molstat.n_F;
10058
  tmp_molstat.n_Cl = molstat.n_Cl;
10059
  tmp_molstat.n_Br = molstat.n_Br;
10060
  tmp_molstat.n_I = molstat.n_I;
10061
  tmp_molstat.n_P = molstat.n_P;
10062
  tmp_molstat.n_B = molstat.n_B;
10063
  tmp_molstat.n_Met = molstat.n_Met;
10064
  tmp_molstat.n_X = molstat.n_X;
10065
  tmp_molstat.n_b1 = molstat.n_b1;
10066
  tmp_molstat.n_b2 = molstat.n_b2;
10067
  tmp_molstat.n_b3 = molstat.n_b3;
10068
  tmp_molstat.n_bar = molstat.n_bar;
10069
  tmp_molstat.n_C1O = molstat.n_C1O;
10070
  tmp_molstat.n_C2O = molstat.n_C2O;
10071
  tmp_molstat.n_CN = molstat.n_CN;
10072
  tmp_molstat.n_XY = molstat.n_XY;
10073
  tmp_molstat.n_r3 = molstat.n_r3;
10074
  tmp_molstat.n_r4 = molstat.n_r4;
10075
  tmp_molstat.n_r5 = molstat.n_r5;
10076
  tmp_molstat.n_r6 = molstat.n_r6;
10077
  tmp_molstat.n_r7 = molstat.n_r7;
10078
  tmp_molstat.n_r8 = molstat.n_r8;
10079
  tmp_molstat.n_r9 = molstat.n_r9;
10080
  tmp_molstat.n_r10 = molstat.n_r10;
10081
  tmp_molstat.n_r11 = molstat.n_r11;
10082
  tmp_molstat.n_r12 = molstat.n_r12;
10083
  tmp_molstat.n_r13p = molstat.n_r13p;
10084
  tmp_molstat.n_rN = molstat.n_rN;
10085
  tmp_molstat.n_rN1 = molstat.n_rN1;
10086
  tmp_molstat.n_rN2 = molstat.n_rN2;
10087
  tmp_molstat.n_rN3p = molstat.n_rN3p;
10088
  tmp_molstat.n_rO = molstat.n_rO;
10089
  tmp_molstat.n_rO1 = molstat.n_rO1;
10090
  tmp_molstat.n_rO2p = molstat.n_rO2p;
10091
  tmp_molstat.n_rS = molstat.n_rS;
10092
  tmp_molstat.n_rX = molstat.n_rX;
10093
  tmp_molstat.n_rAr = molstat.n_rAr;
10094
  tmp_molstat.n_rBz = molstat.n_rBz;   /* v0.3l */
10095
  tmp_molstat.n_br2p = molstat.n_br2p;   /* v0.3n */
10096
/* p2c: checkmol.pas, line 8022:
10097
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10098
  /*$IFDEF extended_molstat
14179 bpr 10099
   v0.3m
6785 bpr 10100
  tmp_molstat.n_psg01 = molstat.n_psg01;
10101
  tmp_molstat.n_psg02 = molstat.n_psg02;
10102
  tmp_molstat.n_psg13 = molstat.n_psg13;
10103
  tmp_molstat.n_psg14 = molstat.n_psg14;
10104
  tmp_molstat.n_psg15 = molstat.n_psg15;
10105
  tmp_molstat.n_psg16 = molstat.n_psg16;
10106
  tmp_molstat.n_psg17 = molstat.n_psg17;
10107
  tmp_molstat.n_psg18 = molstat.n_psg18;
10108
  tmp_molstat.n_pstm = molstat.n_pstm;
10109
  tmp_molstat.n_psla = molstat.n_psla;
10110
  $ENDIF*/
10111
  /* make sure some modes can be switched on only by the query file */
10112
  /* and not by subsequent haystack file(s) */
10113
  if (ez_flag)   /* new in v0.3f */
10114
    ez_search = true;
10115
  if (chir_flag)   /* new in v0.3f */
10116
    rs_search = true;
10117
}
10118
#endif
10119
 
14179 bpr 10120
static void copy_tmp_to_mol ()
6785 bpr 10121
{
10122
  //int i, j, FORLIM;
10123
 
10124
  /*if (n_atoms == 0)
10125
     return; *///If a NoStruct is read, this leads to madness and illegal memory access
10126
 
10127
  atom = (atom_rec *) safe_calloc (n_atoms, sizeof (atom_rec));
10128
  bond = (bond_rec *) safe_calloc (n_bonds, sizeof (bond_rec));
10129
  ring = (ringpath_type *) safe_calloc (1, sizeof (ringlist));
10130
  ringprop = (ringprop_rec *) safe_calloc (1, sizeof (ringprop_type));
10131
 
10132
  n_atoms = tmp_n_atoms;
10133
  n_bonds = tmp_n_bonds;
10134
  n_rings = tmp_n_rings;
10135
  n_heavyatoms = tmp_n_heavyatoms;
10136
  n_heavybonds = tmp_n_heavybonds;
10137
  strcpy (molname, tmp_molname);
10138
  n_Ctot = tmp_n_Ctot;
10139
  n_Otot = tmp_n_Otot;
10140
  n_Ntot = tmp_n_Ntot;
10141
  memcpy (atom, tmp_atom, tmp_n_atoms * sizeof (atom_rec));
10142
 
10143
  if (tmp_n_bonds > 0)
10144
    memcpy (bond, tmp_bond, tmp_n_bonds * sizeof (bond_rec));
10145
 
14179 bpr 10146
  if (tmp_n_rings > 0) {
6785 bpr 10147
      memcpy (ring, tmp_ring, sizeof (ringlist));
10148
      memcpy (ringprop, tmp_ringprop, sizeof (ringprop_type));
14179 bpr 10149
  }
6785 bpr 10150
 
10151
  memcpy (&molstat, &tmp_molstat, sizeof (tmp_molstat));
10152
 
14179 bpr 10153
  // make sure some modes can be switched on only by the query file
10154
  // and not by subsequent haystack file(s)
10155
  if (ez_flag)                  // new in v0.3f
6785 bpr 10156
    ez_search = true;
10157
 
14179 bpr 10158
  if (chir_flag)                // new in v0.3f
6785 bpr 10159
    rs_search = true;
10160
 
10161
}
10162
 
10163
#if 0
10164
static void copy_tmp_to_mol()
10165
{
10166
  int i, j, FORLIM;
10167
 
10168
  if (tmp_n_atoms == 0)
10169
    return;
10170
  n_atoms = tmp_n_atoms;
10171
  n_bonds = tmp_n_bonds;
10172
  n_rings = tmp_n_rings;
10173
  n_heavyatoms = tmp_n_heavyatoms;
10174
  n_heavybonds = tmp_n_heavybonds;
10175
  strcpy(molname, tmp_molname);
10176
  n_Ctot = tmp_n_Ctot;
10177
  n_Otot = tmp_n_Otot;
10178
  n_Ntot = tmp_n_Ntot;
10179
  /* try */
10180
  atom = (atom_rec *)safe_malloc(n_atoms * sizeof(atom_rec));
10181
  bond = (bond_rec *)safe_malloc(n_bonds * sizeof(bond_rec));
10182
  ring = (ringpath_type *)safe_malloc(sizeof(ringlist));
10183
  ringprop = (ringprop_rec *)safe_malloc(sizeof(ringprop_type));
10184
  FORLIM = tmp_n_atoms;
10185
  /* except*/
10186
    on e:Eoutofmemory do
10187
      begin
10188
        writeln('Not enough memory');
10189
        halt(4);
10190
      end;
14179 bpr 10191
  end;
6785 bpr 10192
  for (i = 0; i < FORLIM; i++) {
10193
    strcpy(atom[i].element, tmp_atom[i].element);
10194
    strcpy(atom[i].atype, tmp_atom[i].atype);
10195
    atom[i].x = tmp_atom[i].x;
10196
    atom[i].y = tmp_atom[i].y;
10197
    atom[i].z = tmp_atom[i].z;
10198
    atom[i].formal_charge = tmp_atom[i].formal_charge;
10199
    atom[i].real_charge = tmp_atom[i].real_charge;
10200
    atom[i].Hexp = tmp_atom[i].Hexp;
10201
    atom[i].Htot = tmp_atom[i].Htot;
10202
    atom[i].neighbor_count = tmp_atom[i].neighbor_count;
10203
    atom[i].ring_count = tmp_atom[i].ring_count;
10204
    atom[i].arom = tmp_atom[i].arom;
10205
    atom[i].stereo_care = tmp_atom[i].stereo_care;
10206
    atom[i].heavy = tmp_atom[i].heavy;   /* v0.3l */
10207
    atom[i].metal = tmp_atom[i].metal;   /* v0.3l */
10208
    atom[i].tag = tmp_atom[i].tag;   /* v0.3o */
10209
  }
10210
  if (tmp_n_bonds > 0) {
10211
    FORLIM = tmp_n_bonds;
10212
    for (i = 0; i < FORLIM; i++) {
10213
      bond[i].a1 = tmp_bond[i].a1;
10214
      bond[i].a2 = tmp_bond[i].a2;
10215
      bond[i].btype = tmp_bond[i].btype;
10216
      bond[i].arom = tmp_bond[i].arom;
10217
      bond[i].ring_count = tmp_bond[i].ring_count;   /* new in v0.3d */
10218
      bond[i].topo = tmp_bond[i].topo;   /* new in v0.3d */
10219
      bond[i].stereo = tmp_bond[i].stereo;   /* new in v0.3d */
10220
    }
10221
  }
10222
  if (tmp_n_rings > 0) {
10223
    FORLIM = tmp_n_rings;
10224
    for (i = 0; i < FORLIM; i++) {
10225
      for (j = 0; j < max_ringsize; j++)
10226
        ring[i][j] = tmp_ring[i][j];
10227
    }
10228
    for (i = 0; i < max_rings; i++) {   /* new in v0.3 */
10229
      ringprop[i].size = tmp_ringprop[i].size;
10230
      ringprop[i].arom = tmp_ringprop[i].arom;
10231
      ringprop[i].envelope = tmp_ringprop[i].envelope;
10232
    }
10233
  }
10234
  molstat.n_QA = tmp_molstat.n_QA;
10235
  molstat.n_QB = tmp_molstat.n_QB;
10236
  molstat.n_chg = tmp_molstat.n_chg;
10237
  molstat.n_C1 = tmp_molstat.n_C1;
10238
  molstat.n_C2 = tmp_molstat.n_C2;
10239
  molstat.n_C = tmp_molstat.n_C;
10240
  molstat.n_CHB1p = tmp_molstat.n_CHB1p;
10241
  molstat.n_CHB2p = tmp_molstat.n_CHB2p;
10242
  molstat.n_CHB3p = tmp_molstat.n_CHB3p;
10243
  molstat.n_CHB4 = tmp_molstat.n_CHB4;
10244
  molstat.n_O2 = tmp_molstat.n_O2;
10245
  molstat.n_O3 = tmp_molstat.n_O3;
10246
  molstat.n_N1 = tmp_molstat.n_N1;
10247
  molstat.n_N2 = tmp_molstat.n_N2;
10248
  molstat.n_N3 = tmp_molstat.n_N3;
10249
  molstat.n_S = tmp_molstat.n_S;
10250
  molstat.n_SeTe = tmp_molstat.n_SeTe;
10251
  molstat.n_F = tmp_molstat.n_F;
10252
  molstat.n_Cl = tmp_molstat.n_Cl;
10253
  molstat.n_Br = tmp_molstat.n_Br;
10254
  molstat.n_I = tmp_molstat.n_I;
10255
  molstat.n_P = tmp_molstat.n_P;
10256
  molstat.n_B = tmp_molstat.n_B;
10257
  molstat.n_Met = tmp_molstat.n_Met;
10258
  molstat.n_X = tmp_molstat.n_X;
10259
  molstat.n_b1 = tmp_molstat.n_b1;
10260
  molstat.n_b2 = tmp_molstat.n_b2;
10261
  molstat.n_b3 = tmp_molstat.n_b3;
10262
  molstat.n_bar = tmp_molstat.n_bar;
10263
  molstat.n_C1O = tmp_molstat.n_C1O;
10264
  molstat.n_C2O = tmp_molstat.n_C2O;
10265
  molstat.n_CN = tmp_molstat.n_CN;
10266
  molstat.n_XY = tmp_molstat.n_XY;
10267
  molstat.n_r3 = tmp_molstat.n_r3;
10268
  molstat.n_r4 = tmp_molstat.n_r4;
10269
  molstat.n_r5 = tmp_molstat.n_r5;
10270
  molstat.n_r6 = tmp_molstat.n_r6;
10271
  molstat.n_r7 = tmp_molstat.n_r7;
10272
  molstat.n_r8 = tmp_molstat.n_r8;
10273
  molstat.n_r9 = tmp_molstat.n_r9;
10274
  molstat.n_r10 = tmp_molstat.n_r10;
10275
  molstat.n_r11 = tmp_molstat.n_r11;
10276
  molstat.n_r12 = tmp_molstat.n_r12;
10277
  molstat.n_r13p = tmp_molstat.n_r13p;
10278
  molstat.n_rN = tmp_molstat.n_rN;
10279
  molstat.n_rN1 = tmp_molstat.n_rN1;
10280
  molstat.n_rN2 = tmp_molstat.n_rN2;
10281
  molstat.n_rN3p = tmp_molstat.n_rN3p;
10282
  molstat.n_rO = tmp_molstat.n_rO;
10283
  molstat.n_rO1 = tmp_molstat.n_rO1;
10284
  molstat.n_rO2p = tmp_molstat.n_rO2p;
10285
  molstat.n_rS = tmp_molstat.n_rS;
10286
  molstat.n_rX = tmp_molstat.n_rX;
10287
  molstat.n_rAr = tmp_molstat.n_rAr;
10288
  molstat.n_rBz = tmp_molstat.n_rBz;   /* v0.3l */
10289
  molstat.n_br2p = tmp_molstat.n_br2p;   /* v0.3n */
10290
/* p2c: checkmol.pas, line 8169:
10291
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10292
  /*$IFDEF extended_molstat
10293
     molstat.n_psg01 = tmp_molstat.n_psg01;
10294
     molstat.n_psg02 = tmp_molstat.n_psg02;
10295
     molstat.n_psg13 = tmp_molstat.n_psg13;
10296
     molstat.n_psg14 = tmp_molstat.n_psg14;
10297
     molstat.n_psg15 = tmp_molstat.n_psg15;
10298
     molstat.n_psg16 = tmp_molstat.n_psg16;
10299
     molstat.n_psg17 = tmp_molstat.n_psg17;
10300
     molstat.n_psg18 = tmp_molstat.n_psg18;
10301
     molstat.n_pstm = tmp_molstat.n_pstm;
10302
     molstat.n_psla = tmp_molstat.n_psla;
10303
     $ENDIF */
10304
  /* make sure some modes can be switched on only by the query file */
10305
  /* and not by subsequent haystack file(s) */
10306
     if (ez_flag)
10307
     ez_search = true;
10308
     if (chir_flag)
10309
     rs_search = true;
10310
     }
10311
#endif
10312
 
14179 bpr 10313
static void get_ringstat (r_id)
6785 bpr 10314
     int r_id;
10315
{
10316
  int i, j;
10317
  ringpath_type testring;
10318
  int ring_size, a_ref;
10319
  str2 elem;
10320
  int nN = 0, nO = 0, nS = 0, nX = 0;
10321
 
10322
  if (r_id < 1 || r_id > n_rings)
10323
    return;
10324
  memset (testring, 0, sizeof (ringpath_type));
10325
  ring_size = ringprop[r_id - 1].size;  /* v0.3j */
10326
  for (j = 0; j < ring_size; j++)       /* v0.3j */
10327
    testring[j] = ring[r_id - 1][j];
14179 bpr 10328
    /* p2c: checkmol.pas, line 8238:
10329
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10330
#ifdef reduced_SAR
10331
  if (ring_size <= 2 || ringprop[r_id - 1].envelope != false)
10332
    /* v0.3n: ignore envelope rings */
10333
    return;
10334
#else
10335
  if (ring_size <= 2)
10336
    return;
10337
#endif
14179 bpr 10338
  for (i = 0; i < ring_size; i++) {
10339
    a_ref = testring[i];
10340
    strcpy (elem, atom[a_ref - 1].element);
10341
    if (strcmp (elem, "C ") && strcmp (elem, "A ")) {
10342
            nX++;                       /* general heteroatom count */
10343
            if (!strcmp (elem, "N "))
10344
              nN++;
10345
            if (!strcmp (elem, "O "))
10346
              nO++;
10347
            if (!strcmp (elem, "S "))
10348
              nS++;
10349
          }
10350
  }
10351
  if (nN > 0) {
10352
    molstat.n_rN++;
10353
    if (nN == 1)
10354
            molstat.n_rN1++;
10355
    if (nN == 2)
10356
            molstat.n_rN2++;
10357
    if (nN > 2)
10358
            molstat.n_rN3p++;
10359
  }
10360
  if (nO > 0) {
10361
    molstat.n_rO++;
10362
    if (nO == 1)
10363
            molstat.n_rO1++;
10364
    if (nO == 2)
10365
            molstat.n_rO2p++;
10366
  }
6785 bpr 10367
  if (nS > 0)
10368
    molstat.n_rS++;
10369
  if (nX > 0)
10370
    molstat.n_rX++;
10371
  /* general ringsize descriptors; v0.3m */
14179 bpr 10372
  switch (ring_size) {
6785 bpr 10373
    case 3:
10374
      molstat.n_r3++;
10375
      break;
10376
 
10377
    case 4:
10378
      molstat.n_r4++;
10379
      break;
10380
 
10381
    case 5:
10382
      molstat.n_r5++;
10383
      break;
10384
 
10385
    case 6:
10386
      molstat.n_r6++;
10387
      break;
10388
 
10389
    case 7:
10390
      molstat.n_r7++;
10391
      break;
10392
 
10393
    case 8:
10394
      molstat.n_r8++;
10395
      break;
10396
 
10397
    case 9:
10398
      molstat.n_r9++;
10399
      break;
10400
 
10401
    case 10:
10402
      molstat.n_r10++;
10403
      break;
10404
 
10405
    case 11:
10406
      molstat.n_r11++;
10407
      break;
10408
 
10409
    case 12:
10410
      molstat.n_r12++;
10411
      break;
10412
 
10413
    default:
10414
      molstat.n_r13p++;
10415
      break;
14179 bpr 10416
  }                             /* end v0.3m        */
6785 bpr 10417
}
10418
 
14179 bpr 10419
static void get_molstat ()
6785 bpr 10420
{
10421
  int i;
10422
  str2 elem;
10423
  str3 atype;
10424
  int a1, a2;
10425
  str2 a1el, a2el;
10426
  char btype;
10427
  int hbc;
10428
  int n_b2formal = 0;           /* new in v0.2e */
10429
  int FORLIM;
10430
 
10431
  if (n_atoms == 0)
10432
    return;
10433
  FORLIM = n_atoms;
14179 bpr 10434
  for (i = 0; i < FORLIM; i++) {
10435
    if (atom[i].heavy) {
10436
            strcpy (elem, atom[i].element);
10437
            strcpy (atype, atom[i].atype);
10438
            if (!strcmp (atype, "C1 "))
10439
              molstat.n_C1++;
10440
            if (!strcmp (atype, "C2 ") || !strcmp (atype, "CAR"))
10441
              molstat.n_C2++;
10442
            if (!strcmp (elem, "C "))
10443
              molstat.n_C++;
10444
            if (!strcmp (atype, "O2 "))
10445
              molstat.n_O2++;
10446
            if (!strcmp (atype, "O3 "))
10447
              molstat.n_O3++;
10448
            if (!strcmp (atype, "N1 "))
10449
              molstat.n_N1++;
10450
            if (!strcmp (atype, "N2 ") || !strcmp (atype, "NAR") ||
10451
                (!strcmp (atype, "NAM") && atom[i].arom == true))
10452
              /* v0.3n */
10453
              molstat.n_N2++;
10454
            if (!strcmp (atype, "N3 ") || !strcmp (atype, "NPL") ||
10455
                !strcmp (atype, "N3+") ||
10456
                (!strcmp (atype, "NAM") && atom[i].arom == false))
10457
              /* v0.3n */
10458
              molstat.n_N3++;
10459
            if (!strcmp (elem, "A "))   /* query atom */
10460
              molstat.n_QA++;
10461
            if (!strcmp (elem, "Q "))   /* query atom */
10462
              molstat.n_QA++;
10463
            if (!strcmp (elem, "X "))   /* query atom */
10464
              molstat.n_QA++;
10465
            if (!strcmp (elem, "S "))
10466
              molstat.n_S++;
10467
            if (!strcmp (elem, "SE"))
6785 bpr 10468
            molstat.n_SeTe++;
14179 bpr 10469
            if (!strcmp (elem, "TE"))
10470
              molstat.n_SeTe++;
10471
            if (!strcmp (elem, "F "))
10472
              molstat.n_F++;
10473
            if (!strcmp (elem, "CL"))
10474
              molstat.n_Cl++;
10475
            if (!strcmp (elem, "BR"))
10476
              molstat.n_Br++;
10477
            if (!strcmp (elem, "I "))
10478
              molstat.n_I++;
10479
            if (!strcmp (elem, "P "))
10480
              molstat.n_P++;
10481
            if (!strcmp (elem, "B "))
10482
              molstat.n_B++;
10483
            /* check for known metals */
10484
            if (atom[i].metal)  /* v0.3l */
10485
              molstat.n_Met++;
10486
            /* still missing: unknown elements */
6785 bpr 10487
 
14179 bpr 10488
            /* check number of heteroatom bonds per C atom */
10489
            if (!strcmp (elem, "C ")) {
6785 bpr 10490
              hbc = raw_hetbond_count (i + 1);
10491
              /* new in v0.2j (replaces hetbond_count) */
10492
              if (hbc >= 1)
14179 bpr 10493
                      molstat.n_CHB1p++;
6785 bpr 10494
              if (hbc >= 2)
14179 bpr 10495
                      molstat.n_CHB2p++;
6785 bpr 10496
              if (hbc >= 3)
14179 bpr 10497
                      molstat.n_CHB3p++;
6785 bpr 10498
              if (hbc == 4)
14179 bpr 10499
                      molstat.n_CHB4++;
6785 bpr 10500
            }
14179 bpr 10501
            if (atom[i].formal_charge != 0) {
6785 bpr 10502
              molstat.n_chg++;
10503
              //n_charges++;
10504
            }
14179 bpr 10505
            if (atom[i].nucleon_number != 0) {
6785 bpr 10506
              molstat.n_iso++;
10507
            }
14179 bpr 10508
            if (atom[i].radical_type != 0) {
6785 bpr 10509
              molstat.n_rad++;
10510
            }
14179 bpr 10511
            /* check for "other" elements;  v0.3l */
10512
            if (!atom[i].metal && strcmp (elem, "C ") && strcmp (elem, "N ")
10513
                && strcmp (elem, "O ") && strcmp (elem, "S ")
10514
                && strcmp (elem, "SE") && strcmp (elem, "TE")
10515
                && strcmp (elem, "P ") && strcmp (elem, "B ")
10516
                && strcmp (elem, "A ") && strcmp (elem, "Q "))
10517
              molstat.n_X++;
10518
            /*(elem = 'F ') or (elem = 'CL') or (elem = 'BR') or (elem = 'I ') or  (* leave halogens as type X, v0.3m */
10519
      /* p2c: checkmol.pas, line 8353:
10520
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10521
            /*$IFDEF extended_molstat */
10522
            if (!strcmp (elem, "LI") || !strcmp (elem, "NA")
10523
                || !strcmp (elem, "K ") || !strcmp (elem, "RB")
10524
                || !strcmp (elem, "CS") || !strcmp (elem, "FR"))
10525
              molstat.n_psg01++;
10526
            if (!strcmp (elem, "BE") || !strcmp (elem, "MG")
10527
                || !strcmp (elem, "CA") || !strcmp (elem, "SR")
10528
                || !strcmp (elem, "BA") || !strcmp (elem, "RA"))
10529
              molstat.n_psg02++;
10530
            if (!strcmp (elem, "B ") || !strcmp (elem, "AL")
10531
                || !strcmp (elem, "GA") || !strcmp (elem, "IN")
10532
                || !strcmp (elem, "TL"))
10533
              molstat.n_psg13++;
10534
            if (!strcmp (elem, "C ") || !strcmp (elem, "SI")
10535
                || !strcmp (elem, "GE") || !strcmp (elem, "SN")
10536
                || !strcmp (elem, "PB"))
10537
              molstat.n_psg14++;
10538
            if (!strcmp (elem, "N ") || !strcmp (elem, "P ")
6785 bpr 10539
              || !strcmp (elem, "AS") || !strcmp (elem, "SB")
10540
              || !strcmp (elem, "BI"))
10541
            molstat.n_psg15++;
14179 bpr 10542
            if (!strcmp (elem, "O ") || !strcmp (elem, "S ")
10543
                || !strcmp (elem, "SE") || !strcmp (elem, "TE")
10544
                || !strcmp (elem, "PO"))
10545
              molstat.n_psg16++;
10546
            if (!strcmp (elem, "F ") || !strcmp (elem, "CL")
10547
                || !strcmp (elem, "BR") || !strcmp (elem, "I ")
10548
                || !strcmp (elem, "AT"))
10549
              molstat.n_psg17++;
10550
            if (!strcmp (elem, "HE") || !strcmp (elem, "NE")
10551
                || !strcmp (elem, "AR") || !strcmp (elem, "KR")
10552
                || !strcmp (elem, "XE") || !strcmp (elem, "RN"))
10553
              molstat.n_psg18++;
10554
            if (!strcmp (elem, "SC") || !strcmp (elem, "Y ")
10555
                || !strcmp (elem, "LU") || !strcmp (elem, "LR")
10556
                || !strcmp (elem, "TI") || !strcmp (elem, "ZR")
10557
                || !strcmp (elem, "HF") || !strcmp (elem, "RF")
10558
                || !strcmp (elem, "V ") || !strcmp (elem, "NB")
10559
                || !strcmp (elem, "TA") || !strcmp (elem, "DB")
10560
                || !strcmp (elem, "CR") || !strcmp (elem, "MO")
10561
                || !strcmp (elem, "W ") || !strcmp (elem, "SG")
10562
                || !strcmp (elem, "MN") || !strcmp (elem, "TC")
10563
                || !strcmp (elem, "RE") || !strcmp (elem, "BH")
10564
                || !strcmp (elem, "FE") || !strcmp (elem, "RU")
10565
                || !strcmp (elem, "OS") || !strcmp (elem, "HS")
10566
                || !strcmp (elem, "CO") || !strcmp (elem, "RH")
10567
                || !strcmp (elem, "IR") || !strcmp (elem, "MT")
10568
                || !strcmp (elem, "NI") || !strcmp (elem, "PD")
10569
                || !strcmp (elem, "PT") || !strcmp (elem, "DS")
10570
                || !strcmp (elem, "CU") || !strcmp (elem, "AG")
10571
                || !strcmp (elem, "AU") || !strcmp (elem, "RG")
10572
                || !strcmp (elem, "ZN") || !strcmp (elem, "CD")
10573
                || !strcmp (elem, "HG"))
10574
        /* p2c: checkmol.pas, line 8439:
10575
        * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10035 [251] */
10576
              molstat.n_pstm++;
10577
            if (!strcmp (elem, "LA") || !strcmp (elem, "CE")
10578
                || !strcmp (elem, "PR") || !strcmp (elem, "ND")
10579
                || !strcmp (elem, "PM") || !strcmp (elem, "SM")
10580
                || !strcmp (elem, "EU") || !strcmp (elem, "GD")
10581
                || !strcmp (elem, "TB") || !strcmp (elem, "DY")
10582
                || !strcmp (elem, "HO") || !strcmp (elem, "ER")
10583
                || !strcmp (elem, "TM") || !strcmp (elem, "YB")
10584
                || !strcmp (elem, "AC") || !strcmp (elem, "TH")
10585
                || !strcmp (elem, "PA") || !strcmp (elem, "U ")
10586
                || !strcmp (elem, "NP") || !strcmp (elem, "PU")
10587
                || !strcmp (elem, "AM") || !strcmp (elem, "CM")
10588
                || !strcmp (elem, "BK") || !strcmp (elem, "CF")
10589
                || !strcmp (elem, "ES") || !strcmp (elem, "FM")
10590
                || !strcmp (elem, "MD") || !strcmp (elem, "NO"))
10591
      /* p2c: checkmol.pas, line 8439:
10592
      * Note: Line breaker spent 0.0 seconds, 5000 tries on line 10048 [251] */
10593
              molstat.n_psla++;
10594
            /*$ENDIF */
10595
          }                     /* is heavy */
10596
  }                             /* atoms */
10597
  if (n_bonds > 0) {
10598
    FORLIM = n_bonds;
10599
    for (i = 0; i < FORLIM; i++) {
10600
            a1 = bond[i].a1;
10601
            a2 = bond[i].a2;
10602
            strcpy (a1el, atom[a1 - 1].element);
10603
            strcpy (a2el, atom[a2 - 1].element);
10604
            btype = bond[i].btype;
10605
            if (bond[i].arom)
10606
              molstat.n_bar++;
10607
            else {
6785 bpr 10608
              if (btype == 'S' && atom[a1 - 1].heavy && atom[a2 - 1].heavy)
14179 bpr 10609
                      molstat.n_b1++;
6785 bpr 10610
              if (btype == 'D')
14179 bpr 10611
                     molstat.n_b2++;
6785 bpr 10612
              if (btype == 'T')
14179 bpr 10613
                      molstat.n_b3++;
6785 bpr 10614
            }
14179 bpr 10615
            /* v0.3n: ignore bonds to (explicit) hydrogens */
10616
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "O ")) ||
10617
                (!strcmp (a1el, "O ") && !strcmp (a2el, "C "))) {
6785 bpr 10618
              if (btype == 'S')
14179 bpr 10619
                      molstat.n_C1O++;
6785 bpr 10620
              if (btype == 'D')
14179 bpr 10621
                      molstat.n_C2O++;
6785 bpr 10622
            }
14179 bpr 10623
            if ((!strcmp (a1el, "C ") && !strcmp (a2el, "N ")) ||
10624
                (!strcmp (a1el, "N ") && !strcmp (a2el, "C ")))
10625
              molstat.n_CN++;
10626
            if (strcmp (a1el, "C ") && atom[a1 - 1].heavy
10627
                && strcmp (a2el, "C ") && atom[a2 - 1].heavy)
10628
              molstat.n_XY++;
10629
            /* new in v0.3n: number of bonds belonging to more than one ring */
10630
            if (bond[i].ring_count > 1)
10631
              molstat.n_br2p++;
10632
          }
10633
  }                             /* bonds */
10634
  if (n_rings <= 0) {
6785 bpr 10635
      return;
14179 bpr 10636
  }                             /* rings */
6785 bpr 10637
  /* v0.3n */
10638
  n_countablerings = 0;         /* v0.3n */
10639
  FORLIM = n_rings;
14179 bpr 10640
  for (i = 1; i <= FORLIM; i++) {
10641
    if (ringprop[i - 1].envelope == false)      /* v0.3n */
10642
            n_countablerings++;
10643
    if (is_arene (i) && ringprop[i - 1].envelope == false) {
10644
      /* v0.3n: ignore envelope rings */
10645
            molstat.n_rAr++;
10646
            if ((ringprop[i - 1].size == 6) && (is_heterocycle (i) == false))
10647
              /* v0.3l */
10648
              molstat.n_rBz++;
10649
          }
10650
    get_ringstat (i);
10651
    if (ringprop[i - 1].arom == true && ringprop[i - 1].envelope == false)
10652
            /* new in v0.3n; replaces assignment below */
10653
            n_b2formal++;
10654
  }
6785 bpr 10655
  /*n_b2formal := n_rar;  (* new in v0.2e; adds 1 formal double bond for each aromatic ring */
10656
  /* in order to allow an isolated double bond in the needle */
10657
  /* to be matched as a ring fragment of an aromatic ring */
10658
  if (n_b2formal > molstat.n_bar / 2)
10659
    n_b2formal = molstat.n_bar / 2;
10660
  molstat.n_b2 += n_b2formal;
10661
}
10662
 
14179 bpr 10663
static void fix_ssr_ringcounts ()
6785 bpr 10664
{
10665
  /* new in v0.3n */
10666
  /* if SAR -> SSR fallback happens, set some molstat values */
10667
  /* to a maximum (ring counts for various ring sizes); */
10668
  /* this should be necessary only for ring sizes which */
10669
  /* are a) too large for the SSR (depending on ssr_vringsize) */
10670
  /* and b) which are likely to contain "envelope rings" */
10671
  /* (size 6 and above) */
10672
  /*  if (molstat.n_r3 = 0) then molstat.n_r3 := max_rings; */
10673
  /*  if (molstat.n_r4 = 0) then molstat.n_r4 := max_rings; */
10674
  /*  if (molstat.n_r5 = 0) then molstat.n_r5 := max_rings; */
10675
  if (molstat.n_r6 == 0)
10676
    molstat.n_r6 = max_rings;
10677
  if (molstat.n_r7 == 0)
10678
    molstat.n_r7 = max_rings;
10679
  if (molstat.n_r8 == 0)
10680
    molstat.n_r8 = max_rings;
10681
  if (molstat.n_r9 == 0)
10682
    molstat.n_r9 = max_rings;
10683
  if (molstat.n_r10 == 0)
10684
    molstat.n_r10 = max_rings;
10685
  if (molstat.n_r11 == 0)
10686
    molstat.n_r11 = max_rings;
10687
  if (molstat.n_r12 == 0)
10688
    molstat.n_r12 = max_rings;
10689
  if (molstat.n_r13p == 0)
10690
    molstat.n_r13p = max_rings;
10691
}
10692
 
14179 bpr 10693
static void write_molstat ()
6785 bpr 10694
{
10695
  if (auto_ssr)                 /* v0.3n */
10696
    fix_ssr_ringcounts ();
10697
  printf ("n_atoms:%d;", n_heavyatoms);
10698
  /* count only non-H atoms (some molfiles contain explicit H's) */
10699
  if (n_bonds > 0)              /* count only bonds between non-H atoms */
10700
    printf ("n_bonds:%d;", n_heavybonds);
14179 bpr 10701
  /* p2c: checkmol.pas, line 8471:
10702
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10703
#ifdef REDUCED_SAR
10704
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10705
    printf ("n_rings:%d;", n_countablerings);
10706
#else
10707
  if (n_rings > 0)              /* changed to non-envelope rings in v0.3n */
10708
    printf ("n_rings:%d;", n_rings);
10709
#endif
10710
  /*      if n_QA    > 0 then write('n_QA:',n_QA,';'); */
10711
  /*      if n_QB    > 0 then write('n_QB:',n_QB,';'); */
10712
  if (molstat.n_chg > 0)        /* 0.3x */
10713
    printf ("n_chg:%d;", molstat.n_chg);
10714
 
10715
  if (molstat.n_C1 > 0)
10716
    printf ("n_C1:%d;", molstat.n_C1);
10717
  if (molstat.n_C2 > 0)
10718
    printf ("n_C2:%d;", molstat.n_C2);
10719
  /* requirement of a given number of sp3 carbons might be too restrictive, */
10720
  /* so we use the total number of carbons instead  (initially used variable n_C3 is now n_C) */
10721
  if (molstat.n_C > 0)
10722
    printf ("n_C:%d;", molstat.n_C);
10723
  if (molstat.n_CHB1p > 0)
10724
    printf ("n_CHB1p:%d;", molstat.n_CHB1p);
10725
  if (molstat.n_CHB2p > 0)
10726
    printf ("n_CHB2p:%d;", molstat.n_CHB2p);
10727
  if (molstat.n_CHB3p > 0)
10728
    printf ("n_CHB3p:%d;", molstat.n_CHB3p);
10729
  if (molstat.n_CHB4 > 0)
10730
    printf ("n_CHB4:%d;", molstat.n_CHB4);
10731
  if (molstat.n_O2 > 0)
10732
    printf ("n_O2:%d;", molstat.n_O2);
10733
  if (molstat.n_O3 > 0)
10734
    printf ("n_O3:%d;", molstat.n_O3);
10735
  if (molstat.n_N1 > 0)
10736
    printf ("n_N1:%d;", molstat.n_N1);
10737
  if (molstat.n_N2 > 0)
10738
    printf ("n_N2:%d;", molstat.n_N2);
10739
  if (molstat.n_N3 > 0)
10740
    printf ("n_N3:%d;", molstat.n_N3);
10741
  if (molstat.n_S > 0)
10742
    printf ("n_S:%d;", molstat.n_S);
10743
  if (molstat.n_SeTe > 0)
10744
    printf ("n_SeTe:%d;", molstat.n_SeTe);
10745
  if (molstat.n_F > 0)
10746
    printf ("n_F:%d;", molstat.n_F);
10747
  if (molstat.n_Cl > 0)
10748
    printf ("n_Cl:%d;", molstat.n_Cl);
10749
  if (molstat.n_Br > 0)
10750
    printf ("n_Br:%d;", molstat.n_Br);
10751
  if (molstat.n_I > 0)
10752
    printf ("n_I:%d;", molstat.n_I);
10753
  if (molstat.n_P > 0)
10754
    printf ("n_P:%d;", molstat.n_P);
10755
  if (molstat.n_B > 0)
10756
    printf ("n_B:%d;", molstat.n_B);
10757
  if (molstat.n_Met > 0)
10758
    printf ("n_Met:%d;", molstat.n_Met);
10759
  if (molstat.n_X > 0)
10760
    printf ("n_X:%d;", molstat.n_X);
10761
  if (molstat.n_b1 > 0)
10762
    printf ("n_b1:%d;", molstat.n_b1);
10763
  if (molstat.n_b2 > 0)
10764
    printf ("n_b2:%d;", molstat.n_b2);
10765
  if (molstat.n_b3 > 0)
10766
    printf ("n_b3:%d;", molstat.n_b3);
10767
  if (molstat.n_bar > 0)
10768
    printf ("n_bar:%d;", molstat.n_bar);
10769
  if (molstat.n_C1O > 0)
10770
    printf ("n_C1O:%d;", molstat.n_C1O);
10771
  if (molstat.n_C2O > 0)
10772
    printf ("n_C2O:%d;", molstat.n_C2O);
10773
  if (molstat.n_CN > 0)
10774
    printf ("n_CN:%d;", molstat.n_CN);
10775
  if (molstat.n_XY > 0)
10776
    printf ("n_XY:%d;", molstat.n_XY);
10777
  if (molstat.n_r3 > 0)
10778
    printf ("n_r3:%d;", molstat.n_r3);
10779
  if (molstat.n_r4 > 0)
10780
    printf ("n_r4:%d;", molstat.n_r4);
10781
  if (molstat.n_r5 > 0)
10782
    printf ("n_r5:%d;", molstat.n_r5);
10783
  if (molstat.n_r6 > 0)
10784
    printf ("n_r6:%d;", molstat.n_r6);
10785
  if (molstat.n_r7 > 0)
10786
    printf ("n_r7:%d;", molstat.n_r7);
10787
  if (molstat.n_r8 > 0)
10788
    printf ("n_r8:%d;", molstat.n_r8);
10789
  if (molstat.n_r9 > 0)
10790
    printf ("n_r9:%d;", molstat.n_r9);
10791
  if (molstat.n_r10 > 0)
10792
    printf ("n_r10:%d;", molstat.n_r10);
10793
  if (molstat.n_r11 > 0)
10794
    printf ("n_r11:%d;", molstat.n_r11);
10795
  if (molstat.n_r12 > 0)
10796
    printf ("n_r12:%d;", molstat.n_r12);
10797
  if (molstat.n_r13p > 0)
10798
    printf ("n_r13p:%d;", molstat.n_r13p);
10799
  if (molstat.n_rN > 0)
10800
    printf ("n_rN:%d;", molstat.n_rN);
10801
  if (molstat.n_rN1 > 0)
10802
    printf ("n_rN1:%d;", molstat.n_rN1);
10803
  if (molstat.n_rN2 > 0)
10804
    printf ("n_rN2:%d;", molstat.n_rN2);
10805
  if (molstat.n_rN3p > 0)
10806
    printf ("n_rN3p:%d;", molstat.n_rN3p);
10807
  if (molstat.n_rO > 0)
10808
    printf ("n_rO:%d;", molstat.n_rO);
10809
  if (molstat.n_rO1 > 0)
10810
    printf ("n_rO1:%d;", molstat.n_rO1);
10811
  if (molstat.n_rO2p > 0)
10812
    printf ("n_rO2p:%d;", molstat.n_rO2p);
10813
  if (molstat.n_rS > 0)
10814
    printf ("n_rS:%d;", molstat.n_rS);
10815
  if (molstat.n_rX > 0)
10816
    printf ("n_rX:%d;", molstat.n_rX);
10817
  if (molstat.n_rAr > 0)
10818
    printf ("n_rar:%d;", molstat.n_rAr);
10819
/* p2c: checkmol.pas, line 8532:
10820
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
10821
  /*$IFDEF extended_molstat */
10822
  if (molstat.n_rBz > 0)
10823
    printf ("n_rbz:%d;", molstat.n_rBz);
10824
  if (molstat.n_br2p > 0)
10825
    printf ("n_br2p:%d;", molstat.n_br2p);
10826
  if (molstat.n_psg01 > 0)
10827
    printf ("n_psg01:%d;", molstat.n_psg01);
10828
  if (molstat.n_psg02 > 0)
10829
    printf ("n_psg02:%d;", molstat.n_psg02);
10830
  if (molstat.n_psg13 > 0)
10831
    printf ("n_psg13:%d;", molstat.n_psg13);
10832
  if (molstat.n_psg14 > 0)
10833
    printf ("n_psg14:%d;", molstat.n_psg14);
10834
  if (molstat.n_psg15 > 0)
10835
    printf ("n_psg15:%d;", molstat.n_psg15);
10836
  if (molstat.n_psg16 > 0)
10837
    printf ("n_psg16:%d;", molstat.n_psg16);
10838
  if (molstat.n_psg17 > 0)
10839
    printf ("n_psg17:%d;", molstat.n_psg17);
10840
  if (molstat.n_psg18 > 0)
10841
    printf ("n_psg18:%d;", molstat.n_psg18);
10842
  if (molstat.n_pstm > 0)
10843
    printf ("n_pstm:%d;", molstat.n_pstm);
10844
  if (molstat.n_psla > 0)
10845
    printf ("n_psla:%d;", molstat.n_psla);
10846
  if (molstat.n_iso > 0)
10847
    printf ("n_iso:%d;", molstat.n_iso);
10848
  if (molstat.n_rad > 0)
10849
    printf ("n_rad:%d;", molstat.n_rad);
10850
  /*$ENDIF */
10851
  putchar ('\n');
10852
}
10853
 
14179 bpr 10854
static void write_molstat_X ()
6785 bpr 10855
{
10856
  if (auto_ssr)                 /* v0.3n */
10857
    fix_ssr_ringcounts ();
14179 bpr 10858
    /* p2c: checkmol.pas, line 8556:
10859
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10860
#ifdef REDUCED_SAR
10861
  printf ("%d,", n_heavyatoms);
10862
  printf ("%d,", n_heavybonds);
10863
  printf ("%d,", n_countablerings);
14179 bpr 10864
    /* v0.3n: n_rings =?> n_countablerings */
6785 bpr 10865
#else
10866
  printf ("%d,", n_heavyatoms);
10867
  printf ("%d,", n_heavybonds);
10868
  printf ("%d,", n_rings);      /* v0.3n: n_rings ==> n_countablerings */
10869
#endif
10870
  printf ("%d,", molstat.n_QA);
10871
  printf ("%d,", molstat.n_QB);
10872
 
10873
  /* 0.3x */
10874
  printf ("%d,", molstat.n_chg);
10875
 
10876
  printf ("%d,", molstat.n_C1);
10877
  printf ("%d,", molstat.n_C2);
10878
  printf ("%d,", molstat.n_C);
10879
  printf ("%d,", molstat.n_CHB1p);
10880
  printf ("%d,", molstat.n_CHB2p);
10881
  printf ("%d,", molstat.n_CHB3p);
10882
  printf ("%d,", molstat.n_CHB4);
10883
  printf ("%d,", molstat.n_O2);
10884
  printf ("%d,", molstat.n_O3);
10885
  printf ("%d,", molstat.n_N1);
10886
  printf ("%d,", molstat.n_N2);
10887
  printf ("%d,", molstat.n_N3);
10888
  printf ("%d,", molstat.n_S);
10889
  printf ("%d,", molstat.n_SeTe);
10890
  printf ("%d,", molstat.n_F);
10891
  printf ("%d,", molstat.n_Cl);
10892
  printf ("%d,", molstat.n_Br);
10893
  printf ("%d,", molstat.n_I);
10894
  printf ("%d,", molstat.n_P);
10895
  printf ("%d,", molstat.n_B);
10896
  printf ("%d,", molstat.n_Met);
10897
  printf ("%d,", molstat.n_X);
10898
  printf ("%d,", molstat.n_b1);
10899
  printf ("%d,", molstat.n_b2);
10900
  printf ("%d,", molstat.n_b3);
10901
  printf ("%d,", molstat.n_bar);
10902
  printf ("%d,", molstat.n_C1O);
10903
  printf ("%d,", molstat.n_C2O);
10904
  printf ("%d,", molstat.n_CN);
10905
  printf ("%d,", molstat.n_XY);
10906
  printf ("%d,", molstat.n_r3);
10907
  printf ("%d,", molstat.n_r4);
10908
  printf ("%d,", molstat.n_r5);
10909
  printf ("%d,", molstat.n_r6);
10910
  printf ("%d,", molstat.n_r7);
10911
  printf ("%d,", molstat.n_r8);
10912
  printf ("%d,", molstat.n_r9);
10913
  printf ("%d,", molstat.n_r10);
10914
  printf ("%d,", molstat.n_r11);
10915
  printf ("%d,", molstat.n_r12);
10916
  printf ("%d,", molstat.n_r13p);
10917
  printf ("%d,", molstat.n_rN);
10918
  printf ("%d,", molstat.n_rN1);
10919
  printf ("%d,", molstat.n_rN2);
10920
  printf ("%d,", molstat.n_rN3p);
10921
  printf ("%d,", molstat.n_rO);
10922
  printf ("%d,", molstat.n_rO1);
10923
  printf ("%d,", molstat.n_rO2p);
10924
  printf ("%d,", molstat.n_rS);
10925
  printf ("%d,", molstat.n_rX);
10926
  printf ("%d", molstat.n_rAr);
14179 bpr 10927
  /* p2c: checkmol.pas, line 8579:
10928
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 10929
  /*$IFDEF extended_molstat */
10930
  printf (",%d", molstat.n_rBz);
10931
  printf (",%d", molstat.n_br2p);
10932
  printf (",%d", molstat.n_psg01);
10933
  printf (",%d", molstat.n_psg02);
10934
  printf (",%d", molstat.n_psg13);
10935
  printf (",%d", molstat.n_psg14);
10936
  printf (",%d", molstat.n_psg15);
10937
  printf (",%d", molstat.n_psg16);
10938
  printf (",%d", molstat.n_psg17);
10939
  printf (",%d", molstat.n_psg18);
10940
  printf (",%d", molstat.n_pstm);
10941
  printf (",%d", molstat.n_psla);
10942
  printf (",%d", molstat.n_iso);
10943
  printf (",%d\n", molstat.n_rad);
10944
  /*$ENDIF */
10945
}
10946
 
10947
/* routines for substructure matching */
10948
 
14179 bpr 10949
static int find_ndl_ref_atom ()
6785 bpr 10950
{
6786 kbelabas 10951
  int i;
6785 bpr 10952
  int score = -1, index = 0;
10953
  int n_nb, n_hc, FORLIM;
10954
 
10955
  /* finds a characteristic atom in the needle molecule, */
10956
  /* i.e., one with as many substituents as possible and */
10957
  /* with as many heteroatom substitutents as possible; */
10958
  /* added in v0.2d: make sure that reference atom is a heavy atom */
10959
  /* and not (accidentally) an explicit hydrogen; */
10960
  /* new in v0.3d: special treatment in case of E/Z geometry search */
10961
  /* to ensure that the entire A-B=C-D fragment is enclosed in one */
10962
  /* matchpath, regardless where the recursive search starts; */
10963
  /* refined in v0.3f: exclude only alkene-C as reference atoms */
10964
  /* added in v0.3o: needle atom must be "tagged" in order to be */
10965
  /* selected (prevents unconnected fragments from being overlooked) */
10966
  if (ndl_n_atoms == 0)
6786 kbelabas 10967
    return false;
14179 bpr 10968
  if (ez_search && ndl_n_heavyatoms > 2) {
10969
    FORLIM = ndl_n_atoms;
10970
    for (i = 1; i <= FORLIM; i++) {                     /* ignore sp2-carbons if not aromatic */
10971
           /*if ((ndl_atom^[i].atype <> 'C2 ') or (ndl_atom^[i].arom = true)) then */
10972
            if (ndl_alkene_C (i) == false && ndl_atom[i - 1].tag) {                     /* v0.3o */
6785 bpr 10973
              n_nb = ndl_atom[i - 1].neighbor_count;
10974
              n_hc = ndl_hetatom_count (i);
14179 bpr 10975
              if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy) {
10976
                /* v0.3j */
10977
                index = i;
10978
                score = n_nb * 11 + n_hc * 7;   /* changed in v0.3j */
10979
              }
6785 bpr 10980
            }
14179 bpr 10981
          }
10982
  }
6785 bpr 10983
  /* it is possible that no suitable reference atom has been found here */
10984
  /* (e.g., with "pure" polyenes), so we need a fallback option anyway */
14179 bpr 10985
  if (index == 0) {
10986
    ez_search = false;  /* just in case it was true */
10987
    opt_geom = false;           /* just in case it was true */
10988
    FORLIM = ndl_n_atoms;
10989
    for (i = 1; i <= FORLIM; i++) {
10990
            n_nb = ndl_atom[i - 1].neighbor_count;
10991
            n_hc = ndl_hetatom_count (i);
10992
            if (n_nb * 11 + n_hc * 7 > score && ndl_atom[i - 1].heavy &&
10993
                ndl_atom[i - 1].tag) {                  /* v0.3j */
6785 bpr 10994
              index = i;
10995
              score = n_nb * 11 + n_hc * 7;     /* changed in v0.3j */
10996
            }
14179 bpr 10997
            /* v0.3o */
10998
          }
10999
  }
6785 bpr 11000
  /* now index must be > 0 in any case (except for H2, or all tags have been cleared) */
11001
  if (index == 0)               /* just to be sure... */
11002
    index++;
11003
  return index;
11004
}
11005
 
14179 bpr 11006
static void cv_init ()
6785 bpr 11007
{
11008
  /* new in v0.3j */
11009
  int i;
11010
 
11011
  if (cv == NULL)
11012
    return;
11013
  memset (cv, 0, sizeof (connval_type));
11014
 
11015
  for (i = 0; i < ndl_n_atoms; i++)
11016
    cv[i].def = ndl_atom[i].neighbor_count;
11017
}
11018
 
14179 bpr 11019
static int cv_count ()
6785 bpr 11020
{
11021
  /* new in v0.3j, modified in v0.3m */
11022
  int i, j;
11023
  int cvlist[max_atoms];
11024
  int cvdef;
11025
  boolean isnew;
11026
  int entries = 0;
11027
  int FORLIM;
11028
 
11029
  if (cv == NULL)
11030
    return 0;
11031
  memset (cvlist, 0, sizeof (int) * max_atoms);
11032
  FORLIM = ndl_n_atoms;
14179 bpr 11033
  for (i = 0; i < FORLIM; i++) {
11034
    if (ndl_atom[i].heavy == true) {
11035
            cvdef = cv[i].def;
11036
            isnew = true;
11037
            if (entries > 0) {
11038
              for (j = 0; j < entries; j++) {
11039
                      if (cvlist[j] == cvdef)
11040
                        isnew = false;
11041
                    }
6785 bpr 11042
            }
14179 bpr 11043
            if (isnew) {
11044
                entries++;
11045
                cvlist[entries - 1] = cvdef;
6785 bpr 11046
            }
14179 bpr 11047
            /* now we have a list of unique connection values */
11048
          }
11049
  }
6785 bpr 11050
  return entries;
11051
}
11052
 
14179 bpr 11053
static int cv_iterate (n_cv_prev)
6785 bpr 11054
     int n_cv_prev;
11055
{
11056
  /* new in v0.3j, modified in v0.3m */
6788 kbelabas 11057
  int i, j;
6785 bpr 11058
  neighbor_rec nb;
11059
  int nnb, nsum, n_cv, FORLIM;
11060
 
11061
  if (cv == NULL || ndl_n_atoms == 0)
6788 kbelabas 11062
    return false;
6785 bpr 11063
  FORLIM = ndl_n_atoms;
11064
  /* update the connection values (Morgan algorithm) */
11065
 
11066
  memset (nb, 0, sizeof (neighbor_rec));
11067
 
14179 bpr 11068
  for (i = 1; i <= FORLIM; i++) {
11069
    if (ndl_atom[i - 1].heavy == true) {
11070
            get_ndl_neighbors (nb, i);
11071
            nnb = ndl_atom[i - 1].neighbor_count;
11072
            nsum = 0;
11073
            if (nnb > 0) {
11074
              for (j = 0; j < nnb; j++) {
11075
                if (ndl_atom[nb[j] - 1].heavy == true)
11076
                  nsum += cv[nb[j] - 1].def;
11077
              }
6785 bpr 11078
            }
14179 bpr 11079
            cv[i - 1].tmp = nsum;
11080
          }
11081
  }
6785 bpr 11082
  n_cv = cv_count ();
14179 bpr 11083
  if (n_cv > n_cv_prev) {
11084
    FORLIM = ndl_n_atoms;
11085
    for (i = 0; i < FORLIM; i++)
11086
            cv[i].def = cv[i].tmp;
11087
  }
6785 bpr 11088
  return n_cv;
11089
}
11090
 
14179 bpr 11091
static int find_ndl_ref_atom_cv ()
6785 bpr 11092
{
11093
  /* new in v0.3j, modified in v0.3m */
11094
  int Result, i;
11095
  int res = 1, it = 0;
11096
  int n_cv;
11097
  int n_cv_prev = 0;
11098
  boolean finished = false;
11099
  int cvmax = 0;
11100
  int FORLIM;
11101
 
11102
  if (ndl_n_atoms == 0)
11103
    return 0;
11104
  /* try */
11105
  cv = (connval_rec *) safe_malloc (sizeof (connval_type));
11106
  /* except
11107
     on e:Eoutofmemory do
11108
     begin
11109
     res := find_ndl_ref_atom;
11110
     $IFDEF debug
11111
     debugoutput('memory allocation for connection values failed, reverting to standard procedure');
11112
     $ENDIF
11113
     end;
11114
     end; */
11115
  cv_init ();
14179 bpr 11116
  do {
11117
    it++;                       /* iteration counter (a safeguard against infinite loops) */
11118
    n_cv = cv_iterate (n_cv_prev);
11119
    if (n_cv <= n_cv_prev)
11120
            finished = true;
11121
    n_cv_prev = n_cv;
11122
  }
6785 bpr 11123
  while (!(finished || it > 10000));
11124
  FORLIM = ndl_n_atoms;
11125
  /* now that we have canonical connection values (Morgan algorithm), */
11126
  /* pick the atom with the highest value */
11127
  /* added in v0.3o: atom must be "tagged" */
14179 bpr 11128
  for (i = 1; i <= FORLIM; i++) {
6785 bpr 11129
      /*writeln('cv for atom ',i,': ',cv^[i].def); */
14179 bpr 11130
    if (((cv[i - 1].def > cvmax) && (ndl_alkene_C (i) == false || ez_search == false))
11131
              && ndl_atom[i - 1].tag) {                 /* v0.3o */
11132
            cvmax = cv[i - 1].def;
11133
            res = i;
11134
          }
11135
  }
6785 bpr 11136
  Result = res;
11137
  /* try */
14179 bpr 11138
  if (cv != NULL) {
6785 bpr 11139
      free (cv);
11140
      cv = NULL;
11141
    }
11142
  /* except
11143
     on e:Einvalidpointer do begin end;
11144
     end; */
11145
  return Result;
11146
}
11147
 
14179 bpr 11148
static boolean atomtypes_OK_strict (ndl_a, hst_a)
6785 bpr 11149
     int ndl_a, hst_a;
11150
{
11151
  /* new in v0.2f */
11152
  str2 ndl_el;
11153
  str3 ndl_atype;
11154
  str2 hst_el;
11155
  str3 hst_atype;
11156
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
11157
  boolean res = false;
11158
 
11159
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11160
  strcpy (ndl_atype, ndl_atom[ndl_a - 1].atype);
11161
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11162
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11163
  strcpy (hst_el, atom[hst_a - 1].element);
11164
  strcpy (hst_atype, atom[hst_a - 1].atype);
11165
  hst_nbc = atom[hst_a - 1].neighbor_count;
11166
  hst_Htot = atom[hst_a - 1].Htot;
11167
  /* v0.3o: formal charges must be the same */
11168
 
11169
  if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
11170
    return false;
11171
 
11172
  /* v0.3x: isotope nucleon numbers must be the same */
11173
 
11174
  if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
11175
    return false;
11176
 
11177
  /* v0.3x: radicals must be the same */
11178
 
11179
  if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11180
    return false;
11181
 
11182
  if (!strcmp (ndl_atype, hst_atype))
11183
    res = true;
14179 bpr 11184
  else {
11185
    if (!strcmp (ndl_el, hst_el) && ndl_atom[ndl_a - 1].arom && atom[hst_a - 1].arom)
11186
            res = true;
11187
    if (ndl_querymol && (ndl_atom[ndl_a - 1].q_arom && atom[hst_a - 1].arom))
11188
            res = true;         /* 0.3 p */
11189
  }
6785 bpr 11190
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
11191
    res = true;
14179 bpr 11192
  if (!strcmp (ndl_el, "Q ")) {
11193
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
11194
            res = true;
11195
  }
11196
  if (!strcmp (ndl_el, "X ")) {
11197
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11198
            !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11199
            || !strcmp (hst_el, "AT"))
11200
          res = true;
11201
  }
6785 bpr 11202
  /* if needle atom has more substituents than haystack atom ==> no match */
11203
  if (ndl_nbc > hst_nbc)
11204
    res = false;
11205
  /* check for explicit hydrogens */
11206
  if (ndl_Hexp > hst_Htot)
11207
    res = false;
14179 bpr 11208
    /* p2c: checkmol.pas, line 8859:
11209
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11210
    /*$IFDEF debug */
11211
    /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
6785 bpr 11212
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+':'+ndl_atype+'/'+inttostr(hst_a)+':'+hst_atype+')'); */
14179 bpr 11213
    /*$ENDIF */
11214
    /* new in v0.3m: in "fingerprint mode", also query atom symbols must match */
11215
  if (opt_fp) {
11216
    if (strcmp (ndl_el, hst_el))
11217
            res = false;
11218
  }
6785 bpr 11219
  return res;
11220
}
11221
 
14179 bpr 11222
static boolean atomtypes_OK (ndl_a, hst_a)
6785 bpr 11223
     int ndl_a, hst_a;
11224
{
11225
  str2 ndl_el, hst_el;
11226
  int ndl_nbc, hst_nbc, ndl_Hexp, hst_Htot;
11227
  boolean res = false;
11228
 
11229
  if (ndl_a < 1 || ndl_a > ndl_n_atoms || hst_a < 1 || hst_a > n_atoms)
11230
    return false;
11231
  /* check for opposite charges;  v0.3l, refined in v0.3o, 0.3x */
11232
  /* except in strict mode, matching pairs of charged+uncharged atoms  */
11233
  /* are tolerated (this is a feature, not a bug) */
14179 bpr 11234
  if (opt_chg) {
11235
    if (ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
6785 bpr 11236
        return false;
14179 bpr 11237
  }
11238
  //  else
11239
  //    {
11240
  //      if (ndl_atom[ndl_a - 1].formal_charge != 0 &&
11241
  //        atom[hst_a - 1].formal_charge != 0 &&
11242
  //        ndl_atom[ndl_a - 1].formal_charge != atom[hst_a - 1].formal_charge)
11243
  //      return false;
11244
  //    }
11245
  //
11246
  //  /* v0.3x: isotopes must be the same */
11247
  if (opt_iso) {
11248
    if (ndl_atom[ndl_a - 1].nucleon_number != atom[hst_a - 1].nucleon_number)
11249
            return false;
11250
  }
11251
  //  else
11252
  //    {
11253
  //      if (ndl_atom[ndl_a - 1].nucleon_number != 0 &&
11254
  //        atom[hst_a - 1].nucleon_number != 0 &&
11255
  //        ndl_atom[ndl_a - 1].nucleon_number !=
11256
  //        atom[hst_a - 1].nucleon_number)
11257
  //      return false;
11258
  //    }
11259
  //
11260
  //  /* v0.3x: radicals must be the same */
11261
  if (opt_rad) {
11262
    if (ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11263
            return false;
11264
  }
11265
  //  else
11266
  //    {
11267
  //      if (ndl_atom[ndl_a - 1].radical_type != 0 &&
11268
  //        atom[hst_a - 1].radical_type != 0 &&
11269
  //        ndl_atom[ndl_a - 1].radical_type != atom[hst_a - 1].radical_type)
11270
  //      return false;
11271
  //    }
6785 bpr 11272
 
11273
  /* in exact mode, check if (disconnected) fragment is already tagged; v0.3o */
14179 bpr 11274
  if (opt_exact && atom[hst_a - 1].tag == true) {
11275
    /* p2c: checkmol.pas, line 8899:
11276
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11277
      /*$IFDEF debug */
11278
      /* debugoutput('fragmnet already tagged at '+inttostr(hst_a)); */
11279
      /*$ENDIF */
11280
      return false;
14179 bpr 11281
  }
6785 bpr 11282
  if (opt_strict)               /* new in v0.2f */
11283
    return (atomtypes_OK_strict (ndl_a, hst_a));
11284
  strcpy (ndl_el, ndl_atom[ndl_a - 1].element);
11285
  ndl_nbc = ndl_atom[ndl_a - 1].neighbor_count;
11286
  ndl_Hexp = ndl_atom[ndl_a - 1].Hexp;
11287
  strcpy (hst_el, atom[hst_a - 1].element);
11288
  hst_nbc = atom[hst_a - 1].neighbor_count;
11289
  hst_Htot = atom[hst_a - 1].Htot;
11290
  if (!strcmp (ndl_el, hst_el)) /* very simplified... */
11291
    res = true;
11292
  if (!strcmp (ndl_el, "A ") && atom[hst_a - 1].heavy)
11293
    res = true;
14179 bpr 11294
  if (!strcmp (ndl_el, "Q ")) {
11295
    if (atom[hst_a - 1].heavy && strcmp (hst_el, "C "))
11296
            res = true;
11297
  }
11298
  if (!strcmp (ndl_el, "X ")) {
11299
    if (!strcmp (hst_el, "F ") || !strcmp (hst_el, "CL") ||
11300
              !strcmp (hst_el, "BR") || !strcmp (hst_el, "I ")
11301
              || !strcmp (hst_el, "AT"))
11302
            res = true;
11303
  }
6785 bpr 11304
  /* v0.3o: in exact mode, check for identical neighbor_count */
14179 bpr 11305
  if (opt_exact) {
11306
    if (ndl_nbc != hst_nbc) {
6785 bpr 11307
          res = false;
14179 bpr 11308
    /* p2c: checkmol.pas, line 8934:
11309
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11310
          /*$IFDEF debug */
11311
          //debugoutput
11312
          //  ("exact match failed: different number of neighbor atoms");
11313
          /*$ENDIF */
11314
          }
11315
  }
6785 bpr 11316
  /* if needle atom has more substituents than haystack atom ==> no match */
11317
  if (ndl_nbc > hst_nbc)
11318
    res = false;
11319
  /* check for explicit hydrogens */
11320
  if (ndl_Hexp > hst_Htot)
11321
    res = false;
14179 bpr 11322
  /* p2c: checkmol.pas, line 8943:
11323
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11324
  /*$IFDEF debug */
11325
  /* if res then debugoutput('atom types OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')')
11326
     else debugoutput('atom types not OK ('+inttostr(ndl_a)+'/'+inttostr(hst_a)+')'); */
11327
  /*$ENDIF */
11328
  return res;
11329
}
11330
 
14179 bpr 11331
static boolean bondtypes_OK_strict (ndl_b, hst_b)
6785 bpr 11332
     int ndl_b, hst_b;
11333
{
11334
  boolean ndl_arom, hst_arom;
11335
  char ndl_btype, hst_btype;
11336
  int ndl_rc;                   /* new in v0.3d */
11337
  int hst_rc;                   /* new in v0.3d */
11338
  int ndl_btopo;                /* new in v0.3d */
11339
  boolean res = false;
14179 bpr 11340
  /* p2c: checkmol.pas, line 8960:
11341
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11342
  /*$IFDEF debug */
11343
  /*char na[256]; char ha[256];*/
11344
  char tstr[256];
11345
 
11346
  /*$ENDIF */
14179 bpr 11347
  /* p2c: checkmol.pas, line 8966:
11348
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11349
  /*$IFDEF debug */
11350
  *tstr = '\0';                 /* for debugging purposes only */
11351
  /*$ENDIF */
11352
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11353
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11354
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11355
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
11356
  hst_arom = bond[hst_b - 1].arom;
11357
  hst_btype = bond[hst_b - 1].btype;
11358
  hst_rc = bond[hst_b - 1].ring_count;
14179 bpr 11359
  /* p2c: checkmol.pas, line 8976:
11360
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11361
   /*$IFDEF debug */
11362
   /*if (ndl_arom)
11363
     strcpy (na, "(ar)");
11364
   else
11365
     *na = '\0';
11366
   if (hst_arom)
11367
     strcpy (ha, "(ar)");
11368
   else
11369
     *ha = '\0';*/
11370
   /*$ENDIF */
6785 bpr 11371
  if (ndl_arom == true && hst_arom == true)
11372
    res = true;
14179 bpr 11373
  if (ndl_arom == false && hst_arom == false) {
11374
    if (ndl_btype == hst_btype)
11375
            res = true;
11376
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
11377
            res = true;
11378
    if (ndl_btype == 's' && hst_btype == 'S')
11379
            res = true;
11380
    if (ndl_btype == 'd' && hst_btype == 'D')
11381
            res = true;
11382
  }
6785 bpr 11383
  /* a little exception: */
14179 bpr 11384
  if (ndl_arom == false && hst_arom == true) {
11385
    if (ndl_btype == 'A')
11386
            res = true;
11387
    if (ndl_btype == 's' || ndl_btype == 'd')
11388
            res = true;
11389
    if (ndl_bond[ndl_b - 1].q_arom)
11390
            res = true;         /* 0.3p */
11391
  }
6785 bpr 11392
  if (ndl_btype == 'a')
11393
    res = true;
11394
  /* new in v0.3d: strict comparison of topology (and even ring_count!) */
14179 bpr 11395
  if (ndl_btopo < btopo_always_any || ndl_btopo == btopo_exact_rc) {
11396
    if (ndl_rc != hst_rc) {
11397
            res = false;                /* this excludes further ring annulations as well as */
11398
      /* p2c: checkmol.pas, line 9001:
11399
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11400
            /*$IFDEF debug */
11401
            /* open-chains query structures to be found in rings */
11402
            /*
11403
               tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')';   */
11404
            /*$ENDIF */
11405
          }
11406
  }
11407
  else {
11408
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc) {
11409
            res = false;
11410
    /* p2c: checkmol.pas, line 9010:
11411
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11412
          /*$IFDEF debug */
11413
          /* tstr := ' ringcount mismatch ('+inttostr(ndl_rc)+'/'+inttostr(hst_rc)+')'; */
11414
          /*$ENDIF */
14179 bpr 11415
          }
11416
  }
11417
  /* p2c: checkmol.pas, line 9015:
11418
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11419
    /*$IFDEF debug */
11420
    /* if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11421
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11422
    /*$ENDIF */
6785 bpr 11423
  return res;
11424
}
11425
 
14179 bpr 11426
static boolean bondtypes_OK (ndl_b, hst_b)
6785 bpr 11427
     int ndl_b, hst_b;
11428
{
11429
  boolean ndl_arom, hst_arom;
11430
  char ndl_btype, hst_btype;
11431
  int ndl_rc;                   /* new in v0.3d */
11432
  int hst_rc;                   /* new in v0.3d */
11433
  int ndl_btopo;                /* new in v0.3d */
11434
  boolean res = false;
14179 bpr 11435
  /* p2c: checkmol.pas, line 9032:
11436
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11437
  /*$IFDEF debug */
11438
  /*char na[256], ha[256];*/
11439
  char tstr[256];
11440
  /*$ENDIF */
11441
  int a1, a2;
11442
  str2 a1_el, a2_el;
11443
 
11444
  if (ndl_b < 1 || ndl_b > ndl_n_bonds || hst_b < 1 || hst_b > n_bonds)
11445
    return false;
11446
  if (opt_strict)               /* new in v0.2f */
11447
    return (bondtypes_OK_strict (ndl_b, hst_b));
14179 bpr 11448
  /* p2c: checkmol.pas, line 9051:
11449
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11450
  /*$IFDEF debug */
11451
  *tstr = '\0';                 /* for debug purposes only */
11452
  /*$ENDIF */
11453
  ndl_arom = ndl_bond[ndl_b - 1].arom;
11454
  ndl_btype = ndl_bond[ndl_b - 1].btype;
11455
  hst_arom = bond[hst_b - 1].arom;
11456
  hst_btype = bond[hst_b - 1].btype;
11457
  ndl_rc = ndl_bond[ndl_b - 1].ring_count;
11458
  hst_rc = bond[hst_b - 1].ring_count;
11459
  ndl_btopo = ndl_bond[ndl_b - 1].topo;
14179 bpr 11460
  /* p2c: checkmol.pas, line 9061:
11461
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11462
    /*$IFDEF debug */
11463
    //if (ndl_arom)
11464
  //    strcpy (na, "(ar)");
11465
  //  else
11466
  //    *na = '\0';
11467
  //  if (hst_arom)
11468
  //    strcpy (ha, "(ar)");
11469
  //  else
11470
  //    *ha = '\0';
6785 bpr 11471
  /*$ENDIF */
11472
  if (ndl_arom == true && hst_arom == true)
11473
    res = true;
14179 bpr 11474
  if (ndl_arom == false && hst_arom == false) {
11475
    if (ndl_btype == hst_btype)
11476
            res = true;
11477
    if (ndl_btype == 'l' && (hst_btype == 'S' || hst_btype == 'D'))
11478
            res = true;
11479
    if (ndl_btype == 's' && hst_btype == 'S')
11480
            res = true;
11481
    if (ndl_btype == 'd' && hst_btype == 'D')
11482
            res = true;
11483
  }
6785 bpr 11484
  /* a little exception: */
14179 bpr 11485
  if (ndl_arom == false && hst_arom == true) {
11486
    if (ndl_btype == 'A')
6785 bpr 11487
            res = true;
14179 bpr 11488
    if (ndl_btype == 's' || ndl_btype == 'd')
11489
            res = true;
11490
    if (ndl_btype == 'D') {                     /* added in 0.2d: do not accept C=O etc. as C-O/arom */
11491
            a1 = ndl_bond[ndl_b - 1].a1;
11492
            a2 = ndl_bond[ndl_b - 1].a2;
11493
            strcpy (a1_el, ndl_atom[a1 - 1].element);
11494
            strcpy (a2_el, ndl_atom[a2 - 1].element);
11495
            if (strcmp (a1_el, "O ") && strcmp (a2_el, "O ")
11496
                && strcmp (a1_el, "S ") && strcmp (a2_el, "S ")
11497
                && strcmp (a1_el, "SE") && strcmp (a2_el, "SE")
11498
                && strcmp (a1_el, "TE") && strcmp (a2_el, "TE"))
11499
              res = true;
11500
          }
11501
    if (ndl_bond[ndl_b - 1].q_arom)
11502
            res = true;         /* 0.3p */
11503
  }
6785 bpr 11504
  if (ndl_btype == 'a')
11505
    res = true;
11506
  /* new in v0.3d: obey topology requirements in query structure */
14179 bpr 11507
  if (ndl_btopo != btopo_any && ndl_btopo != btopo_always_any) {
11508
    if (ndl_btopo == btopo_ring && hst_rc == 0)
11509
      res = false;
11510
    if (ndl_btopo == btopo_chain && hst_rc > 0)
11511
      res = false;
11512
    if (ndl_btopo == btopo_excess_rc && hst_rc <= ndl_rc)
11513
      res = false;
11514
    if (ndl_btopo == btopo_exact_rc && hst_rc != ndl_rc)
11515
      res = false;
11516
  }
11517
  /* p2c: checkmol.pas, line 9098:
11518
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11519
    /*$IFDEF debug */
11520
    /* if res = false then tstr := ' bond topology mismatch '+inttostr(ndl_rc)+'/'+inttostr(hst_rc); */
11521
    /*$ENDIF */
11522
  /* p2c: checkmol.pas, line 9102:
11523
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11524
    /*$IFDEF debug */
11525
    /*
11526
       if res then debugoutput('bond types OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+')') else
11527
       debugoutput('bond types not OK ('+inttostr(ndl_b)+':'+ndl_btype+na+'/'+inttostr(hst_b)+':'+hst_btype+ha+tstr+')'); */
11528
    /*$ENDIF */
6785 bpr 11529
  return res;
11530
}
11531
 
14179 bpr 11532
static boolean matrix_OK (m, ndl_dim, hst_dim)
6785 bpr 11533
boolean (*m)[max_neighbors];
11534
     int ndl_dim, hst_dim;
11535
{
11536
  /* new, recursive version in v0.2i: can handle up to max_neighbors substituents */
11537
  boolean mr = false;
11538
  matchmatrix lm;
11539
  int i, ii, j, lndl_dim, lhst_dim;
11540
 
11541
  if (ndl_dim < 1 || ndl_dim > max_neighbors || hst_dim < 1 ||
11542
      hst_dim > max_neighbors || ndl_dim > hst_dim)
11543
    return false;
14179 bpr 11544
  if (ndl_dim == 1) {
11545
    for (i = 0; i < hst_dim; i++) {
11546
            if (m[0][i])
11547
              mr = true;
11548
          }
11549
    return mr;
11550
  }
11551
  for (i = 1; i <= hst_dim; i++) {
11552
    if (m[0][i - 1]) {
11553
            /* write remaining fields into a new matchmatrix which is smaller by 1x1 */
11554
            memset (lm, false, sizeof (matchmatrix));
11555
            for (j = 2; j <= ndl_dim; j++) {
6785 bpr 11556
              lhst_dim = 0;
14179 bpr 11557
              for (ii = 1; ii <= hst_dim; ii++) {
11558
                if (ii != i) {
11559
                  lhst_dim++;
11560
                  lm[j - 2][lhst_dim - 1] = m[j - 1][ii - 1];
11561
                }
11562
              }
6785 bpr 11563
            }
14179 bpr 11564
            lndl_dim = ndl_dim - 1;
11565
            if (matrix_OK (lm, lndl_dim, lhst_dim)) {                   /* recursive call to matrix_OK */
6785 bpr 11566
              return true;
14179 bpr 11567
            /* stop any further work immediately */
6785 bpr 11568
            }
14179 bpr 11569
          }
11570
  }
6785 bpr 11571
  return false;
11572
}
11573
 
14179 bpr 11574
static boolean is_flat (angle_deg)
6785 bpr 11575
     double angle_deg;
11576
{
11577
  /* new in v0.3j */
11578
  if (fabs (angle_deg) > 5 && fabs (angle_deg) < 175)
11579
    return false;
11580
  else
11581
    return true;
11582
}
11583
 
14179 bpr 11584
static boolean chirality_OK (ndl_cp, hst_cp)
6785 bpr 11585
     int *ndl_cp, *hst_cp;
11586
{
11587
  boolean res = true;
11588
  double ndl_ct, hst_ct, ndl_ct_deg, hst_ct_deg;
11589
  p_3d np1, np2, np3, np4, hp1, hp2, hp3, hp4;
11590
  int level = 0;
11591
  int i;
11592
  boolean up = false, down = false, updown = false;
11593
  int ta1, ta2, ta3, ta4, ba1, ba2, FORLIM;
11594
 
11595
  /* fill temporary atom variables */
11596
  ta1 = ndl_cp[0];              /* this is the central atom */
11597
  ta2 = ndl_cp[1];
11598
  ta3 = ndl_cp[2];
11599
  ta4 = ndl_cp[3];
11600
  /* first, get the central atom of the needle */
11601
  np2.x = ndl_atom[ta1 - 1].x;
11602
  np2.y = ndl_atom[ta1 - 1].y;
11603
  np2.z = ndl_atom[ta1 - 1].z;
11604
  /* next, do the same for all 3 substituent atoms */
11605
  np1.x = ndl_atom[ta2 - 1].x;
11606
  np1.y = ndl_atom[ta2 - 1].y;
11607
  np1.z = ndl_atom[ta2 - 1].z;
11608
  np3.x = ndl_atom[ta3 - 1].x;
11609
  np3.y = ndl_atom[ta3 - 1].y;
11610
  np3.z = ndl_atom[ta3 - 1].z;
11611
  np4.x = ndl_atom[ta4 - 1].x;
11612
  np4.y = ndl_atom[ta4 - 1].y;
11613
  np4.z = ndl_atom[ta4 - 1].z;
11614
  /* now check all needle bonds if we should care about up/down bonds */
14179 bpr 11615
  if (ndl_n_bonds > 0) {
11616
    FORLIM = ndl_n_bonds;
11617
    for (i = 0; i < FORLIM; i++) {
11618
            if (ndl_bond[i].stereo == bstereo_up ||
11619
                  ndl_bond[i].stereo == bstereo_down) {
6785 bpr 11620
              ba1 = ndl_bond[i].a1;
11621
              ba2 = ndl_bond[i].a2;
14179 bpr 11622
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_up) {
11623
                      up = true;
11624
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11625
                        updown = true;
11626
                        if (ba2 == ta2)
11627
                                np1.z += 0.8;
11628
                        if (ba2 == ta3)
11629
                                np3.z += 0.8;
11630
                        if (ba2 == ta4)
11631
                                np4.z += 0.8;
11632
                      }
11633
                      else
11634
                        level++;
6785 bpr 11635
                    }
14179 bpr 11636
              if (ba1 == ta1 && ndl_bond[i].stereo == bstereo_down) {
11637
                      down = true;
11638
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11639
                        updown = true;
11640
                        if (ba2 == ta2)
11641
                                np1.z -= 0.8;
11642
                        if (ba2 == ta3)
11643
                                np3.z -= 0.8;
11644
                        if (ba2 == ta4)
11645
                                np4.z -= 0.8;
11646
                      }
11647
                      else
11648
                        level--;
6785 bpr 11649
                    }
14179 bpr 11650
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_up) {
11651
                      down = true;
11652
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11653
                        updown = true;
11654
                        if (ba1 == ta2)
11655
                          np1.z -= 0.8;
11656
                        if (ba1 == ta3)
11657
                          np3.z -= 0.8;
11658
                        if (ba1 == ta4)
11659
                          np4.z -= 0.8;
11660
                      }
11661
                      else
11662
                        level--;
6785 bpr 11663
                    }
14179 bpr 11664
              if (ba2 == ta1 && ndl_bond[i].stereo == bstereo_down) {
11665
                      up = true;
11666
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11667
                        updown = true;
11668
                        if (ba1 == ta2)
11669
                                np1.z += 0.8;
11670
                        if (ba1 == ta3)
11671
                                np3.z += 0.8;
11672
                        if (ba1 == ta4)
11673
                                np4.z += 0.8;
11674
                      }
11675
                      else
11676
                        level++;
6785 bpr 11677
                    }
11678
            }
14179 bpr 11679
          }                     /* for i ... */
11680
    if (updown == false && level != 0) {
11681
            if (level > 0)
11682
              np2.z += 0.3;
11683
            if (level < 0)
11684
              np2.z -= 0.3;
11685
          }
11686
    else {
11687
            if (up)
11688
              np2.z += 0.1;
11689
            if (down)
11690
              np2.z -= 0.1;
11691
          }
11692
  }
6785 bpr 11693
  /* fill temporary atom variables again */
11694
  ta1 = hst_cp[0];
11695
  ta2 = hst_cp[1];
11696
  ta3 = hst_cp[2];
11697
  ta4 = hst_cp[3];
11698
  /* then, get the central atom of the haystack */
11699
  hp2.x = atom[ta1 - 1].x;
11700
  hp2.y = atom[ta1 - 1].y;
11701
  hp2.z = atom[ta1 - 1].z;
11702
  /* next, do the same for all 3 substituent atoms */
11703
  hp1.x = atom[ta2 - 1].x;
11704
  hp1.y = atom[ta2 - 1].y;
11705
  hp1.z = atom[ta2 - 1].z;
11706
  hp3.x = atom[ta3 - 1].x;
11707
  hp3.y = atom[ta3 - 1].y;
11708
  hp3.z = atom[ta3 - 1].z;
11709
  hp4.x = atom[ta4 - 1].x;
11710
  hp4.y = atom[ta4 - 1].y;
11711
  hp4.z = atom[ta4 - 1].z;
11712
  /* now check all haystack bonds if we should care about up/down bonds */
11713
  level = 0;
11714
  updown = false;
11715
  up = false;
11716
  down = false;
14179 bpr 11717
  if (n_bonds > 0) {
11718
    FORLIM = n_bonds;
11719
    for (i = 0; i < FORLIM; i++) {
11720
            if (bond[i].stereo == bstereo_up || bond[i].stereo == bstereo_down) {
6785 bpr 11721
              ba1 = bond[i].a1;
11722
              ba2 = bond[i].a2;
14179 bpr 11723
              if (ba1 == ta1 && bond[i].stereo == bstereo_up) {
11724
                      up = true;
11725
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11726
                        updown = true;
11727
                        if (ba2 == ta2)
11728
                                hp1.z += 0.8;
11729
                        if (ba2 == ta3)
11730
                                hp3.z += 0.8;
11731
                        if (ba2 == ta4)
11732
                                hp4.z += 0.8;
11733
                      }
11734
                      else
11735
                        level++;
6785 bpr 11736
                    }
14179 bpr 11737
              if (ba1 == ta1 && bond[i].stereo == bstereo_down) {
11738
                      down = true;
11739
                      if (ba2 == ta2 || ba2 == ta3 || ba2 == ta4) {
11740
                        updown = true;
11741
                        if (ba2 == ta2)
11742
                              hp1.z -= 0.8;
11743
                        if (ba2 == ta3)
11744
                                hp3.z -= 0.8;
11745
                        if (ba2 == ta4)
11746
                              hp4.z -= 0.8;
11747
                     }
11748
                    else
11749
                      level--;
6785 bpr 11750
                    }
14179 bpr 11751
              if (ba2 == ta1 && bond[i].stereo == bstereo_up) {
11752
                      down = true;
11753
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11754
                        updown = true;
11755
                        if (ba1 == ta2)
11756
                               hp1.z -= 0.8;
11757
                        if (ba1 == ta3)
11758
                                hp3.z -= 0.8;
11759
                        if (ba1 == ta4)
11760
                                hp4.z -= 0.8;
11761
                      }
11762
                      else
11763
                        level--;
6785 bpr 11764
                    }
14179 bpr 11765
              if (ba2 == ta1 && bond[i].stereo == bstereo_down) {
11766
                      up = true;
11767
                      if (ba1 == ta2 || ba1 == ta3 || ba1 == ta4) {
11768
                        updown = true;
11769
                        if (ba1 == ta2)
11770
                                hp1.z += 0.8;
11771
                        if (ba1 == ta3)
11772
                                hp3.z += 0.8;
11773
                        if (ba1 == ta4)
11774
                                hp4.z += 0.8;
11775
                      }
11776
                      else
11777
                        level++;
6785 bpr 11778
                    }
11779
            }
14179 bpr 11780
          }                     /* for i ... */
11781
    if (updown == false && level != 0) {
11782
            if (level > 0)
11783
              hp2.z += 0.3;
11784
            if (level < 0)
11785
              hp2.z -= 0.3;
11786
          }
11787
    else {
11788
            if (up)
11789
              hp2.z += 0.1;
11790
            if (down)
11791
              hp2.z -= 0.1;
11792
          }
11793
  }
6785 bpr 11794
  /* get the pseudo-torsion angles */
11795
  ndl_ct = ctorsion (np1, np2, np3, np4);
11796
  hst_ct = ctorsion (hp1, hp2, hp3, hp4);
11797
  ndl_ct_deg = radtodeg (ndl_ct);
11798
  hst_ct_deg = radtodeg (hst_ct);
11799
  /* now do a plausibility check and finally check the sense */
11800
  /* (clockwise or counterclockwise) */
11801
  /*
11802
     if (abs(ndl_ct_deg) > 5) and (abs(ndl_ct_deg) < 175) and
11803
     (abs(hst_ct_deg) > 5) and (abs(hst_ct_deg) < 175) and
11804
     (ndl_ct_deg * hst_ct_deg < 0) then res := false;
11805
   */
11806
  if (((!is_flat (ndl_ct_deg)) && (!is_flat (hst_ct_deg))) &&
11807
      ndl_ct_deg * hst_ct_deg < 0)
11808
    res = false;
14179 bpr 11809
  if (rs_strict) {
6785 bpr 11810
      if (((is_flat (ndl_ct_deg) && (!is_flat (hst_ct_deg))) |
14179 bpr 11811
                (is_flat (hst_ct_deg) && (!is_flat (ndl_ct_deg)))) ||
11812
                ndl_ct_deg * hst_ct_deg < 0)
11813
              res = false;
11814
  }
6785 bpr 11815
  return res;
11816
}
11817
 
14179 bpr 11818
static boolean ndl_maybe_chiral (na)
6785 bpr 11819
     int na;
11820
{
11821
  /* new in v0.3h */
11822
  boolean res = false;
11823
  str2 el;
11824
  str3 at;
11825
  int n_nb;
11826
 
11827
  strcpy (el, ndl_atom[na - 1].element);
11828
  strcpy (at, ndl_atom[na - 1].atype);
11829
  n_nb = ndl_atom[na - 1].neighbor_count;
11830
  if (!strcmp (at, "C3 ") && n_nb > 2)
11831
    res = true;
14179 bpr 11832
  if (!strcmp (el, "N ")) {
11833
    if (!strcmp (at, "N3+") && n_nb == 4)
11834
            res = true;
11835
  }
11836
  if (!strcmp (el, "S ")) {                             /* sulfoxide */
11837
    if ((n_nb == 3) && (ndl_hetatom_count (na) == 1))
11838
            res = true;
11839
  }
6785 bpr 11840
  if (strcmp (el, "P ") && strcmp (el, "AS"))   /* "As" added in v0.3j */
11841
    return res;
11842
  if (n_nb > 3)                 /* are we missing something here? */
11843
    res = true;
11844
  if (ndl_hetatom_count (na) >= 2)      /* v0.3m; ignore phosphates etc. */
11845
    res = false;
11846
  return res;
11847
}
11848
 
14179 bpr 11849
static boolean is_matching (ndl_xmp, hst_xmp)
6785 bpr 11850
     int *ndl_xmp, *hst_xmp;
11851
{
11852
  int i, j, k, l, m, ndl_n_nb, n_nb, ndl_a, hst_a;
11853
  int ndl_b = 0, hst_b = 0, prev_ndl_a = 0, prev_hst_a = 0;
11854
  int next_ndl_a, next_hst_a;
11855
  neighbor_rec ndl_nb, hst_nb;
11856
  matchmatrix mm;
11857
  int ndl_mp_len, hst_mp_len;
11858
  matchpath_type ndl_mp, hst_mp;
11859
  boolean emptyline, res, ndl_cis, hst_cis;
11860
  int na1, na2, na3, na4;       /* v0.3d */
11861
  int ha1, ha2, ha3, ha4;       /* atom variables for E/Z check */
11862
  int prev_ndl_b;
11863
  int prev_hst_b;
11864
  p_3d p1, p2, p3, p4;
11865
  /*hst_torsion, ndl_torsion : double; */
11866
  chirpath_type ncp, hcp;
11867
  int n_hits, n_singlehits;
14179 bpr 11868
  /* p2c: checkmol.pas, line 9433:
11869
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11870
  /*$IFDEF debug */
11871
  //char tmpstr[256];
11872
 
11873
  /*$ENDIF */
11874
  /* initialize local matchpath variables */
11875
  //memset (ndl_mp, 0, sizeof (matchpath_type));
11876
  //memset (hst_mp, 0, sizeof (matchpath_type));
11877
  /* copy content of external variables into local ones */
11878
  memcpy (ndl_mp, ndl_xmp, sizeof (matchpath_type));
11879
  memcpy (hst_mp, hst_xmp, sizeof (matchpath_type));
11880
 
11881
  /*for (i = 0; i < max_matchpath_length; i++)
11882
     {
11883
     ndl_mp[i] = ndl_xmp[i];
11884
     hst_mp[i] = hst_xmp[i];
11885
     } */
11886
 
11887
  ndl_mp_len = matchpath_length (ndl_mp);
11888
  hst_mp_len = matchpath_length (hst_mp);
14179 bpr 11889
  if (ndl_mp_len != hst_mp_len) {
6785 bpr 11890
      /* this should never happen.... */
14179 bpr 11891
  /* p2c: checkmol.pas, line 9451:
11892
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11893
      /*$IFDEF debug */
11894
      //debugoutput ("needle and haystack matchpaths are of different length");
11895
      /*$ENDIF */
14179 bpr 11896
    return false;
11897
  }
6785 bpr 11898
  ndl_a = ndl_mp[ndl_mp_len - 1];
11899
  hst_a = hst_mp[hst_mp_len - 1];
11900
  ndl_atom[ndl_a - 1].tag = false;
11901
  /* new in v0.3o: mark the last needle atom as "visited" */
14179 bpr 11902
  if (ndl_mp_len > 1) {
11903
    prev_ndl_a = ndl_mp[ndl_mp_len - 2];
11904
    prev_hst_a = hst_mp[hst_mp_len - 2];
6785 bpr 11905
    }
11906
  /* if geometry checking is on, check it here */
14179 bpr 11907
  if (ez_search == true && ndl_mp_len > 3) {
11908
    na1 = ndl_mp[ndl_mp_len - 1];
11909
    na2 = ndl_mp[ndl_mp_len - 2];
11910
    na3 = ndl_mp[ndl_mp_len - 3];
11911
    na4 = ndl_mp[ndl_mp_len - 4];
11912
    ha1 = hst_mp[hst_mp_len - 1];
11913
    ha2 = hst_mp[hst_mp_len - 2];
11914
    ha3 = hst_mp[hst_mp_len - 3];
11915
    ha4 = hst_mp[hst_mp_len - 4];
11916
    prev_ndl_b = get_ndl_bond (na2, na3);
11917
    prev_hst_b = get_bond (ha2, ha3);
11918
    if (ndl_bond[prev_ndl_b - 1].btype == 'D' && bond[prev_hst_b - 1].arom == false
11919
              && (ndl_bond[prev_ndl_b - 1].stereo != bstereo_double_either
11920
              && bond[prev_hst_b - 1].stereo != bstereo_double_either)
11921
              /* 0.3x always match if needle and/or haystack bond is double_either */
11922
              && (!strcmp (atom[ha2 - 1].element, "C ")
11923
              || !strcmp (atom[ha2 - 1].element, "N "))
11924
              && (!strcmp (atom[ha3 - 1].element, "C ")
11925
              || !strcmp (atom[ha3 - 1].element, "N "))){
11926
                /* v0.3g; check C=C, C=N, N=N bonds */
11927
            p1.x = atom[ha1 - 1].x;
11928
            p1.y = atom[ha1 - 1].y;
11929
            p1.z = atom[ha1 - 1].z;
11930
            p2.x = atom[ha2 - 1].x;
11931
            p2.y = atom[ha2 - 1].y;
11932
            p2.z = atom[ha2 - 1].z;
11933
            p3.x = atom[ha3 - 1].x;
11934
            p3.y = atom[ha3 - 1].y;
11935
            p3.z = atom[ha3 - 1].z;
11936
            p4.x = atom[ha4 - 1].x;
11937
            p4.y = atom[ha4 - 1].y;
11938
            p4.z = atom[ha4 - 1].z;
11939
            hst_cis = is_cis (p1, p2, p3, p4);
11940
            /*hst_torsion := torsion(p1,p2,p3,p4); */
11941
            p1.x = ndl_atom[na1 - 1].x;
11942
            p1.y = ndl_atom[na1 - 1].y;
11943
            p1.z = ndl_atom[na1 - 1].z;
11944
            p2.x = ndl_atom[na2 - 1].x;
11945
            p2.y = ndl_atom[na2 - 1].y;
11946
            p2.z = ndl_atom[na2 - 1].z;
11947
            p3.x = ndl_atom[na3 - 1].x;
11948
            p3.y = ndl_atom[na3 - 1].y;
11949
            p3.z = ndl_atom[na3 - 1].z;
11950
            p4.x = ndl_atom[na4 - 1].x;
11951
            p4.y = ndl_atom[na4 - 1].y;
11952
            p4.z = ndl_atom[na4 - 1].z;
11953
            /*ndl_torsion := torsion(p1,p2,p3,p4); */
11954
            ndl_cis = is_cis (p1, p2, p3, p4);
11955
            if (ndl_cis != hst_cis) {
11956
        /* p2c: checkmol.pas, line 9501:
11957
        * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11958
              /*$IFDEF debug */
11959
              //debugoutput ("E/Z geometry mismatch");
11960
              /*$ENDIF */
11961
              return false;
11962
            }
14179 bpr 11963
          }
11964
  }                             /* end of E/Z geometry check */
6785 bpr 11965
  /* check whatever can be checked as early as now: */
11966
  /* e.g. different elements or more substituents on needle atom than on haystack */
11967
  if (!atomtypes_OK (ndl_a, hst_a))
11968
    return false;
11969
  /* positive scenarios, e.g. one-atom fragments  (v0.3o) */
14179 bpr 11970
  if (atom[hst_a - 1].neighbor_count == 0 && ndl_atom[ndl_a - 1].neighbor_count == 0) {
11971
    if (!atomtypes_OK (ndl_a, hst_a))
11972
            return false;
11973
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
11974
    atom[hst_a - 1].tag = true;
11975
    return true;
11976
  }
6785 bpr 11977
  /* and other possibilities: */
11978
  ndl_b = get_ndl_bond (prev_ndl_a, ndl_a);
11979
  hst_b = get_bond (prev_hst_a, hst_a);
14179 bpr 11980
  /* p2c: checkmol.pas, line 9529:
11981
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 11982
  /*$IFDEF debug */
11983
  /* debugoutput('Now checking atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
11984
  /*$ENDIF */
14179 bpr 11985
  if (ndl_b > 0 && hst_b > 0) {
11986
    /* do a quick check if bond types match */
11987
    if (!bondtypes_OK (ndl_b, hst_b)) {
11988
      /* p2c: checkmol.pas, line 9537:
11989
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
11990
            /*$IFDEF debug */
11991
            /*
6785 bpr 11992
             debugoutput('  failed match of bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)); */
14179 bpr 11993
           /*$ENDIF */
11994
            return false;
11995
          }
11996
  }
6785 bpr 11997
  /* a) we reached the end of our needle fragment (and atom/bond types match) */
14179 bpr 11998
  if ((ndl_atom[ndl_a - 1].neighbor_count == 1) && atomtypes_OK (ndl_a, hst_a) &&
11999
      bondtypes_OK (ndl_b, hst_b)) {
12000
    return true;
12001
  /* p2c: checkmol.pas, line 9549:
12002
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12003
      /*$IFDEF debug */
12004
      /* debugoutput('  ==> end of needle fragment at atom '+inttostr(ndl_a)+' (match)'); */
12005
      /*$ENDIF */
14179 bpr 12006
  }
6785 bpr 12007
  /* a.1) haystack fragment forms a ring, but needle does not;  v0.3m */
12008
  if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_length (ndl_mp)) &&
14179 bpr 12009
        (matchpath_pos (hst_a, hst_mp) < matchpath_length (hst_mp))) {
12010
    return false;
12011
    /* p2c: checkmol.pas, line 9559:
12012
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12013
      /*$IFDEF debug */
12014
      /*
12015
         debugoutput('  haystack forms a ring and needle does not at '+inttostr(hst_a));
12016
         {$ENDIF */
14179 bpr 12017
  }
6785 bpr 12018
  /* b) a ring is formed (ndl_a is already in the path) and atom/bond types match */
12019
  if ((matchpath_pos (ndl_a, ndl_mp) > 0) &&
14179 bpr 12020
      (matchpath_pos (ndl_a, ndl_mp) < matchpath_length (ndl_mp))) {
12021
    if ((matchpath_pos (ndl_a, ndl_mp) == matchpath_pos (hst_a, hst_mp)) &&
12022
              atomtypes_OK (ndl_a, hst_a) && bondtypes_OK (ndl_b, hst_b)) {
12023
              /* 1st chirality check */
12024
            if (!((matchpath_pos (ndl_a, ndl_mp) > 1 && (rs_search ||
12025
                                                       ndl_atom[ndl_a -1].stereo_care)) && ndl_maybe_chiral (ndl_a))) {
12026
                                        /* new in v0.3h */
6785 bpr 12027
              return true;
12028
            }                   /* end of 1st chirality check */
14179 bpr 12029
            na1 = ndl_a;                /* the (potential) chiral center (v0.3f) */
12030
            na2 = ndl_mp[matchpath_pos (ndl_a, ndl_mp) - 2];
12031
            na3 = ndl_mp[matchpath_pos (ndl_a, ndl_mp)];
12032
            na4 = ndl_mp[matchpath_length (ndl_mp) - 2];
12033
            ha1 = hst_a;
12034
            ha2 = hst_mp[matchpath_pos (hst_a, hst_mp) - 2];
12035
            ha3 = hst_mp[matchpath_pos (hst_a, hst_mp)];
12036
            ha4 = hst_mp[matchpath_length (hst_mp) - 2];
12037
            memset (ncp, 0, sizeof (chirpath_type));
12038
            memset (hcp, 0, sizeof (chirpath_type));
12039
            ncp[0] = na1;
12040
            ncp[1] = na2;
12041
            ncp[2] = na3;
12042
            ncp[3] = na4;
12043
            hcp[0] = ha1;
12044
            hcp[1] = ha2;
12045
            hcp[2] = ha3;
12046
            hcp[3] = ha4;
12047
            if (!chirality_OK (ncp, hcp)) {
12048
        /* p2c: checkmol.pas, line 9589:
12049
         * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12050
                      /*$IFDEF debug */
12051
                      //debugoutput ("chirality check failed at ring junction");
12052
                      /*$ENDIF */
12053
        return false;
12054
      }
12055
      /* p2c: checkmol.pas, line 9596:
12056
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12057
          /*$IFDEF debug */
12058
          //debugoutput ("chirality check succeeded at ring junction");
12059
          /*$ENDIF */
12060
      return true;
12061
      /* p2c: checkmol.pas, line 9602:
12062
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12063
            /*$IFDEF debug */
12064
            /* debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (match)'); */
12065
            /*$ENDIF */
12066
          }
12067
    else {
12068
            return false;
12069
      /* p2c: checkmol.pas, line 9609:
12070
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12071
            /*$IFDEF debug */
12072
            /*
12073
               debugoutput('matchpath forms ring at: '+inttostr(ndl_a)+' (no match)'); */
12074
            /*$ENDIF */
12075
          }
12076
  }
6785 bpr 12077
  /* in all other cases, do the hard work: */
12078
  /* first, get all heavy-atom neighbors of needle and haystack; */
12079
  /* at the beginning of the search, this means all neighbors, then it means */
12080
  /* all but the previous atom (where we came from) */
12081
  memset (ndl_nb, 0, sizeof (neighbor_rec));
12082
  memset (hst_nb, 0, sizeof (neighbor_rec));
12083
 
14179 bpr 12084
  if (matchpath_length (ndl_mp) == 1) {
12085
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count;
12086
    n_nb = atom[hst_a - 1].neighbor_count;
12087
    get_ndl_neighbors (ndl_nb, ndl_a);
12088
    get_neighbors (hst_nb, hst_a);
12089
  }
12090
  else {
12091
    ndl_n_nb = ndl_atom[ndl_a - 1].neighbor_count - 1;
12092
    n_nb = atom[hst_a - 1].neighbor_count - 1;
12093
    get_ndl_nextneighbors (ndl_nb, ndl_a, prev_ndl_a);
12094
    get_nextneighbors (hst_nb, hst_a, prev_hst_a);
12095
  }
6785 bpr 12096
  /* v0.3o: mark all neighbor atoms as "visited" */
12097
  for (i = 0; i < ndl_n_nb; i++)
12098
    ndl_atom[ndl_nb[i] - 1].tag = false;
12099
  /* now that the neighbor-arrays are filled, get all */
12100
  /* combinations of matches recursively; */
12101
  /* first, initialize the match matrix */
12102
  memset (mm, false, sizeof (matchmatrix));     /* new in v0.2i */
12103
  /* make sure there are not too many neighbors (max. max_neighbors)   */
14179 bpr 12104
  if (ndl_n_nb > max_neighbors || n_nb > max_neighbors) {                               /* updated in v0.2i */
12105
    /* p2c: checkmol.pas, line 9644:
12106
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12107
      /*$IFDEF debug */
12108
      //debugoutput ("too many neighbors - exiting");
12109
      /*$ENDIF */
14179 bpr 12110
    return false;
12111
  }
6785 bpr 12112
  /* check if matchpath is not already filled up */
14179 bpr 12113
  if (matchpath_length (ndl_mp) == max_matchpath_length) {
12114
    /* p2c: checkmol.pas, line 9653:
12115
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12116
      /*$IFDEF debug */
12117
      //debugoutput ("matchpath too int - exiting");
12118
      /*$ENDIF */
14179 bpr 12119
    return false;
12120
  }
6785 bpr 12121
  /* next, check which chain of the needle matches which chain of the haystack  */
14179 bpr 12122
  for (i = 0; i < ndl_n_nb; i++) {
12123
    emptyline = true;
12124
    next_ndl_a = ndl_nb[i];
12125
    for (j = 0; j < n_nb; j++) {
12126
            next_hst_a = hst_nb[j];
12127
            ndl_mp[ndl_mp_len] = next_ndl_a;
12128
            hst_mp[hst_mp_len] = next_hst_a;
12129
            if (is_matching (ndl_mp, hst_mp)) {                 /* recursive function call */
6785 bpr 12130
              if (max_match_recursion_depth != 0
14179 bpr 12131
                          && ++recursion_depth > max_match_recursion_depth) {
6785 bpr 12132
#ifndef MAKE_SHARED_LIBRARY
14179 bpr 12133
                      if (opt_verbose)
6785 bpr 12134
#endif
14179 bpr 12135
                        printf
6785 bpr 12136
                      ("Warning: max. number of match recursions (%i) reached, reverting to non-exhaustive match\n",
14179 bpr 12137
                      max_match_recursion_depth);
12138
                      //n_rings = max_rings;
12139
                     return true;
12140
                    }
6785 bpr 12141
              mm[i][j] = true;
12142
              emptyline = false;
12143
            }
14179 bpr 12144
          }
12145
    /* if a needle substituent does not match any of the haystack substituents, */
12146
    /* stop any further work immediately */
12147
    if (emptyline)
12148
            return false;
12149
  }
6785 bpr 12150
  /* finally, check the content of the matrix */
12151
  res = matrix_OK (mm, ndl_n_nb, n_nb);
12152
  /* optional: chirality check */
14179 bpr 12153
  if (!((res && (rs_search || ndl_atom[ndl_a - 1].stereo_care)) && ndl_maybe_chiral (ndl_a)))
6785 bpr 12154
    return res;
12155
  /* first, we have to clean up the match matrix in order to remove */
12156
  /* "impossible" multiple matches (new in v0.3h) */
14179 bpr 12157
  for (i = 1; i <= 3; i++) {
12158
    for (j = 1; j <= max_neighbors; j++) {                      /* haystack dimension */
12159
            n_hits = 0;
12160
            l = 0;
12161
            for (k = 1; k <= max_neighbors; k++) {                      /* needle dimension */
12162
              if (mm[k - 1][j - 1]) {
12163
                      n_hits++;
12164
                      l = k;
12165
                    }
6785 bpr 12166
            }
14179 bpr 12167
            if (n_hits == 1) {                  /* a unique match ==> kick out any other match at this pos. */
12168
              for (m = 1; m <= max_neighbors; m++) {
12169
                      if (m != j)
12170
                        mm[l - 1][m - 1] = false;
12171
                    }
6785 bpr 12172
            }
14179 bpr 12173
          }
12174
  }
6785 bpr 12175
  /* end of match matrix clean-up */
14179 bpr 12176
  if (prev_ndl_a > 0) {
12177
    n_singlehits = 1;
12178
    ncp[1] = prev_ndl_a;
12179
    hcp[1] = prev_hst_a;
12180
  }
6785 bpr 12181
  else
12182
    n_singlehits = 0;
12183
  ncp[0] = ndl_a;
12184
  hcp[0] = hst_a;
12185
  i = 0;
12186
  l = 0;
14179 bpr 12187
  while (n_singlehits < 3 && i < 4) {
12188
    i++;
12189
    n_hits = 0;
12190
    for (k = 1; k <= n_nb; k++) {
12191
            if (mm[i - 1][k - 1]) {
6785 bpr 12192
              n_hits++;
12193
              l = k;
12194
            }
14179 bpr 12195
          }
12196
    if (n_hits == 1) {
12197
            n_singlehits++;
12198
            ncp[n_singlehits] = ndl_nb[i - 1];
12199
            hcp[n_singlehits] = hst_nb[l - 1];
12200
          }
12201
  }
6785 bpr 12202
  if (n_singlehits != 3)
12203
    return res;
14179 bpr 12204
  if (!chirality_OK (ncp, hcp)) {
12205
    /* p2c: checkmol.pas, line 9749:
12206
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12207
          /*$IFDEF debug */
12208
          //debugoutput ("chirality check failed");
12209
          /*$ENDIF */
12210
          res = false;
12211
  }
12212
  else {
6785 bpr 12213
/* p2c: checkmol.pas, line 9755:
12214
 * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12215
      /*$IFDEF debug */
12216
      //debugoutput ("chirality check OK");
12217
      /*$ENDIF */
14179 bpr 12218
  }
6785 bpr 12219
  return res;
14179 bpr 12220
  /* p2c: checkmol.pas, line 9762:
12221
   * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12222
    /*$IFDEF debug */
12223
    /* if res then tmpstr := ' MATCH' else tmpstr := ' NO MATCH';
12224
       debugoutput('result for atoms '+inttostr(ndl_a)+'/'+inttostr(hst_a)+', bonds '+inttostr(ndl_b)+'/'+inttostr(hst_b)+':'+tmpstr); */
12225
    /*$ENDIF */
6785 bpr 12226
}
12227
 
14179 bpr 12228
static boolean quick_match ()
6785 bpr 12229
{
12230
  /* added in v0.2c */
12231
  int i;
12232
  boolean res = true;
14179 bpr 12233
  /* str3 ndl_atype;*/
6785 bpr 12234
  str2 ndl_el;                  /* v0.3l */
6788 kbelabas 12235
  int ndl_chg = 0;              /* v0.3l */
12236
  int ndl_rad = 0;              /* v0.3x */
12237
  int ndl_iso = 0;              /* v0.3x */
6785 bpr 12238
 
12239
  if ((ez_search || rs_search) && ndl_n_heavyatoms > 3)
12240
    /* v0.3f, v0.3m, v0.3o */
12241
    return false;
12242
  if (ndl_n_atoms < 1 || n_atoms < 1 || ndl_n_atoms > n_atoms ||
14179 bpr 12243
        ndl_n_bonds > n_bonds) {                                /* just to be sure... */
12244
    /* p2c: checkmol.pas, line 9786:
12245
     * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12246
          /*$IFDEF debug */
12247
    /* p2c: checkmol.pas: Note: Eliminated unused assignment statement [338] */
12248
          //debugoutput (" ==> quick_match failed");
12249
          /*$ENDIF */
12250
    return false;
12251
  }
6785 bpr 12252
 
14179 bpr 12253
  if (ndl_n_heavyatoms > 1) {
12254
    for (i = 0; i < ndl_n_atoms; i++) {
12255
            /*if atom^[i].atype <> ndl_atom^[i].atype then res := false;    (* changed in */
12256
            if (strcmp (atom[i].element, ndl_atom[i].element))  /* v0.2k */
12257
              return false;
12258
            //  if (atom[i].formal_charge != ndl_atom[i].formal_charge) /* v0.3o */
12259
            //res = false;
6785 bpr 12260
 
14179 bpr 12261
            if (opt_chg) {
6785 bpr 12262
              if (ndl_atom[i].formal_charge != atom[i].formal_charge)
14179 bpr 12263
                      return false;
6785 bpr 12264
            }
14179 bpr 12265
      /*  else {
12266
            if (ndl_atom[i].formal_charge != 0 &&
12267
          atom[i].formal_charge != 0 &&
12268
          ndl_atom[i].formal_charge != atom[i].formal_charge)
12269
        return false;
12270
          } */
6785 bpr 12271
 
14179 bpr 12272
          /* v0.3x: isotopes must be the same */
12273
            if (opt_iso) {
6785 bpr 12274
              if (ndl_atom[i].nucleon_number != atom[i].nucleon_number)
14179 bpr 12275
                      return false;
6785 bpr 12276
            }
14179 bpr 12277
          /*  else {
12278
          if (ndl_atom[i].nucleon_number != 0 &&
12279
          atom[i].nucleon_number != 0 &&
12280
          ndl_atom[i].nucleon_number !=
12281
          atom[i].nucleon_number)
12282
        return false;
12283
        }*/
6785 bpr 12284
 
14179 bpr 12285
            /* v0.3x: radicals must be the same */
12286
            if (opt_rad) {
6785 bpr 12287
              if (ndl_atom[i].radical_type != atom[i].radical_type)
14179 bpr 12288
                      return false;
6785 bpr 12289
            }
14179 bpr 12290
      /*  else {
12291
         if (ndl_atom[i].radical_type != 0 &&
12292
             atom[i].radical_type != 0 &&
12293
             ndl_atom[i].radical_type != atom[i].radical_type)
12294
           return false;
12295
       }*/
6785 bpr 12296
 
12297
        }
14179 bpr 12298
  /* p2c: checkmol.pas, line 9798:
12299
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12300
      /*$IFDEF debug */
12301
      //if (res)
12302
      //debugoutput (" ==> quick_match: atoms OK");
12303
      //else
12304
      //  debugoutput (" ==> quick_match: atoms not OK");
12305
      /*$ENDIF */
14179 bpr 12306
    if (ndl_n_bonds > 0) {
12307
            for (i = 0; i < ndl_n_bonds; i++) {
6785 bpr 12308
              if (ndl_bond[i].a1 != bond[i].a1 || ndl_bond[i].a2 != bond[i].a2
14179 bpr 12309
                        || ndl_bond[i].btype != bond[i].btype)
12310
                      return false;
6785 bpr 12311
            }
14179 bpr 12312
          }
12313
    /* p2c: checkmol.pas, line 9810:
12314
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12315
         /*$IFDEF debug */
12316
         //if (res)
12317
         //  debugoutput (" ==> quick_match: bonds OK");
12318
         //else
12319
         //  debugoutput (" ==> quick_match: bonds not OK");
12320
         /*$ENDIF */
12321
         /* added in v0.2d: special case: needle contains only one heavy atom; refined in v0.3l, v0.3o */
12322
   }
12323
  else {
12324
    /* first, find out the element and atom type of the only heavy atom       */
12325
    for (i = 0; i < ndl_n_atoms; i++) {
12326
            if (ndl_atom[i].heavy) {
6785 bpr 12327
              //strcpy (ndl_atype, ndl_atom[i].atype);
12328
              strcpy (ndl_el, ndl_atom[i].element);     /* v0.3l */
12329
              ndl_chg = ndl_atom[i].formal_charge;      /* v0.3l */
12330
              ndl_iso = ndl_atom[i].nucleon_number;     /* 0.3x */
12331
              ndl_rad = ndl_atom[i].radical_type;       /* 0.3x */
12332
            }
14179 bpr 12333
          }
12334
    for (i = 0; i < n_atoms; i++) {                     /* v0.3l, v0.3o */
12335
            if (                //      !strcmp (atom[i].atype, ndl_atype) &&
12336
                !strcmp (atom[i].element, ndl_el)) {
12337
              if (opt_chg || opt_strict) {
12338
                      if (ndl_chg != atom[i].formal_charge)
12339
                        return false;
12340
                    }
12341
              if (opt_iso || opt_strict) {
12342
                      if (ndl_iso != atom[i].nucleon_number)
12343
                        return false;
12344
                    }
6785 bpr 12345
 
14179 bpr 12346
              if (opt_rad || opt_strict) {
12347
                      if (ndl_rad != atom[i].radical_type)
12348
                        return false;
12349
                    }
12350
                    return true;
12351
            }
12352
            else {
12353
              res=false;
12354
            }
12355
          }
12356
  }
12357
  /* p2c: checkmol.pas, line 9828:
12358
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12359
  /*$IFDEF debug */
12360
  //if (res)
12361
  //  debugoutput (" ==> quick_match succeeded");
12362
  //else
12363
  //  debugoutput (" ==> quick_match failed (2)");
12364
  /*$ENDIF */
12365
  return res;
12366
}
12367
 
14179 bpr 12368
static void perform_match ()
6785 bpr 12369
{
12370
  int i = 0;
12371
  int j;
12372
  /*ndl_ref_atom : integer;  (* since v0.3j as a global variable */
12373
  int ndl_n_nb, ndl_n_hc, n_nb, n_hc;
12374
  boolean qm;                   /* v0.3l */
12375
  /* check for NoStruct (0 atoms);  v0.3l */
14179 bpr 12376
  if (n_atoms == 0 || ndl_n_atoms == 0) {
6785 bpr 12377
      matchresult = false;
14179 bpr 12378
  /* p2c: checkmol.pas, line 9849:
12379
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12380
      /*$IFDEF debug */
12381
      //debugoutput ("NoStruct encountered - aborted match routine");
12382
      /*$ENDIF */
14179 bpr 12383
    return;
12384
  }
6785 bpr 12385
  /* if we perform an exact match, needle and haystack must have */
12386
  /* the same number of atoms, bonds, and rings */
14179 bpr 12387
  if (opt_exact && opt_iso)     /* 0.3x */ {
12388
      if (n_heavyatoms != ndl_n_heavyatoms || n_heavybonds != ndl_n_heavybonds) {
12389
              matchresult = false;
12390
      /* p2c: checkmol.pas, line 9861:
12391
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12392
          /*$IFDEF debug */
12393
          //debugoutput ("different number of heavy atoms and/or bonds");
12394
          /*$ENDIF */
12395
          //return;
12396
          }
12397
  }
6785 bpr 12398
 
12399
  /* have a quick look if needle and haystack are identical molfiles */
12400
  qm = quick_match ();          /* v0.3l */
14179 bpr 12401
  if (qm) {
12402
    matchresult = true;
12403
    clear_ndl_atom_tags ();     /* v0.3o */
12404
    return;
12405
  }
6785 bpr 12406
  /* if we have only one heavy atom and quick_match fails, return "false";  v0.3l */
14179 bpr 12407
  if (ndl_n_heavyatoms == 1) {
12408
    matchresult = false;
12409
    return;
12410
  }
12411
  /* p2c: checkmol.pas, line 9881:
12412
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12413
  /*$IFDEF debug */
12414
  /* debugoutput('needle reference atom: '+inttostr(ndl_ref_atom)+' ('+ndl_atom^[ndl_ref_atom].atype+')'); */
12415
  /*$ENDIF */
12416
  ndl_n_nb = ndl_atom[ndl_ref_atom - 1].neighbor_count;
12417
  ndl_n_hc = ndl_hetatom_count (ndl_ref_atom);
14179 bpr 12418
  /* p2c: checkmol.pas, line 9886:
12419
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12420
  /*$IFDEF debug */
12421
  /* debugoutput('neighbor atoms: '+inttostr(ndl_n_nb)+'  heteroatom neighbors: '+inttostr(ndl_n_hc)); */
12422
  /*$ENDIF */
12423
  matchresult = false;
14179 bpr 12424
  for (j = 0; j < max_matchpath_length; j++) {
12425
    ndl_matchpath[j] = 0;
12426
    hst_matchpath[j] = 0;
12427
  }
6785 bpr 12428
  ndl_matchpath[0] = ndl_ref_atom;
14179 bpr 12429
  while (i < n_atoms && matchresult == false) {
12430
    i++;
12431
    n_nb = atom[i - 1].neighbor_count;
12432
    n_hc = hetatom_count (i);
12433
    if (n_nb >= ndl_n_nb && n_hc >= ndl_n_hc) {
12434
      /* p2c: checkmol.pas, line 9904:
12435
      * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12436
              /*$IFDEF debug */
12437
              /* debugoutput('trying atom '+inttostr(i)+'; neighbor atoms: '+inttostr(n_nb)+' heteroatom neighbors: '+inttostr(n_hc)); */
12438
              /*$ENDIF */
6785 bpr 12439
 
14179 bpr 12440
            recursion_depth = 0;
12441
            hst_matchpath[0] = i;
12442
            matchresult = is_matching (ndl_matchpath, hst_matchpath);
12443
      /* p2c: checkmol.pas, line 9909:
12444
       * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12445
          /*$IFDEF debug */
12446
          /* if matchresult then debugoutput('matching atom in haystack: '+inttostr(i)+' ('+atom^[i].atype+')'); */
12447
          /*$ENDIF */
12448
      if (matchresult)  /* v0.3o; mark this fragment as matched */
12449
        atom[i - 1].tag = true;
12450
          }
12451
  }
6785 bpr 12452
}
12453
 
14179 bpr 12454
static void clear_rings ()
6785 bpr 12455
{
12456
  int i, FORLIM;
12457
  n_rings = 0;
12458
  memset (ring, 0, sizeof (ringlist));
14179 bpr 12459
  for (i = 0; i < max_rings; i++) {                             /* new in v0.3 */
12460
    ringprop[i].size = 0;
12461
    ringprop[i].arom = false;
12462
    ringprop[i].envelope = false;
12463
  }
12464
  if (n_atoms > 0) {
12465
    FORLIM = n_atoms;
12466
    for (i = 0; i < FORLIM; i++)
12467
            atom[i].ring_count = 0;
12468
  }
12469
  if (n_bonds > 0) {
12470
    FORLIM = n_bonds;
12471
    for (i = 0; i < FORLIM; i++)
12472
            bond[i].ring_count = 0;
12473
  }
6785 bpr 12474
}
12475
 
14179 bpr 12476
static int ring_lastpos (s)
6785 bpr 12477
     int *s;
12478
{
12479
  int i, rc;
12480
  int rlp = 0;
12481
  int FORLIM;
12482
  if (n_rings <= 0)
12483
    return rlp;
12484
  FORLIM = n_rings;
14179 bpr 12485
  for (i = 1; i <= FORLIM; i++) {
12486
    rc = ringcompare (s, ring[i - 1]);
12487
    if (rc_identical (rc))
12488
            rlp = i;
12489
  }
6785 bpr 12490
  return rlp;
12491
}
12492
 
14179 bpr 12493
static void remove_redundant_rings ()
6785 bpr 12494
{
12495
  int i, j, k, rlp;
12496
  ringpath_type tmp_path;
12497
  int FORLIM, FORLIM1;
12498
  if (n_rings < 2)
12499
    return;
12500
  FORLIM = n_rings;
14179 bpr 12501
  for (i = 1; i < FORLIM; i++) {
12502
    memcpy (tmp_path, ring[i - 1], sizeof (ringpath_type));
12503
    rlp = ring_lastpos (tmp_path);
12504
    while (rlp > i) {
12505
           FORLIM1 = n_rings;
12506
      /* p2c: checkmol.pas, line 9970:
12507
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 12508
          /*$IFDEF debug */
12509
          /* debugoutput('removing redundant ring: '+inttostr(rlp)+' (identical to ring '+inttostr(i)+')'); */
12510
          /*$ENDIF */
14179 bpr 12511
            for (j = rlp; j < FORLIM1; j++) {
6785 bpr 12512
              memcpy (ring[j - 1], ring[j], sizeof (ringpath_type));
12513
              ringprop[j - 1].size = ringprop[j].size;  /* new in v0.3 */
12514
              ringprop[j - 1].arom = ringprop[j].arom;
12515
              ringprop[j - 1].envelope = ringprop[j].envelope;
12516
            }
14179 bpr 12517
            for (k = 0; k < max_ringsize; k++)
12518
              ring[n_rings - 1][k] = 0;
12519
            n_rings--;
12520
            rlp = ring_lastpos (tmp_path);
12521
          }
12522
  }
6785 bpr 12523
}
12524
 
14179 bpr 12525
static int count_aromatic_rings ()
6785 bpr 12526
{
12527
  int i;
12528
  int n = 0;
12529
  int FORLIM;
12530
  if (n_rings <= 0)
12531
    return n;
12532
  FORLIM = n_rings;
14179 bpr 12533
  for (i = 0; i < FORLIM; i++) {
12534
    if (ringprop[i].arom)
12535
            n++;
12536
  }
6785 bpr 12537
  return n;
12538
}
12539
 
14179 bpr 12540
static void chk_envelopes ()
6785 bpr 12541
{
12542
  /* new in v0.3d */
12543
  /* checks if a ring completely contains one or more other rings */
12544
  int a, i, j, k, l, pl, pli;
12545
  boolean found_atom, found_all_atoms, found_ring;
12546
  int FORLIM;
12547
  if (n_rings < 2)
12548
    return;
12549
  FORLIM = n_rings;
14179 bpr 12550
  for (i = 1; i < FORLIM; i++) {
12551
    found_ring = false;
12552
    j = 0;
12553
    pli = ringprop[i].size;     /* path_length(ring^[i]); */
12554
    while (j < i && found_ring == false) {
12555
            j++;
12556
            found_all_atoms = true;
12557
            pl = ringprop[j - 1].size;  /* path_length(ring^[j]); */
12558
            for (k = 0; k < pl; k++) {
6785 bpr 12559
              found_atom = false;
12560
              a = ring[j - 1][k];
14179 bpr 12561
              for (l = 0; l < pli; l++) {
12562
                      if (ring[i][l] == a)
12563
                        found_atom = true;
12564
                    }
6785 bpr 12565
              if (found_atom == false)
14179 bpr 12566
                      found_all_atoms = false;
6785 bpr 12567
            }
14179 bpr 12568
            if (found_all_atoms)
12569
              found_ring = true;
12570
          }
12571
    if (found_ring)
12572
            ringprop[i].envelope = true;
12573
  }
6785 bpr 12574
}
12575
 
14179 bpr 12576
static void update_ringcount ()
6785 bpr 12577
{
12578
  int i, j, a1, a2, b, pl, FORLIM;
12579
  if (n_rings <= 0)
12580
    return;
12581
  chk_envelopes ();
12582
  FORLIM = n_rings;
14179 bpr 12583
  for (i = 0; i < FORLIM; i++) {
12584
      if (ringprop[i].envelope == false) {
12585
            pl = ringprop[i].size;      /* path_length(ring^[i]);  (* v0.3d */
12586
            a2 = ring[i][pl - 1];
12587
            for (j = 0; j < pl; j++) {
6785 bpr 12588
              a1 = ring[i][j];
12589
              atom[a1 - 1].ring_count++;
12590
              b = get_bond (a1, a2);
12591
              bond[b - 1].ring_count++;
12592
              a2 = a1;
12593
            }
14179 bpr 12594
          }
12595
  }
6785 bpr 12596
}
12597
 
14179 bpr 12598
static boolean normalize_ionic_bonds ()
6785 bpr 12599
{
12600
  /* v0.3k */
12601
  /* changed from a procedure into a function in v0.3m */
12602
  int i, a1, a2, fc1, fc2;
12603
  char bt;
12604
  boolean res = false;          /* v0.3m */
12605
  int FORLIM;
12606
  /* v0.3m */
12607
  if (n_bonds == 0)
12608
    return false;
12609
  FORLIM = n_bonds;
14179 bpr 12610
  for (i = 0; i < FORLIM; i++) {
12611
    a1 = bond[i].a1;
12612
    a2 = bond[i].a2;
12613
    bt = bond[i].btype;
12614
    fc1 = atom[a1 - 1].formal_charge;
12615
    fc2 = atom[a2 - 1].formal_charge;
12616
    if (fc1 * fc2 == -1 && (bt == 'S' || bt == 'D')) {
12617
            atom[a1 - 1].formal_charge = 0;
12618
            atom[a2 - 1].formal_charge = 0;
12619
            if (!strcmp (atom[a1 - 1].atype, "N3+"))    /* v0.3m */
12620
              strcpy (atom[a1 - 1].atype, "N3 ");
12621
            if (!strcmp (atom[a2 - 1].atype, "N3+"))    /* v0.3m */
12622
              strcpy (atom[a2 - 1].atype, "N3 ");
12623
            if (bt == 'D')
12624
              bond[i].btype = 'T';
12625
            if (bt == 'S')
12626
              bond[i].btype = 'D';
12627
            res = true;         /* v0.3m */
12628
          }
12629
  }
6785 bpr 12630
  return res;                   /* v0.3m (return true if any change was made */
12631
}
12632
 
12633
#if 0
14179 bpr 12634
static void chk_wildcard_rings ()               // new in v0.3p
6785 bpr 12635
// checks if there are any wildcard atom types or bond types
12636
// in a ring of the needle; if yes ==> set the q_arom flag in the
14179 bpr 12637
// atom and bond record of all ring members in order to perform the
6785 bpr 12638
// match a bit more generously
12639
{
12640
 
12641
  int i, j, rs;
12642
  int a1, a2, b;
12643
  boolean wcr;
12644
  str3 at;
12645
  char bt;
12646
 
12647
  if (ndl_querymol == false)
12648
    return;
12649
  if (ndl_n_rings == 0)
12650
    return;
12651
  // now look for any not-yet-aromatic rings which contain a wildcard
14179 bpr 12652
  for (i = 0; i < ndl_n_rings; i++) {
12653
    wcr = false;
12654
    if (ndl_ringprop[i].arom == false) {
12655
            rs = ndl_ringprop[i].size;
12656
            a2 = ndl_ring[i][rs];
12657
            for (j = 0; j < rs; j++) {
6785 bpr 12658
              a1 = ndl_ring[i][j];
12659
              b = get_ndl_bond (a1, a2);
12660
              strcpy (at, ndl_atom[a1].atype);
12661
              bt = ndl_bond[b].btype;
12662
              if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
14179 bpr 12663
                      wcr = true;
6785 bpr 12664
              if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
14179 bpr 12665
                      wcr = true;
6785 bpr 12666
              a2 = a1;
12667
            }
14179 bpr 12668
            if (wcr) {                  // if yes, flag all atoms and bonds in this ring as "potentially" aromatic
6785 bpr 12669
              // {$IFDEF debug}
12670
              // debugoutput('wildcard ring found');
12671
              // {$ENDIF}
12672
              a2 = ndl_ring[i][rs];
14179 bpr 12673
              for (j = 0; j < rs; j++) {
12674
                      a1 = ndl_ring[i][j];
12675
                      b = get_ndl_bond (a1, a2);
12676
                      strcpy (at, ndl_atom[a1].atype);
12677
                      bt = ndl_bond[b].btype;
12678
                      ndl_atom[a1].q_arom = true;
12679
                      ndl_bond[b].q_arom = true;
12680
                      a2 = a1;
12681
                    }
6785 bpr 12682
            }
14179 bpr 12683
          }
12684
  }
6785 bpr 12685
  // and now undo this flagging for all rings which contain no wildcard
14179 bpr 12686
  for (i = 0; i < ndl_n_rings; i++) {
12687
    wcr = false;
12688
    rs = ndl_ringprop[i].size;
12689
    a2 = ndl_ring[i][rs];
12690
    for (j = 0; j < rs; j++) {
12691
            a1 = ndl_ring[i][j];
12692
            b = get_ndl_bond (a1, a2);
12693
            strcpy (at, ndl_atom[a1].atype);
12694
            bt = ndl_bond[b].btype;
12695
            if (!strcmp (at, "A  ") || !strcmp (at, "Q  "))
12696
              wcr = true;
12697
            if (bt == 'l' || bt == 's' || bt == 'd' || bt == 'a')
12698
              wcr = true;
12699
            a2 = a1;
12700
          }
12701
    if (!wcr) {                 // if yes, unflag all atoms and bonds in this ring
12702
            a2 = ndl_ring[i][rs];
12703
            for (j = 0; j < rs; j++) {
6785 bpr 12704
              a1 = ndl_ring[i][j];
12705
              b = get_ndl_bond (a1, a2);
12706
              strcpy (at, ndl_atom[a1].atype);
12707
              bt = ndl_bond[b].btype;
12708
              ndl_atom[a1].q_arom = false;
12709
              ndl_bond[b].q_arom = false;
12710
              a2 = a1;
12711
            }
14179 bpr 12712
          }
12713
  }
6785 bpr 12714
  // some further refinement would be necessary here in order to unflag everything
12715
  // which contains a wildcard but which definitely cannot be aromatic
12716
}
12717
#endif
12718
 
12719
#ifndef MAKE_SHARED_LIBRARY
12720
 
14179 bpr 12721
int main (int argc, char *argv[])
6785 bpr 12722
{                               /* main routine */
12723
  char STR1[256], STR6[256];
12724
  int FORLIM;
12725
  /* progmode = pmMatchMol */
12726
  rfile = NULL;
12727
  strcpy (progname, argv[0]);
12728
  strncpy (STR1, progname, 253);
12729
  if (strstr (STR1, "matchmol") != NULL)
12730
    progmode = pmMatchMol;
14179 bpr 12731
  else {
12732
    strncpy (STR6, progname, 253);
12733
    if (strstr (STR6, "checkmol") == NULL) {
12734
            printf ("THOU SHALLST NOT RENAME ME!\n");
12735
            exit (9);
12736
          }
12737
    progmode = pmCheckMol;
12738
  }
12739
  if (argc == 1) {
12740
    show_usage ();
12741
    exit (1);
12742
  }
6785 bpr 12743
  init_globals ();
12744
  init_molstat (&molstat);
12745
  parse_args (argc, argv);
12746
  if (ringsearch_mode == rs_sar)
12747
    max_vringsize = max_ringsize;
12748
  else
12749
    max_vringsize = ssr_vringsize;
12750
  /* v0.3n (was: 10) */
12751
  /*if opt_verbose then writeln(progname+' v',version,'  N. Haider 2003-2007'); */
14179 bpr 12752
  if (progmode == pmMatchMol) {
12753
    left_trim (ndl_molfilename);
12754
    left_trim (molfilename);
12755
    if ((*molfilename == '\0' || *ndl_molfilename == '\0' || argc < 3) && !opt_stdin) {
6785 bpr 12756
            show_usage ();
14179 bpr 12757
            exit (2);           /* new in v0.2k */
12758
          }
12759
    if (!(file_exists (ndl_molfilename)) && !opt_stdin) {
12760
      /*not  fileexists(ndl_molfilename) REPLACE!!! */
12761
                  printf("2");
12762
                  /* p2c: checkmol.pas, line 10128:
12763
                  * Warning: Expected an expression, found a ')' [227] */
12764
            if (strlen (ndl_molfilename) > 1 && ndl_molfilename[0] == '-')
12765
              show_usage ();
12766
            else
12767
              printf ("file %s not found!\n", ndl_molfilename);
12768
            /* new in v0.2k */
12769
            exit (2);
12770
          }
12771
  }
6785 bpr 12772
 
14179 bpr 12773
  if (!(file_exists (molfilename)) && !opt_stdin) {                             /*not  fileexists(ndl_molfilename) REPLACE!!! */
12774
    /* p2c: checkmol.pas, line 10128:
12775
    * Warning: Expected an expression, found a ')' [227] */
6785 bpr 12776
 
14179 bpr 12777
    if (strlen (molfilename) > 1 && molfilename[0] == '-')
12778
            show_usage ();
12779
    else
12780
            printf ("file %s not found!\n", molfilename);
6785 bpr 12781
      /* new in v0.2k */
12782
      exit (2);
14179 bpr 12783
  }
6785 bpr 12784
 
12785
  /* read the first molecule and process it; if we are in "matchmol" mode, */
12786
  /* this is the "needle" */
12787
  if (progmode == pmMatchMol)
12788
    readinputfile (ndl_molfilename);
12789
  else
12790
    readinputfile (molfilename);
12791
  li = 1;                       /* initialize line pointer for input buffer */
12792
  get_filetype (filetype, ndl_molfilename);
14179 bpr 12793
  if (!strcmp (filetype, "unknown")) {
12794
    printf ("unknown query file format!\n");
12795
    if (!opt_verbose)
12796
            exit (3);
12797
    printf ("===========================================\n");
12798
    FORLIM = molbufindex;
12799
    for (i = 1; i <= FORLIM; i++)
12800
            puts (molbuf[i - 1]);
12801
    exit (3);
12802
  }
6785 bpr 12803
  mol_OK = true;                /* added in v0.2i */
12804
  if (!strcmp (filetype, "alchemy"))
12805
    read_molfile (ndl_molfilename);
12806
  if (!strcmp (filetype, "sybyl"))
12807
    read_mol2file (ndl_molfilename);
12808
  if (!strcmp (filetype, "mdl"))
12809
    read_MDLmolfile (ndl_molfilename);
12810
  count_neighbors ();
14179 bpr 12811
  if (!mol_OK || n_atoms < 1) {                                 /* v0.3g; check if this is a valid query structure */
12812
    printf ("invalid molecule\n");
12813
    exit (3);
12814
  }
12815
  if (!found_arominfo || progmode == pmCheckMol) {                              /* added in v0.2b/0.2c */
12816
  /* p2c: checkmol.pas, line 10172:
12817
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12818
      /*$IFDEF debug
6785 bpr 12819
         if (!found_arominfo)
12820
         debugoutput
12821
         ("no aromaticity information found - checking myself...");
12822
         else
12823
         debugoutput ("performing full aromaticity check");
14179 bpr 12824
         // new in v0.3d
6785 bpr 12825
      $ENDIF */
14179 bpr 12826
    chk_ringbonds ();
12827
    if (ringsearch_mode == rs_ssr)
12828
            remove_redundant_rings ();
12829
    if (n_rings >= max_rings) {
12830
            if (opt_verbose)
12831
              printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12832
                 max_rings);
12833
            ringsearch_mode = rs_ssr;
12834
            auto_ssr = true;    /* v0.3n */
12835
            clear_rings ();
12836
            max_vringsize = ssr_vringsize;      /* v0.3n (was: 10) */
12837
            chk_ringbonds ();
12838
            remove_redundant_rings ();
12839
          }
12840
    update_ringcount ();
12841
    /* new in v0.3k: if output is a molfile, leave the original */
12842
    /* representation of N-oxides, S-oxides, nitro groups, etc. */
12843
    /* unchanged (ionic or non-ionic), in any other case make covalent bonds */
12844
    if (!opt_xmdlout)           /* v0.3k */
12845
            normalize_ionic_bonds ();
12846
    update_atypes ();
12847
    update_Htotal ();           /* added in v0.3 */
12848
    chk_arom ();
12849
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
12850
            do {
6785 bpr 12851
              prev_n_ar = count_aromatic_rings ();
12852
              chk_arom ();
12853
              n_ar = count_aromatic_rings ();
12854
            }
14179 bpr 12855
            while (prev_n_ar - n_ar != 0);
12856
          }
12857
  }
12858
  else {                                /* v0.3k */
12859
    /* p2c: checkmol.pas, line 10206:
12860
    * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12861
      /*$IFDEF debug
6785 bpr 12862
         debugoutput ("found aromaticity information in input file");
12863
         $ENDIF */
14179 bpr 12864
    if (!opt_xmdlout)
12865
            normalize_ionic_bonds ();
12866
    update_atypes ();           /* added in v0.2f */
12867
    update_Htotal ();           /* end v0.2b snippet */
12868
  }
12869
  if (progmode == pmCheckMol) {
12870
    if (opt_verbose)
12871
            write_mol ();
12872
    get_molstat ();
12873
    if (opt_molstat) {
12874
            if (opt_molstat_X)
12875
              write_molstat_X ();
12876
            else
12877
              write_molstat ();
12878
          }
12879
    else {
12880
            if (found_querymol) {
12881
                printf ("input structure contains query atom or query bond!\n");
12882
                exit (1);
6785 bpr 12883
            }
14179 bpr 12884
            chk_functionalgroups ();
12885
            if (opt_none)
12886
              opt_text = true;
12887
            if (opt_text)
12888
              write_fg_text ();
12889
            if (opt_text_de)
12890
              write_fg_text_de ();
12891
            if (opt_code)
12892
              write_fg_code ();
12893
            if (opt_bin)
12894
              write_fg_binary ();
12895
            if (opt_bitstring)
12896
              write_fg_bitstring ();
12897
            if (opt_xmdlout)
12898
              write_MDLmolfile ();
12899
          }
6785 bpr 12900
      /*if opt_verbose   then write_mol; */
14179 bpr 12901
    zap_molecule ();
12902
  }
12903
  else {
6785 bpr 12904
      /* now transfer all data to the "needle" set of variables, except for "fingerprint" mode */
14179 bpr 12905
    if (!opt_fp) {                      /* v0.3m */
12906
            copy_mol_to_needle ();
12907
            //chk_wildcard_rings (); /* 0.3p */
12908
            set_ndl_atom_tags ();       /* v0.3o */
12909
            if (opt_verbose)
12910
              write_needle_mol ();
12911
            if (rs_strict)      /* v0.3j */
12912
              ndl_ref_atom = find_ndl_ref_atom_cv ();
12913
            else
12914
              ndl_ref_atom = find_ndl_ref_atom ();
12915
          }
12916
    else {
12917
            copy_mol_to_tmp (); /* v0.3m */
12918
            if (opt_verbose)
12919
              printf ("1st molecule stored in buffer: %s\n", tmp_molname);
12920
          }
12921
    /* next, read the "haystack" file and process it */
12922
    li = 1;
12923
    mol_count = 0;
12924
    fpdecimal = 0;              /* v0.3m */
12925
    fpindex = 0;                /* v0.3m */
12926
    do {
12927
            /* new in v0.3i: reset ringsearch_mode to its initial value */
12928
            /* for each new molecule */
12929
            ringsearch_mode = opt_rs;
12930
            if (ringsearch_mode == rs_sar)
12931
              max_vringsize = max_ringsize;
12932
            else
12933
              max_vringsize = ssr_vringsize;
12934
            /* v0.3n (was: 10) */
12935
            readinputfile (molfilename);
12936
            li = 1;
12937
            get_filetype (filetype, molfilename);
12938
            if (strcmp (filetype, "unknown")) {
6785 bpr 12939
              found_arominfo = false;   /* added in v0.2b */
12940
              mol_OK = true;    /* added in v0.2i */
12941
              if (!strcmp (filetype, "alchemy"))
14179 bpr 12942
                      read_molfile (molfilename);
6785 bpr 12943
              if (!strcmp (filetype, "sybyl"))
14179 bpr 12944
                      read_mol2file (molfilename);
6785 bpr 12945
              if (!strcmp (filetype, "mdl"))
14179 bpr 12946
                      read_MDLmolfile (molfilename);
6785 bpr 12947
              mol_count++;
12948
              fpindex++;
12949
              count_neighbors ();
12950
              /*if (not mol_OK) or (n_atoms < 1) then writeln(mol_count,':no valid structure found') else */
14179 bpr 12951
              if (!mol_OK || (n_atoms < 1 && !(opt_fp && fpformat == fpf_decimal)))
12952
                      printf ("%i:F\n", mol_count);
12953
              else {
12954
                      if (opt_exact && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
12955
                                || n_Ntot != ndl_n_Ntot)) {             /* new in v0.3g */
12956
                        if (!opt_molout && !(opt_fp && fpformat == fpf_decimal))
12957
                                printf ("%i:F\n", mol_count);
12958
                      }
12959
                      else {
12960
                        if (!found_arominfo || (opt_strict && tmfmismatch)) {   /* added in v0.3m */
12961
              /* p2c: checkmol.pas, line 10294:
12962
               * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12963
                                  /*$IFDEF debug
12964
                              debugoutput
12965
                              ("no aromaticity information found (or tweak mismatch) - checking myself...");
12966
                              *$ENDIF */
6785 bpr 12967
                              chk_ringbonds ();
14179 bpr 12968
                              if (ringsearch_mode == rs_ssr)
12969
                                remove_redundant_rings ();
12970
                               if (n_rings == max_rings) {
12971
                                if (opt_verbose)
12972
                                        printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
12973
                                         max_rings);
12974
                                ringsearch_mode = rs_ssr;
12975
                                clear_rings ();
12976
                                max_vringsize = ssr_vringsize;  /* v0.3n (was: 10) */
12977
                                chk_ringbonds ();
12978
                                remove_redundant_rings ();
12979
                              }
12980
                              update_ringcount ();
12981
                              update_atypes ();
12982
                              update_Htotal (); /* added in v0.3 */
12983
                              chk_arom ();
12984
                              if (ringsearch_mode == rs_ssr) {  /* new in v0.3 */
12985
                                do {
12986
                                        prev_n_ar = count_aromatic_rings ();
12987
                                        chk_arom ();
12988
                                        n_ar = count_aromatic_rings ();
12989
                                      }
12990
                                while (prev_n_ar - n_ar != 0);
12991
                              }
6785 bpr 12992
                            }
14179 bpr 12993
                      else {    /* added in v0.2f */
12994
            /* p2c: checkmol.pas, line 10322:
12995
            * Note: Turbo Pascal conditional compilation directive was ignored [218] */
12996
                            /*$IFDEF debug
6785 bpr 12997
                             debugoutput
12998
                             ("found aromaticity information in input file");
12999
                             $ENDIF */
14179 bpr 13000
                              if (opt_strict)
13001
                                update_atypes ();
13002
                              update_Htotal ();
13003
                            }
6785 bpr 13004
                      init_molstat (&ndl_molstat);
13005
                      if (normalize_ionic_bonds ())
14179 bpr 13006
                              /* new in v0.3k, modified in v0.3m */
13007
                              update_atypes ();
6785 bpr 13008
                      if (opt_verbose && !opt_fp)
14179 bpr 13009
                              write_mol ();
6785 bpr 13010
                      /* if in "fingerprint mode", exchange needle and haystack */
14179 bpr 13011
                      if (opt_fp) {     /* v0.3m */
13012
                              zap_needle ();
13013
                              copy_mol_to_needle ();
13014
                              //chk_wildcard_rings (); /* 0.3p */
13015
                              zap_molecule ();
13016
                              copy_tmp_to_mol ();
13017
                              if (opt_verbose)
13018
                                write_needle_mol ();
13019
                              if (rs_strict)    /* v0.3j */
13020
                                ndl_ref_atom = find_ndl_ref_atom_cv ();
13021
                              else
13022
                                ndl_ref_atom = find_ndl_ref_atom ();
13023
                              if (opt_verbose)
13024
                                write_mol ();
13025
                            }   /* v0.3m */
6785 bpr 13026
                      /* now that we have both molecules, perform the comparison */
13027
                      /* v0.3o: takes care of disconnected fragment... */
13028
                      clear_atom_tags ();
13029
                      set_ndl_atom_tags ();
13030
                      matchsummary = true;
13031
                      perform_match ();
13032
                      matchsummary = matchresult;
14179 bpr 13033
                      if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true) {
13034
                              do {
13035
                                if (rs_strict)
13036
                                        ndl_ref_atom = find_ndl_ref_atom_cv ();
13037
                                else
13038
                                        ndl_ref_atom = find_ndl_ref_atom ();
13039
                                perform_match ();
13040
                                if (matchresult == false)
13041
                                        matchsummary = false;
13042
                              }
13043
                              while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
6785 bpr 13044
                            }
13045
                      /* end of disconnected-fragment matching (v0.3o) */
14179 bpr 13046
                      if (matchsummary == true) {       /* v0.3o */
13047
                              if (opt_molout) {
13048
                                FORLIM = molbufindex;
13049
                                for (i = 1; i <= FORLIM; i++)
13050
                                        puts (molbuf[i - 1]);
13051
                              }
13052
                              else {
13053
                                if (!opt_fp)    /* inttostr(mol_count) REPLACE!!!, */
13054
                                        printf ("%i:T\n", mol_count);
13055
                                else {
13056
                                        if (ndl_n_heavyatoms == n_heavyatoms &&
13057
                                            ndl_n_heavybonds == n_heavybonds)
13058
                                          fp_exacthit = true;
13059
                                        else
13060
                                          fp_exacthit = false;
13061
                                        if (fp_exacthit)
13062
                                          fp_exactblock = true;
13063
                                        if (fpformat == fpf_boolean) {
13064
                                          if (fp_exacthit)      /* inttostr(mol_count), REPACE!!! */
13065
                                                  printf ("%i:TX\n", mol_count);
13066
                                          else
13067
                                                  printf ("%i:T\n", mol_count);
13068
                                        }
13069
                                        /* inttostr(mol_count), REPLACE!!! */
13070
                                        if (fpformat == fpf_decimal) {
13071
                                          fpincrement = 1;
13072
                                          FORLIM = fpindex;
13073
                                          for (i = 1; i <= FORLIM; i++)
13074
                                                  fpincrement <<= 1;
13075
                                          fpdecimal += fpincrement;
13076
                                        }
13077
                                      }
13078
                              }
6785 bpr 13079
                            }
14179 bpr 13080
                      else {
13081
                              if (!(opt_molout || (opt_fp && fpformat == fpf_decimal)))
13082
                                /* inttostr(mol_count), REPLACE!!! */
13083
                               printf ("%i:F\n", mol_count);
6785 bpr 13084
                            }
14179 bpr 13085
                      if (opt_fp && fpformat == fpf_decimal && fpindex == fp_blocksize) {
13086
                              if (fp_exactblock)
13087
                                fpdecimal++;
13088
                              printf ("%lld\n", fpdecimal);
13089
                              fpindex = 0;
13090
                              fpdecimal = 0;
13091
                              fp_exactblock = false;
13092
                            }
6785 bpr 13093
                      zap_molecule ();
13094
                      molbufindex = 0;
13095
                    }
14179 bpr 13096
                  }
13097
          }
13098
          else {
13099
            /* v0.3l */
13100
            /* mol_OK */
13101
            printf ("%i:unknown file format\n", mol_count);
13102
          }
6785 bpr 13103
        }
14179 bpr 13104
  while (mol_in_queue != false);
13105
    /* if filetype <> 'unknown' */
13106
    if (opt_fp && fpformat == fpf_decimal && fpindex > 0) {
13107
            if (fp_exactblock)
13108
              fpdecimal++;
13109
            printf ("%lld\n", fpdecimal);
13110
          }
13111
    zap_needle ();
13112
    if (rfile_is_open){                 /* new in v0.2g */
13113
            if (rfile != NULL)
13114
              fclose (rfile);
13115
            rfile = NULL;
13116
          }
13117
  }
6785 bpr 13118
  if (rfile != NULL)
13119
    fclose (rfile);
13120
  exit (0);
13121
}
13122
 
13123
#else
13124
 
14179 bpr 13125
static void init_globals_dll (void)
6785 bpr 13126
{
13127
 
13128
//printf("init_globals_dll\n");
13129
 
13130
  int i;
13131
  opt_verbose = false;
13132
  opt_debug = false;
13133
  opt_stdin = false;
13134
  opt_text = false;
13135
  opt_code = false;
13136
  opt_bin = false;
13137
  opt_bitstring = false;
13138
  opt_molout = false;
13139
  opt_molstat = false;
13140
  opt_molstat_X = false;
13141
  opt_xmdlout = false;
13142
  opt_fp = false;               /* new in v0.3m */
13143
  /*cm_mdlmolfile   := false; */
13144
  found_arominfo = false;
13145
  found_querymol = false;
13146
  ndl_querymol = false;
13147
  opt_rs = rs_sar;              /* v0.3i */
13148
  ringsearch_mode = opt_rs;
13149
  rfile_is_open = false;        /* new in v0.2g */
13150
  ez_flag = false;              /* new in v0.3f */
13151
  chir_flag = false;            /* new in v0.3f */
13152
  n_Ctot = 0;
13153
  n_Otot = 0;
13154
  n_Ntot = 0;                   /* new in v0.3g */
13155
  //for (i = 0; i < max_fg; i++)
13156
  //  fg[i] = false;
13157
  memset (fg, 0, sizeof (fglist));
13158
 
14179 bpr 13159
  if (!yet_initialized) {
13160
    molbuf = (void *) safe_malloc (sizeof (molbuftype));
13161
    opt_exact = false;
13162
    opt_strict = false; /* new in v0.2f */
13163
    opt_metalrings = false;     /* new in v0.3 */
13164
    opt_geom = false;           /* new in v0.3d */
13165
    opt_chiral = false; /* new in v0.3f */
13166
    opt_iso = false;            /* new in v0.3x */
13167
    opt_chg = false;            /* new in v0.3x */
13168
    opt_rad = false;            /* new in v0.3x */
13169
    ez_search = false;  /* new in v0.3d */
13170
    rs_search = false;  /* new in v0.3f */
13171
    rs_strict = false;  /* new in v0.3j */
13172
    ndl_n_Ctot = 0;
13173
    ndl_n_Otot = 0;
13174
    ndl_n_Ntot = 0;             /* new in v0.3g */
13175
    yet_initialized = true;
13176
  }
6785 bpr 13177
 
13178
  ether_generic = false;        /* v0.3j */
13179
  amine_generic = false;        /* v0.3j */
13180
  hydroxy_generic = false;      /* v0.3j */
13181
  fpformat = fpf_decimal;       /* v0.3m */
13182
  fpindex = 0;                  /* v0.3m */
13183
  fp_exacthit = false;          /* v0.3m */
13184
  fp_exactblock = false;        /* v0.3m */
13185
  tmfcode = 0;                  /* v0.3m */
13186
  tmfmismatch = false;          /* v0.3m */
13187
  auto_ssr = false;
13188
  recursion_depth = 0;
13189
}
13190
 
14179 bpr 13191
static void mm_init_mol (void)
6785 bpr 13192
{
13193
//printf("mm_init_mol\n");
13194
  init_globals_dll ();
13195
  init_molstat (&molstat);
14179 bpr 13196
  if (opt_rs_dll == RPA_DEFAULT) {
13197
    ringsearch_mode = opt_rs;
13198
    //printf("DEFAULT: %i\n",ringsearch_mode);
13199
  }
13200
  else {
13201
    ringsearch_mode = opt_rs_dll;
13202
  }
6785 bpr 13203
  //printf("RPA: %i\n",ringsearch_mode);
13204
 
14179 bpr 13205
  if (ringsearch_mode == rs_sar) {
6785 bpr 13206
      max_vringsize = max_ringsize;
14179 bpr 13207
  }
13208
  else {
6785 bpr 13209
      max_vringsize = ssr_vringsize;
14179 bpr 13210
  }
6785 bpr 13211
  zap_molecule ();
13212
  molbufindex = 0;
13213
  mol_count = 0;
13214
//printf("mm_init_mol\n");
13215
}
13216
 
14179 bpr 13217
static void mm_elab_mol (boolean checkmol_mode, boolean normalize_ionic_bnds)
6785 bpr 13218
{
13219
//printf("mm_elab_mol\n");
13220
 
13221
  li = 1;                       // initialize line pointer for input buffer
13222
  get_filetype (filetype, ndl_molfilename);
14179 bpr 13223
  if (strcmp (filetype, "unknown") == 0) {
13224
    //messagebox (0,'Error in mm_ElabMol: Unknown file format','MATCHMOLDLL ERROR',0);
13225
    exit (3);
13226
  }
6785 bpr 13227
 
13228
  if (checkmol_mode == true)
13229
    progmode = pmCheckMol;
13230
  else
13231
    progmode = pmMatchMol;
13232
  if (strcmp (filetype, "alchemy") == 0)
13233
    read_molfile (ndl_molfilename);
13234
  if (strcmp (filetype, "sybyl") == 0)
13235
    read_mol2file (ndl_molfilename);
13236
  if (strcmp (filetype, "mdl") == 0)
13237
    read_MDLmolfile (ndl_molfilename);
14179 bpr 13238
  if (checkmol_mode) {
13239
    if (found_querymol) {
13240
            printf ("Warning: Input structure contains query atom or query bond.\n");
13241
          }
13242
  }
6785 bpr 13243
 
13244
  count_neighbors ();
14179 bpr 13245
  if (!found_arominfo || checkmol_mode || opt_strict) {
13246
    //printf("No arom found or checkmol mode\n");
13247
    chk_ringbonds ();
13248
    if (ringsearch_mode == rs_ssr)
13249
            remove_redundant_rings ();
13250
    if (n_rings >= max_rings) {
13251
            printf ("Warning: max. number of rings (%i) reached, reverting to SSR search\n",
13252
               max_rings);
13253
            ringsearch_mode = rs_ssr;
13254
            auto_ssr = true;
13255
            clear_rings ();
13256
            max_vringsize = ssr_vringsize;
13257
            chk_ringbonds ();
13258
            remove_redundant_rings ();
13259
          }
6785 bpr 13260
 
14179 bpr 13261
    update_ringcount ();
13262
    if (normalize_ionic_bnds)   /* v0.3k */
13263
            normalize_ionic_bonds ();
13264
    update_atypes ();
13265
    update_Htotal ();
13266
    chk_arom ();
13267
    if (ringsearch_mode == rs_ssr) {                    /* new in v0.3 */
13268
            do {
6785 bpr 13269
              prev_n_ar = count_aromatic_rings ();
13270
              chk_arom ();
13271
              n_ar = count_aromatic_rings ();
13272
            }
14179 bpr 13273
            while (prev_n_ar - n_ar != 0);
13274
          }
13275
  }
13276
  else {
13277
    if (normalize_ionic_bnds)   /* v0.3k  */
13278
            normalize_ionic_bonds ();
13279
    //if (opt_strict)
13280
    update_atypes ();
13281
    update_Htotal ();
13282
  }
13283
  //printf("mm_elab_mol\n");
6785 bpr 13284
}
13285
 
14179 bpr 13286
DLLEXPORT void mm_set_current_mol_as_query (void)
6785 bpr 13287
{
14179 bpr 13288
  //printf("mm_set_current_mol_as_query\n");
6785 bpr 13289
  zap_needle ();
14179 bpr 13290
  //mm_ElabMol;
6785 bpr 13291
  copy_mol_to_needle ();
13292
  //chk_wildcard_rings (); /* 0.3p */
13293
  set_ndl_atom_tags ();         /* v0.3o */
13294
  if (opt_geom)                 /* v0.3d */
13295
    ez_search = true;
13296
  else if (!ez_flag && ez_search)
13297
    ez_search = false;          //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
14179 bpr 13298
  if (opt_chiral) {                             /* v0.3f */
6785 bpr 13299
      rs_search = true;
13300
      //printf("%i\n",rs_search);
14179 bpr 13301
  }
13302
  else
13303
    if (!chir_flag && rs_search) {
6785 bpr 13304
      rs_search = false;        //chir_flag initialized in read_MDLmolfile, otherwise we lose that info
13305
      //printf("%i\n",rs_search);
13306
    }
13307
  if (opt_chiral && opt_strict && opt_exact)    /* new in v0.3j */
13308
    rs_strict = true;
13309
  else
13310
    rs_strict = false;
14179 bpr 13311
    /* if (rs_strict)              // v0.3j
13312
       ndl_ref_atom = find_ndl_ref_atom_cv ();
13313
       //ndl_ref_atom = find_ndl_ref_atom ();
13314
       else
13315
       ndl_ref_atom = find_ndl_ref_atom (); */
6785 bpr 13316
 
13317
  molbufindex = 0;
13318
  mol_count = 0;
14179 bpr 13319
  /*printf("mm_set_current_mol_as_query\n");*/
6785 bpr 13320
}
13321
 
14179 bpr 13322
DLLEXPORT int mm_get_rings (void)
6785 bpr 13323
{
13324
  return n_rings;
13325
}
13326
 
14179 bpr 13327
DLLEXPORT void xm_version (char *buffer)
6785 bpr 13328
{
13329
  buffer[0] = '\0';
13330
  strncpy (buffer, version, 255);
13331
}
13332
 
14179 bpr 13333
DLLEXPORT int mm_get_atom_ring (int atom_number)
6785 bpr 13334
{
13335
 
13336
  int i, j, a1, pl;
13337
  int ret = 0;
13338
  a1 = atom[atom_number].ring_count;
14179 bpr 13339
  if (n_rings > 0) {
13340
    for (i = 1; i < n_rings; i++) {
13341
            pl = path_length (ring[i]);
13342
      //          a2 := ring^[i,pl];
13343
            for (j = 1; j < pl; j++) {
6785 bpr 13344
              a1 = ring[i][j];
13345
              if (atom_number == a1)
14179 bpr 13346
                      ret = i;
13347
          //
13348
          //              inc(atom^[a1].ring_count);
13349
          //              b := get_bond(a1,a2);
13350
          //              inc(bond^[b].ring_count);
13351
          //              a2 := a1;
6785 bpr 13352
            }
14179 bpr 13353
          }
13354
  }
6785 bpr 13355
  return ret;
13356
}
13357
 
14179 bpr 13358
static void mm_read_input_line (char *st)
6785 bpr 13359
{
13360
//printf("mm_read_input_line_in\n");
13361
//var
13362
//yyy:pchar;
13363
 
13364
  mol_in_queue = false;
14179 bpr 13365
  if (molbufindex < (max_atoms + max_bonds + slack)) {
6785 bpr 13366
 
14179 bpr 13367
    //yyy:=Pchar(IntToStr(molbufindex));
13368
    //messagebox (0,yyy,'',0);
13369
    //printf("%i\n",molbufindex);
13370
    //printf("B:%s\n",st);
13371
          strcpy (molbuf[molbufindex++], st);
13372
    //printf("%x %x\n",&molbuf,molbuf);
13373
    //printf("%s\n",molbuf[molbufindex-1]);
13374
          //  molbufindex++;
13375
  }
13376
  else {
13377
    //messagebox(0,'Error in mm_Readinputline; memory problem','ERROR',0);
13378
    printf ("Not enough memory for molfile! %i\n", molbufindex);
13379
    exit (1);
13380
  }
6785 bpr 13381
//printf("mm_read_input_line_out\n");
13382
}
13383
 
14179 bpr 13384
static void mm_set_mol_dll (const char *st, boolean checkmol_mode,
6785 bpr 13385
                boolean normalize_ionic_bnds)
13386
{
14179 bpr 13387
  //printf("mm_set_mol\n");
13388
  //printf("%s\n",st);
6785 bpr 13389
  char bb;
13390
  char aa;
13391
  int i;
13392
  int k;
13393
  int J;
13394
  int spt = 0;
13395
  char tt[256];
13396
  char bb10 = '\n';
13397
  char bb13 = '\r';
13398
  char bb0 = '\0';
13399
  int lenst;
14179 bpr 13400
  //char d[256];
6785 bpr 13401
  lenst = strlen (st);
14179 bpr 13402
  //tt=(char*)safe_malloc(256*sizeof(char));
6785 bpr 13403
  tt[0] = '\0';
14179 bpr 13404
  //messagebox(0,st,'',0);
6785 bpr 13405
  mm_init_mol ();
14179 bpr 13406
  for (i = spt; i < lenst; i++) {
13407
    bb = st[i];
13408
    if ((bb == bb10) || (i == lenst)) {
13409
            J = 0;
13410
            // d:='';
13411
            for (k = spt; k < i; k++) {
6785 bpr 13412
              aa = st[k];
14179 bpr 13413
              if ((aa != bb10) && (aa != bb13)) {
13414
                      //d:=d+aa;
13415
                      tt[J] = aa;
13416
                      J++;
13417
                    }
6785 bpr 13418
            }
14179 bpr 13419
            tt[J] = bb0;
13420
            spt = i;
13421
            //messagebox (0,tt,tt,0);
13422
      //printf("A:%s\n",tt);
13423
            mm_read_input_line (tt);
13424
          }
13425
  }
6785 bpr 13426
//free(tt);
13427
  mm_elab_mol (checkmol_mode, normalize_ionic_bnds);
13428
//printf("mm_set_mol\n");
13429
}
13430
 
14179 bpr 13431
DLLEXPORT void cm_set_mol (const char *st, int normalize_ionic_bnds)
6785 bpr 13432
{
13433
  mm_set_mol_dll (st, true, (normalize_ionic_bnds != FEATURE_OFF));
13434
}
13435
 
14179 bpr 13436
DLLEXPORT void mm_set_mol (const char *st)
6785 bpr 13437
{
13438
  mm_set_mol_dll (st, false, true);
13439
}
13440
 
14179 bpr 13441
DLLEXPORT void xm_set_strict_typing (int strict_typing)
6785 bpr 13442
{
13443
  if (!yet_initialized)
13444
    init_globals_dll ();
13445
  opt_strict = (strict_typing != FEATURE_OFF);
13446
  //opt_strict=false; //This never worked right and is harmful
13447
}
13448
 
14179 bpr 13449
DLLEXPORT void mm_set_r_s_check (int r_s_check)
6785 bpr 13450
{
13451
  if (!yet_initialized)
13452
    init_globals_dll ();
13453
  opt_chiral = (r_s_check != FEATURE_OFF);
13454
}
13455
 
14179 bpr 13456
DLLEXPORT void mm_set_e_z_check (int e_z_check)
6785 bpr 13457
{
13458
  if (!yet_initialized)
13459
    init_globals_dll ();
13460
  opt_geom = (e_z_check != FEATURE_OFF);
13461
}
13462
 
14179 bpr 13463
DLLEXPORT void mm_set_chg_check (int chg_check)
6785 bpr 13464
{
13465
  if (!yet_initialized)
13466
    init_globals_dll ();
13467
  opt_chg = (chg_check != FEATURE_OFF);
13468
}
13469
 
14179 bpr 13470
DLLEXPORT void mm_set_iso_check (int iso_check)
6785 bpr 13471
{
13472
  if (!yet_initialized)
13473
    init_globals_dll ();
13474
  opt_iso = (iso_check != FEATURE_OFF);
13475
}
13476
 
14179 bpr 13477
DLLEXPORT void mm_set_rad_check (int rad_check)
6785 bpr 13478
{
13479
  if (!yet_initialized)
13480
    init_globals_dll ();
13481
  opt_rad = (rad_check != FEATURE_OFF);
13482
}
13483
 
14179 bpr 13484
DLLEXPORT void mm_set_exact_match (int exact)
6785 bpr 13485
{
13486
  if (!yet_initialized)
13487
    init_globals_dll ();
13488
  opt_exact = (exact != FEATURE_OFF);
13489
}
13490
 
14179 bpr 13491
DLLEXPORT int mm_match ()
6785 bpr 13492
{
13493
  mol_count = 1;
14179 bpr 13494
  //     mm_ElabMol;
13495
  /*printf("%i\n",opt_exact);
13496
  printf("%i\n",n_Ctot);
13497
  printf("%i\n",ndl_n_Ctot);
13498
  printf("%i\n",n_Otot);
13499
  printf("%i\n",ndl_n_Otot);
13500
  printf("%i\n",n_Ntot);
13501
  printf("%i\n",ndl_n_Ntot);*/
6785 bpr 13502
  if (opt_exact
13503
      && (n_Ctot != ndl_n_Ctot || n_Otot != ndl_n_Otot
14179 bpr 13504
            || n_Ntot != ndl_n_Ntot))
6785 bpr 13505
    return 0;
13506
  init_molstat (&ndl_molstat);
13507
  //perform_match ();
13508
  //---------------------------------------------------- 0.3o
13509
  if (rs_strict)                /* v0.3j */
13510
    ndl_ref_atom = find_ndl_ref_atom_cv ();
13511
  //ndl_ref_atom = find_ndl_ref_atom ();
13512
  else
13513
    ndl_ref_atom = find_ndl_ref_atom ();
13514
  clear_atom_tags ();
13515
  set_ndl_atom_tags ();
13516
  matchsummary = true;
13517
  perform_match ();
13518
  matchsummary = matchresult;
14179 bpr 13519
  if (count_tagged_ndl_heavyatoms () > 0 && matchsummary == true) {
13520
    do {
13521
            if (rs_strict)
13522
              ndl_ref_atom = find_ndl_ref_atom_cv ();
13523
            else
13524
              ndl_ref_atom = find_ndl_ref_atom ();
13525
            perform_match ();
13526
            if (matchresult == false)
13527
             matchsummary = false;
13528
          }
13529
    while (count_tagged_ndl_heavyatoms () != 0 && matchsummary != false);
13530
  }
6785 bpr 13531
 
13532
  //-----------------------------------------------------
13533
 
13534
  //mol_count = 0;
13535
 
13536
  //molbufindex = 0;
13537
 
13538
  //return matchresult ? 1 : 0;
13539
 
13540
  return matchsummary ? 1 : 0;
13541
}
13542
 
13543
//-------------------------
13544
 
14179 bpr 13545
DLLEXPORT void xm_set_ring_perception_algorithm (int algo)
6785 bpr 13546
{
14179 bpr 13547
  switch (algo) {
6785 bpr 13548
    case RPA_SAR:
13549
      opt_rs_dll = rs_sar;
13550
      break;
13551
    case RPA_SSR:
13552
      opt_rs_dll = rs_ssr;
13553
      break;
13554
    default:
13555
      opt_rs_dll = RPA_DEFAULT;
13556
      break;
13557
    }
13558
  //printf("RPA_SET: %i\n",opt_rs_dll);
13559
}
13560
 
14179 bpr 13561
static void write_molstat_X_dll (char *out_buffer)
6785 bpr 13562
{
13563
  char tmp_buf[256];
13564
  out_buffer[0] = '\0';
13565
  if (auto_ssr)                 /* v0.3n */
13566
    fix_ssr_ringcounts ();
13567
  sprintf (tmp_buf, "%d,", n_heavyatoms);
13568
  strcat (out_buffer, tmp_buf);
13569
  sprintf (tmp_buf, "%d,", n_heavybonds);
13570
  strcat (out_buffer, tmp_buf);
13571
#ifdef REDUCED_SAR
13572
  sprintf (tmp_buf, "%d,", n_countablerings);
13573
  strcat (out_buffer, tmp_buf);
13574
#else
13575
  sprintf (tmp_buf, "%d,", n_rings);
13576
  strcat (out_buffer, tmp_buf);
13577
#endif
13578
  sprintf (tmp_buf, "%d,", molstat.n_QA);
13579
  strcat (out_buffer, tmp_buf);
13580
  sprintf (tmp_buf, "%d,", molstat.n_QB);
13581
  strcat (out_buffer, tmp_buf);
13582
  //if (opt_chg)
13583
//    {                         /* 0.3x */
13584
//      sprintf (tmp_buf, "%d,", molstat.n_chg);
13585
//    }
13586
//  else
13587
//    {
13588
  sprintf (tmp_buf, "%d,", molstat.n_chg);
13589
  //   }
13590
  strcat (out_buffer, tmp_buf);
13591
  sprintf (tmp_buf, "%d,", molstat.n_C1);
13592
  strcat (out_buffer, tmp_buf);
13593
  sprintf (tmp_buf, "%d,", molstat.n_C2);
13594
  strcat (out_buffer, tmp_buf);
13595
  sprintf (tmp_buf, "%d,", molstat.n_C);
13596
  strcat (out_buffer, tmp_buf);
13597
  sprintf (tmp_buf, "%d,", molstat.n_CHB1p);
13598
  strcat (out_buffer, tmp_buf);
13599
  sprintf (tmp_buf, "%d,", molstat.n_CHB2p);
13600
  strcat (out_buffer, tmp_buf);
13601
  sprintf (tmp_buf, "%d,", molstat.n_CHB3p);
13602
  strcat (out_buffer, tmp_buf);
13603
  sprintf (tmp_buf, "%d,", molstat.n_CHB4);
13604
  strcat (out_buffer, tmp_buf);
13605
  sprintf (tmp_buf, "%d,", molstat.n_O2);
13606
  strcat (out_buffer, tmp_buf);
13607
  sprintf (tmp_buf, "%d,", molstat.n_O3);
13608
  strcat (out_buffer, tmp_buf);
13609
  sprintf (tmp_buf, "%d,", molstat.n_N1);
13610
  strcat (out_buffer, tmp_buf);
13611
  sprintf (tmp_buf, "%d,", molstat.n_N2);
13612
  strcat (out_buffer, tmp_buf);
13613
  sprintf (tmp_buf, "%d,", molstat.n_N3);
13614
  strcat (out_buffer, tmp_buf);
13615
  sprintf (tmp_buf, "%d,", molstat.n_S);
13616
  strcat (out_buffer, tmp_buf);
13617
  sprintf (tmp_buf, "%d,", molstat.n_SeTe);
13618
  strcat (out_buffer, tmp_buf);
13619
  sprintf (tmp_buf, "%d,", molstat.n_F);
13620
  strcat (out_buffer, tmp_buf);
13621
  sprintf (tmp_buf, "%d,", molstat.n_Cl);
13622
  strcat (out_buffer, tmp_buf);
13623
  sprintf (tmp_buf, "%d,", molstat.n_Br);
13624
  strcat (out_buffer, tmp_buf);
13625
  sprintf (tmp_buf, "%d,", molstat.n_I);
13626
  strcat (out_buffer, tmp_buf);
13627
  sprintf (tmp_buf, "%d,", molstat.n_P);
13628
  strcat (out_buffer, tmp_buf);
13629
  sprintf (tmp_buf, "%d,", molstat.n_B);
13630
  strcat (out_buffer, tmp_buf);
13631
  sprintf (tmp_buf, "%d,", molstat.n_Met);
13632
  strcat (out_buffer, tmp_buf);
13633
  sprintf (tmp_buf, "%d,", molstat.n_X);
13634
  strcat (out_buffer, tmp_buf);
13635
  sprintf (tmp_buf, "%d,", molstat.n_b1);
13636
  strcat (out_buffer, tmp_buf);
13637
  sprintf (tmp_buf, "%d,", molstat.n_b2);
13638
  strcat (out_buffer, tmp_buf);
13639
  sprintf (tmp_buf, "%d,", molstat.n_b3);
13640
  strcat (out_buffer, tmp_buf);
13641
  sprintf (tmp_buf, "%d,", molstat.n_bar);
13642
  strcat (out_buffer, tmp_buf);
13643
  sprintf (tmp_buf, "%d,", molstat.n_C1O);
13644
  strcat (out_buffer, tmp_buf);
13645
  sprintf (tmp_buf, "%d,", molstat.n_C2O);
13646
  strcat (out_buffer, tmp_buf);
13647
  sprintf (tmp_buf, "%d,", molstat.n_CN);
13648
  strcat (out_buffer, tmp_buf);
13649
  sprintf (tmp_buf, "%d,", molstat.n_XY);
13650
  strcat (out_buffer, tmp_buf);
13651
  sprintf (tmp_buf, "%d,", molstat.n_r3);
13652
  strcat (out_buffer, tmp_buf);
13653
  sprintf (tmp_buf, "%d,", molstat.n_r4);
13654
  strcat (out_buffer, tmp_buf);
13655
  sprintf (tmp_buf, "%d,", molstat.n_r5);
13656
  strcat (out_buffer, tmp_buf);
13657
  sprintf (tmp_buf, "%d,", molstat.n_r6);
13658
  strcat (out_buffer, tmp_buf);
13659
  sprintf (tmp_buf, "%d,", molstat.n_r7);
13660
  strcat (out_buffer, tmp_buf);
13661
  sprintf (tmp_buf, "%d,", molstat.n_r8);
13662
  strcat (out_buffer, tmp_buf);
13663
  sprintf (tmp_buf, "%d,", molstat.n_r9);
13664
  strcat (out_buffer, tmp_buf);
13665
  sprintf (tmp_buf, "%d,", molstat.n_r10);
13666
  strcat (out_buffer, tmp_buf);
13667
  sprintf (tmp_buf, "%d,", molstat.n_r11);
13668
  strcat (out_buffer, tmp_buf);
13669
  sprintf (tmp_buf, "%d,", molstat.n_r12);
13670
  strcat (out_buffer, tmp_buf);
13671
  sprintf (tmp_buf, "%d,", molstat.n_r13p);
13672
  strcat (out_buffer, tmp_buf);
13673
  sprintf (tmp_buf, "%d,", molstat.n_rN);
13674
  strcat (out_buffer, tmp_buf);
13675
  sprintf (tmp_buf, "%d,", molstat.n_rN1);
13676
  strcat (out_buffer, tmp_buf);
13677
  sprintf (tmp_buf, "%d,", molstat.n_rN2);
13678
  strcat (out_buffer, tmp_buf);
13679
  sprintf (tmp_buf, "%d,", molstat.n_rN3p);
13680
  strcat (out_buffer, tmp_buf);
13681
  sprintf (tmp_buf, "%d,", molstat.n_rO);
13682
  strcat (out_buffer, tmp_buf);
13683
  sprintf (tmp_buf, "%d,", molstat.n_rO1);
13684
  strcat (out_buffer, tmp_buf);
13685
  sprintf (tmp_buf, "%d,", molstat.n_rO2p);
13686
  strcat (out_buffer, tmp_buf);
13687
  sprintf (tmp_buf, "%d,", molstat.n_rS);
13688
  strcat (out_buffer, tmp_buf);
13689
  sprintf (tmp_buf, "%d,", molstat.n_rX);
13690
  strcat (out_buffer, tmp_buf);
13691
  sprintf (tmp_buf, "%d,", molstat.n_rAr);
13692
  strcat (out_buffer, tmp_buf);
13693
  sprintf (tmp_buf, "%d,", molstat.n_rBz);
13694
  strcat (out_buffer, tmp_buf);
13695
  sprintf (tmp_buf, "%d,", molstat.n_br2p);
13696
  strcat (out_buffer, tmp_buf);
13697
  sprintf (tmp_buf, "%d,", molstat.n_psg01);
13698
  strcat (out_buffer, tmp_buf);
13699
  sprintf (tmp_buf, "%d,", molstat.n_psg02);
13700
  strcat (out_buffer, tmp_buf);
13701
  sprintf (tmp_buf, "%d,", molstat.n_psg13);
13702
  strcat (out_buffer, tmp_buf);
13703
  sprintf (tmp_buf, "%d,", molstat.n_psg14);
13704
  strcat (out_buffer, tmp_buf);
13705
  sprintf (tmp_buf, "%d,", molstat.n_psg15);
13706
  strcat (out_buffer, tmp_buf);
13707
  sprintf (tmp_buf, "%d,", molstat.n_psg16);
13708
  strcat (out_buffer, tmp_buf);
13709
  sprintf (tmp_buf, "%d,", molstat.n_psg17);
13710
  strcat (out_buffer, tmp_buf);
13711
  sprintf (tmp_buf, "%d,", molstat.n_psg18);
13712
  strcat (out_buffer, tmp_buf);
13713
  sprintf (tmp_buf, "%d,", molstat.n_pstm);
13714
  strcat (out_buffer, tmp_buf);
13715
  sprintf (tmp_buf, "%d,", molstat.n_psla);
13716
  strcat (out_buffer, tmp_buf);
13717
  sprintf (tmp_buf, "%d,", molstat.n_iso);
13718
  strcat (out_buffer, tmp_buf);
13719
  sprintf (tmp_buf, "%d", molstat.n_rad);
13720
  strcat (out_buffer, tmp_buf);
13721
}
13722
 
14179 bpr 13723
static void write_molstat_dll (char *out_buffer, int mode) {
6785 bpr 13724
  char tmp_buf[256];
13725
  char *sep1;
13726
  char *sep2;
14179 bpr 13727
  switch (mode) {
6785 bpr 13728
    case 1:
13729
      sep1 = "=";
13730
      sep2 = " AND ";
13731
      break;
13732
    case 2:
13733
      sep1 = "<=";
13734
      sep2 = " AND ";
13735
      break;
13736
    default:
13737
      sep1 = ":";
13738
      sep2 = ";";
13739
      break;
13740
    }
13741
 
13742
  out_buffer[0] = '\0';
13743
 
13744
  if (auto_ssr)                 /* v0.3n */
13745
    fix_ssr_ringcounts ();
13746
  sprintf (tmp_buf, "n_atoms%s%d%s", sep1, n_heavyatoms, sep2);
13747
  strcat (out_buffer, tmp_buf);
14179 bpr 13748
  if (n_bonds > 0) {
6785 bpr 13749
      sprintf (tmp_buf, "n_bonds%s%d%s", sep1, n_heavybonds, sep2);
13750
      strcat (out_buffer, tmp_buf);
13751
    }
13752
 
13753
#ifdef REDUCED_SAR
14179 bpr 13754
  if (n_rings > 0) {
6785 bpr 13755
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_countablerings, sep2);
13756
      strcat (out_buffer, tmp_buf);
13757
    }
13758
#else
14179 bpr 13759
  if (n_rings > 0) {
6785 bpr 13760
      sprintf (tmp_buf, "n_rings%s%d%s", sep1, n_rings, sep2);
13761
      strcat (out_buffer, tmp_buf);
13762
    }
13763
#endif
13764
 
14179 bpr 13765
  if (opt_chg && molstat.n_chg > 0)     /* 0.3x */ {
13766
    sprintf (tmp_buf, "n_chg%s%d%s", sep1, molstat.n_chg, sep2);
13767
    strcat (out_buffer, tmp_buf);
13768
  }
13769
  if (molstat.n_C1 > 0) {
13770
    sprintf (tmp_buf, "n_C1%s%d%s", sep1, molstat.n_C1, sep2);
13771
    strcat (out_buffer, tmp_buf);
13772
  }
13773
  if (molstat.n_C2 > 0) {
13774
    sprintf (tmp_buf, "n_C2%s%d%s", sep1, molstat.n_C2, sep2);
13775
    strcat (out_buffer, tmp_buf);
13776
  }
6785 bpr 13777
 
14179 bpr 13778
  if (molstat.n_C > 0) {
13779
    sprintf (tmp_buf, "n_C%s%d%s", sep1, molstat.n_C, sep2);
13780
    strcat (out_buffer, tmp_buf);
13781
  }
13782
  if (molstat.n_CHB1p > 0) {
13783
    sprintf (tmp_buf, "n_CHB1p%s%d%s", sep1, molstat.n_CHB1p, sep2);
13784
    strcat (out_buffer, tmp_buf);
13785
  }
13786
  if (molstat.n_CHB2p > 0) {
13787
    sprintf (tmp_buf, "n_CHB2p%s%d%s", sep1, molstat.n_CHB2p, sep2);
13788
    strcat (out_buffer, tmp_buf);
13789
  }
13790
  if (molstat.n_CHB3p > 0) {
13791
    sprintf (tmp_buf, "n_CHB3p%s%d%s", sep1, molstat.n_CHB3p, sep2);
13792
    strcat (out_buffer, tmp_buf);
13793
  }
13794
  if (molstat.n_CHB4 > 0) {
13795
    sprintf (tmp_buf, "n_CHB4%s%d%s", sep1, molstat.n_CHB4, sep2);
13796
    strcat (out_buffer, tmp_buf);
13797
  }
13798
  if (molstat.n_O2 > 0) {
13799
    sprintf (tmp_buf, "n_O2%s%d%s", sep1, molstat.n_O2, sep2);
13800
    strcat (out_buffer, tmp_buf);
13801
  }
13802
  if (molstat.n_O3 > 0) {
13803
    sprintf (tmp_buf, "n_O3%s%d%s", sep1, molstat.n_O3, sep2);
13804
    strcat (out_buffer, tmp_buf);
13805
  }
13806
  if (molstat.n_N1 > 0) {
13807
    sprintf (tmp_buf, "n_N1%s%d%s", sep1, molstat.n_N1, sep2);
13808
    strcat (out_buffer, tmp_buf);
13809
  }
13810
  if (molstat.n_N2 > 0) {
13811
    sprintf (tmp_buf, "n_N2%s%d%s", sep1, molstat.n_N2, sep2);
13812
    strcat (out_buffer, tmp_buf);
13813
  }
13814
  if (molstat.n_N3 > 0) {
13815
    sprintf (tmp_buf, "n_N3%s%d%s", sep1, molstat.n_N3, sep2);
13816
    strcat (out_buffer, tmp_buf);
13817
  }
13818
  if (molstat.n_S > 0) {
13819
    sprintf (tmp_buf, "n_S%s%d%s", sep1, molstat.n_S, sep2);
13820
    strcat (out_buffer, tmp_buf);
13821
  }
13822
  if (molstat.n_SeTe > 0) {
13823
    sprintf (tmp_buf, "n_SeTe%s%d%s", sep1, molstat.n_SeTe, sep2);
13824
    strcat (out_buffer, tmp_buf);
13825
  }
13826
  if (molstat.n_F > 0) {
13827
    sprintf (tmp_buf, "n_F%s%d%s", sep1, molstat.n_F, sep2);
13828
    strcat (out_buffer, tmp_buf);
13829
  }
13830
  if (molstat.n_Cl > 0) {
13831
    sprintf (tmp_buf, "n_Cl%s%d%s", sep1, molstat.n_Cl, sep2);
13832
    strcat (out_buffer, tmp_buf);
13833
  }
13834
  if (molstat.n_Br > 0) {
13835
    sprintf (tmp_buf, "n_Br%s%d%s", sep1, molstat.n_Br, sep2);
13836
    strcat (out_buffer, tmp_buf);
13837
  }
13838
  if (molstat.n_I > 0) {
13839
    sprintf (tmp_buf, "n_I%s%d%s", sep1, molstat.n_I, sep2);
13840
    strcat (out_buffer, tmp_buf);
13841
  }
13842
  if (molstat.n_P > 0) {
13843
    sprintf (tmp_buf, "n_P%s%d%s", sep1, molstat.n_P, sep2);
13844
    strcat (out_buffer, tmp_buf);
13845
  }
13846
  if (molstat.n_B > 0) {
13847
    sprintf (tmp_buf, "n_B%s%d%s", sep1, molstat.n_B, sep2);
13848
    strcat (out_buffer, tmp_buf);
13849
  }
13850
  if (molstat.n_Met > 0) {
13851
    sprintf (tmp_buf, "n_Met%s%d%s", sep1, molstat.n_Met, sep2);
13852
    strcat (out_buffer, tmp_buf);
13853
  }
13854
  if (molstat.n_X > 0) {
13855
    sprintf (tmp_buf, "n_X%s%d%s", sep1, molstat.n_X, sep2);
13856
    strcat (out_buffer, tmp_buf);
13857
  }
13858
  if (molstat.n_b1 > 0) {
13859
    sprintf (tmp_buf, "n_b1%s%d%s", sep1, molstat.n_b1, sep2);
13860
    strcat (out_buffer, tmp_buf);
13861
  }
13862
  if (molstat.n_b2 > 0) {
13863
    sprintf (tmp_buf, "n_b2%s%d%s", sep1, molstat.n_b2, sep2);
13864
    strcat (out_buffer, tmp_buf);
13865
  }
13866
  if (molstat.n_b3 > 0) {
13867
    sprintf (tmp_buf, "n_b3%s%d%s", sep1, molstat.n_b3, sep2);
13868
    strcat (out_buffer, tmp_buf);
13869
  }
13870
  if (molstat.n_bar > 0) {
13871
   sprintf (tmp_buf, "n_bar%s%d%s", sep1, molstat.n_bar, sep2);
13872
   strcat (out_buffer, tmp_buf);
13873
  }
13874
  if (molstat.n_C1O > 0) {
13875
    sprintf (tmp_buf, "n_C1O%s%d%s", sep1, molstat.n_C1O, sep2);
13876
    strcat (out_buffer, tmp_buf);
13877
  }
13878
  if (molstat.n_C2O > 0) {
6785 bpr 13879
      sprintf (tmp_buf, "n_C2O%s%d%s", sep1, molstat.n_C2O, sep2);
13880
      strcat (out_buffer, tmp_buf);
13881
    }
14179 bpr 13882
  if (molstat.n_CN > 0) {
6785 bpr 13883
      sprintf (tmp_buf, "n_CN%s%d%s", sep1, molstat.n_CN, sep2);
13884
      strcat (out_buffer, tmp_buf);
13885
    }
14179 bpr 13886
  if (molstat.n_XY > 0) {
13887
    sprintf (tmp_buf, "n_XY%s%d%s", sep1, molstat.n_XY, sep2);
13888
    strcat (out_buffer, tmp_buf);
13889
  }
13890
  if (molstat.n_r3 > 0) {
13891
    sprintf (tmp_buf, "n_r3%s%d%s", sep1, molstat.n_r3, sep2);
13892
    strcat (out_buffer, tmp_buf);
13893
  }
13894
  if (molstat.n_r4 > 0) {
13895
    sprintf (tmp_buf, "n_r4%s%d%s", sep1, molstat.n_r4, sep2);
13896
    strcat (out_buffer, tmp_buf);
13897
  }
13898
  if (molstat.n_r5 > 0) {
13899
    sprintf (tmp_buf, "n_r5%s%d%s", sep1, molstat.n_r5, sep2);
13900
    strcat (out_buffer, tmp_buf);
13901
  }
13902
  if (molstat.n_r6 > 0) {
13903
    sprintf (tmp_buf, "n_r6%s%d%s", sep1, molstat.n_r6, sep2);
13904
    strcat (out_buffer, tmp_buf);
13905
  }
13906
  if (molstat.n_r7 > 0) {
13907
    sprintf (tmp_buf, "n_r7%s%d%s", sep1, molstat.n_r7, sep2);
13908
    strcat (out_buffer, tmp_buf);
13909
  }
13910
  if (molstat.n_r8 > 0) {
13911
    sprintf (tmp_buf, "n_r8%s%d%s", sep1, molstat.n_r8, sep2);
13912
    strcat (out_buffer, tmp_buf);
13913
  }
13914
  if (molstat.n_r9 > 0) {
13915
    sprintf (tmp_buf, "n_r9%s%d%s", sep1, molstat.n_r9, sep2);
13916
    strcat (out_buffer, tmp_buf);
13917
  }
13918
  if (molstat.n_r10 > 0) {
13919
    sprintf (tmp_buf, "n_r10%s%d%s", sep1, molstat.n_r10, sep2);
13920
    strcat (out_buffer, tmp_buf);
13921
  }
13922
  if (molstat.n_r11 > 0) {
13923
    sprintf (tmp_buf, "n_r11%s%d%s", sep1, molstat.n_r11, sep2);
13924
    strcat (out_buffer, tmp_buf);
13925
  }
13926
  if (molstat.n_r12 > 0) {
13927
    sprintf (tmp_buf, "n_r12%s%d%s", sep1, molstat.n_r12, sep2);
13928
    strcat (out_buffer, tmp_buf);
13929
  }
13930
  if (molstat.n_r13p > 0) {
6785 bpr 13931
      sprintf (tmp_buf, "n_r13p%s%d%s", sep1, molstat.n_r13p, sep2);
13932
      strcat (out_buffer, tmp_buf);
13933
    }
14179 bpr 13934
  if (molstat.n_rN > 0) {
13935
    sprintf (tmp_buf, "n_rN%s%d%s", sep1, molstat.n_rN, sep2);
13936
    strcat (out_buffer, tmp_buf);
13937
  }
13938
  if (molstat.n_rN1 > 0) {
13939
    sprintf (tmp_buf, "n_rN1%s%d%s", sep1, molstat.n_rN1, sep2);
13940
    strcat (out_buffer, tmp_buf);
13941
  }
13942
  if (molstat.n_rN2 > 0) {
13943
    sprintf (tmp_buf, "n_rN2%s%d%s", sep1, molstat.n_rN2, sep2);
13944
    strcat (out_buffer, tmp_buf);
13945
  }
13946
  if (molstat.n_rN3p > 0) {
13947
    sprintf (tmp_buf, "n_rN3p%s%d%s", sep1, molstat.n_rN3p, sep2);
13948
    strcat (out_buffer, tmp_buf);
13949
  }
13950
  if (molstat.n_rO > 0) {
13951
    sprintf (tmp_buf, "n_rO%s%d%s", sep1, molstat.n_rO, sep2);
13952
    strcat (out_buffer, tmp_buf);
13953
  }
13954
  if (molstat.n_rO1 > 0) {
13955
    sprintf (tmp_buf, "n_rO1%s%d%s", sep1, molstat.n_rO1, sep2);
13956
    strcat (out_buffer, tmp_buf);
13957
  }
13958
  if (molstat.n_rO2p > 0) {
13959
    sprintf (tmp_buf, "n_rO2p%s%d%s", sep1, molstat.n_rO2p, sep2);
13960
    strcat (out_buffer, tmp_buf);
13961
  }
13962
  if (molstat.n_rS > 0) {
13963
    sprintf (tmp_buf, "n_rS%s%d%s", sep1, molstat.n_rS, sep2);
13964
    strcat (out_buffer, tmp_buf);
13965
  }
13966
  if (molstat.n_rX > 0) {
13967
    sprintf (tmp_buf, "n_rX%s%d%s", sep1, molstat.n_rX, sep2);
13968
    strcat (out_buffer, tmp_buf);
13969
  }
13970
  if (molstat.n_rAr > 0) {
13971
    sprintf (tmp_buf, "n_rar%s%d%s", sep1, molstat.n_rAr, sep2);
13972
    strcat (out_buffer, tmp_buf);
13973
  }
6785 bpr 13974
 
14179 bpr 13975
  if (molstat.n_rBz > 0) {
13976
    sprintf (tmp_buf, "n_rbz%s%d%s", sep1, molstat.n_rBz, sep2);
13977
    strcat (out_buffer, tmp_buf);
13978
  }
6785 bpr 13979
 
14179 bpr 13980
  if (molstat.n_br2p > 0) {
13981
    sprintf (tmp_buf, "n_br2p%s%d%s", sep1, molstat.n_br2p, sep2);
13982
    strcat (out_buffer, tmp_buf);
13983
  }
6785 bpr 13984
 
14179 bpr 13985
  if (molstat.n_psg01 > 0) {
13986
    sprintf (tmp_buf, "n_psg01%s%d%s", sep1, molstat.n_psg01, sep2);
13987
    strcat (out_buffer, tmp_buf);
13988
  }
6785 bpr 13989
 
14179 bpr 13990
  if (molstat.n_psg02 > 0) {
13991
    sprintf (tmp_buf, "n_psg02%s%d%s", sep1, molstat.n_psg02, sep2);
13992
    strcat (out_buffer, tmp_buf);
13993
  }
6785 bpr 13994
 
14179 bpr 13995
  if (molstat.n_psg13 > 0) {
13996
    sprintf (tmp_buf, "n_psg13%s%d%s", sep1, molstat.n_psg13, sep2);
13997
    strcat (out_buffer, tmp_buf);
13998
  }
6785 bpr 13999
 
14179 bpr 14000
  if (molstat.n_psg14 > 0) {
14001
    sprintf (tmp_buf, "n_psg14%s%d%s", sep1, molstat.n_psg14, sep2);
14002
    strcat (out_buffer, tmp_buf);
14003
  }
6785 bpr 14004
 
14179 bpr 14005
  if (molstat.n_psg15 > 0) {
14006
    sprintf (tmp_buf, "n_psg15%s%d%s", sep1, molstat.n_psg15, sep2);
14007
    strcat (out_buffer, tmp_buf);
14008
  }
6785 bpr 14009
 
14179 bpr 14010
  if (molstat.n_psg16 > 0) {
14011
    sprintf (tmp_buf, "n_psg16%s%d%s", sep1, molstat.n_psg16, sep2);
14012
    strcat (out_buffer, tmp_buf);
14013
  }
6785 bpr 14014
 
14179 bpr 14015
  if (molstat.n_psg17 > 0) {
14016
    sprintf (tmp_buf, "n_psg17%s%d%s", sep1, molstat.n_psg17, sep2);
14017
    strcat (out_buffer, tmp_buf);
14018
  }
6785 bpr 14019
 
14179 bpr 14020
  if (molstat.n_psg18 > 0) {
14021
    sprintf (tmp_buf, "n_psg18%s%d%s", sep1, molstat.n_psg18, sep2);
14022
    strcat (out_buffer, tmp_buf);
14023
  }
6785 bpr 14024
 
14179 bpr 14025
  if (molstat.n_pstm > 0) {
6785 bpr 14026
      sprintf (tmp_buf, "n_pstm%s%d%s", sep1, molstat.n_pstm, sep2);
14027
      strcat (out_buffer, tmp_buf);
14028
    }
14029
 
14179 bpr 14030
  if (molstat.n_psla > 0) {
6785 bpr 14031
      sprintf (tmp_buf, "n_psla%s%d%s", sep1, molstat.n_psla, sep2);
14032
      strcat (out_buffer, tmp_buf);
14033
    }
14034
 
14179 bpr 14035
  if (opt_iso && molstat.n_iso > 0) {
14036
    sprintf (tmp_buf, "n_iso%s%d%s", sep1, molstat.n_iso, sep2);
14037
    strcat (out_buffer, tmp_buf);
14038
  }
6785 bpr 14039
 
14179 bpr 14040
  if (opt_rad && molstat.n_rad > 0) {
14041
    sprintf (tmp_buf, "n_rad%s%d%s", sep1, molstat.n_rad, sep2);
14042
    strcat (out_buffer, tmp_buf);
14043
  }
6785 bpr 14044
}
14045
 
14046
static void
14047
write_fg_code_dll (char *out_buffer)
14048
{
14049
  char tmp_buf[256];
14050
  out_buffer[0] = '\0';
14179 bpr 14051
  if (fg[fg_cation - 1]) {
14052
    sprintf (tmp_buf, "000000T2;");
14053
    strcat (out_buffer, tmp_buf);
14054
  }
14055
  if (fg[fg_anion - 1]) {
14056
    sprintf (tmp_buf, "000000T1;");
14057
    strcat (out_buffer, tmp_buf);
14058
  }
6785 bpr 14059
 
14179 bpr 14060
  if (fg[fg_aldehyde - 1]) {
14061
    sprintf (tmp_buf, "C2O1H000;");
14062
    strcat (out_buffer, tmp_buf);
14063
  }
14064
  if (fg[fg_ketone - 1]) {
14065
    sprintf (tmp_buf, "C2O1C000;");
14066
    strcat (out_buffer, tmp_buf);
14067
  }
6785 bpr 14068
 
14179 bpr 14069
  if (fg[fg_thioaldehyde - 1]) {
14070
    sprintf (tmp_buf, "C2S1H000;");
14071
    strcat (out_buffer, tmp_buf);
14072
  }
14073
  if (fg[fg_thioketone - 1]) {
14074
    sprintf (tmp_buf, "C2S1C000;");
14075
    strcat (out_buffer, tmp_buf);
14076
  }
14077
  if (fg[fg_imine - 1]) {
14078
    sprintf (tmp_buf, "C2N10000;");
14079
    strcat (out_buffer, tmp_buf);
14080
  }
14081
  if (fg[fg_hydrazone - 1]) {
14082
    sprintf (tmp_buf, "C2N1N000;");
14083
    strcat (out_buffer, tmp_buf);
14084
  }
14085
  if (fg[fg_semicarbazone - 1]) {
14086
    sprintf (tmp_buf, "C2NNC4ON;");
14087
    strcat (out_buffer, tmp_buf);
14088
  }
14089
  if (fg[fg_thiosemicarbazone - 1]) {
14090
    sprintf (tmp_buf, "C2NNC4SN;");
14091
    strcat (out_buffer, tmp_buf);
14092
  }
14093
  if (fg[fg_oxime - 1]) {
14094
    sprintf (tmp_buf, "C2N1OH00;");
14095
    strcat (out_buffer, tmp_buf);
14096
  }
14097
  if (fg[fg_oxime_ether - 1]) {
14098
    sprintf (tmp_buf, "C2N1OC00;");
14099
    strcat (out_buffer, tmp_buf);
14100
  }
14101
  if (fg[fg_ketene - 1]) {
14102
    sprintf (tmp_buf, "C3OC0000;");
14103
    strcat (out_buffer, tmp_buf);
14104
  }
14105
  if (fg[fg_ketene_acetal_deriv - 1]) {
14106
    sprintf (tmp_buf, "C3OCC000;");
14107
    strcat (out_buffer, tmp_buf);
14108
  }
14109
  if (fg[fg_carbonyl_hydrate - 1]) {
14110
    sprintf (tmp_buf, "C2O2H200;");
14111
    strcat (out_buffer, tmp_buf);
14112
  }
14113
  if (fg[fg_hemiacetal - 1]) {
14114
    sprintf (tmp_buf, "C2O2HC00;");
14115
    strcat (out_buffer, tmp_buf);
14116
  }
14117
  if (fg[fg_acetal - 1]) {
14118
   sprintf (tmp_buf, "C2O2CC00;");
14119
   strcat (out_buffer, tmp_buf);
14120
  }
14121
  if (fg[fg_hemiaminal - 1]) {
14122
    sprintf (tmp_buf, "C2NOHC10;");
14123
    strcat (out_buffer, tmp_buf);
14124
  }
14125
  if (fg[fg_aminal - 1]) {
14126
    sprintf (tmp_buf, "C2N2CC10;");
14127
    strcat (out_buffer, tmp_buf);
14128
  }
14129
  if (fg[fg_thiohemiaminal - 1]) {
14130
    sprintf (tmp_buf, "C2NSHC10;");
14131
    strcat (out_buffer, tmp_buf);
14132
  }
14133
  if (fg[fg_thioacetal - 1]) {
14134
    sprintf (tmp_buf, "C2S2CC00;");
14135
    strcat (out_buffer, tmp_buf);
14136
  }
14137
  if (fg[fg_enamine - 1]) {
14138
    sprintf (tmp_buf, "C2CNH000;");
14139
    strcat (out_buffer, tmp_buf);
14140
  }
14141
  if (fg[fg_enol - 1]) {
14142
    sprintf (tmp_buf, "C2COH000;");
14143
    strcat (out_buffer, tmp_buf);
14144
  }
14145
  if (fg[fg_enolether - 1]) {
14146
    sprintf (tmp_buf, "C2COC000;");
14147
    strcat (out_buffer, tmp_buf);
14148
  }
6785 bpr 14149
 
14179 bpr 14150
  if (fg[fg_prim_alcohol - 1]) {
14151
    sprintf (tmp_buf, "O1H1C000;");
14152
    strcat (out_buffer, tmp_buf);
14153
  }
14154
  if (fg[fg_sec_alcohol - 1]) {
14155
    sprintf (tmp_buf, "O1H2C000;");
14156
    strcat (out_buffer, tmp_buf);
14157
  }
14158
  if (fg[fg_tert_alcohol - 1]) {
14159
    sprintf (tmp_buf, "O1H3C000;");
14160
    strcat (out_buffer, tmp_buf);
14161
  }
14162
  if (fg[fg_1_2_diol - 1]) {
14163
    sprintf (tmp_buf, "O1H0CO1H;");
14164
    strcat (out_buffer, tmp_buf);
14165
  }
14166
  if (fg[fg_1_2_aminoalcohol - 1]) {
14167
    sprintf (tmp_buf, "O1H0CN1C;");
14168
    strcat (out_buffer, tmp_buf);
14169
  }
14170
  if (fg[fg_phenol - 1]) {
14171
    sprintf (tmp_buf, "O1H1A000;");
14172
    strcat (out_buffer, tmp_buf);
14173
  }
14174
  if (fg[fg_1_2_diphenol - 1]) {
14175
    sprintf (tmp_buf, "O1H2A000;");
14176
    strcat (out_buffer, tmp_buf);
14177
  }
14178
  if (fg[fg_enediol - 1]) {
14179
    sprintf (tmp_buf, "C2COH200;");
14180
    strcat (out_buffer, tmp_buf);
14181
  }
6785 bpr 14182
 
14179 bpr 14183
  if (fg[fg_dialkylether - 1]) {
14184
    sprintf (tmp_buf, "O1C0CC00;");
14185
    strcat (out_buffer, tmp_buf);
14186
  }
14187
  if (fg[fg_alkylarylether - 1]) {
14188
    sprintf (tmp_buf, "O1C0CA00;");
14189
    strcat (out_buffer, tmp_buf);
14190
  }
14191
  if (fg[fg_diarylether - 1]) {
14192
    sprintf (tmp_buf, "O1C0AA00;");
14193
    strcat (out_buffer, tmp_buf);
14194
  }
14195
  if (fg[fg_thioether - 1]) {
14196
    sprintf (tmp_buf, "S1C00000;");
14197
    strcat (out_buffer, tmp_buf);
14198
  }
14199
  if (fg[fg_disulfide - 1]) {
14200
    sprintf (tmp_buf, "S1S1C000;");
14201
    strcat (out_buffer, tmp_buf);
14202
  }
14203
  if (fg[fg_peroxide - 1]) {
14204
    sprintf (tmp_buf, "O1O1C000;");
14205
    strcat (out_buffer, tmp_buf);
14206
  }
14207
  if (fg[fg_hydroperoxide - 1]) {
14208
    sprintf (tmp_buf, "O1O1H000;");
14209
    strcat (out_buffer, tmp_buf);
14210
  }
14211
  if (fg[fg_hydrazine - 1]) {
14212
    sprintf (tmp_buf, "N1N10000;");
14213
    strcat (out_buffer, tmp_buf);
14214
  }
14215
  if (fg[fg_hydroxylamine - 1]) {
14216
    sprintf (tmp_buf, "N1O1H000;");
14217
    strcat (out_buffer, tmp_buf);
14218
  }
6785 bpr 14219
 
14179 bpr 14220
  if (fg[fg_prim_aliph_amine - 1]) {
14221
    sprintf (tmp_buf, "N1C1C000;");
14222
    strcat (out_buffer, tmp_buf);
14223
  }
14224
  if (fg[fg_prim_arom_amine - 1]) {
14225
    sprintf (tmp_buf, "N1C1A000;");
14226
    strcat (out_buffer, tmp_buf);
14227
  }
6785 bpr 14228
 
14179 bpr 14229
  if (fg[fg_sec_aliph_amine - 1]) {
14230
    sprintf (tmp_buf, "N1C2CC00;");
14231
    strcat (out_buffer, tmp_buf);
14232
  }
14233
  if (fg[fg_sec_mixed_amine - 1]) {
14234
    sprintf (tmp_buf, "N1C2AC00;");
14235
    strcat (out_buffer, tmp_buf);
14236
  }
14237
  if (fg[fg_sec_arom_amine - 1]) {
14238
    sprintf (tmp_buf, "N1C2AA00;");
14239
    strcat (out_buffer, tmp_buf);
14240
  }
6785 bpr 14241
 
14179 bpr 14242
  if (fg[fg_tert_aliph_amine - 1]) {
14243
    sprintf (tmp_buf, "N1C3CC00;");
14244
    strcat (out_buffer, tmp_buf);
14245
  }
14246
  if (fg[fg_tert_mixed_amine - 1]) {
14247
    sprintf (tmp_buf, "N1C3AC00;");
14248
    strcat (out_buffer, tmp_buf);
14249
  }
14250
  if (fg[fg_tert_arom_amine - 1]) {
14251
    sprintf (tmp_buf, "N1C3AA00;");
14252
    strcat (out_buffer, tmp_buf);
14253
  }
14254
  if (fg[fg_quart_ammonium - 1]) {
14255
    sprintf (tmp_buf, "N1C400T2;");
14256
    strcat (out_buffer, tmp_buf);
14257
  }
14258
  if (fg[fg_n_oxide - 1]) {
14259
    sprintf (tmp_buf, "N0O10000;");
14260
    strcat (out_buffer, tmp_buf);
14261
  }
6785 bpr 14262
 
14179 bpr 14263
  if (fg[fg_halogen_deriv - 1]) {
14264
    if (!fg[fg_alkyl_halide - 1] && !fg[fg_aryl_halide - 1] && !fg[fg_acyl_halide - 1]) {
14265
            sprintf (tmp_buf, "XX000000;");
14266
            strcat (out_buffer, tmp_buf);
14267
          }
14268
  }
6785 bpr 14269
 
14179 bpr 14270
  if (fg[fg_alkyl_fluoride - 1]) {
14271
    sprintf (tmp_buf, "XF00C000;");
14272
    strcat (out_buffer, tmp_buf);
14273
  }
14274
  if (fg[fg_alkyl_chloride - 1]) {
14275
    sprintf (tmp_buf, "XC00C000;");
14276
    strcat (out_buffer, tmp_buf);
14277
  }
14278
  if (fg[fg_alkyl_bromide - 1]) {
14279
    sprintf (tmp_buf, "XB00C000;");
14280
    strcat (out_buffer, tmp_buf);
14281
  }
14282
  if (fg[fg_alkyl_iodide - 1]) {
14283
    sprintf (tmp_buf, "XI00C000;");
14284
    strcat (out_buffer, tmp_buf);
14285
  }
6785 bpr 14286
 
14179 bpr 14287
  if (fg[fg_aryl_fluoride - 1]) {
14288
    sprintf (tmp_buf, "XF00A000;");
14289
    strcat (out_buffer, tmp_buf);
14290
  }
14291
  if (fg[fg_aryl_chloride - 1]) {
14292
    sprintf (tmp_buf, "XC00A000;");
14293
    strcat (out_buffer, tmp_buf);
14294
  }
14295
  if (fg[fg_aryl_bromide - 1]) {
14296
    sprintf (tmp_buf, "XB00A000;");
14297
    strcat (out_buffer, tmp_buf);
14298
  }
14299
  if (fg[fg_aryl_iodide - 1]) {
14300
    sprintf (tmp_buf, "XI00A000;");
14301
    strcat (out_buffer, tmp_buf);
14302
  }
14303
  if (fg[fg_organometallic - 1]) {
14304
    sprintf (tmp_buf, "000000MX;");
14305
    strcat (out_buffer, tmp_buf);
14306
  }
14307
  if (fg[fg_organolithium - 1]) {
14308
    sprintf (tmp_buf, "000000ML;");
14309
    strcat (out_buffer, tmp_buf);
14310
  }
14311
  if (fg[fg_organomagnesium - 1]) {
14312
    sprintf (tmp_buf, "000000MM;");
14313
    strcat (out_buffer, tmp_buf);
14314
  }
6785 bpr 14315
 
14179 bpr 14316
  if (fg[fg_carboxylic_acid - 1]) {
14317
    sprintf (tmp_buf, "C3O2H000;");
14318
    strcat (out_buffer, tmp_buf);
14319
  }
14320
  if (fg[fg_carboxylic_acid_salt - 1]) {
14321
    sprintf (tmp_buf, "C3O200T1;");
14322
    strcat (out_buffer, tmp_buf);
14323
  }
14324
  if (fg[fg_carboxylic_acid_ester - 1]) {
14325
    sprintf (tmp_buf, "C3O2C000;");
14326
    strcat (out_buffer, tmp_buf);
14327
  }
14328
  if (fg[fg_lactone - 1]) {
14329
    sprintf (tmp_buf, "C3O2CZ00;");
14330
    strcat (out_buffer, tmp_buf);
14331
  }
6785 bpr 14332
 
14179 bpr 14333
  if (fg[fg_carboxylic_acid_prim_amide - 1]) {
14334
    sprintf (tmp_buf, "C3ONC100;");
14335
    strcat (out_buffer, tmp_buf);
14336
  }
14337
  if (fg[fg_carboxylic_acid_sec_amide - 1]) {
14338
    sprintf (tmp_buf, "C3ONC200;");
14339
    strcat (out_buffer, tmp_buf);
14340
  }
14341
  if (fg[fg_carboxylic_acid_tert_amide - 1]) {
14342
    sprintf (tmp_buf, "C3ONC300;");
14343
    strcat (out_buffer, tmp_buf);
14344
  }
14345
  if (fg[fg_lactam - 1]) {
14346
    sprintf (tmp_buf, "C3ONCZ00;");
14347
    strcat (out_buffer, tmp_buf);
14348
  }
14349
  if (fg[fg_carboxylic_acid_hydrazide - 1]) {
14350
    sprintf (tmp_buf, "C3ONN100;");
14351
    strcat (out_buffer, tmp_buf);
14352
  }
14353
  if (fg[fg_carboxylic_acid_azide - 1]) {
14354
    sprintf (tmp_buf, "C3ONN200;");
14355
    strcat (out_buffer, tmp_buf);
14356
  }
14357
  if (fg[fg_hydroxamic_acid - 1]) {
14358
    sprintf (tmp_buf, "C3ONOH00;");
14359
    strcat (out_buffer, tmp_buf);
14360
  }
14361
  if (fg[fg_carboxylic_acid_amidine - 1]) {
14362
    sprintf (tmp_buf, "C3N2H000;");
14363
    strcat (out_buffer, tmp_buf);
14364
  }
14365
  if (fg[fg_carboxylic_acid_amidrazone - 1]) {
14366
    sprintf (tmp_buf, "C3NNN100;");
14367
    strcat (out_buffer, tmp_buf);
14368
  }
14369
  if (fg[fg_nitrile - 1]) {
14370
    sprintf (tmp_buf, "C3N00000;");
14371
    strcat (out_buffer, tmp_buf);
14372
  }
6785 bpr 14373
 
14179 bpr 14374
  if (fg[fg_acyl_fluoride - 1]) {
14375
    sprintf (tmp_buf, "C3OXF000;");
14376
    strcat (out_buffer, tmp_buf);
14377
  }
14378
  if (fg[fg_acyl_chloride - 1]) {
14379
    sprintf (tmp_buf, "C3OXC000;");
14380
    strcat (out_buffer, tmp_buf);
14381
  }
14382
  if (fg[fg_acyl_bromide - 1]) {
14383
    sprintf (tmp_buf, "C3OXB000;");
14384
    strcat (out_buffer, tmp_buf);
14385
  }
14386
  if (fg[fg_acyl_iodide - 1]) {
14387
    sprintf (tmp_buf, "C3OXI000;");
14388
    strcat (out_buffer, tmp_buf);
14389
  }
14390
  if (fg[fg_acyl_cyanide - 1]) {
14391
    sprintf (tmp_buf, "C2OC3N00;");
14392
    strcat (out_buffer, tmp_buf);
14393
  }
14394
  if (fg[fg_imido_ester - 1]) {
14395
    sprintf (tmp_buf, "C3NOC000;");
14396
    strcat (out_buffer, tmp_buf);
14397
  }
14398
  if (fg[fg_imidoyl_halide - 1]) {
14399
    sprintf (tmp_buf, "C3NXX000;");
14400
    strcat (out_buffer, tmp_buf);
14401
  }
6785 bpr 14402
 
14179 bpr 14403
  if (fg[fg_thiocarboxylic_acid - 1]) {
14404
    sprintf (tmp_buf, "C3SOH000;");
14405
    strcat (out_buffer, tmp_buf);
14406
  }
14407
  if (fg[fg_thiocarboxylic_acid_ester - 1]) {
14408
    sprintf (tmp_buf, "C3SOC000;");
14409
    strcat (out_buffer, tmp_buf);
14410
  }
14411
  if (fg[fg_thiolactone - 1]) {
14412
    sprintf (tmp_buf, "C3SOCZ00;");
14413
    strcat (out_buffer, tmp_buf);
14414
  }
14415
  if (fg[fg_thiocarboxylic_acid_amide - 1]) {
14416
    sprintf (tmp_buf, "C3SNH000;");
14417
    strcat (out_buffer, tmp_buf);
14418
  }
14419
  if (fg[fg_thiolactam - 1]) {
14420
    sprintf (tmp_buf, "C3SNCZ00;");
14421
    strcat (out_buffer, tmp_buf);
14422
  }
14423
  if (fg[fg_imido_thioester - 1]) {
14424
    sprintf (tmp_buf, "C3NSC000;");
14425
    strcat (out_buffer, tmp_buf);
14426
  }
14427
  if (fg[fg_oxohetarene - 1]) {
14428
    sprintf (tmp_buf, "C3ONAZ00;");
14429
    strcat (out_buffer, tmp_buf);
14430
  }
14431
  if (fg[fg_thioxohetarene - 1]) {
14432
    sprintf (tmp_buf, "C3SNAZ00;");
14433
    strcat (out_buffer, tmp_buf);
14434
  }
14435
  if (fg[fg_iminohetarene - 1]) {
14436
    sprintf (tmp_buf, "C3NNAZ00;");
14437
    strcat (out_buffer, tmp_buf);
14438
  }
14439
  if (fg[fg_orthocarboxylic_acid_deriv - 1]) {
14440
    sprintf (tmp_buf, "C3O30000;");
14441
    strcat (out_buffer, tmp_buf);
14442
  }
14443
  if (fg[fg_carboxylic_acid_orthoester - 1]) {
14444
    sprintf (tmp_buf, "C3O3C000;");
14445
    strcat (out_buffer, tmp_buf);
14446
  }
14447
  if (fg[fg_carboxylic_acid_amide_acetal - 1]) {
14448
    sprintf (tmp_buf, "C3O3NC00;");
14449
    strcat (out_buffer, tmp_buf);
14450
  }
14451
  if (fg[fg_carboxylic_acid_anhydride - 1]) {
14452
    sprintf (tmp_buf, "C3O2C3O2;");
14453
    strcat (out_buffer, tmp_buf);
14454
  }
6785 bpr 14455
 
14179 bpr 14456
  if (fg[fg_carboxylic_acid_unsubst_imide - 1]) {
14457
    sprintf (tmp_buf, "C3ONCH10;");
14458
    strcat (out_buffer, tmp_buf);
14459
  }
14460
  if (fg[fg_carboxylic_acid_subst_imide - 1]) {
14461
    sprintf (tmp_buf, "C3ONCC10;");
14462
    strcat (out_buffer, tmp_buf);
14463
  }
14464
  if (fg[fg_co2_deriv - 1]) {
14465
    sprintf (tmp_buf, "C4000000;");
14466
    strcat (out_buffer, tmp_buf);
14467
  }
14468
  if (fg[fg_carbonic_acid_deriv - 1]) {
14469
    sprintf (tmp_buf, "C4O30000;");
14470
    strcat (out_buffer, tmp_buf);
14471
  }
14472
  if (fg[fg_carbonic_acid_monoester - 1]) {
14473
    sprintf (tmp_buf, "C4O3C100;");
14474
    strcat (out_buffer, tmp_buf);
14475
  }
14476
  if (fg[fg_carbonic_acid_diester - 1]) {
14477
    sprintf (tmp_buf, "C4O3C200;");
14478
    strcat (out_buffer, tmp_buf);
14479
  }
14480
  if (fg[fg_carbonic_acid_ester_halide - 1]) {
14481
    sprintf (tmp_buf, "C4O3CX00;");
14482
    strcat (out_buffer, tmp_buf);
14483
  }
14484
  if (fg[fg_thiocarbonic_acid_deriv - 1]) {
14485
    sprintf (tmp_buf, "C4SO0000;");
14486
    strcat (out_buffer, tmp_buf);
14487
  }
14488
  if (fg[fg_thiocarbonic_acid_monoester - 1]) {
14489
    sprintf (tmp_buf, "C4SOC100;");
14490
    strcat (out_buffer, tmp_buf);
14491
  }
14492
  if (fg[fg_thiocarbonic_acid_diester - 1]) {
14493
    sprintf (tmp_buf, "C4SOC200;");
14494
    strcat (out_buffer, tmp_buf);
14495
  }
14496
  if (fg[fg_thiocarbonic_acid_ester_halide - 1]) {
14497
    sprintf (tmp_buf, "C4SOX_00;");
14498
    strcat (out_buffer, tmp_buf);
14499
  }
14500
  if (fg[fg_carbamic_acid_deriv - 1]) {
14501
    sprintf (tmp_buf, "C4O2N000;");
14502
    strcat (out_buffer, tmp_buf);
14503
  }
14504
  if (fg[fg_carbamic_acid - 1]) {
14505
    sprintf (tmp_buf, "C4O2NH00;");
14506
    strcat (out_buffer, tmp_buf);
14507
  }
14508
  if (fg[fg_carbamic_acid_ester - 1]) {
14509
    sprintf (tmp_buf, "C4O2NC00;");
14510
    strcat (out_buffer, tmp_buf);
14511
  }
14512
  if (fg[fg_carbamic_acid_halide - 1]) {
14513
    sprintf (tmp_buf, "C4O2NX00;");
14514
    strcat (out_buffer, tmp_buf);
14515
  }
14516
  if (fg[fg_thiocarbamic_acid_deriv - 1]) {
14517
    sprintf (tmp_buf, "C4SN0000;");
14518
    strcat (out_buffer, tmp_buf);
14519
  }
14520
  if (fg[fg_thiocarbamic_acid - 1]) {
14521
    sprintf (tmp_buf, "C4SNOH00;");
14522
    strcat (out_buffer, tmp_buf);
14523
  }
14524
  if (fg[fg_thiocarbamic_acid_ester - 1]) {
14525
    sprintf (tmp_buf, "C4SNOC00;");
14526
    strcat (out_buffer, tmp_buf);
14527
  }
14528
  if (fg[fg_thiocarbamic_acid_halide - 1]) {
14529
    sprintf (tmp_buf, "C4SNXX00;");
14530
    strcat (out_buffer, tmp_buf);
14531
  }
14532
  if (fg[fg_urea - 1]) {
14533
    sprintf (tmp_buf, "C4O1N200;");
14534
    strcat (out_buffer, tmp_buf);
14535
  }
14536
  if (fg[fg_isourea - 1]) {
14537
    sprintf (tmp_buf, "C4N2O100;");
14538
    strcat (out_buffer, tmp_buf);
14539
  }
14540
  if (fg[fg_thiourea - 1]) {
14541
    sprintf (tmp_buf, "C4S1N200;");
14542
    strcat (out_buffer, tmp_buf);
14543
  }
14544
  if (fg[fg_isothiourea - 1]) {
14545
    sprintf (tmp_buf, "C4N2S100;");
14546
    strcat (out_buffer, tmp_buf);
14547
  }
14548
  if (fg[fg_guanidine - 1]) {
14549
    sprintf (tmp_buf, "C4N30000;");
14550
    strcat (out_buffer, tmp_buf);
14551
  }
14552
  if (fg[fg_semicarbazide - 1]) {
14553
    sprintf (tmp_buf, "C4ON2N00;");
14554
    strcat (out_buffer, tmp_buf);
14555
  }
14556
  if (fg[fg_thiosemicarbazide - 1]) {
14557
    sprintf (tmp_buf, "C4SN2N00;");
14558
    strcat (out_buffer, tmp_buf);
14559
  }
14560
  if (fg[fg_azide - 1]) {
14561
    sprintf (tmp_buf, "N4N20000;");
14562
    strcat (out_buffer, tmp_buf);
14563
  }
14564
  if (fg[fg_azo_compound - 1]) {
14565
    sprintf (tmp_buf, "N2N10000;");
14566
    strcat (out_buffer, tmp_buf);
14567
  }
14568
  if (fg[fg_diazonium_salt - 1]) {
14569
    sprintf (tmp_buf, "N3N100T2;");
14570
    strcat (out_buffer, tmp_buf);
14571
  }
14572
  if (fg[fg_isonitrile - 1]) {
14573
    sprintf (tmp_buf, "N3C10000;");
14574
    strcat (out_buffer, tmp_buf);
14575
  }
14576
  if (fg[fg_cyanate - 1]) {
14577
    sprintf (tmp_buf, "C4NO1000;");
14578
    strcat (out_buffer, tmp_buf);
14579
  }
14580
  if (fg[fg_isocyanate - 1]) {
14581
    sprintf (tmp_buf, "C4NO2000;");
14582
    strcat (out_buffer, tmp_buf);
14583
  }
14584
  if (fg[fg_thiocyanate - 1]) {
14585
    sprintf (tmp_buf, "C4NS1000;");
14586
    strcat (out_buffer, tmp_buf);
14587
  }
14588
  if (fg[fg_isothiocyanate - 1]) {
14589
    sprintf (tmp_buf, "C4NS2000;");
14590
    strcat (out_buffer, tmp_buf);
14591
  }
14592
  if (fg[fg_carbodiimide - 1]) {
14593
    sprintf (tmp_buf, "C4N20000;");
14594
    strcat (out_buffer, tmp_buf);
14595
  }
14596
  if (fg[fg_nitroso_compound - 1]) {
14597
    sprintf (tmp_buf, "N2O10000;");
14598
    strcat (out_buffer, tmp_buf);
14599
  }
14600
  if (fg[fg_nitro_compound - 1]) {
14601
    sprintf (tmp_buf, "N4O20000;");
14602
    strcat (out_buffer, tmp_buf);
14603
  }
14604
  if (fg[fg_nitrite - 1]) {
14605
    sprintf (tmp_buf, "N3O20000;");
14606
    strcat (out_buffer, tmp_buf);
14607
  }
14608
  if (fg[fg_nitrate - 1]) {
14609
    sprintf (tmp_buf, "N4O30000;");
14610
    strcat (out_buffer, tmp_buf);
14611
  }
14612
  if (fg[fg_sulfuric_acid_deriv - 1]) {
14613
    sprintf (tmp_buf, "S6O00000;");
14614
    strcat (out_buffer, tmp_buf);
14615
  }
14616
  if (fg[fg_sulfuric_acid - 1]) {
14617
    sprintf (tmp_buf, "S6O4H000;");
14618
    strcat (out_buffer, tmp_buf);
14619
  }
14620
  if (fg[fg_sulfuric_acid_monoester - 1]) {
14621
    sprintf (tmp_buf, "S6O4HC00;");
14622
    strcat (out_buffer, tmp_buf);
14623
  }
14624
  if (fg[fg_sulfuric_acid_diester - 1]) {
14625
    sprintf (tmp_buf, "S6O4CC00;");
14626
    strcat (out_buffer, tmp_buf);
14627
  }
14628
  if (fg[fg_sulfuric_acid_amide_ester - 1]) {
14629
    sprintf (tmp_buf, "S6O3NC00;");
14630
    strcat (out_buffer, tmp_buf);
14631
  }
14632
  if (fg[fg_sulfuric_acid_amide - 1]) {
14633
    sprintf (tmp_buf, "S6O3N100;");
14634
    strcat (out_buffer, tmp_buf);
14635
  }
14636
  if (fg[fg_sulfuric_acid_diamide - 1]) {
14637
    sprintf (tmp_buf, "S6O2N200;");
14638
    strcat (out_buffer, tmp_buf);
14639
  }
14640
  if (fg[fg_sulfuryl_halide - 1]) {
14641
    sprintf (tmp_buf, "S6O3XX00;");
14642
    strcat (out_buffer, tmp_buf);
14643
  }
14644
  if (fg[fg_sulfonic_acid_deriv - 1]) {
14645
    sprintf (tmp_buf, "S5O00000;");
14646
    strcat (out_buffer, tmp_buf);
14647
  }
14648
  if (fg[fg_sulfonic_acid - 1]) {
14649
    sprintf (tmp_buf, "S5O3H000;");
14650
    strcat (out_buffer, tmp_buf);
14651
  }
14652
  if (fg[fg_sulfonic_acid_ester - 1]) {
14653
    sprintf (tmp_buf, "S5O3C000;");
14654
    strcat (out_buffer, tmp_buf);
14655
  }
14656
  if (fg[fg_sulfonamide - 1]) {
14657
    sprintf (tmp_buf, "S5O2N000;");
14658
    strcat (out_buffer, tmp_buf);
14659
  }
14660
  if (fg[fg_sulfonyl_halide - 1]) {
14661
    sprintf (tmp_buf, "S5O2XX00;");
14662
    strcat (out_buffer, tmp_buf);
14663
  }
14664
  if (fg[fg_sulfone - 1]) {
14665
    sprintf (tmp_buf, "S4O20000;");
14666
    strcat (out_buffer, tmp_buf);
14667
  }
14668
  if (fg[fg_sulfoxide - 1]) {
14669
    sprintf (tmp_buf, "S2O10000;");
14670
    strcat (out_buffer, tmp_buf);
14671
  }
14672
  if (fg[fg_sulfinic_acid_deriv - 1]) {
14673
    sprintf (tmp_buf, "S3O00000;");
14674
    strcat (out_buffer, tmp_buf);
14675
  }
14676
  if (fg[fg_sulfinic_acid - 1]) {
14677
    sprintf (tmp_buf, "S3O2H000;");
14678
    strcat (out_buffer, tmp_buf);
14679
  }
14680
  if (fg[fg_sulfinic_acid_ester - 1]) {
14681
    sprintf (tmp_buf, "S3O2C000;");
14682
    strcat (out_buffer, tmp_buf);
14683
  }
14684
  if (fg[fg_sulfinic_acid_halide - 1]) {
14685
    sprintf (tmp_buf, "S3O1XX00;");
14686
    strcat (out_buffer, tmp_buf);
14687
  }
14688
  if (fg[fg_sulfinic_acid_amide - 1]) {
6785 bpr 14689
      sprintf (tmp_buf, "S3O1N000;");
14690
      strcat (out_buffer, tmp_buf);
14691
    }
14179 bpr 14692
  if (fg[fg_sulfenic_acid_deriv - 1]) {
14693
    sprintf (tmp_buf, "S1O00000;");
14694
    strcat (out_buffer, tmp_buf);
14695
  }
14696
  if (fg[fg_sulfenic_acid - 1]) {
14697
    sprintf (tmp_buf, "S1O1H000;");
14698
    strcat (out_buffer, tmp_buf);
14699
  }
14700
  if (fg[fg_sulfenic_acid_ester - 1]) {
14701
    sprintf (tmp_buf, "S1O1C000;");
14702
    strcat (out_buffer, tmp_buf);
14703
  }
14704
  if (fg[fg_sulfenic_acid_halide - 1]) {
14705
    sprintf (tmp_buf, "S1O0XX00;");
14706
    strcat (out_buffer, tmp_buf);
14707
  }
14708
  if (fg[fg_sulfenic_acid_amide - 1]) {
14709
    sprintf (tmp_buf, "S1O0N100;");
14710
    strcat (out_buffer, tmp_buf);
14711
  }
6785 bpr 14712
 
14179 bpr 14713
  if (fg[fg_alkylthiol - 1]) {
14714
    sprintf (tmp_buf, "S1H1C000;");
14715
    strcat (out_buffer, tmp_buf);
14716
  }
14717
  if (fg[fg_arylthiol - 1]) {
14718
    sprintf (tmp_buf, "S1H1A000;");
14719
    strcat (out_buffer, tmp_buf);
14720
  }
14721
  if (fg[fg_phosphoric_acid_deriv - 1]) {
14722
    sprintf (tmp_buf, "P5O0H000;");
14723
    strcat (out_buffer, tmp_buf);
14724
  }
14725
  if (fg[fg_phosphoric_acid - 1]) {
14726
    sprintf (tmp_buf, "P5O4H200;");
14727
    strcat (out_buffer, tmp_buf);
14728
  }
14729
  if (fg[fg_phosphoric_acid_ester - 1]) {
14730
    sprintf (tmp_buf, "P5O4HC00;");
14731
    strcat (out_buffer, tmp_buf);
14732
  }
14733
  if (fg[fg_phosphoric_acid_halide - 1]) {
14734
    sprintf (tmp_buf, "P5O3HX00;");
14735
    strcat (out_buffer, tmp_buf);
14736
  }
14737
  if (fg[fg_phosphoric_acid_amide - 1]) {
14738
    sprintf (tmp_buf, "P5O3HN00;");
14739
    strcat (out_buffer, tmp_buf);
14740
  }
14741
  if (fg[fg_thiophosphoric_acid_deriv - 1]) {
14742
    sprintf (tmp_buf, "P5O0S000;");
14743
    strcat (out_buffer, tmp_buf);
14744
  }
14745
  if (fg[fg_thiophosphoric_acid - 1]) {
14746
    sprintf (tmp_buf, "P5O3SH00;");
14747
    strcat (out_buffer, tmp_buf);
14748
  }
14749
  if (fg[fg_thiophosphoric_acid_ester - 1]) {
14750
    sprintf (tmp_buf, "P5O3SC00;");
14751
    strcat (out_buffer, tmp_buf);
14752
  }
14753
  if (fg[fg_thiophosphoric_acid_halide - 1]) {
14754
    sprintf (tmp_buf, "P5O2SX00;");
14755
    strcat (out_buffer, tmp_buf);
14756
  }
14757
  if (fg[fg_thiophosphoric_acid_amide - 1]) {
14758
    sprintf (tmp_buf, "P5O2SN00;");
14759
    strcat (out_buffer, tmp_buf);
14760
  }
14761
  if (fg[fg_phosphonic_acid_deriv - 1]) {
14762
    sprintf (tmp_buf, "P4O30000;");
14763
    strcat (out_buffer, tmp_buf);
14764
  }
14765
  if (fg[fg_phosphonic_acid - 1]) {
14766
    sprintf (tmp_buf, "P4O3H000;");
14767
    strcat (out_buffer, tmp_buf);
14768
  }
14769
  if (fg[fg_phosphonic_acid_ester - 1]) {
14770
    sprintf (tmp_buf, "P4O3C000;");
14771
    strcat (out_buffer, tmp_buf);
14772
  }
14773
  if (fg[fg_phosphine - 1]) {
14774
    sprintf (tmp_buf, "P3000000;");
14775
    strcat (out_buffer, tmp_buf);
14776
  }
14777
  if (fg[fg_phosphinoxide - 1]) {
14778
    sprintf (tmp_buf, "P2O00000;");
14779
    strcat (out_buffer, tmp_buf);
14780
  }
14781
  if (fg[fg_boronic_acid_deriv - 1]) {
14782
    sprintf (tmp_buf, "B2O20000;");
14783
    strcat (out_buffer, tmp_buf);
14784
  }
14785
  if (fg[fg_boronic_acid - 1]) {
14786
    sprintf (tmp_buf, "B2O2H000;");
14787
    strcat (out_buffer, tmp_buf);
14788
  }
14789
  if (fg[fg_boronic_acid_ester - 1]) {
14790
    sprintf (tmp_buf, "B2O2C000;");
14791
    strcat (out_buffer, tmp_buf);
14792
  }
14793
  if (fg[fg_alkene - 1]) {
14794
    sprintf (tmp_buf, "000C2C00;");
14795
    strcat (out_buffer, tmp_buf);
14796
  }
14797
  if (fg[fg_alkyne - 1]) {
14798
    sprintf (tmp_buf, "000C3C00;");
14799
    strcat (out_buffer, tmp_buf);
14800
  }
14801
  if (fg[fg_aromatic - 1]) {
14802
    sprintf (tmp_buf, "0000A000;");
14803
    strcat (out_buffer, tmp_buf);
14804
  }
14805
  if (fg[fg_heterocycle - 1]) {
14806
    sprintf (tmp_buf, "0000CZ00;");
14807
    strcat (out_buffer, tmp_buf);
14808
  }
14809
  if (fg[fg_alpha_aminoacid - 1]) {
14810
    sprintf (tmp_buf, "C3O2HN1C;");
14811
    strcat (out_buffer, tmp_buf);
14812
  }
14813
  if (fg[fg_alpha_hydroxyacid - 1]) {
14814
    sprintf (tmp_buf, "C3O2HO1H;");
14815
    strcat (out_buffer, tmp_buf);
14816
  }
6785 bpr 14817
}
14818
 
14819
/*static void mm_elab_molstat(void)
14820
{
14821
                count_neighbors();
14822
//      init_molstat(&molstat);
14823
        if (!found_arominfo) {
14824
    chk_ringbonds();
14825
    if (ringsearch_mode == rs_ssr)
14826
      remove_redundant_rings();
14827
    if (n_rings == max_rings) {
14828
      if (opt_verbose)
14829
        printf("warning: max. number of rings exceeded, reverting to SSR search\n");
14830
      ringsearch_mode = rs_ssr;
14831
      clear_rings();
14832
      max_vringsize = 10;
14833
      chk_ringbonds();
14834
      remove_redundant_rings();
14835
    }
14179 bpr 14836
 
6785 bpr 14837
    update_ringcount();
14838
    update_atypes();
14839
    update_Htotal();
14840
    chk_arom();
14841
 
14842
    if (ringsearch_mode == rs_ssr) {
14843
      do {
14844
        prev_n_ar = count_aromatic_rings();
14845
        chk_arom();
14846
        n_ar = count_aromatic_rings();
14847
      } while (prev_n_ar - n_ar != 0);
14848
    }
14849
        } else {
14850
 update_atypes();
14179 bpr 14851
    update_Htotal();
14852
 
6785 bpr 14853
        }
14179 bpr 14854
 
6785 bpr 14855
 // get_molstat();
14856
}*/
14857
 
14858
DLLEXPORT void
14859
cm_molstat_X (char *buf)
14860
{
14861
  init_molstat (&molstat);
14862
//mm_elab_molstat();
14863
  get_molstat ();
14864
  write_molstat_X_dll (buf);
14865
}
14866
 
14867
DLLEXPORT void
14868
cm_molstat (char *buf)
14869
{
14870
  init_molstat (&molstat);
14871
//mm_elab_molstat();
14872
  get_molstat ();
14873
  write_molstat_dll (buf, 0);
14874
}
14875
 
14876
DLLEXPORT void
14877
cm_molstat_sql_exact (char *buf)
14878
{
14879
  init_molstat (&molstat);
14880
//mm_elab_molstat();
14881
  get_molstat ();
14882
  write_molstat_dll (buf, 1);
14883
}
14884
 
14885
DLLEXPORT void
14886
cm_molstat_sql_substruct (char *buf)
14887
{
14888
  init_molstat (&molstat);
14889
//mm_elab_molstat();
14890
  get_molstat ();
14891
  write_molstat_dll (buf, 2);
14892
}
14893
 
14894
DLLEXPORT void
14895
cm_fg_codes (char *buf)
14896
{
14897
//mm_elab_molstat();
14898
  chk_functionalgroups ();
14899
  write_fg_code_dll (buf);
14900
}
14901
 
14179 bpr 14902
static void write_MDLmolfile_dll (char *out_buffer)
6785 bpr 14903
{
14904
  int i;
14905
  char tmpstr[256];
14906
  char wline[256];
14907
  int a_chg;
14908
  int a_iso;
14909
  int a_rad;
14910
  char tmflabel[256];           /* v0.3m */
14911
  char STR1[256], STR7[256];
14912
  int FORLIM;
14913
  *out_buffer = '\0';
14914
  *tmpstr = '\0';
14915
  *wline = '\0';
14916
  sprintf (tmflabel, "%i", tweaklevel); /* v0.3m */
14917
  while (strlen (tmflabel) < 2) /* v0.3m */
14918
    sprintf (tmflabel, "0%s", strcpy (STR1, tmflabel));
14919
  sprintf (tmflabel, "TMF%s", strcpy (STR1, tmflabel)); /* v0.3m */
14920
  if (strlen (molname) > 80)
14921
    sprintf (molname, "%.80s", strcpy (STR1, molname));
14922
  strncat (out_buffer, molname, 80);
14923
  sprintf (wline, "\n  CheckMol                        %s", tmflabel);  /* v0.3m */
14924
  if (ringsearch_mode == rs_sar)        /* v0.3m */
14925
    strcat (wline, ":r0");
14926
  if (ringsearch_mode == rs_ssr)        /* v0.3m */
14927
    strcat (wline, ":r1");
14928
  if (opt_metalrings)
14929
    strcat (wline, ":m1");
14930
  else
14931
    strcat (wline, ":m0");
14932
  /* v0.3m */
14933
  sprintf (tmpstr, "\n%s\n", molcomment);
14934
  strcat (wline, tmpstr);
14935
  sprintf (tmpstr, "%d", n_atoms);
14936
  lblank (3L, tmpstr);
14937
  strcat (wline, tmpstr);
14938
  /* first 3 digits: number of atoms */
14939
  sprintf (tmpstr, "%d", n_bonds);
14940
  lblank (3L, tmpstr);
14941
  strcat (wline, tmpstr);
14942
  *tmpstr = '\0';               /* next 3 digits: number of bonds */
14943
  strcpy (tmpstr, "  0");
14944
  strcat (wline, tmpstr);
14945
  /* next 3 digits: number of atom lists (not used by us) */
14179 bpr 14946
  /* p2c: checkmol.pas, line 2388:
14947
  * Note: Turbo Pascal conditional compilation directive was ignored [218] */
6785 bpr 14948
#ifdef REDUCED_SAR
14949
  sprintf (tmpstr, "%d", n_countablerings);
14950
  /* v0.3n; changed n_rings into n_countablerings */
14951
#else
14952
  sprintf (tmpstr, "%d", n_rings);
14953
#endif
14954
  lblank (3L, tmpstr);
14955
  strcat (wline, tmpstr);
14956
  /* officially "obsolete", we use it for the number of rings */
14957
  strcat (wline, "  ");         /* v0.3n: obey chiral flag */
14958
  if (chir_flag)
14959
    strcat (wline, "1");
14960
  else
14961
    strcat (wline, "0");
14962
  /* v0.3n */
14963
  strcat (wline, "               999 V2000\n");
14964
  /* v0.3n (adjust string length) */
14965
  strcat (out_buffer, wline);
14966
  FORLIM = n_atoms;
14179 bpr 14967
  for (i = 0; i < FORLIM; i++) {
14968
    *wline = '\0';
14969
    *tmpstr = '\0';
14970
    sprintf (tmpstr, "%1.4f", atom[i].x);
14971
    lblank (10L, tmpstr);
14972
    strcat (wline, tmpstr);
14973
    sprintf (tmpstr, "%1.4f", atom[i].y);
14974
    lblank (10L, tmpstr);
14975
    strcat (wline, tmpstr);
14976
    sprintf (tmpstr, "%1.4f", atom[i].z);
14977
    lblank (10L, tmpstr);
14978
    strcat (wline, tmpstr);
14979
    strcpy (tmpstr, atom[i].element);
14980
    /* tmpstr := lowercase(tmpstr); REPLACE!!! */
14981
    //tmpstr[0] = toupper (tmpstr[0]);
14982
    all_lowercase (tmpstr);
14983
    tmpstr[0] = toupper (tmpstr[0]);
14984
    /*wline := wline + ' '+atom^[i].element+' '; */
14985
    sprintf (wline + strlen (wline), " %s ", tmpstr);
14986
    strcat (wline, " 0");       /* mass difference (isotopes) */
14987
    /* now we code aromaticity into the old-style charge column (charges are now in the M  CHG line) */
14988
    if (atom[i].arom)
14989
            strcpy (tmpstr, " 00");
14990
    else
14991
            strcpy (tmpstr, "  0");
14992
    strcat (wline, tmpstr);
14993
    strcat (wline, "  0  0  0  0  0  0  0  0  0  0\n");
14994
    strcat (out_buffer, wline);
14995
  }
6785 bpr 14996
  FORLIM = n_bonds;
14179 bpr 14997
  for (i = 0; i < FORLIM; i++) {
14998
    *wline = '\0';
14999
    *tmpstr = '\0';
15000
    sprintf (tmpstr, "%d", bond[i].a1);
15001
    lblank (3L, tmpstr);
15002
    strcat (wline, tmpstr);
15003
    sprintf (tmpstr, "%d", bond[i].a2);
15004
    lblank (3L, tmpstr);
15005
    strcat (wline, tmpstr);
15006
    if (bond[i].btype == 'S')
15007
            strcpy (tmpstr, "  1");
15008
    if (bond[i].btype == 'D')
15009
            strcpy (tmpstr, "  2");
15010
    if (bond[i].btype == 'T')
15011
            strcpy (tmpstr, "  3");
15012
    if (bond[i].btype == 'A')
15013
            strcpy (tmpstr, "  4");
15014
    if (bond[i].btype == 'l')
15015
            strcpy (tmpstr, "  5");
15016
    if (bond[i].btype == 's')
15017
            strcpy (tmpstr, "  6");
15018
    if (bond[i].btype == 'd')
15019
            strcpy (tmpstr, "  7");
15020
    if (bond[i].btype == 'a')
15021
            strcpy (tmpstr, "  8");
15022
        /* now encode our own aromaticity information */
15023
    if (bond[i].arom)
15024
            tmpstr[1] = '0';
15025
    strcat (wline, tmpstr);     /* next, encode bond stereo property (v0.3f) */
15026
    /*if (bond^[i].stereo = bstereo_up) then wline := wline + '  1' else */
15027
    /*  if (bond^[i].stereo = bstereo_down) then wline := wline + '  6' else */
15028
    /*    wline := wline + '  0'; */
15029
    /* restore original value from MDL molfile (v0.3n) */
15030
    /* wline := wline + '  ' + inttostr(bond^[i].mdl_stereo);    REPLACE!!! */
15031
    *tmpstr = '\0';
15032
    sprintf (tmpstr, "%i", bond[i].mdl_stereo);
15033
    strcat (wline, "  ");
15034
    strcat (wline, tmpstr);
15035
    *tmpstr = '\0';
15036
    /* now encode the ring_count of this bond (using a field which officially is "not used") */
15037
    /* tmpstr := inttostr(bond^[i].ring_count); REPLACE!!! */
15038
    sprintf (tmpstr, "%i", bond[i].ring_count);
15039
    while (strlen (tmpstr) < 3)
15040
            sprintf (tmpstr, " %s", strcpy (STR1, tmpstr));
15041
    sprintf (wline + strlen (wline), "%s  0  0\n", tmpstr);
15042
    strcat (out_buffer, wline);
15043
  }
6785 bpr 15044
  FORLIM = n_atoms;
14179 bpr 15045
  for (i = 1; i <= FORLIM; i++) {
15046
    a_chg = atom[i - 1].formal_charge;
15047
    if (a_chg != 0) {
15048
            strcpy (wline, "M  CHG  1 ");
15049
            sprintf (tmpstr, "%d", i);
15050
            lblank (3L, tmpstr);
15051
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15052
            sprintf (tmpstr, "%d", a_chg);
15053
            lblank (3L, tmpstr);
15054
            strcat (wline, tmpstr);
15055
            strcat (out_buffer, wline);
15056
            strcat (out_buffer, "\n");
15057
          }
15058
  }
15059
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
15060
    a_iso = atom[i - 1].nucleon_number;
15061
    if (a_iso != 0) {
15062
            strcpy (wline, "M  ISO  1 ");
15063
            sprintf (tmpstr, "%d", i);
15064
            lblank (3L, tmpstr);
15065
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15066
            sprintf (tmpstr, "%d", a_iso);
15067
            lblank (3L, tmpstr);
15068
            strcat (wline, tmpstr);
15069
            strcat (out_buffer, wline);
15070
            strcat (out_buffer, "\n");
15071
          }
15072
  }
15073
  for (i = 1; i <= FORLIM; i++) /* 0.3x */ {
15074
    a_rad = atom[i - 1].radical_type;
15075
    if (a_rad != 0) {
15076
            strcpy (wline, "M  RAD  1 ");
15077
            sprintf (tmpstr, "%d", i);
15078
            lblank (3L, tmpstr);
15079
            sprintf (wline + strlen (wline), "%s ", tmpstr);
15080
            sprintf (tmpstr, "%d", a_rad);
15081
            lblank (3L, tmpstr);
15082
            strcat (wline, tmpstr);
15083
            strcat (out_buffer, wline);
15084
            strcat (out_buffer, "\n");
15085
          }
15086
  }
6785 bpr 15087
  strcat (out_buffer, "M  END\n");
15088
}
15089
 
15090
DLLEXPORT void
15091
cm_tweak_molfile (char *buf)
15092
{
15093
//chk_functionalgroups();
15094
  write_MDLmolfile_dll (buf);
15095
}
15096
#endif