Example #1
0
void demo_number_main(void)
{
  char **arg;

  for (arg = toys.optargs; *arg; arg++) {
    long long ll = atolx(*arg);

    if (toys.optflags) {
      human_readable(toybuf, ll, toys.optflags);
      xputs(toybuf);
    } else printf("%lld\n", ll);
  }
}
Example #2
0
//-----------------------------------------------------------------------------
// Command_Decode
//-----------------------------------------------------------------------------
//
// Return Value : Error code
// Parameters   : Pointer to input string
//
// Parses the command string and calls the appropriate functions.
//
//-----------------------------------------------------------------------------
uint8_t CommandDecode(char * instr)
{
	char * cp;						// character pointer
	const DEVICE_FAMILY *dfptr;		// pointer to current device family
	const DERIVATIVE_ENTRY *deptr;	// pointer to current derivative
	uint8_t command_number = 99;	// number of command encoded in 'instr'
	uint8_t result = INVALID_COMMAND;

	printf("Command: %s\n", instr);
	command_number = 0xFF;
	if (instr[0] >= '0' && instr[0] <= '9')
	{
		// if first char is a digit, then interpret it as a command number
		command_number = atoi (instr);
	}

	{
		// interpret command as a string and find command number
		// or find command by command_number
		const COMMAND *ctptr = Commands;
		while (ctptr->name != NULL)
		{
			if (command_number != 0xFF)
			{
				if (ctptr->number == command_number)
					break;
			}
			else if (strncmp (instr, ctptr->name, ctptr->name_size) == 0)
			{	// we've found the command, so record its number and exit
				command_number = ctptr->number;
				break;
			}
			ctptr++;
		}
		if (ctptr->name != NULL)
		{
			if (ctptr->need_discover && !FamilyFound)
			{
				result = DEVICE_UNDISCOVERED;
				command_number = 0xFE;	// Unknown command
			}
		}
		else
			command_number = 0xFF;	// Unknown command
	}

	// Now we have a command number, so act on it.
	switch (command_number)
	{
		case 0:	// Device Autodetect
		{
			uint8_t deviceId = 0xFF;		// initialize device and derivative
			uint8_t revisionId = 0xFF;
			uint8_t derivativeId = 0xFF;	// id's to invalid selections

			printf("Device Autodetect\n");
			Start_Stopwatch();
			if (NO_ERROR == (result = C2_Halt ())
			&&	NO_ERROR == (result = C2_Discover (&deviceId, &revisionId, &derivativeId))
				)
			{
				CommandsList = KnownFamilies[FamilyNumber].InitStrings;
			}
			Stop_Stopwatch();
			printf("Device ID     : %02X\n", deviceId);
			printf("Revision ID   : %02X\n", revisionId);
			printf("Derivative ID : %02X\n", derivativeId);
			break;
		}
		case 1:	// Print Menu
		{
			printf("? stub\n");
			Start_Stopwatch();
			Display_Menu();
			Stop_Stopwatch();
			result = NO_ERROR;
			break;
		}
		case 2:	// Wait ms
		{
			uint16_t wait_time;
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				wait_time = atoi (cp);
				printf("Waiting %d ms\n", wait_time);
				Start_Stopwatch();
				Wait_ms (wait_time);
				Stop_Stopwatch();
				printf("Stopwatch_ms is %u\n", Stopwatch_ms);
				result = NO_ERROR;
			}
			break;
		}
		case 3:	// Wait us
		{
			uint16_t wait_time;
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				wait_time = atoi (cp);

				printf("Waiting %d us\n", wait_time);
				Start_Stopwatch();
				Wait_us (wait_time);
				Stop_Stopwatch();
				printf("Stopwatch_us is %u\n", Stopwatch_us);

				result = NO_ERROR;
			}
			break;
		}
		case 4:	// Start Stopwatch
		{
			printf("Start Stopwatch\n");
			result = Start_Stopwatch();
			break;
		}
		case 5:	// Stop Stopwatch
		{
			printf("Stop Stopwatch\n");
			result = Stop_Stopwatch();
			printf("Stopwatch_ms is %u\n", Stopwatch_ms);
			printf("Stopwatch_us is %u\n", Stopwatch_us);
			break;
		}
		case 6:	// Set Timeout ms
		{
			uint16_t wait_time;
			printf("Set Timeout ms:\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				wait_time = atoi (cp);

				printf("Timing out for %d ms\n", wait_time);
				Start_Stopwatch();
				SetTimeout_ms (wait_time);
				SetTimeout_us (1);
				while (!IsDoneTimeout_ms())
					;
				Stop_Stopwatch();
				printf("Stopwatch_ms is %u\n", Stopwatch_ms);
				result = NO_ERROR;
			}
			break;
		}
		case 7:	// Set Timeout us
		{
			uint16_t wait_time;
			printf("Set Timeout us\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				wait_time = atoi(cp);

				printf("Timing out for %d us\n", wait_time);
				Start_Stopwatch();
				SetTimeout_us(wait_time);
				while (!IsDoneTimeout_us())
					;
				Stop_Stopwatch();
				printf("Stopwatch_us is %u\n", Stopwatch_us);

				result = NO_ERROR;
			}
			break;
		}
		case 8:		// Pin init
		{
			printf("Pin Init\n");
			result = Pin_Init();
			break;
		}
		case 9:		// C2 Reset
		{
			printf("C2 Reset\n");
			result = C2_Reset();
			break;
		}
		case 10:	// C2 Write Address
		{
			uint16_t addr;
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				addr = atox (cp);

				printf("C2 Write Address: %02X\n", addr);
				Start_Stopwatch();
				result = C2_WriteAR(addr);
				Stop_Stopwatch();
			}
			break;
		}
		case 11:	// C2 Read Address
		{
			Start_Stopwatch();
			result = C2_ReadAR();
			Stop_Stopwatch();
			printf("C2 Read Address: %02X\n", (uint16_t) C2_AR);
			break;
		}
		case 12:	// C2 Write Data
		{
			uint8_t data;
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				data = atox (cp);

				printf("C2 Write Data: %02X\n", (uint16_t) data);
				Start_Stopwatch ();
				result = C2_WriteDR (data, C2_WRITE_DR_TIMEOUT_US);
				Stop_Stopwatch ();
			}
			break;
		}
		case 13:	// C2 Read Data
		{
			Start_Stopwatch ();
			result = C2_ReadDR (C2_READ_DR_TIMEOUT_US);
			Stop_Stopwatch ();
			printf("C2 Read Data: %02X\n", (uint16_t) C2_DR);
			break;
		}
		case 14:	// C2 Reset and Halt
		{
			printf("C2 Reset and Halt\n");
			result = C2_Halt ();
			break;
		}
		case 15:	// C2 Get Device ID
		{
			uint8_t devId;

			printf("C2 Get Device ID\n");
			Start_Stopwatch ();
			result = C2_GetDevID (&devId);
			Stop_Stopwatch ();
			printf("Device ID is %u, 0x%04X\n", devId, devId);
			break;
		}
		case 16:	// C2 Get Revision ID
		{
			uint8_t revid;
			printf("C2 Get Revision ID\n");
			Start_Stopwatch ();
			result = C2_GetRevID (&revid);
			Stop_Stopwatch ();
			printf("Revision ID is %u, 0x%04X\n", revid, revid);
			break;
		}
		case 17:	// C2 Read SFR
		{
			uint8_t sfr_value, sfr_address;
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				sfr_address = atox (cp);

				Start_Stopwatch ();
				result = C2_ReadSFR (sfr_address, &sfr_value);
				Stop_Stopwatch ();
				printf("C2 Read SFR(%02X) %02X\n", (uint16_t) sfr_address, (uint16_t) sfr_value);
			}
			break;
		}
		case 18:	// C2 Write SFR
		{
			uint8_t sfr_address, sfr_value;

			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				sfr_address = atox (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{
					sfr_value = atox (cp);

					printf("C2 Write %02X to SFR(%02X)\n", (uint16_t) sfr_value, (uint16_t) sfr_address);
					Start_Stopwatch ();
					result = C2_WriteSFR (sfr_address, sfr_value);
					Stop_Stopwatch ();
				}
			}
			break;
		}
		case 19:	// C2 Read Direct
		{
			uint8_t sfr_value, sfr_address;
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				sfr_address = atox (cp);

				Start_Stopwatch ();
				result = C2_ReadDirect (sfr_address, &sfr_value, C2_DIRECT);
				Stop_Stopwatch ();
				printf("C2 Read Direct(%02X) %02X\n", (uint16_t) sfr_address, (uint16_t) sfr_value);
			}
			break;
		}
		case 20:	// C2 Write Direct <address> <value>
		{
			uint8_t sfr_address, sfr_value;

			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				sfr_address = atox (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{
					sfr_value = atox (cp);

					printf("C2 Write %02x to Direct(%02X)\n", (uint16_t) sfr_value, (uint16_t) sfr_address);
					Start_Stopwatch ();
					result = C2_WriteDirect (sfr_address, sfr_value, C2_DIRECT);
					Stop_Stopwatch ();
				}
			}
			break;
		}
		case 21:	// C2 Read Indirect
		{
			uint8_t sfr_value, sfr_address;
			
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				sfr_address = atox (cp);

				Start_Stopwatch ();
				result = C2_ReadDirect (sfr_address, &sfr_value, C2_INDIRECT);
				Stop_Stopwatch ();
				printf("C2 Read Indirect(%02X) %02X\n", (uint16_t) sfr_address, (uint16_t) sfr_value);
			}
			break;
		}
		case 22:	// C2 Write Indirect
		{
			uint8_t sfr_address;
			uint8_t sfr_value;

			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				sfr_address = atox (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{
					sfr_value = atox (cp);

					printf("C2 Write %02x to Indirect(%02X)\n", (uint16_t) sfr_value, (uint16_t) sfr_address);
					Start_Stopwatch ();
					result = C2_WriteDirect (sfr_address, sfr_value, C2_INDIRECT);
					Stop_Stopwatch ();
				}
			}
			break;
		}
		case 23:	// C2 Discover
		{
			uint8_t j, deviceId, revisionId, derivativeId;

			printf("C2 Discover\n");
			Start_Stopwatch ();
			result = C2_Discover (&deviceId, &revisionId, &derivativeId);
			Stop_Stopwatch ();

			if (result != NO_ERROR)
				break;

			dfptr = &(KnownFamilies[FamilyNumber]);
			deptr = &(KnownFamilies[FamilyNumber].DerivativeList[DerivativeNumber]);

			printf("Family Information:\n");
			printf("Device ID: 0x%04X\n", dfptr->DEVICE_ID);
			printf("Family string: %s\n", dfptr->FAMILY_STRING);
			printf("Mem Type: %u\n", (uint16_t) dfptr->MEM_TYPE);
			printf("Page Size: %u\n", dfptr->PAGE_SIZE);
			printf("Has SFLE: %u\n", (uint16_t) dfptr->HAS_SFLE);
			printf("Security Type: %u\n", (uint16_t) dfptr->SECURITY_TYPE);
			printf("FPDAT address: 0x%02X\n", (uint16_t) dfptr->FPDAT);
			printf("Device ID: 0x%04X\n", dfptr->DEVICE_ID);
			printf("Init strings:\n");
			for (j = 0; ; j++)
			{
				if (dfptr->InitStrings[j] == NULL)
					break;
				printf("%s\n", dfptr->InitStrings[j]);
			}
			printf("\n");
			printf("Derivative Information\n");
			printf("----------------------\n");
			printf("Derivative ID        : %02X\n", deptr->DERIVATIVE_ID);
			printf("Derivative String    : %s\n", deptr->DERIVATIVE_STRING);
			printf("Features String      : %s\n", deptr->FEATURES_STRING);
			printf("Package String       : %s \n", deptr->PACKAGE_STRING);
			printf("Code Start Address   : %05X\n", deptr->CODE_START);
			printf("Code Size            : %05X\n", deptr->CODE_SIZE);
			printf("Write Lock Byte Addr : %05X\n", deptr->WRITELOCKBYTEADDR);
			printf("Read Lock Byte Addr  : %05X\n", deptr->READLOCKBYTEADDR);
			printf("Code 2 Start Address : %05X\n", deptr->CODE2_START);
			printf("Code 2 Size          : %05X\n", deptr->CODE2_SIZE);
			printf("\n");

			break;
		}
		case 24:	// Run Init String
		{
			result = NO_ERROR;
			printf("Execute Device Init String:\n");
			if (FamilyFound == true)
				CommandsList = KnownFamilies[FamilyNumber].InitStrings;
			else
				printf("Device not connected.\n");
			break;
		}
		case 25:	// C2 Flash Read <start addr> <length>
		{
			uint32_t addr;
			uint16_t length;

			printf("C2 Flash Read\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				addr = atolx (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{
					length = atoi (cp);
					if (length > sizeof (BinDest))
						length = sizeof (BinDest);

					printf(
						"Reading %u bytes starting at address 0x%05lX\n",
						length,
						(unsigned long)addr
					);
					Start_Stopwatch ();
					result = C2_FLASH_Read (BinDest, addr, length);
					Stop_Stopwatch ();

					BIN2HEXSTR (HexDest, BinDest, length);
					printf("Memory contents are %s\n", HexDest);
				}
			}
			break;
		}
		case 26:	// C2 OTP Read <start addr> <length>
		{
			uint32_t addr;
			uint16_t length;

			printf("C2 OTP Read\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				addr = atolx (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{
					length = atoi (cp);

					if (length > sizeof (BinDest))
						length = sizeof (BinDest);

					printf("Reading %u bytes starting at address 0x%05lX\n",
						length,
						(unsigned long)addr
					);
					Start_Stopwatch ();
					result = C2_OTP_Read (BinDest, addr, length);
					Stop_Stopwatch ();

					BIN2HEXSTR (HexDest, BinDest, length);
					printf("Memory contents are %s\n", HexDest);
				}
			}
			break;
		}
		case 27:	// C2 Flash Write <start addr> <hex string>
		{
			uint32_t addr;
			uint8_t length;

			printf("C2 Flash Write\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				addr = atolx (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{
					// warning! 'dest' could be overtaken by a long string
					if (NO_ERROR == (result = HEXSTR2BIN (BinDest, cp, &length, sizeof(BinDest))))
					{
						printf("Writing %u bytes starting at address 0x%05X\n", length, addr);
						// printf("Writing the following string: %s\n", cp);
						Start_Stopwatch ();
						result = C2_FLASH_Write (addr, BinDest, length);
						Stop_Stopwatch ();
					}
				}
			}
			break;
		}
		case 28:	// C2 OTP Write <start addr> <hex string>
		{
			uint32_t addr;
			uint8_t length;

			printf("C2 OTP Write\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				addr = atolx (cp);
				cp = GetNextWord(cp);
				if (NO_ERROR == (result = CheckEmpty(cp)))
				{

					if (NO_ERROR != (result = HEXSTR2BIN (BinDest, cp, &length, sizeof(BinDest))))
					{
						printf("Hex string too long");
						break;
					}

					printf(
						"Writing %u bytes starting at address 0x%05lX\n",
						(uint16_t) length,
						(unsigned long)addr
					);
					printf("Writing the following string: %s\n", cp);
					Start_Stopwatch ();
					result = C2_OTP_Write (addr, BinDest, length);
					Stop_Stopwatch ();
				}
			}
			break;
		}
		case 29:	// C2 Page Erase <address in page to erase>
		{
			uint32_t addr;

			printf("C2 Flash Page Erase\n");
			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				addr = atolx (cp);

				printf("Erasing page containing address 0x%05X\n", addr);
				Start_Stopwatch ();
				result = C2_FLASH_PageErase (addr);
				Stop_Stopwatch ();
			}
			break;
		}
		case 30:	// C2 Device Erase
		{
			printf("C2 Flash Device Erase\n");

			printf("Erasing device...\n");
			Start_Stopwatch ();
			result = C2_FLASH_DeviceErase ();
			Stop_Stopwatch ();

			break;
		}
		case 31:	// C2 Flash Blank Check
		{
			uint32_t addr;
			uint32_t length;

			printf("C2 Flash Blank Check\n");

			addr = KnownFamilies[FamilyNumber].DerivativeList[DerivativeNumber].CODE_START;
			length = KnownFamilies[FamilyNumber].DerivativeList[DerivativeNumber].CODE_SIZE;

			printf("Checking starting at address 0x%05X for 0x%05X bytes: ", addr, length);
			Start_Stopwatch ();
			result = C2_FLASH_BlankCheck (addr, length);
			Stop_Stopwatch ();

			printf((result == DEVICE_IS_BLANK) ? "OK\n" : "Fail\n");
			break;
		}
		case 32:	// C2 OTP Blank Check
		{
			uint32_t addr;
			uint32_t length;

			printf("C2 OTP Blank Check\n");

			addr = KnownFamilies[FamilyNumber].DerivativeList[DerivativeNumber].CODE_START;
			length = KnownFamilies[FamilyNumber].DerivativeList[DerivativeNumber].CODE_SIZE;

			printf("Checking starting at address 0x%05X for 0x%05X bytes: ", addr, length);

			Start_Stopwatch ();
			result = C2_OTP_BlankCheck (addr, length);
			Stop_Stopwatch ();

			printf((result == NO_ERROR) ? "OK\n" : "Fail\n");
			break;
		}
		case 33:	// C2 Get Lock Byte value
		{
			printf("C2 Get Lock Byte\n");
			break;
		}
		case 34:	// Write Target to HEX
		{
			printf("Write Target to HEX:\n");
			Start_Stopwatch ();
			result = OP_Write_TARGET2HEX();
			Stop_Stopwatch ();

			break;
		}
		case 36:	// Write HEX to Target
		{
			HEX_RECORD hex;

			printf("Write HEX to Target:\n");

			cp = GetNextWord(instr);
			if (NO_ERROR == (result = CheckEmpty(cp)))
			{
				hex.Buf = BinDest;
				result = HEX_Decode(&hex, cp, sizeof(BinDest));
				if (result == NO_ERROR && hex.RECLEN != 0)
				{
					printf("Writing %u bytes starting at address 0x%05X\n", hex.RECLEN, hex.OFFSET.U16);
					Start_Stopwatch ();
					result = C2_FLASH_Write (hex.OFFSET.U16, hex.Buf, hex.RECLEN);
					Stop_Stopwatch ();
				}
				else if (result == EOF_HEX_RECORD)
					result = NO_ERROR;
			}
			break;
		}
		case 35:	// Read SFRs and directs
		{
			uint8_t row;
			uint8_t col;
			uint8_t value;

			Start_Stopwatch ();
			for (row = 0xF8; row != 0x00; row = row - 8)
			{
				for (col = 0; col != 0x08; col++)
				{
					if (NO_ERROR != (result = C2_ReadDirect ((row+col), &value, C2_DIRECT)))
						break;

					if (col == 0)
						printf("\n0X%02X: %02X", (uint16_t) (row), (uint16_t) value);
					else
						printf(" %02X", (uint16_t) value);
				}
			}
			printf("\n\n");
			Stop_Stopwatch ();
			break;
		}
		case 0xFE:
			break;
		default:
		{
			result = INVALID_COMMAND;
		}
	}
	printf("Result: %02X %s\n", result, GetErrorName(result));
	return result;
}
Example #3
0
void pmap_main(void)
{
  char **optargs;

  for (optargs = toys.optargs; *optargs; optargs++) {
    pid_t pid = atolx(*optargs);
    FILE *fp;
    char *line, *oldline = 0, *name = 0,
         *k = (toys.optflags & FLAG_x) ? "" : "K";
    size_t len;
    long long start, end, pss, tpss = 0, dirty, tdirty = 0, swap, tswap = 0,
              total = 0;
    int xx = 0;

    snprintf(toybuf, sizeof(toybuf), "/proc/%u/cmdline", pid);
    line = readfile(toybuf, 0, 0);
    if (!line) error_msg("No %lu", (long)pid);
    xprintf("%u: %s\n", (int)pid, line);
    free(line);

    // Header
    // Only use the more verbose file in -x mode
    sprintf(toybuf, "/proc/%u/%smaps", pid,
      (toys.optflags & FLAG_x) ? "s" : "");
    if (!(fp = fopen(toybuf, "r"))) {
      error_msg("No %ld\n", (long)pid);
      return;
    }

    if ((toys.optflags & (FLAG_q|FLAG_x)) == FLAG_x)
      xprintf("Address%*cKbytes     PSS   Dirty    Swap  Mode  Mapping\n",
        (sizeof(long)*2)-4, ' ');

    // Loop through mappings
    for (;;) {
      int off, count;

      line = 0;
      if (0 >= getline(&line, &len, fp)) break;
      count = sscanf(line, "%llx-%llx %s %*s %*s %*s %n",
        &start, &end, toybuf, &off);

      if (count == 3) {
        name = line[off] ? line+off : "  [anon]\n";
        if (toybuf[3] == 'p') toybuf[3] = '-';
        total += end = (end-start)/1024;
        printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start,
          6+!!(toys.optflags & FLAG_x), end, k);
        if (toys.optflags & FLAG_x) {
          oldline = line;
          continue;
        }
      } else {
        if (0<sscanf(line, "Pss: %lld", &pss)
            || 0<sscanf(line, "Private_Dirty: %lld", &dirty)
            || 0<sscanf(line, "Swap: %lld", &swap)) xx++;
        free(line);
        if (xx<3) continue;
        line = oldline;
        name = basename(name);
        xx = 0;
        printf("% 7lld %7lld %7lld ", pss, dirty, swap);
        tpss += pss;
        tdirty += dirty;
        tswap += swap;
      }

      xprintf("%s-  %s%s", toybuf, line[off]=='[' ? "  " : "", name);

      free(line);
      line = 0;
    }

    // Trailer
    if (!(toys.optflags & FLAG_q)) {
      int x = !!(toys.optflags & FLAG_x);
      if (x) {
        memset(toybuf, '-', 16);
        xprintf("%.*s  ------  ------  ------  ------\n", (int)(sizeof(long)*2),
          toybuf);
      }
      printf("total% *lld%s", 2*(int)(sizeof(long)+1)+x, total, k);
      if (x) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
      xputc('\n');
    }
 
    fclose(fp);
  }
}
int ParseLine(CString sLine, CString& sBody, CString& sResOut, int& iFrom, double dSpeed, WKCallbackInterface* pCallback)
{
	if(rtDesktop.bottom==0 && rtDesktop.right==0){
		GetWindowRect(GetDesktopWindow(),&rtDesktop);
	}
	CString sParams;
	sParams=CDataXMLSaver::GetInstringPartGreedly("('","')",sLine);
	if(sParams==""){
		sParams=CDataXMLSaver::GetInstringPartGreedly("(",")",sLine);
		if(sParams!=""){
			sLine=sLine.SpanExcluding("(");
		}
	}else{
		sLine=sLine.SpanExcluding("('");
	}
	if(sParams==""){
		sParams=CDataXMLSaver::GetInstringPartGreedly("\"","\"",sLine);
		if(sParams!=""){
			sLine=sLine.SpanExcluding("\"");
		}
	}
	if(sParams==""){
		sParams=CDataXMLSaver::GetInstringPartGreedly("'","'",sLine);
		if(sParams!=""){
			sLine=sLine.SpanExcluding("'");
		}
	}
	sLine.TrimLeft();
	sLine.TrimRight();
	sLine.MakeUpper();
	if(sLine!=""){
		if(sLine=="RETURN"){
			sResOut=sParams;
			sResOut.TrimLeft(" \"'\t");
			sResOut.TrimRight(" \"'\t");
			iFrom=-1;
			return 1;
		}
		if(sLine=="IF"){
			int iDelPos=sParams.Find("==");
			if(iDelPos!=-1){
				CString sLeft=sParams.Left(iDelPos);
				if(sLeft.Find("unescape")==0){
					sLeft=CDataXMLSaver::GetInstringPart("(",")",sLeft);
					sLeft=UnescapeString(sLeft);
				}
				CString sRight=sParams.Mid(iDelPos+2);
				if(sLeft!=sRight){
					iFrom=sBody.Find('}',iFrom);
				}
			}
		}
		if(sLine=="SET_SPEED"){
			double dSpeed=atof(sParams);
			if(dSpeed<0.1){
				dSpeed=1;
			}
		}
		if(sLine=="CALLACTION"){
			if(pCallback){
				pCallback->CallWKAction(atol(sParams));
			}
		}
		if(sLine=="CALLMACRO"){
			if(pCallback){
				pCallback->StartQuickRunByName(sParams,"");
			}
		}
		if(sLine=="WAIT"){
			Sleep(DWORD(atof(sParams)*1000*dSpeed));
		}
		if(sLine=="ACTIVATEWINDOW"){
			sParams.TrimLeft();
			sParams.TrimRight();
			sParams.TrimLeft("\"");
			sParams.TrimRight("\"");
			HWND hActivate=::FindWindow(NULL,sParams);
			if(hActivate){
				::SetForegroundWindow(hActivate);
				::SendMessage(::GetDesktopWindow(), WM_SYSCOMMAND, (WPARAM) SC_HOTKEY, (LPARAM)hActivate);
			}
		}
		if(sLine=="ALERT"){
			AfxMessageBox(sParams);
		}
		if(sLine=="WAITWHILEALLKEYSARERELEASED"){
			if(pCallback){
				pCallback->WaitWhileAllKeysAreReleased();
			}
		}
		if(sLine=="COMMAND"){
			HWND hCur=GetForegroundWindow();
#ifdef _DEBUG
			char szDebugTitle[128]={0};
			GetWindowText(hCur,szDebugTitle,128);
#endif
			CString sTargetByClass=CDataXMLSaver::GetInstringPart("targetByClass=[","]",sParams);
			CString sTargetByTitle=CDataXMLSaver::GetInstringPart("targetByTitle=[","]",sParams);
			if(sTargetByClass!="" || sTargetByTitle!=""){
				hCur=0;// Слать куда попало предназначенные спецклассу мессаги нельзя!
				// Walton Dell <*****@*****.**>
				HWND hTarget=::FindWindow((sTargetByClass!="")?LPCSTR(sTargetByClass):NULL,(sTargetByTitle!="")?LPCSTR(sTargetByTitle):NULL);
				if(hTarget){
					hCur=hTarget;
				}else{
					BOOL bInvis=atol(CDataXMLSaver::GetInstringPart("evenInvisible=[","]",sParams));
					if(bInvis){
						sSearchClass=sTargetByClass;
						sSearchTitle=sTargetByTitle;
						::EnumWindows(EnumFindWndBox,LPARAM(&hTarget));
						if(hTarget){
							hCur=hTarget;
						}
					}
				}
			}
			BOOL bUsedChildWindows=0;
			if(hCur){
				CString sCTargetByID=CDataXMLSaver::GetInstringPart("childTargetByID=[","]",sParams);
				if(sCTargetByID!=""){
					HWND hTarget=::GetDlgItem(hCur,atolx(sCTargetByID));
					if(hTarget){
						bUsedChildWindows=1;
						hCur=hTarget;
					}
				}
				CString sCTargetByClass=CDataXMLSaver::GetInstringPart("childTargetByClass=[","]",sParams);
				CString sCTargetByTitle=CDataXMLSaver::GetInstringPart("childTargetByTitle=[","]",sParams);
				if(sCTargetByClass!="" || sCTargetByClass!=""){
					HWND hTarget=::FindWindowEx(hCur,0,(sCTargetByClass!="")?LPCSTR(sCTargetByClass):NULL,(sCTargetByTitle!="")?LPCSTR(sCTargetByTitle):NULL);
					if(hTarget){
						bUsedChildWindows=1;
						hCur=hTarget;
					}
				}
			}
			{// Выбираем тип и выполняем код
				if(hCur && sParams.Find("activate::")!=-1){
					SwitchToWindow(hCur,TRUE);
				}
				if(sParams.Find("wnd::")!=-1){
					CString sX=CDataXMLSaver::GetInstringPart("x=[","]",sParams);
					long lX=atolx(sX);
					if(sX=="SCREEN_R"){
						lX=rtDesktop.right;
					}
					if(sX=="SCREEN_L"){
						lX=rtDesktop.left;
					}
					CString sY=CDataXMLSaver::GetInstringPart("y=[","]",sParams);
					long lY=atolx(sY);
					if(sY=="SCREEN_B"){
						lY=rtDesktop.bottom;
					}
					if(sY=="SCREEN_T"){
						lY=rtDesktop.top;
					}
					CString sRel=(CDataXMLSaver::GetInstringPart("rel=[","]",sParams));
					long lRel=atolx(sRel);
					sRel.MakeUpper();
					long lSz=atolx(CDataXMLSaver::GetInstringPart("savesize=[","]",sParams));
					long lRb=atolx(CDataXMLSaver::GetInstringPart("rightbottom=[","]",sParams));
					long lCn=atolx(CDataXMLSaver::GetInstringPart("center=[","]",sParams));
					if(hCur){
						HWND hOrif=hCur;
						CRect rt;
						if(!bUsedChildWindows){
							GetWindowTopParent(hCur);
							GetWindowRect(hCur,&rt);
						}else{
							GetClientRect(hCur,&rt);
						}
						CSize sz=rt.Size();
						if(sY=="NOCHANGE_B"){
							lY=rt.bottom;
						}
						if(sY=="NOCHANGE_T"){
							lY=rt.top;
						}
						if(sX=="NOCHANGE_L"){
							lX=rt.left;
						}
						if(sX=="NOCHANGE_R"){
							lX=rt.right;
						}
						/*if(sRel=="CURSOR"){
						CPoint pt;
						GetCursorPos(&pt);
						rt.OffsetRect(lX,lY);
					}*/
						if(lRel || sRel=="RELATIVE"){
							rt.OffsetRect(lX,lY);
						}else if(lSz){
							if(lCn){
								rt.left=(lX-sz.cx)/2;
								rt.top=(lY-sz.cy)/2;
								rt.right=rt.left+sz.cx;
								rt.bottom=rt.top+sz.cy;
							}else if(lRb){
								rt.OffsetRect(lX-rt.right,lY-rt.bottom);
							}else{
								rt.OffsetRect(lX-rt.left,lY-rt.top);
							}
						}else if(lRb){
							rt.right=lX;
							rt.bottom=lY;
						}else{
							rt.left=lX;
							rt.top=lY;
						}
						MoveWindow(hCur,rt.left,rt.top,rt.Width(),rt.Height(),TRUE);
					}
				}
				if(hCur && sParams.Find("cmd::")!=-1){
					DWORD dwMsg=atolx(CDataXMLSaver::GetInstringPart("msg=[","]",sParams));
					LPARAM lPar=atolx(CDataXMLSaver::GetInstringPart("l=[","]",sParams));
					WPARAM wPar=atolx(CDataXMLSaver::GetInstringPart("h=[","]",sParams));
					if(hCur){
						HWND hOrif=hCur;
						if(!bUsedChildWindows){
							GetWindowTopParent(hCur);
						}
						BOOL bRes=0; 
						bRes=::SendMessage(hOrif,dwMsg,wPar,lPar);
					}
				}
				if(sParams.Find("key::")!=-1){
					DWORD dwMsg=atolx(CDataXMLSaver::GetInstringPart("msg=[","]",sParams));
					CString sLow=CDataXMLSaver::GetInstringPart("l=[","]",sParams);
					LPARAM lPar=0;
					if(sLow.GetLength()==9 && sLow[0]=='#'){
						lPar=(hexCode(sLow.Mid(1,2))<<(8*3))+(hexCode(sLow.Mid(3,2))<<(8*2))+(hexCode(sLow.Mid(5,2))<<8)+hexCode(sLow.Mid(7,2));
					}else{
						lPar=atolx(sLow);
					}
					BOOL bKeyDown=atolx(CDataXMLSaver::GetInstringPart("keydown=[","]",sParams));
					DWORD dwVK=LOBYTE(lPar);
					DWORD dwScan=HIBYTE(lPar);
					BOOL bExtended=atolx(CDataXMLSaver::GetInstringPart("ext=[","]",sParams));;
					::keybd_event(BYTE(dwVK), BYTE(dwScan), (bKeyDown?0:KEYEVENTF_KEYUP)|(bExtended?KEYEVENTF_EXTENDEDKEY:0), 0);
				}
				if(sParams.Find("mou::")!=-1){
					DWORD dwMsg=atolx(CDataXMLSaver::GetInstringPart("msg=[","]",sParams));
					long dwX=atolx(CDataXMLSaver::GetInstringPart("x=[","]",sParams));
					long dwY=atolx(CDataXMLSaver::GetInstringPart("y=[","]",sParams));
					// Если все относительно, то колбасим...
					CString sRel=(CDataXMLSaver::GetInstringPart("rel=[","]",sParams));
					sRel.MakeUpper();
					int dwRel=atolx(sRel);
					if(dwRel>0 || sRel=="WINDOW" || sRel=="RELATIVE"){
						if(hCur){
							CRect rt;
							GetWindowRect(hCur,&rt);
							dwX+=rt.left;
							dwY+=rt.top;
						}else{
							// Относительные клики без активного окна скипаем нахрен!
							return 0;
						}
					}
					if(dwRel<0 || sRel=="CURSOR"){
						CPoint pt;
						GetCursorPos(&pt);
						dwX+=pt.x;
						dwY+=pt.y;
					}
					dwX=long(65536*double(dwX)/double(rtDesktop.Width()));
					dwY=long(65536*double(dwY)/double(rtDesktop.Height()));
					if(dwMsg!=WM_MOUSEMOVE){// Сначала двигаем
						::mouse_event(
							MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE
							,dwX
							,dwY
							,0,0);
					}
					if(dwMsg==WM_LBUTTONDOWN){
						dwMsg=MOUSEEVENTF_LEFTDOWN;
					}else if(dwMsg==WM_LBUTTONUP){
						dwMsg=MOUSEEVENTF_LEFTUP;
					}else if(dwMsg==WM_RBUTTONDOWN){
						dwMsg=MOUSEEVENTF_RIGHTDOWN;
					}else if(dwMsg==WM_RBUTTONUP){
						dwMsg=MOUSEEVENTF_RIGHTUP;
					}else if(dwMsg==WM_MBUTTONDOWN){
						dwMsg=MOUSEEVENTF_MIDDLEDOWN;
					}else if(dwMsg==WM_MBUTTONUP){
						dwMsg=MOUSEEVENTF_MIDDLEUP;
					}else{
						dwMsg=MOUSEEVENTF_MOVE;
					}
					::mouse_event(
						MOUSEEVENTF_ABSOLUTE|dwMsg
						,dwX
						,dwY
						,0,0);
				}
			}
		}
	}
	return 0;
}