Files
2025-10-14 09:52:32 +09:00

274 lines
7.8 KiB
C

/* *********************************************************************************************
* @Title: TRACE32 Remote API that use T32_Cmd() and T32_GetMessage()
* @Description:
* TRACE32 Remote API sample program illustrating the use of T32_Cmd() and T32_GetMessage()
* This demo send a command to TRACE32 PowerView and request any AREA message.
* Syntax: t32apicmd [node=<name_or_IP>] [port=<num>] <cmd>
* Example: t32apicmd node=localhost port=20000 PRINT VERSION.BUILD()
*
* For remote access TRACE32's configuration file "config.t32" has to contain these lines:
*
* RCL=NETASSIST
* PORT=20000
*
* This default port value may be changed but has to match the specified command line value.
*
* This sample program also shows how to establish and close a remote connection with TRACE32.
*
* $Id: t32apicmd.c 168148 2024-03-28 16:57:07Z irohloff $
* $LastChangedRevision: 168148 $
* $LastChangedBy: irohloff $
*
* @Copyright: (C) 1989-2020 Lauterbach GmbH, licensed for use with TRACE32(R) only
* *********************************************************************************************
* $Id: t32apicmd.c 168148 2024-03-28 16:57:07Z irohloff $
*/
#define WIN_MESSAGEMODENONE 0x00
#define WIN_MESSAGEMODEINFO 0x01
#define WIN_MESSAGEMODEERROR 0x02
#define WIN_MESSAGEMODESTATE 0x04
#define WIN_MESSAGEMODEWARNINFO 0x08
#define WIN_MESSAGEMODEERRORINFO 0x10
#define WIN_MESSAGEMODETEMP 0x20
#define WIN_MESSAGEMODETEMPINFO 0x40
#include "t32.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
uintptr_t indexOf_shift(char* base, char* str, size_t startIndex)
{
size_t baselen = strlen(base);
char* pos = NULL;
// str should not longer than base
if ((strlen(str) > baselen) || (startIndex > baselen))
return -1;
if (startIndex < 0 ) {
startIndex = 0;
}
pos = strstr(base+startIndex, str);
if (pos == NULL)
return -1;
return pos - base;
}
uintptr_t lastIndexOf(char* base, char* str)
{
uintptr_t start;
uintptr_t endinit;
uintptr_t end;
uintptr_t endtmp;
// str should not longer than base
if (strlen(str) > strlen(base))
return -1;
start = 0;
endinit = strlen(base) - strlen(str);
end = endinit;
endtmp = endinit;
while (start != end) {
start = indexOf_shift(base, str, start);
end = indexOf_shift(base, str, end);
// not found from start
if (start == -1) {
end = -1; // then break;
} else if (end == -1) {
// found from start
// but not found from end
// move end to middle
if (endtmp == (start+1)) {
end = start; // then break;
} else {
end = endtmp - (endtmp - start) / 2;
if (end <= start) {
end = start+1;
}
endtmp = end;
}
} else {
// found from both start and end
// move start to end and
// move end to base - strlen(str)
start = end;
end = endinit;
}
}
return start;
}
static int executeCommand(const char *cmdstring)
{
uint16_t msgtype;
char msgstring[4095];
/* bugfix: calling T32_Cmd("PRINT") first ensures */
/* that T32_GetMessage() will return no old message */
if (T32_Cmd("PRINT") != T32_OK) {
printf(" Failed to execute 'T32_Cmd(""PRINT"")'\n\n" );
return EXIT_FAILURE;
}
if (T32_Cmd(cmdstring) != T32_OK) {
printf(" Failed to execute erroneous user command '%s'\n\n", cmdstring);
return EXIT_FAILURE;
}
if (T32_GetMessage(msgstring, &msgtype) != T32_OK) {
printf(" Failed to query return message.\n\n");
return EXIT_FAILURE;
}
if (msgtype >= (WIN_MESSAGEMODETEMPINFO << 1)) {
printf(" Failed to determine the type of the return message.\n\n");
return EXIT_FAILURE;
}
if (
msgtype == WIN_MESSAGEMODENONE ||
/* bugfix: for empty message the message type may be temp => DO NOT DISPLAY */
(msgstring[0] == 0 && (msgtype & (WIN_MESSAGEMODETEMPINFO|WIN_MESSAGEMODETEMP)) != 0)
) {
printf(" successfully executed user command '%s'\n\n", cmdstring);
return EXIT_SUCCESS;
}
if (msgtype & WIN_MESSAGEMODEINFO)
printf(" info");
if (msgtype & WIN_MESSAGEMODESTATE)
printf(" status");
if (msgtype & WIN_MESSAGEMODEWARNINFO)
printf(" warning");
if ((msgtype & WIN_MESSAGEMODEERRORINFO) || (msgtype & WIN_MESSAGEMODEERROR))
printf(" error");
if ((msgtype & WIN_MESSAGEMODETEMPINFO) || (msgtype & WIN_MESSAGEMODETEMP))
printf(" miscellaneous");
printf(" message: %s\n\n", msgstring);
return EXIT_SUCCESS;
}
int main(int argc, char **argv)
{
size_t i = 0;
size_t j = 0;
int argn = 1;
int retval = EXIT_SUCCESS;
char cmdstring[2041];
size_t index = lastIndexOf(__FILE__, ".");
char filename [100];
if (index == -1 ) {
strcpy(filename,__FILE__);
} else {
strncpy(filename, __FILE__, index);
}
/*** get command line parameters and establish connection ************************************/
if ((argc > argn) && (!strncmp(argv[argn], "node=", 5) || !strncmp(argv[argn], "NODE=", 5))) {
T32_Config("NODE=", argv[argn] + 5);
argn++;
}
if ((argc > argn) && (!strncmp(argv[argn], "port=", 5) || !strncmp(argv[argn], "PORT=", 5))) {
if (T32_Config("PORT=", argv[argn] + 5) != T32_OK) {
printf("\n\n Invalid port number '%s' specified.\n", argv[argn] + 5);
retval = EXIT_FAILURE;
}
argn++;
}
if ((argc <= argn) || (retval == EXIT_FAILURE)) {
printf("\n\n Syntax: %s.exe [node=<name_or_IP>] [port=<num>] <cmd>", filename);
printf( "\n Example: %s.exe node=localhost port=20000 PRINT VERSION.BUILD()\n\n\n", filename);
printf(" Messages printed to TRACE32 AREA window are also printed to this\n");
printf(" shell. Most PRACTICE commands like Go only generate a message in\n");
printf(" case of an error. Escaping is important if the PRINT command is\n");
printf(
" used (try PRINT \042\042\042hi\042\042\042 and"
" PRINT \042\042\042\042\042\042\042hi\042\042\042\042\042\042\042).\n\n"
);
return EXIT_FAILURE;
}
/* PRINT """hi""" and PRINT """""""hi""""""" work this way: */
/* If a command line argument/string is enclosed by quotes, it loses one opening and one closing */
/* quote when the string is stored in argv, so ""hi"" and """"""hi"""""" will be left. For the */
/* input-data of T32_Cmd() the C-language's standard quote-sign-escaping is applied, so "hi" and */
/* """hi""" are transfered to TRACE32 PowerView. TRACE32 expects strings to be enclosed by quotes */
/* and standard quote-sign-escaping is expected for further quotes, so hi and "hi" are printed. */
printf("\n\n Connecting... ");
fflush(stdout);
i = 0;
for(;;) {
i++;
if (i >= 3)
return EXIT_FAILURE;
if (i > 1) {
printf(" ");
fflush(stdout);
}
if (T32_Init() != T32_OK) {
T32_Exit();
if (i==1)
printf("Failed once ");
else
printf("Failed twice");
printf(" to initialize the remote connection.");
if (i >= 2)
printf(" Terminating...");
printf("\n");
continue;
}
if (T32_Attach(T32_DEV_ICD) == T32_OK)
break;
T32_Exit();
if (i==1)
printf("Failed once ");
else
printf("Failed twice");
printf(" to establish a remote connection with TRACE32 PowerView.");
if (i >= 2)
printf(" Terminating ...");
printf("\n");
}
printf("\r Successfully established a remote connection with TRACE32 PowerView.\n");
/*** send input command to TRACE32 PowerView for execution and return any message ************/
for (i = argn; i < argc; i++)
j += strlen(argv[i]); /* see T32_Cmd(),MaxPacketSize in hremote.c */
if ((j + argc - argn - 1 > 2048 - 8) || (sizeof(cmdstring) != 2041)) {
printf(" Failed to send remote command, command exceeds 2040 characters.\n");
return EXIT_FAILURE;
}
strcpy(cmdstring, argv[argn]);
while (++argn < argc) {
strcat(cmdstring, " ");
strcat(cmdstring, argv[argn]);
}
retval = executeCommand(cmdstring);
if (T32_Exit() != T32_OK) {
printf(" Failed to close the remote connection port on the dos shell application's side.\n\n");
return EXIT_FAILURE;
}
return retval;
}