1/*	$NetBSD: gsp_lex.c,v 1.8 2006/08/26 18:15:37 christos Exp $	*/
2/*
3 * Lexical analyser for GSP assembler
4 *
5 * Copyright (c) 1993 Paul Mackerras.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *      This product includes software developed by Paul Mackerras.
19 * 4. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35#ifndef lint
36__RCSID("$NetBSD: gsp_lex.c,v 1.8 2006/08/26 18:15:37 christos Exp $");
37#endif
38
39#include <stdio.h>
40#include <ctype.h>
41#include <stdlib.h>
42#include <string.h>
43
44#include "gsp_ass.h"
45#include "gsp_gram.h"
46
47char *lineptr;
48
49char idents[MAXLINE];
50char *idptr;
51
52extern YYSTYPE yylval;
53
54int str_match(const char *, const char **);
55
56const char *regnames[] = {
57	"A0",	"A1",	"A2",	"A3",	"A4",	"A5",	"A6",	"A7",
58	"A8",	"A9",	"A10",	"A11",	"A12",	"A13",	"A14",	"SP",
59	"B0",	"B1",	"B2",	"B3",	"B4",	"B5",	"B6",	"B7",
60	"B8",	"B9",	"B10",	"B11",	"B12",	"B13",	"B14",	"B15",
61	NULL
62};
63
64short regnumbers[] = {
65	GSPA_A0+0,  GSPA_A0+1,  GSPA_A0+2,  GSPA_A0+3,
66	GSPA_A0+4,  GSPA_A0+5,  GSPA_A0+6,  GSPA_A0+7,
67	GSPA_A0+8,  GSPA_A0+9,  GSPA_A0+10, GSPA_A0+11,
68	GSPA_A0+12, GSPA_A0+13, GSPA_A0+14, GSPA_SP,
69	GSPA_B0+0,  GSPA_B0+1,  GSPA_B0+2,  GSPA_B0+3,
70	GSPA_B0+4,  GSPA_B0+5,	GSPA_B0+6,  GSPA_B0+7,
71	GSPA_B0+8,  GSPA_B0+9,  GSPA_B0+10, GSPA_B0+11,
72	GSPA_B0+12, GSPA_B0+13, GSPA_B0+14, GSPA_B0+15,
73};
74
75void
76lex_init(char *lline)
77{
78	lineptr = lline;
79	idptr = idents;
80}
81
82int
83yylex()
84{
85	int c, tok, x, len;
86	char *lp, *ip;
87	char *end;
88
89	lp = lineptr;
90	c = *lp;
91	while( c == ' ' || c == '\t' )
92		c = *++lp;
93	if( isalpha(c) || c == '_' || c == '.' ){
94		/* an identifier or register name */
95		ip = lp;
96		do {
97			c = *++lp;
98		} while( isalnum(c) || c == '_' );
99		len = lp - ip;
100		if( len == 1 && *ip == '.' )
101			tok = '.';
102		else {
103			strncpy(idptr, ip, len);
104			idptr[len] = 0;
105			ucasify(idptr);
106			x = str_match(idptr, regnames);
107			if( x == -1 ){
108				strncpy(idptr, ip, len);
109				yylval.y_id = idptr;
110				idptr += len + 1;
111				tok = ID;
112			} else {
113				yylval.y_int = regnumbers[x];
114				tok = REGISTER;
115			}
116		}
117	} else if( c == '$' ){
118		/* a hex number */
119		++lp;
120		yylval.y_int = strtoul(lp, &end, 16);
121		if( end == lp )
122			perr("Bad number syntax");
123		else
124			lp = end;
125		tok = NUMBER;
126	} else if( isdigit(c) ){
127		yylval.y_int = strtoul(lp, &end, 0);
128		ip = lp;
129		lp = end;
130		c = *lp;
131		if( (c == 'f' || c == 'F' || c == 'b' || c == 'B')
132		   && !(isalnum((unsigned char)lp[1]) || lp[1] == '_') ){
133			/* reference to numeric label */
134			c = toupper(c);
135			sprintf(idptr, "%ld%c", (long)yylval.y_int, c);
136			yylval.y_id = idptr;
137			idptr += strlen(idptr) + 1;
138			++lp;
139			tok = ID;
140		} else
141			tok = NUMBER;
142	} else if( c == '\n' ){
143		tok = 0;	/* eof */
144	} else if( c == ';' ){
145		/* comment - skip to end of line */
146		while( *++lp != 0 )
147			;
148		tok = 0;
149	} else if( c == '"' ){
150		/* string */
151		yylval.y_id = idptr;
152		while( (c = *++lp) != '"' && c != '\n' && c != 0 )
153			*idptr++ = c;
154		*idptr++ = 0;
155		if( c != '"' )
156			perr("Unterminated string");
157		else
158			++lp;
159		tok = STRING;
160	} else if( c == '<' && lp[1] == '<' ){
161		lp += 2;
162		tok = LEFT_SHIFT;
163	} else if( c == '>' && lp[1] == '>' ){
164		lp += 2;
165		tok = RIGHT_SHIFT;
166	} else {
167		if( c != 0 )
168			++lp;
169		tok = c;
170	}
171	lineptr = lp;
172	return tok;
173}
174
175void
176ucasify(char *p)
177{
178	int c;
179
180	for( ; (c = *p) != 0; p++ )
181		if( islower(c) )
182			*p = toupper(c);
183}
184
185int
186str_match(const char *id, const char **names)
187{
188	const char **np;
189
190	for( np = names; *np != NULL; ++np )
191		if( strcmp(id, *np) == 0 )
192			return np - names;
193	return -1;
194}
195