1 /* $NetBSD: gsp_lex.c,v 1.9 2009/04/15 08:26:35 lukem 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.9 2009/04/15 08:26:35 lukem 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
47 char *lineptr;
48
49 char idents[MAXLINE];
50 char *idptr;
51
52 extern YYSTYPE yylval;
53
54 int str_match(const char *, const char **);
55
56 const 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
64 short 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
75 void
lex_init(char * lline)76 lex_init(char *lline)
77 {
78 lineptr = lline;
79 idptr = idents;
80 }
81
82 int
yylex()83 yylex()
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
175 void
ucasify(char * p)176 ucasify(char *p)
177 {
178 int c;
179
180 for( ; (c = *p) != 0; p++ )
181 if( islower(c) )
182 *p = toupper(c);
183 }
184
185 int
str_match(const char * id,const char ** names)186 str_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