Logo Search packages:      
Sourcecode: acm version File versions  Download package

inventory.c

/*
 *  acm : an aerial combat simulator for X
 *  Copyright (C) 1991-1998  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 <errno.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);
int       ParseEntityMapEntry(struct lex_record *p, entity_object_map *po);
int       ParseMunitionMapEntry(struct lex_record *p, munition_map *po);

static craftType c;

extern craftType *newCraft(void);
extern ITable * copyITable (ITable *oldp);

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,
      TOKEN_SEMICOLON,
      RW_USE,
      RW_AIRCRAFT,
      RW_DESCRIPTION,
      RW_HARDPOINT,
      RW_KINETIC,
      RW_EXPLOSIVE,
      RW_M61A1,
      RW_AIM9M,
      RW_MK82,

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

      Object,
      InternalModel,
      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)},
      {"InternalModel", vtSTRING, InternalModel, A(&c.modelname)},
      {"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},
    {"kinetic", RESERVED_WORD, RW_KINETIC, 0},
      {"explosive", RESERVED_WORD, RW_EXPLOSIVE, 0},
      {"blast", RESERVED_WORD, RW_EXPLOSIVE, 0},

      {"M61A1", RESERVED_WORD, RW_M61A1, 0},
      {"AIM9M", RESERVED_WORD, RW_AIM9M, 0},
      {"MK82",  RESERVED_WORD, RW_MK82,  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];
};

field_id NextToken(struct lex_record * p);
void Resync(struct lex_record *p, field_id token);

#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;
}

int
compileEntityMap(char *name, int *count, entity_object_map **pmap)
{
      struct lex_record *p;
      int       code = 0;
      entity_object_map po;
      int n = 0;

      *pmap = NULL;
      *count = 0;

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

      while (ParseEntityMapEntry(p, &po) == 0 && code == 0) {
            *pmap = realloc (*pmap, sizeof(entity_object_map) * (n+1) );
            if (!pmap) {
                  code = -1;
            }
            (*pmap)[n] = po;
            n++;
      }

      *count = n;

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

int
compileMunitionMap(char *name, int *count, munition_map **pmap)
{
      struct lex_record *p;
      int       code = 0;
      munition_map po;
      int n = 0;

      *pmap = NULL;
      *count = 0;

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

      while (ParseMunitionMapEntry(p, &po) == 0 && code == 0) {
            *pmap = realloc (*pmap, sizeof(munition_map) * (n+1) );
            if (!pmap) {
                  code = -1;
            }
            (*pmap)[n] = po;
            n++;
      }

      *count = n;

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

int
ParseEntityMapEntry(struct lex_record *p, entity_object_map *po)
{
      long ival, result;

      memset (po, 0, sizeof(entity_object_map));

      result = ParseDISEntityType(p);

      /* end-of-file */
      if (result == -2) {
            return -1;
      }

      /* other error */
      if (result != 0) {
            Resync(p, TOKEN_SEMICOLON);
            return -1;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.extra = 0;
      }
      else {
            po->entity_mask.extra = 1;
            po->entity_type.extra = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.specific = 0;
      }
      else {
            po->entity_mask.specific = 1;
            po->entity_type.specific = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.subcategory = 0;
      }
      else {
            po->entity_mask.subcategory = 1;
            po->entity_type.subcategory = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.category = 0;
      }
      else {
            po->entity_mask.category = 1;
            po->entity_type.category = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.country = 0;
      }
      else {
            po->entity_mask.country = 1;
            po->entity_type.country = (unsigned short) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.domain = 0;
      }
      else {
            po->entity_mask.domain = 1;
            po->entity_type.domain = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.kind = 0;
      }
      else {
            po->entity_mask.kind = 1;
            po->entity_type.kind = (unsigned char) ival;
      }

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

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

      po->object_name = strdup( token );

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

      return 0;
}

/*
 *  munition_entity_type , warhead_type , explosion_diameter , damage_factor ;
 */

int
ParseMunitionMapEntry(struct lex_record *p, munition_map *po)
{
      long ival, result;
      field_id t;

      memset (po, 0, sizeof(munition_map));

      result = ParseDISEntityType(p);

      /* end-of-file */
      if (result == -2) {
            return -1;
      }

      /* other error */
      if (result != 0) {
            Resync(p, TOKEN_SEMICOLON);
            return -1;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.extra = 0;
      }
      else {
            po->entity_mask.extra = 1;
            po->entity_type.extra = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.specific = 0;
      }
      else {
            po->entity_mask.specific = 1;
            po->entity_type.specific = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.subcategory = 0;
      }
      else {
            po->entity_mask.subcategory = 1;
            po->entity_type.subcategory = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.category = 0;
      }
      else {
            po->entity_mask.category = 1;
            po->entity_type.category = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.country = 0;
      }
      else {
            po->entity_mask.country = 1;
            po->entity_type.country = (unsigned short) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.domain = 0;
      }
      else {
            po->entity_mask.domain = 1;
            po->entity_type.domain = (unsigned char) ival;
      }

      ival = pop_value(p, long_value);
      if (ival == -1) {
            po->entity_mask.kind = 0;
      }
      else {
            po->entity_mask.kind = 1;
            po->entity_type.kind = (unsigned char) ival;
      }

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

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

      /* warhead type */

      if (lex_value.double_value >= 0) {
            ival = (int) (lex_value.double_value + 0.5);
      }
      else {
            ival = (long)(lex_value.double_value - 0.5);
      }

      if (ival == -1) {
            po->warhead_mask = 0;
      }
      else {
            po->warhead_mask = 1;
            po->warhead_type = (unsigned short) ival;
      }

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

      /* explosion diameter */

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

      po->explosion_diameter_meters = FEETtoMETERS(lex_value.double_value);

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

      /* damage factor */

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

      po->damage_factor = lex_value.double_value;

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

      /* warhead class: kinetic or explosive */

      t = NextToken(p);

      if (t != RW_KINETIC && t != RW_EXPLOSIVE) {
            Resync(p, TOKEN_SEMICOLON);
            return -1;
      }

      po->kinetic_flag = (t == RW_KINETIC) ? 1 : 0;

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

      return 0;
}

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;

      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_SEMICOLON;
                        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 {
                              errno = 0;
                              lex_value.double_value = strtod( token, NULL );
                              if (errno == ERANGE) {
                                    printf ("invalid numeric constant: %s\n", 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;

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

}

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;
      craftType *used;

      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 || t == RW_USE) {

                  kw = lex_value.kw;

                  switch (kw->type) {

                  case RESERVED_WORD:

                        /*
                         *  use "aircraft-type-name"
                         *
                         *  uses a previously defined aircraft as the starting point for defining another
                         */

                        if (kw->id == RW_USE) {
                              if ( NextToken(p) == TOKEN_STRING ) {
                                    char * ptmp = c.name;

                                    n = 1;
                                    used = lookupCraft( token );
                                    if (used) {
                                          c = *used;
                                          c.CLift    = copyITable (used->CLift   );
                                          c.CDb      = copyITable (used->CDb     );
                                          c.CnBeta   = copyITable (used->CnBeta  );
                                          c.ClBeta   = copyITable (used->ClBeta  );
                                          c.Thrust   = copyITable (used->Thrust  );
                                          c.ABThrust = copyITable (used->ABThrust);
                                          //if (used->name) {
                                          //    c.name = strdup( used->name );
                                          //}
                                          c.name = ptmp;
                                          if (used->description) {
                                                c.description = strdup( used->description );
                                          }
                                          if (used->modelname) {
                                                c.modelname = strdup( used->modelname );
                                          }
                                          if (used->objname) {
                                                c.objname = strdup( used->objname );
                                          }
                                          for (i=0; i<STATIONS; ++i) {
                                                if ( used->station[i].type ) {
                                                      c.station[i].type = strdup( used->station[i].type) ;
                                                }
                                          }


                                          n = 0;

                                    }
                                    else {
                                          sprintf(s, "\"%s\" is not a valid aircraft type", token);
                                          ParseError(p, s);
                                    }
                              }
                        }
                        break;

                  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) = (long) (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 = (float_t) x[0];
      table->count = count - 1;
      table->entry = entry;

      for (i = 1; i < count; ++i) {
            entry[i - 1].x = (float_t) x[i];
            entry[i - 1].m = (float_t) ((y[i] - y[i - 1]) / (x[i] - x[i - 1]));
            entry[i - 1].b = (float_t) (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;
}

int
ParseWeaponType(struct lex_record *p)
{
      field_id t;
      int result = 0;

      t = NextToken(p);

      if (t == RW_M61A1) {
            push_value( p, long_value, WK_M61A1 );
      }
      else if (t == RW_AIM9M) {
            push_value( p, long_value, WK_AIM9M );
      }
      else if (t == RW_MK82) {
            push_value( p, long_value, WK_MK82 );
      }
      else {
            Resync(p, Nil);
            result = -1;
      }

      return 0;
}

/*
 *  Parse syntax:  number weapon-type 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;
      field_id  t;

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

              t = NextToken(p);

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

            if (lex_value.double_value > 0) {
              av = (long) (lex_value.double_value + 0.5);
            }
            else {
               av = (long) (lex_value.double_value - 0.5);
            }
            push_value(p, long_value, av);

            if (i < 6 && NextToken(p) != TOKEN_COLON) {
                  Resync(p, Nil);
                  return -1;
            }
      }

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index