Home   -   Gallery   Geology   Music   Software   Hiking   Links   Sport   What?  
Projects   Sources   V4   Flightsim   Joystick   Workshop  
ACM   EPIC   F22   FGFly   FGFS   FLSIM   FLUSH   Fly8   F.o.F.   FS-98   GNU   LaRCsim   More   Vertigo  
Directory   Calculation   Inventory  
Page 321 of 401
 <   > 

(Inventory.c 20241 Bytes 25.09.1997 13:48, renamed to Fb_14inv.htm)

/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 1991-1994  Riley Rainey
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 dated June, 1991.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program;  if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <ctype.h>
#include <pm.h>
#if defined(HAVE_STDLIB_H)
#include <stdlib.h>
#else
#include <malloc.h>
#endif

struct lex_record;

int       ParseAircraft(struct lex_record *p, craftType ** c1), ParseValue(struct lex_record *p),
          ParseTable(struct lex_record *p), ParsePoint(struct lex_record *p);
int       ParseStation(struct lex_record *p);
int       ParseDISEntityType(struct lex_record *p);

static craftType c;

extern craftType *newCraft(void);

extern double genericThrust PARAMS((craft *));
extern void genericResupply PARAMS((craft *));

typedef enum {
   RESERVED_WORD,
   vtDOUBLE,
   vtLONG,
   vtANGLE,
   vtNMILES,
   vtKNOTS,
   vtTABLE,
   vtPOINT,
   vtSTRING,
   vtSTATION,
   vtENTITY
} value_type;

typedef enum {
   Nil,
   EndOfFile,

/*
 *  Reserved words must be added to this section
 */

   TOKEN_NUMBER,
   RW_PUNCTUATION,
   TOKEN_STRING,
   TOKEN_LEFT_BRACE,
   TOKEN_RIGHT_BRACE,
   TOKEN_COMMA,
   TOKEN_COLON,
   RW_USE,
   RW_AIRCRAFT,
   RW_DESCRIPTION,
   RW_HARDPOINT,

/*
 *  Fields in the craftType structure must be added in this section
 */

   Object,
   AspectRatio,
   CLPosStall,
   CLNegStall,
   BetaStall,
   CLift,
   CDb,
   CnBeta,
   ClBeta,
   CDBOrigin,
   CDBFactor,
   CDBPhase,
   CYbeta,
   Clda,
   Cldr,
   Clp,
   Cmq,
   Cnr,
   maxAileron,
   maxRudder,
   effElevator,
   effRudder,
   SeTrimTakeoff,
   Ixx,
   Iyy,
   Izz,
   CmAlpha,
   CmFactor,
   MaxFlap,
   CFlap,
   FlapDrag,
   FlapRate,
   CGearDrag,
   GearRate,
   MaxSpeedBrake,
   CSpeedBrake,
   SpeedBrakeRate,
   SpeedBrakeIncr,
   WingArea,
   WingSpan,
   WingChord,
   EmptyWeight,
   MaxFuel,
   MaxThrust,
   MaxABThrust,
   Thrust,
   ABThrust,
   EngineLag,
   SpFuelConsump,
   SpABFuelConsump,
   GroundingPoint,
   ViewPoint,
   MuStatic,
   MuKinetic,
   MuBStatic,
   MuBKinetic,
   MaxNWDef,
   NWincr,
   MaxNWS,
   Rm,
   Rn,
   Dm,
   Dn,
   Km,
   Kn,
   Gm,
   Gn,
   CmMax,
   CnMax,
   TailExtent,
   StructurePts,
   RadarOutput,
   RadarTRange,
   RadarDRange,
   TEWSThreshold,
   HardPoint0,
   HardPoint1,
   HardPoint2,
   HardPoint3,
   HardPoint4,
   HardPoint5,
   HardPoint6,
   HardPoint7,
   HardPoint8,
   WeaponStation,
   WeaponCount,
   DISEntityType,
   Description
} field_id;

struct keyword_info {
   char     *word;
   value_type type;
   field_id  id;
   char     *ptr;
};

#define A(x)   (char *) x

struct keyword_info keywords[] =
{

   {"Description", vtSTRING, Description, A(&c.description)},
   {"Object", vtSTRING, Object, A(&c.objname)},
   {"AspectRatio", vtDOUBLE, AspectRatio, A(&c.aspectRatio)},
   {"CLPosStall", vtANGLE, CLPosStall, A(&c.CLPosStall)},
   {"CLNegStall", vtANGLE, CLNegStall, A(&c.CLNegStall)},
   {"BetaStall", vtANGLE, BetaStall, A(&c.betaStall)},
   {"CLift", vtTABLE, CLift, A(&c.CLift)},
   {"CDb", vtTABLE, CDb, A(&c.CDb)},
   {"CnBeta", vtTABLE, CnBeta, A(&c.CnBeta)},
   {"ClBeta", vtTABLE, ClBeta, A(&c.ClBeta)},
   {"CDBOrigin", vtDOUBLE, CDBOrigin, A(&c.CDBOrigin)},
   {"CDBFactor", vtDOUBLE, CDBFactor, A(&c.CDBFactor)},
   {"CDBPhase", vtANGLE, CDBPhase, A(&c.CDBPhase)},
   {"CYBeta", vtDOUBLE, CYbeta, A(&c.CYbeta)},
   {"Clda", vtDOUBLE, Clda, A(&c.Clda)},
   {"Cldr", vtDOUBLE, Cldr, A(&c.Cldr)},
   {"Clp", vtDOUBLE, Clp, A(&c.Clp)},
   {"Cmq", vtDOUBLE, Cmq, A(&c.Cmq)},
   {"Cnr", vtDOUBLE, Cnr, A(&c.Cnr)},
   {"MaxAileron", vtANGLE, maxAileron, A(&c.maxAileron)},
   {"MaxRudder", vtANGLE, maxRudder, A(&c.maxRudder)},
   {"EffElevator", vtDOUBLE, effElevator, A(&c.effElevator)},
   {"EffRudder", vtDOUBLE, effRudder, A(&c.effRudder)},
   {"SeTrimTakeoff", vtANGLE, SeTrimTakeoff, A(&c.SeTrimTakeoff)},
   {"Ixx", vtDOUBLE, Ixx, A(&c.I.m[0][0])},
   {"Iyy", vtDOUBLE, Iyy, A(&c.I.m[1][1])},
   {"Izz", vtDOUBLE, Izz, A(&c.I.m[2][2])},
   {"CmAlpha", vtDOUBLE, CmAlpha, A(&c.cmSlope)},
   {"CmFactor", vtDOUBLE, CmFactor, A(&c.cmFactor)},
   {"MaxFlap", vtANGLE, MaxFlap, A(&c.maxFlap)},
   {"CFlap", vtDOUBLE, CFlap, A(&c.cFlap)},
   {"CFlapDrag", vtDOUBLE, FlapDrag, A(&c.cFlapDrag)},
   {"FlapRate", vtANGLE, FlapRate, A(&c.flapRate)},
   {"CGearDrag", vtDOUBLE, CGearDrag, A(&c.cGearDrag)},
   {"GearRate", vtANGLE, GearRate, A(&c.gearRate)},
   {"MaxSpeedBrake", vtANGLE, MaxSpeedBrake, A(&c.maxSpeedBrake)},
   {"CSpeedBrake", vtDOUBLE, CSpeedBrake, A(&c.cSpeedBrake)},
   {"SpeedBrakeRate", vtANGLE, SpeedBrakeRate, A(&c.speedBrakeRate)},
   {"SpeedBrakeIncr", vtANGLE, SpeedBrakeIncr, A(&c.speedBrakeIncr)},
   {"WingArea", vtDOUBLE, WingArea, A(&c.wingS)},
   {"WingHalfSpan", vtDOUBLE, WingSpan, A(&c.wings)},
   {"Chord", vtDOUBLE, WingChord, A(&c.c)},
   {"EmptyWeight", vtDOUBLE, EmptyWeight, A(&c.emptyWeight)},
   {"MaxFuel", vtDOUBLE, MaxFuel, A(&c.maxFuel)},
   {"MaxThrust", vtDOUBLE, MaxThrust, A(&c.maxThrust)},
   {"MaxABThrust", vtDOUBLE, MaxABThrust, A(&c.maxABThrust)},
   {"Thrust", vtTABLE, Thrust, A(&c.Thrust)},
   {"ABThrust", vtTABLE, ABThrust, A(&c.ABThrust)},
   {"EngineLag", vtDOUBLE, EngineLag, A(&c.engineLag)},
   {"SpFuelConsump", vtDOUBLE, SpFuelConsump, A(&c.spFuelConsump)},
   {"SpABFuelConsump", vtDOUBLE, SpABFuelConsump, A(&c.spABFuelConsump)},
   {"GroundingPoint", vtPOINT, GroundingPoint, A(&c.groundingPoint)},
   {"ViewPoint", vtPOINT, ViewPoint, A(&c.viewPoint)},
   {"MuStatic", vtDOUBLE, MuStatic, A(&c.muStatic)},
   {"MuKinetic", vtDOUBLE, MuKinetic, A(&c.muKinetic)},
   {"MuBStatic", vtDOUBLE, MuBStatic, A(&c.muBStatic)},
   {"MuBKinetic", vtDOUBLE, MuBKinetic, A(&c.muBKinetic)},
   {"MaxNWDef", vtANGLE, MaxNWDef, A(&c.maxNWDef)},
   {"NWIncr", vtANGLE, NWincr, A(&c.NWIncr)},
   {"MaxNWS", vtKNOTS, MaxNWS, A(&c.maxNWS)},
   {"Rm", vtPOINT, Rm, A(&c.rm)},
   {"Rn", vtPOINT, Rn, A(&c.rn)},
   {"Dm", vtDOUBLE, Dm, A(&c.Dm)},
   {"Dn", vtDOUBLE, Dn, A(&c.Dn)},
   {"Km", vtDOUBLE, Km, A(&c.Km)},
   {"Kn", vtDOUBLE, Kn, A(&c.Kn)},
   {"Gm", vtDOUBLE, Gm, A(&c.Gm)},
   {"Gn", vtDOUBLE, Gn, A(&c.Gn)},
   {"CmMax", vtDOUBLE, CmMax, A(&c.cmMax)},
   {"CnMax", vtDOUBLE, CnMax, A(&c.cnMax)},
   {"TailExtent", vtPOINT, TailExtent, A(&c.tailExtent)},
   {"StructurePoints", vtLONG, StructurePts, A(&c.structurePts)},
   {"RadarOutput", vtDOUBLE, RadarOutput, A(&c.radarOutput)},
   {"RadarTRange", vtNMILES, RadarTRange, A(&c.radarTRange)},
   {"RadarDRange", vtNMILES, RadarDRange, A(&c.radarDRange)},
   {"TEWSThreshold", vtDOUBLE, TEWSThreshold, A(&c.TEWSThreshold)},
   {"HardPoint1", vtPOINT, HardPoint1, A(&c.wStation[1])},
   {"HardPoint2", vtPOINT, HardPoint2, A(&c.wStation[2])},
   {"HardPoint3", vtPOINT, HardPoint3, A(&c.wStation[3])},
   {"HardPoint4", vtPOINT, HardPoint4, A(&c.wStation[4])},
   {"HardPoint5", vtPOINT, HardPoint5, A(&c.wStation[5])},
   {"HardPoint6", vtPOINT, HardPoint6, A(&c.wStation[6])},
   {"HardPoint7", vtPOINT, HardPoint7, A(&c.wStation[7])},
   {"HardPoint8", vtPOINT, HardPoint8, A(&c.wStation[8])},
   {"HardPoint0", vtPOINT, HardPoint0, A(&c.wStation[0])},
   {"WeaponCount", vtLONG, WeaponCount, A(&c.sCount)},
   {"WeaponStation", vtSTATION, WeaponStation, 0},

   {"use", RESERVED_WORD, RW_USE, 0},
   {"aircraft", RESERVED_WORD, RW_AIRCRAFT, 0},
   {"description", RESERVED_WORD, RW_DESCRIPTION, 0},
   {"hardpoint", RESERVED_WORD, RW_HARDPOINT, 0},

   {"DISEntityType", vtENTITY, DISEntityType, A(&c.entityType)},
   {"DISAltEntityType", vtENTITY, DISEntityType, A(&c.altEntityType)},

   {NULL, RESERVED_WORD, Nil, 0}
};

typedef union {
   struct keyword_info *kw;
   double    double_value;
   ITable   *table_value;
   char     *string_value;
   long      long_value;
} lex_val;

static lex_val lex_value;

struct lex_record {
   char     *filename;
   FILE     *f;
   int       lineno;
   int       lookahead_valid;
   int       lookahead;
   int       stack_top;
   lex_val   value_stack[16];
};

#define push_value(p, type, val) \
   p->value_stack[p->stack_top++].type = val

#define pop_value(p, type) (p->value_stack[--p->stack_top].type)

#define input(p)   (p->lookahead_valid \
            ? (p->lookahead_valid = 0, p->lookahead) \
            : (((p->lookahead = getc(p->f)) == '\n') \
               ? (p->lineno++, p->lookahead) \
               : p->lookahead))

#define unput(p, c)   { p->lookahead = c; p->lookahead_valid = 1; }

#define InitializeLexRecord(p)   { p->lookahead_valid = 0; }

static char token[256];
static int token_length = 0;

#define STATE_INITIAL   0
#define STATE_WORD   1
#define STATE_NUMBER   2
#define STATE_STRING   3
#define STATE_COMMENT   4

extern FILE *acm_fopen(char *name, char *access);

struct lex_record *
OpenSourceFile(char *name)
{
   struct lex_record *p;
   FILE     *f;

   if ((f = acm_fopen(name, "r")) == (FILE *) NULL) {
      return (struct lex_record *) NULL;
   }

   p = (struct lex_record *) malloc(sizeof(struct lex_record));

   p->filename = strdup(name);
   p->lineno = 1;
   p->lookahead_valid = 0;
   p->stack_top = 0;
   p->f = f;

   return p;
}

int
compileAircraftInventory(void)
{
   struct lex_record *p;
   craftType *c, *c1;
   int       code = 0;
   FILE     *f;

   if ((p = OpenSourceFile("inventory")) == NULL) {
      fprintf(stderr, "unable to open aircraft inventory file\n");
      return -1;
   }

   while (1) {
      if (ParseAircraft(p, &c) == 0) {
         if (c) {
            c1 = newCraft();
            *c1 = *c;
            free((char *) c);

/*
 *  Initialize some other interesting values
 */

            f = acm_fopen(c1->objname, "r");
            c1->object = VReadDepthCueuedObject(f, 1);
            fclose(f);
            c1->placeProc = NULL;
            c1->damageBits = SYS_NODAMAGE;
            c1->damageBits &= ~SYS_ENGINE2;
            c1->thrust = genericThrust;
            c1->resupply = genericResupply;

/*
 *  Some older values are now derived from more precise information
 */

            c1->gearD1 = c1->rn.x - c1->rm.x;
            c1->gearD2 = c1->rm.x;
            c1->CLOrigin = interpolate(c1->CLift, 0.0);
            c1->CLSlope = (interpolate(c1->CLift, DEGtoRAD(10.0))
                        - c1->CLOrigin) / DEGtoRAD(10.0);
         }
         else {
            break;
         }
      }
      else {
         code = -1;
         break;
      }
   }

   fclose(p->f);
   free(p->filename);
   free((char *) p);
   return code;
}

void
ParseError(struct lex_record *p, char *s)
{
   fprintf(stderr, "error in file %s (line %d):\n\t%s\n", p->filename,
         p->lineno, s);
}

field_id
NextTokenx(struct lex_record *p)
{
   register int c, state = STATE_INITIAL;
   register struct keyword_info *q;

#ifndef linux
   extern double atof(const char *);

#endif

   token_length = 0;

   while ((c = input(p)) != EOF) {

      switch (state) {

      case STATE_INITIAL:

         if (isalpha(c)) {
            token[token_length++] = c;
            state = STATE_WORD;
         }
         else if (isspace(c)) {
            continue;
         }
         else if (isdigit(c) || c == '-' || c == '+' || c == '.') {
            token[token_length++] = c;
            state = STATE_NUMBER;
         }
         else if (c == '"') {
            state = STATE_STRING;
         }
         else if (c == '#') {
            state = STATE_COMMENT;
         }
         else {
            token[0] = c;
            token[1] = '\0';
#ifdef DEBUG
            printf("other %s\n", token);
#endif
            switch (c) {
            case ',':
               return TOKEN_COMMA;
            case ':':
               return TOKEN_COLON;
            case '{':
               return TOKEN_LEFT_BRACE;
            case '}':
               return TOKEN_RIGHT_BRACE;
            default:
               ParseError(p, "invalid character");
               state = STATE_INITIAL;
            }
         }
         break;

      case STATE_WORD:
      case STATE_NUMBER:
         if (isspace(c) || c == ':' || c == ',' || c == '{' || c == '}') {
            token[token_length] = '\0';
            unput(p, c);
            if (state == STATE_WORD) {
               for (q = keywords; q->word; ++q) {
                  if (strcmp(q->word, token) == 0) {
                     lex_value.kw = q;
                     return q->id;
                  }
               }
               return Nil;
            }
            else {
               lex_value.double_value = atof(token);
               return TOKEN_NUMBER;
            }
         }
         else {
            token[token_length++] = c;
         }
         break;

      case STATE_STRING:

         switch (c) {

         case '"':
            token[token_length] = '\0';
            return TOKEN_STRING;

         case '\n':
            ParseError(p, "strings cannot span a line");
            unput(p, c);
            state = STATE_INITIAL;
            break;

         case '\\':

            switch (c = input(p)) {

            case EOF:
               ParseError(p, "Premature End-of-file");
               break;

            case 'n':
               token[token_length++] = '\n';
               break;

            case 't':
               token[token_length++] = '\t';
               break;

            default:
               token[token_length++] = c;
               break;
            }

         default:
            token[token_length++] = c;
            break;
         }
         break;

      case STATE_COMMENT:
         while (c != EOF) {
            if (c == '\n')
               break;
            c = input(p);
         }
         state = STATE_INITIAL;
         break;

      }
   }

   return EndOfFile;
}

field_id
NextToken(struct lex_record * p)
{
   field_id  t;

   t = NextTokenx(p);

#ifdef DEBUG
   printf("token %s\n", token);
#endif
   return t;
}

/*
 *  Skip to the specified token, if token is Nil, then skip to the end of the
 *  current line.
 */

void
Resync(struct lex_record *p, field_id token)
{
   field_id  t;
   int       c;

   printf("resyncing\n");

   if (token == Nil) {
      while ((c = input(p)) != EOF) {
         if (c == '\n')
            break;
      }
   }
   else {
      while ((t = NextToken(p)) != EndOfFile) {
         if (t == token)
            break;
      }
   }
   printf("resyncing complete\n");

}

int
ParseAircraft(struct lex_record *p, craftType ** c1)
{
   field_id  t;
   long      n, i;
   double    d;
   VPoint    pt;
   ITable   *table;
   dis_entity_type entity;
   char      s[256];
   struct keyword_info *kw;

   memset(&c, 0, sizeof(c));
   *c1 = NULL;

   if ((t = NextToken(p)) != RW_AIRCRAFT) {
      if (t == EndOfFile) {
         return 0;
      }
      else {
         return -1;
      }
   }

   if (NextToken(p) != TOKEN_STRING) {
      return -1;
   }

   c.name = strdup(token);

   if (NextToken(p) != TOKEN_LEFT_BRACE) {
      return -1;
   }

   while ((t = NextToken(p)) != EndOfFile) {

      if (t >= Object) {

         kw = lex_value.kw;

         switch (kw->type) {

         case vtSTRING:
            if (NextToken(p) == TOKEN_STRING) {
               n = 0;
               *((char **) kw->ptr) = strdup(token);
            }
            else
               n = -1;
            break;

         case vtDOUBLE:
         case vtNMILES:
         case vtKNOTS:
            if ((n = ParseValue(p)) == 0) {
               d = pop_value(p, double_value);
               if (kw->type == vtNMILES)
                  d *= NM;
               else if (kw->type == vtKNOTS)
                  d *= NM / 3600;
               *((double *) kw->ptr) = d;
            }
            break;

         case vtANGLE:
            if ((n = ParseValue(p)) == 0) {
               d = DEGtoRAD(pop_value(p, double_value));
               *((double *) kw->ptr) = d;
            }
            break;

         case vtLONG:
            if ((n = ParseValue(p)) == 0) {
               d = pop_value(p, double_value);
               *((long *) kw->ptr) = (d + 0.5);
            }
            break;

         case vtTABLE:
            if ((n = ParseTable(p)) == 0) {
               table = pop_value(p, table_value);
               *((ITable **) kw->ptr) = table;
            }
            break;

         case vtPOINT:
            if ((n = ParsePoint(p)) == 0) {
               pt.z = pop_value(p, double_value);
               pt.y = pop_value(p, double_value);
               pt.x = pop_value(p, double_value);
               *((VPoint *) kw->ptr) = pt;
            }
            break;

         case vtSTATION:
            if ((n = ParseStation(p)) == 0) {
               i = pop_value(p, long_value);
               c.station[i].type =
                  pop_value(p, string_value);
               c.station[i].info =
                  pop_value(p, long_value);
               c.station[i].info2 =
                  pop_value(p, long_value);
               c.station[i].info3 =
                  pop_value(p, long_value);
            }
            break;

         case vtENTITY:
            if ((n = ParseDISEntityType(p)) == 0) {
               entity.extra = (unsigned char)
                  pop_value(p, long_value);
               entity.specific = (unsigned char)
                  pop_value(p, long_value);
               entity.subcategory = (unsigned char)
                  pop_value(p, long_value);
               entity.category = (unsigned char)
                  pop_value(p, long_value);
               entity.country = (unsigned char)
                  pop_value(p, long_value);
               entity.domain = (unsigned char)
                  pop_value(p, long_value);
               entity.kind = (unsigned char)
                  pop_value(p, long_value);
               *((dis_entity_type *) kw->ptr) = entity;
            }
            break;
         }

         if (n != 0) {
            sprintf(s, "invalid syntax for %s\
 parameter", kw->word);
            ParseError(p, s);
         }
      }
      else if (t == TOKEN_RIGHT_BRACE) {
         *c1 = (craftType *) malloc(sizeof(craftType));
         **c1 = c;
         return 0;
      }
      else {
         sprintf(s, "\"%s\" was found where another token was\
 expected", token);
         ParseError(p, s);
         return -1;
      }
   }

   return -1;
}

/*
 *  Parse syntax:  '{' number ',' number ',' number '}'
 */

int
ParsePoint(struct lex_record *p)
{

   if (NextToken(p) != TOKEN_LEFT_BRACE) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   push_value(p, double_value, lex_value.double_value);

   if (NextToken(p) != TOKEN_COMMA) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   push_value(p, double_value, lex_value.double_value);

   if (NextToken(p) != TOKEN_COMMA) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   push_value(p, double_value, lex_value.double_value);

   if (NextToken(p) != TOKEN_RIGHT_BRACE) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   return 0;
}

/*
 *  Parse syntax:  '{' number_list '}'
 *
 *  Where number_list is a collection of zero or more comma separated
 *  numbers.  The list of numbers must be an even count.
 *
 */

int
ParseTable(struct lex_record *p)
{
   field_id  t;
   double    x[64], y[64];
   int       count = 0, i;
   ITable   *table;
   IEntry   *entry;

   if (NextToken(p) != TOKEN_LEFT_BRACE) {
      Resync(p, TOKEN_RIGHT_BRACE);
      return -1;
   }

   while ((t = NextToken(p)) != TOKEN_RIGHT_BRACE) {

      if (t == EndOfFile)
         return -1;

      if (t == TOKEN_NUMBER) {

         if (count == 64) {
            ParseError(p, "too many table entries");
            return -1;
         }

         x[count] = lex_value.double_value;

         if (NextToken(p) != TOKEN_COMMA) {
            Resync(p, TOKEN_RIGHT_BRACE);
            return -1;
         }

         if (NextToken(p) != TOKEN_NUMBER) {
            Resync(p, TOKEN_RIGHT_BRACE);
            return -1;
         }
         y[count++] = lex_value.double_value;

         t = NextToken(p);

         if (t == TOKEN_RIGHT_BRACE)
            goto done;
         else if (t != TOKEN_COMMA) {
            Resync(p, TOKEN_RIGHT_BRACE);
            return -1;
         }
      }
      else {
         Resync(p, TOKEN_RIGHT_BRACE);
         return -1;
      }
   }

  done:

/*
 *  Build an interpolation table
 */

   table = (ITable *) malloc(sizeof(ITable));
   entry = (IEntry *) malloc(sizeof(IEntry) * (count - 1));
   table->minX = x[0];
   table->count = count - 1;
   table->entry = entry;

   for (i = 1; i < count; ++i) {
      entry[i - 1].x = x[i];
      entry[i - 1].m = (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
      entry[i - 1].b = y[i] - (x[i] * entry[i - 1].m);
   }

   push_value(p, table_value, table);

   return 0;
}

int
ParseValue(struct lex_record *p)
{
   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, Nil);
      return -1;
   }
   push_value(p, double_value, lex_value.double_value);
   return 0;
}

/*
 *  Parse syntax:  number string number number
 */

int
ParseStation(struct lex_record *p)
{

   long      i, a1, b1, c1;
   char     *ptr;

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, Nil);
      return -1;
   }

   i = (long) (lex_value.double_value + 0.5);

   if (NextToken(p) != TOKEN_STRING) {
      Resync(p, Nil);
      return -1;
   }

   ptr = strdup(token);

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, Nil);
      return -1;
   }

   a1 = (long) (lex_value.double_value + 0.5);

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, Nil);
      return -1;
   }

   b1 = (long) (lex_value.double_value + 0.5);

   if (NextToken(p) != TOKEN_NUMBER) {
      Resync(p, Nil);
      return -1;
   }

   c1 = (long) (lex_value.double_value + 0.5);

   push_value(p, long_value, c1);
   push_value(p, long_value, b1);
   push_value(p, long_value, a1);
   push_value(p, string_value, ptr);
   push_value(p, long_value, i);

   return 0;
}

/*
 *  Parse syntax:  n.n.n.n.n.n.n
 */

int
ParseDISEntityType(struct lex_record *p)
{

   long      i, av;

   for (i = 0; i < 7; ++i) {

      if (NextToken(p) != TOKEN_NUMBER) {
         printf("1: %d\n", i);
         Resync(p, Nil);
         return -1;
      }

      av = (long) (lex_value.double_value + 0.5);
      push_value(p, long_value, av);

      if (i < 6 && NextToken(p) != TOKEN_COLON) {
         printf("2: %d\n", i);
         Resync(p, Nil);
         return -1;
      }
   }

   return 0;
}

 

.