blob: e31aa88df2e94812871cceb7ea0a8961ca200c97 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 The Regents of the University of California.
* This material was produced under U.S. Government contract W-7405-ENG-36
* for Los Alamos National Laboratory, which is operated by the University
* of California for the U.S. Department of Energy. The U.S. Government has
* rights to use, reproduce, and distribute this software. NEITHER THE
* GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified
* to produce derivative works, such modified software should be clearly marked,
* so as not to confuse it with the version available from LANL.
*
* Additionally, this program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* LA-CC 04-115
*******************************************************************************/
/**
* @author Clement chu
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "MIList.h"
#include "MIResult.h"
#include "MIValue.h"
#include "MIOOBRecord.h"
#include "MISignalInfo.h"
#include "CLIOutput.h"
static int
getBoolean(char* value)
{
if (value != NULL && strncmp(value, "Yes", 3) == 0) {
return 1;
}
return 0;
}
void
CLIGetSigHandleList(MICommand *cmd, MIList** signals)
{
MIList *oobs;
MIOOBRecord *oob;
MISignalInfo *sig;
char *text = NULL;
char *token;
char *pch;
int i;
const char* delims[] = { " ", "\\" };
*signals = MIListNew();
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL)
return;
oobs = cmd->output->oobs;
for (MIListSet(oobs); (oob = (MIOOBRecord *)MIListGet(oobs)) != NULL; ) {
text = oob->cstring;
if (*text == '\0' || *text == '\\') {
continue;
}
if (strncmp(text, "Signal", 6) != 0 && strncmp(text, "Use", 3) != 0 && strncmp(text, "info", 4) != 0) {
token = strdup(text);
pch = strstr(token, delims[0]);
if (pch == NULL) {
continue;
}
sig = MISignalInfoNew();
for (i=0; pch != NULL; i++,pch=strstr(token, delims[1])) {
if (*pch == '\0') {
break;
}
*pch = '\0';
pch++;
while (*pch == ' ' || *pch =='t') { //remove whitespace or t character
pch++;
}
if (*pch == '\\') { //ignore '\\t' again
pch += 2;
}
switch(i) {
case 0:
sig->name = strdup(token);
break;
case 1:
sig->stop = getBoolean(token);
break;
case 2:
sig->print = getBoolean(token);
break;
case 3:
sig->pass = getBoolean(token);
break;
case 4:
sig->desc = strdup(token);
break;
}
token = strdup(pch);
}
free(token);
free(pch);
MIListAdd(*signals, (void *)sig);
}
}
}
double
CLIGetGDBVersion(MICommand *cmd)
{
MIList * oobs;
MIOOBRecord * oob;
char * text;
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL) {
return -1.0;
}
if (cmd->output->rr != NULL && cmd->output->rr->resultClass == MIResultRecordERROR) {
return -1.0;
}
oobs = cmd->output->oobs;
for (MIListSet(oobs); (oob = (MIOOBRecord *)MIListGet(oobs)) != NULL; ) {
text = oob->cstring;
if (*text == '\0') {
continue;
}
while (*text == ' ') {
text++;
}
/*
* Linux: GUN gdb 6.5.0
* Fedora: GNU gdb Red Hat Linux (6.5-8.fc6rh)
* Mac OS X: GNU gdb 6.1-20040303 (Apple version gdb-384) (Mon Mar 21 00:05:26 GMT 2005)
* Ubuntu: GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
*/
if (strncmp(text, "GNU gdb", 7) == 0) {
/*
* bypass "GNU gdb"
*/
text += 8;
/*
* find first digit
*/
while (*text != '\0' && !isdigit(*text))
text++;
/*
* Convert whatever is here to a double
*/
if (*text != '\0')
return strtod(text, NULL);
}
}
return -1.0;
}
/*
* Attempt to fix up the type information returned by the ptype command.
*
* - Replace newlines and tabs with spaces and replace multiple spaces with a single space.
* - Remove "\\n" sequences.
* - Discard '{' and any following characters
*
* Space allocated for the result must be freed by the caller.
*/
static char *
fix_type(char *str)
{
int finished = 0;
int seen_space = 0;
int seen_backslash = 0;
char * s = str;
char * r;
char * result = (char *)malloc(strlen(str));
/*
* Remove leading whitespace
*/
while (isspace(*s)) {
s++;
}
for (r = result; *s != '\0' && !finished; s++) {
switch (*s) {
case ' ':
case '\n':
case '\t':
if (!seen_space) {
*r++ = ' ';
seen_space = 1;
}
break;
case '\\':
seen_backslash = 1;
break;
case '{':
finished = 1;
break;
default:
if (!seen_backslash) {
*r++ = *s;
}
seen_backslash = 0;
seen_space = 0;
}
}
*r = '\0';
/*
* Remove trailing whitespace
*/
r--;
while (isspace(*r) && r >= result) {
*r-- = '\0';
}
return result;
}
char *
CLIGetPTypeInfo(MICommand *cmd)
{
MIList * oobs;
MIOOBRecord * oob;
char * text = NULL;
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL)
return NULL;
oobs = cmd->output->oobs;
for (MIListSet(oobs); (oob = (MIOOBRecord *)MIListGet(oobs)) != NULL; ) {
text = oob->cstring;
if (*text == '\0') {
continue;
}
while (*text == ' ') {
text++;
}
if (strncmp(text, "type =", 6) == 0) {
text += 6;
text = fix_type(text);
if (strlen(text) == 0) {
/*
* Look at next line for type
*/
oob = (MIOOBRecord *)MIListGet(oobs);
if (oob != NULL) {
free(text);
text = fix_type(oob->cstring);
}
}
return text;
}
}
return NULL;
}
CLIInfoThreadsInfo *
CLIInfoThreadsInfoNew(void)
{
CLIInfoThreadsInfo * info;
info = (CLIInfoThreadsInfo *)malloc(sizeof(CLIInfoThreadsInfo));
info->current_thread_id = 1;
info->thread_ids = NULL;
return info;
}
void
CLIInfoThreadsInfoFree(CLIInfoThreadsInfo *info)
{
if (info->thread_ids != NULL)
MIListFree(info->thread_ids, free);
free(info);
}
CLIInfoThreadsInfo *
CLIGetInfoThreadsInfo(MICommand *cmd)
{
MIList * oobs;
MIOOBRecord * oob;
CLIInfoThreadsInfo * info = CLIInfoThreadsInfoNew();
char * text = NULL;
char * id = NULL;
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL) {
return info;
}
if (cmd->output->rr != NULL && cmd->output->rr->resultClass == MIResultRecordERROR) {
return info;
}
oobs = cmd->output->oobs;
info->thread_ids = MIListNew();
for (MIListSet(oobs); (oob = (MIOOBRecord *)MIListGet(oobs)) != NULL; ) {
text = oob->cstring;
if (*text == '\0') {
continue;
}
while (*text == ' ') {
text++;
}
if (strncmp(text, "*", 1) == 0) {
text += 2;//escape "* ";
if (isdigit(*text)) {
info->current_thread_id = strtol(text, &text, 10);
}
continue;
}
if (isdigit(*text)) {
if (info->thread_ids == NULL)
info->thread_ids = MIListNew();
id = strchr(text, ' ');
if (id != NULL) {
*id = '\0';
MIListAdd(info->thread_ids, (void *)strdup(text));
}
}
}
return info;
}
CLIInfoProcInfo *
CLIInfoProcInfoNew()
{
CLIInfoProcInfo * info;
info = (CLIInfoProcInfo *)malloc(sizeof(CLIInfoProcInfo));
info->pid = -1;
info->cmdline = NULL;
info->cwd = NULL;
info->exe = NULL;
return info;
}
void
CLIInfoProcInfoFree(CLIInfoProcInfo *info)
{
if (info->cmdline != NULL) {
free(info->cmdline);
}
if (info->cwd != NULL) {
free(info->cwd);
}
if (info->exe != NULL) {
free(info->exe);
}
free(info);
}
char *
CLIGetCurrentSourceLine(MICommand *cmd)
{
MIList * oobs;
MIOOBRecord * oob;
char * text = NULL;
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL) {
return NULL;
}
if (cmd->output->rr != NULL && cmd->output->rr->resultClass == MIResultRecordERROR) {
return NULL;
}
oobs = cmd->output->oobs;
//Skip the first record, which is "list\n"
MIListSet(oobs);
MIListGet(oobs);
oob = (MIOOBRecord *)MIListGet(oobs);
if (oob != NULL)
{
text = oob->cstring;
if (text != NULL)
{
return strdup(text);
}
else
{
return NULL;
}
}
return NULL;
}
char *
CLIGetPrintInfo(MICommand *cmd)
{
MIList * oobs;
MIOOBRecord * oob;
char * text = NULL;
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL) {
return NULL;
}
if (cmd->output->rr != NULL && cmd->output->rr->resultClass == MIResultRecordERROR) {
return NULL;
}
oobs = cmd->output->oobs;
//Skip the first record, which is "list\n"
MIListSet(oobs);
MIListGet(oobs);
oob = (MIOOBRecord *)MIListGet(oobs);
if (oob != NULL)
{
text = oob->cstring;
if (text != NULL)
{
return strdup(text);
}
else
{
return NULL;
}
}
return NULL;
}
#ifdef __APPLE__
CLIInfoProcInfo *
CLIGetInfoProcInfo(MICommand *cmd)
{
char * str = "";
MIResult * result;
MIValue * value;
MIResultRecord * rr;
CLIInfoProcInfo * info = CLIInfoProcInfoNew();
if (!cmd->completed || cmd->output == NULL || cmd->output->rr == NULL)
return info;
rr = cmd->output->rr;
for (MIListSet(rr->results); (result = (MIResult *)MIListGet(rr->results)) != NULL; ) {
value = result->value;
if (value->type == MIValueTypeConst) {
str = value->cstring;
}
if (strcmp(result->variable, "process-id") == 0) {
info->pid = (int)strtol(str, NULL, 10);
}
}
return info;
}
#else /* __APPLE__ */
CLIInfoProcInfo *
CLIGetInfoProcInfo(MICommand *cmd)
{
int len;
MIList * oobs;
MIOOBRecord * oob;
char * text = NULL;
CLIInfoProcInfo * info = CLIInfoProcInfoNew();
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL)
return info;
oobs = cmd->output->oobs;
for (MIListSet(oobs); (oob = (MIOOBRecord *)MIListGet(oobs)) != NULL; ) {
text = oob->cstring;
if (*text == '\0') {
continue;
}
while (*text == ' ') {
text++;
}
if (strncmp(text, "process", 7) == 0) {
text += 8; /* bypass " " */
if (text != NULL) {
info->pid = (int)strtol(text, NULL, 10);
}
} else if (strncmp(text, "cmdline", 7) == 0) {
text += 11; /* bypass " = '" */
len = strlen(text) - 1; /* exclude "'" */
info->cmdline = (char *)malloc(len + 1);
memcpy(info->cmdline, text, len);
info->cmdline[len] = '\0';
} else if (strncmp(text, "cwd", 3) == 0) {
text += 7; /* bypass " = '" */
len = strlen(text) - 1; /* exclude "'" */
info->cwd = (char *)malloc(len + 1);
memcpy(info->cwd, text, len);
info->cwd[len] = '\0';
} else if (strncmp(text, "exe", 3) == 0) {
text += 7; /* bypass " = '" */
len = strlen(text) - 1; /* exclude "'" */
info->exe = (char *)malloc(len + 1);
memcpy(info->exe, text, len);
info->exe[len] = '\0';
}
}
return info;
}
#endif /* __APPLE__ */
char *
CLIGetHexValueLineFromPrintInfo(MICommand *cmd)
{
MIList * oobs;
MIOOBRecord * oob;
char * text = NULL;
if (!cmd->completed || cmd->output == NULL || cmd->output->oobs == NULL) {
return NULL;
}
if (cmd->output->rr != NULL && cmd->output->rr->resultClass == MIResultRecordERROR) {
return NULL;
}
oobs = cmd->output->oobs;
//Skip the first record, which is "list\n"
MIListSet(oobs);
MIListGet(oobs);
oob = (MIOOBRecord *)MIListGet(oobs);
while (oob != NULL)
{
text = oob->cstring;
if (text != NULL && strstr(text, "0x"))
{
return strdup(text);
}
oob = (MIOOBRecord *)MIListGet(oobs);
}
return NULL;
}