BOOL CFileBasedProjectTemplateItem::InitItem(LPCTSTR lpszPath, CImageList &ImageList32, CImageList &ImageList16)
{
	m_strPath = lpszPath;

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//extract description, if available
	CTextSourceFile TextFile;
	if (TextFile.Create(lpszPath))
	{
		LPCTSTR lpLine;
		int nLength;
		if (TextFile.GetNextLine(lpLine, nLength))
		{
			CString strLine(lpLine, nLength);
			CString strKey(_T("%DESCRIPTION: "));
			CString strStartOfLine = strLine.Left(strKey.GetLength());
			strStartOfLine.MakeUpper();

			if (strStartOfLine == strKey)
				m_strDescription = strLine.Right(strLine.GetLength() - strKey.GetLength());
		}
	}

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//generate title
	m_strTitle = CPathTool::GetFileTitle(m_strPath);

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	//add image to image list and remember index
	HICON hIcon = theApp.LoadIcon(IDR_LATEXDOCTYPE);
	m_nImageIndex = hIcon ? ImageList32.Add(hIcon) : -1;
	ImageList16.Add(hIcon);

	return TRUE;
}
Ejemplo n.º 2
0
/** This function analyses a given source file and count the lines of bCode, comments etc...
 */
void Counter::countLines(wxTextFile& file, CounterRule* pRule, int &total_lines, int &code_lines,
                         int &comment_lines, int &codecomments_lines, int &empty_lines)
{
    bool bDelimitedCommentMode = false;
    total_lines += file.GetLineCount();
    for (unsigned int i=0; i<file.GetLineCount(); ++i)
    {
        // Trim space
        wxString strLine(file[i]);
        strLine = strLine.Trim(true);
        strLine = strLine.Trim(false);

        bool bComment = false;
        bool bCode = false;
        if (strLine.IsEmpty())
            ++empty_lines;
        else
        {
            analyseLine(pRule, strLine, bComment, bCode, bDelimitedCommentMode);
            if (bComment&&bCode) ++codecomments_lines;
            else if (bComment) ++comment_lines;
            else if (bCode) ++code_lines;
        }
    }// End for
}
Ejemplo n.º 3
0
void CHTRichEditCtrl::Add(LPCTSTR pszMsg, int iLen)
{
	if (m_hWnd == NULL){
		CString strLine(pszMsg);
		m_astrBuff.Add(strLine);
	}
	else{
		FlushBuffer();
		AddLine(pszMsg, iLen);
	}
}
Ejemplo n.º 4
0
void CHTRichEditCtrl::AddEntry(LPCTSTR pszMsg)
{
	CString strLine(pszMsg);
	strLine += _T("\n");
	if (m_hWnd == NULL){
		m_astrBuff.Add(strLine);
	}
	else{
		FlushBuffer();
		AddLine(strLine, strLine.GetLength());
	}
}
Ejemplo n.º 5
0
EC_U32 ECConfig::WriteToFile()
{
    if(EC_Err_None == m_sFile.Open((EC_PCHAR)"rt"))
    {
        for(EC_U32 i = 0; i < m_nCount; ++i)
        {
            ECString strKey(m_pConfigItem[i].m_sKey);
            ECString strVal(m_pConfigItem[i].m_sVal);
            ECString strLine(strKey + strVal + (EC_PCHAR)"\n");
            m_sFile.WriteBuffer(strLine.ToCStr(), strLine.Length(), 1);
        };

        m_sFile.Close();
    }

    return EC_Err_None;
}
LLDBBreakpoint::Ptr_t LLDBNewBreakpointDlg::GetBreakpoint()
{
    if ( m_checkBoxFileLine->IsChecked() ) {
        
        long nLine = 0;
        wxString strLine( m_textCtrlLine->GetValue() );
        strLine.ToCLong( &nLine );
        LLDBBreakpoint::Ptr_t bp( new LLDBBreakpoint(m_textCtrlFile->GetValue(), nLine) );
        return bp;
        
    } else if ( m_checkBoxFuncName->IsChecked() ) {
        LLDBBreakpoint::Ptr_t  bp( new LLDBBreakpoint(m_textCtrlFunctionName->GetValue()) );
        return bp;
        
    } else {
        return LLDBBreakpoint::Ptr_t( NULL );
    }
}
bool HbSmileyThemeParser::parseDefinitionFile(const QString& fileName, HbSmileyTheme &theme)
{
    QFile file(fileName);

    if (!file.exists()) {
#ifdef HB_SMILEY_THEME_TRACES
        qDebug() << "HbSmileyThemeParser: File does not exist:" << fileName;
#endif
        return false;
    }

    if (!file.open(QFile::ReadOnly | QFile::Text)) {
#ifdef HB_SMILEY_THEME_TRACES
        qDebug() << "HbSmileyThemeParser: File opening failed:" << fileName;
#endif
        return false;
    }

    QByteArray line;

    while(!file.atEnd()) {
        line=file.readLine().simplified();
        if (line.isEmpty() || line.at(0) == '#') {
            continue;
        }

        QString strLine(line);
        QStringList strList = strLine.split(QRegExp("\\s+"));
        QString smiley = strList.first();
        strList.removeFirst();

        if (!strList.isEmpty()) {
            theme.insert(smiley,strList);
        } else {
#ifdef HB_SMILEY_THEME_TRACES
            qDebug() << "HbSmileyThemeParser: Parsing error: "
                     <<  fileName << "Smiley: " << smiley << "doesn't contain any patterns!";
#endif
            return false;
        }
    }

    return !theme.isNull();
}
Ejemplo n.º 8
0
// 切割字符串
std::vector<CString> Split(LPCTSTR pszStrLine, LPCTSTR pszDelim)
{
	std::vector<CString> vecReturn;
	CString strLine(pszStrLine), strDelim(pszDelim);
	int nPos = strLine.Find(strDelim);
	while (-1 != nPos)
	{
		if (nPos > 0)
		{
			vecReturn.push_back(strLine.Left(nPos));
		}
		strLine.Delete(0, nPos + strDelim.GetLength());
		nPos = strLine.Find(strDelim);
	}
	if (!strLine.IsEmpty())
	{
		vecReturn.push_back(strLine);
	}
	return vecReturn;
}
Ejemplo n.º 9
0
//加载配置文件
BOOL CDataBaseManager::LoadConfig()
{
	wifstream configFile(L"C:\\IOServerConfig.cfg");
	if (!configFile.is_open())
	{
		cout << "无法打开数据库配置文件" << endl;
		return FALSE;
	}
	while (!configFile.eof())
	{
		wchar_t wcsLine[512] = { 0 };
		configFile.getline(wcsLine, 512);
		wstring strLine(wcsLine);
		int nFlag = strLine.find(L":");
		wstring strKey = strLine.substr(0, nFlag);
		wstring strValue = strLine.substr(nFlag + 1);
		if (strKey.compare(L"IP") == 0)
		{
			m_IP = strValue;
		}
		else if (strKey.compare(L"PORT") == 0)
		{
			m_PORT = strValue;
		}
		else if (strKey.compare(L"DBNAME") == 0)
		{
			m_DBNAME = strValue;
		}
		else if (strKey.compare(L"DBUSER") == 0)
		{
			m_DBUSER = strValue;
		}
		else if (strKey.compare(L"DBPWD") == 0)
		{
			m_DBPWD = strValue;
		}
	}


	return TRUE;
}
void Hypergraph::loadHypergraph(const QString &fileName)
{
	ifstream graphFile (fileName.toStdString().c_str());
	graphFile >>_nVertices;
	setNumOfVertices(_nVertices);
	string line;
	_edges.clear();
	while(getline(graphFile,line))
	{
		stringstream strLine(line);
		HyperEdge e(0);
		int fibIdx;
		while (strLine >>fibIdx)
		{
			e.push_back(fibIdx);
		}
		if (!e.empty())
		{
			_edges.push_back(e);
		}
	}
	graphFile.close();
}
BOOL KFileFormat::_IsCommentInvalid(LPCTSTR lpOristr, int nIndex)
{
    CString strLine(lpOristr);
    std::vector<int> vecPos;
    int nStartPos = 0;
    while (1)
    {
        int nIndex = strLine.Find(QUATATION, nStartPos);
        if (-1 == nIndex)
            break;

        if (nIndex > 0 && ('\'' != strLine.GetAt(nIndex - 1) || '\\' != strLine.GetAt(nIndex - 1)))
            vecPos.push_back(nIndex);
        
        nStartPos = nIndex + 1;
    }
    for (int i = 0; i < (int)vecPos.size(); i += 2)
    {
        if (nIndex > vecPos[i] && (i + 1 < (int)vecPos.size() && nIndex < vecPos[i + 1]))
            return TRUE;
    }
    return FALSE;
}
Ejemplo n.º 12
0
// 初始化更新列表
BOOL CUpdaterApp::_InitFileList()
{
	BOOL bReturn(FALSE);

	CString strFileList(m_szServer);
	strFileList += _T("/Filelist.txt");

	CInternetSession sess;
	sess.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 5000);
	sess.SetOption(INTERNET_OPTION_SEND_TIMEOUT, 1000);
	sess.SetOption(INTERNET_OPTION_RECEIVE_TIMEOUT, 5000);
	sess.SetOption(INTERNET_OPTION_DATA_SEND_TIMEOUT, 1000);
	sess.SetOption(INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, 5000);
	sess.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 1);

	try
	{
		CHttpFile* pHttpFile = (CHttpFile*)sess.OpenURL(strFileList, 1, INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_TRANSFER_ASCII, NULL, 0);
		if (pHttpFile)
		{
			DWORD dwErrCode(0);
			pHttpFile->QueryInfo(HTTP_QUERY_STATUS_CODE, dwErrCode);
			if (dwErrCode >= 200 && dwErrCode < 300)
			{
				CStringA strLineA;
				while (pHttpFile->ReadString((LPTSTR)strLineA.GetBuffer(512), 511))
				{
					strLineA.ReleaseBuffer(); // MFC-bug
					CString strLine(strLineA);
					strLine.TrimLeft();
					if (strLine.GetLength() > 0 && strLine[0] != _T('\\'))
					{
						continue;
					}
					std::vector<CString> vecStrs = Split(strLine, _T("^^^^^^"));
					if (vecStrs.size() >= 2)
					{
						LPUPDATEITEM pUpdateItem = new UPDATEITEM;
						ZeroMemory(pUpdateItem, sizeof(*pUpdateItem));
						lstrcpyn(pUpdateItem->szFileName, vecStrs[0], MAX_PATH);
						lstrcpyn(pUpdateItem->szServerMD5, vecStrs[1], 33);
						m_arrUpdate.Add(pUpdateItem);
					}
				}
				pHttpFile->Close();
				sess.Close();
				bReturn = TRUE;
			}
			else
			{
				LOG(_T("网站访问错误码:%d"), dwErrCode);
			}
		}
	}
	catch (...)
	{
		LOG(_T("下载列表异常!"));
	}

	return bReturn;
}
Ejemplo n.º 13
0
wstring MalieExec::ParseString(DWORD dwIndex)
{
	bool fl_rub=0,fl_vol=0;

	wstring strLine(
		(WCHAR *)&pStrTable[vStrIndex[dwIndex].offset],
		(WCHAR *)&pStrTable[vStrIndex[dwIndex].offset+vStrIndex[dwIndex].length]
	);

	wstring outLine(strLine.size()+3,0);


	size_t len = 0;
	for (size_t idx = 0;idx<strLine.size();++idx)
	{
		switch(strLine[idx])
		{
		case 0:
			if (fl_rub||fl_vol) fl_rub=fl_vol=0;
			outLine[len++]=EOSTR;
			break;
		case 1:
			idx+=4;
			break;
		case 2:
			++idx;
			break;	
		case 3:
			idx+=2;
			break;
		case 4:
			++idx;
			break;
		case 5:
			idx+=2;
			break;
		case 6:
			idx+=2;
			break;
		case 0xA:
			outLine[len++]=fl_rub?STRUB:L'\n';
			break;
		case 7:
			switch (strLine[++idx])
			{
			case 0x0001://递归调用文字读取,然后继续处理(包含注释的文字)
				outLine[len++]=TO_RUB;
				fl_rub=1;
				break;
			case 0x0004://下一句自动出来
				outLine[len++]=NXL;
				break;
			case 0x0006://代表本句结束
				outLine[len++]=TO_RTN;
				break;
			case 0x0007://递归调用文字读取然后wcslen,跳过不处理。应该是用于注释
				++idx;
				idx+=wcslen(&strLine[idx]);
				break;
			case 0x0008://LoadVoice 后面是Voice名
				outLine[len++]=TO_VOL;
				fl_vol=1;
				break;
			case 0x0009://LoadVoice结束
				outLine[len++]=EOVOL;
				break;
			default:
				outLine[len++] = UNKNOW_SIG;
				break;
			}
			break;
		default:
			outLine[len++]=strLine[idx];
		}
	}
	outLine[len++]=EOPAR;
	outLine[len++]=L'\n';
	outLine[len++]=L'\n';

	return move(outLine);
}
Ejemplo n.º 14
0
//-----------------------------------------------------------------------//
void CIO::readUnformattedPdb(const string& strPdbFile, ifstream& ifPdbFileStream, bool& bPostProcess)
{
   int iUnformatID = 0;  // idfrm  
        
   delphi_real fDummy[5];
   
   char cLine[80]; // line

   ifPdbFileStream.clear(); ifPdbFileStream.seekg(0); // rewind   

   ifPdbFileStream.read(cLine,80); // header
     
   ifPdbFileStream.read( reinterpret_cast<char*>(&iUnformatID), sizeof(int) ); // idfrm
      
   // First reading of file to determine number of atoms
   switch (iUnformatID)
   {
      case 0:  // one form of unformatted file with       
         while (!ifPdbFileStream.eof())
         {
            // one coord, 2 reals
            ifPdbFileStream.read( reinterpret_cast<char*>(fDummy), 5*sizeof(delphi_real) ); 
            iAtomNum += 1;
         }           
                       
         break;            
         
      case 1: // another form of unformatted file
         ifPdbFileStream.read( reinterpret_cast<char*>(&iAtomNum),sizeof(delphi_integer) ); 
   
         break;
      default:
         throw CUnknownUnformattedPdb(strPdbFile); 
   }   
      
   cout << "number of atoms read in = " << iAtomNum << " unformatted" << endl;

   ifPdbFileStream.clear(); ifPdbFileStream.seekg(0); // rewind

   ifPdbFileStream.read(cLine,80); // header
     
   ifPdbFileStream.read( reinterpret_cast<char*>(&iUnformatID), sizeof(int) ); // idfrm

   CAtomPdb tmpAtomObj;
   
   switch (iUnformatID)
   {
      case 0:  // one form of unformatted file with       
         for (delphi_integer i = 0; i < iAtomNum; i++)
         {
            ifPdbFileStream.read( reinterpret_cast<char*>(fDummy), 5*sizeof(delphi_real) ); 
            
            tmpAtomObj.setPose(fDummy[0],fDummy[1],fDummy[2]); 
            tmpAtomObj.setRadius(fDummy[3]);
            tmpAtomObj.setCharge(fDummy[4]);   
            tmpAtomObj.setAtInf(" ");
            vctapAtomPdb.push_back(tmpAtomObj);
         } 

         bPostProcess = true;
                       
         break;            
      case 1: // another form of unformatted file
         ifPdbFileStream.read( reinterpret_cast<char*>(&iAtomNum),sizeof(delphi_integer) ); 

         for (delphi_integer i = 0; i < iAtomNum; i++)
         {
            ifPdbFileStream.read(cLine,80); string strLine(cLine);
            ifPdbFileStream.read( reinterpret_cast<char*>(fDummy), 5*sizeof(delphi_real) ); 

            tmpAtomObj.setPose(fDummy[0],fDummy[1],fDummy[2]); 
            tmpAtomObj.setRadius(fDummy[3]);
            tmpAtomObj.setCharge(fDummy[4]);   
            tmpAtomObj.setAtInf(strLine);
            vctapAtomPdb.push_back(tmpAtomObj);
         }
         
         bPostProcess = false;
         
         break;
   }   
}
Ejemplo n.º 15
0
	static bool compile(bx::CommandLine& _cmdLine, uint32_t _version, const std::string& _code, bx::WriterI* _writer, bool _firstPass)
	{
		const char* profile = _cmdLine.findOption('p', "profile");
		if (NULL == profile)
		{
			fprintf(stderr, "Error: Shader profile must be specified.\n");
			return false;
		}

		s_compiler = load();

		bool result = false;
		bool debug = _cmdLine.hasArg('\0', "debug");

		uint32_t flags = D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY;
		flags |= debug ? D3DCOMPILE_DEBUG : 0;
		flags |= _cmdLine.hasArg('\0', "avoid-flow-control") ? D3DCOMPILE_AVOID_FLOW_CONTROL : 0;
		flags |= _cmdLine.hasArg('\0', "no-preshader") ? D3DCOMPILE_NO_PRESHADER : 0;
		flags |= _cmdLine.hasArg('\0', "partial-precision") ? D3DCOMPILE_PARTIAL_PRECISION : 0;
		flags |= _cmdLine.hasArg('\0', "prefer-flow-control") ? D3DCOMPILE_PREFER_FLOW_CONTROL : 0;
		flags |= _cmdLine.hasArg('\0', "backwards-compatibility") ? D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY : 0;

		bool werror = _cmdLine.hasArg('\0', "Werror");

		if (werror)
		{
			flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;
		}

		uint32_t optimization = 3;
		if (_cmdLine.hasArg(optimization, 'O') )
		{
			optimization = bx::uint32_min(optimization, BX_COUNTOF(s_optimizationLevelD3D11) - 1);
			flags |= s_optimizationLevelD3D11[optimization];
		}
		else
		{
			flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
		}

		BX_TRACE("Profile: %s", profile);
		BX_TRACE("Flags: 0x%08x", flags);

		ID3DBlob* code;
		ID3DBlob* errorMsg;

		// Output preprocessed shader so that HLSL can be debugged via GPA
		// or PIX. Compiling through memory won't embed preprocessed shader
		// file path.
		std::string hlslfp;

		if (debug)
		{
			hlslfp = _cmdLine.findOption('o');
			hlslfp += ".hlsl";
			writeFile(hlslfp.c_str(), _code.c_str(), (int32_t)_code.size() );
		}

		HRESULT hr = D3DCompile(_code.c_str()
			, _code.size()
			, hlslfp.c_str()
			, NULL
			, NULL
			, "main"
			, profile
			, flags
			, 0
			, &code
			, &errorMsg
			);
		if (FAILED(hr)
		|| (werror && NULL != errorMsg) )
		{
			const char* log = (char*)errorMsg->GetBufferPointer();

			int32_t line   = 0;
			int32_t column = 0;
			int32_t start  = 0;
			int32_t end    = INT32_MAX;

			bool found = false
				|| 2 == sscanf(log, "(%u,%u):",  &line, &column)
				|| 2 == sscanf(log, " :%u:%u: ", &line, &column)
				;

			if (found
			&&  0 != line)
			{
				start = bx::uint32_imax(1, line - 10);
				end   = start + 20;
			}

			printCode(_code.c_str(), line, start, end, column);
			fprintf(stderr, "Error: D3DCompile failed 0x%08x %s\n", (uint32_t)hr, log);
			errorMsg->Release();
			return false;
		}

		UniformArray uniforms;
		uint8_t numAttrs = 0;
		uint16_t attrs[bgfx::Attrib::Count];
		uint16_t size = 0;

		if (_version == 9)
		{
			if (!getReflectionDataD3D9(code, uniforms) )
			{
				fprintf(stderr, "Error: Unable to get D3D9 reflection data.\n");
				goto error;
			}
		}
		else
		{
			UniformNameList unusedUniforms;
			if (!getReflectionDataD3D11(code, profile[0] == 'v', uniforms, numAttrs, attrs, size, unusedUniforms) )
			{
				fprintf(stderr, "Error: Unable to get D3D11 reflection data.\n");
				goto error;
			}

			if (_firstPass
			&&  unusedUniforms.size() > 0)
			{
				const size_t strLength = bx::strLen("uniform");

				// first time through, we just find unused uniforms and get rid of them
				std::string output;
				bx::Error err;
				LineReader reader(_code.c_str() );
				while (err.isOk() )
				{
					char str[4096];
					int32_t len = bx::read(&reader, str, BX_COUNTOF(str), &err);
					if (err.isOk() )
					{
						std::string strLine(str, len);

						for (UniformNameList::iterator it = unusedUniforms.begin(), itEnd = unusedUniforms.end(); it != itEnd; ++it)
						{
							size_t index = strLine.find("uniform ");
							if (index == std::string::npos)
							{
								continue;
							}

							// matching lines like:  uniform u_name;
							// we want to replace "uniform" with "static" so that it's no longer
							// included in the uniform blob that the application must upload
							// we can't just remove them, because unused functions might still reference
							// them and cause a compile error when they're gone
							if (!!bx::findIdentifierMatch(strLine.c_str(), it->c_str() ) )
							{
								strLine = strLine.replace(index, strLength, "static");
								unusedUniforms.erase(it);
								break;
							}
						}

						output += strLine;
					}
				}

				// recompile with the unused uniforms converted to statics
				return compile(_cmdLine, _version, output.c_str(), _writer, false);
			}
		}

		{
			uint16_t count = (uint16_t)uniforms.size();
			bx::write(_writer, count);

			uint32_t fragmentBit = profile[0] == 'p' ? BGFX_UNIFORM_FRAGMENTBIT : 0;
			for (UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
			{
				const Uniform& un = *it;
				uint8_t nameSize = (uint8_t)un.name.size();
				bx::write(_writer, nameSize);
				bx::write(_writer, un.name.c_str(), nameSize);
				uint8_t type = uint8_t(un.type | fragmentBit);
				bx::write(_writer, type);
				bx::write(_writer, un.num);
				bx::write(_writer, un.regIndex);
				bx::write(_writer, un.regCount);

				BX_TRACE("%s, %s, %d, %d, %d"
					, un.name.c_str()
					, getUniformTypeName(un.type)
					, un.num
					, un.regIndex
					, un.regCount
					);
			}
		}

		{
			ID3DBlob* stripped;
			hr = D3DStripShader(code->GetBufferPointer()
				, code->GetBufferSize()
				, D3DCOMPILER_STRIP_REFLECTION_DATA
				| D3DCOMPILER_STRIP_TEST_BLOBS
				, &stripped
				);

			if (SUCCEEDED(hr) )
			{
				code->Release();
				code = stripped;
			}
		}

		{
			uint32_t shaderSize = uint32_t(code->GetBufferSize() );
			bx::write(_writer, shaderSize);
			bx::write(_writer, code->GetBufferPointer(), shaderSize);
			uint8_t nul = 0;
			bx::write(_writer, nul);
		}

		if (_version > 9)
		{
			bx::write(_writer, numAttrs);
			bx::write(_writer, attrs, numAttrs*sizeof(uint16_t) );

			bx::write(_writer, size);
		}

		if (_cmdLine.hasArg('\0', "disasm") )
		{
			ID3DBlob* disasm;
			D3DDisassemble(code->GetBufferPointer()
				, code->GetBufferSize()
				, 0
				, NULL
				, &disasm
				);

			if (NULL != disasm)
			{
				std::string disasmfp = _cmdLine.findOption('o');
				disasmfp += ".disasm";

				writeFile(disasmfp.c_str(), disasm->GetBufferPointer(), (uint32_t)disasm->GetBufferSize() );
				disasm->Release();
			}
		}

		if (NULL != errorMsg)
		{
			errorMsg->Release();
		}

		result = true;

	error:
		code->Release();
		unload();
		return result;
	}
Ejemplo n.º 16
0
int main(int argc, const char *ppArgv[])
{
	std::shared_ptr<FILE> spfOutput(stdout, fclose_checked);
	const char *pszInputFile = nullptr;
	bool bLaserMode = false;
	unsigned int uiLinesOut = 0;

	//
	// Parse command-line arguments:
	// -o outputfile
	// -i inputfile
	// -l or -laser = laser-mode
	std::string strAppName(ppArgv[0]);
#ifdef _WIN32
	std::string::size_type szSlash = strAppName.rfind('\\');
#else
	std::string::size_type szSlash = strAppName.rfind('/');
#endif
	if (szSlash != strAppName.npos)
	{
		strAppName.erase(0, szSlash);
	}

	//
	// Turn on laser mode if the executable name contains the word laser, e.g. gcodeoptlaser
	std::transform(strAppName.begin(), strAppName.end(), strAppName.begin(), ::tolower);
	if (strAppName.npos != strAppName.find("laser"))
	{
		bLaserMode = true;
	}

	for (int iArg = 1; iArg < argc; ++iArg)
	{
		const std::string strOption(ppArgv[iArg]);
		if (strOption == "-o" && iArg < (argc - 1) && spfOutput.get() == stdout)
		{
			spfOutput.reset(fopen(ppArgv[iArg + 1], "wt"), fclose);
			if (nullptr == spfOutput)
			{
				fprintf(stderr, "Error %i opening %hs\n", errno, ppArgv[iArg + 1]);
				return 0;
			}
			++iArg;
		}
		else if (strOption == "-laser" || strOption == "-l")
		{
			bLaserMode = true;
		}
		else if (strOption == "-i" && pszInputFile == nullptr && iArg < (argc - 1))
		{
			if (false == FileExists(ppArgv[iArg + 1]))
			{
				return 0;
			}
			pszInputFile = ppArgv[iArg + 1];
			++iArg;
		}
		else if (pszInputFile == nullptr &&
			FileExists(strOption))
		{
			pszInputFile = ppArgv[iArg];
		}
		else
		{
			fprintf(stderr, "Unknown command-line argument: %hs\n", strOption.c_str());
			return 0;
		}
	}

	if (pszInputFile == nullptr)
	{
		fprintf(stderr, "USAGE: %hs inputfile [-o outputfile][-laser|-l][-x|-y|-xy]\n", ppArgv[0]);
		return 0;
	}

	std::shared_ptr<FILE> spFile(fopen(ppArgv[1], "rt"), fclose);
	if (spFile.get() == nullptr)
	{
		fprintf(stderr, "Error %i opening %hs\n", errno, ppArgv[1]);
		return 1;
	}

	unsigned int uiLine = 0;
	std::deque<GCodeSet> vCurrentSets;

	bool bInPrologue = true;
	bool bInEpilogue = false;
	GCodeSet gcCurrent(0.0f, 0.0f, 0.0f);
	std::string strPreviousLine;
	double dCurrentZ = 0.0f;
	double dCurrentX = 0.0f;
	double dCurrentY = 0.0f;
	double dLastZ = 0.0f;
	double dLastX = 0.0f;
	double dLastY = 0.0f;
	unsigned int uiSets = 0;
	bool bCutterEngaged = false;

	//
	// Add an attribution
	fprintf(spfOutput.get(), "(Optimized by %hs)\n(Written by Andrew L. Sandoval)\n", strAppName.c_str());

	// Read file and break into sections...
	while (!feof(spFile.get()))
	{
		std::array<char, 2048> szLine = { };
		if (nullptr == fgets(&szLine[0], szLine.size(), spFile.get()))
		{
			continue;
		}
		++uiLine;
		std::string strLine(&szLine[0]);
		std::string strLineCodes(strLine);
		std::string::size_type szLE = strLineCodes.find_first_of("\r\n");
		if (szLE != strLineCodes.npos)
		{
			strLineCodes.erase(szLE);
		}
		PreviousLine prevLine(strPreviousLine, strLine);
		std::string::size_type szX = strLine.find(" X");
		std::string::size_type szY = strLine.find(" Y");
		std::string::size_type szZ = strLine.find(" Z");
		if (strLine.length() > 1 && strLine[0] == 'G' && strLine[1] == '0')
		{
			bCutterEngaged = false;
		}
		else if (strLine.length() > 2 && strLine[0] == 'G' && strLine[1] == '1' &&
			false == isdigit(strLine[2])) // Don't clobber G17
		{
			bCutterEngaged = true;
		}
		else if (bInPrologue)
		{
			if (strLineCodes == "M3" && bLaserMode)
			{
				fprintf(spfOutput.get(), "(M3 - removed in laser mode)\n");
			}
			else
			{
				fprintf(spfOutput.get(), strLine.c_str());
			}
			++uiLinesOut;
			continue;	// Stay in prologue until a G0/G1
		}

		//
		// From here on, past prologue

		//
		// Check for  start of epilogue (before we much with M5's)
		if (strLine.find("M5") == 0 ||
			strLine.find("M30") == 0)
		{
			// sort and flush last set, in epilogue -- sort and output vCurrentSets
			vCurrentSets.push_back(gcCurrent);
			OptimizeAndOutputSets(vCurrentSets, uiLinesOut, spfOutput.get());
			gcCurrent.Reset();
			vCurrentSets.clear();
			// Only supporting one tool currently, so first spindle stop means prologue...
			bInEpilogue = true;
			bInPrologue = false;
			if (dCurrentZ < 0.0f && bLaserMode == false)
			{
				fprintf(stderr, "WARNING!!!! Program Ends with cutter down, Z = %.02f\n", dCurrentZ);
			}
		}

		if (bInEpilogue)
		{
			fprintf(spfOutput.get(), strLine.c_str());
			++uiLinesOut;
			continue;
		}

		//
		// G0 w/Z or G1 w/Z
		// If Laser Mode, change any G0 Z to an M5 (laser off)
		// If Laser Mode, change and G1 Z to M3 (laser on)
		if (strLine[0] == 'G' && szZ != strLine.npos)
		{
			if (bCutterEngaged)
			{
				dLastZ = dCurrentZ;
				dCurrentZ = atof(strLine.c_str() + szZ + 2);
				gcCurrent.SetZStart(dCurrentZ);

				if (dLastZ != dCurrentZ)
				{
					// sort and flush last set, new depth -- sort and output vCurrentSets
					// This line will end up in gcCurrent so it can be ignored
					OptimizeAndOutputSets(vCurrentSets, uiLinesOut, spfOutput.get());
					vCurrentSets.clear();
				}
			}

			if (bLaserMode)
			{
				// G0 Z (replace with M3 - shut off laser)
				// G1 Z (replace with M5)
				if (bCutterEngaged == false)
				{
					// Moving with laser disengaged
					strLine = "M5 (laser off - was ";
					strLine += strLineCodes;
					strLine += ")\n";
				}
				else
				{
					strLine = "M3 (laser on - was ";
					strLine += strLineCodes;
					strLine += ")\n";
				}
				if (bInPrologue)		// Only place this should happen...
				{
					fprintf(spfOutput.get(), strLine.c_str());
				}
			}
		}

		//
		// G0 w/X or G1 w/X
		if (strLine[0] == 'G' &&		// Cutter engaged or not, move to X
			szX != strLine.npos)
		{
			// Update current position for tracking end position of set
			dLastX = dCurrentX;
			dCurrentX = atof(strLine.c_str() + szX + 2);
		}

		//
		// G0 w/Y or G1 w/Y
		if (strLine[0] == 'G' &&		// Cutter engaged or not, move to Y
			szY != strLine.npos)
		{
			// Update current position for tracking end position of set
			dLastY = dCurrentY;
			dCurrentY = atof(strLine.c_str() + szY + 2);
		}

		//
		// G0 X - start of a set
		if (strLine.find("G0 X") == 0)	// Rapid Linear Motion, cutter not engaged
		{
			bInPrologue = false;
			bInEpilogue = false;
			// NOTE: Though x and y will be the end of the G0 rapid linear motion, it is the start of a set
			// where cutting begins!
			
			// Error if the depth is not positive!!!

			// Start of a new set...
			if (szX == strLine.npos ||
				szY == strLine.npos)
			{
				fprintf(stderr, "Critical Error: expected a G0 line to contain X and Y axis settings on line #%u: %hs\n", uiLine, strLine.c_str());
				return 0;
			}

			//
			// Update the last set's end point:
			gcCurrent.SetZEnd(dLastZ);
			gcCurrent.SetXEnd(dLastX);
			gcCurrent.SetYEnd(dLastY);

			if (gcCurrent.GetLines().empty() == false)
			{
				vCurrentSets.push_back(gcCurrent);
			}
			// A new set is started with a G0 X
			// When a G1 Z to a new depth is encountered all previous sets can be sorted and output
			// Same for epilogue start
			//
			// Record new set's start point and update references
			gcCurrent.Reset(dCurrentX, dCurrentY, dCurrentZ);	 // Current Z may change on next line
			++uiSets;
		}
		//
		// Part of a set...
		if (bInPrologue == true)
		{
			continue;
		}
		gcCurrent.LineVector().push_back(strLine);
	}

	fprintf(stderr, "Output Lines: %lu\n", uiLinesOut);
	fprintf(stderr, "Input Lines: %lu\n", uiLine);
	return 0;
}