예제 #1
0
static CC_STRING MakeSemaName(const CC_STRING& filename)
{
	CC_STRING sname;
	const char *p;
	char c;

	for(p = filename.c_str(); (c = *p) != 0; p++) {
		if(c == '/' || c == '\\')
			sname += '-';
		else if(c == '.')
			c += '@';
		else
			sname += c;
	}
	return sname;
}
예제 #2
0
파일: fsl.cpp 프로젝트: yodamaster/ycpp
int fsl_mkdir(const CC_STRING& dirname)
{
    CC_STRING newdir;
	char *p, *dir;
	struct stat stb;
	int retval = 0;

	if( dirname[0] != '/' ) {
        newdir = fsl_realpath(dirname);
		if( newdir.isnull() ) {
			retval = -EINVAL;
			goto fail;
		}
	} else
		newdir = dirname.c_str();

	dir = (char*)newdir.c_str();
	if(newdir[0] == '/')
		p = (char*)newdir.c_str() + 1;
	else
		p = (char*)newdir.c_str();
	while(1) {
		char c = *p;
		if(c == 0 || c == '/') {
			const char saved_char = *p;
			*p = '\0';
			if(stat(dir, &stb) != 0) {
				if ( mkdir(dir, 0775) != 0 ) {
					retval = -errno;
					goto fail;
				}
			} else if( ! S_ISDIR(stb.st_mode) ) {
				retval = -EEXIST;
				goto fail;
			}
			if(c == '\0')
				break;
			*p = saved_char;
		}
		p ++;
	}

fail:
	return retval;
}
예제 #3
0
void Parser::IncludedFile::save_conditional(Cond *c, int rh)
{
	CC_STRING tmp;
	static const char *directives[] = {NULL, "if", "elif", "else"};

	assert(c->type <= Cond::CT_ELSE);
	if(directives[c->type]) {
		tmp.Format("  %-4u %s %s ", rh, directives[c->type], (c->value ? "true" : "false"));
		cr_text += tmp;

		if(c->boff)
			tmp.Format("%u,%d ", c->begin, c->boff);
		else
			tmp.Format("%u ", c->begin);
		cr_text += tmp;

		if(c->eoff)
			tmp.Format("%u,%d\n", c->end, c->eoff);
		else
			tmp.Format("%u\n", c->end);
		cr_text += tmp;
	}
}
예제 #4
0
파일: fsl.cpp 프로젝트: yodamaster/ycpp
CC_STRING fsl_realpath(const CC_STRING& src)
{
    char dest[4096];
	const char *s;
	char *d;
	int state = 0;
	
	if( src[0] != '/' ) {
		(void) getcwd(dest, sizeof(dest));
		d = dest + strlen(dest);
		*d ++ = '/';
	} else
		d = dest;
	s = src.c_str();
	while(1) {
		const char c = *s++;
		switch(state) {
		case 0:
			switch(c) {
			case '\0':    *d = c; state = 1; break;
			case UNIX_DD:
			case DOS_DD:  *d++ = c; state = 3; break;
			case '.':     *d++ = c; state = 4; break;
			default:      *d++ = c; break;
			}
			break;
		case 1:	
			#if !HAVE_TRAILING_SPLASH
				if( *(d-1) == UNIX_DD )
					*--d   = '\0';
			#else
				if( *(d-1) != UNIX_DD )
					*d++ = UNIX_DD, *d = '\0';
			#endif
			goto done;
		case 2:	goto fail;
		case 3:	
			switch(c) {
			case '\0':    *d = c; state = 1; break;
			case UNIX_DD:
			case DOS_DD:  break;
			case '.':     *d++ = c; state = 4; break;
			default:      *d++ = c; state = 0; break;
			}
			break;
		case 4:
			switch(c) {
			case '\0':    *d = c; state = 1; break;
			case UNIX_DD:
			case DOS_DD:  state = 3; d -= 1; break;
			case '.':     *d++ = c; state = 5; break;
			default:      *d++ = c; state = 0; break;
			}
			break;
		case 5:
			switch(c) {
			case '\0':    state = 1; goto uplevel;
			case UNIX_DD:
			case DOS_DD:  state = 3; 
				{
					char *t;
				uplevel:
					t = __stdpath_uplevel(dest, d);
					if(t == NULL)
						goto fail;
					d = t;
					if(c == '\0') *d = '\0';
					break;
				}
			default:      state = 2; break;
			}
			break;
		}
	}
done:
	return dest;
fail:
	return NULL;
}
예제 #5
0
파일: macro.cpp 프로젝트: yodamaster/ycpp
CC_STRING CMaExpander::Expand_FLM(CMacro *ma)
{
	CC_STRING outs;
	CC_ARRAY<CC_STRING> margs;
	CC_STRING carg;
	const char *p = pos;
	int level;

	skip_blanks(p);
	if( iseol(*p) ) {
		gex.format("Macro \"%s\" expects arguments", TR(tc,ma->id));
		throw &gex;
	}
	if( *p != '(' ) {
		gex = "Macro expects '('";
		throw &gex;
	}

	p++;
	skip_blanks(p);
	level = 1;
	while( 1 ) {
		if( iseol(*p) )
			break;

		if( *p == ','  ) {
			if( level == 1 && ( ! ma->va_args || (margs.size() + 1 < ma->nr_args) ) ) {
				Trim(carg);
				margs.push_back(carg);
				carg.clear();
			} else {
				carg += ',';
				skip_blanks(p);
			}
		} else if(*p == '(') {
			level ++;
			carg += '(';
		} else if(*p == ')') {
			level --;
			if(level == 0) {
				p++;
				Trim(carg);
				margs.push_back(carg);
				carg.clear();
				break;
			} else
				carg += ')';
		} else {
			carg += *p;
		}
		p++;
	}
	pos = p;

	XCHAR *xc;
	CC_STRING s;
	size_t n;

	n = ma->nr_args;
	assert(n != CMacro::OL_M);
	if(n != margs.size()) {
		if( ma->va_args && margs.size() + 1 == n ) {
			margs.push_back(CC_STRING(""));
		} else {
			gex.format("Macro \"%s\" requires %u arguments, but %u given",
				TR(tc,ma->id), n, margs.size() );
			throw &gex;
		}
	}

	for(xc = ma->parsed; *xc != 0; xc++) {
		if(IS_MA_PAR2(*xc) || IS_MA_PAR0(*xc)) {
			const CC_STRING& carg = margs[(uint8_t)*xc];
			CMaExpander expander2(tc, carg.c_str(), for_include);
			CC_STRING tmp;
			tmp = expander2.TryExpand();
			s += tmp;
		} else if(IS_MA_PAR1(*xc)) {
			const CC_STRING& carg = margs[(uint8_t)*xc];
			s += '"';
			s += carg;
			s += '"';
		} else {
			s += (char) *xc;
		}
	}
	outs += s;

	return outs;
}
예제 #6
0
static bool GetRealPath(const CC_STRING& name, CC_STRING& opath)
{
/*  Use my own function rather than realpath since realpath will expand symblic links */
	opath = fol_realpath(name);
	return ! opath.isnull() ;
}
예제 #7
0
int Parser::Compute(const char *line)
{
	static const char opp[] = { '<', '=', '>', 'X'};
	enum {
		STAT_INIT,
		STAT_OPR1,
		STAT_OPR2,
		STAT_OPND,
		STAT_DEFINED,  /* defined    */
		STAT_DEFINED1, /* defined(   */
		STAT_DEFINED2, /* defined(X  */
	} state;
	CC_STACK<sym_t>  opr_stack;
	CC_STACK<SynToken>  opnd_stack;
	sym_t last_opr = SSID_SHARP;
	SynToken last_token;
	char sign;
	const char *symbol = NULL;
	LOG_VERB dml = LOGV_DEBUG;
	CC_STRING expansion;

	if(!gvar_preprocess_mode) {
		/*
		 *  Keep `#if 0' blocks which are usually user comments.
		 */
		char *copied_line = strdup(line);
		const char *first = strtok(copied_line, " \t");
		int ignore = 0;
		/* Simple code and work properly in most cases */
		if(first && first[0] == '0')
			ignore = 1;
		free(copied_line);
		if(ignore)
			return TSV_X;
	}

	expansion = ExpandLine(intab, false, line, errmsg);
	if( !errmsg.isnull() ) {
		return TSV_X;
	}

	ReadReq req(expansion.c_str());
	SynToken& token = req.token;
	opr_stack.push(SSID_SHARP);
	log(dml, "PUSH OPR: #\n");
	sign = 0;
	state = STAT_OPR1;
	while(1) {
		sym_t  opr;
		const char *last_pos = req.cp;
		int ret;

		ret = ReadToken(intab, &req, false);
		if( ret == 0 )
			break;
		else if( ret < 0 )
			goto error;

		if( token.attr == SynToken::TA_CHAR )
			token.attr = SynToken::TA_INT;
		if( sign != 0 ) {
			if(token.attr != SynToken::TA_UINT && token.id != SSID_DEFINED) {
				errmsg.Format("%s following %c", TR(intab,token.id), sign);
				goto error;
			}
			if(sign == '-') {
				token.attr = SynToken::TA_INT;
				token.i32_val = -token.i32_val;
			}
			sign = 0;
		} else if( (token.id == SSID_ADDITION || token.id == SSID_SUBTRACTION) &&  CheckPrevOperator(last_opr)) {
			sign = token.id == SSID_ADDITION ? '+' : '-';
			goto next;
		}

		switch(state) {
		case STAT_INIT:
			if(IsOperator(token.id))
				state = STAT_OPR1;
			else if(token.id == SSID_DEFINED)
				state = STAT_DEFINED;
			else if(token.attr == SynToken::TA_IDENT)
				state = STAT_OPND;
			break;
		case STAT_OPND:
			if(IsOperator(token.id))
				state = STAT_OPR1;
			else {
				errmsg = "Adjacent operands";
				goto error;
			}
			break;
		case STAT_OPR1:
			if(IsOperator(token.id))
				state = STAT_OPR2;
			else if(token.id == SSID_DEFINED)
				state = STAT_DEFINED;
			else
				state= STAT_INIT;
			break;
		case STAT_OPR2:
			if(IsOperator(token.id)) {
			} else if(token.id == SSID_DEFINED)
				state = STAT_DEFINED;
			else
				state = STAT_INIT;
			break;
		case STAT_DEFINED:
			if(token.id == SSID_LEFT_PARENTHESIS)
				state = STAT_DEFINED1;
			else if(token.attr == SynToken::TA_IDENT) {
				CheckSymbolDefined(last_pos, false, &token);
				if(!errmsg.isnull())
					goto error;
				state = STAT_INIT;
			}
			break;
		case STAT_DEFINED1:
			if(token.attr == SynToken::TA_IDENT) {
				state = STAT_DEFINED2;
				symbol = last_pos;
			} else {
				errmsg = "Syntax error: ";
				goto error;
			}
			break;
		case STAT_DEFINED2:
			if(token.id == SSID_RIGHT_PARENTHESIS) {
				CheckSymbolDefined(symbol, false, &token);
				if(!errmsg.isnull())
					goto error;
				state = STAT_INIT;
				opnd_stack.push(token);
				opr = token.id;
				goto next;
			} else {
				errmsg = "Unmatched (";
				goto error;
			}
			break;
		}
		if(state == STAT_DEFINED || state == STAT_DEFINED1 || state == STAT_DEFINED2)
			goto next;

		if( token.id == SynToken::TA_UINT || token.id == SynToken::TA_INT )
			log(dml, "Current: %u\n", token.u32_val);
		else
			log(dml, "Current: %s\n", TR(intab,token.id));
//		log(dml, "OPR  Stack: \n", opr_stack);
//		log(dml, "OPND Stack: \n", opnd_stack);
		opr = token.id;
		if( IsOperator(opr) ) {
			sym_t opr0;
			int result;
again:
			opr0 = opr_stack.top();
			result = intab->opMat.Compare(opr0, opr);
			log(dml, "Compare: %s %c %s\n", TR(intab,opr0),opp[1+result],TR(intab,opr));
			switch(result) {
			case _EQ:
				opr_stack.pop(opr0);
				break;
			case _GT:
				opr_stack.pop(opr0);
				if( ! CalculateOnStackTop(opr0, opnd_stack, opr_stack) ) {
					goto error;
				}
				goto again;
			case _LT:
				opr_stack.push(opr);
				break;
			case _XX:
				errmsg.Format("Cannot compare \"%s\" and \"%s\"", TR(intab,opr0), TR(intab,opr));
				log(LOGV_ERROR, "*ERROR* %s\n", errmsg.c_str());
				goto error;
			}
		} else {
			opnd_stack.push(token);
		}

	next:
		last_opr = opr;
	}

	do {
		sym_t opr0;
		int result;

		if( ! opr_stack.pop(opr0) )
			goto error;
		result = intab->opMat.Compare(opr0, SSID_SHARP);
		log(dml, "Compare: %s %c #\n", TR(intab,opr0),opp[result]);
		switch(result) {
		case _EQ:
			break;
		case _GT:
			if( ! CalculateOnStackTop(opr0, opnd_stack, opr_stack) ) {
				goto error;
			}
			break;
		default:
			log(LOGV_ERROR, "%s:%u: Bad expression\n", __func__,  __LINE__);
			errmsg = "[1] Bad expression";
			goto error;
		}
	} while( opr_stack.size() != 0 );

	if( opnd_stack.size() != 1 ) {
		log(LOGV_ERROR, "%s:%u: Bad expression\n", __func__,  __LINE__);
		errmsg = "[2] Bad expression";
		goto error;
	}

	if( opnd_stack.top().attr == SynToken::TA_IDENT ) {
		if( gvar_preprocess_mode ) {
			return TSV_0;
		}
		return TSV_X;
	}
	log(dml, "Numberic Value: %u\n", opnd_stack.top().i32_val);;
	return !!opnd_stack.top().i32_val;

error:
	log(LOGV_ERROR, "*Error* %s\n", errmsg.c_str());
	return gvar_preprocess_mode ? TSV_0 : TSV_X;
}
예제 #8
0
/*  Parse the input file and update the global symbol table and macro table,
 *  output the stripped file contents to devices if OUTFILE is not nil.
 *
 *  Returns a pointer to the error messages on failure, or nil on success.
 */
bool Parser::DoFile(InternalTables *intab, size_t num_preprocessors, File *infile, ParserContext *ctx)
{
	bool ignored;
	FILE *out_fp;
	bool retval = false;
	CC_STRING bak_fname, out_fname;
	struct stat    stb;
	struct utimbuf utb;

	if(ctx) {
		ignored = ctx->check_ignore(infile->name);
		if( ignored && ! has_dep_file() )
			return true;
	} else
		ignored = false;

	if( stat(infile->name, &stb) == 0 ) {
		utb.actime  = stb.st_atime;
		utb.modtime = stb.st_mtime;
	}
	if( ! infile->Open() ) {
		errmsg.Format("Cannot open \"%s\" for reading\n");
		return false;
	}

	out_fp = NULL;

	if(ctx != NULL && ctx->outfile != ParserContext::OF_NULL ) {
		if( ctx->outfile == ParserContext::OF_STDOUT )
			out_fp = stdout;
		else {
#if SANITY_CHECK
			assert( ! ctx->baksuffix.isnull() );
#endif
			if( ctx->baksuffix[0] != ParserContext::MAGIC_CHAR )
				bak_fname = infile->name + ctx->baksuffix;
			else
				out_fname = infile->name;

			int fd;
			char tmp_outfile[32];
			strcpy(tmp_outfile, "@cl@-XXXXXX");
			fd = mkstemp(tmp_outfile);
			if( fd < 0 ) {
				errmsg.Format("Cannot open \"%s\" for writing\n", tmp_outfile);
				infile->Close();
				return false;
			}
			out_fp = fdopen(fd, "wb");
			out_fname = tmp_outfile;
		}
	}

	if(ctx == NULL)
		memset(writers, 0, sizeof(writers));
	else {
		writers[VCH_CL] = NULL;
		if(!ctx->of_array[VCH_DEP].isnull())
			writers[VCH_DEP] = gvar_file_writers[VCH_DEP];
		if(!ctx->of_array[VCH_CV].isnull())
			writers[VCH_CV] = gvar_file_writers[VCH_CV];
	}

	if( num_preprocessors >= COUNT_OF(Parser::preprocessors) )
		num_preprocessors  = COUNT_OF(Parser::preprocessors);
	Reset(intab, num_preprocessors, ctx);

	if(has_dep_file())
		AddDependency("", infile->name);

	PushIncludedFile(infile, out_fp, COUNT_OF(Parser::preprocessors), false, conditionals.size());

	if(ctx != NULL) {
		GetCmdLineIncludeFiles(ctx->imacro_files, 2);
		GetCmdLineIncludeFiles(ctx->include_files, COUNT_OF(preprocessors));
	}

	if( ! RunEngine(0) )
		goto error;

	SaveDepInfo(deptext);
	if( conditionals.size() != 0 )
		errmsg = "Unmatched #if";
	else
		retval = true;

error:
	if(!retval) {
		if(included_files.size() > 0) {
			CC_STRING tmp;
			tmp.Format("%s:%u:  %s\n%s\n", GetCurrentFileName().c_str(), GetCurrentLineNumber(), pline.from.c_str(), GetError());
			errmsg = tmp;
		}
		#if 0
		IncludedFile *ilevel;
		while(included_files.size() > 0) {
			ilevel = PopIncludedFile();
			if(infile != ilevel->ifile)
				delete ilevel;
		}
		#endif
	}

	if(out_fp != NULL && out_fp != stdout)
		fclose(out_fp);

	if( retval && ctx != NULL && ! ignored ) {
		CC_STRING semname;
		sem_t *sem;

		semname = MakeSemaName(infile->name);
		sem = sem_open(semname.c_str(), O_CREAT, 0666, 1);
		sem_wait(sem);

		if( ! bak_fname.isnull() )
			rename(infile->name, bak_fname);
		if( ! out_fname.isnull() ) {
			rename(out_fname, infile->name);
			utime(infile->name.c_str(), &utb);
		}

		sem_post(sem);
		sem_unlink(semname.c_str());
	} else if( ! out_fname.isnull() )
		unlink(out_fname.c_str());

	return retval;
}