mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-04 02:18:37 +00:00
Adding Massif, the heap profiler.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2245
This commit is contained in:
parent
49c135649d
commit
563c4e566a
@ -9,6 +9,7 @@ SUBDIRS = include coregrind . docs tests auxprogs \
|
||||
cachegrind \
|
||||
corecheck \
|
||||
helgrind \
|
||||
massif \
|
||||
lackey \
|
||||
none
|
||||
|
||||
|
||||
10
configure.in
10
configure.in
@ -373,12 +373,16 @@ AC_OUTPUT(
|
||||
cachegrind/tests/Makefile
|
||||
cachegrind/docs/Makefile
|
||||
cachegrind/cg_annotate
|
||||
corecheck/Makefile
|
||||
corecheck/tests/Makefile
|
||||
corecheck/docs/Makefile
|
||||
helgrind/Makefile
|
||||
helgrind/tests/Makefile
|
||||
helgrind/docs/Makefile
|
||||
massif/Makefile
|
||||
massif/hp2ps/Makefile
|
||||
massif/tests/Makefile
|
||||
massif/docs/Makefile
|
||||
corecheck/Makefile
|
||||
corecheck/tests/Makefile
|
||||
corecheck/docs/Makefile
|
||||
lackey/Makefile
|
||||
lackey/tests/Makefile
|
||||
lackey/docs/Makefile
|
||||
|
||||
@ -1365,9 +1365,6 @@ extern Int VG_(vgexecfd);
|
||||
/* client executable file descriptor */
|
||||
extern Int VG_(clexecfd);
|
||||
|
||||
/* Path to all our library/aux files */
|
||||
extern const Char *VG_(libdir);
|
||||
|
||||
/* Determine if %esp adjustment must be noted */
|
||||
extern Bool VG_(need_to_handle_esp_assignment) ( void );
|
||||
|
||||
|
||||
@ -98,12 +98,15 @@ An open-source tool for debugging and profiling Linux-x86 executables.
|
||||
<h4>6 <a href="hg_main.html#hg-top">
|
||||
Helgrind: a data-race detector</a></h4>
|
||||
|
||||
<h4>7 <a href="ms_main.html#ms-top">
|
||||
Massif: a heap profiler</a></h4>
|
||||
|
||||
<p>
|
||||
The following is not part of the user manual. It describes how you can
|
||||
write tools for Valgrind, in order to make new program supervision
|
||||
tools.
|
||||
|
||||
<h4>7 <a href="coregrind_tools.html">
|
||||
<h4>8 <a href="coregrind_tools.html">
|
||||
Valgrind Tools</a></h4>
|
||||
|
||||
<p>
|
||||
@ -111,10 +114,10 @@ The following are not part of the user manual. They describe internal
|
||||
details of how Valgrind works. Reading them may rot your brain. You
|
||||
have been warned.
|
||||
|
||||
<h4>8 <a href="mc_techdocs.html#mc-techdocs">
|
||||
<h4>9 <a href="mc_techdocs.html#mc-techdocs">
|
||||
The design and implementation of Valgrind</a></h4>
|
||||
|
||||
<h4>9 <a href="cg_techdocs.html#cg-techdocs">
|
||||
<h4>10 <a href="cg_techdocs.html#cg-techdocs">
|
||||
How Cachegrind works</a></h4>
|
||||
|
||||
<hr width="100%">
|
||||
|
||||
@ -114,6 +114,10 @@ typedef unsigned char Bool;
|
||||
#include "vg_kerneliface.h"
|
||||
|
||||
|
||||
/* Path to all our library/aux files */
|
||||
extern const Char *VG_(libdir);
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== Core/skin interface version ===*/
|
||||
/*====================================================================*/
|
||||
|
||||
24
massif/Makefile.am
Normal file
24
massif/Makefile.am
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
SUBDIRS = . tests docs hp2ps
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\"
|
||||
AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
|
||||
@PREFERRED_STACK_BOUNDARY@ -g
|
||||
|
||||
valdir = $(libdir)/valgrind
|
||||
inplacedir = $(top_srcdir)/.in_place
|
||||
|
||||
val_PROGRAMS = vgskin_massif.so vgpreload_massif.so
|
||||
|
||||
vgskin_massif_so_SOURCES = ms_main.c
|
||||
vgskin_massif_so_LDFLAGS = -shared
|
||||
|
||||
vgpreload_massif_so_SOURCES =
|
||||
vgpreload_massif_so_LDADD = $(top_srcdir)/coregrind/vg_replace_malloc.o
|
||||
vgpreload_massif_so_DEPENDENCIES = $(top_srcdir)/coregrind/vg_replace_malloc.o
|
||||
vgpreload_massif_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst
|
||||
|
||||
all-local:
|
||||
mkdir -p $(inplacedir)
|
||||
-rm -f $(addprefix $(inplacedir)/,$(val_PROGRAMS))
|
||||
ln -f -s $(addprefix $(top_srcdir)/$(subdir)/,$(val_PROGRAMS)) $(inplacedir)
|
||||
5
massif/docs/Makefile.am
Normal file
5
massif/docs/Makefile.am
Normal file
@ -0,0 +1,5 @@
|
||||
docdir = $(datadir)/doc/valgrind
|
||||
|
||||
doc_DATA = ms_main.html date.gif
|
||||
|
||||
EXTRA_DIST = $(doc_DATA)
|
||||
BIN
massif/docs/date.gif
Normal file
BIN
massif/docs/date.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
331
massif/docs/ms_main.html
Normal file
331
massif/docs/ms_main.html
Normal file
@ -0,0 +1,331 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Massif: a heap profiler</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a name="ms-top"></a>
|
||||
<h2>7 <b>Massif</b>: a heap profiler</h2>
|
||||
|
||||
To use this tool, you must specify <code>--tool=massif</code>
|
||||
on the Valgrind command line.
|
||||
|
||||
<a name="spaceprof"></a>
|
||||
<h3>7.1 Heap profiling</h3>
|
||||
Massif is a heap profiler, i.e. it measures how much heap memory programs use.
|
||||
In particular, it can give you information about:
|
||||
<ul>
|
||||
<li>Heap blocks;
|
||||
<li>Heap administration blocks;
|
||||
<li>Stack sizes.
|
||||
</ul>
|
||||
|
||||
Heap profiling is useful to help you reduce the amount of memory your program
|
||||
uses. On modern machines with virtual memory, this provides the following
|
||||
benefits:
|
||||
<ul>
|
||||
<li>It can speed up your program -- a smaller program will interact better
|
||||
with your machine's caches, avoid paging, and so on.
|
||||
|
||||
<li>If your program uses lots of memory, it will reduce the chance that it
|
||||
exhausts your machine's swap space.
|
||||
</ul>
|
||||
|
||||
Also, there are certain space leaks that aren't detected by traditional
|
||||
leak-checkers, such as Memcheck's. That's because the memory isn't ever
|
||||
actually lost -- a pointer remains to it -- but it's not in use. Programs
|
||||
that have leaks like this can unnecessarily increase the amount of memory
|
||||
they are using over time.
|
||||
<p>
|
||||
|
||||
|
||||
<a name="whyuse_heapprof"></a>
|
||||
<h3>7.2 Why Use a Heap Profiler?</h3>
|
||||
|
||||
Everybody knows how useful time profilers are for speeding up programs. They
|
||||
are particularly useful because people are notoriously bad at predicting where
|
||||
are the bottlenecks in their programs.
|
||||
<p>
|
||||
But the story is different for heap profilers. Some programming languages,
|
||||
particularly lazy functional languages like <a
|
||||
href="http://www.haskell.org">Haskell</a>, have quite sophisticated heap
|
||||
profilers. But there are few tools as powerful for profiling C and C++
|
||||
programs.
|
||||
<p>
|
||||
Why is this? Maybe it's because C and C++ programmers must think that
|
||||
they know where the memory is being allocated. After all, you can see all the
|
||||
calls to <code>malloc()</code> and <code>new</code> and <code>new[]</code>,
|
||||
right? But, in a big program, do you really know which heap allocations are
|
||||
being executed, how many times, and how large each allocation is? Can you give
|
||||
even a vague estimate of the memory footprint for your program? Do you know
|
||||
this for all the libraries your program uses? What about administration bytes
|
||||
required by the heap allocator to track heap blocks -- have you thought about
|
||||
them? What about the stack? If you are unsure about any of these things,
|
||||
maybe you should think about heap profiling.
|
||||
<p>
|
||||
Massif can tell you these things.
|
||||
<p>
|
||||
Or maybe it's because it's relatively easy to add basic heap profiling
|
||||
functionality into a program, to tell you how many bytes you have allocated for
|
||||
certain objects, or similar. But this information might only be simple like
|
||||
total counts for the whole program's execution. What about space usage at
|
||||
different points in the program's execution, for example? And reimplementing
|
||||
heap profiling code for each project is a pain.
|
||||
<p>
|
||||
Massif can save you this effort.
|
||||
<p>
|
||||
|
||||
|
||||
<a name="overview"></a>
|
||||
<h3>7.3 Overview</h3>
|
||||
First off, as for normal Valgrind use, you probably want to compile with
|
||||
debugging info (the <code>-g</code> flag). But, as opposed to Memcheck,
|
||||
you probably <b>do</b> want to turn optimisation on, since you should profile
|
||||
your program as it will be normally run.
|
||||
<p>
|
||||
Then, run your program with <code>valgrind --tool=massif</code> in front of the
|
||||
normal command line invocation. When the program finishes, Massif will print
|
||||
summary space statistics. It also creates a graph representing the program's
|
||||
heap usage in a file called <code>massif.<i>pid</i>.ps</code>, which can
|
||||
be read by any PostScript viewer, such as Ghostview.
|
||||
<p>
|
||||
It also puts detailed information about heap consumption in a file file
|
||||
<code>massif.<i>pid</i>.txt</code> (text format) or
|
||||
<code>massif.<i>pid</i>.html</code> (HTML format), where
|
||||
<code><i>pid</i></code> is the program's process id.
|
||||
<p>
|
||||
|
||||
|
||||
<a name="basicresults"></a>
|
||||
<h3>7.4 Basic Results of Profiling</h3>
|
||||
|
||||
To gather heap profiling information about the program <code>prog</code>,
|
||||
type:
|
||||
<p>
|
||||
<blockquote>
|
||||
<code>valgrind --tool=massif prog</code>
|
||||
</blockquote>
|
||||
<p>
|
||||
The program will execute (slowly). Upon completion, summary statistics
|
||||
that look like this will be printed:
|
||||
|
||||
<pre>
|
||||
==27519== Total spacetime: 2,258,106 ms.B
|
||||
==27519== heap: 24.0%
|
||||
==27519== heap admin: 2.2%
|
||||
==27519== stack(s): 73.7%
|
||||
</pre>
|
||||
|
||||
All measurements are done in <i>spacetime</i>, i.e. space (in bytes) multiplied
|
||||
by time (in milliseconds). Note that because Massif slows a program down a
|
||||
lot, the actual spacetime figure is fairly meaningless; it's the relative
|
||||
values that are interesting.
|
||||
<p>
|
||||
Which entries you see in the breakdown depends on the command line options
|
||||
given. The above example measures all the possible parts of memory:
|
||||
<ul>
|
||||
<li>Heap: number of words allocated on the heap, via <code>malloc()</code>,
|
||||
<code>new</code> and <code>new[]</code>.
|
||||
<p>
|
||||
<li>Heap admin: each heap block allocated requires some administration data,
|
||||
which lets the allocator track certain things about the block. It is easy
|
||||
to forget about this, and if your program allocates lots of small blocks,
|
||||
it can add up. This value is an estimate of the space required for this
|
||||
administration data.
|
||||
<p>
|
||||
<li>Stack(s): the spacetime used by the programs' stack(s). (Threaded programs
|
||||
can have multiple stacks.) This includes signal handler stacks.
|
||||
<p>
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
|
||||
<a name="graphs"></a>
|
||||
<h3>7.5 Spacetime Graphs</h3>
|
||||
As well as printing summary information, Massif also creates a file
|
||||
representing a spacetime graph, <code>massif.<i>pid</i>.hp</code>.
|
||||
It will produce a file called <code>massif.<i>pid</i>.ps</code>, which can be
|
||||
viewed in a PostScript viewer.
|
||||
<p>
|
||||
Massif uses a program called <code>hp2ps</code> to convert the raw data into
|
||||
the PostScript graph. It's distributed with Massif, but came originally
|
||||
from the <a href="http://haskell.cs.yale.edu/ghc/">Glasgow Haskell
|
||||
Compiler</a>. You shouldn't need to worry about this at all. However, if
|
||||
the graph creation fails for any reason, Massif tell you, and will leave
|
||||
behind a file named <code>massif.<i>pid</i>.hp</code>, containing the raw
|
||||
heap profiling data.
|
||||
<p>
|
||||
Here's an example graph:<br>
|
||||
<img src="date.gif" alt="spacetime graph">
|
||||
<p>
|
||||
The graph is broken into several bands. Most bands represent a single line of
|
||||
your program that does some heap allocation; each such band represents all
|
||||
the allocations and deallocations done from that line. Up to twenty bands are
|
||||
shown; less significant allocation sites are merged into "other" and/or "OTHER"
|
||||
bands. The accompanying text/HTML file produced by Massif has more detail
|
||||
about these heap allocation bands. Then there are single bands for the
|
||||
stack(s) and heap admin bytes.
|
||||
<p>
|
||||
Note: it's the height of a band that's important. Don't let the ups and downs
|
||||
caused by other bands confuse you. For example, the
|
||||
<code>read_alias_file</code> band in the example has the same height all the
|
||||
time it's in existence.
|
||||
<p>
|
||||
The triangles on the x-axis show each point at which a memory census was taken.
|
||||
These aren't necessarily evenly spread; Massif only takes a census when
|
||||
memory is allocated or deallocated. The time on the x-axis is wallclock
|
||||
time, which is not ideal because you can get different graphs for different
|
||||
executions of the same program, due to random OS delays. But it's not too
|
||||
bad, and it becomes less of a problem the longer a program runs.
|
||||
<p>
|
||||
Massif takes censuses at an appropriate timescale; censuses take place less
|
||||
frequently as the program runs for longer. There is no point having more
|
||||
than 100-200 censuses on a single graph.
|
||||
<p>
|
||||
The graphs give a good overview of where your program's space use comes from,
|
||||
and how that varies over time. The accompanying text/HTML file gives a lot
|
||||
more information about heap use.
|
||||
|
||||
<a name="detailsofheap"></a>
|
||||
<h3>7.6 Details of Heap Allocations</h3>
|
||||
|
||||
The text/HTML file contains information to help interpret the heap bands of the
|
||||
graph. It also contains a lot of extra information about heap allocations that you don't see in the graph.
|
||||
<p>
|
||||
Here's part of the information that accompanies the above graph.
|
||||
|
||||
<hr>
|
||||
== 0 ===========================<br>
|
||||
Heap allocation functions accounted for 50.8% of measured spacetime<br>
|
||||
<p>
|
||||
Called from:
|
||||
<ul>
|
||||
<li><a name="a401767D1"></a><a href="#b401767D1">22.1%</a>: 0x401767D0: _nl_intern_locale_data (in /lib/i686/libc-2.3.2.so)
|
||||
<li><a name="a4017C394"></a><a href="#b4017C394"> 8.6%</a>: 0x4017C393: read_alias_file (in /lib/i686/libc-2.3.2.so)
|
||||
|
||||
<li><i>(several entries omitted)</i>
|
||||
|
||||
<li>and 6 other insignificant places</li>
|
||||
</ul>
|
||||
<hr>
|
||||
The first part shows the total spacetime due to heap allocations, and the
|
||||
places in the program where most memory was allocated (nb: if this program had
|
||||
been compiled with <code>-g</code>, actual line numbers would be given). These
|
||||
places are sorted, from most significant to least, and correspond to the bands
|
||||
seen in the graph. Insignificant sites (accounting for less than 0.5% of total
|
||||
spacetime) are omitted.
|
||||
<p>
|
||||
That alone can be useful, but often isn't enough. What if one of these
|
||||
functions was called from several different places in the program? Which one
|
||||
of these is responsible for most of the memory used? For
|
||||
<code>_nl_intern_locale_data()</code>, this question is answered by clicking on
|
||||
the <a href="#b401767D1">22.1%</a> link, which takes us to the following part
|
||||
of the file.
|
||||
|
||||
<hr>
|
||||
<p>== 1 ===========================<br>
|
||||
<a name="b401767D1"></a>Context accounted for <a href="#a401767D1">22.1%</a> of measured spacetime<br>
|
||||
0x401767D0: _nl_intern_locale_data (in /lib/i686/libc-2.3.2.so)<br>
|
||||
<p>
|
||||
Called from:
|
||||
<ul>
|
||||
<li><a name="a40176F96"></a><a href="#b40176F96">22.1%</a>: 0x40176F95: _nl_load_locale_from_archive (in /lib/i686/libc-2.3.2.so)
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
At this level, we can see all the places from which
|
||||
<code>_nl_load_locale_from_archive()</code> was called such that it allocated
|
||||
memory at 0x401767D0. (We can click on the top <a href="#a40176F96">22.1%</a>
|
||||
link to go back to the parent entry.) At this level, we have moved beyond the
|
||||
information presented in the graph. In this case, it is only called from one
|
||||
place. We can again follow the link for more detail, moving to the following
|
||||
part of the file.
|
||||
|
||||
<hr>
|
||||
<p>== 2 ===========================<br>
|
||||
<a name="b40176F96"></a>Context accounted for <a href="#a40176F96">22.1%</a> of measured spacetime<br>
|
||||
0x401767D0: _nl_intern_locale_data (in /lib/i686/libc-2.3.2.so)<br>
|
||||
0x40176F95: _nl_load_locale_from_archive (in /lib/i686/libc-2.3.2.so)<br>
|
||||
<p>
|
||||
Called from:
|
||||
<ul>
|
||||
<li><a name="a40176185"></a>22.1%: 0x40176184: _nl_find_locale (in /lib/i686/libc-2.3.2.so)
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
In this way we can dig deeper into the call stack, to work out exactly what
|
||||
sequence of calls led to some memory being allocated. At this point, with a
|
||||
call depth of 3, the information runs out (thus the address of the child entry,
|
||||
0x40176184, isn't a link). We could rerun the program with a greater
|
||||
<code>--depth</code> value if we wanted more information.
|
||||
<p>
|
||||
Sometimes you will get a code location like this:
|
||||
<ul>
|
||||
<li>30.8% : 0xFFFFFFFF: ???
|
||||
</ul>
|
||||
The code address isn't really 0xFFFFFFFF -- that's impossible. This is what
|
||||
Massif does when it can't work out what the real code address is.
|
||||
<p>
|
||||
Massif produces this information in a plain text file by default, or HTML with
|
||||
the <code>--format=html</code> option. The plain text version obviously
|
||||
doesn't have the links, but a similar effect can be achieved by searching on
|
||||
the code addresses. (In Vim, the '*' and '#' searches are ideal for this.)
|
||||
|
||||
|
||||
<a name="massifoptions"></a>
|
||||
<h3>7.7 Massif options</h3>
|
||||
|
||||
Massif-specific options are:
|
||||
|
||||
<ul>
|
||||
<li><code>--heap=no</code><br>
|
||||
<code>--heap=yes</code> [default]<br>
|
||||
When enabled, profile heap usage in detail. Without it, the
|
||||
<code>massif.<i>pid</i>.txt</code> or
|
||||
<code>massif.<i>pid</i>.html</code> will be very short.
|
||||
<p>
|
||||
<li><code>--heap-admin=<i>n</i></code> [default: 8]<br>
|
||||
The number of admin bytes per block to use. This can only be an
|
||||
estimate of the average, since it may vary. The allocator used by
|
||||
<code>glibc</code> requires somewhere between 4--15 bytes per block,
|
||||
depending on various factors. It also requires admin space for freed
|
||||
blocks, although Massif does not count this.
|
||||
<p>
|
||||
<li><code>--stacks=no</code><br>
|
||||
<code>--stacks=yes</code> [default]<br>
|
||||
When enabled, include stack(s) in the profile. Threaded programs can
|
||||
have multiple stacks.
|
||||
<p>
|
||||
<li><code>--depth=<i>n</i></code> [default: 3]<br>
|
||||
Depth of call chains to present in the detailed heap information.
|
||||
Increasing it will give more information, but Massif will run the program
|
||||
more slowly, using more memory, and produce a bigger
|
||||
<code>.txt</code>/<code>.hp</code> file.
|
||||
<p>
|
||||
<li><code>--alloc-fn=<i>name</i></code><br>
|
||||
Specify a function that allocates memory. This is useful for functions
|
||||
that are wrappers to <code>malloc()</code>, which can fill up the context
|
||||
information uselessly (and give very uninformative bands on the graph).
|
||||
Functions specified will be ignored in contexts, i.e. treated as though
|
||||
they were <code>malloc()</code>. This option can be specified multiple
|
||||
times on the command line, to name multiple functions.
|
||||
<p>
|
||||
<li><code>--format=text</code> [default]<br>
|
||||
<code>--format=html</code><br>
|
||||
Produce the detailed heap information in text or HTML format. The file
|
||||
suffix used will be either <code>.txt</code> or <code>.html</code>.
|
||||
<p>
|
||||
</ul>
|
||||
|
||||
<a name="accuracy"></a>
|
||||
<h3>7.8 Accuracy</h3>
|
||||
The information should be pretty accurate. Some approximations made might
|
||||
cause some allocation contexts to be attributed with less memory than they
|
||||
actually allocated, but the amounts should be miniscule.
|
||||
<p>
|
||||
The heap admin spacetime figure is an approximation, as described above. If
|
||||
anyone knows how to improve its accuracy, please let us know.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
63
massif/hp2ps/AreaBelow.c
Normal file
63
massif/hp2ps/AreaBelow.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "AreaBelow.h"
|
||||
|
||||
extern void free();
|
||||
|
||||
/*
|
||||
* Return the area enclosed by all of the curves. The algorithm
|
||||
* used is the same as the trapizoidal rule for integration.
|
||||
*/
|
||||
|
||||
floatish
|
||||
AreaBelow()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
intish bucket;
|
||||
floatish value;
|
||||
struct chunk *ch;
|
||||
floatish area;
|
||||
floatish trap;
|
||||
floatish base;
|
||||
floatish *maxima;
|
||||
|
||||
maxima = (floatish *) xmalloc(nsamples * sizeof(floatish));
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
maxima[i] = 0.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
bucket = ch->d[j].bucket;
|
||||
value = ch->d[j].value;
|
||||
if (bucket >= nsamples)
|
||||
Disaster("bucket out of range");
|
||||
maxima[ bucket ] += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
area = 0.0;
|
||||
|
||||
for (i = 1; i < nsamples; i++) {
|
||||
base = samplemap[i] - samplemap[i-1];
|
||||
if (maxima[i] > maxima[i-1]) {
|
||||
trap = base * maxima[i-1] + ((base * (maxima[i] - maxima[i-1]))/ 2.0);
|
||||
} else {
|
||||
trap = base * maxima[i] + ((base * (maxima[i-1] - maxima[i]))/ 2.0);
|
||||
}
|
||||
|
||||
area += trap;
|
||||
}
|
||||
|
||||
free(maxima);
|
||||
return area;
|
||||
}
|
||||
6
massif/hp2ps/AreaBelow.h
Normal file
6
massif/hp2ps/AreaBelow.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef AREA_BELOW_H
|
||||
#define AREA_BELOW_H
|
||||
|
||||
floatish AreaBelow PROTO((void));
|
||||
|
||||
#endif /* AREA_BELOW_H */
|
||||
168
massif/hp2ps/AuxFile.c
Normal file
168
massif/hp2ps/AuxFile.c
Normal file
@ -0,0 +1,168 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Shade.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Reorder.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "AuxFile.h"
|
||||
|
||||
static void GetAuxLine PROTO((FILE *)); /* forward */
|
||||
static void GetAuxTok PROTO((FILE *)); /* forward */
|
||||
|
||||
void
|
||||
GetAuxFile(auxfp)
|
||||
FILE* auxfp;
|
||||
{
|
||||
g_ch = ' ';
|
||||
endfile = 0;
|
||||
linenum = 1;
|
||||
|
||||
GetAuxTok(auxfp);
|
||||
|
||||
while (endfile == 0) {
|
||||
GetAuxLine(auxfp);
|
||||
}
|
||||
|
||||
fclose(auxfp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read the next line from the aux file, check the syntax, and
|
||||
* perform the appropriate action.
|
||||
*/
|
||||
|
||||
static void
|
||||
GetAuxLine(auxfp)
|
||||
FILE* auxfp;
|
||||
{
|
||||
switch (thetok) {
|
||||
case X_RANGE_TOK:
|
||||
GetAuxTok(auxfp);
|
||||
if (thetok != FLOAT_TOK) {
|
||||
Error("%s, line %d, floating point number must follow X_RANGE",
|
||||
auxfile, linenum);
|
||||
}
|
||||
auxxrange = thefloatish;
|
||||
GetAuxTok(auxfp);
|
||||
break;
|
||||
case Y_RANGE_TOK:
|
||||
GetAuxTok(auxfp);
|
||||
if (thetok != FLOAT_TOK) {
|
||||
Error("%s, line %d, floating point number must follow Y_RANGE",
|
||||
auxfile, linenum);
|
||||
}
|
||||
auxyrange = thefloatish;
|
||||
GetAuxTok(auxfp);
|
||||
break;
|
||||
case ORDER_TOK:
|
||||
GetAuxTok(auxfp);
|
||||
if (thetok != IDENTIFIER_TOK) {
|
||||
Error("%s, line %d: identifier must follow ORDER",
|
||||
auxfile, linenum);
|
||||
}
|
||||
GetAuxTok(auxfp);
|
||||
if (thetok != INTEGER_TOK) {
|
||||
Error("%s, line %d: identifier and integer must follow ORDER",
|
||||
auxfile, linenum);
|
||||
}
|
||||
OrderFor(theident, theinteger);
|
||||
GetAuxTok(auxfp);
|
||||
break;
|
||||
case SHADE_TOK:
|
||||
GetAuxTok(auxfp);
|
||||
if (thetok != IDENTIFIER_TOK) {
|
||||
Error("%s, line %d: identifier must follow SHADE",
|
||||
auxfile, linenum);
|
||||
}
|
||||
GetAuxTok(auxfp);
|
||||
if (thetok != FLOAT_TOK) {
|
||||
Error("%s, line %d: identifier and floating point number must follow SHADE",
|
||||
auxfile, linenum);
|
||||
}
|
||||
ShadeFor(theident, thefloatish);
|
||||
GetAuxTok(auxfp);
|
||||
break;
|
||||
case EOF_TOK:
|
||||
endfile = 1;
|
||||
break;
|
||||
default:
|
||||
Error("%s, line %d: %s unexpected", auxfile, linenum,
|
||||
TokenToString(thetok));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Read the next token from the input and assign its value
|
||||
* to the global variable "thetok". In the case of numbers,
|
||||
* the corresponding value is also assigned to "thefloatish";
|
||||
* in the case of identifiers it is assigned to "theident".
|
||||
*/
|
||||
|
||||
static void GetAuxTok(auxfp)
|
||||
FILE* auxfp;
|
||||
{
|
||||
|
||||
while (isspace(g_ch)) { /* skip whitespace */
|
||||
if (g_ch == '\n') linenum++;
|
||||
g_ch = getc(auxfp);
|
||||
}
|
||||
|
||||
if (g_ch == EOF) {
|
||||
thetok = EOF_TOK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isdigit(g_ch)) {
|
||||
thetok = GetNumber(auxfp);
|
||||
return;
|
||||
} else if (IsIdChar(g_ch)) { /* g_ch can't be a digit here */
|
||||
GetIdent(auxfp);
|
||||
if (!isupper(theident[0])) {
|
||||
thetok = IDENTIFIER_TOK;
|
||||
} else if (strcmp(theident, "X_RANGE") == 0) {
|
||||
thetok = X_RANGE_TOK;
|
||||
} else if (strcmp(theident, "Y_RANGE") == 0) {
|
||||
thetok = Y_RANGE_TOK;
|
||||
} else if (strcmp(theident, "ORDER") == 0) {
|
||||
thetok = ORDER_TOK;
|
||||
} else if (strcmp(theident, "SHADE") == 0) {
|
||||
thetok = SHADE_TOK;
|
||||
} else {
|
||||
thetok = IDENTIFIER_TOK;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
Error("%s, line %d: strange character (%c)", auxfile, linenum, g_ch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PutAuxFile(auxfp)
|
||||
FILE* auxfp;
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(auxfp, "X_RANGE %.2f\n", xrange);
|
||||
fprintf(auxfp, "Y_RANGE %.2f\n", yrange);
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
fprintf(auxfp, "ORDER %s %d\n", identtable[i]->name, i+1);
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
fprintf(auxfp, "SHADE %s %.2f\n", identtable[i]->name,
|
||||
ShadeOf(identtable[i]->name));
|
||||
}
|
||||
|
||||
fclose(auxfp);
|
||||
}
|
||||
7
massif/hp2ps/AuxFile.h
Normal file
7
massif/hp2ps/AuxFile.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef AUX_FILE_H
|
||||
#define AUX_FILE_H
|
||||
|
||||
void PutAuxFile PROTO((FILE *));
|
||||
void GetAuxFile PROTO((FILE *));
|
||||
|
||||
#endif /* AUX_FILE_H */
|
||||
241
massif/hp2ps/Axes.c
Normal file
241
massif/hp2ps/Axes.c
Normal file
@ -0,0 +1,241 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Curves.h"
|
||||
#include "Defines.h"
|
||||
#include "Dimensions.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Axes.h"
|
||||
|
||||
typedef enum {MEGABYTE, KILOBYTE, BYTE} mkb;
|
||||
|
||||
static void XAxis PROTO((void)); /* forward */
|
||||
static void YAxis PROTO((void)); /* forward */
|
||||
|
||||
static void XAxisMark PROTO((floatish, floatish)); /* forward */
|
||||
static void YAxisMark PROTO((floatish, floatish, mkb)); /* forward */
|
||||
|
||||
static floatish Round PROTO((floatish)); /* forward */
|
||||
|
||||
void
|
||||
Axes()
|
||||
{
|
||||
XAxis();
|
||||
YAxis();
|
||||
}
|
||||
|
||||
static void
|
||||
XAxisMark(x, num)
|
||||
floatish x; floatish num;
|
||||
{
|
||||
/* calibration mark */
|
||||
fprintf(psfp, "%f %f moveto\n", xpage(x), ypage(0.0));
|
||||
fprintf(psfp, "0 -4 rlineto\n");
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
/* number */
|
||||
fprintf(psfp, "HE%d setfont\n", NORMAL_FONT);
|
||||
fprintf(psfp, "(%.1f)\n", num);
|
||||
fprintf(psfp, "dup stringwidth pop\n");
|
||||
fprintf(psfp, "2 div\n");
|
||||
fprintf(psfp, "%f exch sub\n", xpage(x));
|
||||
fprintf(psfp, "%f moveto\n", borderspace);
|
||||
fprintf(psfp, "show\n");
|
||||
}
|
||||
|
||||
|
||||
#define N_X_MARKS 7
|
||||
#define XFUDGE 15
|
||||
|
||||
extern floatish xrange;
|
||||
extern char *sampleunitstring;
|
||||
|
||||
static void
|
||||
XAxis()
|
||||
{
|
||||
floatish increment, i;
|
||||
floatish t, x;
|
||||
floatish legendlen;
|
||||
|
||||
/* draw the x axis line */
|
||||
fprintf(psfp, "%f %f moveto\n", xpage(0.0), ypage(0.0));
|
||||
fprintf(psfp, "%f 0 rlineto\n", graphwidth);
|
||||
fprintf(psfp, "%f setlinewidth\n", borderthick);
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
/* draw x axis legend */
|
||||
fprintf(psfp, "HE%d setfont\n", NORMAL_FONT);
|
||||
fprintf(psfp, "(%s)\n", sampleunitstring);
|
||||
fprintf(psfp, "dup stringwidth pop\n");
|
||||
fprintf(psfp, "%f\n", xpage(0.0) + graphwidth);
|
||||
fprintf(psfp, "exch sub\n");
|
||||
fprintf(psfp, "%f moveto\n", borderspace);
|
||||
fprintf(psfp, "show\n");
|
||||
|
||||
|
||||
/* draw x axis scaling */
|
||||
|
||||
increment = Round(xrange / (floatish) N_X_MARKS);
|
||||
|
||||
t = graphwidth / xrange;
|
||||
legendlen = StringSize(sampleunitstring) + (floatish) XFUDGE;
|
||||
|
||||
for (i = samplemap[0]; i < samplemap[nsamples - 1]; i += increment) {
|
||||
x = (i - samplemap[0]) * t;
|
||||
|
||||
if (x < (graphwidth - legendlen)) {
|
||||
XAxisMark(x,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
YAxisMark(y, num, unit)
|
||||
floatish y; floatish num; mkb unit;
|
||||
{
|
||||
/* calibration mark */
|
||||
fprintf(psfp, "%f %f moveto\n", xpage(0.0), ypage(y));
|
||||
fprintf(psfp, "-4 0 rlineto\n");
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
/* number */
|
||||
fprintf(psfp, "HE%d setfont\n", NORMAL_FONT);
|
||||
|
||||
switch (unit) {
|
||||
case MEGABYTE :
|
||||
fprintf(psfp, "(");
|
||||
CommaPrint(psfp, (intish) (num / 1e6 + 0.5));
|
||||
fprintf(psfp, "M)\n");
|
||||
break;
|
||||
case KILOBYTE :
|
||||
fprintf(psfp, "(");
|
||||
CommaPrint(psfp, (intish) (num / 1e3 + 0.5));
|
||||
fprintf(psfp, "k)\n");
|
||||
break;
|
||||
case BYTE:
|
||||
fprintf(psfp, "(");
|
||||
CommaPrint(psfp, (intish) (num + 0.5));
|
||||
fprintf(psfp, ")\n");
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(psfp, "dup stringwidth\n");
|
||||
fprintf(psfp, "2 div\n");
|
||||
fprintf(psfp, "%f exch sub\n", ypage(y));
|
||||
|
||||
fprintf(psfp, "exch\n");
|
||||
fprintf(psfp, "%f exch sub\n", graphx0 - borderspace);
|
||||
|
||||
fprintf(psfp, "exch\n");
|
||||
fprintf(psfp, "moveto\n");
|
||||
fprintf(psfp, "show\n");
|
||||
}
|
||||
|
||||
#define N_Y_MARKS 7
|
||||
#define YFUDGE 15
|
||||
|
||||
extern floatish yrange;
|
||||
extern char *valueunitstring;
|
||||
|
||||
static void
|
||||
YAxis()
|
||||
{
|
||||
floatish increment, i;
|
||||
floatish t, y;
|
||||
floatish legendlen;
|
||||
mkb unit;
|
||||
|
||||
/* draw the y axis line */
|
||||
fprintf(psfp, "%f %f moveto\n", xpage(0.0), ypage(0.0));
|
||||
fprintf(psfp, "0 %f rlineto\n", graphheight);
|
||||
fprintf(psfp, "%f setlinewidth\n", borderthick);
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
/* draw y axis legend */
|
||||
fprintf(psfp, "gsave\n");
|
||||
fprintf(psfp, "HE%d setfont\n", NORMAL_FONT);
|
||||
fprintf(psfp, "(%s)\n", valueunitstring);
|
||||
fprintf(psfp, "dup stringwidth pop\n");
|
||||
fprintf(psfp, "%f\n", ypage(0.0) + graphheight);
|
||||
fprintf(psfp, "exch sub\n");
|
||||
fprintf(psfp, "%f exch\n", xpage(0.0) - borderspace);
|
||||
fprintf(psfp, "translate\n");
|
||||
fprintf(psfp, "90 rotate\n");
|
||||
fprintf(psfp, "0 0 moveto\n");
|
||||
fprintf(psfp, "show\n");
|
||||
fprintf(psfp, "grestore\n");
|
||||
|
||||
/* draw y axis scaling */
|
||||
increment = max( yrange / (floatish) N_Y_MARKS, 1.0);
|
||||
increment = Round(increment);
|
||||
|
||||
if (increment >= 1e6) {
|
||||
unit = MEGABYTE;
|
||||
} else if (increment >= 1e3) {
|
||||
unit = KILOBYTE;
|
||||
} else {
|
||||
unit = BYTE;
|
||||
}
|
||||
|
||||
t = graphheight / yrange;
|
||||
legendlen = StringSize(valueunitstring) + (floatish) YFUDGE;
|
||||
|
||||
for (i = 0.0; i <= yrange; i += increment) {
|
||||
y = i * t;
|
||||
|
||||
if (y < (graphheight - legendlen)) {
|
||||
YAxisMark(y, i, unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a "nice round" value to use on the axis.
|
||||
*/
|
||||
|
||||
static floatish OneTwoFive PROTO((floatish)); /* forward */
|
||||
|
||||
static floatish
|
||||
Round(y)
|
||||
floatish y;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (y > 10.0) {
|
||||
for (i = 0; y > 10.0; y /= 10.0, i++) ;
|
||||
y = OneTwoFive(y);
|
||||
for ( ; i > 0; y = y * 10.0, i--) ;
|
||||
|
||||
} else if (y < 1.0) {
|
||||
for (i = 0; y < 1.0; y *= 10.0, i++) ;
|
||||
y = OneTwoFive(y);
|
||||
for ( ; i > 0; y = y / 10.0, i--) ;
|
||||
|
||||
} else {
|
||||
y = OneTwoFive(y);
|
||||
}
|
||||
|
||||
return (y);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* OneTwoFive() -- Runciman's 1,2,5 scaling rule. Argument 1.0 <= y <= 10.0.
|
||||
*/
|
||||
|
||||
static floatish
|
||||
OneTwoFive(y)
|
||||
floatish y;
|
||||
{
|
||||
if (y > 4.0) {
|
||||
return (5.0);
|
||||
} else if (y > 1.0) {
|
||||
return (2.0);
|
||||
} else {
|
||||
return (1.0);
|
||||
}
|
||||
}
|
||||
6
massif/hp2ps/Axes.h
Normal file
6
massif/hp2ps/Axes.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef AXES_H
|
||||
#define AXES_H
|
||||
|
||||
void Axes PROTO((void));
|
||||
|
||||
#endif /* AXES_H */
|
||||
39
massif/hp2ps/CHANGES
Normal file
39
massif/hp2ps/CHANGES
Normal file
@ -0,0 +1,39 @@
|
||||
1.
|
||||
|
||||
When generating PostScript to show strings, '(' and ')' may need to be escaped.
|
||||
These characters are now escaped when the JOB string is shown.
|
||||
|
||||
2.
|
||||
|
||||
Manually deleting samples from a .hp file now does what you would expect.
|
||||
|
||||
3.
|
||||
|
||||
The -t flag for setting the threshold percentage has been scrapped. No one
|
||||
ever used it.
|
||||
|
||||
4.
|
||||
|
||||
Long JOB strings cause hp2ps to use a big title box. Big and small boxes
|
||||
can be forced with -b and -s flag.
|
||||
|
||||
5.
|
||||
|
||||
MARKS now print as small triangles which remain below the x axis.
|
||||
|
||||
6.
|
||||
|
||||
There is an updated manual page.
|
||||
|
||||
7.
|
||||
|
||||
-m flag for setting maximum no of bands (default 20, cant be more than 20).
|
||||
-t flag for setting threshold (between 0% and 5%, default 1%).
|
||||
|
||||
8.
|
||||
|
||||
Axes scaling rounding errors removed.
|
||||
|
||||
9.
|
||||
|
||||
Fixed bug whereby x-axis was assumed to start at zero when placing MARKs.
|
||||
164
massif/hp2ps/Curves.c
Normal file
164
massif/hp2ps/Curves.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Dimensions.h"
|
||||
#include "HpFile.h"
|
||||
#include "Shade.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Curves.h"
|
||||
|
||||
static floatish *g_x; /* x and y values */
|
||||
static floatish *g_y;
|
||||
|
||||
static floatish *g_py; /* previous y values */
|
||||
|
||||
static void Curve PROTO((struct entry *)); /* forward */
|
||||
static void ShadeCurve(); /* forward */
|
||||
|
||||
void
|
||||
Curves()
|
||||
{
|
||||
intish i;
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
Curve(identtable[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw a curve, and fill the area that is below it and above
|
||||
* the previous curve.
|
||||
*/
|
||||
|
||||
static void
|
||||
Curve(e)
|
||||
struct entry* e;
|
||||
{
|
||||
struct chunk* ch;
|
||||
int j;
|
||||
|
||||
for (ch = e->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
g_y[ ch->d[j].bucket ] += ch->d[j].value;
|
||||
}
|
||||
}
|
||||
|
||||
ShadeCurve(g_x, g_y, g_py, ShadeOf(e->name));
|
||||
}
|
||||
|
||||
|
||||
static void PlotCurveLeftToRight PROTO((floatish *, floatish *)); /* forward */
|
||||
static void PlotCurveRightToLeft PROTO((floatish *, floatish *)); /* forward */
|
||||
|
||||
static void SaveCurve PROTO((floatish *, floatish *)); /* forward */
|
||||
|
||||
/*
|
||||
* Map virtual x coord to physical x coord
|
||||
*/
|
||||
|
||||
floatish
|
||||
xpage(x)
|
||||
floatish x;
|
||||
{
|
||||
return (x + graphx0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Map virtual y coord to physical y coord
|
||||
*/
|
||||
|
||||
floatish
|
||||
ypage(y)
|
||||
floatish y;
|
||||
{
|
||||
return (y + graphy0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill the region bounded by two splines, using the given
|
||||
* shade.
|
||||
*/
|
||||
|
||||
static void
|
||||
ShadeCurve(x, y, py, shade)
|
||||
floatish *x; floatish *y; floatish *py; floatish shade;
|
||||
{
|
||||
fprintf(psfp, "%f %f moveto\n", xpage(x[0]), ypage(py[0]));
|
||||
PlotCurveLeftToRight(x, py);
|
||||
|
||||
fprintf(psfp, "%f %f lineto\n", xpage(x[nsamples - 1]),
|
||||
ypage(y[nsamples - 1]));
|
||||
PlotCurveRightToLeft(x, y);
|
||||
|
||||
fprintf(psfp, "closepath\n");
|
||||
|
||||
fprintf(psfp, "gsave\n");
|
||||
|
||||
SetPSColour(shade);
|
||||
fprintf(psfp, "fill\n");
|
||||
|
||||
fprintf(psfp, "grestore\n");
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
SaveCurve(y, py);
|
||||
}
|
||||
|
||||
static void
|
||||
PlotCurveLeftToRight(x,y)
|
||||
floatish *x; floatish *y;
|
||||
{
|
||||
intish i;
|
||||
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
fprintf(psfp, "%f %f lineto\n", xpage(x[i]), ypage(y[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PlotCurveRightToLeft(x,y)
|
||||
floatish *x; floatish *y;
|
||||
{
|
||||
intish i;
|
||||
|
||||
for (i = nsamples - 1; i >= 0; i-- ) {
|
||||
fprintf(psfp, "%f %f lineto\n", xpage(x[i]), ypage(y[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the curve coordinates stored in y[] in py[].
|
||||
*/
|
||||
|
||||
static void
|
||||
SaveCurve(y, py)
|
||||
floatish *y; floatish* py;
|
||||
{
|
||||
intish i;
|
||||
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
py[i] = y[i];
|
||||
}
|
||||
}
|
||||
|
||||
extern floatish xrange;
|
||||
|
||||
void
|
||||
CurvesInit()
|
||||
{
|
||||
intish i;
|
||||
|
||||
g_x = (floatish*) xmalloc(nsamples * sizeof(floatish));
|
||||
g_y = (floatish*) xmalloc(nsamples * sizeof(floatish));
|
||||
g_py = (floatish*) xmalloc(nsamples * sizeof(floatish));
|
||||
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
g_x[i] = ((samplemap[i] - samplemap[0])/ xrange) * graphwidth;
|
||||
g_y[i] = g_py[i] = 0.0;
|
||||
}
|
||||
}
|
||||
10
massif/hp2ps/Curves.h
Normal file
10
massif/hp2ps/Curves.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef CURVES_H
|
||||
#define CURVES_H
|
||||
|
||||
void Curves PROTO((void));
|
||||
void CurvesInit PROTO((void));
|
||||
|
||||
floatish xpage PROTO((floatish));
|
||||
floatish ypage PROTO((floatish));
|
||||
|
||||
#endif /* CURVES_H */
|
||||
61
massif/hp2ps/Defines.h
Normal file
61
massif/hp2ps/Defines.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef DEFINES_H
|
||||
#define DEFINES_H
|
||||
|
||||
/*
|
||||
* Things that can be altered.
|
||||
*/
|
||||
|
||||
#define THRESHOLD_PERCENT _thresh_ /* all values below 1% insignificant */
|
||||
#define DEFAULT_THRESHOLD 1.0
|
||||
extern floatish _thresh_;
|
||||
|
||||
#define TWENTY _twenty_ /* show top 20 bands, grouping excess */
|
||||
#define DEFAULT_TWENTY 20 /* this is default and absolute maximum */
|
||||
extern int _twenty_;
|
||||
|
||||
#define LARGE_FONT 12 /* Helvetica 12pt */
|
||||
#define NORMAL_FONT 10 /* Helvetica 10pt */
|
||||
|
||||
#define BORDER_HEIGHT 432.0 /* page border box 432pt (6 inches high) */
|
||||
#define BORDER_WIDTH 648.0 /* page border box 648pt (9 inches wide) */
|
||||
#define BORDER_SPACE 5.0 /* page border space */
|
||||
#define BORDER_THICK 0.5 /* page border line thickness 0.5pt */
|
||||
|
||||
|
||||
#define TITLE_HEIGHT 20.0 /* title box is 20pt high */
|
||||
#define TITLE_TEXT_FONT LARGE_FONT /* title in large font */
|
||||
#define TITLE_TEXT_SPACE 6.0 /* space between title text and box */
|
||||
|
||||
|
||||
#define AXIS_THICK 0.5 /* axis thickness 0.5pt */
|
||||
#define AXIS_TEXT_SPACE 6 /* space between axis legends and axis */
|
||||
#define AXIS_TEXT_FONT NORMAL_FONT /* axis legends in normal font */
|
||||
#define AXIS_Y_TEXT_SPACE 35 /* space for y axis text */
|
||||
|
||||
#define KEY_BOX_WIDTH 14 /* key boxes are 14pt high */
|
||||
|
||||
#define SMALL_JOB_STRING_WIDTH 35 /* small title for 35 characters or less */
|
||||
#define BIG_JOB_STRING_WIDTH 80 /* big title for everything else */
|
||||
|
||||
#define GRAPH_X0 (AXIS_Y_TEXT_SPACE + (2 * BORDER_SPACE))
|
||||
#define GRAPH_Y0 (AXIS_TEXT_FONT + (2 * BORDER_SPACE))
|
||||
|
||||
|
||||
/*
|
||||
* Things that should be left well alone.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#define START_X 72 /* start 72pt (1 inch) from left (portrait) */
|
||||
#define START_Y 108 /* start 108pt (1.5 inch) from bottom (portrait) */
|
||||
|
||||
#define NUMBER_LENGTH 32
|
||||
|
||||
#define N_CHUNK 24
|
||||
|
||||
#define VERSION "0.25" /* as of 95/03/21 */
|
||||
|
||||
#define max(x,y) ((x) > (y) ? (x) : (y)) /* not everyone has this */
|
||||
|
||||
#endif /* DEFINES_H */
|
||||
140
massif/hp2ps/Deviation.c
Normal file
140
massif/hp2ps/Deviation.c
Normal file
@ -0,0 +1,140 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
extern void free();
|
||||
|
||||
/* own stuff */
|
||||
#include "Deviation.h"
|
||||
|
||||
/*
|
||||
* Reorder the identifiers in the identifier table so that the
|
||||
* ones whose data points exhibit the mininal standard deviation
|
||||
* come first.
|
||||
*/
|
||||
|
||||
void
|
||||
Deviation()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
floatish dev;
|
||||
struct chunk* ch;
|
||||
int min;
|
||||
floatish t;
|
||||
struct entry* e;
|
||||
floatish *averages;
|
||||
floatish *deviations;
|
||||
|
||||
averages = (floatish*) xmalloc(nidents * sizeof(floatish));
|
||||
deviations = (floatish*) xmalloc(nidents * sizeof(floatish));
|
||||
|
||||
/* find averages */
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
averages[i] = 0.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
averages[i] += ch->d[j].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
averages[i] /= (floatish) nsamples;
|
||||
}
|
||||
|
||||
/* calculate standard deviation */
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
deviations[i] = 0.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
dev = ch->d[j].value - averages[i];
|
||||
deviations[i] += dev * dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
deviations[i] = (floatish) sqrt ((doublish) (deviations[i] /
|
||||
(floatish) (nsamples - 1)));
|
||||
}
|
||||
|
||||
|
||||
/* sort on basis of standard deviation */
|
||||
|
||||
for (i = 0; i < nidents-1; i++) {
|
||||
min = i;
|
||||
for (j = i+1; j < nidents; j++) {
|
||||
if (deviations[ j ] < deviations[min]) {
|
||||
min = j;
|
||||
}
|
||||
}
|
||||
|
||||
t = deviations[min];
|
||||
deviations[min] = deviations[i];
|
||||
deviations[i] = t;
|
||||
|
||||
e = identtable[min];
|
||||
identtable[min] = identtable[i];
|
||||
identtable[i] = e;
|
||||
}
|
||||
|
||||
free(averages);
|
||||
free(deviations);
|
||||
}
|
||||
|
||||
void
|
||||
Identorder(iflag)
|
||||
int iflag; /* a funny three-way flag ? WDP 95/03 */
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int min;
|
||||
struct entry* e;
|
||||
|
||||
/* sort on basis of ident string */
|
||||
if (iflag > 0) {
|
||||
/* greatest at top i.e. smallest at start */
|
||||
|
||||
for (i = 0; i < nidents-1; i++) {
|
||||
min = i;
|
||||
for (j = i+1; j < nidents; j++) {
|
||||
if (strcmp(identtable[j]->name, identtable[min]->name) < 0) {
|
||||
min = j;
|
||||
}
|
||||
}
|
||||
|
||||
e = identtable[min];
|
||||
identtable[min] = identtable[i];
|
||||
identtable[i] = e;
|
||||
}
|
||||
} else {
|
||||
/* smallest at top i.e. greatest at start */
|
||||
|
||||
for (i = 0; i < nidents-1; i++) {
|
||||
min = i;
|
||||
for (j = i+1; j < nidents; j++) {
|
||||
if (strcmp(identtable[j]->name, identtable[min]->name) > 0) {
|
||||
min = j;
|
||||
}
|
||||
}
|
||||
|
||||
e = identtable[min];
|
||||
identtable[min] = identtable[i];
|
||||
identtable[i] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
massif/hp2ps/Deviation.h
Normal file
7
massif/hp2ps/Deviation.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef DEVIATION_H
|
||||
#define DEVIATION_H
|
||||
|
||||
void Deviation PROTO((void));
|
||||
void Identorder PROTO((int));
|
||||
|
||||
#endif /* DEVIATION_H */
|
||||
203
massif/hp2ps/Dimensions.c
Normal file
203
massif/hp2ps/Dimensions.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "HpFile.h"
|
||||
#include "Scale.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Dimensions.h"
|
||||
|
||||
/*
|
||||
* Get page and other dimensions before printing.
|
||||
*/
|
||||
|
||||
floatish borderheight = BORDER_HEIGHT;
|
||||
floatish borderwidth = BORDER_WIDTH;
|
||||
floatish borderspace = BORDER_SPACE;
|
||||
floatish borderthick = BORDER_THICK;
|
||||
|
||||
floatish titlewidth = (BORDER_WIDTH - (2 * BORDER_SPACE));
|
||||
floatish titletextspace = TITLE_TEXT_SPACE;
|
||||
floatish titleheight;
|
||||
|
||||
floatish graphx0 = GRAPH_X0;
|
||||
floatish graphy0 = GRAPH_Y0;
|
||||
|
||||
floatish graphheight;
|
||||
floatish graphwidth;
|
||||
|
||||
static floatish KeyWidth PROTO((void)); /* forward */
|
||||
|
||||
void
|
||||
Dimensions()
|
||||
{
|
||||
xrange = samplemap[nsamples - 1] - samplemap[0];
|
||||
xrange = max(xrange, auxxrange);
|
||||
if (xrange == 0.0) xrange = 1.0; /* avoid division by 0.0 */
|
||||
|
||||
yrange = MaxCombinedHeight();
|
||||
yrange = max(yrange, auxyrange);
|
||||
if (yrange == 0.0) yrange = 1.0; /* avoid division by 0.0 */
|
||||
|
||||
if (!bflag && !sflag) {
|
||||
bflag = strlen(jobstring) > SMALL_JOB_STRING_WIDTH;
|
||||
}
|
||||
|
||||
if (bflag) {
|
||||
titleheight = 2 * TITLE_HEIGHT;
|
||||
} else {
|
||||
titleheight = TITLE_HEIGHT;
|
||||
}
|
||||
|
||||
graphwidth = titlewidth - graphx0 - (TWENTY ? KeyWidth() : 0);
|
||||
graphheight = borderheight - titleheight - (2 * borderspace) - graphy0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the width of the key.
|
||||
*/
|
||||
|
||||
static floatish
|
||||
KeyWidth()
|
||||
{
|
||||
intish i;
|
||||
floatish c;
|
||||
|
||||
c = 0.0;
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
c = max(c, StringSize(identtable[i]->name));
|
||||
}
|
||||
|
||||
c += 3.0 * borderspace;
|
||||
|
||||
c += (floatish) KEY_BOX_WIDTH;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A desperately grim solution.
|
||||
*/
|
||||
|
||||
|
||||
floatish fonttab[] = {
|
||||
/* 20 (' ') = */ 3.0,
|
||||
/* 21 ('!') = */ 1.0,
|
||||
/* 22 ('"') = */ 1.0,
|
||||
/* 23 ('#') = */ 3.0,
|
||||
/* 24 ('$') = */ 3.0,
|
||||
/* 25 ('%') = */ 3.0,
|
||||
/* 26 ('&') = */ 3.0,
|
||||
/* 27 (''') = */ 1.0,
|
||||
/* 28 ('(') = */ 3.0,
|
||||
/* 29 (')') = */ 3.0,
|
||||
/* 2a ('*') = */ 2.0,
|
||||
/* 2b ('+') = */ 3.0,
|
||||
/* 2c (',') = */ 1.0,
|
||||
/* 2d ('-') = */ 3.0,
|
||||
/* 2e ('.') = */ 1.0,
|
||||
/* 2f ('/') = */ 3.0,
|
||||
/* 30 ('0') = */ 4.0,
|
||||
/* 31 ('1') = */ 4.0,
|
||||
/* 32 ('2') = */ 4.0,
|
||||
/* 33 ('3') = */ 4.0,
|
||||
/* 34 ('4') = */ 4.0,
|
||||
/* 35 ('5') = */ 4.0,
|
||||
/* 36 ('6') = */ 4.0,
|
||||
/* 37 ('7') = */ 4.0,
|
||||
/* 38 ('8') = */ 4.0,
|
||||
/* 39 ('9') = */ 4.0,
|
||||
/* 3a (':') = */ 1.0,
|
||||
/* 3b (';') = */ 1.0,
|
||||
/* 3c ('<') = */ 3.0,
|
||||
/* 3d ('=') = */ 3.0,
|
||||
/* 3e ('>') = */ 3.0,
|
||||
/* 3f ('?') = */ 2.0,
|
||||
/* 40 ('@') = */ 3.0,
|
||||
/* 41 ('A') = */ 5.0,
|
||||
/* 42 ('B') = */ 5.0,
|
||||
/* 43 ('C') = */ 5.0,
|
||||
/* 44 ('D') = */ 5.0,
|
||||
/* 45 ('E') = */ 5.0,
|
||||
/* 46 ('F') = */ 5.0,
|
||||
/* 47 ('G') = */ 5.0,
|
||||
/* 48 ('H') = */ 5.0,
|
||||
/* 49 ('I') = */ 1.0,
|
||||
/* 4a ('J') = */ 5.0,
|
||||
/* 4b ('K') = */ 5.0,
|
||||
/* 4c ('L') = */ 5.0,
|
||||
/* 4d ('M') = */ 5.0,
|
||||
/* 4e ('N') = */ 5.0,
|
||||
/* 4f ('O') = */ 5.0,
|
||||
/* 50 ('P') = */ 5.0,
|
||||
/* 51 ('Q') = */ 5.0,
|
||||
/* 52 ('R') = */ 5.0,
|
||||
/* 53 ('S') = */ 5.0,
|
||||
/* 54 ('T') = */ 5.0,
|
||||
/* 55 ('U') = */ 5.0,
|
||||
/* 56 ('V') = */ 5.0,
|
||||
/* 57 ('W') = */ 5.0,
|
||||
/* 58 ('X') = */ 5.0,
|
||||
/* 59 ('Y') = */ 5.0,
|
||||
/* 5a ('Z') = */ 5.0,
|
||||
/* 5b ('[') = */ 2.0,
|
||||
/* 5c ('\') = */ 3.0,
|
||||
/* 5d (']') = */ 2.0,
|
||||
/* 5e ('^') = */ 1.0,
|
||||
/* 5f ('_') = */ 3.0,
|
||||
/* 60 ('`') = */ 1.0,
|
||||
/* 61 ('a') = */ 3.0,
|
||||
/* 62 ('b') = */ 3.0,
|
||||
/* 63 ('c') = */ 3.0,
|
||||
/* 64 ('d') = */ 3.0,
|
||||
/* 65 ('e') = */ 3.0,
|
||||
/* 66 ('f') = */ 3.0,
|
||||
/* 67 ('g') = */ 3.0,
|
||||
/* 68 ('h') = */ 3.0,
|
||||
/* 69 ('i') = */ 1.0,
|
||||
/* 6a ('j') = */ 2.0,
|
||||
/* 6b ('k') = */ 3.0,
|
||||
/* 6c ('l') = */ 1.0,
|
||||
/* 6d ('m') = */ 5.0,
|
||||
/* 6e ('n') = */ 3.0,
|
||||
/* 6f ('o') = */ 3.0,
|
||||
/* 70 ('p') = */ 3.0,
|
||||
/* 71 ('q') = */ 3.0,
|
||||
/* 72 ('r') = */ 2.0,
|
||||
/* 73 ('s') = */ 3.0,
|
||||
/* 74 ('t') = */ 2.0,
|
||||
/* 75 ('u') = */ 3.0,
|
||||
/* 76 ('v') = */ 3.0,
|
||||
/* 77 ('w') = */ 3.0,
|
||||
/* 78 ('x') = */ 3.0,
|
||||
/* 79 ('y') = */ 3.0,
|
||||
/* 7a ('z') = */ 3.0,
|
||||
/* 7b ('{') = */ 2.0,
|
||||
/* 7c ('|') = */ 1.0,
|
||||
/* 7d ('}') = */ 2.0,
|
||||
/* 7e ('~') = */ 2.0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* What size is a string (in points)?
|
||||
*/
|
||||
|
||||
#define FUDGE (2.834646 * 0.6)
|
||||
|
||||
floatish
|
||||
StringSize(s)
|
||||
char* s;
|
||||
{
|
||||
floatish r;
|
||||
|
||||
for (r = 0.0; *s; s++) {
|
||||
r += fonttab[(*s) - 0x20];
|
||||
}
|
||||
|
||||
return r * FUDGE;
|
||||
}
|
||||
22
massif/hp2ps/Dimensions.h
Normal file
22
massif/hp2ps/Dimensions.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef DIMENSIONS_H
|
||||
#define DIMENSIONS_H
|
||||
|
||||
extern floatish borderheight;
|
||||
extern floatish borderwidth;
|
||||
extern floatish borderspace;
|
||||
extern floatish borderthick;
|
||||
|
||||
extern floatish titleheight;
|
||||
extern floatish titlewidth;
|
||||
extern floatish titletextspace;
|
||||
|
||||
extern floatish graphx0;
|
||||
extern floatish graphy0;
|
||||
|
||||
extern floatish graphheight;
|
||||
extern floatish graphwidth;
|
||||
|
||||
void Dimensions PROTO((void));
|
||||
floatish StringSize PROTO((char *));
|
||||
|
||||
#endif /* DIMENSIONS_H */
|
||||
55
massif/hp2ps/Error.c
Normal file
55
massif/hp2ps/Error.c
Normal file
@ -0,0 +1,55 @@
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Error.h"
|
||||
|
||||
void exit PROTO((int));
|
||||
|
||||
/*VARARGS0*/
|
||||
void
|
||||
Error(a1,a2,a3,a4)
|
||||
char* a1; char* a2; char* a3; char* a4;
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "%s: ", programname);
|
||||
fprintf(stderr, a1, a2, a3, a4);
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*VARARGS0*/
|
||||
void
|
||||
Disaster(a1,a2,a3,a4)
|
||||
char* a1; char* a2; char* a3; char* a4;
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "%s: ", programname);
|
||||
fprintf(stderr, " Disaster! (");
|
||||
fprintf(stderr, a1, a2, a3, a4);
|
||||
fprintf(stderr, ")\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
Usage(str)
|
||||
char *str;
|
||||
{
|
||||
if (str) printf("error: %s\n", str);
|
||||
printf("usage: %s -b -d -ef -g -i -p -mn -p -s -tf -y [file[.hp]]\n", programname);
|
||||
printf("where -b use large title box\n");
|
||||
printf(" -d sort by standard deviation\n");
|
||||
printf(" -ef[in|mm|pt] produce Encapsulated PostScript f units wide (f > 2 inches)\n");
|
||||
printf(" -g produce output suitable for GHOSTSCRIPT previever\n");
|
||||
printf(" -i[+|-] sort by identifier string (-i+ gives greatest on top) \n");
|
||||
printf(" -mn print maximum of n bands (default & max 20)\n");
|
||||
printf(" -m0 removes the band limit altogether\n");
|
||||
printf(" -p use previous scaling, shading and ordering\n");
|
||||
printf(" -s use small title box\n");
|
||||
printf(" -tf ignore trace bands which sum below f%% (default 1%%, max 5%%)\n");
|
||||
printf(" -y traditional\n");
|
||||
printf(" -c colour ouput\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
8
massif/hp2ps/Error.h
Normal file
8
massif/hp2ps/Error.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
extern void Error (); /*PROTO((char *, ...)); */
|
||||
extern void Disaster (); /* PROTO((char *, ...)); */
|
||||
extern void Usage (); /* PROTO((char *)); */
|
||||
|
||||
#endif /* ERROR_H */
|
||||
587
massif/hp2ps/HpFile.c
Normal file
587
massif/hp2ps/HpFile.c
Normal file
@ -0,0 +1,587 @@
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
#ifndef atof
|
||||
double atof PROTO((const char *));
|
||||
#endif
|
||||
|
||||
/* own stuff already included */
|
||||
|
||||
#define N_MARKS 50 /* start size of the mark table */
|
||||
#define N_SAMPLES 500 /* start size of the sample table */
|
||||
|
||||
char *theident;
|
||||
char *thestring;
|
||||
int theinteger;
|
||||
floatish thefloatish;
|
||||
int g_ch; /* last character read */
|
||||
token thetok; /* last token */
|
||||
int linenum; /* current line number */
|
||||
int endfile; /* true at end of file */
|
||||
|
||||
static boolish gotjob = 0; /* "JOB" read */
|
||||
static boolish gotdate = 0; /* "DATE" read */
|
||||
static boolish gotvalueunit = 0; /* "VALUE_UNIT" read */
|
||||
static boolish gotsampleunit = 0; /* "SAMPLE_UNIT" read */
|
||||
static boolish insample = 0; /* true when in sample */
|
||||
|
||||
static floatish lastsample; /* the last sample time */
|
||||
|
||||
static void GetHpLine PROTO((FILE *)); /* forward */
|
||||
static void GetHpTok PROTO((FILE *)); /* forward */
|
||||
|
||||
static struct entry *GetEntry PROTO((char *)); /* forward */
|
||||
|
||||
static void MakeIdentTable PROTO((void)); /* forward */
|
||||
|
||||
char *jobstring;
|
||||
char *datestring;
|
||||
|
||||
char *sampleunitstring;
|
||||
char *valueunitstring;
|
||||
|
||||
floatish *samplemap; /* sample intervals */
|
||||
floatish *markmap; /* sample marks */
|
||||
|
||||
/*
|
||||
* An extremely simple parser. The input is organised into lines of
|
||||
* the form
|
||||
*
|
||||
* JOB s -- job identifier string
|
||||
* DATE s -- date string
|
||||
* SAMPLE_UNIT s -- sample unit eg "seconds"
|
||||
* VALUE_UNIT s -- value unit eg "bytes"
|
||||
* MARK i -- sample mark
|
||||
* BEGIN_SAMPLE i -- start of ith sample
|
||||
* identifier i -- there are i identifiers in this sample
|
||||
* END_SAMPLE i -- end of ith sample
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
GetHpFile(infp)
|
||||
FILE *infp;
|
||||
{
|
||||
nsamples = 0;
|
||||
nmarks = 0;
|
||||
nidents = 0;
|
||||
|
||||
g_ch = ' ';
|
||||
endfile = 0;
|
||||
linenum = 1;
|
||||
lastsample = 0.0;
|
||||
|
||||
GetHpTok(infp);
|
||||
|
||||
while (endfile == 0) {
|
||||
GetHpLine(infp);
|
||||
}
|
||||
|
||||
if (!gotjob) {
|
||||
Error("%s: JOB missing", hpfile);
|
||||
}
|
||||
|
||||
if (!gotdate) {
|
||||
Error("%s: DATE missing", hpfile);
|
||||
}
|
||||
|
||||
if (!gotvalueunit) {
|
||||
Error("%s: VALUE_UNIT missing", hpfile);
|
||||
}
|
||||
|
||||
if (!gotsampleunit) {
|
||||
Error("%s: SAMPLE_UNIT missing", hpfile);
|
||||
}
|
||||
|
||||
if (nsamples == 0) {
|
||||
Error("%s: contains no samples", hpfile);
|
||||
}
|
||||
|
||||
|
||||
MakeIdentTable();
|
||||
|
||||
fclose(hpfp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the next line from the input, check the syntax, and perform
|
||||
* the appropriate action.
|
||||
*/
|
||||
|
||||
static void
|
||||
GetHpLine(infp)
|
||||
FILE* infp;
|
||||
{
|
||||
static intish nmarkmax = 0, nsamplemax = 0;
|
||||
|
||||
switch (thetok) {
|
||||
case JOB_TOK:
|
||||
GetHpTok(infp);
|
||||
if (thetok != STRING_TOK) {
|
||||
Error("%s, line %d: string must follow JOB", hpfile, linenum);
|
||||
}
|
||||
jobstring = thestring;
|
||||
gotjob = 1;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case DATE_TOK:
|
||||
GetHpTok(infp);
|
||||
if (thetok != STRING_TOK) {
|
||||
Error("%s, line %d: string must follow DATE", hpfile, linenum);
|
||||
}
|
||||
datestring = thestring;
|
||||
gotdate = 1;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case SAMPLE_UNIT_TOK:
|
||||
GetHpTok(infp);
|
||||
if (thetok != STRING_TOK) {
|
||||
Error("%s, line %d: string must follow SAMPLE_UNIT", hpfile,
|
||||
linenum);
|
||||
}
|
||||
sampleunitstring = thestring;
|
||||
gotsampleunit = 1;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case VALUE_UNIT_TOK:
|
||||
GetHpTok(infp);
|
||||
if (thetok != STRING_TOK) {
|
||||
Error("%s, line %d: string must follow VALUE_UNIT", hpfile,
|
||||
linenum);
|
||||
}
|
||||
valueunitstring = thestring;
|
||||
gotvalueunit = 1;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case MARK_TOK:
|
||||
GetHpTok(infp);
|
||||
if (thetok != FLOAT_TOK) {
|
||||
Error("%s, line %d, floating point number must follow MARK",
|
||||
hpfile, linenum);
|
||||
}
|
||||
if (insample) {
|
||||
Error("%s, line %d, MARK occurs within sample", hpfile, linenum);
|
||||
}
|
||||
if (nmarks >= nmarkmax) {
|
||||
if (!markmap) {
|
||||
nmarkmax = N_MARKS;
|
||||
markmap = (floatish*) xmalloc(nmarkmax * sizeof(floatish));
|
||||
} else {
|
||||
nmarkmax *= 2;
|
||||
markmap = (floatish*) xrealloc(markmap, nmarkmax * sizeof(floatish));
|
||||
}
|
||||
}
|
||||
markmap[ nmarks++ ] = thefloatish;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case BEGIN_SAMPLE_TOK:
|
||||
insample = 1;
|
||||
GetHpTok(infp);
|
||||
if (thetok != FLOAT_TOK) {
|
||||
Error("%s, line %d, floating point number must follow BEGIN_SAMPLE", hpfile, linenum);
|
||||
}
|
||||
if (thefloatish < lastsample) {
|
||||
Error("%s, line %d, samples out of sequence", hpfile, linenum);
|
||||
} else {
|
||||
lastsample = thefloatish;
|
||||
}
|
||||
if (nsamples >= nsamplemax) {
|
||||
if (!samplemap) {
|
||||
nsamplemax = N_SAMPLES;
|
||||
samplemap = (floatish*) xmalloc(nsamplemax * sizeof(floatish));
|
||||
} else {
|
||||
nsamplemax *= 2;
|
||||
samplemap = (floatish*) xrealloc(samplemap,
|
||||
nsamplemax * sizeof(floatish));
|
||||
}
|
||||
}
|
||||
samplemap[ nsamples ] = thefloatish;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case END_SAMPLE_TOK:
|
||||
insample = 0;
|
||||
GetHpTok(infp);
|
||||
if (thetok != FLOAT_TOK) {
|
||||
Error("%s, line %d: floating point number must follow END_SAMPLE",
|
||||
hpfile, linenum);
|
||||
}
|
||||
nsamples++;
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case IDENTIFIER_TOK:
|
||||
GetHpTok(infp);
|
||||
if (thetok != INTEGER_TOK) {
|
||||
Error("%s, line %d: integer must follow identifier", hpfile,
|
||||
linenum);
|
||||
}
|
||||
StoreSample(GetEntry(theident), nsamples, (floatish) theinteger);
|
||||
GetHpTok(infp);
|
||||
break;
|
||||
|
||||
case EOF_TOK:
|
||||
endfile = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
Error("%s, line %d: %s unexpected", hpfile, linenum,
|
||||
TokenToString(thetok));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
TokenToString(t)
|
||||
token t;
|
||||
{
|
||||
switch (t) {
|
||||
case EOF_TOK: return "EOF";
|
||||
case INTEGER_TOK: return "integer";
|
||||
case FLOAT_TOK: return "floating point number";
|
||||
case IDENTIFIER_TOK: return "identifier";
|
||||
case STRING_TOK: return "string";
|
||||
case BEGIN_SAMPLE_TOK: return "BEGIN_SAMPLE";
|
||||
case END_SAMPLE_TOK: return "END_SAMPLE";
|
||||
case JOB_TOK: return "JOB";
|
||||
case DATE_TOK: return "DATE";
|
||||
case SAMPLE_UNIT_TOK: return "SAMPLE_UNIT";
|
||||
case VALUE_UNIT_TOK: return "VALUE_UNIT";
|
||||
case MARK_TOK: return "MARK";
|
||||
|
||||
case X_RANGE_TOK: return "X_RANGE";
|
||||
case Y_RANGE_TOK: return "Y_RANGE";
|
||||
case ORDER_TOK: return "ORDER";
|
||||
case SHADE_TOK: return "SHADE";
|
||||
default: return "(strange token)";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the next token from the input and assign its value
|
||||
* to the global variable "thetok". In the case of numbers,
|
||||
* the corresponding value is also assigned to "theinteger"
|
||||
* or "thefloatish" as appropriate; in the case of identifiers
|
||||
* it is assigned to "theident".
|
||||
*/
|
||||
|
||||
static void
|
||||
GetHpTok(infp)
|
||||
FILE* infp;
|
||||
{
|
||||
|
||||
while (isspace(g_ch)) { /* skip whitespace */
|
||||
if (g_ch == '\n') linenum++;
|
||||
g_ch = getc(infp);
|
||||
}
|
||||
|
||||
if (g_ch == EOF) {
|
||||
thetok = EOF_TOK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isdigit(g_ch)) {
|
||||
thetok = GetNumber(infp);
|
||||
return;
|
||||
} else if (g_ch == '\"') {
|
||||
GetString(infp);
|
||||
thetok = STRING_TOK;
|
||||
return;
|
||||
} else if (IsIdChar(g_ch)) {
|
||||
ASSERT(! (isdigit(g_ch))); /* g_ch can't be a digit here */
|
||||
GetIdent(infp);
|
||||
if (!isupper(theident[0])) {
|
||||
thetok = IDENTIFIER_TOK;
|
||||
} else if (strcmp(theident, "BEGIN_SAMPLE") == 0) {
|
||||
thetok = BEGIN_SAMPLE_TOK;
|
||||
} else if (strcmp(theident, "END_SAMPLE") == 0) {
|
||||
thetok = END_SAMPLE_TOK;
|
||||
} else if (strcmp(theident, "JOB") == 0) {
|
||||
thetok = JOB_TOK;
|
||||
} else if (strcmp(theident, "DATE") == 0) {
|
||||
thetok = DATE_TOK;
|
||||
} else if (strcmp(theident, "SAMPLE_UNIT") == 0) {
|
||||
thetok = SAMPLE_UNIT_TOK;
|
||||
} else if (strcmp(theident, "VALUE_UNIT") == 0) {
|
||||
thetok = VALUE_UNIT_TOK;
|
||||
} else if (strcmp(theident, "MARK") == 0) {
|
||||
thetok = MARK_TOK;
|
||||
} else {
|
||||
thetok = IDENTIFIER_TOK;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
Error("%s, line %d: strange character (%c)", hpfile, linenum, g_ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read a sequence of digits and convert the result to an integer
|
||||
* or floating point value (assigned to the "theinteger" or
|
||||
* "thefloatish").
|
||||
*/
|
||||
|
||||
static char numberstring[ NUMBER_LENGTH - 1 ];
|
||||
|
||||
token
|
||||
GetNumber(infp)
|
||||
FILE* infp;
|
||||
{
|
||||
int i;
|
||||
int containsdot;
|
||||
|
||||
ASSERT(isdigit(ch)); /* we must have a digit to start with */
|
||||
|
||||
containsdot = 0;
|
||||
|
||||
for (i = 0; i < NUMBER_LENGTH && (isdigit(g_ch) || g_ch == '.'); i++) {
|
||||
numberstring[ i ] = g_ch;
|
||||
containsdot |= (g_ch == '.');
|
||||
g_ch = getc(infp);
|
||||
}
|
||||
|
||||
ASSERT(i < NUMBER_LENGTH); /* did not overflow */
|
||||
|
||||
numberstring[ i ] = '\0';
|
||||
|
||||
if (containsdot) {
|
||||
thefloatish = (floatish) atof(numberstring);
|
||||
return FLOAT_TOK;
|
||||
} else {
|
||||
theinteger = atoi(numberstring);
|
||||
return INTEGER_TOK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a sequence of identifier characters and assign the result
|
||||
* to the string "theident".
|
||||
*/
|
||||
|
||||
void
|
||||
GetIdent(infp)
|
||||
FILE *infp;
|
||||
{
|
||||
unsigned int i;
|
||||
char idbuffer[5000];
|
||||
|
||||
for (i = 0; i < (sizeof idbuffer)-1 && IsIdChar(g_ch); i++) {
|
||||
idbuffer[ i ] = g_ch;
|
||||
g_ch = getc(infp);
|
||||
}
|
||||
|
||||
idbuffer[ i ] = '\0';
|
||||
|
||||
if (theident)
|
||||
free(theident);
|
||||
|
||||
theident = copystring(idbuffer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read a sequence of characters that make up a string and
|
||||
* assign the result to "thestring".
|
||||
*/
|
||||
|
||||
void
|
||||
GetString(infp)
|
||||
FILE *infp;
|
||||
{
|
||||
unsigned int i;
|
||||
char stringbuffer[5000];
|
||||
|
||||
ASSERT(ch == '\"');
|
||||
|
||||
g_ch = getc(infp); /* skip the '\"' that begins the string */
|
||||
|
||||
for (i = 0; i < (sizeof stringbuffer)-1 && g_ch != '\"'; i++) {
|
||||
stringbuffer[ i ] = g_ch;
|
||||
g_ch = getc(infp);
|
||||
}
|
||||
|
||||
stringbuffer[i] = '\0';
|
||||
thestring = copystring(stringbuffer);
|
||||
|
||||
ASSERT(g_ch == '\"');
|
||||
|
||||
g_ch = getc(infp); /* skip the '\"' that terminates the string */
|
||||
}
|
||||
|
||||
boolish
|
||||
IsIdChar(ch)
|
||||
int ch;
|
||||
{
|
||||
return (!isspace(ch));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The information associated with each identifier is stored
|
||||
* in a linked list of chunks. The table below allows the list
|
||||
* of chunks to be retrieved given an identifier name.
|
||||
*/
|
||||
|
||||
#define N_HASH 513
|
||||
|
||||
static struct entry* hashtable[ N_HASH ];
|
||||
|
||||
static intish
|
||||
Hash(s)
|
||||
char *s;
|
||||
{
|
||||
int r;
|
||||
|
||||
for (r = 0; *s; s++) {
|
||||
r = r + r + r + *s;
|
||||
}
|
||||
|
||||
if (r < 0) r = -r;
|
||||
|
||||
return r % N_HASH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get space for a new chunk. Initialise it, and return a pointer
|
||||
* to the new chunk.
|
||||
*/
|
||||
|
||||
static struct chunk*
|
||||
MakeChunk()
|
||||
{
|
||||
struct chunk* ch;
|
||||
struct datapoint* d;
|
||||
|
||||
ch = (struct chunk*) xmalloc( sizeof(struct chunk) );
|
||||
|
||||
d = (struct datapoint*) xmalloc (sizeof(struct datapoint) * N_CHUNK);
|
||||
|
||||
ch->nd = 0;
|
||||
ch->d = d;
|
||||
ch->next = 0;
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get space for a new entry. Initialise it, and return a pointer
|
||||
* to the new entry.
|
||||
*/
|
||||
|
||||
struct entry *
|
||||
MakeEntry(name)
|
||||
char *name;
|
||||
{
|
||||
struct entry* e;
|
||||
|
||||
e = (struct entry *) xmalloc(sizeof(struct entry));
|
||||
e->chk = MakeChunk();
|
||||
e->name = copystring(name);
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the entry associated with "name", creating a new entry if
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
static struct entry *
|
||||
GetEntry(name)
|
||||
char* name;
|
||||
{
|
||||
intish h;
|
||||
struct entry* e;
|
||||
|
||||
h = Hash(name);
|
||||
|
||||
for (e = hashtable[ h ]; e; e = e->next) {
|
||||
if (strcmp(e->name, name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e) {
|
||||
return (e);
|
||||
} else {
|
||||
nidents++;
|
||||
e = MakeEntry(name);
|
||||
e->next = hashtable[ h ];
|
||||
hashtable[ h ] = e;
|
||||
return (e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Store information from a sample.
|
||||
*/
|
||||
|
||||
void
|
||||
StoreSample(en, bucket, value)
|
||||
struct entry* en; intish bucket; floatish value;
|
||||
{
|
||||
struct chunk* chk;
|
||||
|
||||
for (chk = en->chk; chk->next != 0; chk = chk->next)
|
||||
;
|
||||
|
||||
if (chk->nd < N_CHUNK) {
|
||||
chk->d[ chk->nd ].bucket = bucket;
|
||||
chk->d[ chk->nd ].value = value;
|
||||
chk->nd += 1;
|
||||
} else {
|
||||
struct chunk* t;
|
||||
t = chk->next = MakeChunk();
|
||||
t->d[ 0 ].bucket = bucket;
|
||||
t->d[ 0 ].value = value;
|
||||
t->nd += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct entry** identtable;
|
||||
|
||||
/*
|
||||
* The hash table is useful while reading the input, but it
|
||||
* becomes a liability thereafter. The code below converts
|
||||
* it to a more easily processed table.
|
||||
*/
|
||||
|
||||
static void
|
||||
MakeIdentTable()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
struct entry* e;
|
||||
|
||||
nidents = 0;
|
||||
for (i = 0; i < N_HASH; i++) {
|
||||
for (e = hashtable[ i ]; e; e = e->next) {
|
||||
nidents++;
|
||||
}
|
||||
}
|
||||
|
||||
identtable = (struct entry**) xmalloc(nidents * sizeof(struct entry*));
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < N_HASH; i++) {
|
||||
for (e = hashtable[ i ]; e; e = e->next, j++) {
|
||||
identtable[ j ] = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
77
massif/hp2ps/HpFile.h
Normal file
77
massif/hp2ps/HpFile.h
Normal file
@ -0,0 +1,77 @@
|
||||
#ifndef HP_FILE_H
|
||||
#define HP_FILE_H
|
||||
|
||||
typedef enum {
|
||||
/* These tokens are found in ".hp" files */
|
||||
|
||||
EOF_TOK,
|
||||
INTEGER_TOK,
|
||||
FLOAT_TOK,
|
||||
IDENTIFIER_TOK,
|
||||
STRING_TOK,
|
||||
BEGIN_SAMPLE_TOK,
|
||||
END_SAMPLE_TOK,
|
||||
JOB_TOK,
|
||||
DATE_TOK,
|
||||
SAMPLE_UNIT_TOK,
|
||||
VALUE_UNIT_TOK,
|
||||
MARK_TOK,
|
||||
|
||||
/* These extra ones are found only in ".aux" files */
|
||||
|
||||
X_RANGE_TOK,
|
||||
Y_RANGE_TOK,
|
||||
ORDER_TOK,
|
||||
SHADE_TOK
|
||||
} token;
|
||||
|
||||
struct datapoint {
|
||||
int bucket;
|
||||
floatish value;
|
||||
};
|
||||
|
||||
struct chunk {
|
||||
struct chunk *next;
|
||||
short nd; /* 0 .. N_CHUNK - 1 */
|
||||
struct datapoint *d;
|
||||
};
|
||||
|
||||
|
||||
struct entry {
|
||||
struct entry *next;
|
||||
struct chunk *chk;
|
||||
char *name;
|
||||
};
|
||||
|
||||
extern char *theident;
|
||||
extern char *thestring;
|
||||
extern int theinteger;
|
||||
extern floatish thefloatish;
|
||||
extern int g_ch;
|
||||
extern token thetok;
|
||||
extern int linenum;
|
||||
extern int endfile;
|
||||
|
||||
char *TokenToString PROTO((token));
|
||||
|
||||
extern struct entry** identtable;
|
||||
|
||||
extern floatish *samplemap;
|
||||
extern floatish *markmap;
|
||||
|
||||
void GetHpFile PROTO((FILE *));
|
||||
void StoreSample PROTO((struct entry *, intish, floatish));
|
||||
struct entry *MakeEntry PROTO((char *));
|
||||
|
||||
token GetNumber PROTO((FILE *));
|
||||
void GetIdent PROTO((FILE *));
|
||||
void GetString PROTO((FILE *));
|
||||
boolish IsIdChar PROTO((int)); /* int is a "char" from getc */
|
||||
|
||||
extern char *jobstring;
|
||||
extern char *datestring;
|
||||
|
||||
extern char *sampleunitstring;
|
||||
extern char *valueunitstring;
|
||||
|
||||
#endif /* HP_FILE_H */
|
||||
17
massif/hp2ps/INSTALL
Normal file
17
massif/hp2ps/INSTALL
Normal file
@ -0,0 +1,17 @@
|
||||
NOTE: these are instructions for installing hp2ps separately. If you only want
|
||||
to use it with the Valgrind tool, Massif, it should be installed automatically.
|
||||
|
||||
The original Makefile, for which the below instructions apply, is kept as
|
||||
Makefile.old.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
For binary distribution:
|
||||
|
||||
- just copy "hp2ps" into an appropriate directory.
|
||||
|
||||
For source distribution:
|
||||
|
||||
- edit "Makefile" and set the $DSTBIN to the directory you wish to install
|
||||
hp2ps in
|
||||
|
||||
- do "make install"
|
||||
63
massif/hp2ps/Key.c
Normal file
63
massif/hp2ps/Key.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Dimensions.h"
|
||||
#include "HpFile.h"
|
||||
#include "Shade.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Key.h"
|
||||
|
||||
static void KeyEntry PROTO((floatish, char *, floatish));
|
||||
|
||||
void Key()
|
||||
{
|
||||
intish i;
|
||||
floatish c;
|
||||
floatish dc;
|
||||
|
||||
for (i = 0; i < nidents; i++) /* count identifiers */
|
||||
;
|
||||
|
||||
c = graphy0;
|
||||
dc = graphheight / (floatish) (i + 1);
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
c += dc;
|
||||
KeyEntry(c, identtable[i]->name, ShadeOf(identtable[i]->name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
KeyEntry(centreline, name, colour)
|
||||
floatish centreline; char* name; floatish colour;
|
||||
{
|
||||
floatish namebase;
|
||||
floatish keyboxbase;
|
||||
floatish kstart;
|
||||
|
||||
namebase = centreline - (floatish) (NORMAL_FONT / 2);
|
||||
keyboxbase = centreline - ((floatish) KEY_BOX_WIDTH / 2.0);
|
||||
|
||||
kstart = graphx0 + graphwidth;
|
||||
|
||||
fprintf(psfp, "%f %f moveto\n", kstart + borderspace, keyboxbase);
|
||||
fprintf(psfp, "0 %d rlineto\n", KEY_BOX_WIDTH);
|
||||
fprintf(psfp, "%d 0 rlineto\n", KEY_BOX_WIDTH);
|
||||
fprintf(psfp, "0 %d rlineto\n", -KEY_BOX_WIDTH);
|
||||
fprintf(psfp, "closepath\n");
|
||||
|
||||
fprintf(psfp, "gsave\n");
|
||||
SetPSColour(colour);
|
||||
fprintf(psfp, "fill\n");
|
||||
fprintf(psfp, "grestore\n");
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", NORMAL_FONT);
|
||||
fprintf(psfp, "%f %f moveto\n", kstart + (floatish) KEY_BOX_WIDTH + 2 * borderspace, namebase);
|
||||
|
||||
fprintf(psfp, "(%s) show\n", name);
|
||||
}
|
||||
6
massif/hp2ps/Key.h
Normal file
6
massif/hp2ps/Key.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef KEY_H
|
||||
#define KEY_H
|
||||
|
||||
void Key PROTO((void));
|
||||
|
||||
#endif /* KEY_H */
|
||||
31
massif/hp2ps/LICENSE
Normal file
31
massif/hp2ps/LICENSE
Normal file
@ -0,0 +1,31 @@
|
||||
The Glasgow Haskell Compiler License
|
||||
|
||||
Copyright 2002, The University Court of the University of Glasgow.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither name of the University nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
|
||||
GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
253
massif/hp2ps/Main.c
Normal file
253
massif/hp2ps/Main.c
Normal file
@ -0,0 +1,253 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "AuxFile.h"
|
||||
#include "AreaBelow.h"
|
||||
#include "Dimensions.h"
|
||||
#include "HpFile.h"
|
||||
#include "PsFile.h"
|
||||
#include "Reorder.h"
|
||||
#include "Scale.h"
|
||||
#include "TopTwenty.h"
|
||||
#include "TraceElement.h"
|
||||
#include "Deviation.h"
|
||||
#include "Error.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
boolish pflag = 0; /* read auxiliary file */
|
||||
boolish eflag = 0; /* scaled EPSF */
|
||||
boolish dflag = 0; /* sort by standard deviation */
|
||||
int iflag = 0; /* sort by identifier (3-way flag) */
|
||||
boolish gflag = 0; /* output suitable for previewer */
|
||||
boolish yflag = 0; /* ignore marks */
|
||||
boolish bflag = 0; /* use a big title box */
|
||||
boolish sflag = 0; /* use a small title box */
|
||||
int mflag = 0; /* max no. of bands displayed (default 20) */
|
||||
boolish tflag = 0; /* ignored threshold specified */
|
||||
boolish cflag = 0; /* colour output */
|
||||
|
||||
boolish filter; /* true when running as a filter */
|
||||
|
||||
static floatish WidthInPoints PROTO((char *)); /* forward */
|
||||
static FILE *Fp PROTO((char *, char **, char *, char *)); /* forward */
|
||||
|
||||
char *hpfile;
|
||||
char *psfile;
|
||||
char *auxfile;
|
||||
|
||||
char *programname;
|
||||
|
||||
static char *pathName;
|
||||
static char *baseName; /* "basename" is a std C library name (sigh) */
|
||||
|
||||
FILE* hpfp;
|
||||
FILE* psfp;
|
||||
FILE* auxfp;
|
||||
|
||||
floatish xrange = 0.0;
|
||||
floatish yrange = 0.0;
|
||||
|
||||
floatish auxxrange = 0.0;
|
||||
floatish auxyrange = 0.0;
|
||||
|
||||
floatish epsfwidth;
|
||||
floatish areabelow;
|
||||
|
||||
intish nsamples;
|
||||
intish nmarks;
|
||||
intish nidents;
|
||||
|
||||
floatish THRESHOLD_PERCENT = DEFAULT_THRESHOLD;
|
||||
int TWENTY = DEFAULT_TWENTY;
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char* argv[];
|
||||
{
|
||||
|
||||
programname = copystring(Basename(argv[0]));
|
||||
|
||||
argc--, argv++;
|
||||
while (argc && argv[0][0] == '-') {
|
||||
while (*++*argv)
|
||||
switch(**argv) {
|
||||
case 'p':
|
||||
pflag++;
|
||||
break;
|
||||
case 'e':
|
||||
eflag++;
|
||||
epsfwidth = WidthInPoints(*argv + 1);
|
||||
goto nextarg;
|
||||
case 'd':
|
||||
dflag++;
|
||||
goto nextarg;
|
||||
case 'i':
|
||||
switch( *(*argv + 1) ) {
|
||||
case '-':
|
||||
iflag = -1;
|
||||
case '+':
|
||||
default:
|
||||
iflag = 1;
|
||||
}
|
||||
goto nextarg;
|
||||
case 'g':
|
||||
gflag++;
|
||||
goto nextarg;
|
||||
case 'y':
|
||||
yflag++;
|
||||
goto nextarg;
|
||||
case 'b':
|
||||
bflag++;
|
||||
goto nextarg;
|
||||
case 's':
|
||||
sflag++;
|
||||
goto nextarg;
|
||||
case 'm':
|
||||
mflag++;
|
||||
TWENTY = atoi(*argv + 1);
|
||||
if (TWENTY > DEFAULT_TWENTY)
|
||||
Usage(*argv-1);
|
||||
goto nextarg;
|
||||
case 't':
|
||||
tflag++;
|
||||
THRESHOLD_PERCENT = (floatish) atof(*argv + 1);
|
||||
if (THRESHOLD_PERCENT < 0 || THRESHOLD_PERCENT > 5)
|
||||
Usage(*argv-1);
|
||||
goto nextarg;
|
||||
case 'c':
|
||||
cflag++;
|
||||
goto nextarg;
|
||||
case '?':
|
||||
default:
|
||||
Usage(*argv-1);
|
||||
}
|
||||
nextarg: ;
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
hpfile = "stdin";
|
||||
psfile = "stdout";
|
||||
|
||||
hpfp = stdin;
|
||||
psfp = stdout;
|
||||
|
||||
filter = argc < 1;
|
||||
|
||||
|
||||
|
||||
if (!filter) {
|
||||
pathName = copystring(argv[0]);
|
||||
DropSuffix(pathName, ".hp");
|
||||
baseName = copystring(Basename(pathName));
|
||||
|
||||
hpfp = Fp(pathName, &hpfile, ".hp", "r");
|
||||
psfp = Fp(baseName, &psfile, ".ps", "w");
|
||||
|
||||
if (pflag) auxfp = Fp(baseName, &auxfile, ".aux", "r");
|
||||
}
|
||||
|
||||
GetHpFile(hpfp);
|
||||
|
||||
if (!filter && pflag) GetAuxFile(auxfp);
|
||||
|
||||
|
||||
TraceElement(); /* Orders on total, Removes trace elements (tflag) */
|
||||
|
||||
if (dflag) Deviation(); /* ReOrders on deviation */
|
||||
|
||||
if (iflag) Identorder(iflag); /* ReOrders on identifier */
|
||||
|
||||
if (pflag) Reorder(); /* ReOrders on aux file */
|
||||
|
||||
if (TWENTY) TopTwenty(); /* Selects top twenty (mflag) */
|
||||
|
||||
Dimensions();
|
||||
|
||||
areabelow = AreaBelow();
|
||||
|
||||
Scale();
|
||||
|
||||
PutPsFile();
|
||||
|
||||
if (!filter) {
|
||||
auxfp = Fp(baseName, &auxfile, ".aux", "w");
|
||||
PutAuxFile(auxfp);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef enum {POINTS, INCHES, MILLIMETRES} pim;
|
||||
|
||||
static pim Units PROTO((char *)); /* forward */
|
||||
|
||||
static floatish
|
||||
WidthInPoints(wstr)
|
||||
char *wstr;
|
||||
{
|
||||
floatish result;
|
||||
|
||||
result = (floatish) atof(wstr);
|
||||
|
||||
switch (Units(wstr)) {
|
||||
case INCHES:
|
||||
result *= 72.0;
|
||||
break;
|
||||
case MILLIMETRES:
|
||||
result *= 2.834646;
|
||||
break;
|
||||
case POINTS:
|
||||
default: ;
|
||||
}
|
||||
|
||||
if (result <= 144) /* Minimum of 2in wide ! */
|
||||
Usage(wstr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static pim
|
||||
Units(wstr)
|
||||
char* wstr;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = strlen(wstr) - 2;
|
||||
|
||||
if (wstr[i] == 'p' && wstr[i+1] == 't') {
|
||||
return POINTS;
|
||||
} else if (wstr[i] == 'i' && wstr[i+1] == 'n') {
|
||||
return INCHES;
|
||||
} else if (wstr[i] == 'm' && wstr[i+1] == 'm') {
|
||||
return MILLIMETRES;
|
||||
} else {
|
||||
return POINTS;
|
||||
}
|
||||
}
|
||||
|
||||
static FILE *
|
||||
Fp(rootname, filename, suffix, mode)
|
||||
char* rootname; char** filename; char* suffix; char* mode;
|
||||
{
|
||||
*filename = copystring2(rootname, suffix);
|
||||
|
||||
return(OpenFile(*filename, mode));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
_stgAssert (filename, linenum)
|
||||
char *filename;
|
||||
unsigned int linenum;
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "ASSERTION FAILED: file %s, line %u\n", filename, linenum);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
78
massif/hp2ps/Main.h
Normal file
78
massif/hp2ps/Main.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
//#include "config.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
#define PROTO(x) x
|
||||
#else
|
||||
#define PROTO(x) ()
|
||||
#endif
|
||||
|
||||
/* our own ASSERT macro (for C) */
|
||||
#ifndef DEBUG
|
||||
#define ASSERT(predicate) /*nothing*/
|
||||
|
||||
#else
|
||||
void _ghcAssert PROTO((char *, unsigned int));
|
||||
|
||||
#define ASSERT(predicate) \
|
||||
if (predicate) \
|
||||
/*null*/; \
|
||||
else \
|
||||
_ghcAssert(__FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
/* partain: some ubiquitous types: floatish & intish.
|
||||
Dubious to use float/int, but that is what it used to be...
|
||||
(WDP 95/03)
|
||||
*/
|
||||
typedef double floatish;
|
||||
typedef double doublish; /* higher precision, if anything; little used */
|
||||
typedef int boolish;
|
||||
|
||||
/* Use "long long" if we have it: the numbers in profiles can easily
|
||||
* overflow 32 bits after a few seconds execution.
|
||||
*/
|
||||
#define HAVE_LONG_LONG 1 // --added by njn, because config.h removed
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
typedef long long int intish;
|
||||
#else
|
||||
typedef long int intish;
|
||||
#endif
|
||||
|
||||
extern intish nsamples;
|
||||
extern intish nmarks;
|
||||
extern intish nidents;
|
||||
|
||||
extern floatish maxcombinedheight;
|
||||
extern floatish areabelow;
|
||||
extern floatish epsfwidth;
|
||||
|
||||
extern floatish xrange;
|
||||
extern floatish yrange;
|
||||
|
||||
extern floatish auxxrange;
|
||||
extern floatish auxyrange;
|
||||
|
||||
extern boolish eflag;
|
||||
extern boolish gflag;
|
||||
extern boolish yflag;
|
||||
extern boolish bflag;
|
||||
extern boolish sflag;
|
||||
extern int mflag;
|
||||
extern boolish tflag;
|
||||
extern boolish cflag;
|
||||
|
||||
extern char *programname;
|
||||
|
||||
extern char *hpfile;
|
||||
extern char *psfile;
|
||||
extern char *auxfile;
|
||||
|
||||
extern FILE *hpfp;
|
||||
extern FILE *psfp;
|
||||
extern FILE *g_auxfp;
|
||||
|
||||
#endif /* MAIN_H */
|
||||
43
massif/hp2ps/Marks.c
Normal file
43
massif/hp2ps/Marks.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Curves.h"
|
||||
#include "Dimensions.h"
|
||||
#include "HpFile.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Marks.h"
|
||||
|
||||
static void Caret PROTO((floatish, floatish, floatish));
|
||||
|
||||
void
|
||||
Marks()
|
||||
{
|
||||
intish i;
|
||||
floatish m;
|
||||
|
||||
for (i = 0; i < nmarks; i++) {
|
||||
m = ((markmap[i] - samplemap[0]) / xrange) * graphwidth;
|
||||
Caret(xpage(m), ypage(0.0), 4.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Draw a small white caret at (x,y) with width 2 * d
|
||||
*/
|
||||
|
||||
static void
|
||||
Caret(x,y,d)
|
||||
floatish x; floatish y; floatish d;
|
||||
{
|
||||
fprintf(psfp, "%f %f moveto\n", x - d, y);
|
||||
fprintf(psfp, "%f %f rlineto\n", d, -d);
|
||||
fprintf(psfp, "%f %f rlineto\n", d, d);
|
||||
fprintf(psfp, "closepath\n");
|
||||
|
||||
fprintf(psfp, "gsave\n");
|
||||
fprintf(psfp, "1.0 setgray\n");
|
||||
fprintf(psfp, "fill\n");
|
||||
fprintf(psfp, "grestore\n");
|
||||
fprintf(psfp, "stroke\n");
|
||||
}
|
||||
6
massif/hp2ps/Marks.h
Normal file
6
massif/hp2ps/Marks.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef MARKS_H
|
||||
#define MARKS_H
|
||||
|
||||
void Marks PROTO((void));
|
||||
|
||||
#endif /* MARKS_H */
|
||||
280
massif/hp2ps/PsFile.c
Normal file
280
massif/hp2ps/PsFile.c
Normal file
@ -0,0 +1,280 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Dimensions.h"
|
||||
#include "Curves.h"
|
||||
#include "HpFile.h"
|
||||
#include "Axes.h"
|
||||
#include "Key.h"
|
||||
#include "Marks.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "PsFile.h"
|
||||
|
||||
static void Prologue PROTO((void)); /* forward */
|
||||
static void Variables PROTO((void)); /* forward */
|
||||
static void BorderOutlineBox PROTO((void)); /* forward */
|
||||
static void BigTitleOutlineBox PROTO((void)); /* forward */
|
||||
static void TitleOutlineBox PROTO((void)); /* forward */
|
||||
static void BigTitleText PROTO((void)); /* forward */
|
||||
static void TitleText PROTO((void)); /* forward */
|
||||
|
||||
void
|
||||
PutPsFile()
|
||||
{
|
||||
Prologue();
|
||||
Variables();
|
||||
BorderOutlineBox();
|
||||
|
||||
if (bflag) {
|
||||
BigTitleOutlineBox();
|
||||
BigTitleText();
|
||||
} else {
|
||||
TitleOutlineBox();
|
||||
TitleText();
|
||||
}
|
||||
|
||||
CurvesInit();
|
||||
|
||||
Axes();
|
||||
|
||||
if (TWENTY) Key();
|
||||
|
||||
Curves();
|
||||
|
||||
if (!yflag) Marks();
|
||||
|
||||
fprintf(psfp, "showpage\n");
|
||||
}
|
||||
|
||||
|
||||
static void StandardSpecialComments PROTO((void)); /* forward */
|
||||
static void EPSFSpecialComments PROTO((floatish)); /* forward */
|
||||
static void Landscape PROTO((void)); /* forward */
|
||||
static void Portrait PROTO((void)); /* forward */
|
||||
static void Scaling PROTO((floatish)); /* forward */
|
||||
|
||||
static void
|
||||
Prologue()
|
||||
{
|
||||
if (eflag) {
|
||||
floatish epsfscale = epsfwidth / (floatish) borderwidth;
|
||||
EPSFSpecialComments(epsfscale);
|
||||
Scaling(epsfscale);
|
||||
} else {
|
||||
StandardSpecialComments();
|
||||
if (gflag) Portrait(); else Landscape();
|
||||
}
|
||||
}
|
||||
|
||||
extern char *jobstring;
|
||||
extern char *datestring;
|
||||
|
||||
static void
|
||||
StandardSpecialComments()
|
||||
{
|
||||
fprintf(psfp, "%%!PS-Adobe-2.0\n");
|
||||
fprintf(psfp, "%%%%Title: %s\n", jobstring);
|
||||
fprintf(psfp, "%%%%Creator: %s (version %s)\n", programname, VERSION);
|
||||
fprintf(psfp, "%%%%CreationDate: %s\n", datestring);
|
||||
fprintf(psfp, "%%%%EndComments\n");
|
||||
}
|
||||
|
||||
static void
|
||||
EPSFSpecialComments(epsfscale)
|
||||
floatish epsfscale;
|
||||
{
|
||||
fprintf(psfp, "%%!PS-Adobe-2.0\n");
|
||||
fprintf(psfp, "%%%%Title: %s\n", jobstring);
|
||||
fprintf(psfp, "%%%%Creator: %s (version %s)\n", programname, VERSION);
|
||||
fprintf(psfp, "%%%%CreationDate: %s\n", datestring);
|
||||
fprintf(psfp, "%%%%BoundingBox: 0 0 %d %d\n",
|
||||
(int) (borderwidth * epsfscale + 0.5),
|
||||
(int) (borderheight * epsfscale + 0.5) );
|
||||
fprintf(psfp, "%%%%EndComments\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
Landscape()
|
||||
{
|
||||
fprintf(psfp, "-90 rotate\n");
|
||||
fprintf(psfp, "%f %f translate\n", -(borderwidth + (floatish) START_Y),
|
||||
(floatish) START_X);
|
||||
}
|
||||
|
||||
static void
|
||||
Portrait()
|
||||
{
|
||||
fprintf(psfp, "%f %f translate\n", (floatish) START_X, (floatish) START_Y);
|
||||
}
|
||||
|
||||
static void
|
||||
Scaling(epsfscale)
|
||||
floatish epsfscale;
|
||||
{
|
||||
fprintf(psfp, "%f %f scale\n", epsfscale, epsfscale);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Variables()
|
||||
{
|
||||
fprintf(psfp, "/HE%d /Helvetica findfont %d scalefont def\n",
|
||||
NORMAL_FONT, NORMAL_FONT);
|
||||
|
||||
fprintf(psfp, "/HE%d /Helvetica findfont %d scalefont def\n",
|
||||
LARGE_FONT, LARGE_FONT);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
BorderOutlineBox()
|
||||
{
|
||||
fprintf(psfp, "newpath\n");
|
||||
fprintf(psfp, "0 0 moveto\n");
|
||||
fprintf(psfp, "0 %f rlineto\n", borderheight);
|
||||
fprintf(psfp, "%f 0 rlineto\n", borderwidth);
|
||||
fprintf(psfp, "0 %f rlineto\n", -borderheight);
|
||||
fprintf(psfp, "closepath\n");
|
||||
fprintf(psfp, "%f setlinewidth\n", borderthick);
|
||||
fprintf(psfp, "stroke\n");
|
||||
}
|
||||
|
||||
static void
|
||||
BigTitleOutlineBox()
|
||||
{
|
||||
fprintf(psfp, "newpath\n");
|
||||
fprintf(psfp, "%f %f moveto\n", borderspace,
|
||||
borderheight - titleheight - borderspace);
|
||||
fprintf(psfp, "0 %f rlineto\n", titleheight);
|
||||
fprintf(psfp, "%f 0 rlineto\n", titlewidth);
|
||||
fprintf(psfp, "0 %f rlineto\n", -titleheight);
|
||||
fprintf(psfp, "closepath\n");
|
||||
fprintf(psfp, "%f setlinewidth\n", borderthick);
|
||||
fprintf(psfp, "stroke\n");
|
||||
|
||||
fprintf(psfp, "%f %f moveto\n", borderspace,
|
||||
borderheight - titleheight / 2 - borderspace);
|
||||
fprintf(psfp, "%f 0 rlineto\n", titlewidth);
|
||||
fprintf(psfp, "stroke\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TitleOutlineBox()
|
||||
{
|
||||
fprintf(psfp, "newpath\n");
|
||||
fprintf(psfp, "%f %f moveto\n", borderspace,
|
||||
borderheight - titleheight - borderspace);
|
||||
fprintf(psfp, "0 %f rlineto\n", titleheight);
|
||||
fprintf(psfp, "%f 0 rlineto\n", titlewidth);
|
||||
fprintf(psfp, "0 %f rlineto\n", -titleheight);
|
||||
fprintf(psfp, "closepath\n");
|
||||
fprintf(psfp, "%f setlinewidth\n", borderthick);
|
||||
fprintf(psfp, "stroke\n");
|
||||
}
|
||||
|
||||
static void EscapePrint PROTO((char *, int)); /* forward */
|
||||
|
||||
static void
|
||||
BigTitleText()
|
||||
{
|
||||
floatish x, y;
|
||||
|
||||
x = borderspace + titletextspace;
|
||||
y = borderheight - titleheight / 2 - borderspace + titletextspace;
|
||||
|
||||
/* job identifier goes on top at the far left */
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", TITLE_TEXT_FONT);
|
||||
fprintf(psfp, "%f %f moveto\n", x, y);
|
||||
fputc('(', psfp);
|
||||
EscapePrint(jobstring, BIG_JOB_STRING_WIDTH);
|
||||
fprintf(psfp, ") show\n");
|
||||
|
||||
y = borderheight - titleheight - borderspace + titletextspace;
|
||||
|
||||
/* area below curve gows at the botton, far left */
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", TITLE_TEXT_FONT);
|
||||
fprintf(psfp, "%f %f moveto\n", x, y);
|
||||
fputc('(', psfp);
|
||||
CommaPrint(psfp, (intish)areabelow);
|
||||
fprintf(psfp, " %s x %s)\n", valueunitstring, sampleunitstring);
|
||||
fprintf(psfp, "show\n");
|
||||
|
||||
/* date goes at far right */
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", TITLE_TEXT_FONT);
|
||||
fprintf(psfp, "(%s)\n", datestring);
|
||||
fprintf(psfp, "dup stringwidth pop\n");
|
||||
fprintf(psfp, "%f\n", (titlewidth + borderspace) - titletextspace);
|
||||
fprintf(psfp, "exch sub\n");
|
||||
fprintf(psfp, "%f moveto\n", y);
|
||||
fprintf(psfp, "show\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
TitleText()
|
||||
{
|
||||
floatish x, y;
|
||||
|
||||
x = borderspace + titletextspace;
|
||||
y = borderheight - titleheight - borderspace + titletextspace;
|
||||
|
||||
/* job identifier goes at far left */
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", TITLE_TEXT_FONT);
|
||||
fprintf(psfp, "%f %f moveto\n", x, y);
|
||||
fputc('(', psfp);
|
||||
EscapePrint(jobstring, SMALL_JOB_STRING_WIDTH);
|
||||
fprintf(psfp, ") show\n");
|
||||
|
||||
/* area below curve is centered */
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", TITLE_TEXT_FONT);
|
||||
fputc('(', psfp);
|
||||
CommaPrint(psfp, (intish) areabelow);
|
||||
fprintf(psfp, " %s x %s)\n", valueunitstring, sampleunitstring);
|
||||
|
||||
fprintf(psfp, "dup stringwidth pop\n");
|
||||
fprintf(psfp, "2 div\n");
|
||||
fprintf(psfp, "%f\n", titlewidth / 2);
|
||||
fprintf(psfp, "exch sub\n");
|
||||
fprintf(psfp, "%f moveto\n", y);
|
||||
fprintf(psfp, "show\n");
|
||||
|
||||
/* date goes at far right */
|
||||
|
||||
fprintf(psfp, "HE%d setfont\n", TITLE_TEXT_FONT);
|
||||
fprintf(psfp, "(%s)\n", datestring);
|
||||
fprintf(psfp, "dup stringwidth pop\n");
|
||||
fprintf(psfp, "%f\n", (titlewidth + borderspace) - titletextspace);
|
||||
fprintf(psfp, "exch sub\n");
|
||||
fprintf(psfp, "%f moveto\n", y);
|
||||
fprintf(psfp, "show\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string s in width w, escaping characters where necessary.
|
||||
*/
|
||||
|
||||
static void
|
||||
EscapePrint(s,w)
|
||||
char* s; int w;
|
||||
{
|
||||
for ( ; *s && w > 0; s++, w--) {
|
||||
if (*s == '(') { /* escape required */
|
||||
fputc('\\', psfp);
|
||||
} else if (*s == ')') {
|
||||
fputc('\\', psfp);
|
||||
}
|
||||
|
||||
fputc(*s, psfp);
|
||||
}
|
||||
}
|
||||
6
massif/hp2ps/PsFile.h
Normal file
6
massif/hp2ps/PsFile.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PS_FILE_H
|
||||
#define PS_FILE_H
|
||||
|
||||
void PutPsFile PROTO((void));
|
||||
|
||||
#endif /* PS_FILE_H */
|
||||
1
massif/hp2ps/README
Normal file
1
massif/hp2ps/README
Normal file
@ -0,0 +1 @@
|
||||
This "hp2ps" program was written by Dave Wakeling at York.
|
||||
89
massif/hp2ps/Reorder.c
Normal file
89
massif/hp2ps/Reorder.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Reorder.h"
|
||||
|
||||
static struct order {
|
||||
char* ident;
|
||||
int order;
|
||||
} *ordermap = 0;
|
||||
|
||||
static int ordermapmax = 0;
|
||||
static int ordermapindex = 0;
|
||||
|
||||
|
||||
void
|
||||
OrderFor(ident, order)
|
||||
char* ident;
|
||||
int order;
|
||||
{
|
||||
if (! ordermap) {
|
||||
ordermapmax = (nidents > TWENTY ? nidents : TWENTY) * 2;
|
||||
/* Assume nidents read is indication of the No of
|
||||
idents in the .aux file (*2 for good luck !) */
|
||||
ordermap = xmalloc(ordermapmax * sizeof(struct order));
|
||||
}
|
||||
|
||||
if (ordermapindex < ordermapmax) {
|
||||
ordermap[ ordermapindex ].ident = copystring(ident);
|
||||
ordermap[ ordermapindex ].order = order;
|
||||
ordermapindex++;
|
||||
} else {
|
||||
Disaster("order map overflow");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the order of to be used for "ident" if there is one.
|
||||
* Otherwise, return 0 which is the minimum ordering value.
|
||||
*/
|
||||
|
||||
int
|
||||
OrderOf(ident)
|
||||
char* ident;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ordermapindex; i++) {
|
||||
if (strcmp(ordermap[i].ident, ident) == 0) { /* got it */
|
||||
return(ordermap[i].order);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reorder on the basis of information from ".aux" file.
|
||||
*/
|
||||
|
||||
void
|
||||
Reorder()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
int min;
|
||||
struct entry* e;
|
||||
int o1, o2;
|
||||
|
||||
for (i = 0; i < nidents-1; i++) {
|
||||
min = i;
|
||||
for (j = i+1; j < nidents; j++) {
|
||||
o1 = OrderOf(identtable[ j ]->name);
|
||||
o2 = OrderOf(identtable[ min ]->name);
|
||||
|
||||
if (o1 < o2 ) min = j;
|
||||
}
|
||||
|
||||
e = identtable[ min ];
|
||||
identtable[ min ] = identtable[ i ];
|
||||
identtable[ i ] = e;
|
||||
}
|
||||
}
|
||||
8
massif/hp2ps/Reorder.h
Normal file
8
massif/hp2ps/Reorder.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef REORDER_H
|
||||
#define REORDER_H
|
||||
|
||||
void Reorder PROTO((void));
|
||||
int OrderOf PROTO((char *));
|
||||
void OrderFor PROTO((char *, int));
|
||||
|
||||
#endif /* REORDER_H */
|
||||
87
massif/hp2ps/Scale.c
Normal file
87
massif/hp2ps/Scale.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Dimensions.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Scale.h"
|
||||
|
||||
/*
|
||||
* Return the maximum combined height that all the sample
|
||||
* curves will reach. This (absolute) figure can then be
|
||||
* used to scale the samples automatically so that they
|
||||
* fit on the page.
|
||||
*/
|
||||
|
||||
extern void free();
|
||||
|
||||
floatish
|
||||
MaxCombinedHeight()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
floatish mx;
|
||||
int bucket;
|
||||
floatish value;
|
||||
struct chunk* ch;
|
||||
floatish *maxima;
|
||||
|
||||
maxima = (floatish*) xmalloc(nsamples * sizeof(floatish));
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
maxima[ i ] = 0.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
bucket = ch->d[j].bucket;
|
||||
value = ch->d[j].value;
|
||||
if (bucket >= nsamples)
|
||||
Disaster("bucket out of range");
|
||||
maxima[ bucket ] += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (mx = maxima[ 0 ], i = 0; i < nsamples; i++) {
|
||||
if (maxima[ i ] > mx) mx = maxima[ i ];
|
||||
}
|
||||
|
||||
free(maxima);
|
||||
return mx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Scale the values from the samples so that they will fit on
|
||||
* the page.
|
||||
*/
|
||||
|
||||
extern floatish xrange;
|
||||
extern floatish yrange;
|
||||
|
||||
void
|
||||
Scale()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
floatish sf;
|
||||
struct chunk* ch;
|
||||
|
||||
if (yrange == 0.0) /* no samples */
|
||||
return;
|
||||
|
||||
sf = graphheight / yrange;
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
ch->d[j].value = ch->d[j].value * sf;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
massif/hp2ps/Scale.h
Normal file
7
massif/hp2ps/Scale.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef SCALE_H
|
||||
#define SCALE_H
|
||||
|
||||
floatish MaxCombinedHeight PROTO((void));
|
||||
void Scale PROTO((void));
|
||||
|
||||
#endif /* SCALE_H */
|
||||
130
massif/hp2ps/Shade.c
Normal file
130
massif/hp2ps/Shade.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "Shade.h"
|
||||
|
||||
static struct shade {
|
||||
char* ident;
|
||||
floatish shade;
|
||||
} *shademap;
|
||||
|
||||
static int shademapmax = 0;
|
||||
static int shademapindex = 0;
|
||||
|
||||
/*
|
||||
* Set the shade to be used for "ident" to "shade".
|
||||
*/
|
||||
|
||||
void
|
||||
ShadeFor(ident, shade)
|
||||
char* ident;
|
||||
floatish shade;
|
||||
{
|
||||
if (! shademap) {
|
||||
shademapmax = (nidents > TWENTY ? nidents : TWENTY) * 2;
|
||||
/* Assume nidents read is indication of the No of
|
||||
idents in the .aux file (*2 for good luck) */
|
||||
/* NB *2 is needed as .aux and .hp elements may differ */
|
||||
shademap = xmalloc(shademapmax * sizeof(struct shade));
|
||||
}
|
||||
|
||||
if (shademapindex < shademapmax) {
|
||||
shademap[ shademapindex ].ident = copystring(ident);
|
||||
shademap[ shademapindex ].shade = shade;
|
||||
shademapindex++;
|
||||
} else {
|
||||
Disaster("shade map overflow");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the shade to be used for "ident" if there is one.
|
||||
* Otherwise, think of a new one.
|
||||
*/
|
||||
|
||||
static floatish ThinkOfAShade PROTO((void)); /* forward */
|
||||
|
||||
floatish
|
||||
ShadeOf(ident)
|
||||
char* ident;
|
||||
{
|
||||
int i;
|
||||
floatish shade;
|
||||
|
||||
for (i = 0; i < shademapindex; i++) {
|
||||
if (strcmp(shademap[i].ident, ident) == 0) { /* got it */
|
||||
return(shademap[i].shade);
|
||||
}
|
||||
}
|
||||
|
||||
shade = ThinkOfAShade();
|
||||
|
||||
ShadeFor(ident, shade);
|
||||
|
||||
return shade;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define N_MONO_SHADES 10
|
||||
|
||||
static floatish m_shades[ N_MONO_SHADES ] = {
|
||||
0.00000, 0.20000, 0.60000, 0.30000, 0.90000,
|
||||
0.40000, 1.00000, 0.70000, 0.50000, 0.80000
|
||||
};
|
||||
|
||||
#define N_COLOUR_SHADES 27
|
||||
|
||||
/* HACK: 0.100505 means 100% red, 50% green, 50% blue */
|
||||
|
||||
static floatish c_shades[ N_COLOUR_SHADES ] = {
|
||||
0.000000, 0.000010, 0.001000, 0.001010, 0.100000,
|
||||
0.100010, 0.101000, 0.101010, 0.000005, 0.000500,
|
||||
0.000510, 0.001005, 0.050000, 0.050010, 0.051000,
|
||||
0.051010, 0.100005, 0.100500, 0.100510, 0.101005,
|
||||
0.000505, 0.050005, 0.050500, 0.050510, 0.051005,
|
||||
0.100505, 0.050505
|
||||
};
|
||||
|
||||
static floatish
|
||||
ThinkOfAShade()
|
||||
{
|
||||
static int thisshade = -1;
|
||||
|
||||
thisshade++;
|
||||
return cflag ?
|
||||
c_shades[ thisshade % N_COLOUR_SHADES ] :
|
||||
m_shades[ thisshade % N_MONO_SHADES ] ;
|
||||
}
|
||||
|
||||
static floatish
|
||||
extract_colour(shade,factor)
|
||||
floatish shade;
|
||||
intish factor;
|
||||
{
|
||||
intish i,j;
|
||||
|
||||
i = (int)(shade * factor);
|
||||
j = i / 100;
|
||||
return (i - j * 100) / 10.0;
|
||||
}
|
||||
|
||||
void
|
||||
SetPSColour(shade)
|
||||
floatish shade;
|
||||
{
|
||||
if (cflag) {
|
||||
fprintf(psfp, "%f %f %f setrgbcolor\n",
|
||||
extract_colour(shade, (intish)100),
|
||||
extract_colour(shade, (intish)10000),
|
||||
extract_colour(shade, (intish)1000000));
|
||||
} else {
|
||||
fprintf(psfp, "%f setgray\n", shade);
|
||||
}
|
||||
}
|
||||
8
massif/hp2ps/Shade.h
Normal file
8
massif/hp2ps/Shade.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef SHADE_H
|
||||
#define SHADE_H
|
||||
|
||||
floatish ShadeOf PROTO((char *));
|
||||
void ShadeFor PROTO((char *, floatish));
|
||||
void SetPSColour PROTO((floatish));
|
||||
|
||||
#endif /* SHADE_H */
|
||||
73
massif/hp2ps/TopTwenty.c
Normal file
73
massif/hp2ps/TopTwenty.c
Normal file
@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "HpFile.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "TopTwenty.h"
|
||||
|
||||
/*
|
||||
* We only have room in the key for a maximum of 20 identifiers.
|
||||
* We therefore choose to keep the top 20 bands --- these will
|
||||
* be the most important ones, since this pass is performed after
|
||||
* the threshold and standard deviation passes. If there are more
|
||||
* than 20 bands, the excess are gathered together as an "OTHER" ]
|
||||
* band which appears as band 20.
|
||||
*/
|
||||
|
||||
extern void free();
|
||||
|
||||
void
|
||||
TopTwenty()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
intish compact;
|
||||
intish bucket;
|
||||
floatish value;
|
||||
struct entry* en;
|
||||
struct chunk* ch;
|
||||
floatish *other;
|
||||
|
||||
i = nidents;
|
||||
if (i <= TWENTY) return; /* nothing to do! */
|
||||
|
||||
other = (floatish*) xmalloc(nsamples * sizeof(floatish));
|
||||
/* build a list of samples for "OTHER" */
|
||||
|
||||
compact = (i - TWENTY) + 1;
|
||||
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
other[ i ] = 0.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < compact && i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
bucket = ch->d[j].bucket;
|
||||
value = ch->d[j].value;
|
||||
if (bucket >= nsamples)
|
||||
Disaster("bucket out of range");
|
||||
other[ bucket ] += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
en = MakeEntry("OTHER");
|
||||
en->next = 0;
|
||||
|
||||
for (i = 0; i < nsamples; i++) {
|
||||
StoreSample(en, i, other[i]);
|
||||
}
|
||||
|
||||
/* slide samples down */
|
||||
for (i = compact; i < nidents; i++) {
|
||||
identtable[i-compact+1] = identtable[i];
|
||||
}
|
||||
|
||||
nidents = TWENTY;
|
||||
identtable[0] = en;
|
||||
free(other);
|
||||
}
|
||||
6
massif/hp2ps/TopTwenty.h
Normal file
6
massif/hp2ps/TopTwenty.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef TOP_TWENTY_H
|
||||
#define TOP_TWENTY_H
|
||||
|
||||
void TopTwenty PROTO((void));
|
||||
|
||||
#endif /* TOP_TWENTY_H */
|
||||
97
massif/hp2ps/TraceElement.c
Normal file
97
massif/hp2ps/TraceElement.c
Normal file
@ -0,0 +1,97 @@
|
||||
#include <stdio.h>
|
||||
#include "Main.h"
|
||||
#include "Defines.h"
|
||||
#include "HpFile.h"
|
||||
#include "Error.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
/* own stuff */
|
||||
#include "TraceElement.h"
|
||||
|
||||
/*
|
||||
* Compute the total volume for each identifier, and the grand
|
||||
* total of these totals. The identifiers whose totals when
|
||||
* added together amount to less that a threshold percentage
|
||||
* (default 1%) of the grand total are considered to be ``trace
|
||||
* elements'' and they are thrown away.
|
||||
*/
|
||||
|
||||
extern void free();
|
||||
|
||||
extern floatish thresholdpercent;
|
||||
|
||||
void TraceElement()
|
||||
{
|
||||
intish i;
|
||||
intish j;
|
||||
struct chunk* ch;
|
||||
floatish grandtotal;
|
||||
intish min;
|
||||
floatish t;
|
||||
floatish p;
|
||||
struct entry* e;
|
||||
intish *totals;
|
||||
|
||||
totals = (intish *) xmalloc(nidents * sizeof(intish));
|
||||
|
||||
/* find totals */
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
totals[ i ] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
for (ch = identtable[i]->chk; ch; ch = ch->next) {
|
||||
for (j = 0; j < ch->nd; j++) {
|
||||
totals[ i ] += ch->d[j].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sort on the basis of total */
|
||||
|
||||
for (i = 0; i < nidents-1; i++) {
|
||||
min = i;
|
||||
for (j = i+1; j < nidents; j++) {
|
||||
if (totals[ j ] < totals[ min ]) {
|
||||
min = j;
|
||||
}
|
||||
}
|
||||
|
||||
t = totals[ min ];
|
||||
totals[ min ] = totals[ i ];
|
||||
totals[ i ] = t;
|
||||
|
||||
e = identtable[ min ];
|
||||
identtable[ min ] = identtable[ i ];
|
||||
identtable[ i ] = e;
|
||||
}
|
||||
|
||||
|
||||
/* find the grand total (NB: can get *BIG*!) */
|
||||
|
||||
grandtotal = 0.0;
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
grandtotal += (floatish) totals[ i ];
|
||||
}
|
||||
|
||||
t = 0.0; /* cumulative percentage */
|
||||
|
||||
for (i = 0; i < nidents; i++) {
|
||||
p = (100.0 * (floatish) totals[i]) / grandtotal;
|
||||
t = t + p;
|
||||
if (t >= THRESHOLD_PERCENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* identifiers from 0 to i-1 should be removed */
|
||||
for (j = 0; i < nidents; i++, j++) {
|
||||
identtable[j] = identtable[i];
|
||||
}
|
||||
|
||||
nidents = j;
|
||||
|
||||
free(totals);
|
||||
}
|
||||
6
massif/hp2ps/TraceElement.h
Normal file
6
massif/hp2ps/TraceElement.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef TRACE_ELEMENT_H
|
||||
#define TRACE_ELEMENT_H
|
||||
|
||||
void TraceElement PROTO((void));
|
||||
|
||||
#endif /* TRACE_ELEMENT_H */
|
||||
132
massif/hp2ps/Utilities.c
Normal file
132
massif/hp2ps/Utilities.c
Normal file
@ -0,0 +1,132 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Main.h"
|
||||
#include "Error.h"
|
||||
|
||||
extern void* malloc();
|
||||
|
||||
char*
|
||||
Basename(name)
|
||||
char* name;
|
||||
{
|
||||
char* t;
|
||||
|
||||
t = name;
|
||||
|
||||
while (*name) {
|
||||
if (*name == '/') {
|
||||
t = name+1;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
DropSuffix(name, suffix)
|
||||
char* name; char* suffix;
|
||||
{
|
||||
char* t;
|
||||
|
||||
t = (char*) 0;
|
||||
|
||||
while (*name) {
|
||||
if (*name == '.') {
|
||||
t = name;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
|
||||
if (t != (char*) 0 && strcmp(t, suffix) == 0) {
|
||||
*t = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
FILE*
|
||||
OpenFile(s, mode)
|
||||
char* s; char* mode;
|
||||
{
|
||||
FILE* r;
|
||||
|
||||
if ((r = fopen(s, mode)) == NULL) {
|
||||
/*NOTREACHED*/
|
||||
Error("cannot open %s", s);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#define ONETHOUSAND 1000
|
||||
|
||||
/*
|
||||
* Print a positive integer with commas
|
||||
*/
|
||||
|
||||
void
|
||||
CommaPrint(fp,n)
|
||||
FILE* fp;
|
||||
intish n;
|
||||
{
|
||||
if (n < ONETHOUSAND) {
|
||||
fprintf(fp, "%d", (int)n);
|
||||
} else {
|
||||
CommaPrint(fp, n / ONETHOUSAND);
|
||||
fprintf(fp, ",%03d", (int)n % ONETHOUSAND);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc(n)
|
||||
int n;
|
||||
{
|
||||
void *r;
|
||||
|
||||
r = (void*) malloc(n);
|
||||
if (!r) {
|
||||
/*NOTREACHED*/
|
||||
Disaster("%s, sorry, out of memory", hpfile);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void *
|
||||
xrealloc(p, n)
|
||||
void *p;
|
||||
int n;
|
||||
{
|
||||
void *r;
|
||||
extern void *realloc();
|
||||
|
||||
r = realloc(p, n);
|
||||
if (!r) {
|
||||
/*NOTREACHED*/
|
||||
Disaster("%s, sorry, out of memory", hpfile);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
copystring(s)
|
||||
char *s;
|
||||
{
|
||||
char *r;
|
||||
|
||||
r = (char*) xmalloc(strlen(s)+1);
|
||||
strcpy(r, s);
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
copystring2(s, t)
|
||||
char *s, *t;
|
||||
{
|
||||
char *r;
|
||||
|
||||
r = (char*) xmalloc(strlen(s)+strlen(t)+1);
|
||||
strcpy(r, s);
|
||||
strcat(r, t);
|
||||
return r;
|
||||
}
|
||||
|
||||
13
massif/hp2ps/Utilities.h
Normal file
13
massif/hp2ps/Utilities.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef UTILITIES_H
|
||||
#define UTILITIES_H
|
||||
|
||||
char* Basename PROTO((char *));
|
||||
void DropSuffix PROTO((char *, char *));
|
||||
FILE* OpenFile PROTO((char *, char *));
|
||||
void CommaPrint PROTO((FILE *, intish));
|
||||
char *copystring PROTO((char *));
|
||||
char *copystring2 PROTO((char *, char *));
|
||||
void *xmalloc PROTO((int));
|
||||
void *xrealloc PROTO((void *, int));
|
||||
|
||||
#endif /* UTILITIES_H */
|
||||
145
massif/hp2ps/hp2ps.1
Normal file
145
massif/hp2ps/hp2ps.1
Normal file
@ -0,0 +1,145 @@
|
||||
.\" man page for hp2ps
|
||||
.ds PS P\s-2OST\s+2S\s-2CRIPT\s+2
|
||||
.\" typeset examples in fixed size font as indented paragraph
|
||||
.de Ex
|
||||
.sp
|
||||
.RS
|
||||
.nf
|
||||
.ft C
|
||||
..
|
||||
.de Xe
|
||||
.RE
|
||||
.sp
|
||||
.fi
|
||||
..
|
||||
.TH HP2PS 1 "18 April 1992"
|
||||
.SH NAME
|
||||
hp2ps \- convert a heap profile to a \*(PS graph
|
||||
.SH SYNOPSIS
|
||||
.B hp2ps
|
||||
[flags] [file][.hp]
|
||||
.SH DESCRIPTION
|
||||
The program
|
||||
.B hp2ps
|
||||
converts a heap profile stored in
|
||||
.IR file
|
||||
into a \*(PS graph, sending the result to
|
||||
.IR file.ps.
|
||||
By convention, files to be processed by
|
||||
.B hp2ps
|
||||
have a
|
||||
.I .hp
|
||||
extension. However, for compatibility with older versions of
|
||||
.B hp2ps,
|
||||
this extension can be omitted. If
|
||||
.IR file
|
||||
is omitted entirely, then the program behaves as a filter.
|
||||
.SH OPTIONS
|
||||
The flags are:
|
||||
.IP "\fB\-d\fP"
|
||||
In order to make graphs more readable,
|
||||
.B hp2ps
|
||||
sorts the shaded bands for each identifier. The default sort ordering is for
|
||||
the bands with the largest area to be stacked on top of the smaller ones.
|
||||
The
|
||||
.B \-d
|
||||
option causes rougher bands (those reprsenting series of values with the
|
||||
largest standard deviations) to be stacked on top of smoother ones.
|
||||
.IP "\fB\-b\fP"
|
||||
Normally,
|
||||
.B hp2ps
|
||||
puts the title of the graph in a small box at the top of the page. However,
|
||||
if the JOB string is too long to fit in a small box (more than 35 characters),
|
||||
then
|
||||
.B hp2ps
|
||||
will choose to use a big box instead. The
|
||||
.B \-b
|
||||
option forces
|
||||
.B hp2ps
|
||||
to use a big box.
|
||||
.IP "\fB\-e\fP \fIfloat\fP[in|mm|pt]"
|
||||
Generate encapsulated \*(PS suitable for inclusion in LaTeX documents.
|
||||
Usually, the \*(PS graph is drawn in landscape mode in an area
|
||||
9 inches wide by 6 inches high, and
|
||||
.B hp2ps
|
||||
arranges for this area to be approximately centered on a sheet of a4
|
||||
paper. This format is convenient of studying the graph in detail, but
|
||||
it is unsuitable for inclusion in LaTeX documents. The
|
||||
.B \-e
|
||||
option causes the graph to be drawn in portrait mode, with
|
||||
.I float
|
||||
specifying the width in inches, millimetres or points (the default).
|
||||
The resulting \*(PS file conforms to the
|
||||
.I "Encapsulated Post Script"
|
||||
(EPS) convention, and it can be included in a LaTeX document using Rokicki's
|
||||
dvi-to-\*(PS converter
|
||||
.B dvips.
|
||||
.B hp2ps
|
||||
requires the width to exceed 2 inches.
|
||||
.IP "\fB\-g\fP"
|
||||
Create output suitable for the
|
||||
.B gs
|
||||
\*(PS previewer (or similar). In this case the graph is printed in portrait
|
||||
mode without scaling. The output is unsuitable for a laser printer.
|
||||
.IP "\fB\-p\fP"
|
||||
Use previous parameters. By default, the \*(PS graph is automatically
|
||||
scaled both horizontally and vertically so that it fills the page.
|
||||
However, when preparing a seires of graphs for use in a presentation,
|
||||
it is often useful to draw a new graph using the same scale, shading and
|
||||
ordering as a previous one. The
|
||||
.B \-p
|
||||
flag causes the graph to be drawn using the parameters determined by
|
||||
a previous run of
|
||||
.B hp2ps
|
||||
on
|
||||
.IR file.
|
||||
.IP "\fB\-s\fP"
|
||||
Use a small box for the title.
|
||||
.IP "\fB\-y\fP"
|
||||
Draw the graph in the traditional York style, ignoring marks.
|
||||
.IP "\fB\-?\fP"
|
||||
Print out usage information.
|
||||
.SH "INPUT FORMAT"
|
||||
The format of a heap profile is best described by example:
|
||||
.Ex
|
||||
JOB "a.out -p"
|
||||
DATE "Fri Apr 17 11:43:45 1992"
|
||||
SAMPLE_UNIT "seconds"
|
||||
VALUE_UNIT "bytes"
|
||||
BEGIN_SAMPLE 0.00
|
||||
SYSTEM 24
|
||||
END_SAMPLE 0.00
|
||||
BEGIN_SAMPLE 1.00
|
||||
elim 180
|
||||
insert 24
|
||||
intersect 12
|
||||
disin 60
|
||||
main 12
|
||||
reduce 20
|
||||
SYSTEM 12
|
||||
END_SAMPLE 1.00
|
||||
MARK 1.50
|
||||
MARK 1.75
|
||||
MARK 1.80
|
||||
BEGIN_SAMPLE 2.00
|
||||
elim 192
|
||||
insert 24
|
||||
intersect 12
|
||||
disin 84
|
||||
main 12
|
||||
SYSTEM 24
|
||||
END_SAMPLE 2.00
|
||||
BEGIN_SAMPLE 2.82
|
||||
END_SAMPLE 2.82
|
||||
|
||||
.Xe
|
||||
.SH "SEE ALSO"
|
||||
dvips(1), latex(1), hbchp (1), lmlchp(1)
|
||||
.br
|
||||
C. Runciman and D. Wakeling,
|
||||
.I
|
||||
Heap Profiling for Lazy Functional Languages, YCS-172, University of York, 1992
|
||||
.SH NOTES
|
||||
\*(PS is a registered trademark of Adobe Systems Incorporated.
|
||||
.SH AUTHOR
|
||||
David Wakeling of the University of York.
|
||||
1815
massif/ms_main.c
Normal file
1815
massif/ms_main.c
Normal file
File diff suppressed because it is too large
Load Diff
6
massif/tests/Makefile.am
Normal file
6
massif/tests/Makefile.am
Normal file
@ -0,0 +1,6 @@
|
||||
noinst_SCRIPTS = filter_stderr
|
||||
|
||||
EXTRA_DIST = $(noinst_SCRIPTS) \
|
||||
true_html.stderr.exp true_html.vgtest \
|
||||
true_text.stderr.exp true_text.vgtest
|
||||
|
||||
6
massif/tests/true_html.stderr.exp
Normal file
6
massif/tests/true_html.stderr.exp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
Total spacetime:
|
||||
heap:
|
||||
heap admin:
|
||||
stack(s):
|
||||
2
massif/tests/true_html.vgtest
Normal file
2
massif/tests/true_html.vgtest
Normal file
@ -0,0 +1,2 @@
|
||||
prog: ../../tests/true
|
||||
vgopts: --format=html
|
||||
6
massif/tests/true_text.stderr.exp
Normal file
6
massif/tests/true_text.stderr.exp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
Total spacetime:
|
||||
heap:
|
||||
heap admin:
|
||||
stack(s):
|
||||
2
massif/tests/true_text.vgtest
Normal file
2
massif/tests/true_text.vgtest
Normal file
@ -0,0 +1,2 @@
|
||||
prog: ../../tests/true
|
||||
vgopts: --format=text
|
||||
Loading…
x
Reference in New Issue
Block a user