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