+++ /dev/null
-#include "Main.h"
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.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 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;
-
- 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(ch)) { /* skip whitespace */
- if (ch == '\n') linenum++;
- ch = getc(infp);
- }
-
- if (ch == EOF) {
- thetok = EOF_TOK;
- return;
- }
-
- if (isdigit(ch)) {
- thetok = GetNumber(infp);
- return;
- } else if (ch == '\"') {
- GetString(infp);
- thetok = STRING_TOK;
- return;
- } else if (IsIdChar(ch)) {
- ASSERT(! (isdigit(ch))); /* ch can't be a digit here */
- GetIdent(infp);
- if (!isupper((int)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, 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(ch) || ch == '.'); i++) {
- numberstring[ i ] = ch;
- containsdot |= (ch == '.');
- 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(ch); i++) {
- idbuffer[ i ] = ch;
- 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 == '\"');
-
- ch = getc(infp); /* skip the '\"' that begins the string */
-
- for (i = 0; i < (sizeof stringbuffer)-1 && ch != '\"'; i++) {
- stringbuffer[ i ] = ch;
- ch = getc(infp);
- }
-
- stringbuffer[i] = '\0';
- thestring = copystring(stringbuffer);
-
- ASSERT(ch == '\"');
-
- 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;
- }
- }
-}