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.

Reply via email to