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