1*23f24377SWarner LoshBEGIN { 2*23f24377SWarner Losh macros = "/usr/bwk/chem/chem.macros" # CHANGE ME!!!!! 3*23f24377SWarner Losh macros = "/dev/null" # since originals are lost 4*23f24377SWarner Losh 5*23f24377SWarner Losh pi = 3.141592654 6*23f24377SWarner Losh deg = 57.29578 7*23f24377SWarner Losh setparams(1.0) 8*23f24377SWarner Losh set(dc, "up 0 right 90 down 180 left 270 ne 45 se 135 sw 225 nw 315") 9*23f24377SWarner Losh set(dc, "0 n 30 ne 45 ne 60 ne 90 e 120 se 135 se 150 se 180 s") 10*23f24377SWarner Losh set(dc, "300 nw 315 nw 330 nw 270 w 210 sw 225 sw 240 sw") 11*23f24377SWarner Losh} 12*23f24377SWarner Loshfunction init() { 13*23f24377SWarner Losh printf ".PS\n" 14*23f24377SWarner Losh if (firsttime++ == 0) { 15*23f24377SWarner Losh printf "copy \"%s\"\n", macros 16*23f24377SWarner Losh printf "\ttextht = %g; textwid = .1; cwid = %g\n", textht, cwid 17*23f24377SWarner Losh printf "\tlineht = %g; linewid = %g\n", lineht, linewid 18*23f24377SWarner Losh } 19*23f24377SWarner Losh printf "Last: 0,0\n" 20*23f24377SWarner Losh RING = "R"; MOL = "M"; BOND = "B"; OTHER = "O" # manifests 21*23f24377SWarner Losh last = OTHER 22*23f24377SWarner Losh dir = 90 23*23f24377SWarner Losh} 24*23f24377SWarner Loshfunction setparams(scale) { 25*23f24377SWarner Losh lineht = scale * 0.2 26*23f24377SWarner Losh linewid = scale * 0.2 27*23f24377SWarner Losh textht = scale * 0.16 28*23f24377SWarner Losh db = scale * 0.2 # bond length 29*23f24377SWarner Losh cwid = scale * 0.12 # character width 30*23f24377SWarner Losh cr = scale * 0.08 # rad of invis circles at ring vertices 31*23f24377SWarner Losh crh = scale * 0.16 # ht of invis ellipse at ring vertices 32*23f24377SWarner Losh crw = scale * 0.12 # wid 33*23f24377SWarner Losh dav = scale * 0.015 # vertical shift up for atoms in atom macro 34*23f24377SWarner Losh dew = scale * 0.02 # east-west shift for left of/right of 35*23f24377SWarner Losh ringside = scale * 0.3 # side of all rings 36*23f24377SWarner Losh dbrack = scale * 0.1 # length of bottom of bracket 37*23f24377SWarner Losh} 38*23f24377SWarner Losh 39*23f24377SWarner Losh { lineno++ } 40*23f24377SWarner Losh 41*23f24377SWarner Losh/^(\.cstart)|(begin chem)/ { init(); inchem = 1; next } 42*23f24377SWarner Losh/^(\.cend)|(end)/ { inchem = 0; print ".PE"; next } 43*23f24377SWarner Losh 44*23f24377SWarner Losh/^\./ { print; next } # troff 45*23f24377SWarner Losh 46*23f24377SWarner Loshinchem == 0 { print; next } # everything else 47*23f24377SWarner Losh 48*23f24377SWarner Losh$1 == "pic" { shiftfields(1); print; next } # pic pass-thru 49*23f24377SWarner Losh$1 ~ /^#/ { next } # comment 50*23f24377SWarner Losh 51*23f24377SWarner Losh$1 == "textht" { textht = $NF; next } 52*23f24377SWarner Losh$1 == "cwid" { cwid = $NF; next } 53*23f24377SWarner Losh$1 == "db" { db = $NF; next } 54*23f24377SWarner Losh$1 == "size" { if ($NF <= 4) size = $NF; else size = $NF/10 55*23f24377SWarner Losh setparams(size); next } 56*23f24377SWarner Losh 57*23f24377SWarner Losh { print "\n#", $0 } # debugging, etc. 58*23f24377SWarner Losh { lastname = "" } 59*23f24377SWarner Losh 60*23f24377SWarner Losh$1 ~ /^[A-Z].*:$/ { # label; falls thru after shifting left 61*23f24377SWarner Losh lastname = substr($1, 1, length($1)-1) 62*23f24377SWarner Losh print $1 63*23f24377SWarner Losh shiftfields(1) 64*23f24377SWarner Losh} 65*23f24377SWarner Losh 66*23f24377SWarner Losh$1 ~ /^\"/ { print "Last: ", $0; last = OTHER; next } 67*23f24377SWarner Losh 68*23f24377SWarner Losh$1 ~ /bond/ { bond($1); next } 69*23f24377SWarner Losh$1 ~ /^(double|triple|front|back)$/ && $2 == "bond" { 70*23f24377SWarner Losh $1 = $1 $2; shiftfields(2); bond($1); next } 71*23f24377SWarner Losh 72*23f24377SWarner Losh$1 == "aromatic" { temp = $1; $1 = $2; $2 = temp } 73*23f24377SWarner Losh$1 ~ /ring|benz/ { ring($1); next } 74*23f24377SWarner Losh 75*23f24377SWarner Losh$1 == "methyl" { $1 = "CH3" } # left here as an example 76*23f24377SWarner Losh 77*23f24377SWarner Losh$1 ~ /^[A-Z]/ { molecule(); next } 78*23f24377SWarner Losh 79*23f24377SWarner Losh$1 == "left" { left[++stack] = fields(2, NF); printf("Last: [\n"); next } 80*23f24377SWarner Losh 81*23f24377SWarner Losh$1 == "right" { bracket(); stack--; next } 82*23f24377SWarner Losh 83*23f24377SWarner Losh$1 == "label" { label(); next } 84*23f24377SWarner Losh 85*23f24377SWarner Losh/./ { print "Last: ", $0; last = OTHER } 86*23f24377SWarner Losh 87*23f24377SWarner LoshEND { if (firsttime == 0) error("did you forget .cstart and .cend?") 88*23f24377SWarner Losh if (inchem) printf ".PE\n" 89*23f24377SWarner Losh} 90*23f24377SWarner Losh 91*23f24377SWarner Loshfunction bond(type, i, goes, from) { 92*23f24377SWarner Losh goes = "" 93*23f24377SWarner Losh for (i = 2; i <= NF; i++) 94*23f24377SWarner Losh if ($i == ";") { 95*23f24377SWarner Losh goes = $(i+1) 96*23f24377SWarner Losh NF = i - 1 97*23f24377SWarner Losh break 98*23f24377SWarner Losh } 99*23f24377SWarner Losh leng = db 100*23f24377SWarner Losh from = "" 101*23f24377SWarner Losh for (cf = 2; cf <= NF; ) { 102*23f24377SWarner Losh if ($cf ~ /(\+|-)?[0-9]+|up|down|right|left|ne|se|nw|sw/) 103*23f24377SWarner Losh dir = cvtdir(dir) 104*23f24377SWarner Losh else if ($cf ~ /^leng/) { 105*23f24377SWarner Losh leng = $(cf+1) 106*23f24377SWarner Losh cf += 2 107*23f24377SWarner Losh } else if ($cf == "to") { 108*23f24377SWarner Losh leng = 0 109*23f24377SWarner Losh from = fields(cf, NF) 110*23f24377SWarner Losh break 111*23f24377SWarner Losh } else if ($cf == "from") { 112*23f24377SWarner Losh from = dofrom() 113*23f24377SWarner Losh break 114*23f24377SWarner Losh } else if ($cf ~ /^#/) { 115*23f24377SWarner Losh cf = NF+1 116*23f24377SWarner Losh break; 117*23f24377SWarner Losh } else { 118*23f24377SWarner Losh from = fields(cf, NF) 119*23f24377SWarner Losh break 120*23f24377SWarner Losh } 121*23f24377SWarner Losh } 122*23f24377SWarner Losh if (from ~ /( to )|^to/) # said "from ... to ...", so zap length 123*23f24377SWarner Losh leng = 0 124*23f24377SWarner Losh else if (from == "") # no from given at all 125*23f24377SWarner Losh from = "from Last." leave(last, dir) " " fields(cf, NF) 126*23f24377SWarner Losh printf "Last: %s(%g, %g, %s)\n", type, leng, dir, from 127*23f24377SWarner Losh last = BOND 128*23f24377SWarner Losh if (lastname != "") 129*23f24377SWarner Losh labsave(lastname, last, dir) 130*23f24377SWarner Losh if (goes) { 131*23f24377SWarner Losh $0 = goes 132*23f24377SWarner Losh molecule() 133*23f24377SWarner Losh } 134*23f24377SWarner Losh} 135*23f24377SWarner Losh 136*23f24377SWarner Loshfunction dofrom( n, s) { 137*23f24377SWarner Losh cf++ # skip "from" 138*23f24377SWarner Losh n = $cf 139*23f24377SWarner Losh if (n in labtype) # "from Thing" => "from Thing.V.s" 140*23f24377SWarner Losh return "from " n "." leave(labtype[n], dir) 141*23f24377SWarner Losh if (n ~ /^\.[A-Z]/) # "from .V" => "from Last.V.s" 142*23f24377SWarner Losh return "from Last" n "." corner(dir) 143*23f24377SWarner Losh if (n ~ /^[A-Z][^.]*\.[A-Z][^.]*$/) # "from X.V" => "from X.V.s" 144*23f24377SWarner Losh return "from " n "." corner(dir) 145*23f24377SWarner Losh return fields(cf-1, NF) 146*23f24377SWarner Losh} 147*23f24377SWarner Losh 148*23f24377SWarner Loshfunction bracket( t) { 149*23f24377SWarner Losh printf("]\n") 150*23f24377SWarner Losh if ($2 == ")") 151*23f24377SWarner Losh t = "spline" 152*23f24377SWarner Losh else 153*23f24377SWarner Losh t = "line" 154*23f24377SWarner Losh printf("%s from last [].sw+(%g,0) to last [].sw to last [].nw to last [].nw+(%g,0)\n", 155*23f24377SWarner Losh t, dbrack, dbrack) 156*23f24377SWarner Losh printf("%s from last [].se-(%g,0) to last [].se to last [].ne to last [].ne-(%g,0)\n", 157*23f24377SWarner Losh t, dbrack, dbrack) 158*23f24377SWarner Losh if ($3 == "sub") 159*23f24377SWarner Losh printf("\" %s\" ljust at last [].se\n", fields(4,NF)) 160*23f24377SWarner Losh} 161*23f24377SWarner Losh 162*23f24377SWarner Loshfunction molecule( n, type) { 163*23f24377SWarner Losh n = $1 164*23f24377SWarner Losh if (n == "BP") { 165*23f24377SWarner Losh $1 = "\"\" ht 0 wid 0" 166*23f24377SWarner Losh type = OTHER 167*23f24377SWarner Losh } else { 168*23f24377SWarner Losh $1 = atom(n) 169*23f24377SWarner Losh type = MOL 170*23f24377SWarner Losh } 171*23f24377SWarner Losh gsub(/[^A-Za-z0-9]/, "", n) # for stuff like C(OH3): zap non-alnum 172*23f24377SWarner Losh if ($2 == "") 173*23f24377SWarner Losh printf "Last: %s: %s with .%s at Last.%s\n", \ 174*23f24377SWarner Losh n, $0, leave(type,dir+180), leave(last,dir) 175*23f24377SWarner Losh else if ($2 == "below") 176*23f24377SWarner Losh printf("Last: %s: %s with .n at %s.s\n", n, $1, $3) 177*23f24377SWarner Losh else if ($2 == "above") 178*23f24377SWarner Losh printf("Last: %s: %s with .s at %s.n\n", n, $1, $3) 179*23f24377SWarner Losh else if ($2 == "left" && $3 == "of") 180*23f24377SWarner Losh printf("Last: %s: %s with .e at %s.w+(%g,0)\n", n, $1, $4, dew) 181*23f24377SWarner Losh else if ($2 == "right" && $3 == "of") 182*23f24377SWarner Losh printf("Last: %s: %s with .w at %s.e-(%g,0)\n", n, $1, $4, dew) 183*23f24377SWarner Losh else 184*23f24377SWarner Losh printf "Last: %s: %s\n", n, $0 185*23f24377SWarner Losh last = type 186*23f24377SWarner Losh if (lastname != "") 187*23f24377SWarner Losh labsave(lastname, last, dir) 188*23f24377SWarner Losh labsave(n, last, dir) 189*23f24377SWarner Losh} 190*23f24377SWarner Losh 191*23f24377SWarner Loshfunction label( i, v) { 192*23f24377SWarner Losh if (substr(labtype[$2], 1, 1) != RING) 193*23f24377SWarner Losh error(sprintf("%s is not a ring", $2)) 194*23f24377SWarner Losh else { 195*23f24377SWarner Losh v = substr(labtype[$2], 2, 1) 196*23f24377SWarner Losh for (i = 1; i <= v; i++) 197*23f24377SWarner Losh printf("\"\\s-3%d\\s0\" at 0.%d<%s.C,%s.V%d>\n", i, v+2, $2, $2, i) 198*23f24377SWarner Losh } 199*23f24377SWarner Losh} 200*23f24377SWarner Losh 201*23f24377SWarner Loshfunction ring(type, typeint, pt, verts, i) { 202*23f24377SWarner Losh pt = 0 # points up by default 203*23f24377SWarner Losh if (type ~ /[1-8]$/) 204*23f24377SWarner Losh verts = substr(type, length(type), 1) 205*23f24377SWarner Losh else if (type ~ /flat/) 206*23f24377SWarner Losh verts = 5 207*23f24377SWarner Losh else 208*23f24377SWarner Losh verts = 6 209*23f24377SWarner Losh fused = other = "" 210*23f24377SWarner Losh for (i = 1; i <= verts; i++) 211*23f24377SWarner Losh put[i] = dbl[i] = "" 212*23f24377SWarner Losh nput = aromatic = withat = 0 213*23f24377SWarner Losh for (cf = 2; cf <= NF; ) { 214*23f24377SWarner Losh if ($cf == "pointing") 215*23f24377SWarner Losh pt = cvtdir(0) 216*23f24377SWarner Losh else if ($cf == "double" || $cf == "triple") 217*23f24377SWarner Losh dblring(verts) 218*23f24377SWarner Losh else if ($cf ~ /arom/) { 219*23f24377SWarner Losh aromatic++ 220*23f24377SWarner Losh cf++ # handled later 221*23f24377SWarner Losh } else if ($cf == "put") { 222*23f24377SWarner Losh putring(verts) 223*23f24377SWarner Losh nput++ 224*23f24377SWarner Losh } else if ($cf ~ /^#/) { 225*23f24377SWarner Losh cf = NF+1 226*23f24377SWarner Losh break; 227*23f24377SWarner Losh } else { 228*23f24377SWarner Losh if ($cf == "with" || $cf == "at") 229*23f24377SWarner Losh withat = 1 230*23f24377SWarner Losh other = other " " $cf 231*23f24377SWarner Losh cf++ 232*23f24377SWarner Losh } 233*23f24377SWarner Losh } 234*23f24377SWarner Losh typeint = RING verts pt # RING | verts | dir 235*23f24377SWarner Losh if (withat == 0) 236*23f24377SWarner Losh fused = joinring(typeint, dir, last) 237*23f24377SWarner Losh printf "Last: [\n" 238*23f24377SWarner Losh makering(type, pt, verts) 239*23f24377SWarner Losh printf "] %s %s\n", fused, other 240*23f24377SWarner Losh last = typeint 241*23f24377SWarner Losh if (lastname != "") 242*23f24377SWarner Losh labsave(lastname, last, dir) 243*23f24377SWarner Losh} 244*23f24377SWarner Losh 245*23f24377SWarner Loshfunction makering(type, pt, v, i, a, r) { 246*23f24377SWarner Losh if (type ~ /flat/) 247*23f24377SWarner Losh v = 6 248*23f24377SWarner Losh # vertices 249*23f24377SWarner Losh r = ringside / (2 * sin(pi/v)) 250*23f24377SWarner Losh printf "\tC: 0,0\n" 251*23f24377SWarner Losh for (i = 0; i <= v+1; i++) { 252*23f24377SWarner Losh a = ((i-1) / v * 360 + pt) / deg 253*23f24377SWarner Losh printf "\tV%d: (%g,%g)\n", i, r * sin(a), r * cos(a) 254*23f24377SWarner Losh } 255*23f24377SWarner Losh if (type ~ /flat/) { 256*23f24377SWarner Losh printf "\tV4: V5; V5: V6\n" 257*23f24377SWarner Losh v = 5 258*23f24377SWarner Losh } 259*23f24377SWarner Losh # sides 260*23f24377SWarner Losh if (nput > 0) { # hetero ... 261*23f24377SWarner Losh for (i = 1; i <= v; i++) { 262*23f24377SWarner Losh c1 = c2 = 0 263*23f24377SWarner Losh if (put[i] != "") { 264*23f24377SWarner Losh printf("\tV%d: ellipse invis ht %g wid %g at V%d\n", 265*23f24377SWarner Losh i, crh, crw, i) 266*23f24377SWarner Losh printf("\t%s at V%d\n", put[i], i) 267*23f24377SWarner Losh c1 = cr 268*23f24377SWarner Losh } 269*23f24377SWarner Losh j = i+1 270*23f24377SWarner Losh if (j > v) 271*23f24377SWarner Losh j = 1 272*23f24377SWarner Losh if (put[j] != "") 273*23f24377SWarner Losh c2 = cr 274*23f24377SWarner Losh printf "\tline from V%d to V%d chop %g chop %g\n", i, j, c1, c2 275*23f24377SWarner Losh if (dbl[i] != "") { # should check i<j 276*23f24377SWarner Losh if (type ~ /flat/ && i == 3) { 277*23f24377SWarner Losh rat = 0.75; fix = 5 278*23f24377SWarner Losh } else { 279*23f24377SWarner Losh rat = 0.85; fix = 1.5 280*23f24377SWarner Losh } 281*23f24377SWarner Losh if (put[i] == "") 282*23f24377SWarner Losh c1 = 0 283*23f24377SWarner Losh else 284*23f24377SWarner Losh c1 = cr/fix 285*23f24377SWarner Losh if (put[j] == "") 286*23f24377SWarner Losh c2 = 0 287*23f24377SWarner Losh else 288*23f24377SWarner Losh c2 = cr/fix 289*23f24377SWarner Losh printf "\tline from %g<C,V%d> to %g<C,V%d> chop %g chop %g\n", 290*23f24377SWarner Losh rat, i, rat, j, c1, c2 291*23f24377SWarner Losh if (dbl[i] == "triple") 292*23f24377SWarner Losh printf "\tline from %g<C,V%d> to %g<C,V%d> chop %g chop %g\n", 293*23f24377SWarner Losh 2-rat, i, 2-rat, j, c1, c2 294*23f24377SWarner Losh } 295*23f24377SWarner Losh } 296*23f24377SWarner Losh } else { # regular 297*23f24377SWarner Losh for (i = 1; i <= v; i++) { 298*23f24377SWarner Losh j = i+1 299*23f24377SWarner Losh if (j > v) 300*23f24377SWarner Losh j = 1 301*23f24377SWarner Losh printf "\tline from V%d to V%d\n", i, j 302*23f24377SWarner Losh if (dbl[i] != "") { # should check i<j 303*23f24377SWarner Losh if (type ~ /flat/ && i == 3) { 304*23f24377SWarner Losh rat = 0.75 305*23f24377SWarner Losh } else 306*23f24377SWarner Losh rat = 0.85 307*23f24377SWarner Losh printf "\tline from %g<C,V%d> to %g<C,V%d>\n", 308*23f24377SWarner Losh rat, i, rat, j 309*23f24377SWarner Losh if (dbl[i] == "triple") 310*23f24377SWarner Losh printf "\tline from %g<C,V%d> to %g<C,V%d>\n", 311*23f24377SWarner Losh 2-rat, i, 2-rat, j 312*23f24377SWarner Losh } 313*23f24377SWarner Losh } 314*23f24377SWarner Losh } 315*23f24377SWarner Losh # punt on triple temporarily 316*23f24377SWarner Losh # circle 317*23f24377SWarner Losh if (type ~ /benz/ || aromatic > 0) { 318*23f24377SWarner Losh if (type ~ /flat/) 319*23f24377SWarner Losh r *= .4 320*23f24377SWarner Losh else 321*23f24377SWarner Losh r *= .5 322*23f24377SWarner Losh printf "\tcircle rad %g at 0,0\n", r 323*23f24377SWarner Losh } 324*23f24377SWarner Losh} 325*23f24377SWarner Losh 326*23f24377SWarner Loshfunction putring(v) { # collect "put Mol at n" 327*23f24377SWarner Losh cf++ 328*23f24377SWarner Losh mol = $(cf++) 329*23f24377SWarner Losh if ($cf == "at") 330*23f24377SWarner Losh cf++ 331*23f24377SWarner Losh if ($cf >= 1 && $cf <= v) { 332*23f24377SWarner Losh m = mol 333*23f24377SWarner Losh gsub(/[^A-Za-z0-9]/, "", m) 334*23f24377SWarner Losh put[$cf] = m ":" atom(mol) 335*23f24377SWarner Losh } 336*23f24377SWarner Losh cf++ 337*23f24377SWarner Losh} 338*23f24377SWarner Losh 339*23f24377SWarner Loshfunction joinring(type, dir, last) { # join a ring to something 340*23f24377SWarner Losh if (substr(last, 1, 1) == RING) { # ring to ring 341*23f24377SWarner Losh if (substr(type, 3) == substr(last, 3)) # fails if not 6-sided 342*23f24377SWarner Losh return "with .V6 at Last.V2" 343*23f24377SWarner Losh } 344*23f24377SWarner Losh # if all else fails 345*23f24377SWarner Losh return sprintf("with .%s at Last.%s", \ 346*23f24377SWarner Losh leave(type,dir+180), leave(last,dir)) 347*23f24377SWarner Losh} 348*23f24377SWarner Losh 349*23f24377SWarner Loshfunction leave(last, d, c, c1) { # return vertex of last in dir d 350*23f24377SWarner Losh if (last == BOND) 351*23f24377SWarner Losh return "end" 352*23f24377SWarner Losh d = reduce(d) 353*23f24377SWarner Losh if (substr(last, 1, 1) == RING) 354*23f24377SWarner Losh return ringleave(last, d) 355*23f24377SWarner Losh if (last == MOL) { 356*23f24377SWarner Losh if (d == 0 || d == 180) 357*23f24377SWarner Losh c = "C" 358*23f24377SWarner Losh else if (d > 0 && d < 180) 359*23f24377SWarner Losh c = "R" 360*23f24377SWarner Losh else 361*23f24377SWarner Losh c = "L" 362*23f24377SWarner Losh if (d in dc) 363*23f24377SWarner Losh c1 = dc[d] 364*23f24377SWarner Losh else 365*23f24377SWarner Losh c1 = corner(d) 366*23f24377SWarner Losh return sprintf("%s.%s", c, c1) 367*23f24377SWarner Losh } 368*23f24377SWarner Losh if (last == OTHER) 369*23f24377SWarner Losh return corner(d) 370*23f24377SWarner Losh return "c" 371*23f24377SWarner Losh} 372*23f24377SWarner Losh 373*23f24377SWarner Loshfunction ringleave(last, d, rd, verts) { # return vertex of ring in dir d 374*23f24377SWarner Losh verts = substr(last, 2, 1) 375*23f24377SWarner Losh rd = substr(last, 3) 376*23f24377SWarner Losh return sprintf("V%d.%s", int(reduce(d-rd)/(360/verts)) + 1, corner(d)) 377*23f24377SWarner Losh} 378*23f24377SWarner Losh 379*23f24377SWarner Loshfunction corner(dir) { 380*23f24377SWarner Losh return dc[reduce(45 * int((dir+22.5)/45))] 381*23f24377SWarner Losh} 382*23f24377SWarner Losh 383*23f24377SWarner Loshfunction labsave(name, type, dir) { 384*23f24377SWarner Losh labtype[name] = type 385*23f24377SWarner Losh labdir[name] = dir 386*23f24377SWarner Losh} 387*23f24377SWarner Losh 388*23f24377SWarner Loshfunction dblring(v, d, v1, v2) { # should canonicalize to i,i+1 mod v 389*23f24377SWarner Losh d = $cf 390*23f24377SWarner Losh for (cf++; $cf ~ /^[1-9]/; cf++) { 391*23f24377SWarner Losh v1 = substr($cf,1,1) 392*23f24377SWarner Losh v2 = substr($cf,3,1) 393*23f24377SWarner Losh if (v2 == v1+1 || v1 == v && v2 == 1) # e.g., 2,3 or 5,1 394*23f24377SWarner Losh dbl[v1] = d 395*23f24377SWarner Losh else if (v1 == v2+1 || v2 == v && v1 == 1) # e.g., 3,2 or 1,5 396*23f24377SWarner Losh dbl[v2] = d 397*23f24377SWarner Losh else 398*23f24377SWarner Losh error(sprintf("weird %s bond in\n\t%s", d, $0)) 399*23f24377SWarner Losh } 400*23f24377SWarner Losh} 401*23f24377SWarner Losh 402*23f24377SWarner Loshfunction cvtdir(d) { # maps "[pointing] somewhere" to degrees 403*23f24377SWarner Losh if ($cf == "pointing") 404*23f24377SWarner Losh cf++ 405*23f24377SWarner Losh if ($cf ~ /^[+\-]?[0-9]+/) 406*23f24377SWarner Losh return reduce($(cf++)) 407*23f24377SWarner Losh else if ($cf ~ /left|right|up|down|ne|nw|se|sw/) 408*23f24377SWarner Losh return reduce(dc[$(cf++)]) 409*23f24377SWarner Losh else { 410*23f24377SWarner Losh cf++ 411*23f24377SWarner Losh return d 412*23f24377SWarner Losh } 413*23f24377SWarner Losh} 414*23f24377SWarner Losh 415*23f24377SWarner Loshfunction reduce(d) { # reduces d to 0 <= d < 360 416*23f24377SWarner Losh while (d >= 360) 417*23f24377SWarner Losh d -= 360 418*23f24377SWarner Losh while (d < 0) 419*23f24377SWarner Losh d += 360 420*23f24377SWarner Losh return d 421*23f24377SWarner Losh} 422*23f24377SWarner Losh 423*23f24377SWarner Loshfunction atom(s, c, i, n, nsub, cloc, nsubc) { # convert CH3 to atom(...) 424*23f24377SWarner Losh if (s == "\"\"") 425*23f24377SWarner Losh return s 426*23f24377SWarner Losh n = length(s) 427*23f24377SWarner Losh nsub = nsubc = 0 428*23f24377SWarner Losh cloc = index(s, "C") 429*23f24377SWarner Losh if (cloc == 0) 430*23f24377SWarner Losh cloc = 1 431*23f24377SWarner Losh for (i = 1; i <= n; i++) 432*23f24377SWarner Losh if (substr(s, i, 1) !~ /[A-Z]/) { 433*23f24377SWarner Losh nsub++ 434*23f24377SWarner Losh if (i < cloc) 435*23f24377SWarner Losh nsubc++ 436*23f24377SWarner Losh } 437*23f24377SWarner Losh gsub(/([0-9]+\.[0-9]+)|([0-9]+)/, "\\s-3\\d&\\u\\s+3", s) 438*23f24377SWarner Losh if (s ~ /([^0-9]\.)|(\.[^0-9])/) # centered dot 439*23f24377SWarner Losh gsub(/\./, "\\v#-.3m#.\\v#.3m#", s) 440*23f24377SWarner Losh return sprintf("atom(\"%s\", %g, %g, %g, %g, %g, %g)", 441*23f24377SWarner Losh s, (n-nsub/2)*cwid, textht, (cloc-nsubc/2-0.5)*cwid, crh, crw, dav) 442*23f24377SWarner Losh} 443*23f24377SWarner Losh 444*23f24377SWarner Loshfunction in_line( i, n, s, s1, os) { 445*23f24377SWarner Losh s = $0 446*23f24377SWarner Losh os = "" 447*23f24377SWarner Losh while ((n = match(s, /!?[A-Z][A-Za-z]*(([0-9]+\.[0-9]+)|([0-9]+))/)) > 0) { 448*23f24377SWarner Losh os = os substr(s, 1, n-1) # prefix 449*23f24377SWarner Losh s1 = substr(s, n, RLENGTH) # molecule 450*23f24377SWarner Losh if (substr(s1, 1, 1) == "!") { # !mol => leave alone 451*23f24377SWarner Losh s1 = substr(s1, 2) 452*23f24377SWarner Losh } else { 453*23f24377SWarner Losh gsub(/([0-9]+\.[0-9]+)|([0-9]+)/, "\\s-3\\d&\\u\\s+3", s1) 454*23f24377SWarner Losh if (s1 ~ /([^0-9]\.)|(\.[^0-9])/) # centered dot 455*23f24377SWarner Losh gsub(/\./, "\\v#-.3m#.\\v#.3m#", s1) 456*23f24377SWarner Losh } 457*23f24377SWarner Losh os = os s1 458*23f24377SWarner Losh s = substr(s, n + RLENGTH) # tail 459*23f24377SWarner Losh } 460*23f24377SWarner Losh os = os s 461*23f24377SWarner Losh print os 462*23f24377SWarner Losh return 463*23f24377SWarner Losh} 464*23f24377SWarner Losh 465*23f24377SWarner Loshfunction shiftfields(n, i) { # move $n+1..$NF to $n..$NF-1, zap $NF 466*23f24377SWarner Losh for (i = n; i < NF; i++) 467*23f24377SWarner Losh $i = $(i+1) 468*23f24377SWarner Losh $NF = "" 469*23f24377SWarner Losh NF-- 470*23f24377SWarner Losh} 471*23f24377SWarner Losh 472*23f24377SWarner Loshfunction fields(n1, n2, i, s) { 473*23f24377SWarner Losh if (n1 > n2) 474*23f24377SWarner Losh return "" 475*23f24377SWarner Losh s = "" 476*23f24377SWarner Losh for (i = n1; i <= n2; i++) { 477*23f24377SWarner Losh if ($i ~ /^#/) 478*23f24377SWarner Losh break; 479*23f24377SWarner Losh s = s $i " " 480*23f24377SWarner Losh } 481*23f24377SWarner Losh return s 482*23f24377SWarner Losh} 483*23f24377SWarner Losh 484*23f24377SWarner Loshfunction set(a, s, i, n, q) { 485*23f24377SWarner Losh n = split(s, q) 486*23f24377SWarner Losh for (i = 1; i <= n; i += 2) 487*23f24377SWarner Losh a[q[i]] = q[i+1] 488*23f24377SWarner Losh} 489*23f24377SWarner Losh 490*23f24377SWarner Loshfunction error(s) { 491*23f24377SWarner Losh printf "chem\007: error on line %d: %s\n", lineno, s | "cat 1>&2" 492*23f24377SWarner Losh} 493