1 1.1 fvdl %{ 2 1.6 jdolecek /* $NetBSD: aicasm_scan.l,v 1.6 2020/06/27 16:19:38 jdolecek Exp $ */ 3 1.1 fvdl /* 4 1.1 fvdl * Lexical Analyzer for the Aic7xxx SCSI Host adapter sequencer assembler. 5 1.1 fvdl * 6 1.3 fvdl * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. 7 1.3 fvdl * Copyright (c) 2001, 2002 Adaptec Inc. 8 1.1 fvdl * All rights reserved. 9 1.1 fvdl * 10 1.1 fvdl * Redistribution and use in source and binary forms, with or without 11 1.1 fvdl * modification, are permitted provided that the following conditions 12 1.1 fvdl * are met: 13 1.1 fvdl * 1. Redistributions of source code must retain the above copyright 14 1.1 fvdl * notice, this list of conditions, and the following disclaimer, 15 1.1 fvdl * without modification. 16 1.3 fvdl * 2. Redistributions in binary form must reproduce at minimum a disclaimer 17 1.3 fvdl * substantially similar to the "NO WARRANTY" disclaimer below 18 1.3 fvdl * ("Disclaimer") and any redistribution must be conditioned upon 19 1.3 fvdl * including a substantially similar Disclaimer requirement for further 20 1.3 fvdl * binary redistribution. 21 1.3 fvdl * 3. Neither the names of the above-listed copyright holders nor the names 22 1.3 fvdl * of any contributors may be used to endorse or promote products derived 23 1.3 fvdl * from this software without specific prior written permission. 24 1.3 fvdl * 25 1.3 fvdl * Alternatively, this software may be distributed under the terms of the 26 1.3 fvdl * GNU General Public License ("GPL") version 2 as published by the Free 27 1.3 fvdl * Software Foundation. 28 1.1 fvdl * 29 1.3 fvdl * NO WARRANTY 30 1.3 fvdl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 1.3 fvdl * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 1.3 fvdl * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 33 1.3 fvdl * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 34 1.3 fvdl * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35 1.1 fvdl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36 1.1 fvdl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37 1.3 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 38 1.3 fvdl * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 39 1.3 fvdl * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 1.3 fvdl * POSSIBILITY OF SUCH DAMAGES. 41 1.1 fvdl * 42 1.3 fvdl * $FreeBSD: src/sys/dev/aic7xxx/aicasm/aicasm_scan.l,v 1.21 2002/09/27 03:23:02 gibbs Exp $ 43 1.1 fvdl */ 44 1.1 fvdl 45 1.1 fvdl #include <sys/types.h> 46 1.1 fvdl 47 1.3 fvdl #include <inttypes.h> 48 1.1 fvdl #include <limits.h> 49 1.3 fvdl #include <regex.h> 50 1.1 fvdl #include <stdio.h> 51 1.1 fvdl #include <string.h> 52 1.1 fvdl #include <sysexits.h> 53 1.3 fvdl #ifdef __linux__ 54 1.3 fvdl #include "../queue.h" 55 1.3 fvdl #else 56 1.1 fvdl #include <sys/queue.h> 57 1.3 fvdl #endif 58 1.1 fvdl 59 1.1 fvdl #include "aicasm.h" 60 1.1 fvdl #include "aicasm_symbol.h" 61 1.1 fvdl #include "aicasm_gram.h" 62 1.1 fvdl 63 1.6 jdolecek int yyparse(void); 64 1.6 jdolecek void yy_delete_buffer(YY_BUFFER_STATE); 65 1.6 jdolecek int mmlex(void); 66 1.6 jdolecek int mmparse(void); 67 1.6 jdolecek void mm_delete_buffer(YY_BUFFER_STATE); 68 1.6 jdolecek void mm_switch_to_buffer(YY_BUFFER_STATE); 69 1.6 jdolecek 70 1.3 fvdl /* This is used for macro body capture too, so err on the large size. */ 71 1.3 fvdl #define MAX_STR_CONST 4096 72 1.3 fvdl static char string_buf[MAX_STR_CONST]; 73 1.3 fvdl static char *string_buf_ptr; 74 1.3 fvdl static int parren_count; 75 1.3 fvdl static int quote_count; 76 1.3 fvdl static char buf[255]; 77 1.1 fvdl %} 78 1.1 fvdl 79 1.3 fvdl PATH ([/]*[-A-Za-z0-9_.])+ 80 1.1 fvdl WORD [A-Za-z_][-A-Za-z_0-9]* 81 1.1 fvdl SPACE [ \t]+ 82 1.3 fvdl MCARG [^(), \t]+ 83 1.3 fvdl MBODY ((\\[^\n])*[^\n\\]*)+ 84 1.1 fvdl 85 1.1 fvdl %x COMMENT 86 1.1 fvdl %x CEXPR 87 1.1 fvdl %x INCLUDE 88 1.3 fvdl %x STRING 89 1.3 fvdl %x MACRODEF 90 1.3 fvdl %x MACROARGLIST 91 1.3 fvdl %x MACROCALLARGS 92 1.3 fvdl %x MACROBODY 93 1.1 fvdl 94 1.1 fvdl %% 95 1.1 fvdl \n { ++yylineno; } 96 1.1 fvdl "/*" { BEGIN COMMENT; /* Enter comment eating state */ } 97 1.1 fvdl <COMMENT>"/*" { fprintf(stderr, "Warning! Comment within comment."); } 98 1.1 fvdl <COMMENT>\n { ++yylineno; } 99 1.1 fvdl <COMMENT>[^*/\n]* ; 100 1.1 fvdl <COMMENT>"*"+[^*/\n]* ; 101 1.1 fvdl <COMMENT>"/"+[^*/\n]* ; 102 1.1 fvdl <COMMENT>"*"+"/" { BEGIN INITIAL; } 103 1.1 fvdl if[ \t]*\( { 104 1.1 fvdl string_buf_ptr = string_buf; 105 1.1 fvdl parren_count = 1; 106 1.1 fvdl BEGIN CEXPR; 107 1.1 fvdl return T_IF; 108 1.1 fvdl } 109 1.1 fvdl <CEXPR>\( { *string_buf_ptr++ = '('; parren_count++; } 110 1.1 fvdl <CEXPR>\) { 111 1.1 fvdl parren_count--; 112 1.1 fvdl if (parren_count == 0) { 113 1.1 fvdl /* All done */ 114 1.1 fvdl BEGIN INITIAL; 115 1.1 fvdl *string_buf_ptr = '\0'; 116 1.1 fvdl yylval.sym = symtable_get(string_buf); 117 1.1 fvdl return T_CEXPR; 118 1.1 fvdl } else { 119 1.1 fvdl *string_buf_ptr++ = ')'; 120 1.1 fvdl } 121 1.1 fvdl } 122 1.1 fvdl <CEXPR>\n { ++yylineno; } 123 1.3 fvdl <CEXPR>[^()\n]+ { 124 1.3 fvdl char *yptr; 125 1.3 fvdl 126 1.3 fvdl yptr = yytext; 127 1.3 fvdl while (*yptr != '\0') { 128 1.3 fvdl /* Remove duplicate spaces */ 129 1.3 fvdl if (*yptr == '\t') 130 1.3 fvdl *yptr = ' '; 131 1.3 fvdl if (*yptr == ' ' 132 1.3 fvdl && string_buf_ptr != string_buf 133 1.3 fvdl && string_buf_ptr[-1] == ' ') 134 1.3 fvdl yptr++; 135 1.4 perry else 136 1.3 fvdl *string_buf_ptr++ = *yptr++; 137 1.3 fvdl } 138 1.3 fvdl } 139 1.1 fvdl 140 1.3 fvdl VERSION { return T_VERSION; } 141 1.3 fvdl PREFIX { return T_PREFIX; } 142 1.3 fvdl PATCH_ARG_LIST { return T_PATCH_ARG_LIST; } 143 1.3 fvdl \" { 144 1.3 fvdl string_buf_ptr = string_buf; 145 1.3 fvdl BEGIN STRING; 146 1.3 fvdl } 147 1.3 fvdl <STRING>[^"]+ { 148 1.3 fvdl char *yptr; 149 1.3 fvdl 150 1.3 fvdl yptr = yytext; 151 1.3 fvdl while (*yptr) 152 1.1 fvdl *string_buf_ptr++ = *yptr++; 153 1.1 fvdl } 154 1.3 fvdl <STRING>\" { 155 1.3 fvdl /* All done */ 156 1.3 fvdl BEGIN INITIAL; 157 1.3 fvdl *string_buf_ptr = '\0'; 158 1.3 fvdl yylval.str = string_buf; 159 1.3 fvdl return T_STRING; 160 1.3 fvdl } 161 1.3 fvdl {SPACE} ; 162 1.1 fvdl 163 1.1 fvdl /* Register/SCB/SRAM definition keywords */ 164 1.3 fvdl export { return T_EXPORT; } 165 1.1 fvdl register { return T_REGISTER; } 166 1.1 fvdl const { yylval.value = FALSE; return T_CONST; } 167 1.1 fvdl download { return T_DOWNLOAD; } 168 1.1 fvdl address { return T_ADDRESS; } 169 1.1 fvdl access_mode { return T_ACCESS_MODE; } 170 1.3 fvdl modes { return T_MODES; } 171 1.1 fvdl RW|RO|WO { 172 1.1 fvdl if (strcmp(yytext, "RW") == 0) 173 1.1 fvdl yylval.value = RW; 174 1.1 fvdl else if (strcmp(yytext, "RO") == 0) 175 1.1 fvdl yylval.value = RO; 176 1.1 fvdl else 177 1.1 fvdl yylval.value = WO; 178 1.1 fvdl return T_MODE; 179 1.1 fvdl } 180 1.3 fvdl BEGIN_CRITICAL { return T_BEGIN_CS; } 181 1.3 fvdl END_CRITICAL { return T_END_CS; } 182 1.3 fvdl SET_SRC_MODE { return T_SET_SRC_MODE; } 183 1.3 fvdl SET_DST_MODE { return T_SET_DST_MODE; } 184 1.3 fvdl field { return T_FIELD; } 185 1.3 fvdl enum { return T_ENUM; } 186 1.1 fvdl mask { return T_MASK; } 187 1.1 fvdl alias { return T_ALIAS; } 188 1.1 fvdl size { return T_SIZE; } 189 1.1 fvdl scb { return T_SCB; } 190 1.1 fvdl scratch_ram { return T_SRAM; } 191 1.1 fvdl accumulator { return T_ACCUM; } 192 1.3 fvdl mode_pointer { return T_MODE_PTR; } 193 1.1 fvdl allones { return T_ALLONES; } 194 1.1 fvdl allzeros { return T_ALLZEROS; } 195 1.1 fvdl none { return T_NONE; } 196 1.1 fvdl sindex { return T_SINDEX; } 197 1.1 fvdl A { return T_A; } 198 1.1 fvdl 199 1.1 fvdl /* Opcodes */ 200 1.1 fvdl shl { return T_SHL; } 201 1.1 fvdl shr { return T_SHR; } 202 1.1 fvdl ror { return T_ROR; } 203 1.1 fvdl rol { return T_ROL; } 204 1.1 fvdl mvi { return T_MVI; } 205 1.1 fvdl mov { return T_MOV; } 206 1.1 fvdl clr { return T_CLR; } 207 1.1 fvdl jmp { return T_JMP; } 208 1.1 fvdl jc { return T_JC; } 209 1.1 fvdl jnc { return T_JNC; } 210 1.1 fvdl je { return T_JE; } 211 1.1 fvdl jne { return T_JNE; } 212 1.1 fvdl jz { return T_JZ; } 213 1.1 fvdl jnz { return T_JNZ; } 214 1.1 fvdl call { return T_CALL; } 215 1.1 fvdl add { return T_ADD; } 216 1.1 fvdl adc { return T_ADC; } 217 1.1 fvdl bmov { return T_BMOV; } 218 1.1 fvdl inc { return T_INC; } 219 1.1 fvdl dec { return T_DEC; } 220 1.1 fvdl stc { return T_STC; } 221 1.1 fvdl clc { return T_CLC; } 222 1.1 fvdl cmp { return T_CMP; } 223 1.3 fvdl not { return T_NOT; } 224 1.1 fvdl xor { return T_XOR; } 225 1.1 fvdl test { return T_TEST;} 226 1.1 fvdl and { return T_AND; } 227 1.1 fvdl or { return T_OR; } 228 1.1 fvdl ret { return T_RET; } 229 1.1 fvdl nop { return T_NOP; } 230 1.1 fvdl else { return T_ELSE; } 231 1.1 fvdl 232 1.1 fvdl /* Allowed Symbols */ 233 1.3 fvdl \<\< { return T_EXPR_LSHIFT; } 234 1.3 fvdl \>\> { return T_EXPR_RSHIFT; } 235 1.3 fvdl [-+,:()~|&."{};<>[\]/*!=] { return yytext[0]; } 236 1.1 fvdl 237 1.1 fvdl /* Number processing */ 238 1.1 fvdl 0[0-7]* { 239 1.1 fvdl yylval.value = strtol(yytext, NULL, 8); 240 1.1 fvdl return T_NUMBER; 241 1.1 fvdl } 242 1.1 fvdl 243 1.1 fvdl 0[xX][0-9a-fA-F]+ { 244 1.1 fvdl yylval.value = strtoul(yytext + 2, NULL, 16); 245 1.1 fvdl return T_NUMBER; 246 1.1 fvdl } 247 1.1 fvdl 248 1.1 fvdl [1-9][0-9]* { 249 1.1 fvdl yylval.value = strtol(yytext, NULL, 10); 250 1.1 fvdl return T_NUMBER; 251 1.1 fvdl } 252 1.3 fvdl /* Include Files */ 253 1.3 fvdl #include{SPACE} { 254 1.3 fvdl BEGIN INCLUDE; 255 1.3 fvdl quote_count = 0; 256 1.3 fvdl return T_INCLUDE; 257 1.3 fvdl } 258 1.3 fvdl <INCLUDE>[<] { return yytext[0]; } 259 1.3 fvdl <INCLUDE>[>] { BEGIN INITIAL; return yytext[0]; } 260 1.3 fvdl <INCLUDE>[\"] { 261 1.3 fvdl if (quote_count != 0) 262 1.3 fvdl BEGIN INITIAL; 263 1.3 fvdl quote_count++; 264 1.3 fvdl return yytext[0]; 265 1.3 fvdl } 266 1.3 fvdl <INCLUDE>{PATH} { 267 1.3 fvdl char *yptr; 268 1.1 fvdl 269 1.3 fvdl yptr = yytext; 270 1.3 fvdl string_buf_ptr = string_buf; 271 1.3 fvdl while (*yptr) 272 1.3 fvdl *string_buf_ptr++ = *yptr++; 273 1.3 fvdl yylval.str = string_buf; 274 1.3 fvdl *string_buf_ptr = '\0'; 275 1.3 fvdl return T_PATH; 276 1.3 fvdl } 277 1.1 fvdl <INCLUDE>. { stop("Invalid include line", EX_DATAERR); } 278 1.3 fvdl #define{SPACE} { 279 1.3 fvdl BEGIN MACRODEF; 280 1.3 fvdl return T_DEFINE; 281 1.3 fvdl } 282 1.4 perry <MACRODEF>{WORD}{SPACE} { 283 1.3 fvdl char *yptr; 284 1.1 fvdl 285 1.3 fvdl /* Strip space and return as a normal symbol */ 286 1.3 fvdl yptr = yytext; 287 1.3 fvdl while (*yptr != ' ' && *yptr != '\t') 288 1.3 fvdl yptr++; 289 1.3 fvdl *yptr = '\0'; 290 1.3 fvdl yylval.sym = symtable_get(yytext); 291 1.3 fvdl string_buf_ptr = string_buf; 292 1.3 fvdl BEGIN MACROBODY; 293 1.3 fvdl return T_SYMBOL; 294 1.3 fvdl } 295 1.3 fvdl <MACRODEF>{WORD}\( { 296 1.3 fvdl /* 297 1.3 fvdl * We store the symbol with its opening 298 1.3 fvdl * parren so we can differentiate macros 299 1.3 fvdl * that take args from macros with the 300 1.3 fvdl * same name that do not take args as 301 1.3 fvdl * is allowed in C. 302 1.3 fvdl */ 303 1.3 fvdl BEGIN MACROARGLIST; 304 1.3 fvdl yylval.sym = symtable_get(yytext); 305 1.3 fvdl unput('('); 306 1.3 fvdl return T_SYMBOL; 307 1.3 fvdl } 308 1.3 fvdl <MACROARGLIST>{WORD} { 309 1.3 fvdl yylval.str = yytext; 310 1.3 fvdl return T_ARG; 311 1.3 fvdl } 312 1.3 fvdl <MACROARGLIST>{SPACE} ; 313 1.3 fvdl <MACROARGLIST>[(,] { 314 1.3 fvdl return yytext[0]; 315 1.3 fvdl } 316 1.3 fvdl <MACROARGLIST>[)] { 317 1.3 fvdl string_buf_ptr = string_buf; 318 1.3 fvdl BEGIN MACROBODY; 319 1.3 fvdl return ')'; 320 1.3 fvdl } 321 1.3 fvdl <MACROARGLIST>. { 322 1.3 fvdl snprintf(buf, sizeof(buf), "Invalid character " 323 1.3 fvdl "'%c' in macro argument list", 324 1.3 fvdl yytext[0]); 325 1.3 fvdl stop(buf, EX_DATAERR); 326 1.3 fvdl } 327 1.3 fvdl <MACROCALLARGS>{SPACE} ; 328 1.3 fvdl <MACROCALLARGS>\( { 329 1.3 fvdl parren_count++; 330 1.3 fvdl if (parren_count == 1) 331 1.3 fvdl return ('('); 332 1.3 fvdl *string_buf_ptr++ = '('; 333 1.3 fvdl } 334 1.3 fvdl <MACROCALLARGS>\) { 335 1.3 fvdl parren_count--; 336 1.3 fvdl if (parren_count == 0) { 337 1.3 fvdl BEGIN INITIAL; 338 1.3 fvdl return (')'); 339 1.3 fvdl } 340 1.3 fvdl *string_buf_ptr++ = ')'; 341 1.3 fvdl } 342 1.3 fvdl <MACROCALLARGS>{MCARG} { 343 1.3 fvdl char *yptr; 344 1.1 fvdl 345 1.3 fvdl yptr = yytext; 346 1.3 fvdl while (*yptr) 347 1.3 fvdl *string_buf_ptr++ = *yptr++; 348 1.3 fvdl } 349 1.3 fvdl <MACROCALLARGS>\, { 350 1.3 fvdl if (string_buf_ptr != string_buf) { 351 1.3 fvdl /* 352 1.3 fvdl * Return an argument and 353 1.3 fvdl * rescan this comma so we 354 1.3 fvdl * can return it as well. 355 1.3 fvdl */ 356 1.3 fvdl *string_buf_ptr = '\0'; 357 1.3 fvdl yylval.str = string_buf; 358 1.3 fvdl string_buf_ptr = string_buf; 359 1.3 fvdl unput(','); 360 1.3 fvdl return T_ARG; 361 1.3 fvdl } 362 1.3 fvdl return ','; 363 1.3 fvdl } 364 1.3 fvdl <MACROBODY>\\\n { 365 1.3 fvdl /* Eat escaped newlines. */ 366 1.3 fvdl ++yylineno; 367 1.3 fvdl } 368 1.3 fvdl <MACROBODY>\n { 369 1.3 fvdl /* Macros end on the first unescaped newline. */ 370 1.3 fvdl BEGIN INITIAL; 371 1.3 fvdl *string_buf_ptr = '\0'; 372 1.3 fvdl yylval.str = string_buf; 373 1.3 fvdl ++yylineno; 374 1.3 fvdl return T_MACROBODY; 375 1.3 fvdl } 376 1.3 fvdl <MACROBODY>{MBODY} { 377 1.3 fvdl char *yptr; 378 1.1 fvdl 379 1.3 fvdl yptr = yytext; 380 1.3 fvdl while (*yptr) 381 1.3 fvdl *string_buf_ptr++ = *yptr++; 382 1.3 fvdl } 383 1.3 fvdl {WORD}\( { 384 1.3 fvdl char *yptr; 385 1.3 fvdl char *ycopy; 386 1.3 fvdl 387 1.3 fvdl /* May be a symbol or a macro invocation. */ 388 1.3 fvdl yylval.sym = symtable_get(yytext); 389 1.3 fvdl if (yylval.sym->type == MACRO) { 390 1.3 fvdl YY_BUFFER_STATE old_state; 391 1.3 fvdl YY_BUFFER_STATE temp_state; 392 1.3 fvdl 393 1.3 fvdl ycopy = strdup(yytext); 394 1.3 fvdl yptr = ycopy + yyleng; 395 1.3 fvdl while (yptr > ycopy) 396 1.3 fvdl unput(*--yptr); 397 1.3 fvdl old_state = YY_CURRENT_BUFFER; 398 1.3 fvdl temp_state = 399 1.3 fvdl yy_create_buffer(stdin, 400 1.3 fvdl YY_BUF_SIZE); 401 1.3 fvdl yy_switch_to_buffer(temp_state); 402 1.3 fvdl mm_switch_to_buffer(old_state); 403 1.3 fvdl mmparse(); 404 1.3 fvdl mm_switch_to_buffer(temp_state); 405 1.3 fvdl yy_switch_to_buffer(old_state); 406 1.3 fvdl mm_delete_buffer(temp_state); 407 1.3 fvdl expand_macro(yylval.sym); 408 1.3 fvdl } else { 409 1.3 fvdl if (yylval.sym->type == UNINITIALIZED) { 410 1.3 fvdl /* Try without the '(' */ 411 1.3 fvdl symbol_delete(yylval.sym); 412 1.3 fvdl yytext[yyleng-1] = '\0'; 413 1.3 fvdl yylval.sym = 414 1.3 fvdl symtable_get(yytext); 415 1.3 fvdl } 416 1.3 fvdl unput('('); 417 1.3 fvdl return T_SYMBOL; 418 1.3 fvdl } 419 1.3 fvdl } 420 1.3 fvdl {WORD} { 421 1.3 fvdl yylval.sym = symtable_get(yytext); 422 1.3 fvdl if (yylval.sym->type == MACRO) { 423 1.3 fvdl expand_macro(yylval.sym); 424 1.3 fvdl } else { 425 1.3 fvdl return T_SYMBOL; 426 1.3 fvdl } 427 1.3 fvdl } 428 1.4 perry . { 429 1.1 fvdl snprintf(buf, sizeof(buf), "Invalid character " 430 1.1 fvdl "'%c'", yytext[0]); 431 1.1 fvdl stop(buf, EX_DATAERR); 432 1.1 fvdl } 433 1.1 fvdl %% 434 1.1 fvdl 435 1.1 fvdl typedef struct include { 436 1.1 fvdl YY_BUFFER_STATE buffer; 437 1.1 fvdl int lineno; 438 1.1 fvdl char *filename; 439 1.1 fvdl SLIST_ENTRY(include) links; 440 1.1 fvdl }include_t; 441 1.1 fvdl 442 1.1 fvdl SLIST_HEAD(, include) include_stack; 443 1.1 fvdl 444 1.1 fvdl void 445 1.3 fvdl include_file(char *file_name, include_type type) 446 1.1 fvdl { 447 1.1 fvdl FILE *newfile; 448 1.1 fvdl include_t *include; 449 1.1 fvdl 450 1.1 fvdl newfile = NULL; 451 1.1 fvdl /* Try the current directory first */ 452 1.1 fvdl if (includes_search_curdir != 0 || type == SOURCE_FILE) 453 1.1 fvdl newfile = fopen(file_name, "r"); 454 1.1 fvdl 455 1.1 fvdl if (newfile == NULL && type != SOURCE_FILE) { 456 1.1 fvdl path_entry_t include_dir; 457 1.3 fvdl for (include_dir = search_path.slh_first; 458 1.4 perry include_dir != NULL; 459 1.3 fvdl include_dir = include_dir->links.sle_next) { 460 1.1 fvdl char fullname[PATH_MAX]; 461 1.1 fvdl 462 1.1 fvdl if ((include_dir->quoted_includes_only == TRUE) 463 1.1 fvdl && (type != QUOTED_INCLUDE)) 464 1.1 fvdl continue; 465 1.1 fvdl 466 1.1 fvdl snprintf(fullname, sizeof(fullname), 467 1.1 fvdl "%s/%s", include_dir->directory, file_name); 468 1.1 fvdl 469 1.1 fvdl if ((newfile = fopen(fullname, "r")) != NULL) 470 1.1 fvdl break; 471 1.1 fvdl } 472 1.1 fvdl } 473 1.1 fvdl 474 1.1 fvdl if (newfile == NULL) { 475 1.1 fvdl perror(file_name); 476 1.1 fvdl stop("Unable to open input file", EX_SOFTWARE); 477 1.1 fvdl /* NOTREACHED */ 478 1.1 fvdl } 479 1.1 fvdl 480 1.1 fvdl if (type != SOURCE_FILE) { 481 1.1 fvdl include = (include_t *)malloc(sizeof(include_t)); 482 1.1 fvdl if (include == NULL) { 483 1.1 fvdl stop("Unable to allocate include stack entry", 484 1.1 fvdl EX_SOFTWARE); 485 1.1 fvdl /* NOTREACHED */ 486 1.1 fvdl } 487 1.1 fvdl include->buffer = YY_CURRENT_BUFFER; 488 1.1 fvdl include->lineno = yylineno; 489 1.1 fvdl include->filename = yyfilename; 490 1.1 fvdl SLIST_INSERT_HEAD(&include_stack, include, links); 491 1.1 fvdl } 492 1.1 fvdl yy_switch_to_buffer(yy_create_buffer(newfile, YY_BUF_SIZE)); 493 1.1 fvdl yylineno = 1; 494 1.1 fvdl yyfilename = strdup(file_name); 495 1.1 fvdl } 496 1.1 fvdl 497 1.3 fvdl static void next_substitution(struct symbol *mac_symbol, const char *body_pos, 498 1.3 fvdl const char **next_match, 499 1.3 fvdl struct macro_arg **match_marg, regmatch_t *match); 500 1.3 fvdl 501 1.3 fvdl void 502 1.3 fvdl expand_macro(struct symbol *macro_symbol) 503 1.3 fvdl { 504 1.3 fvdl struct macro_arg *marg; 505 1.3 fvdl struct macro_arg *match_marg; 506 1.3 fvdl const char *body_head; 507 1.3 fvdl const char *body_pos; 508 1.3 fvdl const char *next_match; 509 1.3 fvdl 510 1.3 fvdl /* 511 1.3 fvdl * Due to the nature of unput, we must work 512 1.3 fvdl * backwards through the macro body performing 513 1.3 fvdl * any expansions. 514 1.3 fvdl */ 515 1.3 fvdl body_head = macro_symbol->info.macroinfo->body; 516 1.3 fvdl body_pos = body_head + strlen(body_head); 517 1.3 fvdl while (body_pos > body_head) { 518 1.3 fvdl regmatch_t match; 519 1.3 fvdl 520 1.3 fvdl next_match = body_head; 521 1.3 fvdl match_marg = NULL; 522 1.3 fvdl next_substitution(macro_symbol, body_pos, &next_match, 523 1.3 fvdl &match_marg, &match); 524 1.3 fvdl 525 1.3 fvdl /* Put back everything up until the replacement. */ 526 1.3 fvdl while (body_pos > next_match) 527 1.3 fvdl unput(*--body_pos); 528 1.3 fvdl 529 1.3 fvdl /* Perform the replacement. */ 530 1.3 fvdl if (match_marg != NULL) { 531 1.3 fvdl const char *strp; 532 1.3 fvdl 533 1.3 fvdl next_match = match_marg->replacement_text; 534 1.3 fvdl strp = next_match + strlen(next_match); 535 1.3 fvdl while (strp > next_match) 536 1.3 fvdl unput(*--strp); 537 1.3 fvdl 538 1.3 fvdl /* Skip past the unexpanded macro arg. */ 539 1.3 fvdl body_pos -= match.rm_eo - match.rm_so; 540 1.3 fvdl } 541 1.3 fvdl } 542 1.3 fvdl 543 1.3 fvdl /* Cleanup replacement text. */ 544 1.3 fvdl STAILQ_FOREACH(marg, ¯o_symbol->info.macroinfo->args, links) { 545 1.3 fvdl free(marg->replacement_text); 546 1.3 fvdl } 547 1.3 fvdl } 548 1.3 fvdl 549 1.3 fvdl /* 550 1.3 fvdl * Find the next substitution in the macro working backwards from 551 1.3 fvdl * body_pos until the beginning of the macro buffer. next_match 552 1.3 fvdl * should be initialized to the beginning of the macro buffer prior 553 1.3 fvdl * to calling this routine. 554 1.3 fvdl */ 555 1.3 fvdl static void 556 1.3 fvdl next_substitution(struct symbol *mac_symbol, const char *body_pos, 557 1.3 fvdl const char **next_match, struct macro_arg **match_marg, 558 1.3 fvdl regmatch_t *match) 559 1.3 fvdl { 560 1.3 fvdl regmatch_t matches[2]; 561 1.3 fvdl struct macro_arg *marg; 562 1.3 fvdl const char *search_pos; 563 1.3 fvdl int retval; 564 1.3 fvdl 565 1.3 fvdl do { 566 1.3 fvdl search_pos = *next_match; 567 1.3 fvdl 568 1.3 fvdl STAILQ_FOREACH(marg, &mac_symbol->info.macroinfo->args, links) { 569 1.3 fvdl 570 1.3 fvdl retval = regexec(&marg->arg_regex, search_pos, 2, 571 1.3 fvdl matches, 0); 572 1.3 fvdl if (retval == 0 573 1.3 fvdl && (matches[1].rm_eo + search_pos) <= body_pos 574 1.3 fvdl && (matches[1].rm_eo + search_pos) > *next_match) { 575 1.3 fvdl *match = matches[1]; 576 1.3 fvdl *next_match = match->rm_eo + search_pos; 577 1.3 fvdl *match_marg = marg; 578 1.3 fvdl } 579 1.3 fvdl } 580 1.3 fvdl } while (search_pos != *next_match); 581 1.3 fvdl } 582 1.3 fvdl 583 1.1 fvdl int 584 1.1 fvdl yywrap() 585 1.1 fvdl { 586 1.1 fvdl include_t *include; 587 1.1 fvdl 588 1.1 fvdl yy_delete_buffer(YY_CURRENT_BUFFER); 589 1.1 fvdl (void)fclose(yyin); 590 1.1 fvdl if (yyfilename != NULL) 591 1.1 fvdl free(yyfilename); 592 1.1 fvdl yyfilename = NULL; 593 1.3 fvdl include = include_stack.slh_first; 594 1.1 fvdl if (include != NULL) { 595 1.1 fvdl yy_switch_to_buffer(include->buffer); 596 1.1 fvdl yylineno = include->lineno; 597 1.1 fvdl yyfilename = include->filename; 598 1.1 fvdl SLIST_REMOVE_HEAD(&include_stack, links); 599 1.1 fvdl free(include); 600 1.1 fvdl return (0); 601 1.1 fvdl } 602 1.1 fvdl return (1); 603 1.1 fvdl } 604