/* aslex.c */ /* * (C) Copyright 1989-1995 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 * * 28-Oct-97 JLH bug in getst(): sign extend on ~(SPACE|ILL) * causes infinite loop */ #include #include #include #include "asm.h" /*)Module aslex.c * * The module aslex.c includes the general lexical * analysis routines for the assembler. * * aslex.c contains the following functions: * char endline() * char get() * VOID getid(id,c) * int getline() * int getmap() * char getnb() * VOID getst() * int more() * VOID unget(c) * * aslex.c contains no local/static variables */ /*)Function VOID getid(id,c) * * char * id a pointer to a string of * maximum length NCPS * int c mode flag * >=0 this is first character to * copy to the string buffer * <0 skip white space, first * character must be a LETTER * * The function getid() scans the current assembler-source text line * from the current position copying the next LETTER | DIGIT string * into the external string buffer (id). The string ends when a non * LETTER or DIGIT character is found. The maximum number of * characters copied is NCPS. If the input string is larger than * NCPS characters then the string is truncated, if the input string * is shorter than NCPS characters then the string is NULL filled. * If the mode argument (c) is >=0 then (c) is the first character * copied to the string buffer, if (c) is <0 then intervening white * space (SPACES and TABS) are skipped and the first character found * must be a LETTER else a 'q' error terminates the parse of this * assembler-source text line. * * local variables: * char * p pointer to external string buffer * int c current character value * * global variables: * char ctype[] a character array which defines the * type of character being processed. * This index is the character * being processed. * * called functions: * char get() aslex.c * char getnb() aslex.c * VOID unget() aslex.c * * side effects: * use of getnb(), get(), and unget() updates the * global pointer ip, the position in the current * assembler-source text line. */ VOID getid(id, c) register int c; char *id; { register char *p; if (c < 0) { c = getnb(); if ((ctype[c] & LETTER) == 0) qerr(); } p = id; do { if (p < &id[NCPS]) *p++ = c; } while (ctype[c=get()] & (LETTER|DIGIT)); unget(c); while (p < &id[NCPS]) *p++ = 0; } /*)Function VOID getst(id,c) * * char * id a pointer to a string of * maximum length NCPS * int c mode flag * >=0 this is first character to * copy to the string buffer * <0 skip white space, first * character must be a LETTER * * The function getnbid() scans the current assembler-source text line * from the current position copying the next character string into * the external string buffer (id). The string ends when a SPACE or * ILL character is found. The maximum number of * characters copied is NCPS. If the input string is larger than * NCPS characters then the string is truncated, if the input string * is shorter than NCPS characters then the string is NULL filled. * If the mode argument (c) is >=0 then (c) is the first character * copied to the string buffer, if (c) is <0 then intervening white * space (SPACES and TABS) are skipped and the first character found * must be a LETTER else a 'q' error terminates the parse of this * assembler-source text line. * * local variables: * char * p pointer to external string buffer * int c current character value * * global variables: * char ctype[] a character array which defines the * type of character being processed. * This index is the character * being processed. * * called functions: * char get() aslex.c * char getnb() aslex.c * VOID unget() aslex.c * * side effects: * use of getnb(), get(), and unget() updates the * global pointer ip, the position in the current * assembler-source text line. */ VOID getst(id, c) register int c; char *id; { register char *p; if (c < 0) { c = getnb(); if ((ctype[c] & LETTER) == 0) qerr(); } p = id; do { if (p < &id[NCPS]) *p++ = c; } while (ctype[c=get()] & (0xFF - (SPACE|ILL))); unget(c); while (p < &id[NCPS]) *p++ = 0; } /*)Function char getnb() * * The function getnb() scans the current assembler-source * text line returning the first character not a SPACE or TAB. * * local variables: * int c current character from * assembler-source text line * * global variables: * none * * called functions: * char get() aslex.c * * side effects: * use of get() updates the global pointer ip, the position * in the current assembler-source text line */ char getnb() { register int c; while ((c=get()) == ' ' || c == '\t') ; return (c); } /*)Function char get() * * The function get() returns the next character in the * assembler-source text line, at the end of the line a * NULL character is returned. * * local variables: * int c current character from * assembler-source text line * * global variables: * char * ip pointer into the current * assembler-source text line * * called functions: * none * * side effects: * updates ip to the next character position in the * assembler-source text line. If ip is at the end of the * line, ip is not updated. */ char get() { register int c; if ((c = *ip) != 0) ++ip; return (c); } /*)Function VOID unget(c) * * int c value of last character read from * assembler-source text line * * If (c) is not a NULL character then the global pointer ip * is updated to point to the preceeding character in the * assembler-source text line. * * NOTE: This function does not push the character (c) * back into the assembler-source text line, only * the pointer ip is changed. * * local variables: * int c last character read from * assembler-source text line * * global variables: * char * ip position into the current * assembler-source text line * * called functions: * none * * side effects: * ip decremented by 1 character position */ VOID unget(c) { if (c) if (ip != ib) --ip; } /*)Function int getmap(d) * * int d value to compare with the * assembler-source text line character * * The function getmap() converts the 'C' style characters \b, \f, * \n, \r, and \t to their equivalent ascii values and also * converts 'C' style octal constants '\123' to their equivalent * numeric values. If the first character is equivalent to (d) then * a (-1) is returned, if the end of the line is detected then * a 'q' error terminates the parse for this line, or if the first * character is not a \ then the character value is returned. * * local variables: * int c value of character from the * assembler-source text line * int n looping counter * int v current value of numeric conversion * * global variables: * none * * called functions: * char get() aslex.c * * side effects: * use of get() updates the global pointer ip the position * in the current assembler-source text line */ int getmap(d) { register int c, n, v; if ((c=get()) == '\0') qerr(); if (c == d) return (-1); if (c == '\\') { c = get(); switch (c) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': n = 0; v = 0; while (++n<=3 && c>='0' && c<='7') { v = (v<<3) + c - '0'; c = get(); } unget(c); c = v; break; } } return (c); } /*)Function int getline() * * The function getline() reads a line of assembler-source text * from an assembly source text file or an include file. * Lines of text are processed from assembler-source files until * all files have been read. If an include file is opened then * lines of text are read from the include file (or nested * include file) until the end of the include file is found. * The input text line is copied into the global string ib[] * and converted to a NULL terminated string. The function * getline() returns a (1) after succesfully reading a line * or a (0) if all files have been read. * * local variables: * int i string length * * global variables: * char ib[] string buffer containing * assembler-source text line * char ifp[] array of file handles for * include files * int incfil index for ifp[] specifies * active include file * int incline[] array of include file * line numbers * char sfp[] array of file handles for * assembler source files * int cfile index for sfp[] specifies * active source file * int srcline[] array of source file * line numbers * int inpfil maximum input file index * * called functions: * int fclose() c-library * char * fgets() c-library * int strlen() c-library * * side effects: * include file will be closed at detection of end of file. * the next sequential source file may be selected. * the global file indexes incfil or cfile may be changed. * The respective source line or include line counter * will be updated. */ int getline() { loop: if (incfil >= 0) { if (fgets(ib, sizeof ib, ifp[incfil]) == NULL) { fclose(ifp[incfil--]); lop = NLPP; goto loop; } else { ++incline[incfil]; } } else { if (fgets(ib, sizeof ib, sfp[cfile]) == NULL) { if (++cfile <= inpfil) { srcline[cfile] = 0; goto loop; } return (0); } else { ++srcline[cfile]; } } chop_crlf(ib); return (1); } /*)Function int more() * * The function more() scans the assembler-source text line * skipping white space (SPACES and TABS) and returns a (0) * if the end of the line or a comment delimeter (;) is found, * or a (1) if their are additional characters in the line. * * local variables: * int c next character from the * assembler-source text line * * global variables: * none * * called functions: * char getnb() aslex.c * VOID unget() aslex.c * * side effects: * use of getnb() and unget() updates the global pointer ip * the position in the current assembler-source text line */ int more() { register int c; c = getnb(); unget(c); return( (c == '\0' || c == ';') ? 0 : 1 ); } /*)Function char endline() * * The function endline() scans the assembler-source text line * skipping white space (SPACES and TABS) and returns the next * character or a (0) if the end of the line is found or a * comment delimiter (;) is found. * * local variables: * int c next character from the * assembler-source text line * * global variables: * none * * called functions: * char getnb() aslex.c * * side effects: * use of getnb() updates the global pointer ip the * position in the current assembler-source text line */ char endline() { register int c; c = getnb(); return( (c == '\0' || c == ';') ? 0 : c ); } /*)Function VOID chop_crlf(str) * * char *str string to chop * * The function chop_crlf() removes trailing LF or CR/LF from * str, if present. * * local variables: * int i string length * * global variables: * none * * functions called: * none * * side effects: * none */ VOID chop_crlf(str) char *str; { register int i; i = strlen(str); if (i >= 1 && str[i-1] == '\n') str[i-1] = 0; if (i >= 2 && str[i-2] == '\r') str[i-2] = 0; }