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