Example #1
0
bool CMaExpander::ReadToken(CToken *token)
{
	bool retval;

	retval = ::ReadToken(tc, &pos, token, &gex, for_include);
	if( gex.GetError() != NULL )
		throw &gex;
	return retval;
}
Example #2
0
static bool get_token(TCC_CONTEXT *tc, const char **line, CToken *token, bool for_include)
{
	bool retval;
	CException *ex = new CException;

	retval = ::ReadToken(tc, line, token, ex, for_include);
	if( ex->GetError() != NULL )
		throw ex;
	delete ex;
	return retval;
}
Example #3
0
static void handle_define(TCC_CONTEXT *tc, sym_t mid, CMacro *ma)
{
	enum {
		STA_OKAY,
		STA_LEFT_PARENTHESIS,
		STA_PARAMETER,
		STA_SEPERATOR,
		STA_TRIDOT,
	} state;

	const char *line = ma->line;
	CToken token;

	if( ! get_token(tc, &line, &token, false) )
		return;

	if(token.attr == CToken::TA_IDENT) {
		if(*line == '(') {
			CC_ARRAY<sym_t>  para_list;
			XCHAR *xc;
			const char *last_pos;
			sym_t last_para = SSID_INVALID;
			bool has_va_args = false;
		
			state = STA_LEFT_PARENTHESIS;
			line++;
			while( get_token(tc, &line, &token, false) ) {
				switch(state) {
				case STA_LEFT_PARENTHESIS:	
					if( token.id == SSID_RIGHT_PARENTHESIS) {
						state = STA_OKAY;
						goto okay;
					} else if(token.attr == CToken::TA_IDENT) {
						para_list.push_back(token.id);
						state = STA_SEPERATOR;
					} else if(token.id == SSID_TRIDOT) {
						state = STA_TRIDOT;
						continue;
					} else {
						gEx.format("\"%s\" may not appear in macro parameter list", TR(tc,token.id));
						goto error;
					}
					break;
		
				case STA_SEPERATOR:
					if(token.id == SSID_RIGHT_PARENTHESIS) {
						state = STA_OKAY;
						goto okay;
					} else if(token.id == SSID_COMMA)
						state = STA_PARAMETER;
					else if(token.id == SSID_TRIDOT) {
						state = STA_TRIDOT;
					} else {
						gEx = "macro parameters must be comma-separated";
						goto error;
					}
					break;
		
				case STA_PARAMETER:
					if(token.id == SSID_TRIDOT) {
						state = STA_TRIDOT;
						continue;
					} else if(token.attr == CToken::TA_IDENT) {
						para_list.push_back(token.id);
						state = STA_SEPERATOR;
					} else {
						gEx = "parameter name missing";
						goto error;
					}
					break;

				case STA_TRIDOT:
					if(token.id != SSID_RIGHT_PARENTHESIS) {
						gEx = "missing ')' in macro parameter list";
						throw &gEx;
					}
					has_va_args = true;
					if(last_para == SSID_COMMA || last_para == SSID_LEFT_PARENTHESIS) {
						para_list.push_back(SSID_VA_ARGS);
						last_para = SSID_VA_ARGS;
					}
					goto okay;

				default:
					assert(0);
				}
				last_para = token.id;
			}

			if(state != STA_OKAY) {
				gEx = "missing ')' in macro parameter list";
				throw &gEx;
			}
		
		okay:
			xc = (XCHAR*) malloc(sizeof(XCHAR) * strlen(line) + 4);
			ma->id         = mid;
			ma->parsed     = xc;
			ma->nr_args    = para_list.size();
			ma->va_args    = has_va_args;

			skip_blanks(line);
			last_pos = line;
			sym_t prev_sid = SSID_INVALID;

			while(  ReadToken(tc, &line, &token, &gEx, false) ) {
				if(gEx.GetError() != NULL)
					throw (&gEx);
				
				if(token.id == SSID_DUAL_SHARP) {
					if(xc == ma->parsed) {
						gEx = "'##' cannot appear at either end of a macro expansion";
						goto error;
					} else if( IS_MA_PAR0(*(xc-1)) )
						*(xc-1) |= XF_MA_PAR2;
				}
				if(prev_sid == SSID_DUAL_SHARP) {
					XCHAR *yc = xc - 3;
					while( yc >= ma->parsed && (*yc == '\t' || *yc == ' ') )
						yc--;
					xc = yc + 1;
					assert(*xc == '#' || *xc == ' ' || *xc == '\t');
				}

				if( token.attr == CToken::TA_IDENT  ) {
					int magic = 0;
					int16_t para_ord;
					static const XCHAR xflags[3] = { XF_MA_PAR0, XF_MA_PAR1, XF_MA_PAR2 };

					if( has_va_args && (token.id == last_para || token.id == SSID_VA_ARGS) )
						para_ord = ma->nr_args - 1;
					else
						para_ord = find(token.id, para_list);
					if(prev_sid == SSID_SHARP) {
						if(para_ord < 0) {
							gEx = "'#' is not followed by a macro parameter";
							goto error;
						}
						magic = 1;
						xc--;
					} else if(prev_sid == SSID_DUAL_SHARP) {
						magic = 2;
					}
					if(para_ord < 0)
						goto do_cat;
					*xc++ = para_ord | xflags[magic];
				} else {
				do_cat:
					if(prev_sid == SSID_DUAL_SHARP) {
						skip_blanks(last_pos);
					}
					join(&xc, last_pos, line);
				}
				last_pos = line;
				prev_sid = token.id;
			} /*end while*/
			*xc = 0;
		} else {
			XCHAR *xc;

			xc = (XCHAR*) malloc(sizeof(XCHAR) * strlen(line) + 4);
			ma->id      = mid;
			ma->parsed  = xc;
			ma->nr_args = CMacro::OL_M;

			skip_blanks(line);
			while(1) {
				char c = *line;
				if( iseol(c) ) {
					*xc = '\0';
					break;
				}
				*xc = c;
				xc++, line++;
			}
		}
	}
//	dump(ma->parsed);
	return;

error:
	throw &gEx;
}