实例介绍
【实例简介】
一款简易的C/C 开发环境源码,支持格式化、代码分色显示。必须与MinGW环境搭配使用,实现debug功能。 Dr.Dobb的作品,适合C/C 开发人员参考、定制自己的IDE.
【实例截图】Quincy2005ProjectV1.3.zip
【核心代码】
// ---------- build.cpp
#include "stdafx.h"
#include "Quincy.h"
#include "QuincyView.h"
#include "QuincyDoc.h"
#include "TextDocument.h"
#include "compiler.h"
#include ".\quincyview.h"
// --- recursive function to make subdirectories that don't exist
void CQuincyView::MakeSubdirectories(const CString& strPath)
{
if (!strPath.IsEmpty()) {
int ndx = strPath.ReverseFind('\\');
if (ndx != -1)
MakeSubdirectories(strPath.Left(ndx));
struct _stat sbf;
if (_stat(strPath, &sbf) != 0 || (sbf.st_mode & _S_IFDIR) == 0)
_mkdir(strPath);
}
}
// ----- project Build command
void CQuincyView::BuildProject(bool bDoExecute, bool bDoStep)
{
int ndx = m_strTargetFile.ReverseFind('\\');
if (ndx != -1) {
CString strPath = m_strTargetFile.Left(ndx);
struct _stat sbf;
// see if the target path exists and is a directory
if (_stat(strPath, &sbf) != 0 || (sbf.st_mode & _S_IFDIR) == 0) {
if (AfxMessageBox("Path " strPath "\\ does not exist. Make it?", MB_YESNO) == IDNO)
return;
MakeSubdirectories(strPath);
}
}
CDocument* pDoc = GetDocument();
ASSERT(pDoc != 0);
const CString& strPath = pDoc->GetPathName();
if (!strPath.IsEmpty())
pDoc->OnSaveDocument(strPath);
theApp.GetCompiler().BuildTarget(m_strTargetFile,
bDoExecute ? (bDoStep ? Compiler::step : Compiler::run) : Compiler::none);
}
bool CQuincyView::TargetIsCurrent(bool bForceRebuild)
{
CListCtrl& rlist = GetListCtrl();
int count = rlist.GetItemCount();
if (count == 0)
return true;
bool bIsCurrent = !bForceRebuild;
theApp.SetBuildingCPP(false);
theApp.GetCompiler().ClearArrays();
theApp.GetCompiler().ClearErrorLog();
theApp.GetCompiler().AddLogEntry("Checking dependencies");
// ---- iterate through the source files in the project
for (int nItem = 0; nItem < count; nItem ) {
CString strSrcFile = rlist.GetItemText(nItem, 0);
bool bCpp = strSrcFile.Right(4).CompareNoCase(".cpp") == 0;
if (bCpp)
theApp.SetBuildingCPP(true);
bool bLib = (strSrcFile.Right(2).CompareNoCase(".a") == 0);
bool bRc = strSrcFile.Right(3).CompareNoCase(".rc") == 0;
bool bRes = strSrcFile.Right(4).CompareNoCase(".res") == 0;
bool bDef = strSrcFile.Right(4).CompareNoCase(".def") == 0;
if (!bLib && !bRes)
// ---- if the source file is in memory and modified, save it
bIsCurrent &= !UpdateSourceFile(strSrcFile);
if (bLib) {
// --- object library, add to compiler's list of files to include in link
theApp.GetCompiler().AddLibraryFile(strSrcFile);
if (!bForceRebuild && bIsCurrent) {
CString strLibPathFile;
const CStringArray& rstrLibs = theApp.GetLibraryArray();
int nSize = rstrLibs.GetSize();
int i;
bool isLib =
(strSrcFile.Left(3).CompareNoCase("lib") == 0 && strSrcFile.Right(2).CompareNoCase(".a") == 0);
// ---- test to see if the library file exists
for (i = 0; i < nSize; i ) {
if (isLib)
strLibPathFile = rstrLibs[i] "\\" strSrcFile;
else
strLibPathFile = strSrcFile;
if (_access(strLibPathFile, 0) == 0)
break;
}
// ---- test to see if the library file exists and is newer than the executable
if (i < nSize && theApp.CompareFileTimes(m_strTargetFile, strLibPathFile) < 0)
bIsCurrent = false;
}
continue;
}
if (bDef && bIsCurrent) {
bool bCompileDef = false;
if (!bForceRebuild && bIsCurrent) {
// if target older than def, compile
bCompileDef = theApp.CompareFileTimes(m_strTargetFile, strSrcFile) < 0;
if (!bCompileDef) {
const Compiler& rc = theApp.GetCompiler();
const CString& strTg = rc.GetTargetName();
CString ext("a");
CString strImportLib =
theApp.GetFileName(strTg.Left(strTg.GetLength() - 3) ext);
// if import lib older than def, compile
bCompileDef = theApp.CompareFileTimes(strImportLib, strSrcFile) < 0;
}
}
if (bForceRebuild || bCompileDef) {
theApp.GetCompiler().AddSourceFile(strSrcFile);
bIsCurrent = false;
}
continue;
}
// ---- make a copy of the source file name without the path or file extension
CString strSrcName = theApp.GetFileName(strSrcFile.Left(strSrcFile.ReverseFind('.')));
// ==================================================
CString strObjFile = theApp.GetCompiler().MakeObjectFileName(strSrcName);
if (bRc) {
// --- compiling .rc into .o
theApp.GetCompiler().AddObjectFile(strObjFile);
if (bForceRebuild || theApp.CompareFileTimes(strObjFile, strSrcFile) < 0) {
theApp.GetCompiler().AddSourceFile(strSrcFile);
bIsCurrent = false;
}
else if (theApp.CompareFileTimes(m_strTargetFile, strObjFile) < 0)
bIsCurrent = false;
continue;
}
if (bRes) {
// --- linking .res into .exe (bcc) or compiling res or rc into .o (gcc)
CString strResFile(strSrcName ".res");
// --- compiling .res into .o
theApp.GetCompiler().AddObjectFile(strObjFile);
if (bForceRebuild || theApp.CompareFileTimes(strObjFile, strSrcFile) < 0) {
theApp.GetCompiler().AddSourceFile(strResFile);
bIsCurrent = false;
}
if (theApp.CompareFileTimes(m_strTargetFile, strObjFile) < 0)
bIsCurrent = false;
continue;
}
// --- c or cpp source file
// ---- make a copy of the source file's object file specification
strObjFile = theApp.GetCompiler().MakeObjectFileName(strSrcName);
// ---- add the object file to the compiler's link list
theApp.GetCompiler().AddObjectFile(strObjFile);
// ---- if the object file has no path info, add it from the target spec
if (strObjFile.Find("\\") == -1) {
// --- extract path info from target spec
int ndx = m_strTargetFile.ReverseFind('\\');
strObjFile = m_strTargetFile.Left(ndx 1) strObjFile;
}
// ---- test for rebuild all or if the source file is newer than the object or
// an included file is newer than the object file.
if ( IncludesAreNewer(strSrcFile, strObjFile)
|| bForceRebuild || theApp.CompareFileTimes(strObjFile, strSrcFile) < 0 ) {
// ---- queue the source file to be compiled
theApp.GetCompiler().AddSourceFile(strSrcFile);
bIsCurrent = false;
m_IncludesChecked.RemoveAll();
}
// ---- test to see if the object file is newer than the executable
else if (theApp.CompareFileTimes(m_strTargetFile, strObjFile) < 0)
bIsCurrent = false;
}
if (bIsCurrent) {
theApp.GetCompiler().ClearArrays();
if (!bForceRebuild) {
CString msg = theApp.GetFileName(m_strTargetFile);
msg = " is up to date";
theApp.GetCompiler().AddLogEntry(msg);
}
}
return bIsCurrent;
}
// ---- if the named source file is in memory and modified, save it
bool CQuincyView::UpdateSourceFile(CString& strSrcFile)
{
CTextDocument* pDoc = theApp.GetTextDocument(strSrcFile);
bool bUd = pDoc != 0 && pDoc->IsModified();
if (bUd)
pDoc->OnSaveDocument(strSrcFile);
return bUd;
}
bool CQuincyView::IncludesAreNewer(CString& strSrcFile, CString& strObjFile)
{
CStdioFile ifile(strSrcFile, CFile::modeRead);
char buf[81];
while (ifile.ReadString(buf, 80) != 0) {
// ---- parse the line for an #include statement with "" delimiters
char *cp = buf;
while (isspace(*cp))
cp ;
if (*cp != '#')
continue;
while (isspace(*cp))
cp ;
if (strncmp(cp, "include", 7) != 0)
continue;
cp = 7;
while (isspace(*cp))
cp ;
if (*cp != '"')
continue;
cp ;
// ---- extract the filename of the included file
while (isspace(*cp))
cp ;
char ifilename[81];
char *cp2 = ifilename;
while (*cp != '"' && !isspace(*cp) && cp2 < ifilename 80)
*cp2 = *cp ;
*cp2 = '\0';
CString strInclFile(ifilename);
// ---- see if this file has already been checked
int nSize = m_IncludesChecked.GetSize();
int i;
for (i = 0; i < nSize; i )
if (strInclFile == m_IncludesChecked[i])
break;
if (i < nSize)
continue;
m_IncludesChecked.Add(strInclFile);
// ---- if the included source file is in memory and modified, save it
if (UpdateSourceFile(strInclFile))
return true;
// ---- see if the included file is in one of the -I specifications
const CStringArray& rstrIncludes = theApp.GetIncludeArray();
nSize = rstrIncludes.GetSize();
i = 0;
if (nSize && (_access(strInclFile, 0) != 0)) {
// --- not a local header
for (; i < nSize; i ) {
strInclFile = rstrIncludes[i] "\\" theApp.GetFileName(strInclFile);
if (_access(strInclFile, 0) == 0)
break;
}
}
if (i == nSize) // not in -I, must be system header
continue;
// ---- compare the times of the two files
if (theApp.CompareFileTimes(strInclFile, strObjFile) > 0)
return true;
// ---- now check nested includes
if (IncludesAreNewer(strInclFile, strObjFile))
return true;
}
return false;
}
void CQuincyView::MakeTargetName()
{
CQuincyDoc* pDoc = static_cast<CQuincyDoc*>(GetDocument());
ASSERT(pDoc != 0);
m_strTargetFile = pDoc->TargetName();
if (m_strTargetFile.Find('\\') == -1 || m_strTargetFile[1] != ':') {
// --- incomplete or no path information in the target, prefix with the path of the project
CString strProjPath = pDoc->GetPathName();
// strip the file name
int nIndex = strProjPath.ReverseFind('\\');
if (nIndex == -1)
nIndex = strProjPath.ReverseFind(':');
if (nIndex != -1)
strProjPath = strProjPath.Left(nIndex 1);
// ----- build the target file specification
m_strTargetFile = strProjPath pDoc->TargetName();
}
}
bool CQuincyView::CanExecuteProgram(bool bDoStep)
{
MakeTargetName();
CString msg = theApp.GetFileName(m_strTargetFile);
bool bExeExists = _access(m_strTargetFile, 0) == 0;
bool bIsCurrent = TargetIsCurrent();
if (bExeExists) {
// ---- exe file exists
if (bIsCurrent)
return true;
msg = " is out of date. Rebuild?";
}
else
// ---- exe file does not exist
msg = " does not exist. Build?";
int rtn = AfxMessageBox(msg, MB_YESNOCANCEL | MB_ICONQUESTION);
if (rtn == IDYES)
BuildProject(true, bDoStep); // ???????
else if (rtn != IDCANCEL && bExeExists)
return true;
return false;
}
void CQuincyView::OnRun()
{
if (!theApp.ExecuteRunningProgram())
if (CanExecuteProgram(false))
theApp.StartProgram(m_strTargetFile);
}
void CQuincyView::OnDebugStep()
{
if (!theApp.StepProgram())
if (CanExecuteProgram(true))
theApp.DebugProgram(m_strTargetFile, true);
}
void CQuincyView::OnBuild()
{
MakeTargetName();
if (!TargetIsCurrent())
BuildProject(false, false);
}
void CQuincyView::OnBuildAll()
{
MakeTargetName();
TargetIsCurrent(true);
BuildProject(false, false);
}
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论