Hello.
I am writing a simple awk script powered by a shell script. It is
called eg, which stands for equation grapher, and it graphs
mathematical equations like on a graphing calculator. It works
perfectly on Mac OS X (Google "grap" and you'll find an open-source
version).
So I decided to send it to Plan 9 for testing, since Plan 9 already
has grap. It doesn't work. What gives?
grap was giving me this funky error message saying that its "new"
statement was followed by a newline, and that it didn't like that.
The documentation allows "new" to have no arguments. Huh?
Here is some sample input:
.EG
y = x
.EE
.EG
# The letters x and y must each be one word for correct scanning
x < 2 * sin( y )
.EE
.EG
polar
r = sin( t / 180 )
.EE
== begin eg ==
# eg: equation grapher
# by pietro gagliardi
# started october 24, 2007
# completed ?
# usage: eg files...
# produces grap output, so use as so:
# eg file | grap | pic | troff
awk '
BEGIN {
in_it = 0
xmin = xmax = ymin = ymax = 0
fwid = fht = lower = upper = step = 0
showxaxis = showyaxis = showxticks = showyticks = 0
showxlabel = showylabel = showgrid = 0
complex = polar = start_drawing = i = 0
pi = "3.14159265358979323846264338327950288"
negpi = "-" pi
twopi = "6.28318530717958647692528676655900576"
# The value of 2*pi was calculated with GNU bc version 1.06
# running on Mac OS X 10.4.10 on a Core 2 Duo iMac. At the time,
# my C double type did not have the precision to get a value to
# check my hand-calculated values, so I used bc instead of PG hoc.
# I do not know how it gets such values! One day I will find a
# machine where double can hold more than 15 digits. Thanks,
# scale variable of bc!
}
# .EG - begin graph
$1 == ".EG" || ($1 == "." && $2 == "EG") {
in_it = 1
set_defaults()
printf ".G1"
for (x = 2; x <= NF; x++)
printf " %s", $x
printf "\n"
next
}
# .EE - end graph
# only counts while in graph
in_it && ($1 == ".EE" || ($1 == "." && $2 == "EG")) {
finish_it()
printf ".G2\n"
in_it = 0
next
}
# not in it - print
!in_it { print; next }
# From here on in, we assume we are in it
# # stuff - comment
$1 ~ /^\#/ { next }
# . followed by whatever is copied verbatim
$1 ~ /^\./ {
start_drawing = 1
code[i] = "literal"
eqn[i] = $0
i++
next
}
# grap <stuff> - print verbatim, without grap
$1 == "grap" {
start_drawing = 1
s = ""
for (x = 2; x <= NF; x++)
s = s " " $x
mode[i] = "literal"
eqn[i] = s
i++
next
}
# pic <stuff> - print verbatim too (also sent to grap)
$1 == "pic" {
start_drawing = 1
mode[i] = "literal"
eqn[i] = $0
i++
next
}
# frame <height> <width> - set frame size
$1 == "frame" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
fht = $2
fwid = $3
next
}
# window <xmin> <xmax> <ymin> <ymin> - set coordinates
$1 == "window" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
xmin = lower = $2
xmax = upper = $3
ymin = lower = $4
ymax = upper = $5
next
}
# step (<lower> <upper>|[-]polar) [<step>] - control drawing
$1 == "step" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
if ($2 == "polar") {
lower = 0
upper = twopi
if (NF > 2)
step = $3
else
step = .01
} else if ($2 == "-polar") {
lower = negpi
upper = pi
if (NF > 2)
step = $3
else
step = .01
} else {
lower = $2
upper = $3
if (NF >= 4)
step = $4
else
step = .01
}
next
}
# grid (on|off) - control grid
$1 == "grid" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
showgrid = ($2 == "on") || (NF == 1)
next
}
# axes ([xXyYrRtT]|on|off) - control axes
$1 == "axes" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
if (($2 == "on") || (NF == 1))
showxaxis = showyaxis = showxlabel = showylabel = showxticks =
showyticks = 1
else if ($2 == "off")
showxaxis = showyaxis = showxlabel = showylabel = showxticks =
showyticks = 0
else {
showxaxis = showxlabel = showxticks = ($2 ~ /[xXrR]/)
showyaxis = showylabel = showyticks = ($2 ~ /[yYtT]/)
}
next
}
# ticks ([xXyYrRtT]|on|off) - control ticks
$1 == "ticks" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
if (($2 == "on") || (NF == 1))
showxticks = showyticks = 1
else if ($2 == "off")
showxticks = showyticks = 0
else {
showxticks = ($2 ~ /[xXrR]/)
showyticks = ($2 ~ /[yYtT]/)
}
next
}
# axislabel ([xXyYrRtT]|on|off) - control labels on axes
$1 == "axislabel" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
if (($2 == "on") || (NF == 1))
showxlabel = showylabel = 1
else if ($2 == "off")
showxlabel = showylabel = 0
else {
showxlabel = ($2 ~ /[xXrRtT]/)
showylabel = ($2 ~ /[yYrRtT]/)
}
next
}
# rect - set rectangular coordinates
$1 == "rect" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
polar = 0
next
}
# polar - set polar coordinates
$1 == "polar" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
polar = 1
next
}
# real - set real coordinates
$1 == "real" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
complex = 0
next
}
# complex - set complex coordinates
$1 == "complex" {
if (start_drawing) {
err("eg: control command cannot be used after draw")
next
}
complex = 1
next
}
# [xXyYrRtT] [(=|<|<=|>|>=)] equation - draw on given axis
$1 ~ /^[xXyYrRtT]$/ {
start_drawing = 1
mode[i] = tolower($1)
s = ""
start = 2
if ($2 ~ /^(=|<|>|<=|>=)$/)
start = 3
for (x = start; x <= NF; x++)
if (polar) {
if ($x ~ /^[rR]$/)
s = s " rcoord"
else if ($x ~ /^[tT]$/)
s = s " tcoord"
else
s = s " " $x
} else {
if ($x ~ /^[xXyY]$/)
s = s " xpos"
else
s = s " " $x
}
eqn[i] = s
if (start == 2)
type[i] = "="
else
type[i] = $2
i++
next
}
# empty line or line with whitespace only - ignore
NF == 0 { next }
# else error
{ err("eg: bad line: " $0) }
END {
if (in_it)
err("eg: unclosed graph at end of file")
}
# set_defaults: reset environment
function set_defaults() {
xmin = ymin = lower = -10
xmax = ymax = upper = 10
fwid = fht = 4
complex = i = 0
showxaxis = showyaxis = showxticks = showyticks = showxlabel =
showylabel = showgrid = 1
step = .01
}
# finish_it: draw the graph
function finish_it() {
printf "xmin = %s\n", xmin
printf "xmax = %s\n", xmax
printf "ymin = %s\n", ymin
printf "ymax = %s\n", ymax
printf "frame invis ht %s wid %s\n", fht, fwid
printf "coord x xmin,xmax y ymin,ymax\n"
if (showgrid) {
printf "grid bot ticks off from xmin to xmax by 1\n"
printf "grid left ticks off from ymin to ymax by 1\n"
}
if (showxaxis) {
printf "arrow solid from xmin,0 to xmax,0\n"
printf "arrow solid from xmax,0 to xmin,0\n"
}
if (showyaxis) {
printf "arrow solid from 0,ymin to 0,ymax\n"
printf "arrow solid from 0,ymax to 0,ymin\n"
}
if (showxlabel) {
xstr = "x"
if (polar)
xstr = "r"
printf "\" \\fI%s\\fP\" ljust at xmax,0\n", xstr
}
if (showylabel) {
ystr = "y"
if (polar)
ystr = "\\(*h"
if (complex)
ystr = ystr "i"
printf "\"\\fI%s\\fP\" above at 0,ymax\n", ystr
}
if (showxticks) {
printf "for xticks from (xmin + 1) to (xmax - 1) by 1 do {\n"
printf "if xticks != 0 then {\n"
printf "line solid from xticks,0 to xticks,.25\n"
printf "sprintf(\"%%g\", xticks) above at xticks,.25\n"
printf "}\n"
printf "}\n"
}
if (showyticks) {
printf "for yticks from (ymin + 1) to (ymax - 1) by 1 do {\n"
printf "if yticks != 0 then {\n"
printf "line solid from 0,yticks to .25,yticks\n"
printf "sprintf(\" %%g\", yticks) ljust at .25,yticks\n"
printf "}\n"
printf "}\n"
}
for (x = 0; x < i; x++) {
if (mode[x] == "literal")
printf "%s\n", eqn[x]
else {
if (type[x] ~ /=/)
drawmode = "solid"
else
drawmode = "dashed"
printf "new\ndraw %s\n", drawmode
printf "for xpos from %s to %s by %s do {\n", lower,
upper, step
if (!polar) {
if (mode[x] == "y") {
printf "next at xpos, (%s)\n", eqn[x]
if (type[x] ~ /</)
printf "line from (xpos, (%s)) to
(xpos, ymin)\n", eqn[x]
else if (type[x] ~ />/)
printf "line from (xpos, (%s)) to
(xpos, ymax)\n", eqn[x]
} else
printf "next at (%s), xpos\n", eqn[x]
} else {
if (mode[x] == "r")
printf "tcoord = xpos\nrcoord = %s\n",
eqn[x]
else
printf "rcoord = xpos\ntcoord = %s\n",
eqn[x]
printf "xpoint = rcoord * cos(tcoord)\n"
printf "ypoint = rcoord * sin(tcoord)\n"
printf "next at xpoint, ypoint\n"
}
printf "}\n"
}
}
}
# err: print error
function err(s) {
print s | "cat 1>&2"
}
' $*
== end of eg ==
I could attach it if necessary.