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