Пример #1
0
/* Find the specific macro in the table. Expand it if it is not expanded.
 *
 */
CMacro * CMaExpander::GetMacro(sym_t mid)
{
	CMacro *ma = tc->maMap.Lookup(mid);
	if( IS_MACRO(ma) && ma->id == SSID_INVALID ) {
		handle_define(tc, mid, ma);
		free(ma->line);
		ma->line = NULL;
		return tc->maMap.Lookup(mid);
	}
	return ma;
}
Пример #2
0
static int
yylex1(void)
{
    register char *yyp;
    register int c;
    register int c1, c2;
    
    for (;;)
    {
	if (lex_fatal)
	{
	    return -1;
	}
	switch(c = mygetc())
	{
	case EOF:
	    if (inctop)
	    {
		struct incstate *p;
		p = inctop;
		(void)fclose(yyin);
		/*(void)fprintf(stderr, "popping to %s\n", p->file);*/
		free(current_file);
		nexpands = 0;
		current_file = p->file;
		current_line = p->line + 1;
		current_incfile = p->incfnum;
		pragma_strict_types = p->pragma_strict_types;
		yyin = p->yyin;
		slast = p->slast;
		lastchar = p->lastchar;
		inctop = p->next;
		
		if (p->nbuf)
		{
		    nbuf = p->nbuf;
		    outp = defbuf + DEFMAX - nbuf;
		    memcpy(outp, p->outp, nbuf);
		    free((char *)p->outp);
		}
		else
		{
		    nbuf = 0;
		    outp = defbuf + DEFMAX;
		}
		
		store_line_number_info(current_incfile, current_line);
		incdepth--;
		
		free((char *)p);
		break;
	    }
	    if (iftop)
	    {
		struct ifstate *p = iftop;
		lexerror(p->state == EXPECT_ENDIF ? "Missing #endif" : "Missing #else");
		while (iftop)
		{
		    p = iftop;
		    iftop = p->next;
		    free((char *)p);
		}
	    }
	    return -1;
	case '\n':
	{
	    nexpands=0;
	    store_line_number_info(current_incfile, current_line);
	    current_line++;
	    total_lines++;
	}
        /* FALLTHROUGH */
	case ' ':
	case '\t':
	case '\f':
	case '\v':
	    break;
	case '+':
	    TRY('+', F_INC);
	    TRY('=', F_ADD_EQ);
	    return c;
	case '-':
	    TRY('>', F_ARROW);
	    TRY('-', F_DEC);
	    TRY('=', F_SUB_EQ);
	    return c;
	case '&':
	    TRY('&', F_LAND);
	    TRY('=', F_AND_EQ);
	    return c;
	case '|':
	    TRY('|', F_LOR);
	    TRY('=', F_OR_EQ);
	    return c;
	case '^':
	    TRY('=', F_XOR_EQ);
	    return c;
	case '<':
	    if (gobble('<')) {
		TRY('=', F_LSH_EQ);
		return F_LSH;
	    }
	    TRY('=', F_LE);
	    return c;
	case '>':
	    if (gobble('>'))
	    {
		TRY('=', F_RSH_EQ);
		return F_RSH;
	    }
	    TRY('=', F_GE);
	    return c;
	case '*':
	    TRY('=', F_MULT_EQ);
	    return c;
	case '%':
	    TRY('=', F_MOD_EQ);
	    return F_MOD;
	case '/':
	    if (gobble('*'))
	    {
		skip_comment();
		break;
	    }
	    else if (gobble('/'))
	    {
		skip_comment2();
		break;
	    }
	    TRY('=', F_DIV_EQ);
	    return c;
	case '=':
	    TRY('=', F_EQ);
	    return c;
	case ';':
	case '(':
	case ')':
	case ',':
	case '{':
	case '}':
	case '~':
	case '[':
	case ']':
	case '?':
	case '@':
	    return c;
	case '!':
	    TRY('=', F_NE);
	    return F_NOT;
	case ':':
	    TRY(':', F_COLON_COLON);
	    return ':';
	case '.':
	    if (gobble('.'))
	    {
		if (gobble('.'))
		    return F_VARARG;
		else
		    return F_RANGE;
	    }
	    return c;
	case '#':
	    if (lastchar == '\n') 
	    {
		char *ssp = 0;
		int quote;
		
		yyp = yytext;
		do 
		{
		    c = mygetc();
		} while (isspace(c));
		
		for (quote = 0;;) 
		{
		    if (c == '"')
			quote ^= 1;
		    
		    /*gc - handle comments cpp-like! 1.6.91 @@@*/
		    while (!quote && c == '/')  
		    {
			if (gobble('*')) 
			{ 
			    skip_comment();
			    c = mygetc();
			}
			else 
			    break;
		    }
		    
		    if (!ssp && isspace(c))
			ssp = yyp;
		    if (c == '\n' || c == EOF)
			break;
		    SAVEC;
		    c = mygetc();
		}
		if (ssp) 
		{
		    *ssp++ = 0;
		    while (isspace(*ssp))
			ssp++;
		} 
		else 
		{
		    ssp = yyp;
		}
		*yyp = 0;
		if (strcmp("define", yytext) == 0) 
		{
		    handle_define(ssp);
		} 
		else if (strcmp("if", yytext) == 0) 
		{
#if 0
		    short int nega=0; /*@@@ allow #if !VAR gc 1.6.91*/
		    if (*ssp=='!'){ ssp++; nega=1;}
		    if (isdigit(*ssp))
		    {
			char *p;
			long l;
			l = strtol(ssp, &p, 10);
			while (isspace(*p))
			    p++;
			if (*p)
			    lexerror("Condition too complex in #if");
			else
			    handle_cond(nega ? !(int)l : (int)l);
		    }
		    else if (isalunum(*ssp))
		    {
			char *p = ssp;
			while (isalunum(*p))
			    p++;
			if (*p)
			{
			    *p++ = 0;
			    while (isspace(*p))
				p++;
			}
			if (*p)
			    lexerror("Condition too complex in #if");
			else
			{
			    struct defn *d;
			    d = lookup_define(ssp);
			    if (d)
			    {
				handle_cond(nega ? !atoi(d->exps) : atoi(d->exps));/* a hack! */
			    }
			    else
			    {
				handle_cond(nega?1:0); /* cpp-like gc*/
			    }
			}
		    }
		    else
			lexerror("Condition too complex in #if");
#else
		    int cond;
            
		    myungetc(0);
		    add_input(ssp);
		    cond = cond_get_exp(0);
		    if (mygetc()) 
		    {
			lexerror("Condition too complex in #if");
			while (mygetc())
			    ;
		    }
		    else
			handle_cond(cond);
#endif
		}
		else if (strcmp("ifdef", yytext) == 0) 
		{
		    deltrail(ssp);
		    handle_cond(lookup_define(ssp) != 0);
		}
		else if (strcmp("ifndef", yytext) == 0)
		{
		    deltrail(ssp);
		    handle_cond(lookup_define(ssp) == 0);
		} 
		else if (strcmp("else", yytext) == 0) 
		{
		    if (iftop && iftop->state == EXPECT_ELSE) 
		    {
			struct ifstate *p = iftop;
			
			/*(void)fprintf(stderr, "found else\n");*/
			iftop = p->next;
			free((char *)p);
			(void)skip_to("endif", (char *)0);
			store_line_number_info(current_incfile, current_line);
			current_line++;
			total_lines++;
		    }
		    else
		    {
			lexerror("Unexpected #else");
		    }
		} 
		else if (strcmp("endif", yytext) == 0) 
		{
		    if (iftop && (iftop->state == EXPECT_ENDIF ||
				  iftop->state == EXPECT_ELSE)) 
		    {
			struct ifstate *p = iftop;
			
			/*(void)fprintf(stderr, "found endif\n");*/
			iftop = p->next;
			free((char *)p);
		    } 
		    else 
		    {
			lexerror("Unexpected #endif");
		    }
		} 
		else if (strcmp("undef", yytext) == 0) 
		{
		    struct defn *d;
		    
		    deltrail(ssp);
		    if ((d = lookup_define(ssp)) != NULL )
			d->undef++;
		} 
		else if (strcmp("echo", yytext) == 0) 
		{
		    (void)fprintf(stderr, "%s\n", ssp);
		} 
		else if (strcmp("include", yytext) == 0) 
		{
		    /*(void)fprintf(stderr, "including %s\n", ssp);     */
		    handle_include(ssp, 0);
		}
		else if (strcmp("pragma", yytext) == 0)
		{
		    deltrail(ssp);
		    handle_pragma(ssp);
		} 
		else if (strcmp("error", yytext) == 0)
		{
		    handle_exception(ERROR, ssp);
		}
		else if (strcmp("warning", yytext) == 0)
		{
		    handle_exception(WARNING, ssp);
		}
		else 
		{
		    lexerror("Unrecognised # directive");
		}
		myungetc('\n');
		break;
	    }
	    else
		goto badlex;
	case '\'':
	    yylval.number = mygetc();
	    if (yylval.number == '\\')
	    {
		int tmp = mygetc();
		switch (tmp)
		{
		case 'n': yylval.number = '\n'; break;
		case 't': yylval.number = '\t'; break;
		case 'b': yylval.number = '\b'; break;
		case 'a': yylval.number = '\a'; break;
		case 'v': yylval.number = '\v'; break;
		case '\'':
		case '\\':
		case '"':
		    yylval.number = tmp; break;
		default:
		    lexwarning("Bad character escape sequence");
		    yylval.number = tmp;
		    break;
		}
	    }
	    if (!gobble('\''))
		lexerror("Illegal character constant");
	    return F_NUMBER;
	case '"':
	    yyp = yytext;
	    *yyp++ = c;
	    for (;;)
	    {
		c = mygetc();
		if (c == EOF)
		{
		    lexerror("End of file in string");
		    return string("\"\"");
		}
		else if (c == '\n')
		{
		    lexerror("Newline in string");
		    return string("\"\"");
		}
		SAVEC;
		if (c == '"')
		    break;
		if (c == '\\')
		{
		    c = mygetc();
		    if ( c == '\n' )
		    {
			yyp--;
			store_line_number_info(current_incfile, current_line);
			current_line++;
			total_lines++;
		    } 
		    else if ( c == EOF ) 
		    {
			/* some operating systems give EOF only once */
			myungetc(c); 
		    } 
		    else
			*yyp++ = c;
		}
	    }
	    *yyp = 0;
	    return string(yytext);

	case '0':
	    c = mygetc();
	    if ( c == 'X' || c == 'x' || c == 'o') 
	    {
                char *endptr;
                long long value;
                int base = 16;
                if (c == 'o')
                    base = 8;

                
		yyp = yytext;

		for (;;) 
		{
		    c = mygetc();
		    if (!isxdigit(c))
			break;
                    SAVEC;
		}
		myungetc(c);
                *yyp = '\0';
                
                value = strtoll(yytext, &endptr, base);
                if (*endptr != '\0')
                {
                    fprintf(stderr, "%s\n", yytext);
                    lexwarning("Invalid digits in octal number number");
                }
                
                return number(value);
	    }
	    myungetc(c);
	    c = '0';
	    /* FALLTHROUGH */
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	    yyp = yytext;
	    *yyp++ = c;
	    for (;;)
	    {
		c = mygetc();
		if (!isdigit(c))
		    break;
		SAVEC;
	    }
	    if (c == '.')
	    {
		if (isdigit(c1 = mygetc()))
		{
		    SAVEC;
		    c = c1;
		    SAVEC;
		    for (c = mygetc(); isdigit(c); c = mygetc())
			SAVEC;
		    if (c == 'e' || c == 'E')
		    {
			c1 = mygetc();
			if (c1 == '-' || c1 == '+')
			{
			    c2 = mygetc();
			    if (isdigit(c2))
			    {
				SAVEC;
				c = c1;
				SAVEC;
				c = c2;
				SAVEC;
				for (c = mygetc(); isdigit(c); c = mygetc())
				    SAVEC;
			    }
			    else
			    {
				myungetc(c2);
				myungetc(c1);
			    }
			}
			else if (isdigit(c1))
			{
			    SAVEC;
			    c = c1;
			    SAVEC;
			    for (c = mygetc(); isdigit(c); c = mygetc())
				SAVEC;
			}
			else
			    myungetc(c1);
		    }
		    myungetc(c);
		    *yyp = 0;
		    return real(strtod(yytext, NULL));
		}
		myungetc(c1);
	    }
	    myungetc(c);
	    *yyp = 0;
	    if (*yytext == '0')
            {
                /* OCTALS */
                char *endptr;
                long long value;

                value = strtoll(yytext, &endptr, 010);

                if (*endptr != '\0')
                    lexwarning("Invalid digits in octal number");

                if (value != 0)
                    lexwarning("Obsolete octal format used. Use 0o111 syntax");
                
		return number(value);
            }
	    return number(atoll(yytext));
	default:
	    if (isalpha(c) || c == '_') {
		int r;
		
		yyp = yytext;
		*yyp++ = c;
		for (;;)
		{
		    c = mygetc();
		    if (!isalunum(c))
			break;
		    SAVEC;
		}
		*yyp = 0;
		
		myungetc(c);
		if (!expand_define())
		{
		    r = lookup_resword(yytext);
		    if (r >= 0)
		    {
			return r;
		    }
		    else
			return ident(yytext);
		}
		break;
	    }
	    goto badlex;
	}
    }
  badlex:
    {
	lexerror("Illegal character (hex %02x) '%c'", c, c);
        return ' '; 
    }
}
Пример #3
0
void preprocess_file(preprocessor_state* preproc)
{
	lexer_state save_lexer, *lexer = &preproc->lexer;
	long fpos;
	int c;

	token_lex tlex[10];

	FILE* input = preproc->input;
	FILE* output = preproc->output;

	// if not -P
	fprintf(output, "# 0 \"%s\"\n", lexer->cur_file);

	tlex[0] = read_token(input, lexer, output);
	for ( ; tlex[0].tok.type != END; tlex[0] = read_token(input, lexer, output)) {

		if (tlex[0].tok.type == ID) {
			int is_macro = look_up_macro_loc(preproc, tlex[0].tok.v.id);
			if (is_macro >= 0) {
				macro_params* p = GET_PARAM(&preproc->params, is_macro);
				//for a function style macro if the name isn't followed by a ( it's not an error
				//it's just not an invocation so just print it out
				if (p->num_params >= 0) {
					save_lexer = *lexer;
					if ((fpos = ftell(input)) == -1) {
						perror("ftell failure in preprocess_file");
						exit(0);
					}
					tlex[1] = read_token(input, lexer, NULL);
					if (tlex[1].tok.type != LPAREN) {
						*lexer = save_lexer;
						if (fseek(input, fpos, SEEK_SET)) {
							perror("fseek failure in preprocess_file");
							exit(0);
						}

						if (tlex[1].tok.type == ID || tlex[1].tok.type == STR_LITERAL)
							free(tlex[1].tok.v.id);

						print_token(&tlex[0].tok, output, 0);
						free(tlex[0].tok.v.id);
						continue;
					}
					//restore ( for symmetry in handle_macro
					*lexer = save_lexer;
					if (fseek(input, fpos, SEEK_SET)) {
						perror("fseek failure in preprocess_file");
						exit(0);
					}
				}

				handle_macro(preproc, is_macro);
			} else {
				print_token(&tlex[0].tok, output, 0);
			}
			free(tlex[0].tok.v.id);

		} else if (tlex[0].tok.type == POUND) {
			//has to be the first token
			if (lexer->cur_tok != 1) {
				preprocessor_error(NULL, lexer, "Error: stray # in program\n");
			}

			save_lexer = *lexer;
			if ((fpos = ftell(input)) == -1) {
				perror("ftell failure in preprocess_file");
				exit(0);
			}
			tlex[1] = read_token(input, lexer, NULL);
			if (tlex[0].line != tlex[1].line) { //null directive (EOF is always on it's own line)
				if (tlex[1].tok.type == POUND) {
					tlex[0] = tlex[1];
					continue;
				} else if (tlex[1].tok.type == ID || tlex[1].tok.type == STR_LITERAL) {
					free(tlex[1].tok.v.id);
				}
				*lexer = save_lexer;
				if (fseek(input, fpos, SEEK_SET)) {
					perror("fseek failure in preprocess_file");
					exit(0);
				}
				continue;
			}

			
			if (tlex[1].tok.type != ID) {
				preprocessor_error(&tlex[1], lexer, "expected ID as macro name,");
			}
			
			if (!strcmp(tlex[1].tok.v.id, "define")) {
				free(tlex[1].tok.v.id);

				handle_define(preproc);
				goto eat_newline;
			}

			if (!strcmp(tlex[1].tok.v.id, "undef")) {
				free(tlex[1].tok.v.id);
				save_lexer = *lexer;
				fpos = ftell(input);
				tlex[1] = read_token(input, lexer, NULL);
				if (tlex[1].line != tlex[0].line) {
					preprocessor_error(NULL, lexer, "macro name missing in undef directive\n");
				}

				if (tlex[1].tok.type != ID) {
					preprocessor_error(&tlex[1], lexer, "ID expected in undef directive,");
				}
			
				int exists = look_up_macro_loc(preproc, tlex[0].tok.v.id);
				if (exists >= 0) {
					cvec_erase_str(&preproc->macros, exists, exists);
					cvec_erase_str(&preproc->values, exists, exists);
					cvec_erase_void(&preproc->params, exists, exists);
				}
				free(tlex[1].tok.v.id);

				goto eat_newline;
			}

			if (!strcmp(tlex[1].tok.v.id, "include")) {
				free(tlex[1].tok.v.id);
				handle_include(preproc);
				goto eat_newline;
			}
			if (!strcmp(tlex[1].tok.v.id, "if")) {
				free(tlex[1].tok.v.id);
			}

			if (!strcmp(tlex[1].tok.v.id, "ifdef")) {
				free(tlex[1].tok.v.id);
				handle_ifdef(preproc);
				goto eat_newline;
			}

			if (!strcmp(tlex[1].tok.v.id, "ifndef")) {
				free(tlex[1].tok.v.id);
			}

			if (!strcmp(tlex[1].tok.v.id, "else")) {
			}
			if (!strcmp(tlex[1].tok.v.id, "endif")) {
			}
			if (!strcmp(tlex[1].tok.v.id, "elif")) {
			}

			if (!strcmp(tlex[1].tok.v.id, "defined")) {
			}
			if (!strcmp(tlex[1].tok.v.id, "pragma")) {
			}

			if (!strcmp(tlex[1].tok.v.id, "error")) {
				// check for string
				// preprocessor_error(NULL,
			}

eat_newline:
			//the newline should reset the position
			//but since the line of a directive should be
			//invisible to the final program it shouldn't affect line count
			do {
				c = getc(preproc->input);
				if (!isspace(c))
					preprocessor_error(NULL, lexer, "extra tokens in directive\n");
			} while (c != '\n');
			lexer->cur_pos = 1;
			lexer->cur_tok = 0;
		}
	}
}