| /******************************************************************************* |
| * 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; |
| } |
| |