Beispiel #1
0
/************************************************************************
** move_to_exp_esc:	moves zero terminated string starting at source to
**	the current position in EXP_BUFFER, with quotes placed around the
**	string and interior backslashes and dquotes are escaped with a
**	backslash.  The terminating null should not be copied.  The null
**	does not come from the property of a string, but rather is the
**	marker used to indicate there is no more actual.
************************************************************************/
void   move_to_exp_esc(int quote_char, REG ptext_t source)
{
    int		mapped_c;
    int		mapped_quote;
    int		in_quoted = FALSE;

    if( ! source ) {
	return;
    }

    *Exp_ptr++ = (char)quote_char;
    for(;;) {
	if(Exp_ptr >= ELIMIT) {
	    fatal_in_macro(10056);
	}
	switch(mapped_c = CHARMAP(*source)) {
	case LX_EOS:
	    if(*source == EOS_CHAR) {
		goto leave_move_stringize;
	    }
	    /* got BACKSLASH */
	    /* but it can't be backslash-newline combination because
				** we are reprocessing text already read in
				*/
	    if(in_quoted) {
		*Exp_ptr++ = '\\';
	    }
	    break;
	    break;
	case LX_DQUOTE:
	    if(CHARMAP(quote_char) == LX_DQUOTE) {
		*Exp_ptr++ = '\\';
	    }
	    /*
			**	FALLTHROUGH
			*/
	case LX_SQUOTE:
	    if(CHARMAP(quote_char) == LX_SQUOTE) {
		break;
	    }
	    if(in_quoted ) {
		if(mapped_c == mapped_quote) {
		    in_quoted = FALSE;
		}
	    }
	    else {
		in_quoted = TRUE;
		mapped_quote = mapped_c;
	    }
	    break;
	case LX_LEADBYTE:
	    *Exp_ptr++ = *source++;
	    break;
	}
	*Exp_ptr++ = *source++;
    }

leave_move_stringize:
    *Exp_ptr++ = (char)quote_char;
}
Beispiel #2
0
/************************************************************************
**  dump_comment : while skipping a comment, output it.
************************************************************************/
void   dump_comment()
{
    if( ! Cflag ) {
        skip_1comment();
        return;
    }
    myfwrite(L"/*", 2 * sizeof(WCHAR), 1, OUTPUTFILE);
    for(;;) {
        WCHAR c;

        switch(CHARMAP(c = GETCH())) {
        case LX_STAR:
            if(checkop(L'/')) {
                myfwrite(L"*/", 2 * sizeof(WCHAR), 1, OUTPUTFILE);
                return;
            }
            break;
        case LX_EOS:
            handle_eos();
            continue;
        case LX_NL:
            Linenumber++;
            break;      /* output below */
        // must manually write '\r' with '\n' when writing 16-bit strings
        //case LX_CR:
        //    continue;
        }
        myfwrite(&c, sizeof(WCHAR), 1, OUTPUTFILE);
    }
}
Beispiel #3
0
/************************************************************************
**      str_const : gather up a string constant
************************************************************************/
void   str_const(VOID)
{
    REG WCHAR c;
    REG PWCHAR  p_buf;
    int not_warned_yet = TRUE;

    p_buf = yylval.yy_string.str_ptr = Macro_buffer;
    /*
        **      Is it possible that reading this string during a rescan will
        **      overwrite the expansion being rescanned?  No, because a macro
        **      expansion is limited to the top half of Macro_buffer.
        **      For Macro_depth > 0, this is like copying the string from
        **      somewhere in the top half of Macro_buffer to the bottom half
        **      of Macro_buffer.
        **      Note that the restriction on the size of an expanded macro is
        **      stricter than the limit on an L_STRING length.  An expanded
        **      macro is limited to around 1019 bytes, but an L_STRING is
        **      limited to 2043 bytes.
        */
    for(;;) {
        switch(CHARMAP(c = GETCH())) {
        case LX_NL:
            UNGETCH();
            strcpy (Msg_Text, GET_MSG (2001));
            error(2001);
            /*
	    **  FALLTHROUGH
	    */
        case LX_DQUOTE:
            *p_buf++ = L'\0';
            yylval.yy_string.str_len = (USHORT)(p_buf-yylval.yy_string.str_ptr);
            return;
            break;
        case LX_EOS:
            if(handle_eos() != BACKSLASH_EOS) {
                continue;
            }
            if(InInclude) {
                break;
            }
            else {
                c = (WCHAR)escape(get_non_eof());  /* process escaped char */
            }
            break;
        }
        if(p_buf - Macro_buffer > LIMIT_STRING_LENGTH) {
            if( not_warned_yet ) {
                strcpy (Msg_Text, GET_MSG (4009));
                warning(4009);          /* string too big, truncating */
                not_warned_yet = FALSE;
            }
        }
        else {
            *p_buf++ = c;
        }
    }
}
Beispiel #4
0
/************************************************************************
**post_paste:		looks ahead one character to find out if a paste has
**	been requested immediately after this identifier.  If the next
**	character can continue an identifier, or is the macformal marker,
**	a paste should be done.  This is called after a macformal is found
**	to find out if the expanded or unexpanded actual should be used.
************************************************************************/
int  post_paste(void)
{
    UCHAR	c;

    if((CHARMAP(c = GETCH()) == LX_MACFORMAL) || (LXC_IS_IDENT(c))) {
	UNGETCH();
	return(TRUE);
    }
    UNGETCH();
    return(FALSE);
}
Beispiel #5
0
/************************************************************************
**      char_const : gather up a character constant
**  we're called after finding the openning single quote.
************************************************************************/
token_t char_const(void)
{
    REG WCHAR c;
    value_t value;
    token_t     tok;

    tok = (token_t)(Jflag ? L_CUNSIGNED : L_CINTEGER);
first_switch:
    switch(CHARMAP(c = GETCH())) {
    case LX_BACKSLASH:
        break;
    case LX_SQUOTE:
        strcpy (Msg_Text, GET_MSG (2137));  //"empty character constant"
        error(2137);
        value.v_long = 0;
        UNGETCH();
        break;
    case LX_EOS:                /* ??? assumes i/o buffering > 1 char */
        if(handle_eos() != BACKSLASH_EOS) {
            goto first_switch;
        }
        value.v_long = escape(get_non_eof());
        if( tok == L_CUNSIGNED ) {              /* don't sign extend */
            value.v_long &= 0xff;
        }
        break;
    case LX_NL:
        /* newline in character constant */
        strcpy (Msg_Text, GET_MSG (2001));
        error (2001);
        UNGETCH();
        /*
                **  FALLTHROUGH
                */
    default:
        value.v_long = c;
        break;
    }
    if((c = get_non_eof()) != L'\'') {
        strcpy (Msg_Text, GET_MSG (2015));
        error (2015);           /* too many chars in constant */
        do {
            if(c == L'\n') {
                strcpy (Msg_Text, GET_MSG (2016));
                error(2016);            /* missing closing ' */
                    break;
            }
        } while((c = get_non_eof()) != L'\'');
    }
    yylval.yy_tree = build_const(tok, &value);
    return(tok);
}
Beispiel #6
0
/************************************************************************
**	can_get_non_white:	tries to get the next non white character
**		using P1 rules for white space (NL included).  If the end of
**		an actual, or a rescan is found, this returns FALSE, so control
**		can drop into one of the lexers.
************************************************************************/
int	  can_get_non_white(void)
{
    int		return_value = FALSE;
    int		white_found = FALSE;

    for(;;) {
	switch(CHARMAP(GETCH())) {
	case LX_NL:
	    if(On_pound_line) {
		UNGETCH();
		goto leave_cgnw;
	    }
	    Linenumber++;
	    /*
				**	FALLTHROUGH
				*/
	case LX_WHITE:
	case LX_CR:
	    white_found = TRUE;
	    break;
	case LX_EOS:
	    {
		int	eos_res;
		if((eos_res = handle_eos()) & (ACTUAL_EOS | RESCAN_EOS)) {
		    goto leave_cgnw;
		}
		if(eos_res != BACKSLASH_EOS) {
		    break;
		}
	    }
	    /*
				**	FALLTHROUGH
				*/
	default:
	    UNGETCH();
	    return_value = TRUE;
	    goto leave_cgnw;
	    break;
	}
    }
leave_cgnw:
    if(white_found) {
	if(Exp_ptr >= ELIMIT) {
	    fatal_in_macro(10056);
	}
	if(*(Exp_ptr - 1) != ' ') {
	    *Exp_ptr++ = ' ';
	}
    }
    return(return_value);		/* could you get next non white? */
}
Beispiel #7
0
/************************************************************************
**      prep_string : outputs char/string constants when preprocessing only
************************************************************************/
void   prep_string(REG WCHAR c)
{
    REG WCHAR *p_buf;
    int term_char;

    p_buf = Reuse_W;

    term_char = c;

    *p_buf++ = c;               /*  save the open quote  */

    for(;;) {
        switch(CHARMAP(c = GETCH())) {
            case LX_DQUOTE:
            case LX_SQUOTE:
                if(c == (WCHAR)term_char) {
                    *p_buf++ = (WCHAR)term_char;/* save the terminating quote */
                    goto out_of_loop;
                }
                break;
            case LX_BACKSLASH:
                *p_buf++ = c;
                break;
            case LX_CR:
                continue;
            case LX_NL:
                UNGETCH();
                goto out_of_loop;
            case LX_EOS:
                if(c == L'\\') {
                    *p_buf++ = c;
                    c = get_non_eof();
                    break;
                }
                handle_eos();
                continue;
        }
        *p_buf++ = c;
        if(p_buf >= &Reuse_W[MED_BUFFER - 1]) {
            *p_buf = L'\0';
            myfwrite(Reuse_W, (size_t)(p_buf - Reuse_W) * sizeof(WCHAR), 1, OUTPUTFILE);
            p_buf = Reuse_W;
        }
    }

out_of_loop:
    *p_buf = L'\0';
    myfwrite(Reuse_W, (size_t)(p_buf - Reuse_W) * sizeof(WCHAR), 1, OUTPUTFILE);
}
Beispiel #8
0
/************************************************************************
**  gather_chars : collect chars until a matching one is found.
**  skip backslashed chars. moves the chars into the buffer,
**  returns a ptr past the last char copied.
************************************************************************/
ptext_t   gather_chars(REG ptext_t p, UCHAR match_c)
{
    UCHAR	c;

    *p++ = match_c;
    for(;;) {
	if(p > ELIMIT) {
	    return(ELIMIT);
	}
	switch(CHARMAP(c = GETCH())) {
	case LX_NL:
	    Msg_Temp = GET_MSG (2001);
       	    SET_MSG (Msg_Text, Msg_Temp);
	    error(2001);
	    UNGETCH();
	    c = match_c;
	    /*
			**  FALLTHROUGH
			*/
	case LX_DQUOTE:
	case LX_SQUOTE:
	    if(c == match_c) {
		*p++ = c;
		return(p);		/* only way out */
	    }
	    break;
	case LX_EOS:
	    if(handle_eos() != BACKSLASH_EOS) {
		continue;
	    }
	    else {
		/* got backslash */
		*p++ = '\\';
		c = get_non_eof();
		if((c == '\\') && (checknl())) {
		    continue;
		}
	    }
	    break;
	case LX_LEADBYTE:
	    *p++ = c;
	    c = get_non_eof();
	    break;
	}
	*p++ = c;
    }
}
Beispiel #9
0
ptext_t esc_sequence(ptext_t dest, ptext_t name)
{
    *dest = '"';
    while((*++dest = *name) != 0) {
	switch( CHARMAP(*name) ) {
	case LX_EOS:
	    *++dest = '\\';
	    break;
	case LX_LEADBYTE:
	    *++dest = *++name;
	    break;
	}
	name++;
    }
    *dest++ = '"';		/* overwrite null */
    return( dest );
}
Beispiel #10
0
/************************************************************************
**  nested_include : searches the parentage list of the currently
**		open files on the stack when a new include file is found.
**		Input : ptr to include file name.
**		Output : TRUE if the file was found, FALSE if not.
*************************************************************************/
int nested_include(void)
{
    PUCHAR	p_tmp1;
    PUCHAR	p_file;
    PUCHAR	p_slash;
    int			tos;

    tos = Findex;
    p_file = Filename;		/* always start with the current file */
    for(;;) {
	p_tmp1 = p_file;
	p_slash = NULL;
	while(*p_tmp1) {	/* pt to end of filename, find trailing slash */
	    if(CHARMAP(*p_tmp1) == LX_LEADBYTE) {
		p_tmp1++;
	    }
	    else if(strchr(Path_chars, *p_tmp1)) {
		p_slash = p_tmp1;
	    }
	    p_tmp1++;
	}
	if(p_slash) {
	    p_tmp1 = Reuse_1;
	    while(p_file <= p_slash) {	/*  we want the trailing '/'  */
		*p_tmp1++ = *p_file++;	/*  copy the parent directory  */
	    }
	    p_file = yylval.yy_string.str_ptr;
	    while((*p_tmp1++ = *p_file++)!=0) {  /*append include file name  */
		;	/*  NULL  */
	    }
	}
	else {
	    SET_MSG(Reuse_1,"%s",yylval.yy_string.str_ptr);
	}
	if(newinput(Reuse_1,MAY_OPEN)) {
	    return(TRUE);
	}
	if(tos <= 0) {
	    break;
	}
	p_file = Fstack[tos--].fl_name;
    }
    return(FALSE);
}
Beispiel #11
0
/************************************************************************
**  DumpSlashComment : while skipping a comment, output it.
************************************************************************/
void   DumpSlashComment(VOID)
{
    if( ! Cflag ) {
        skip_NLonly();
        return;
    }
    myfwrite(L"//", 2 * sizeof(WCHAR), 1, OUTPUTFILE);
    for(;;) {
        WCHAR c;

        switch(CHARMAP(c = GETCH())) {
        // must manually write '\r' with '\n' when writing 16-bit strings
        //case LX_CR:
        //    continue;
        case LX_EOS:
            handle_eos();
            continue;
        case LX_NL:
            UNGETCH();
            return;
        }
        myfwrite(&c, sizeof(WCHAR), 1, OUTPUTFILE);
    }
}
Beispiel #12
0
/************************************************************************
**  skip_cwhite : while the current character is whitespace or a comment.
**  a newline is NOT whitespace.
************************************************************************/
WCHAR     skip_cwhite(void)
{
    REG WCHAR           c;

skip_cwhite_again:
    while((c = GETCH()) <= L'/') {       /* many chars are above this */
        if(c == L'/') {
            if( ! skip_comment()) {
                return(L'/');
            }
        }
        else if(c > L' ') {              /* char is between '!' and '.' */
            return(c);
        }
        else {
            switch(CHARMAP(c)) {
            case LX_EOS:
                handle_eos();
                break;
            case LX_WHITE:
                continue;
                break;
            case LX_CR:
                continue;
                break;
            default:
                return(c);
                break;
            }
        }
    }
    if((c == L'\\') && (checknl())) {
        goto skip_cwhite_again;
    }
    return(c);
}
Beispiel #13
0
/************************************************************************
**  get_actuals :  Paren must already be found.  If all the actuals can
**		be read, the macro is pushed and expansion begins. Otherwise,
**		this function is quickly exited and lets the tiny lexer take
**		care of rescanning.
************************************************************************/
void   get_actuals(pdefn_t pdef, int n_formals)
{
    /*
    **	The only concern with this is that a rescan could finish while
    **	this is trying to collect actuals.  When a rescan finishes, it
    **	may reset Act_ptr and Exp_ptr.  Unless these are saved before the
    **	end of rescan is handled, the part of the actual collected so far
    **	would be lost.
    */
    REG	ptext_t	start;
    UCHAR		c;
    ptext_t	actuals_start;
    int			paste;
    int			level;

    *Exp_ptr++ = PREVCH();			/* must be oparen */
    level = 0;
    actuals_start = Act_ptr;

    while( level >= 0) {
	if(Exp_ptr >= ELIMIT) {
	    fatal_in_macro(10056);
	}
more_white:
	if( ! can_get_non_white()) {
	    return;
	}
	if(CHARMAP(CHECKCH()) == LX_SLASH) {
	    SKIPCH();
	    if(skip_comment()) {
		goto more_white;
	    }
	    else {
		start = Exp_ptr;
		*Exp_ptr++ = '/';
	    }
	}
	else {
	    start = Exp_ptr;
	}
	paste = FALSE;

	for(;;) {
	    switch(CHARMAP(c = GETCH())) {
	    case LX_CPAREN:
		if(--level < 0) {
		    goto leave_loop;
		}
		break;
	    case LX_COMMA:
		/*
		**	if the comma is not at level == 0, it is part of
		**	a parenthesized list and not a delimiter
		*/
		if(level == 0) {
		    goto leave_loop;
		}
		break;
	    case LX_SLASH:
		if( ! skip_comment()) {
		    break;
		}
		if(*(Exp_ptr - 1) == ' ') {
		    continue;
		}
		c = ' ';
		break;
	    case LX_CR:
	    case LX_NL:
	    case LX_WHITE:
		UNGETCH();		/* This char is valid white space */
		if( ! can_get_non_white()) {
		    return;
		}
		continue;
		break;
	    case LX_OPAREN:
		++level;
		break;
	    case LX_DQUOTE:
	    case LX_SQUOTE:
		Exp_ptr = gather_chars(Exp_ptr, c);
		continue;
		break;
	    case LX_ID:
		*Exp_ptr++ = c;
		while(LXC_IS_IDENT(c = GETCH())) {
		    if(Exp_ptr >= ELIMIT) {
			fatal_in_macro(10056);
		    }
		    *Exp_ptr++ = c;
		}
		if(CHARMAP(c) != LX_MACFORMAL) {
		    UNGETCH();
		    continue;
		}
		paste = TRUE;
		/*
		**	FALLTHROUGH
		*/
	    case LX_MACFORMAL:
		move_to_exp(do_macformal(&paste));
		continue;
		break;
	    case LX_STRFORMAL:
		move_to_exp_esc('"', do_strformal());
		continue;
		break;
	    case LX_CHARFORMAL:
		move_to_exp_esc('\'', do_strformal());
		continue;
		break;
	    case LX_EOS:
		/*
		**	Will saving this pointers create dead space in the
		**	buffers?  Yes, but only temporarily.
		**
		**	handle_eos() may reset Act_ptr and Exp_ptr to the
		**	beginning of the buffers if a rescan is finishing
		**	and Macro_depth is going to be 0.  ANSI allows
		**	actuals to start within a macro defintion and be
		**	completed (further actuals and closing paren) later
		**	in the text.
		**
		**	These buffer pointers will eventually be reset to
		**	the beginnings of their respective buffers when the
		**	macro for the actuals being collected right now
		**	finish rescan
		**
		**	This is special handling for folks who use
		**	unbalanced parens in macro definitions
		*/
		{
		    ptext_t	Exp_save;
		    ptext_t	Act_save;
		    int	eos_res;

		    Exp_save = Exp_ptr;
		    Act_save = Act_ptr;
		    if((eos_res = handle_eos()) & (ACTUAL_EOS | RESCAN_EOS)) {
			return;
		    }
		    Act_ptr = Act_save;
		    Exp_ptr = Exp_save;
		    if(eos_res == BACKSLASH_EOS) {	/* ??? DFP QUESTION  */
			*Exp_ptr++ = c;		/*  save the \  */
			c = get_non_eof();	/*  get char following \  */
			break;
		    }
		}
		continue;
		break;
	    }
	    *Exp_ptr++ = c;
	}
leave_loop:
	/*
		**	if the last character was whitespace, hose it
		*/
	if(CHARMAP(*(Exp_ptr - 1)) == LX_WHITE) {
	    Exp_ptr--;
	}
	/*
	**	if Exp_ptr <= start, foo() was read, don't incr N_actuals
	*/
	if(Exp_ptr > start) {
	    N_actuals++;
	    move_to_actual(start, Exp_ptr);
	}
	*Exp_ptr++ = c;
    }

    P_actuals = actuals_start;
    if(n_formals < N_actuals) {
	Msg_Temp = GET_MSG (4002);
        SET_MSG (Msg_Text, Msg_Temp, Reuse_1);
	warning(4002);
    }
    else if(n_formals > N_actuals) {
	Msg_Temp = GET_MSG (4003);
        SET_MSG (Msg_Text, Msg_Temp, Reuse_1);
	warning(4003);
    }

    if(DEFN_TEXT(pdef)) {
	push_macro(pdef);
	expand_macro();
    }
    else {
	/*
		**	the macro expands to nothing (no definition)
		**	This essentially means delete the macro and its actuals
		**	from the expanded text
		*/
	Act_ptr = P_actuals;	/* reset pointer to get rid of actuals */
	Exp_ptr = Save_Exp_ptr;	/* delete macro & actuals from exp text */
    }
}
Beispiel #14
0
/************************************************************************
**	can_expand:		tries to expand the macro passed to it - returns
**		true if it succeeded in expanding it.  It will only return FALSE
**		if a macro name was found, a paren was expected, and a paren was
**		not the next non white character.
************************************************************************/
int can_expand(pdefn_t pdef)
{
    UCHAR		c;
    int			n_formals;
    int			return_value = FALSE;

    Tiny_lexer_nesting = 0;
    Save_Exp_ptr = Exp_ptr;		/* not necessarily EXP_BUFFER */
    Macro_line = Linenumber;
expand_name:

    P_actuals = Act_ptr;
    N_actuals = 0;

    n_formals = DEFN_NFORMALS(pdef);
    if( PRE_DEFINED(pdef) ) {
	push_macro(pdef);
	DEFN_EXPANDING(CURRENT_MACRO)++;
	if(rescan_expansion()) {
	    return(TRUE);			/* could expand macro */
	}
    }
    else if( n_formals == 0 ) {
	return_value = TRUE;
	if(DEFN_TEXT(pdef)) {
	    push_macro(pdef);
	    expand_definition();
	}
	else {
	    /*
		**	Macro expands to nothing (no definition).  Since it
		**	didn't have any actuals, Act_ptr is already correct.
		**	Exp_ptr must be changed however to delete the
		**	identifier from the expanded text.
		*/
	    Exp_ptr = Save_Exp_ptr;
	}
    }
    else {
	if( n_formals == -1 ) {
	    n_formals = 0;
	}
name_comment_paren:
	if( can_get_non_white()) {
	    if(CHARMAP(CHECKCH()) == LX_SLASH) {
		SKIPCH();
		if(skip_comment()) {
		    goto name_comment_paren;
		}
		else {
		    UNGETCH();
		}
	    }
	    if(CHARMAP(CHECKCH())==LX_OPAREN) {
		SKIPCH();
		return_value = TRUE;
		get_actuals(pdef, n_formals);
	    }
	    else {
		/*
				**	#define xx(a) a
				**  xx bar();
				**  don't lose white space between "xx" and "bar"
				*/
		ptext_t	p = Exp_ptr;

		push_macro(pdef);
		DEFN_EXPANDING(CURRENT_MACRO)++;
		Exp_ptr = p;
		if( rescan_expansion() ) {
		    return(FALSE);
		}
	    }
	}
	else {
	}
    }
    /*
	**	makes sure a macro is being worked on. At this point, there will
	**	be a macro to expand, unless the macro expand_the_named_macro was
	**	passed had no definition text.  If it had no defintion text,
	**	Tiny_lexer_nesting was not incremented.
	*/
    while(Tiny_lexer_nesting != 0) {
	if(Exp_ptr >= ELIMIT) {
	    fatal_in_macro(10056);
	}
	switch(CHARMAP(c = GETCH())) {
	case LX_ID:
	case LX_MACFORMAL:
	    Save_Exp_ptr = Exp_ptr;
	    if(tl_getid(c) && ((pdef = get_defined())!= 0)) {
		if(DEFN_EXPANDING(pdef)) {
		    /*
						**	the macro is already being expanded, so just
						**	write the do not expand marker and the
						**	identifier to the expand area.  The do not
						**	expand marker is necessary so this macro
						**	doesn't get expanded on the rescan
						*/
		    int		len = Reuse_1_length - 1;

		    *Exp_ptr++ = LX_NOEXPANDMARK;
		    *Exp_ptr++ = ((UCHAR)len);
		}
		else {
		    /*
						** a legal identifier was read, it is defined, and
						** it is not currently being expanded.  This means
						** there is reason to believe it can be expanded.
						*/
		    goto expand_name;
		}
	    }
	    if(InIf &&(memcmp(Reuse_1, "defined", 8) ==0)) {
		do_defined(Reuse_1);
	    }
	    continue;
	    break;
	case LX_NUMBER:
	    /* getnum with Prep on to keep leading 0x on number */
	    {
		int	Save_prep = Prep;
		Prep = TRUE;
		getnum(c);
		Prep = Save_prep;
	    }
	    continue;
	    break;
	case LX_DOT:
	    *Exp_ptr++ = '.';
dot_switch:
	    switch(CHARMAP(c = GETCH())) {
	    case LX_EOS:
		if(handle_eos() != BACKSLASH_EOS) {
		    if(Tiny_lexer_nesting > 0) {
			goto dot_switch;
		    }
		    continue;
		}
		break;
	    case LX_DOT:
		*Exp_ptr++ = '.';
		if( ! checkop('.')) {
		    break;	/* error will be caught on rescan */
		}
		*Exp_ptr++ = '.';
		continue;
		break;
	    case LX_NUMBER:
		*Exp_ptr++ = c;
		get_real(Exp_ptr);
		continue;
	    }
	    UNGETCH();
	    continue;
	case LX_CHARFORMAL:
	    move_to_exp_esc('\'', do_strformal());
	    continue;
	    break;
	case LX_STRFORMAL:
	    move_to_exp_esc('"', do_strformal());
	    continue;
	    break;
	case LX_DQUOTE:
	case LX_SQUOTE:
	    /*
	    ** 	gather_chars is called even though the error reported
	    **	on overflow may need to be changed.
	    */
	    Exp_ptr = gather_chars(Exp_ptr, c);
	    continue;
	    break;
	case LX_WHITE:
	    while(LXC_IS_WHITE(GETCH())) {
		;
	    }
	    UNGETCH();
	    c = ' ';
	    break;
	case LX_EOS:
	    if(handle_eos() == BACKSLASH_EOS) {
		*Exp_ptr++ = c;
		c = GETCH();
		break;
	    }
	    continue;
	    break;
	}
	*Exp_ptr++ = c;
    }
    return(return_value);
}
Beispiel #15
0
/************************************************************************
**  get_definition : accumulate the macro definition, stops when it finds
**  a newline (it uses it). returns a ptr to the end of the string it builds.
**  builds the string in Macro_buffer. (given the start in P_defn_start)
************************************************************************/
int   get_definition(void)
{
    REG	ptext_t	p;
    UCHAR	c;
    int		stringize = FALSE;
    int		charize = FALSE;

    p = P_defn_start;
    c = skip_cwhite();
    for(;;) {
	chkbuf(p);
	switch(CHARMAP(c)) {
	case LX_EOS:
	    if(handle_eos() == BACKSLASH_EOS) {
		/* got backslash EOS */
		/* \<anything else> goes out as is.  The <anything else>
			* character must be emitted now, so that
			*		#define FOO(name)	\name
			*		. . .
			*		FOO(bar)
			*
			* does NOT see occurence of name in the definition as an
			* occurence of the formal param and emit \bar when it is
			* expanded later,but if the definition is \nname it will
			* find name as a formal paramater and emit \nbar
			*/
		*p++ = c;	/* put in backslash, break'll add new char */
		c = get_non_eof();
	    }
	    else {
		c = GETCH();
		continue;
	    }
	    break;
	case LX_NL:		/*  only way out  */
	    UNGETCH();
	    if(p == P_defn_start) {
		return(0);
	    }
	    chkbuf(p);
	    *p++ = EOS_CHAR;
	    *p++ = EOS_DEFINITION;	/* tells handle_eos defn finished */
	    return(p - P_defn_start);/* p's last incr counts the 0*/
	    break;
	case LX_DQUOTE:
	case LX_SQUOTE:
	    p = gather_chars(p, c);
	    c = GETCH();
	    continue;
	    break;
	case LX_POUND:
split_op:
	    switch(CHARMAP(GETCH())) {
	    case LX_POUND:
		/*
		**  handle ## processing. cant be the first or the last.
		*/
		if(p == P_defn_start) {
	    	    Msg_Temp = GET_MSG (2160);
       	    	    SET_MSG (Msg_Text, Msg_Temp);
		    error(2160);	/* ## not allowed as first entry */
		    continue;
		}
		if(*(p - 1) == ' ') {	/* hose the last blank */
		    p--;
		}
		if(CHARMAP(c = skip_cwhite()) == LX_NL) {
		    UNGETCH();
	    	    Msg_Temp = GET_MSG (2161);
       	    	    SET_MSG (Msg_Text, Msg_Temp);
		    error(2161);
		    continue;
		}
		/* this case does *not* fall through to LX_ID */
		continue;
		break;
	    case LX_EACH:
		charize = TRUE;
		break;
	    case LX_EOS:
		if( handle_eos() != BACKSLASH_EOS ) {
		    goto split_op;
		}
		/*
		**	FALLTHROUGH
		*/
	    default:
		UNGETCH();
		stringize = TRUE;
		break;
	    }
	    if(CHARMAP(c = skip_cwhite()) != LX_ID) {
	    	Msg_Temp = GET_MSG (2162);
       	    	SET_MSG (Msg_Text, Msg_Temp);
		error(2162);	/* must have id following */
		continue;
	    }
	    /*
	    **  FALLTHROUGH
	    */
	case LX_ID:
	    {
		/* we have the start of an identifier - check it to see if
		 * its an occurence of a formal parameter name.
		 * we gather the id ourselves (instead of getid()) since this
		 * wil save us from having to copy it to our string if it's
		 * not a formal parameter.
		 */
		int			n;
		ptext_t	p_macformal;

		p_macformal = p;
		do {
		    chkbuf(p);
		    *p++ = c;
get_more_id:
		    c = GETCH();
		} while(LXC_IS_IDENT(c));
		if(CHARMAP(c) == LX_EOS) {
		    if(handle_eos() != BACKSLASH_EOS) {
			goto get_more_id;
		    }
		}
		*p = '\0'; /* term. string, but do not advance ptr */
		if((n = is_macro_arg(p_macformal)) >= 1) {
		    /*
		    **  this is an occurance of formal 'n', replace the id with
		    **  the special MAC character.
		    */
		    p = p_macformal;
		    if(stringize) {
			*p++ = LX_FORMALSTR;
		    }
		    else {
			if(charize) {
			    *p++ = LX_FORMALCHAR;
			}
			else {
			    *p++ = LX_FORMALMARK;
			}
		    }
		    *p++ = (UCHAR) n;
		}
		else if(charize || stringize) {
	  	    Msg_Temp = GET_MSG (2162);
       	    	    SET_MSG (Msg_Text, Msg_Temp);
		    error(2162);
		}
		stringize = FALSE;
		charize = FALSE;
		continue;	/* we broke out of the loop with a new char */
	    }
	case LX_SLASH:
	    if( ! skip_comment() ) {	/* really is a slash */
		break;
	    }
	    /*
			**  FALLTHROUGH
			*/
	case LX_CR:
	case LX_WHITE:
	    /*
	    **  this is white space, all contiguous whitespace is transformed
	    **  to 1 blank. (hence the skip_cwhite() and the continue).
	    */
	    if(CHARMAP(c = skip_cwhite()) != LX_NL) {
		*p++ = ' ';
	    }
	    continue;				/* restart loop */
	case LX_ILL:
	    Msg_Temp = GET_MSG (2018);
       	    SET_MSG (Msg_Text, Msg_Temp, c);
	    error(2018);
	    c = GETCH();
	    continue;
	}
	*p++ = c;
	c = GETCH();
    }
}
Beispiel #16
0
/************************************************************************
**  get_formals : collect comma separated idents until the first closing paren
**  (the openning paren has already been read)
**  since we can't be in a macro when we're asked for this, we can be assured
**  that we can use a single buffer to collect all the formal names.
************************************************************************/
void   get_formals(void)
{
    UCHAR		c;
    ptext_t	p_stop;
    ptext_t	p_id;

    p_id = p_stop = FORMAL_TEXT(P_defn_start);
    for(;;) {
	switch(CHARMAP(c = skip_cwhite())) {
	case LX_ID:
	    if( p_id != p_stop ) {
		Msg_Temp = GET_MSG (2010);
        	SET_MSG (Msg_Text, Msg_Temp, c);
        	error (2010);
	    }
	    *p_stop++ = c;
	    for(;;) {
		while(LXC_IS_IDENT(c = GETCH())) {	/* while an id char */
		    *p_stop++ = c;			/* collect it */
		} if(c == EOS_CHAR) {
		 	/*
			**  found end of buffer marker, make sure it is,
			**  then handle it.
			*/
		    if(io_eob()) {	/* end of buffer in here is bad */
			Msg_Temp = GET_MSG (1004);
			SET_MSG (Msg_Text, Msg_Temp);
			fatal (1004);
		    }
		    continue;
		}
		if((c == '\\') && (checknl())) {
		    continue;
		}
		UNGETCH();
		break;
	    }
	    *p_stop++ = '\0';
	    break;
	case LX_COMMA:
	case LX_CPAREN:
	    if( p_stop > p_id ) {
		/* make sure an identifier was read */
		if((p_stop - p_id) >= TINY_BUFFER) {
		    p_id[TINY_BUFFER - 1] = '\0';
		    Msg_Temp = GET_MSG (4111);
		    SET_MSG (Msg_Text, Msg_Temp, p_id);
		    warning(4011);		/* id truncated */
		    p_stop = p_id + TINY_BUFFER;
		}
		if(is_macro_arg(p_id) >= 1) {
		    Msg_Temp = GET_MSG (2009);
        	    SET_MSG (Msg_Text, Msg_Temp, p_id);
		    error(2009);		/* reuse of formal */
		}
		else {
		    FORMAL_SIZE(P_defn_start) = (UCHAR)(p_stop - P_defn_start);
		    P_defn_start = p_stop;
		    N_formals++;
		}
	    }
	    else {
		if( (CHARMAP(c) == LX_COMMA) || (N_formals > 0) ) {
		    Msg_Temp = GET_MSG (2010);
        	    SET_MSG (Msg_Text, Msg_Temp, c);
		    error(2010);
		}
	    }
	    if( CHARMAP(c) == LX_CPAREN ) {
		return;
	    }
	    p_id = p_stop = FORMAL_TEXT(P_defn_start);
	    break;
	default:
	    Msg_Temp = GET_MSG (2010);
       	    SET_MSG (Msg_Text, Msg_Temp, c);
	    error(2010); /*  unexpected char in formal list */
	    break;
	}
    }
}
Beispiel #17
0
void   do_newline()
{
    ++Linenumber;
    for(;;) {
        switch(CHARMAP(GETCH())) {
        case LX_BOM:  // ignore Byte Order Mark
            break;
        case LX_CR:
            break;
        case LX_POUND:
            preprocess();
            break;
        case LX_SLASH:
            if( ! skip_comment()) {
                goto leave_do_newline;
            }
            break;
        case LX_NL:
            {
                if ((lCPPTotalLinenumber++ & RC_PREPROCESS_UPDATE) == 0)
                    UpdateStatus(1, lCPPTotalLinenumber);
            }
            Linenumber++;
            // must manually write '\r' with '\n' when writing 16-bit strings
            if( Prep ) {        /*  preprocessing only */
                myfwrite(L"\r", sizeof(WCHAR), 1, OUTPUTFILE);
            }
            /*
                        **  FALLTHROUGH
                        */
        case LX_WHITE:
            if( Prep ) {        /*  preprocessing only, output whitespace  */
                myfwrite(&(PREVCH()), sizeof(WCHAR), 1, OUTPUTFILE);
            }
            else {
                do {
                    ;
                } while(LXC_IS_WHITE(GETCH()));
                UNGETCH();
            }
            break;
        case LX_EOS:
            if(PREVCH() == EOS_CHAR || PREVCH() == CONTROL_Z) {
                if(io_eob()) {          /* leaves us pointing at a valid char */
                    return;
                }
                break;
            }
            if(checknl()) {
                continue;
            }
            /* it's a backslash */
            /*
                        **      FALLTHROUGH
                        */
        default:                /* first non-white is not a '#', leave */

leave_do_newline:

            UNGETCH();
            return;
        }
    }
}
Beispiel #18
0
/************************************************************************
**tl_getid:		This function reads an identifier for the tiny lexer
**		into EXP_BUFFER.  if macformal is found, the text of that actual
**		(expanded or not) is appended to the identifier.  It is possible
**		that this text will contain characters that are not legal
**		identifiers so return value is whether checking to see if the
**		"identifier" is defined is worth the bother.
************************************************************************/
int tl_getid(UCHAR c)
{
    UCHAR	*p;
    int		paste;
    int		legal_identifier;
    int		length = 0;

    p = Exp_ptr;
    paste = FALSE;
    legal_identifier = TRUE;

do_handle_macformal:
    if(CHARMAP(c) == LX_MACFORMAL) {
	ptext_t	p_buf;

	if((p_buf = do_macformal(&paste)) != 0) {
	    while( *p_buf ) {
		if( ! LXC_IS_IDENT(*p_buf)) {
		    legal_identifier = FALSE;
		}
		if(Exp_ptr >= ELIMIT) {
		    fatal_in_macro(10056);
		}
		*Exp_ptr++ = *p_buf++;
	    }
	}
    }
    else {
	*Exp_ptr++ = c;
    }

do_handle_eos:
    while(LXC_IS_IDENT(c = GETCH())) {
	if(Exp_ptr >= ELIMIT) {
	    fatal_in_macro(10056);
	}
	*Exp_ptr++ = c;
    }

    if(CHARMAP(c) == LX_NOEXPAND) {
	length = (int)GETCH();			/* just skip length */
	goto do_handle_eos;
    }

    if(CHARMAP(c) == LX_MACFORMAL) {
	paste = TRUE;
	goto do_handle_macformal;
    }

    UNGETCH();
    if(legal_identifier && (length == (Exp_ptr - p))) {
	legal_identifier = FALSE;
    }

    if(legal_identifier) {
	if(((Exp_ptr - p) > LIMIT_ID_LENGTH) && ( ! Prep)) {
	    Exp_ptr = &p[LIMIT_ID_LENGTH];
	    *Exp_ptr = '\0';	/* terminates identifier for warning */
	    Msg_Temp = GET_MSG (4011);
            SET_MSG (Msg_Text, Msg_Temp, p);
	    warning(4011);		/* id truncated */
	}
	else {
	    *Exp_ptr = '\0';	/* terminates identifier for expandable check */
	}
	/*
	**	Whether or not we are doing Prep output, we still have to make
	**	sure the identifier will fit in Reuse_1
	*/
	if((Exp_ptr - p) > sizeof(Reuse_1)) {
	    Exp_ptr = &p[LIMIT_ID_LENGTH];
	    *Exp_ptr = '\0';
	    Msg_Temp = GET_MSG (4011);
            SET_MSG (Msg_Text, Msg_Temp, p);
	    warning(4011);
	}
	/*
	**	copy into Reuse_1 for warnings about mismatched number of
	**	formals/actuals, and in case it's not expandable
	*/
	memcpy(Reuse_1, p, (int)((Exp_ptr - p) + 1));
	Reuse_1_hash = local_c_hash(Reuse_1);
	/*
	**	the characters from Exp_ptr to p inclusive do not include the
	**	the hash character, the length character, and the terminating
	**	null.
	*/
	Reuse_1_length = (UCHAR)((Exp_ptr - p) + 1);
    }
    return(legal_identifier);
}
Beispiel #19
0
/************************************************************************
**  BEGIN DEFINE A MACRO {
************************************************************************/
void   define(void)
{
    UCHAR	c;

    if (! (LX_IS_IDENT(c = skip_cwhite())) ) {
	Msg_Temp = GET_MSG (2007);
	SET_MSG (Msg_Text, Msg_Temp);
        error (2007); /* #define syntax */
	skip_cnew();
	return;
    }
    getid(c);
    N_formals = 0;
    P_defn_start = Macro_buffer;
/*
**  the next character must be white space or an open paren
*/
first_switch:
    switch(CHARMAP(c = GETCH())) {
    case LX_OPAREN:			/*  we have formal parameters  */
	get_formals();		/*  changes N_formals and fills Macro_buffer */
	if(N_formals == 0) {/*  empty formal list  */
		/*
		**  we must special case this since the expand() reads in the
		**  actual arguments iff there are formal parameters. thus if we
		**	#define	foo()	bar()
		**		. . .
		**		foo()
		**  will expand as 
		**		bar()()
		**  we put the right paren in to fool the expander into looking
		**  for actuals.
		*/
	    N_formals = -1;
	}
	break;
    case LX_WHITE:
	break;
    case LX_CR:
	goto first_switch;
    case LX_SLASH:
	if( ! skip_comment()) {
	    Msg_Temp = GET_MSG (2008);
            SET_MSG (Msg_Text, Msg_Temp, '/');
            error (2008);
	}
	break;
    case LX_NL:			/* no definition */
	UNGETCH();
	definstall((ptext_t)0, 0, 0);
	return;
	break;
    case LX_EOS:
	if(handle_eos() != BACKSLASH_EOS) {
	    goto first_switch;
	}
	/* got BACKSLASH_EOS */
	/*
	**  FALLTHROUGH
	*/
    default:
	Msg_Temp = GET_MSG (2008);
        SET_MSG (Msg_Text, Msg_Temp, c);
        error (2008); /* unexpected character in macro definition */
    }
    definstall(P_defn_start, get_definition(), N_formals);
}
Beispiel #20
0
bool MathInterpreter::interpretGreekLetter (MDEVector &target,
					 const std::string &src,
					 size_t &i)
{

#define CHARMAP(symbol1,char1,symbol2,char2) ( GreekLetterMap(symbol1, MDE_GreekLetter::char1) ) ( GreekLetterMap(symbol2, MDE_GreekLetter::char2) )
  static const std::vector<GreekLetterMap> map = boost::assign::list_of
    CHARMAP('a', alpha, 'A', Alpha)
    CHARMAP('b', beta, 'B', Beta)
    CHARMAP('g', gamma, 'G', Gamma)
    CHARMAP('d', delta, 'D', Delta)
    CHARMAP('e', epsilon, 'E', Epsilon)
    CHARMAP('z', zeta, 'Z', Zeta)
    CHARMAP('h', eta, 'H', Eta)
    CHARMAP('t', theta, 'T', Theta)
    CHARMAP('i', iota, 'I', Iota)
    CHARMAP('k', kappa, 'K', Kappa)
    CHARMAP('l', lambda, 'L', Lambda)
    CHARMAP('m', mu, 'M', Mu)
    CHARMAP('n', nu, 'N', Nu)
    CHARMAP('x', xi, 'X', Xi)
    CHARMAP('o', omicron, 'O', Omicron)
    CHARMAP('p', pi, 'P', Pi)
    CHARMAP('q', tau, 'Q', Tau)
    CHARMAP('r', rho, 'R', Rho)
    CHARMAP('s', sigma, 'S', Sigma)
    CHARMAP('u', upsilon, 'U', Upsilon)
    CHARMAP('v', phi, 'V', Phi)
    CHARMAP('c', chi, 'C', Chi)
    CHARMAP('f', psi, 'F', Psi)
    CHARMAP('w', omega, 'W', Omega)
    ;

  if (src [i] != '%' || (i+1) >= src.length())
    return false;

  char c = src [i+1];
  if (c == '%') /* %% is the symbol for 'percent sign' */
    return false;

  for (std::vector<GreekLetterMap>::const_iterator it = map.begin();
       it != map.end(); ++it) {
    const GreekLetterMap &mi = *it;
    // Look for the first character
    if (c == mi.symbol) {
      LOG_TRACE << "* added greek letter for (" << mi.symbol << ")";
      target.push_back (boost::make_shared<MDE_GreekLetter>(mi.character));
      i += 2;

      return true;
    }
  }

  MSG_WARNING(UNKNOWN_GREEK, boost::str(boost::format("'%%%c' does not represent a greek letter") % c));
  return false;
}