Beispiel #1
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 #2
0
/************************************************************************
**  checknl : check for newline, skipping carriage return if there is one.
**  also increments Linenumber, so this should be used by routines which
**  will not push the newline back in such a way that rawtok() will be invoked,
**  find the newline and do another increment.
************************************************************************/
int checknl(void)
{
    REG WCHAR           c;

    for(;;) {
        c = GETCH();
        if(c > L'\r') {
            UNGETCH();
            return(FALSE);
        }
        switch(c) {
        case L'\n':
            Linenumber++;
            // must manually write '\r' with '\n' when writing 16-bit strings
            if( Prep ) {
                myfwrite(L"\r\n", 2 * sizeof(WCHAR), 1, OUTPUTFILE);
            }
            return(TRUE);
            break;
        case L'\r':
            continue;
            break;
        case EOS_CHAR:
            handle_eos();
            PREVCH() = L'\\';    /* M00HACK - needs pushback */
            continue;
            break;
        default:
            UNGETCH();
            return(FALSE);
            break;
        }
    }
}
Beispiel #3
0
/************************************************************************
**  skip_1comment : we're called when we're already in a comment.
**  we're looking for the comment close. we also count newlines
**  and output them if we're preprocessing.
************************************************************************/
void   skip_1comment(void)
{
    UINT        c;

    for(;;) {
        c = GETCH();
        if(c == L'*') {

recheck:

            c = GETCH();
            if(c == L'/') {      /* end of comment */
                return;
            }
            else if(c == L'*') {
                /*
                **  if we get another '*' go back and check for a slash
                */
                goto recheck;
            }
            else if(c == EOS_CHAR) {
                handle_eos();
                goto recheck;
            }
        }
        /*
        **  note we fall through here. we know this baby is not a '*'
        **  we used to unget the char and continue. since we check for
        **  another '*' inside the above test, we can fall through here
        **  without ungetting/getting and checking again.
        */
        if(c <= L'\n') {
            /*
            **  hopefully, the above test is less expensive than doing two tests
            */
            if(c == L'\n') {
                Linenumber++;
                if(Prep) {
                    myfwrite(L"\r\n", 2 * sizeof(WCHAR), 1, OUTPUTFILE);
                }
            }
            else if(c == EOS_CHAR) {
                handle_eos();
            }
        }
    }
}
Beispiel #4
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 #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
/************************************************************************
**  get_non_eof : get a real char.
************************************************************************/
WCHAR     get_non_eof(void)
{
    WCHAR    c;

get_non_eof_again:
    while((c = GETCH()) <= L'\r') {
        if(c == L'\r') {
            continue;
        }
        else if(c != EOS_CHAR) {
            break;
        }
        if(Tiny_lexer_nesting > 0) {
            break;
        }
        handle_eos();
    }
    if((c == L'\\') && (checknl())) {
        goto get_non_eof_again;
    }
    return(c);
}
Beispiel #10
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 #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
/************************************************************************
**  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 #13
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 #14
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 #15
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 #16
0
int fc_solve_initial_user_state_to_c(
    const char * string,
    fcs_state_with_locations_t * out_state,
    int freecells_num,
    int stacks_num,
    int decks_num
#ifdef FCS_WITH_TALONS
    ,int talon_type
#endif
#ifdef INDIRECT_STACK_STATES
    , char * indirect_stacks_buffer
#endif
    )
{
    fcs_state_with_locations_t ret_with_locations;

    int s,c;
    const char * str;
    fcs_card_t card;
    int first_line;

    int prefix_found;
    const char * const * prefixes;
    int i;
    int decks_index[4];

    fcs_state_init(
        &ret_with_locations, 
        stacks_num
#ifdef INDIRECT_STACK_STATES        
        , indirect_stacks_buffer  
#endif
        );
    str = string;

    first_line = 1;

#define ret (ret_with_locations.s)
/* Handle the end of string - shouldn't happen */
#define handle_eos() \
    { \
        if ((*str) == '\0') \
        {  \
            return FCS_USER_STATE_TO_C__PREMATURE_END_OF_INPUT; \
        } \
    }

#ifdef FCS_WITH_TALONS
    if (talon_type == FCS_TALON_KLONDIKE)
    {
        fcs_klondike_talon_num_redeals_left(ret) = -1;
    }
#endif

    for(s=0;s<stacks_num;s++)
    {
        /* Move to the next stack */
        if (!first_line)
        {
            while((*str) != '\n')
            {
                handle_eos();
                str++;
            }
            str++;
        }
        first_line = 0;

        prefixes = freecells_prefixes;
        prefix_found = 0;
        for(i=0;prefixes[i][0] != '\0'; i++)
        {
            if (!strncasecmp(str, prefixes[i], strlen(prefixes[i])))
            {
                prefix_found = 1;
                str += strlen(prefixes[i]);
                break;
            }
        }

        if (prefix_found)
        {
            for(c=0;c<freecells_num;c++)
            {
                fcs_empty_freecell(ret, c);
            }
            for(c=0;c<freecells_num;c++)
            {
                if (c!=0)
                {
                    while(
                            ((*str) != ' ') &&
                            ((*str) != '\t') &&
                            ((*str) != '\n') &&
                            ((*str) != '\r')
                         )
                    {
                        handle_eos();
                        str++;
                    }
                    if ((*str == '\n') || (*str == '\r'))
                    {
                        break;
                    }
                    str++;
                }

                while ((*str == ' ') || (*str == '\t'))
                {
                    str++;
                }
                if ((*str == '\r') || (*str == '\n'))
                    break;

                if ((*str == '*') || (*str == '-'))
                {
                    card = fcs_empty_card;
                }
                else
                {
                    card = fcs_card_user2perl(str);
                }

                fcs_put_card_in_freecell(ret, c, card);
            }

            while (*str != '\n')
            {
                handle_eos();
                str++;
            }
            s--;
            continue;
        }

        prefixes = foundations_prefixes;
        prefix_found = 0;
        for(i=0;prefixes[i][0] != '\0'; i++)
        {
            if (!strncasecmp(str, prefixes[i], strlen(prefixes[i])))
            {
                prefix_found = 1;
                str += strlen(prefixes[i]);
                break;
            }
        }

        if (prefix_found)
        {
            int d;

            for(d=0;d<decks_num*4;d++)
            {
                fcs_set_foundation(ret, d, 0);
            }

            for(d=0;d<4;d++)
            {
                decks_index[d] = 0;
            }
            while (1)
            {
                while((*str == ' ') || (*str == '\t'))
                    str++;
                if ((*str == '\n') || (*str == '\r'))
                    break;
                d = fcs_u2p_suit(str);
                str++;
                while (*str == '-')
                    str++;
                c = fcs_u2p_card_number(str);
                while (
                        (*str != ' ') &&
                        (*str != '\t') &&
                        (*str != '\n') &&
                        (*str != '\r')
                      )
                {
                    handle_eos();
                    str++;
                }

                fcs_set_foundation(ret, (decks_index[d]*4+d), c);
                decks_index[d]++;
                if (decks_index[d] >= decks_num)
                {
                    decks_index[d] = 0;
                }
            }
            s--;
            continue;
        }

#ifdef FCS_WITH_TALONS
        prefixes = talon_prefixes;
        prefix_found = 0;
        for(i=0;prefixes[i][0] != '\0'; i++)
        {
            if (!strncasecmp(str, prefixes[i], strlen(prefixes[i])))
            {
                prefix_found = 1;
                str += strlen(prefixes[i]);
                break;
            }
        }

        if (prefix_found)
        {
            /* Input the Talon */
            int talon_size;

            talon_size = MAX_NUM_DECKS*52+16;
            ret.talon = malloc(sizeof(fcs_card_t)*talon_size);
            fcs_talon_pos(ret) = 0;

            for(c=0 ; c < talon_size ; c++)
            {
                /* Move to the next card */
                if (c!=0)
                {
                    while(
                        ((*str) != ' ') &&
                        ((*str) != '\t') &&
                        ((*str) != '\n') &&
                        ((*str) != '\r')
                    )
                    {
                        handle_eos();
                        str++;
                    }
                    if ((*str == '\n') || (*str == '\r'))
                    {
                        break;
                    }
                }

                while ((*str == ' ') || (*str == '\t'))
                {
                    str++;
                }

                if ((*str == '\n') || (*str == '\r'))
                {
                    break;
                }

                card = fcs_card_user2perl(str);

                fcs_put_card_in_talon(ret, c+(talon_type==FCS_TALON_KLONDIKE), card);
            }
            fcs_talon_len(ret) = c;

            if (talon_type == FCS_TALON_KLONDIKE)
            {
                int talon_len;

                talon_len = fcs_talon_len(ret);
                fcs_klondike_talon_len(ret) = talon_len;
                fcs_klondike_talon_stack_pos(ret) = -1;
                fcs_klondike_talon_queue_pos(ret) = 0;
            }

            s--;
            continue;
        }

        prefixes = num_redeals_prefixes;
        prefix_found = 0;
        for(i=0;prefixes[i][0] != '\0'; i++)
        {
            if (!strncasecmp(str, prefixes[i], strlen(prefixes[i])))
            {
                prefix_found = 1;
                str += strlen(prefixes[i]);
                break;
            }
        }

        if (prefix_found)
        {
            while ((*str < '0') && (*str > '9') && (*str != '\n'))
            {
                handle_eos();
                str++;
            }
            if (*str != '\n')
            {
                int num_redeals;

                num_redeals = atoi(str);
                if (talon_type == FCS_TALON_KLONDIKE)
                {
                    fcs_klondike_talon_num_redeals_left(ret) =
                        (num_redeals < 0) ?
                            (-1) :
                            ((num_redeals > 127) ? 127 : num_redeals)
                                ;
                }
            }
            s--;
            continue;
        }
#endif

        for(c=0 ; c < MAX_NUM_CARDS_IN_A_STACK ; c++)
        {
            /* Move to the next card */
            if (c!=0)
            {
                while(
                    ((*str) != ' ') &&
                    ((*str) != '\t') &&
                    ((*str) != '\n') &&
                    ((*str) != '\r')
                )
                {
                    handle_eos();
                    str++;
                }
                if ((*str == '\n') || (*str == '\r'))
                {
                    break;
                }
            }

            while ((*str == ' ') || (*str == '\t'))
            {
                str++;
            }
            if ((*str == '\n') || (*str == '\r'))
            {
                break;
            }
            card = fcs_card_user2perl(str);

            fcs_push_card_into_stack(ret, s, card);
        }
    }

    *out_state = ret_with_locations;
    return FCS_USER_STATE_TO_C__SUCCESS;
}