1 /* ----------------------------------------------------------------------
3 * PACKAGE: as31 - 8031/8051 Assembler.
6 * This file contains the lexical tokenizer for the assembler.
7 * Since yacc is being used the lexer is called yylex().
9 * In order to produce a listing, some record of the users
10 * source line must be kept. This is done by adding
11 * get_ch(), and unget_ch() routine which returns/ungets a character
12 * but also places information into a secret array.
14 * When a newline is encountered the text line is returned as
15 * an attribute on the '\n' character.
18 * Jan. 19, 1990 - Created. (Ken Stauffer)
21 * All code in this file written by Ken Stauffer (University of Calgary).
36 char last_token[256], prev_token[256];
38 static char line[100];
39 static char *lineptr=line;
41 /* ----------------------------------------------------------------------
43 * Get a character from stdin, place char in line[]
51 if (last_token_len >=0 && last_token_len < 254 &&
52 c != EOF && (last_token_len > 0 || !isspace(c))) {
53 last_token[last_token_len++] = c;
55 if( c != EOF && lineptr - line < sizeof(line) )
60 /* ----------------------------------------------------------------------
62 * Unget a character and move lineptr back by one.
74 /* when there is a parse error, yyparse should call here to */
75 /* advance to the end of the current line, so we can continue */
76 /* parsing the rest of the file */
85 } while (c != '\n' && c != EOF);
93 /* return a pointer to the last successfully parsed token, so */
94 /* we can give a nicer error message when there is a syntax error */
96 const char *get_last_token(void)
99 if (last_token_len < 0) last_token_len = 0;
100 last_token[last_token_len] = '\0';
107 /* ----------------------------------------------------------------------
109 * The tokens themselves are returned via return(token)
111 * Some tokens have attributes. These attributes are returned
112 * by setting a global variable yylval:
116 * strings (in pass 1).
117 * bit positions .0, .1, .2, ...
120 * strings (in pass 2).
121 * '\n' (both passes).
124 * User defined symbols.
127 * Reserved keyword (opcode/directive/misc.)
129 * No other fields in yylval are used by yylex().
131 * Characters that do not have an attribute do
132 * not set anything in the yylval variable.
140 static int nl_flag=0; /* sync. error messages and the cur. line */
142 char buf[1024]; /* temporary buffer */
143 char *p; /* general pointer */
147 int octal=0,hex=0,decimal=0,binary=0;
148 register long value = 0;
150 if (last_token_len > 0) {
151 last_token[last_token_len] = '\0';
152 strcpy(prev_token, last_token);
166 case EOF: return(EOF);
180 while((c=get_ch()) != EOF && c!='\n');
189 while((c=get_ch()) != EOF && c!='"' && c!='\n') {
192 case 'n': c = '\n'; break;
193 case 'r': c = '\r'; break;
194 case 't': c = '\t'; break;
195 case 'b': c = '\b'; break;
196 case '"': c = '"'; break;
197 case '\\': c = '\\'; break;
199 warn("Invalid escape character: \\%c",c);
202 if( p-buf<sizeof(buf)-1 ) {
205 error("String constant longer than %d bytes",
210 if( c == '\n' || c == EOF ) {
211 warn("String terminated improperly");
216 yylval.value = strlen(buf);
218 p = (char *)malloc(strlen(buf) + 1);
220 error("Cannot allocate %d bytes",
222 yylval.str = "as31 ran out of memory!";
231 if( (c=get_ch())>='0' && c<='7' ) {
232 yylval.value = c-'0';
242 case 'n': c = '\n'; break;
243 case 'r': c = '\r'; break;
244 case 't': c = '\t'; break;
245 case 'b': c = '\b'; break;
246 case '0': c = 0; break;
247 case 'o': c = 0; break;
248 case 'O': c = 0; break;
249 case '\\': c = '\\'; break;
250 case '\'': c = '\''; break;
252 warn("Invalid escape character: \\%c",c);
255 if( get_ch() != '\'' )
256 warn("Missing quote in character constant");
260 case '0': /* parse a number */
261 case '1': /* could be followed by a: */
262 case '2': /* 'b','B' - Binary */
263 case '3': /* 'h','H' - Hex */
264 case '4': /* 'd','D' - Decimal */
265 case '5': /* 'o','O' - Octal */
266 case '6': /* *** Numbers must start with a digit */
267 case '7': /* Numbers could be also preceeded by: */
268 case '8': /* 0x - Hex */
269 case '9': /* 0b - binary */
273 if( p-buf<sizeof(buf)-1 )
276 } while( c=='H' || c=='h' || c=='O' || c=='o' ||
277 c=='x' || c=='X' || isxdigit(c) );
281 /* Check any preceeding chars */
282 if( buf[0]=='0' && (buf[1]=='x' || buf[1]=='X') ) {
287 (buf[1]=='b' || buf[1]=='B') &&
288 *(p-1) != 'h' && *(p-1) != 'H') {
294 /* check any trailing chars */
296 if( !hex && (c=='b' || c=='B') )
297 { binary++; *(p-1) = '\0'; }
298 else if( c=='H' || c=='h' )
299 { hex++; *(p-1) = '\0'; }
300 else if( !hex && (c=='D' || c=='d') )
301 { decimal++; *(p-1) = '\0'; }
302 else if( c=='O' || c=='o' )
303 { octal++; *(p-1) = '\0'; }
304 else if( !hex && !octal && !binary) decimal++;
307 if (hex) warn("ambiguous number, bin or hex");
308 if (decimal) warn("ambiguous number, bin or dec");
309 if (octal) warn("ambiguous number, bin or oct");
310 for(p=buf; *p; p++ ) {
311 if( *p=='1' ) value = value * 2 + 1;
312 else if( *p=='0' ) value = value * 2;
314 warn("Invalid binary digit: %c",*p);
316 yylval.value = value;
321 if (binary) warn("ambiguous number, hex or bin");
322 if (decimal) warn("ambiguous number, hex or dec");
323 if (octal) warn("ambiguous number, hex or oct");
324 for(p=buf; *p; p++ ) {
328 else if( *p>='a' && *p<='f' )
330 else if( *p>='A' && *p<='F' )
333 warn("Invalid hex digit: %c",*p);
335 yylval.value = value;
340 if (hex) warn("ambiguous number, dec or hex");
341 if (binary) warn("ambiguous number, dec or bin");
342 if (octal) warn("ambiguous number, dec or oct");
343 for(p=buf; *p; p++ ) {
345 value = value*10 + *p-'0';
347 warn("Invalid decimal digit: %c",*p);
349 yylval.value = value;
354 if (hex) warn("ambiguous number, oct or hex");
355 if (binary) warn("ambiguous number, oct or bin");
356 if (decimal) warn("ambiguous number, oct or dec");
357 for(p=buf; *p; p++ ) {
358 if( *p>='0' && *p<='7' )
359 value = (value << 3) + (*p - '0');
361 warn("Invalid octal digit: %c",*p);
363 yylval.value = value;
368 if( isalpha(c) || c=='_' ) {
371 if( p-buf<sizeof(buf)-1 )
374 } while( isalnum(c) || c=='_' );
377 if ( (op = lookop(buf)) != NULL ) {