Пример #1
0
//- AN ----------------------------------------------
//  Компиляция строки BufPtr в байткод CurMacroBuffer
//- AN ----------------------------------------------
int __parseMacroString(DWORD *&CurMacroBuffer, int &CurMacroBufferSize, const wchar_t *BufPtr)
{
	_KEYMACRO(CleverSysLog Clev(L"parseMacroString"));
	//_KEYMACRO(SysLog(L"BufPtr[%p]='%s'", BufPtr,BufPtr));
	_macro_nErr = 0;
	_macro_nLine= 0;
	_macro_nPos = 0;
	pSrcString = emptyString;
	inloop = 0;
	/*pSrcString = */oSrcString = sSrcString = emptyString;

	if (!BufPtr || !*BufPtr)
	{
		keyMacroParseError(err_ZeroLengthMacro);
		return FALSE;
	}

	bool useUDL=true;
	const wchar_t *NewBufPtr;

	UserDefinedList MacroSrcList(ULF_NOTRIM|ULF_NOUNQUOTE, L"\r\n");
	if(!MacroSrcList.Set(BufPtr))
		useUDL=false; // все в одну строку
	//{
	//	_SVS(SysLog(L"MacroSrcList.GetTotal()=%d",MacroSrcList.GetTotal()));
	//	while((NewBufPtr=MacroSrcList.GetNext()) )
	//		_SVS(SysLog(L"[%s]",NewBufPtr));
	//	MacroSrcList.Reset();
	//}

	size_t SizeCurKeyText = (StrLength(BufPtr)*2)*sizeof(wchar_t);
	string strCurrKeyText;
	//- AN ----------------------------------------------
	//  Буфер под парсинг выражений
	//- AN ----------------------------------------------
	DWORD *dwExprBuff = (DWORD*)xf_malloc(SizeCurKeyText*sizeof(DWORD));

	if (!dwExprBuff)
		return FALSE;

	TExec exec;
	wchar_t varName[256];
	DWORD KeyCode, *CurMacro_Buffer = nullptr;

	if(useUDL)
		BufPtr=MacroSrcList.GetNext();

	pSrcString=BufPtr;

	for (;;)
	{
		int Size = 1;
		int SizeVarName = 0;
		const wchar_t *oldBufPtr = BufPtr;

		if (!(BufPtr = __GetNextWord(BufPtr, strCurrKeyText, _macro_nLine)))
		{
			if(!useUDL)
				break;
			NewBufPtr=MacroSrcList.GetNext();
			if(!NewBufPtr)
				break;
			_macro_nLine++;
			pSrcString=BufPtr=NewBufPtr;
			continue;
		}
		_SVS(SysLog(L"_macro_nLine   = [%d]",_macro_nLine));
		_SVS(SysLog(L"BufPtr         = [%s]",BufPtr));
		_SVS(SysLog(L"pSrcString     = [%s]",pSrcString));
		_SVS(SysLog(L"strCurrKeyText = [%s]",strCurrKeyText.CPtr()));

		//- AN ----------------------------------------------
		//  Проверка на строковый литерал
		//  Сделаем $Text опциональным
		//- AN ----------------------------------------------
		if (strCurrKeyText.At(0) == L'\"' && strCurrKeyText.At(1))
		{
			KeyCode = MCODE_OP_PLAINTEXT;
			BufPtr = oldBufPtr;
		}
		else if ((KeyCode = KeyNameMacroToKey(strCurrKeyText)) == (DWORD)-1 && (KeyCode = KeyNameToKey(strCurrKeyText)) == (DWORD)-1)
		{
			int ProcError=0;

			if (strCurrKeyText.At(0) == L'%' &&
			        (
			            (IsAlphaNum(strCurrKeyText.At(1)) || strCurrKeyText.At(1) == L'_') ||
			            (
			                strCurrKeyText.At(1) == L'%' &&
			                (IsAlphaNum(strCurrKeyText.At(2)) || strCurrKeyText.At(2)==L'_')
			            )
			        )
			   )
			{
				BufPtr = oldBufPtr;

				while (*BufPtr && (IsSpace(*BufPtr) || IsEol(*BufPtr)))
				{
					if (IsEol(*BufPtr))
					{
						_macro_nLine++;//TODO!!!
					}
					BufPtr++;
				}

				ClearArray(varName);
				KeyCode = MCODE_OP_SAVE;
				wchar_t* p = varName;
				const wchar_t* s = strCurrKeyText.CPtr()+1;

				if (*s == L'%')
					*p++ = *s++;

				wchar_t ch;
				*p++ = *s++;

				while ((iswalnum(ch = *s++) || (ch == L'_')))
					*p++ = ch;

				*p = 0;
				size_t Length = (StrLength(varName)+1)*sizeof(wchar_t);
				// строка должна быть выровнена на 4
				SizeVarName = static_cast<int>(Length/sizeof(DWORD));

				if (Length == sizeof(wchar_t) || (Length % sizeof(DWORD)) )    // дополнение до sizeof(DWORD) нулями.
					SizeVarName++;

				_SVS(SysLog(L"BufPtr=%s",BufPtr));
				BufPtr += Length/sizeof(wchar_t);
				_SVS(SysLog(L"BufPtr=%s",BufPtr));
				Size += parseExpr(BufPtr, dwExprBuff, L'=', L';');

				if (_macro_nErr)
				{
					ProcError++;
				}
			}
			else
			{
				// проверим вариант, когда вызвали функцию, но результат не присвоили,
				// например, вызвали MsgBox(), но результат неважен
				// тогда SizeVarName=1 и varName=""
				wchar_t *lpwszCurrKeyText = strCurrKeyText.GetBuffer();
				wchar_t *Brack=(wchar_t *)wcspbrk(lpwszCurrKeyText,L"( "), Chr=0;

				if (Brack)
				{
					Chr=*Brack;
					*Brack=0;
				}

				if (funcLook(lpwszCurrKeyText) != MCODE_F_NOFUNC)
				{
					if (Brack) *Brack=Chr;

					BufPtr = oldBufPtr;

					while (*BufPtr && (IsSpace(*BufPtr) || IsEol(*BufPtr)))
					{
						if (IsEol(*BufPtr))
						{
							_macro_nLine++;//TODO!!!
						}
						BufPtr++;
					}

					Size += parseExpr(BufPtr, dwExprBuff, 0, 0);

					/*
					// этого пока ненадо, считаем, что ';' идет сразу за функцией, иначе это отдельный символ ';', который нужно поместить в поток
					while ( *BufPtr && (IsSpace(*BufPtr) || IsEol(*BufPtr)) )
					{
						if (IsEol(*BufPtr))
						{
							_macro_nLine++;//TODO!!!
						}
						BufPtr++;
					}
					*/
					if (*BufPtr == L';')
						BufPtr++; // здесь Size не увеличиваем, т.к. мы прокидываем символ ';'

					//Size--; //???
					if (_macro_nErr)
					{
						ProcError++;
					}
					else
					{
						KeyCode=MCODE_OP_SAVE;
						SizeVarName=1;
						ClearArray(varName);
					}
				}
				else
				{
					if (Brack) *Brack=Chr;

					ProcError++;
				}

				strCurrKeyText.ReleaseBuffer();
			}

			if (ProcError)
			{
				if (!_macro_nErr)
					//keyMacroParseError(err_Unrecognized_keyword, strCurrKeyText, strCurrKeyText,strCurrKeyText);
					keyMacroParseError(err_Unrecognized_keyword, oldBufPtr, pSrcString, strCurrKeyText);

				if (CurMacro_Buffer )
				{
					xf_free(CurMacro_Buffer);
					CurMacroBuffer = nullptr;
				}

				CurMacroBufferSize = 0;
				xf_free(dwExprBuff);
				return FALSE;
			}
		}
		else if (!(strCurrKeyText.At(0) == L'$' && strCurrKeyText.At(1)))
		{
			Size=3;
			KeyCode=MCODE_OP_KEYS;
		}

		switch (KeyCode)
		{
			// $Text
			// -------------------------------------
			//            MCODE_OP_PLAINTEXT
			//            <expr>
			case MCODE_OP_PLAINTEXT:
			{
				Size += parseExpr(BufPtr, dwExprBuff, 0, 0);
				break;
			}
			// $If (expr) ... $End
			// -------------------------------------
			//            <expr>
			//            MCODE_OP_JZ                     p1=*+0
			//            addr1        ------------+
			//            ...                      |
			//            MCODE_OP_JMP             |
			// +--------- addr2                    |
			// |          ...          <-----------+
			// +--------> MCODE_OP_END
			// или
			//            <expr>
			//            MCODE_OP_JZ                     p1=*+0
			//            addr1        ------------+
			//            ...                      |
			//            MCODE_OP_END <-----------+
			case MCODE_OP_IF:
			{
				Size += parseExpr(BufPtr, dwExprBuff, L'(', L')');

				if (!exec.add(emmThen, CurMacroBufferSize+Size))
				{
					if (CurMacro_Buffer )
					{
						xf_free(CurMacro_Buffer);
						CurMacroBuffer = nullptr;
					}

					CurMacroBufferSize = 0;
					xf_free(dwExprBuff);
					return FALSE;
				}

				Size++;
				break;
			}
			case MCODE_OP_ELSE:
			{
				Size++;
				break;
			}
			// $Rep (expr) ... $End
			// -------------------------------------
			//            <expr>
			//            MCODE_OP_SAVEREPCOUNT       1
			// +--------> MCODE_OP_REP                    p1=*
			// |          <counter>                   3
			// |          <counter>                   4
			// |          MCODE_OP_JZ                 5   p2=*+2
			// |          addr1        ------------+
			// |          ...                      |
			// |          MCODE_OP_JMP             |
			// +--------- addr2                    |
			//            MCODE_OP_END <-----------+
			case MCODE_OP_REP:
			{
				inloop++;
				Size += parseExpr(BufPtr, dwExprBuff, L'(', L')');

				if (!exec.add(emmRep, CurMacroBufferSize+Size, CurMacroBufferSize+Size+4))   //??? 3
				{
					if (CurMacro_Buffer )
					{
						xf_free(CurMacro_Buffer);
						CurMacroBuffer = nullptr;
					}

					CurMacroBufferSize = 0;
					xf_free(dwExprBuff);
					return FALSE;
				}

				Size += 5;  // естественно, размер будет больше = 4
				break;
			}
			// $While (expr) ... $End
			// -------------------------------------
			// +--------> <expr>
			// |          MCODE_OP_JZ                    CurMacroBufferSize + Size - 2
			// |          addr1        ------------+     CurMacroBufferSize + Size - 1
			// |          ...                      |     ...
			// |          MCODE_OP_JMP             |     CurMacroBufferSize + Size - 3
			// +--------- addr2                    |     CurMacroBufferSize + Size - 2
			//            MCODE_OP_END <-----------+     CurMacroBufferSize + Size - 1
			//                                           CurMacroBufferSize + Size
			case MCODE_OP_WHILE:
			{
				inloop++;
				Size += parseExpr(BufPtr, dwExprBuff, L'(', L')');

				if (!exec.add(emmWhile, CurMacroBufferSize, CurMacroBufferSize+Size))
				{
					if (CurMacro_Buffer )
					{
						xf_free(CurMacro_Buffer);
						CurMacroBuffer = nullptr;
					}

					CurMacroBufferSize = 0;
					xf_free(dwExprBuff);
					return FALSE;
				}

				Size++;
				break;
			}
			// $continue
			// -------------------------------------
			// ^          MCODE_OP_CONTINUE
			// |          MCODE_OP_JMP
			// +--------- addr
			case MCODE_OP_CONTINUE:
			{
				Size++; // Место под адрес
				break;
			}
			// $break
			// -------------------------------------
			//            MCODE_OP_BREAK
			//            MCODE_OP_JMP
			//            addr -->
			case MCODE_OP_BREAK:
			{
				Size++; // Место под адрес
				break;
			}
			case MCODE_OP_END:
			{
				switch (exec().state)
				{
					case emmRep:
					case emmWhile:
						Size += 2; // Место под дополнительный JMP
						break;
					default:
						break;
				}

				break;
			}
		}

		if (_macro_nErr)
		{
			if (CurMacro_Buffer )
			{
				xf_free(CurMacro_Buffer);
				CurMacroBuffer = nullptr;
			}

			CurMacroBufferSize = 0;
			xf_free(dwExprBuff);
			return FALSE;
		}

		if (!BufPtr)   // ???
			break;

		// код найден, добавим этот код в буфер последовательности.
		CurMacro_Buffer = (DWORD *)xf_realloc(CurMacro_Buffer,sizeof(*CurMacro_Buffer)*(CurMacroBufferSize+Size+SizeVarName));

		if (!CurMacro_Buffer)
		{
			CurMacroBuffer = nullptr;
			CurMacroBufferSize = 0;
			xf_free(dwExprBuff);
			return FALSE;
		}

		switch (KeyCode)
		{
			case MCODE_OP_PLAINTEXT:
			{
				_SVS(SysLog(L"[%d] Size=%u",__LINE__,Size));
				memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD));
				CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode;
				break;
			}
			case MCODE_OP_SAVE:
			{
				memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD));
				CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode;
				memcpy(CurMacro_Buffer+CurMacroBufferSize+Size, varName, SizeVarName*sizeof(DWORD));
				break;
			}
			case MCODE_OP_IF:
			{
				memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD));
				CurMacro_Buffer[CurMacroBufferSize+Size-2] = MCODE_OP_JZ;
				break;
			}
			case MCODE_OP_REP:
			{
				memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD));
				CurMacro_Buffer[CurMacroBufferSize+Size-6] = MCODE_OP_SAVEREPCOUNT;
				CurMacro_Buffer[CurMacroBufferSize+Size-5] = KeyCode;
				CurMacro_Buffer[CurMacroBufferSize+Size-4] = 0; // Initilize 0
				CurMacro_Buffer[CurMacroBufferSize+Size-3] = 0;
				CurMacro_Buffer[CurMacroBufferSize+Size-2] = MCODE_OP_JZ;
				break;
			}
			case MCODE_OP_WHILE:
			{
				memcpy(CurMacro_Buffer+CurMacroBufferSize, dwExprBuff, Size*sizeof(DWORD));
				CurMacro_Buffer[CurMacroBufferSize+Size-2] = MCODE_OP_JZ;
				break;
			}
			case MCODE_OP_ELSE:
			{
				if (exec().state == emmThen)
				{
					exec().state = emmElse;
					CurMacro_Buffer[exec().pos1] = CurMacroBufferSize+2;
					exec().pos1 = CurMacroBufferSize;
					CurMacro_Buffer[CurMacroBufferSize] = 0;
				}
				else // тут $else и не предвиделось :-/
				{
					keyMacroParseError(err_Not_expected_ELSE, BufPtr, pSrcString); // strCurrKeyText

					if (CurMacro_Buffer )
					{
						xf_free(CurMacro_Buffer);
						CurMacroBuffer = nullptr;
					}

					CurMacroBufferSize = 0;
					xf_free(dwExprBuff);
					return FALSE;
				}

				break;
			}
			case MCODE_OP_BREAK:
			case MCODE_OP_CONTINUE:
			{
				TExecItem *ei=nullptr;
				if (!inloop || (KeyCode==MCODE_OP_CONTINUE && exec.findnearloop(&ei) == -1))
				{
					keyMacroParseError(KeyCode==MCODE_OP_CONTINUE?err_Continue_Outside_The_Loop:err_Break_Outside_The_Loop, oldBufPtr, pSrcString);//BufPtr, pSrcString); // strCurrKeyText

					if (CurMacro_Buffer )
					{
						xf_free(CurMacro_Buffer);
						CurMacroBuffer = nullptr;
					}

					CurMacroBufferSize = 0;
					xf_free(dwExprBuff);
					return FALSE;
				}
				CurMacro_Buffer[CurMacroBufferSize+Size-2] = KeyCode==MCODE_OP_CONTINUE?MCODE_OP_JMP:MCODE_OP_BREAK;
				CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode==MCODE_OP_CONTINUE?ei->pos1:0;
				break;
			}
			case MCODE_OP_END:
			{
				switch (exec().state)
				{
					case emmMain:
						// тут $end и не предвиделось :-/
						keyMacroParseError(err_Not_expected_END, BufPtr, pSrcString); // strCurrKeyText

						if (CurMacro_Buffer )
						{
							xf_free(CurMacro_Buffer);
							CurMacroBuffer = nullptr;
						}

						CurMacroBufferSize = 0;
						xf_free(dwExprBuff);
						return FALSE;
					case emmThen:
						CurMacro_Buffer[exec().pos1-1] = MCODE_OP_JZ;
						CurMacro_Buffer[exec().pos1+0] = CurMacroBufferSize+Size-1;
						CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode;
						break;
					case emmElse:
						CurMacro_Buffer[exec().pos1-0] = MCODE_OP_JMP;
						CurMacro_Buffer[exec().pos1+1] = CurMacroBufferSize+Size-1;
						CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode;
						break;
					case emmRep:
					case emmWhile:
						inloop--;
						CurMacro_Buffer[exec().pos2] = CurMacroBufferSize+Size-1;
						CurMacro_Buffer[CurMacroBufferSize+Size-3] = MCODE_OP_JMP;
						CurMacro_Buffer[CurMacroBufferSize+Size-2] = exec().pos1;
						CurMacro_Buffer[CurMacroBufferSize+Size-1] = KeyCode;
						CorrectBreakCode(CurMacro_Buffer,CurMacro_Buffer+exec().pos1,CurMacro_Buffer+(CurMacroBufferSize+Size-1));
						break;
				}

				if (!exec.del())    // Вообще-то этого быть не должно,  но подстрахуемся
				{
					if (CurMacro_Buffer )
					{
						xf_free(CurMacro_Buffer);
						CurMacroBuffer = nullptr;
					}

					CurMacroBufferSize = 0;
					xf_free(dwExprBuff);
					return FALSE;
				}

				break;
			}
			case MCODE_OP_KEYS:
			{
				CurMacro_Buffer[CurMacroBufferSize+Size-3]=MCODE_OP_KEYS;
				CurMacro_Buffer[CurMacroBufferSize+Size-2]=KeyNameToKey(strCurrKeyText);
				CurMacro_Buffer[CurMacroBufferSize+Size-1]=MCODE_OP_ENDKEYS;
				break;
			}
			default:
				CurMacro_Buffer[CurMacroBufferSize]=KeyCode;
		} // end switch(KeyCode)

		CurMacroBufferSize += Size+SizeVarName;
	} // END for (;;)

	if (CurMacroBufferSize == 1)
	{
		CurMacro_Buffer = (DWORD *)xf_realloc(CurMacro_Buffer,sizeof(*CurMacro_Buffer)*(CurMacroBufferSize+1));

		if (!CurMacro_Buffer)
		{
			CurMacroBuffer = nullptr;
			CurMacroBufferSize = 0;
			xf_free(dwExprBuff);
			return FALSE;
		}

		CurMacro_Buffer[CurMacroBufferSize]=MCODE_OP_NOP;
		CurMacroBufferSize++;
	}

#ifdef _DEBUG
#ifdef SYSLOG_KEYMACRO
	SysLogDump(L"Macro Buffer",0,(LPBYTE)CurMacro_Buffer,CurMacroBufferSize*sizeof(DWORD),nullptr);
	SysLog(L"<ByteCode>{");

	if (CurMacro_Buffer)
	{
		int ii;

		for (ii = 0 ; ii < CurMacroBufferSize ; ii++)
			printKeyValue(CurMacro_Buffer, ii);
	}
	else
		SysLog(L"??? is nullptr");

	SysLog(L"}</ByteCode>");
#endif
#endif

	if (CurMacroBufferSize > 1)
		CurMacroBuffer = CurMacro_Buffer;
	else if (CurMacro_Buffer)
	{
		CurMacroBuffer = reinterpret_cast<DWORD*>((intptr_t)(*CurMacro_Buffer));
		xf_free(CurMacro_Buffer);
	}

	xf_free(dwExprBuff);

	if (exec().state != emmMain)
	{
		keyMacroParseError(err_Unexpected_EOS, strCurrKeyText, strCurrKeyText);
		return FALSE;
	}

	if (_macro_nErr)
	{
		return FALSE;
	}

	return TRUE;
}
Пример #2
0
bool ScanTree::GetNextName(FAR_FIND_DATA_EX *fdata,string &strFullName)
{
	if (!ScanItems.getCount())
		return false;

	bool Done=false;
	Flags.Clear(FSCANTREE_SECONDDIRNAME);

	for (;;)
	{
		ScanTreeData* LastItem = ScanItems.lastItem();
		if (!LastItem->Find)
		{
			LastItem->Find = new FindFile(strFindPath);
		}
		Done=!LastItem->Find->Get(*fdata);

		if (Flags.Check(FSCANTREE_FILESFIRST))
		{
			if (LastItem->Flags.Check(FSCANTREE_SECONDPASS))
			{
				if (!Done && !(fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
					continue;
			}
			else
			{
				if (!Done && (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
					continue;

				if (Done)
				{
					if(LastItem->Find)
					{
						delete LastItem->Find;
						LastItem->Find = nullptr;
					}
					LastItem->Flags.Set(FSCANTREE_SECONDPASS);
					continue;
				}
			}
		}
		break;
	}

	if (Done)
	{
		ScanItems.deleteItem(ScanItems.getCount()-1);

		if (!ScanItems.getCount())
			return false;
		else
		{
			if (ScanItems.lastItem()->Flags.Check(FSCANTREE_INSIDEJUNCTION))
				Flags.Clear(FSCANTREE_INSIDEJUNCTION);

			CutToSlash(strFindPath,true);

			if (Flags.Check(FSCANTREE_RETUPDIR))
			{
				strFullName = strFindPath;
				apiGetFindDataEx(strFullName, *fdata);
			}

			CutToSlash(strFindPath);
			strFindPath += strFindMask;
			_SVS(SysLog(L"1. FullName='%s'",strFullName.CPtr()));

			if (Flags.Check(FSCANTREE_RETUPDIR))
			{
				Flags.Set(FSCANTREE_SECONDDIRNAME);
				return true;
			}

			return GetNextName(fdata,strFullName);
		}
	}
	else
	{
		if ((fdata->dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && Flags.Check(FSCANTREE_RECUR) &&
		        (!(fdata->dwFileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) || Flags.Check(FSCANTREE_SCANSYMLINK)))
		{
			string RealPath(ScanItems.lastItem()->RealPath);
			AddEndSlash(RealPath);
			RealPath += fdata->strFileName;

			if (fdata->dwFileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)
				ConvertNameToReal(RealPath, RealPath);

			//recursive symlinks guard
			bool Recursion = false;

			for (size_t i = 0; i < ScanItems.getCount() && !Recursion; i++)
				Recursion = ScanItems.getItem(i)->RealPath == RealPath;

			if (!Recursion)
			{
				CutToSlash(strFindPath);
				strFindPath += fdata->strFileName;
				strFullName = strFindPath;
				strFindPath += L"\\";
				strFindPath += strFindMask;
				ScanItems.addItem();
				ScanItems.lastItem()->Flags = ScanItems.getItem(ScanItems.getCount()-2)->Flags; // наследуем флаг
				ScanItems.lastItem()->Flags.Clear(FSCANTREE_SECONDPASS);
				ScanItems.lastItem()->RealPath = RealPath;

				if (fdata->dwFileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)
				{
					ScanItems.lastItem()->Flags.Set(FSCANTREE_INSIDEJUNCTION);
					Flags.Set(FSCANTREE_INSIDEJUNCTION);
				}

				return true;
			}
		}
	}

	strFullName = strFindPath;
	CutToSlash(strFullName);
	strFullName += fdata->strFileName;
	return true;
}