/*
|
/*
|
* fatal --- fatal error handler
|
* fatal --- fatal error handler
|
*/
|
*/
|
fatal(str)
|
fatal(str)
|
char *str;
|
char *str;
|
{
|
{
|
printf("%s\n",str);
|
printf("%s\n",str);
|
|
|
#ifdef IBM /* changed ver TER_2.0 */
|
#ifdef IBM /* changed ver TER_2.0 */
|
exit(-1);
|
exit(-1);
|
#else
|
#else
|
exit(10); /* Amiga & UNIX prefer positive numbers for error
|
exit(10); /* Amiga & UNIX prefer positive numbers for error
|
minimal error is 10 (no system prob) */
|
minimal error is 10 (no system prob) */
|
#endif
|
#endif
|
}
|
}
|
|
|
/*
|
/*
|
* error --- error in a line
|
* error --- error in a line
|
* print line number and error
|
* print line number and error
|
*/
|
*/
|
error(str)
|
error(str)
|
char *str;
|
char *str;
|
{
|
{
|
/* if(N_files > 1) commented out test for N_files in rel TER_2.0
|
/* if(N_files > 1) commented out test for N_files in rel TER_2.0
|
because a single command line source file
|
because a single command line source file
|
(which is what N_files counts) can have multiple
|
(which is what N_files counts) can have multiple
|
include source files. */
|
include source files. */
|
printf("%s\n",str);
|
printf("%s\n",str);
|
}
|
}
|
/*
|
/*
|
* warn --- trivial error in a line
|
* warn --- trivial error in a line
|
* print line number and error
|
* print line number and error
|
*/
|
*/
|
warn(str)
|
warn(str)
|
char *str;
|
char *str;
|
{
|
{
|
/* if(N_files > 1) commented out in rel TER_2.0 same reason as above */
|
/* if(N_files > 1) commented out in rel TER_2.0 same reason as above */
|
printf("%s, line no.",Argv[Cfn]); /* current file name */
|
printf("%s, line no.",Argv[Cfn]); /* current file name */
|
printf("%d: ",Line_num); /* current line number */
|
printf("%d: ",Line_num); /* current line number */
|
printf("Warning --- %s\n",str);
|
printf("Warning --- %s\n",str);
|
Page_lines++;
|
Page_lines++;
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* delim --- check if character is a delimiter
|
* delim --- check if character is a delimiter
|
*/
|
*/
|
delim(c)
|
delim(c)
|
char c;
|
char c;
|
{
|
{
|
if( any(c," \t\n"))
|
if( any(c," \t\n"))
|
return(YES);
|
return(YES);
|
return(NO);
|
return(NO);
|
}
|
}
|
|
|
/*
|
/*
|
* skip_white --- move pointer to next non-whitespace char
|
* skip_white --- move pointer to next non-whitespace char
|
*/
|
*/
|
char *skip_white(ptr)
|
char *skip_white(ptr)
|
char *ptr;
|
char *ptr;
|
{
|
{
|
while(*ptr==BLANK || *ptr==TAB)
|
while(*ptr==BLANK || *ptr==TAB)
|
ptr++;
|
ptr++;
|
return(ptr);
|
return(ptr);
|
}
|
}
|
|
|
/*
|
/*
|
* eword --- emit a word to code file
|
* eword --- emit a word to code file
|
*/
|
*/
|
eword(wd)
|
eword(wd)
|
int wd;
|
int wd;
|
{
|
{
|
emit(hibyte(wd));
|
emit(hibyte(wd));
|
emit(lobyte(wd));
|
emit(lobyte(wd));
|
}
|
}
|
|
|
/*
|
/*
|
* emit --- emit a byte to code file
|
* emit --- emit a byte to code file
|
*/
|
*/
|
emit(byte)
|
emit(byte)
|
{
|
{
|
#ifdef DEBUG
|
#ifdef DEBUG
|
printf("%2x @ %4x\n",byte,Pc);
|
printf("%2x @ %4x\n",byte,Pc);
|
#endif
|
#endif
|
if(Pass==1){
|
if(Pass==1){
|
Pc++;
|
Pc++;
|
return(YES);
|
return(YES);
|
}
|
}
|
if(P_total < P_LIMIT)
|
if(P_total < P_LIMIT)
|
P_bytes[P_total++] = byte;
|
P_bytes[P_total++] = byte;
|
E_bytes[E_total++] = byte;
|
E_bytes[E_total++] = byte;
|
Pc++;
|
Pc++;
|
if(E_total == E_LIMIT)
|
if(E_total == E_LIMIT)
|
f_record();
|
f_record();
|
}
|
}
|
|
|
/*
|
/*
|
* f_record --- flush record out in `S1' format
|
* f_record --- flush record out in `S1' format
|
*/
|
*/
|
void f_record() /* made void for ANSI C compat ver TER_2.0 6/18/89 */
|
void f_record() /* made void for ANSI C compat ver TER_2.0 6/18/89 */
|
{
|
{
|
int i;
|
int i;
|
int chksum;
|
int chksum;
|
|
|
if(Pass == 1)
|
if(Pass == 1)
|
return;
|
return;
|
if(E_total==0){
|
if(E_total==0){
|
E_pc = Pc;
|
E_pc = Pc;
|
return;
|
return;
|
}
|
}
|
F_total += E_total; /* total bytes in file ver (TER)2.01 19 Jun 89 */
|
F_total += E_total; /* total bytes in file ver (TER)2.01 19 Jun 89 */
|
chksum = E_total+3; /* total bytes in this record */
|
chksum = E_total+3; /* total bytes in this record */
|
chksum += lobyte(E_pc);
|
chksum += lobyte(E_pc);
|
chksum += E_pc>>8;
|
chksum += E_pc>>8;
|
fprintf(Objfil,"S1"); /* record header preamble */
|
fprintf(Objfil,"S1"); /* record header preamble */
|
hexout(E_total+3); /* byte count +3 */
|
hexout(E_total+3); /* byte count +3 */
|
hexout(E_pc>>8); /* high byte of PC */
|
hexout(E_pc>>8); /* high byte of PC */
|
hexout(lobyte(E_pc)); /* low byte of PC */
|
hexout(lobyte(E_pc)); /* low byte of PC */
|
for(i=0;i<E_total;i++){
|
for(i=0;i<E_total;i++){
|
chksum += lobyte(E_bytes[i]);
|
chksum += lobyte(E_bytes[i]);
|
hexout(lobyte(E_bytes[i])); /* data byte */
|
hexout(lobyte(E_bytes[i])); /* data byte */
|
}
|
}
|
chksum =~ chksum; /* one's complement */
|
chksum =~ chksum; /* one's complement */
|
hexout(lobyte(chksum)); /* checksum */
|
hexout(lobyte(chksum)); /* checksum */
|
if (CRflag == 1) /* test for CRflag added ver TER_1.1 */
|
if (CRflag == 1) /* test for CRflag added ver TER_1.1 */
|
fprintf(Objfil,"%c\n",CR); /* print in IBM format for some PROM boxes */
|
fprintf(Objfil,"%c\n",CR); /* print in IBM format for some PROM boxes */
|
else
|
else
|
fprintf(Objfil,"\n"); /* this is original statement */
|
fprintf(Objfil,"\n"); /* this is original statement */
|
E_pc = Pc;
|
E_pc = Pc;
|
E_total = 0;
|
E_total = 0;
|
}
|
}
|
|
|
char *hexstr = { "0123456789ABCDEF" } ;
|
char *hexstr = { "0123456789ABCDEF" } ;
|
|
|
hexout(byte)
|
hexout(byte)
|
int byte;
|
int byte;
|
{
|
{
|
|
|
byte = lobyte(byte);
|
byte = lobyte(byte);
|
fprintf(Objfil,"%c%c",hexstr[byte>>4],hexstr[byte&017]);
|
fprintf(Objfil,"%c%c",hexstr[byte>>4],hexstr[byte&017]);
|
}
|
}
|
|
|
/*
|
/*
|
* print_line --- pretty print input line
|
* print_line --- pretty print input line
|
*/
|
*/
|
print_line()
|
print_line()
|
{
|
{
|
int i;
|
int i;
|
register char *ptr;
|
register char *ptr;
|
|
|
printf ("%04d ",Line_num);
|
printf ("%04d ",Line_num);
|
if(P_total || P_force)
|
if(P_total || P_force)
|
printf("%04X",Old_pc);
|
printf("%04X",Old_pc);
|
else
|
else
|
printf(" ");
|
printf(" ");
|
|
|
for(i=0;i<P_total && i<6;i++)
|
for(i=0;i<P_total && i<6;i++)
|
printf(" %02X",lobyte(P_bytes[i]));
|
printf(" %02X",lobyte(P_bytes[i]));
|
for(;i<6;i++)
|
for(;i<6;i++)
|
printf(" ");
|
printf(" ");
|
printf(" ");
|
printf(" ");
|
|
|
if(Cflag){
|
if(Cflag){
|
if(Cycles)
|
if(Cycles)
|
printf("[%2d ] ",Cycles);
|
printf("[%2d ] ",Cycles);
|
else
|
else
|
printf(" ");
|
printf(" ");
|
}
|
}
|
ptr = Line;
|
ptr = Line;
|
while( *ptr != '\n' ) /* just echo the line back out */
|
while( *ptr != '\n' ) /* just echo the line back out */
|
putchar(*ptr++);
|
putchar(*ptr++);
|
for(;i<P_total;i++){
|
for(;i<P_total;i++){
|
if( i%6 == 0 )
|
if( i%6 == 0 )
|
printf("\n "); /* force data alignment DWC 1-5-92 */
|
printf("\n "); /* force data alignment DWC 1-5-92 */
|
printf(" %02X",lobyte(P_bytes[i]));
|
printf(" %02X",lobyte(P_bytes[i]));
|
}
|
}
|
if (Pflag50 && (++Page_lines>=50)) /* form feed if flag set */
|
if (Pflag50 && (++Page_lines>=50)) /* form feed if flag set */
|
NewPage(); /* ver (TER) 2.02 19 Jun 89 */
|
NewPage(); /* ver (TER) 2.02 19 Jun 89 */
|
|
|
if (Pflag75 && (++Page_lines>=75)) /* form feed if flag set */
|
if (Pflag75 && (++Page_lines>=75)) /* form feed if flag set */
|
NewPage(); /* ver (DWC) 2.10 8 Oct 2001 */
|
NewPage(); /* ver (DWC) 2.10 8 Oct 2001 */
|
|
|
|
|
printf("\n");
|
printf("\n");
|
}
|
}
|
|
|
/*
|
/*
|
* any --- does str contain c?
|
* any --- does str contain c?
|
*/
|
*/
|
any(c,str)
|
any(c,str)
|
char c;
|
char c;
|
char *str;
|
char *str;
|
{
|
{
|
while(*str != EOS)
|
while(*str != EOS)
|
if(*str++ == c)
|
if(*str++ == c)
|
return(YES);
|
return(YES);
|
return(NO);
|
return(NO);
|
}
|
}
|
|
|
/*
|
/*
|
* mapdn --- convert A-Z to a-z
|
* mapdn --- convert A-Z to a-z
|
*/
|
*/
|
char mapdn(c)
|
char mapdn(c)
|
char c;
|
char c;
|
{
|
{
|
if( c >= 'A' && c <= 'Z')
|
if( c >= 'A' && c <= 'Z')
|
return((char)(c+040)); /* cast value to char for ANSI C, ver TER_2.0 */
|
return((char)(c+040)); /* cast value to char for ANSI C, ver TER_2.0 */
|
return(c);
|
return(c);
|
}
|
}
|
|
|
/*
|
/*
|
* lobyte --- return low byte of an int
|
* lobyte --- return low byte of an int
|
*/
|
*/
|
lobyte(i)
|
lobyte(i)
|
int i;
|
int i;
|
{
|
{
|
return(i&0xFF);
|
return(i&0xFF);
|
}
|
}
|
/*
|
/*
|
* hibyte --- return high byte of an int
|
* hibyte --- return high byte of an int
|
*/
|
*/
|
hibyte(i)
|
hibyte(i)
|
int i;
|
int i;
|
{
|
{
|
return((i>>8)&0xFF);
|
return((i>>8)&0xFF);
|
}
|
}
|
|
|
/*
|
/*
|
* head --- is str2 the head of str1?
|
* head --- is str2 the head of str1?
|
*/
|
*/
|
head(str1,str2)
|
head(str1,str2)
|
char *str1,*str2;
|
char *str1,*str2;
|
{
|
{
|
while( *str1 != EOS && *str2 != EOS){
|
while( *str1 != EOS && *str2 != EOS){
|
if( *str1 != *str2 )break;
|
if( *str1 != *str2 )break;
|
str1++;
|
str1++;
|
str2++;
|
str2++;
|
}
|
}
|
if(*str1 == *str2)return(YES);
|
if(*str1 == *str2)return(YES);
|
if(*str2==EOS)
|
if(*str2==EOS)
|
if( any(*str1," \t\n,+-];*") )return(YES);
|
if( any(*str1," \t\n,+-];*") )return(YES);
|
return(NO);
|
return(NO);
|
}
|
}
|
|
|
/*
|
/*
|
* alpha --- is character a legal letter
|
* alpha --- is character a legal letter
|
*/
|
*/
|
alpha(c)
|
alpha(c)
|
char c;
|
char c;
|
{
|
{
|
if( c<= 'z' && c>= 'a' )return(YES);
|
if( c<= 'z' && c>= 'a' )return(YES);
|
if( c<= 'Z' && c>= 'A' )return(YES);
|
if( c<= 'Z' && c>= 'A' )return(YES);
|
if( c== '_' )return(YES);
|
if( c== '_' )return(YES);
|
if( c== '.' )return(YES);
|
if( c== '.' )return(YES);
|
return(NO);
|
return(NO);
|
}
|
}
|
/*
|
/*
|
* alphan --- is character a legal letter or digit
|
* alphan --- is character a legal letter or digit
|
*/
|
*/
|
alphan(c)
|
alphan(c)
|
char c;
|
char c;
|
{
|
{
|
if( alpha(c) )return(YES);
|
if( alpha(c) )return(YES);
|
if( c<= '9' && c>= '0' )return(YES);
|
if( c<= '9' && c>= '0' )return(YES);
|
if( c == '$' )return(YES); /* allow imbedded $ */
|
if( c == '$' )return(YES); /* allow imbedded $ */
|
if( c == '@' )return(YES); /* allow imbedded @, added ver TER_2.0
|
if( c == '@' )return(YES); /* allow imbedded @, added ver TER_2.0
|
added to permit redefinable variables */
|
added to permit redefinable variables */
|
return(NO);
|
return(NO);
|
}
|
}
|
|
|
/*
|
/*
|
* white --- is character whitespace?
|
* white --- is character whitespace?
|
*/
|
*/
|
white(c)
|
white(c)
|
char c;
|
char c;
|
{
|
{
|
if( c == TAB || c == BLANK || c == '\n' )return(YES);
|
if( c == TAB || c == BLANK || c == '\n' )return(YES);
|
return(NO);
|
return(NO);
|
}
|
}
|
|
|
/*
|
/*
|
* alloc --- allocate memory
|
* alloc --- allocate memory
|
*/
|
*/
|
char *
|
char *
|
alloc(nbytes)
|
alloc(nbytes)
|
int nbytes;
|
int nbytes;
|
{
|
{
|
return(malloc(nbytes));
|
return(malloc(nbytes));
|
}
|
}
|
|
|
/*
|
/*
|
* FNameGet --- Find a file name <file> or "file" in the Operand string
|
* FNameGet --- Find a file name <file> or "file" in the Operand string
|
added ver TER_2.0 6/17/89
|
added ver TER_2.0 6/17/89
|
note: this routine will return a file name with white
|
note: this routine will return a file name with white
|
space if between delimeters. This is permitted in
|
space if between delimeters. This is permitted in
|
AmigaDOS. Other DOS may hiccup or just use name up to white space
|
AmigaDOS. Other DOS may hiccup or just use name up to white space
|
*/
|
*/
|
|
|
int
|
int
|
FNameGet(NameString)
|
FNameGet(NameString)
|
char *NameString; /* pointer to output string */
|
char *NameString; /* pointer to output string */
|
{
|
{
|
char *frompoint; /* pointers to input string, don't bash Operand */
|
char *frompoint; /* pointers to input string, don't bash Operand */
|
char *topoint; /* pointer to output string, don't bash NameString */
|
char *topoint; /* pointer to output string, don't bash NameString */
|
|
|
frompoint=Operand; /* include file name is in parsed string Operand */
|
frompoint=Operand; /* include file name is in parsed string Operand */
|
topoint=NameString; /* copy of pointer to increment in copying */
|
topoint=NameString; /* copy of pointer to increment in copying */
|
if (*frompoint != '<' && *frompoint != '"') return(0); /* bad syntax */
|
if (*frompoint != '<' && *frompoint != '"') return(0); /* bad syntax */
|
frompoint++; /* skip < or " */
|
frompoint++; /* skip < or " */
|
|
|
while (*frompoint != '>' && *frompoint != '"') /* look for delimeter */
|
while (*frompoint != '>' && *frompoint != '"') /* look for delimeter */
|
{
|
{
|
if (*frompoint == EOS) return(0); /* missing delimeter */
|
if (*frompoint == EOS) return(0); /* missing delimeter */
|
*topoint++ = *frompoint++; /* copy path & file name for DOS */
|
*topoint++ = *frompoint++; /* copy path & file name for DOS */
|
}
|
}
|
|
|
*topoint=EOS; /* terminate file name */
|
*topoint=EOS; /* terminate file name */
|
#ifdef DEBUG2
|
#ifdef DEBUG2
|
printf("FNameGet: file name=%s\n",NameString);
|
printf("FNameGet: file name=%s\n",NameString);
|
#endif
|
#endif
|
return(1); /* proper syntax anyway */
|
return(1); /* proper syntax anyway */
|
}
|
}
|
|
|
/*
|
/*
|
* --- strsave() find a place to save a string & return pointer to it
|
* --- strsave() find a place to save a string & return pointer to it
|
added ver TER_2.0 6/18/89 function taken from
|
added ver TER_2.0 6/18/89 function taken from
|
Kernighan & Ritchie 78
|
Kernighan & Ritchie 78
|
*/
|
*/
|
char *strsave(s)
|
char *strsave(s)
|
char *s;
|
char *s;
|
{
|
{
|
char *p;
|
char *p;
|
|
|
if ((p = alloc(strlen(s)+1)) != NULL)
|
if ((p = alloc(strlen(s)+1)) != NULL)
|
strcpy(p,s);
|
strcpy(p,s);
|
return(p);
|
return(p);
|
}
|
}
|
|
|
/*
|
/*
|
* pouterror() ---- print out standard error header
|
* pouterror() ---- print out standard error header
|
added rel TER_2.0 6/18/89
|
added rel TER_2.0 6/18/89
|
*/
|
*/
|
|
|
void pouterror()
|
void pouterror()
|
{
|
{
|
printf("%s, line no. ",Argv[Cfn]); /* current file name */
|
printf("%s, line no. ",Argv[Cfn]); /* current file name */
|
printf("%d: ",Line_num); /* current line number */
|
printf("%d: ",Line_num); /* current line number */
|
/* NOTE: THERE IS NO \n ! Calling procedure supplies suffixing
|
/* NOTE: THERE IS NO \n ! Calling procedure supplies suffixing
|
error message and \n. viz. file pseudo.c procedure do_pseudo
|
error message and \n. viz. file pseudo.c procedure do_pseudo
|
in case INCLUDE. Note also that error count is incremented. */
|
in case INCLUDE. Note also that error count is incremented. */
|
Err_count++;
|
Err_count++;
|
Page_lines++; /* increment lines per page */
|
Page_lines++; /* increment lines per page */
|
}
|
}
|
|
|
/*
|
/*
|
* New Page() --- form feed a new page, print heading & inc page number
|
* New Page() --- form feed a new page, print heading & inc page number
|
Moved here from do_pseudo (pseudo.c) in ver (TER) 2.02
|
Moved here from do_pseudo (pseudo.c) in ver (TER) 2.02
|
19 Jun 89 so that can call from print_line() as well
|
19 Jun 89 so that can call from print_line() as well
|
for p50 option.
|
for p50 option.
|
*/
|
*/
|
|
|
void NewPage()
|
void NewPage()
|
{
|
{
|
Page_lines = 0; /* ver TER_2.08 so that OPT PAGE works */
|
Page_lines = 0; /* ver TER_2.08 so that OPT PAGE works */
|
printf ("\n\f\n");
|
printf ("\n\f\n");
|
printf ("%-10s",Argv[Cfn]);
|
printf ("%-10s",Argv[Cfn]);
|
printf (" ");
|
printf (" ");
|
printf (" ");
|
printf (" ");
|
printf ("page %3d\n",Page_num++);
|
printf ("page %3d\n",Page_num++);
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* LastChar() ----- return a pointer to the last character in a string
|
* LastChar() ----- return a pointer to the last character in a string
|
Exception: will return garbage if NULL string
|
Exception: will return garbage if NULL string
|
*/
|
*/
|
|
|
char *LastChar(strpt)
|
char *LastChar(strpt)
|
char *strpt; /* pointer to string to be examined */
|
char *strpt; /* pointer to string to be examined */
|
{
|
{
|
char *c;
|
char *c;
|
|
|
c=strpt; /* don't zap original */
|
c=strpt; /* don't zap original */
|
while (*c != EOS) /* search for end */
|
while (*c != EOS) /* search for end */
|
c++;
|
c++;
|
return(--c); /* back up one to last character */
|
return(--c); /* back up one to last character */
|
}
|
}
|
|
|