static void cmd_infer(void) { infer_what setting; int on; get_token(); setting = match_tok(infer_tab, TABSIZE(infer_tab)); if (setting == INFER_NULL) { file.lpos += strlen(buffer); compile_error_skip(-/*Found “%s”, expecting “EQUATES”, “EXPORTS”, or “PLUMBS”*/31, buffer); return; } get_token(); on = match_tok(onoff_tab, TABSIZE(onoff_tab)); if (on == -1) { file.lpos += strlen(buffer); compile_error_skip(-/*Found “%s”, expecting “ON” or “OFF”*/32, buffer); return; } if (on) { pcs->infer |= BIT(setting); if (setting == INFER_EXPORTS) fExportUsed = fTrue; } else { pcs->infer &= ~BIT(setting); } }
extern void handle_command(void) { int cmdtok; get_token(); cmdtok = match_tok(cmd_tab, TABSIZE(cmd_tab)); if (cmdtok < 0 || cmdtok >= (int)(sizeof(cmd_funcs) / sizeof(cmd_fn))) { file.lpos += strlen(buffer); compile_error_skip(-/*Unknown command “%s”*/12, buffer); return; } switch (cmdtok) { case CMD_EXPORT: if (!f_export_ok) compile_error(/**EXPORT must immediately follow “*BEGIN <SURVEY>”*/57); break; case CMD_COPYRIGHT: case CMD_DATE: case CMD_INSTRUMENT: case CMD_TEAM: case CMD_TITLE: /* These can occur between *begin and *export */ break; default: /* NB: additional handling for "*begin <survey>" in cmd_begin */ f_export_ok = fFalse; break; } cmd_funcs[cmdtok](); }
static void cmd_default(void) { static sztok defaulttab[] = { { "CALIBRATE", CMD_CALIBRATE }, { "DATA", CMD_DATA }, { "UNITS", CMD_UNITS }, { NULL, CMD_NULL } }; static int default_depr_count = 0; if (default_depr_count < 5) { compile_warning(-/**DEFAULT is deprecated - use *CALIBRATE/DATA/SD/UNITS with argument DEFAULT instead*/20); if (++default_depr_count == 5) compile_warning(/*Further uses of this deprecated feature will not be reported*/95); } get_token(); switch (match_tok(defaulttab, TABSIZE(defaulttab))) { case CMD_CALIBRATE: default_calib(pcs); break; case CMD_DATA: default_style(pcs); default_grade(pcs); break; case CMD_UNITS: default_units(pcs); break; default: file.lpos += strlen(buffer); compile_error_skip(-/*Unknown setting “%s”*/41, buffer); } }
static void cmd_case(void) { int setting; get_token(); setting = match_tok(case_tab, TABSIZE(case_tab)); if (setting != -1) { pcs->Case = setting; } else { file.lpos += strlen(buffer); compile_error_skip(-/*Found “%s”, expecting “PRESERVE”, “TOUPPER”, or “TOLOWER”*/10, buffer); } }
static int is_roman(T_CHAR * ptr)/* could be more smart i think */ { if (ptr[0]==']' && ptr[1]=='[' && separator(ptr[2])) return 1; while(!separator(*ptr)) { UINT n; bool found=0; for(n=0;n<TABSIZE(roman_num);n++) { if (*ptr==roman_num[n]) {found=1;break;} } if (!found) return 0; ptr++; } return 1; }
static void cmd_flags(void) { static sztok flagtab[] = { {"DUPLICATE", FLAGS_DUPLICATE }, {"NOT", FLAGS_NOT }, {"SPLAY", FLAGS_SPLAY }, {"SURFACE", FLAGS_SURFACE }, {NULL, FLAGS_UNKNOWN } }; bool fNot = fFalse; bool fEmpty = fTrue; while (1) { int flag; get_token(); /* If buffer is empty, it could mean end of line, or maybe * some non-letter junk which is better reported later */ if (!buffer[0]) break; fEmpty = fFalse; flag = match_tok(flagtab, TABSIZE(flagtab)); /* treat the second NOT in "NOT NOT" as an unknown flag */ if (flag == FLAGS_UNKNOWN || (fNot && flag == FLAGS_NOT)) { file.lpos += strlen(buffer); compile_error(-/*FLAG “%s” unknown*/68, buffer); /* Recover from “*FLAGS NOT BOGUS SURFACE” by ignoring "NOT BOGUS" */ fNot = fFalse; } else if (flag == FLAGS_NOT) { fNot = fTrue; } else if (fNot) { pcs->flags &= ~BIT(flag); fNot = fFalse; } else { pcs->flags |= BIT(flag); } } if (fNot) { file.lpos += strlen(buffer); compile_error(-/*Expecting “DUPLICATE”, “SPLAY”, or “SURFACE”*/188); } else if (fEmpty) { file.lpos += strlen(buffer); compile_error(-/*Expecting “NOT”, “DUPLICATE”, “SPLAY”, or “SURFACE”*/189); } }
static int get_units(unsigned long qmask, bool percent_ok) { static sztok utab[] = { {"DEGREES", UNITS_DEGS }, {"DEGS", UNITS_DEGS }, {"FEET", UNITS_FEET }, {"GRADS", UNITS_GRADS }, {"METERS", UNITS_METRES }, {"METRES", UNITS_METRES }, {"METRIC", UNITS_METRES }, {"MILS", UNITS_GRADS }, {"MINUTES", UNITS_MINUTES }, {"PERCENT", UNITS_PERCENT }, {"PERCENTAGE", UNITS_PERCENT }, {"YARDS", UNITS_YARDS }, {NULL, UNITS_NULL } }; int units; get_token(); units = match_tok(utab, TABSIZE(utab)); if (units == UNITS_NULL) { file.lpos += strlen(buffer); compile_error_skip(-/*Unknown units “%s”*/35, buffer); return UNITS_NULL; } if (units == UNITS_PERCENT && percent_ok && !(qmask & ~(BIT(Q_GRADIENT)|BIT(Q_BACKGRADIENT)))) { return units; } if (((qmask & LEN_QMASK) && !TSTBIT(LEN_UMASK, units)) || ((qmask & ANG_QMASK) && !TSTBIT(ANG_UMASK, units))) { file.lpos += strlen(buffer); compile_error_skip(-/*Invalid units “%s” for quantity*/37, buffer); return UNITS_NULL; } return units; }
static void GetStatisticTable(void) { FILE *inp; int i; char line[64]; if (!(inp = fopen(StatisticFileName, "r"))) { fprintf(stderr, "FEHLER: File %s kann nicht geöffnet werden: %s\n", StatisticFileName, strerror(errno)); exit(20); } for (i = 0; i < TABSIZE(PropTable); i++) { fgets(line, sizeof(line), inp); if (feof(inp)) { fprintf(stderr, "FEHLER: Unerwartetes Dateieine in %s nach %d Einträgen.\n", StatisticFileName, i); exit(20); } PropTable[i] = atof(line); } fclose(inp); }
void run() { if (!spec) {Error();return;} while(*spec) { if (*spec=='%') { spec++; if (*spec=='%') {str.AddChar('%');spec++;continue;} T_CHAR* s1=spec+1; while(*s1 && *s1!='%') s1++; if (!*s1) {Error();break;} *s1=0; T_CHAR * tag=f(spec,fp); *s1='%'; /*if (!tag) tag=tag_unknown; */ if (tag && tag[0]) { found++; str.AddString(tag); } else { str.AddString(_TX("?")); } if (tag && ff) ff(tag,fp); spec=s1+1; } else if (*spec=='$') { spec++; if (*spec=='$') {str.AddChar('$');spec++;continue;} T_CHAR * s1=spec+1; while(*s1 && *s1!='(') s1++; if (!*s1) {Error();break;} T_CHAR * s2=s1+1; if (!skipshit(&s2,_TX(")"))) {Error();break;} if (!*s2) {Error();break;}; T_CHAR * p=s1+1; T_CHAR* temp[64]; UINT temp_f[64]; UINT nt=0; T_CHAR * p1=s1+1; while(p<=s2 && nt<64) { if (!skipshit(&p,_TX(",)"))) {Error();return;} if (p>s2 || (*p!=',' && *p!=')')) {Error(_TX("internal error"));return;} T_CHAR bk=*p; *p=0; temp[nt]=_FMT(p1,&temp_f[nt]); nt++; *p=bk;; p1=p+1; p++; } *s1=0; UINT n; for (n=0; n<TABSIZE(FUNCS); n++) if (!t_stricmp(spec, FUNCS[n].name)) break; *s1='('; if (n != TABSIZE(FUNCS)) { if (!FUNCS[n].func(nt, temp, temp_f, str)) { Error(_TX("[INVALID $")); str.AddString(FUNCS[n].name); str.AddString(_TX(" SYNTAX]")); return; } } else { Error(_TX("[UNKNOWN FUNCTION]")); return; } for(n=0;n<nt;n++) free(temp[n]); spec=s2+1; } else if (*spec=='\'') { spec++; if (*spec=='\'') {str.AddChar('\'');spec++;continue;} T_CHAR * s1=spec+1; while(*s1 && *s1!='\'') s1++; if (!*s1) {Error();break;} *s1=0; str.AddString(spec); *s1='\''; spec=s1+1; } else if (*spec=='[') { spec++; T_CHAR * s1=spec; UINT bc=0; if (!skipshit(&s1,_TX("]"))) {Error();break;} T_CHAR bk=*s1; *s1=0; FMT fmt(this,spec); fmt.run(); if (fmt.found) { str.AddString(fmt.str); found+=fmt.found; } *s1=bk; spec=s1+1; } else if (*spec == ']') {Error();break;} else { str.AddChar(*spec); spec++; } } }
static void cmd_data(void) { static sztok dtab[] = { {"ALTITUDE", Dz }, {"BACKBEARING", BackComp }, {"BACKCLINO", BackClino }, /* alternative name */ {"BACKCOMPASS", BackComp }, /* alternative name */ {"BACKGRADIENT", BackClino }, {"BEARING", Comp }, {"CEILING", Up }, /* alternative name */ {"CLINO", Clino }, /* alternative name */ {"COMPASS", Comp }, /* alternative name */ {"COUNT", Count }, /* FrCount&ToCount in multiline */ {"DEPTH", Depth }, /* FrDepth&ToDepth in multiline */ {"DEPTHCHANGE", DepthChange }, {"DIRECTION", Dir }, {"DOWN", Down }, {"DX", Dx }, {"DY", Dy }, {"DZ", Dz }, {"EASTING", Dx }, {"FLOOR", Down }, /* alternative name */ {"FROM", Fr }, {"FROMCOUNT", FrCount }, {"FROMDEPTH", FrDepth }, {"GRADIENT", Clino }, {"IGNORE", Ignore }, {"IGNOREALL", IgnoreAll }, {"LEFT", Left }, {"LENGTH", Tape }, {"NEWLINE", Newline }, {"NORTHING", Dy }, {"RIGHT", Right }, {"STATION", Station }, /* Fr&To in multiline */ {"TAPE", Tape }, /* alternative name */ {"TO", To }, {"TOCOUNT", ToCount }, {"TODEPTH", ToDepth }, {"UP", Up }, {NULL, End } }; #define MASK_stns BIT(Fr) | BIT(To) | BIT(Station) #define MASK_tape BIT(Tape) | BIT(FrCount) | BIT(ToCount) | BIT(Count) #define MASK_dpth BIT(FrDepth) | BIT(ToDepth) | BIT(Depth) | BIT(DepthChange) #define MASK_comp BIT(Comp) | BIT(BackComp) #define MASK_clin BIT(Clino) | BIT(BackClino) #define MASK_NORMAL MASK_stns | BIT(Dir) | MASK_tape | MASK_comp | MASK_clin #define MASK_DIVING MASK_stns | BIT(Dir) | MASK_tape | MASK_comp | MASK_dpth #define MASK_CARTESIAN MASK_stns | BIT(Dx) | BIT(Dy) | BIT(Dz) #define MASK_CYLPOLAR MASK_stns | BIT(Dir) | MASK_tape | MASK_comp | MASK_dpth #define MASK_PASSAGE BIT(Station) | BIT(Left) | BIT(Right) | BIT(Up) | BIT(Down) #define MASK_NOSURVEY MASK_stns /* readings which may be given for each style */ static const unsigned long mask[] = { MASK_NORMAL, MASK_DIVING, MASK_CARTESIAN, MASK_CYLPOLAR, MASK_NOSURVEY, MASK_PASSAGE }; /* readings which may be omitted for each style */ static const unsigned long mask_optional[] = { BIT(Dir) | BIT(Clino) | BIT(BackClino), BIT(Dir), 0, BIT(Dir), 0, 0 /* BIT(Left) | BIT(Right) | BIT(Up) | BIT(Down), */ }; /* all valid readings */ static const unsigned long mask_all[] = { MASK_NORMAL | BIT(Newline) | BIT(Ignore) | BIT(IgnoreAll) | BIT(End), MASK_DIVING | BIT(Newline) | BIT(Ignore) | BIT(IgnoreAll) | BIT(End), MASK_CARTESIAN | BIT(Newline) | BIT(Ignore) | BIT(IgnoreAll) | BIT(End), MASK_CYLPOLAR | BIT(Newline) | BIT(Ignore) | BIT(IgnoreAll) | BIT(End), MASK_NOSURVEY | BIT(Ignore) | BIT(IgnoreAll) | BIT(End), MASK_PASSAGE | BIT(Ignore) | BIT(IgnoreAll) | BIT(End) }; #define STYLE_DEFAULT -2 #define STYLE_UNKNOWN -1 static sztok styletab[] = { {"CARTESIAN", STYLE_CARTESIAN }, {"CYLPOLAR", STYLE_CYLPOLAR }, {"DEFAULT", STYLE_DEFAULT }, {"DIVING", STYLE_DIVING }, {"NORMAL", STYLE_NORMAL }, {"NOSURVEY", STYLE_NOSURVEY }, {"PASSAGE", STYLE_PASSAGE }, {"TOPOFIL", STYLE_NORMAL }, {NULL, STYLE_UNKNOWN } }; #define m_multi (BIT(Station) | BIT(Count) | BIT(Depth)) int style, k = 0, kMac; reading *new_order, d; unsigned long mUsed = 0; char *style_name; /* after a bad *data command ignore survey data until the next * *data command to avoid an avalanche of errors */ pcs->style = STYLE_IGNORE; kMac = 6; /* minimum for NORMAL style */ new_order = osmalloc(kMac * sizeof(reading)); get_token(); style = match_tok(styletab, TABSIZE(styletab)); if (style == STYLE_DEFAULT) { default_style(pcs); return; } if (style == STYLE_UNKNOWN) { file.lpos += strlen(buffer); compile_error_skip(-/*Data style “%s” unknown*/65, buffer); return; } skipblanks(); #ifndef NO_DEPRECATED /* Olde syntax had optional field for survey grade, so allow an omit * but issue a warning about it */ if (isOmit(ch)) { static int data_depr_count = 0; if (data_depr_count < 5) { file.lpos += strlen(buffer); compile_warning(-/*“*data %s %c …” is deprecated - use “*data %s …” instead*/104, buffer, ch, buffer); if (++data_depr_count == 5) compile_warning(/*Further uses of this deprecated feature will not be reported*/95); } nextch(); } #endif style_name = osstrdup(buffer); do { filepos fp; get_pos(&fp); get_token(); d = match_tok(dtab, TABSIZE(dtab)); /* only token allowed after IGNOREALL is NEWLINE */ if (k && new_order[k - 1] == IgnoreAll && d != Newline) { set_pos(&fp); break; } /* Note: an unknown token is reported as trailing garbage */ if (!TSTBIT(mask_all[style], d)) { file.lpos += strlen(buffer); compile_error_skip(-/*Reading “%s” not allowed in data style “%s”*/63, buffer, style_name); osfree(style_name); osfree(new_order); return; } if (TSTBIT(mUsed, Newline) && TSTBIT(m_multi, d)) { /* e.g. "*data diving station newline tape depth compass" */ file.lpos += strlen(buffer); compile_error_skip(-/*Reading “%s” must occur before NEWLINE*/225, buffer); osfree(style_name); osfree(new_order); return; } /* Check for duplicates unless it's a special reading: * IGNOREALL,IGNORE (duplicates allowed) ; END (not possible) */ if (!((BIT(Ignore) | BIT(End) | BIT(IgnoreAll)) & BIT(d))) { if (TSTBIT(mUsed, d)) { file.lpos += strlen(buffer); compile_error_skip(-/*Duplicate reading “%s”*/67, buffer); osfree(style_name); osfree(new_order); return; } else { /* Check for previously listed readings which are incompatible * with this one - e.g. Count vs FrCount */ bool fBad = fFalse; switch (d) { case Station: if (mUsed & (BIT(Fr) | BIT(To))) fBad = fTrue; break; case Fr: case To: if (TSTBIT(mUsed, Station)) fBad = fTrue; break; case Count: if (mUsed & (BIT(FrCount) | BIT(ToCount) | BIT(Tape))) fBad = fTrue; break; case FrCount: case ToCount: if (mUsed & (BIT(Count) | BIT(Tape))) fBad = fTrue; break; case Depth: if (mUsed & (BIT(FrDepth) | BIT(ToDepth) | BIT(DepthChange))) fBad = fTrue; break; case FrDepth: case ToDepth: if (mUsed & (BIT(Depth) | BIT(DepthChange))) fBad = fTrue; break; case DepthChange: if (mUsed & (BIT(FrDepth) | BIT(ToDepth) | BIT(Depth))) fBad = fTrue; break; case Newline: if (mUsed & ~m_multi) { /* e.g. "*data normal from to tape newline compass clino" */ file.lpos += strlen(buffer); compile_error_skip(-/*NEWLINE can only be preceded by STATION, DEPTH, and COUNT*/226); osfree(style_name); osfree(new_order); return; } if (k == 0) { file.lpos += strlen(buffer); compile_error_skip(-/*NEWLINE can’t be the first reading*/222); osfree(style_name); osfree(new_order); return; } break; default: /* avoid compiler warnings about unhandled enums */ break; } if (fBad) { /* Not entirely happy with phrasing this... */ file.lpos += strlen(buffer); compile_error_skip(-/*Reading “%s” duplicates previous reading(s)*/77, buffer); osfree(style_name); osfree(new_order); return; } mUsed |= BIT(d); /* used to catch duplicates */ } } if (k && new_order[k - 1] == IgnoreAll) { SVX_ASSERT(d == Newline); k--; d = IgnoreAllAndNewLine; } if (k >= kMac) { kMac = kMac * 2; new_order = osrealloc(new_order, kMac * sizeof(reading)); } new_order[k++] = d; } while (d != End); if (k >= 2 && new_order[k - 2] == Newline) { file.lpos += strlen(buffer); compile_error_skip(-/*NEWLINE can’t be the last reading*/223); osfree(style_name); osfree(new_order); return; } if (style == STYLE_NOSURVEY) { if (TSTBIT(mUsed, Station)) { if (k >= kMac) { kMac = kMac * 2; new_order = osrealloc(new_order, kMac * sizeof(reading)); } new_order[k - 1] = Newline; new_order[k++] = End; } } else if (style == STYLE_PASSAGE) { /* Station doesn't mean "multiline" for STYLE_PASSAGE. */ } else if (!TSTBIT(mUsed, Newline) && (m_multi & mUsed)) { /* This is for when they write * *data normal station tape compass clino * (i.e. no newline, but interleaved readings) */ compile_error_skip(/*Interleaved readings, but no NEWLINE*/224); osfree(style_name); osfree(new_order); return; } #if 0 printf("mUsed = 0x%x\n", mUsed); #endif /* Check the supplied readings form a sufficient set. */ if (style != STYLE_PASSAGE) { if (mUsed & (BIT(Fr) | BIT(To))) mUsed |= BIT(Station); else if (TSTBIT(mUsed, Station)) mUsed |= BIT(Fr) | BIT(To); } if (mUsed & (BIT(Comp) | BIT(BackComp))) mUsed |= BIT(Comp) | BIT(BackComp); if (mUsed & (BIT(Clino) | BIT(BackClino))) mUsed |= BIT(Clino) | BIT(BackClino); if (mUsed & (BIT(FrDepth) | BIT(ToDepth))) mUsed |= BIT(Depth) | BIT(DepthChange); else if (TSTBIT(mUsed, Depth)) mUsed |= BIT(FrDepth) | BIT(ToDepth) | BIT(DepthChange); else if (TSTBIT(mUsed, DepthChange)) mUsed |= BIT(FrDepth) | BIT(ToDepth) | BIT(Depth); if (mUsed & (BIT(FrCount) | BIT(ToCount))) mUsed |= BIT(Count) | BIT(Tape); else if (TSTBIT(mUsed, Count)) mUsed |= BIT(FrCount) | BIT(ToCount) | BIT(Tape); else if (TSTBIT(mUsed, Tape)) mUsed |= BIT(FrCount) | BIT(ToCount) | BIT(Count); #if 0 printf("mUsed = 0x%x, opt = 0x%x, mask = 0x%x\n", mUsed, mask_optional[style], mask[style]); #endif if (((mUsed &~ BIT(Newline)) | mask_optional[style]) != mask[style]) { /* Test should only fail with too few bits set, not too many */ SVX_ASSERT((((mUsed &~ BIT(Newline)) | mask_optional[style]) &~ mask[style]) == 0); compile_error_skip(/*Too few readings for data style “%s”*/64, style_name); osfree(style_name); osfree(new_order); return; } /* don't free default ordering or ordering used by parent */ if (pcs->ordering != default_order && !(pcs->next && pcs->next->ordering == pcs->ordering)) osfree(pcs->ordering); pcs->style = style; pcs->ordering = new_order; osfree(style_name); if (style == STYLE_PASSAGE) { lrudlist * new_psg = osnew(lrudlist); new_psg->tube = NULL; new_psg->next = model; model = new_psg; next_lrud = &(new_psg->tube); } }
static void cmd_set(void) { static sztok chartab[] = { {"BLANK", SPECIAL_BLANK }, /*FIXME {"CLOSE", SPECIAL_CLOSE }, */ {"COMMENT", SPECIAL_COMMENT }, {"DECIMAL", SPECIAL_DECIMAL }, {"EOL", SPECIAL_EOL }, /* EOL won't work well */ {"KEYWORD", SPECIAL_KEYWORD }, {"MINUS", SPECIAL_MINUS }, {"NAMES", SPECIAL_NAMES }, {"OMIT", SPECIAL_OMIT }, /*FIXME {"OPEN", SPECIAL_OPEN }, */ {"PLUS", SPECIAL_PLUS }, #ifndef NO_DEPRECATED {"ROOT", SPECIAL_ROOT }, #endif {"SEPARATOR", SPECIAL_SEPARATOR }, {NULL, SPECIAL_UNKNOWN } }; int mask; int i; get_token(); mask = match_tok(chartab, TABSIZE(chartab)); if (mask == SPECIAL_UNKNOWN) { file.lpos += strlen(buffer); compile_error_skip(-/*Unknown character class “%s”*/42, buffer); return; } #ifndef NO_DEPRECATED if (mask == SPECIAL_ROOT) { if (root_depr_count < 5) { file.lpos += strlen(buffer); compile_warning(-/*ROOT is deprecated*/25); if (++root_depr_count == 5) compile_warning(/*Further uses of this deprecated feature will not be reported*/95); } } #endif /* if we're currently using an inherited translation table, allocate a new * table, and copy old one into it */ if (pcs->next && pcs->next->Translate == pcs->Translate) { short *p; p = ((short*)osmalloc(ossizeof(short) * 257)) + 1; memcpy(p - 1, pcs->Translate - 1, sizeof(short) * 257); pcs->Translate = p; } skipblanks(); /* clear this flag for all non-alphanums */ for (i = 0; i < 256; i++) if (!isalnum(i)) pcs->Translate[i] &= ~mask; /* now set this flag for all specified chars */ while (!isEol(ch)) { if (!isalnum(ch)) { pcs->Translate[ch] |= mask; } else if (tolower(ch) == 'x') { int hex; filepos fp; get_pos(&fp); nextch(); if (!isxdigit(ch)) { set_pos(&fp); break; } hex = isdigit(ch) ? ch - '0' : tolower(ch) - 'a'; nextch(); if (!isxdigit(ch)) { set_pos(&fp); break; } hex = hex << 4 | (isdigit(ch) ? ch - '0' : tolower(ch) - 'a'); pcs->Translate[hex] |= mask; } else { break; } nextch(); } }
/* returns mask with bit x set to indicate quantity x specified */ static unsigned long get_qlist(unsigned long mask_bad) { static sztok qtab[] = { {"ALTITUDE", Q_DZ }, {"BACKBEARING", Q_BACKBEARING }, {"BACKCLINO", Q_BACKGRADIENT }, /* alternative name */ {"BACKCOMPASS", Q_BACKBEARING }, /* alternative name */ {"BACKGRADIENT", Q_BACKGRADIENT }, {"BEARING", Q_BEARING }, {"CEILING", Q_UP }, /* alternative name */ {"CLINO", Q_GRADIENT }, /* alternative name */ {"COMPASS", Q_BEARING }, /* alternative name */ {"COUNT", Q_COUNT }, {"COUNTER", Q_COUNT }, /* alternative name */ {"DECLINATION", Q_DECLINATION }, {"DEFAULT", Q_DEFAULT }, /* not a real quantity... */ {"DEPTH", Q_DEPTH }, {"DOWN", Q_DOWN }, {"DX", Q_DX }, /* alternative name */ {"DY", Q_DY }, /* alternative name */ {"DZ", Q_DZ }, /* alternative name */ {"EASTING", Q_DX }, {"FLOOR", Q_DOWN }, /* alternative name */ {"GRADIENT", Q_GRADIENT }, {"LEFT", Q_LEFT }, {"LENGTH", Q_LENGTH }, {"LEVEL", Q_LEVEL}, {"NORTHING", Q_DY }, {"PLUMB", Q_PLUMB}, {"POSITION", Q_POS }, {"RIGHT", Q_RIGHT }, {"TAPE", Q_LENGTH }, /* alternative name */ {"UP", Q_UP }, {NULL, Q_NULL } }; unsigned long qmask = 0; int tok; filepos fp; while (1) { get_pos(&fp); get_token(); tok = match_tok(qtab, TABSIZE(qtab)); if (tok == Q_DEFAULT && !(mask_bad & BIT(Q_DEFAULT))) { /* Only recognise DEFAULT if it is the first quantity, and then don't * look for any more. */ if (qmask == 0) return BIT(Q_DEFAULT); break; } /* bail out if we reach the table end with no match */ if (tok == Q_NULL) break; qmask |= BIT(tok); if (qmask & mask_bad) { file.lpos += strlen(buffer); compile_error_skip(-/*Unknown instrument “%s”*/39, buffer); return 0; } } if (qmask == 0) { file.lpos += strlen(buffer); compile_error_skip(-/*Unknown quantity “%s”*/34, buffer); } else { set_pos(&fp); } return qmask; }