%{
/*
* Copyright (c) 2020 NVI, Inc.
*
* This file is part of VLBI Field System
* (see http://github.com/nvi-inc/fs).
*
* 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, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see .
*/
#include
#include
#include
#include
#include "vex.h"
#include "vex_parse.tab.h"
#define ALLOC_SIZE 32
#define NEWSTR(ptr,from) { if(strlen(from) > 128) {\
yyerror("string too long"); }\
if (NULL == (ptr = strdup(from)) ) { \
yyerror("out of memory");} }
#define isodigit(x) ((x) >= '0' && (x) <= '7')
#define hextoint(x) (isdigit((x)) ? (x) - '0'\
: ((x) - 'A') + 10)
static char *find_end(char *buffer, char *text);
static int ref=0;
static int inthreads=0;
static int trailing=0;
int lines=1;
static int version=1;
struct llist *lit();
char *quote();
void yyerror(char const *s);
%}
%option noyywrap
%x VERSION DEF LINE REF
%e 5000
%p 10000
%n 2000
%a 8000
NAME [^ \t\n\r;:=&*$"]*
WHITE [ \t\r]
MANTISSA [+-]?([0-9]+"."[0-9]+|[0-9]+|[0-9]+"."[0-9]*|[0-9]*"."[0-9]+)
EXPONENT [eE][+-]?[0-9]+
DOUBLE {MANTISSA}{EXPONENT}?
SEC [0-9]{1,2}|{DOUBLE}
ANGLE [+-]?([0-9]{1,2})d([0-9]{1,2})\'{SEC}\"
%%
{if(version)BEGIN(VERSION);version=0;}
"*" {yyerror("Comment not allowed before end of VEX_REV statement\n");}
VEX_rev {return T_VEX_REV;}
{NAME} {NEWSTR(yylval.sval,yytext); return T_NAME;}
{WHITE}* { /* skip white space */ }
; {trailing=1;BEGIN(LINE); return yytext[0];}
= {return(yytext[0]);}
. {yyerror("lexical error 1 - non-token in version");}
\n {lines++;}
{WHITE}* { /* skip white space */ }
; {trailing=1;BEGIN(LINE); return yytext[0];}
{NAME}* {NEWSTR(yylval.sval,yytext); return T_NAME;}
\" { yylval.sval=quote(); return T_NAME;}
: { return(yytext[0]);}
. { yyerror("lexical error 2 - non-token in def statement");}
"*"[^\n]* {NEWSTR(yylval.sval,yytext); /* comment */
if(trailing)
return T_COMMENT_TRAILING;
else
return T_COMMENT;}
"$"GLOBAL {BEGIN(INITIAL);return B_GLOBAL;}
"$"STATION {BEGIN(INITIAL);return B_STATION;}
"$"EXPER {BEGIN(INITIAL);return B_EXPER;}
"$"SCHEDULING_PARAMS {BEGIN(INITIAL);return B_SCHEDULING_PARAMS;}
"$"PROCEDURES {BEGIN(INITIAL);return B_PROCEDURES;}
"$"EOP {BEGIN(INITIAL);return B_EOP;}
"$"MODE {BEGIN(INITIAL);return B_MODE;}
"$"FREQ {BEGIN(INITIAL);return B_FREQ;}
"$"CLOCK {BEGIN(INITIAL);return B_CLOCK;}
"$"ANTENNA {BEGIN(INITIAL);return B_ANTENNA;}
"$"BBC {BEGIN(INITIAL);return B_BBC;}
"$"BITSTREAMS {BEGIN(INITIAL);return B_BITSTREAMS;}
"$"EXTENSIONS {BEGIN(INITIAL);return B_EXTENSIONS;}
"$"CORR {BEGIN(INITIAL);return B_CORR;}
"$"DAS {BEGIN(INITIAL);return B_DAS;}
"$"DATASTREAMS {inthreads = 0; BEGIN(INITIAL);return B_DATASTREAMS;}
"$"HEAD_POS {BEGIN(INITIAL);return B_HEAD_POS;}
"$"PASS_ORDER {BEGIN(INITIAL);return B_PASS_ORDER;}
"$"PHASE_CAL_DETECT {BEGIN(INITIAL);return B_PHASE_CAL_DETECT;}
"$"ROLL {BEGIN(INITIAL);return B_ROLL;}
"$"IF {BEGIN(INITIAL);return B_IF;}
"$"SEFD {BEGIN(INITIAL);return B_SEFD;}
"$"SITE {BEGIN(INITIAL);return B_SITE;}
"$"SOURCE {BEGIN(INITIAL);return B_SOURCE;}
"$"TAPELOG_OBS {BEGIN(INITIAL);return B_TAPELOG_OBS;}
"$"TRACKS {BEGIN(INITIAL);return B_TRACKS;}
"$"THREADS {inthreads = 1; BEGIN(INITIAL); return B_THREADS;}
"$"SCHED {BEGIN(INITIAL);return B_SCHED;}
[= {if(ref == 1) {ref=0;BEGIN(DEF);} return(yytext[0]);}
ref {BEGIN(REF);ref=1;return T_REF;}
def {BEGIN(DEF);return T_DEF;}
enddef {BEGIN(INITIAL);return T_ENDDEF;}
scan {BEGIN(DEF);return T_SCAN;}
endscan {BEGIN(INITIAL);return T_ENDSCAN;}
chan_def {BEGIN(INITIAL);return T_CHAN_DEF;}
sample_rate {BEGIN(INITIAL);return T_SAMPLE_RATE;}
bits_per_sample {BEGIN(INITIAL);return T_BITS_PER_SAMPLE;}
switching_cycle {BEGIN(INITIAL);return T_SWITCHING_CYCLE;}
start {BEGIN(INITIAL);return T_START;}
source {BEGIN(INITIAL);return T_SOURCE;}
mode {BEGIN(INITIAL);return T_MODE;}
station {BEGIN(INITIAL);return T_STATION;}
data_transfer {BEGIN(INITIAL);return T_DATA_TRANSFER;}
intent {BEGIN(INITIAL);return T_INTENT;}
pointing_offset {BEGIN(INITIAL);return T_POINTING_OFFSET;}
antenna_diam {BEGIN(INITIAL);return T_ANTENNA_DIAM;}
axis_type {BEGIN(INITIAL);return T_AXIS_TYPE;}
axis_offset {BEGIN(INITIAL);return T_AXIS_OFFSET;}
antenna_motion {BEGIN(INITIAL);return T_ANTENNA_MOTION;}
pointing_sector {BEGIN(INITIAL);return T_POINTING_SECTOR;}
nasmyth {BEGIN(INITIAL);return T_NASMYTH;}
BBC_assign {BEGIN(INITIAL);return T_BBC_ASSIGN;}
stream_def {BEGIN(INITIAL);return T_STREAM_DEF;}
stream_sample_rate {BEGIN(INITIAL);return T_STREAM_SAMPLE_RATE;}
stream_label {BEGIN(INITIAL);return T_STREAM_LABEL;}
clock_early {BEGIN(INITIAL);return T_CLOCK_EARLY;}
record_transport_type {BEGIN(INITIAL);return T_RECORD_TRANSPORT_TYPE;}
electronics_rack_type {BEGIN(INITIAL);return T_ELECTRONICS_RACK_TYPE;}
number_drives {BEGIN(INITIAL);return T_NUMBER_DRIVES;}
headstack {BEGIN(INITIAL);return T_HEADSTACK;}
record_density {BEGIN(INITIAL);return T_RECORD_DENSITY;}
tape_length {BEGIN(INITIAL);return T_TAPE_LENGTH;}
recording_system_ID {BEGIN(INITIAL);return T_RECORDING_SYSTEM_ID;}
tape_motion {BEGIN(INITIAL);return T_TAPE_MOTION;}
tape_control {BEGIN(INITIAL);return T_TAPE_CONTROL;}
equip {BEGIN(INITIAL);return T_EQUIP;}
composite_equip {BEGIN(INITIAL);return T_COMPOSITE_EQUIP;}
equip_set {BEGIN(INITIAL);return T_EQUIP_SET;}
equip_info {BEGIN(INITIAL);return T_EQUIP_INFO;}
connection {BEGIN(INITIAL);return T_CONNECTION;}
record_method {BEGIN(INITIAL);return T_RECORD_METHOD;}
record_control {BEGIN(INITIAL);return T_RECORD_CONTROL;}
datastream {BEGIN(INITIAL);return T_DATASTREAM;}
thread {BEGIN(INITIAL);return (inthreads ? T_THREAD_DEF : T_THREAD);}
channel {BEGIN(INITIAL);return (inthreads ? T_CHANNEL_DEF : T_CHANNEL);}
merged_datastream {BEGIN(INITIAL);return T_MERGED_DATASTREAM;}
TAI-UTC {BEGIN(INITIAL);return T_TAI_UTC;}
A1-TAI {BEGIN(INITIAL);return T_A1_TAI;}
eop_ref_epoch {BEGIN(INITIAL);return T_EOP_REF_EPOCH;}
num_eop_points {BEGIN(INITIAL);return T_NUM_EOP_POINTS;}
eop_interval {BEGIN(INITIAL);return T_EOP_INTERVAL;}
ut1-utc {BEGIN(INITIAL);return T_UT1_UTC;}
x_wobble {BEGIN(INITIAL);return T_X_WOBBLE;}
y_wobble {BEGIN(INITIAL);return T_Y_WOBBLE;}
nut_ref_epoch {BEGIN(INITIAL);return T_NUT_REF_EPOCH;}
num_nut_points {BEGIN(INITIAL);return T_NUM_NUT_POINTS;}
nut_interval {BEGIN(INITIAL);return T_NUT_INTERVAL;}
delta_psi {BEGIN(INITIAL);return T_DELTA_PSI;}
delta_eps {BEGIN(INITIAL);return T_DELTA_EPS;}
nut_model {BEGIN(INITIAL);return T_NUT_MODEL;}
eop_origin {BEGIN(INITIAL);return T_EOP_ORIGIN;}
delta_x_nut {BEGIN(INITIAL);return T_DELTA_X_NUT;}
delta_y_nut {BEGIN(INITIAL);return T_DELTA_Y_NUT;}
nut_origin {BEGIN(INITIAL);return T_NUT_ORIGIN;}
exper_num {BEGIN(INITIAL);return T_EXPER_NUM;}
exper_name {BEGIN(INITIAL);return T_EXPER_NAME;}
exper_description {BEGIN(INITIAL);return T_EXPER_DESCRIPTION;}
exper_nominal_start {BEGIN(INITIAL);return T_EXPER_NOMINAL_START;}
exper_nominal_stop {BEGIN(INITIAL);return T_EXPER_NOMINAL_STOP;}
PI_name {BEGIN(INITIAL);return T_PI_NAME;}
PI_email {BEGIN(INITIAL);return T_PI_EMAIL;}
contact_name {BEGIN(INITIAL);return T_CONTACT_NAME;}
contact_email {BEGIN(INITIAL);return T_CONTACT_EMAIL;}
scheduler_name {BEGIN(INITIAL);return T_SCHEDULER_NAME;}
scheduler_email {BEGIN(INITIAL);return T_SCHEDULER_EMAIL;}
target_correlator {BEGIN(INITIAL);return T_TARGET_CORRELATOR;}
scheduling_software {BEGIN(INITIAL);return T_SCHEDULING_SOFTWARE;}
VEX_file_writer {BEGIN(INITIAL);return T_VEX_FILE_WRITER;}
extension {BEGIN(INITIAL);return T_EXTENSION;}
headstack_pos {BEGIN(INITIAL);return T_HEADSTACK_POS;}
if_def {BEGIN(INITIAL);return T_IF_DEF;}
receiver_name {BEGIN(INITIAL);return T_RECEIVER_NAME;}
sub_lo_frequencies {BEGIN(INITIAL);return T_SUB_LO_FREQUENCIES;}
sub_lo_sidebands {BEGIN(INITIAL);return T_SUB_LO_SIDEBANDS;}
switched_power {BEGIN(INITIAL);return T_SWITCHED_POWER;}
pass_order {BEGIN(INITIAL);return T_PASS_ORDER;}
S2_group_order {BEGIN(INITIAL);return T_S2_GROUP_ORDER;}
phase_cal_detect {BEGIN(INITIAL);return T_PHASE_CAL_DETECT;}
tape_change {BEGIN(INITIAL);return T_TAPE_CHANGE;}
headstack_motion {BEGIN(INITIAL);return T_HEADSTACK_MOTION;}
new_source_command {BEGIN(INITIAL);return T_NEW_SOURCE_COMMAND;}
new_tape_setup {BEGIN(INITIAL);return T_NEW_TAPE_SETUP;}
setup_always {BEGIN(INITIAL);return T_SETUP_ALWAYS;}
parity_check {BEGIN(INITIAL);return T_PARITY_CHECK;}
tape_prepass {BEGIN(INITIAL);return T_TAPE_PREPASS;}
preob_cal {BEGIN(INITIAL);return T_PREOB_CAL;}
midob_cal {BEGIN(INITIAL);return T_MIDOB_CAL;}
postob_cal {BEGIN(INITIAL);return T_POSTOB_CAL;}
procedure_name_prefix {BEGIN(INITIAL);return T_PROCEDURE_NAME_PREFIX;}
roll_reinit_period {BEGIN(INITIAL);return T_ROLL_REINIT_PERIOD;}
roll_inc_period {BEGIN(INITIAL);return T_ROLL_INC_PERIOD;}
roll {BEGIN(INITIAL);return T_ROLL;}
roll_def {BEGIN(INITIAL);return T_ROLL_DEF;}
sefd_model {BEGIN(INITIAL);return T_SEFD_MODEL;}
sefd {BEGIN(INITIAL);return T_SEFD;}
site_type {BEGIN(INITIAL);return T_SITE_TYPE;}
site_name {BEGIN(INITIAL);return T_SITE_NAME;}
site_ID {BEGIN(INITIAL);return T_SITE_ID;}
site_position {BEGIN(INITIAL);return T_SITE_POSITION;}
site_position_epoch {BEGIN(INITIAL);return T_SITE_POSITION_EPOCH;}
site_position_ref {BEGIN(INITIAL);return T_SITE_POSITION_REF;}
site_velocity {BEGIN(INITIAL);return T_SITE_VELOCITY;}
horizon_map_az {BEGIN(INITIAL);return T_HORIZON_MAP_AZ;}
horizon_map_el {BEGIN(INITIAL);return T_HORIZON_MAP_EL;}
zen_atmos {BEGIN(INITIAL);return T_ZEN_ATMOS;}
ocean_load_vert {BEGIN(INITIAL);return T_OCEAN_LOAD_VERT;}
ocean_load_horiz {BEGIN(INITIAL);return T_OCEAN_LOAD_HORIZ;}
occupation_code {BEGIN(INITIAL);return T_OCCUPATION_CODE;}
inclination {BEGIN(INITIAL);return T_INCLINATION;}
eccentricity {BEGIN(INITIAL);return T_ECCENTRICITY;}
arg_perigee {BEGIN(INITIAL);return T_ARG_PERIGEE;}
ascending_node {BEGIN(INITIAL);return T_ASCENDING_NODE;}
mean_anomaly {BEGIN(INITIAL);return T_MEAN_ANOMALY;}
semi-major_axis {BEGIN(INITIAL);return T_SEMI_MAJOR_AXIS;}
mean_motion {BEGIN(INITIAL);return T_MEAN_MOTION;}
orbit_epoch {BEGIN(INITIAL);return T_ORBIT_EPOCH;}
source_type {BEGIN(INITIAL);return T_SOURCE_TYPE;}
source_name {BEGIN(INITIAL);return T_SOURCE_NAME;}
IAU_name {BEGIN(INITIAL);return T_IAU_NAME;}
ra {BEGIN(INITIAL);return T_RA;}
dec {BEGIN(INITIAL);return T_DEC;}
ref_coord_frame {BEGIN(INITIAL);return T_REF_COORD_FRAME;}
source_position_ref {BEGIN(INITIAL);return T_SOURCE_POSITION_REF;}
ra_rate {BEGIN(INITIAL);return T_RA_RATE;}
dec_rate {BEGIN(INITIAL);return T_DEC_RATE;}
source_position_epoch {BEGIN(INITIAL);return T_SOURCE_POSITION_EPOCH;}
velocity_wrt_LSR {BEGIN(INITIAL);return T_VELOCITY_WRT_LSR;}
source_model {BEGIN(INITIAL);return T_SOURCE_MODEL;}
bsp_file_name {BEGIN(INITIAL);return T_BSP_FILE_NAME;}
bsp_object_id {BEGIN(INITIAL);return T_BSP_OBJECT_ID;}
tle0 {BEGIN(INITIAL);return T_TLE0;}
tle1 {BEGIN(INITIAL);return T_TLE1;}
tle2 {BEGIN(INITIAL);return T_TLE2;}
datum {BEGIN(INITIAL);return T_DATUM;}
vector {BEGIN(INITIAL);return T_VECTOR;}
VSN {BEGIN(INITIAL);return T_VSN;}
fanin_def {BEGIN(INITIAL);return T_FANIN_DEF;}
fanout_def {BEGIN(INITIAL);return T_FANOUT_DEF;}
track_frame_format {BEGIN(INITIAL);return T_TRACK_FRAME_FORMAT;}
data_modulation {BEGIN(INITIAL);return T_DATA_MODULATION;}
VLBA_frmtr_sys_trk {BEGIN(INITIAL);return T_VLBA_FRMTR_SYS_TRK;}
VLBA_trnsprt_sys_trk {BEGIN(INITIAL);return T_VLBA_TRNSPRT_SYS_TRK;}
S2_recording_mode {BEGIN(INITIAL);return T_S2_RECORDING_MODE;}
S2_data_source {BEGIN(INITIAL);return T_S2_DATA_SOURCE;}
format {BEGIN(INITIAL);return T_FORMAT_DEF;}
start_literal\( {BEGIN(INITIAL); yylval.llptr=lit(); return T_LITERAL;}
\n {trailing=0;lines++;}
{WHITE}* {/* skip white space */}
. {yyerror("lexical error 3 - non-token at start of statement");}
][{NAME} { NEWSTR(yylval.sval,yytext);return T_NAME; }
][: {return(yytext[0]);}
][. {yyerror("lexical error 4 - non-token in ref statement");}
{ANGLE} { NEWSTR(yylval.sval,yytext); return T_ANGLE; }
\" { yylval.sval=quote(); return T_NAME;}
{NAME} { NEWSTR(yylval.sval,yytext); return T_NAME; }
\&{NAME} { NEWSTR(yylval.sval,yytext+1); return T_LINK; }
\&\" { yylval.sval=quote(); return T_LINK;}
\n {trailing=0;lines++;}
{WHITE}* {/* skip white space */}
; {trailing=1;BEGIN(LINE);return(yytext[0]);}
: {return(yytext[0]);}
. {yyerror("lexical error 5 - non-token after statement started");}
<> {version=1;ref=0;trailing=0;lines=1;yyterminate();}
%%
struct llist *lit()
{
int inch, count, max_size;
char *buffer, *last, *text;
struct llist *llist;
buffer = malloc(ALLOC_SIZE);
if(buffer == NULL)
yyerror("out of memory in literal 1");
/* find text inside start_literal() */
max_size = ALLOC_SIZE;
count=0;
inch= input();
while(inch !=EOF && inch != ')' && inch != 0 && inch != '\n') {
buffer[count++]=inch;
if(count >= max_size) {
buffer=realloc(buffer,max_size+ALLOC_SIZE);
if(buffer == NULL)
yyerror("out of memory in literal 2");
max_size += ALLOC_SIZE;
}
inch=input();
}
if(inch == EOF)
yyerror("End of file in literal block delimiting text\n");
else if (inch == 0)
yyerror("Illegal character (\\0) in literal delimiting text\n");
else if (inch == '\n')
yyerror("Illegal character (\\n) in literal delimiting text\n");
buffer[count++]='\0';
buffer=realloc(buffer,count);
if(buffer == NULL)
yyerror("out of memory in literal 3");
text=buffer;
llist=add_list(NULL,buffer);
/* skip to ';' */
inch=input();
while(inch !=EOF && inch != ';' && inch != '\0') {
if(inch == '\n')
lines++;
else if(NULL == strchr(" \t\r",inch))
yyerror("Illegal character after start_literal()");
inch=input();
}
if(inch == EOF)
yyerror("End of file in literal block");
else if (inch == 0)
yyerror("Illegal character (\\0) after start_literal()");
/* skip to '\n' */
inch=input();
while(inch !=EOF && inch != '\n' && inch != '\0') {
if(NULL == strchr(" \t\r",inch))
yyerror("Illegal Xcharacter after start_literal();");
inch=input();
}
if(inch == EOF)
yyerror("End of file in literal block");
else if (inch == 0)
yyerror("Illegal character (\\0) after start_literal();");
else if(inch == '\n')
lines++;
/* read lines */
buffer = malloc(ALLOC_SIZE);
if(buffer == NULL)
yyerror("out of memory in literal 4");
max_size = ALLOC_SIZE;
count=0;
inch= input();
while(inch !=EOF && inch != 0) {
if(inch != '\n') {
buffer[count++]=inch;
if(count >= max_size) {
buffer=realloc(buffer,max_size+ALLOC_SIZE);
if(buffer == NULL)
yyerror("out of memory in literal 8");
max_size += ALLOC_SIZE;
}
} else {
buffer[count++]='\0';
last=find_end(buffer,text);
if(last != NULL)
goto done;
lines++;
buffer=realloc(buffer,count);
if(buffer == NULL)
yyerror("out of memory in literal 6");
llist=add_list(llist,buffer);
buffer = malloc(ALLOC_SIZE);
if(buffer == NULL)
yyerror("out of memory in literal 7");
max_size = ALLOC_SIZE;
count=0;
}
inch=input();
}
if(inch == EOF)
yyerror("End of file in literal block\n");
else if (inch == 0)
yyerror("Illegal character (\\0) in literal block\n");
done:
{
int i=strlen(last)-1;
unput('\n');
while ( i >= 0) {
unput(last[i]);
i--;
}
}
free(buffer);
return llist;
}
static char *find_end(char *buffer, char *text)
{
char *ptr, *start;
char end[]="end_literal(";
int textlen=strlen(text);
start=buffer;
while(NULL != (ptr=strchr(buffer++,end[0])))
if(0==strncmp(ptr,end,sizeof(end)-1))
if(0==strncmp(ptr+sizeof(end)-1,text,textlen))
if(0==strncmp(ptr+sizeof(end)-1+textlen,")",1)) {
*ptr='\0';
for(;*start!=0;start++)
if(NULL == strchr(" \t\r",*start))
yyerror("Illegal character between '\\n' and end_literal(...)");
return ptr+sizeof(end)+textlen;
}
return NULL;
}
char *quote()
{
int inch, count, max_size;
char *buffer;
int temp, ch;
buffer = malloc(ALLOC_SIZE);
max_size = ALLOC_SIZE;
inch=input();
count=0;
while(inch != EOF && inch != '"' && inch != '\n') {
if(inch=='\\') {
inch=input();
ch=0;
switch (inch) {
case '\n':
lines++;
inch=input();
break;
case 'b':
inch='\b';
break;
case 't':
inch='\t';
break;
case 'n':
inch='\n';
break;
case 'v':
inch='\v';
break;
case 'f':
inch='\f';
break;
case 'r':
inch='\r';
break;
case 'X':
ch='X';
case 'x':
inch=input();
if(isxdigit(inch)){
temp=hextoint(toupper(inch));
inch=input();
if(isxdigit(inch)){
temp=(temp <<4) + hextoint(toupper(inch));
} else {
unput(inch);
}
inch=temp;
} else {
unput(inch);
if (ch=='X') {
inch='X';
} else {
inch='x';
}
}
break;
default:
if(isodigit(inch)) {
temp=inch-'0';
inch=input();
if(isodigit(inch)){
temp = (temp << 3) + (inch - '0');
inch=input();
if(isodigit(inch)){
temp = (temp << 3) + (inch - '0');
} else {
unput(inch);
}
} else {
unput(inch);
}
inch=temp;
}
}
}
if(inch == 0) {
char tmpbuf[128];
sprintf(tmpbuf, "Null byte specified at line %d\n", lines);
yyerror(tmpbuf);
}
buffer[count++] = inch;
if(count >= max_size) {
buffer = realloc(buffer,max_size + ALLOC_SIZE);
max_size += ALLOC_SIZE;
}
inch = input();
}
if(inch == EOF || inch == '\n') {
char tmpbuf[128];
sprintf(tmpbuf, "Unterminated string at line %d\n", lines);
yyerror(tmpbuf);
}
buffer[count]='\0';
if(strlen(buffer) > 128) {
yyerror("quoted string too long");
}
return buffer;
}
]