Home | History | Annotate | Line # | Download | only in gspa
      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
     76 lex_init(char *lline)
     77 {
     78 	lineptr = lline;
     79 	idptr = idents;
     80 }
     81 
     82 int
     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
    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
    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