Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: f718950a327ac9234f7c2f21c7b27910c948472a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*******************************************************************************
 * Copyright (c) 2008, 2010 Ericsson and others.
 * All rights reserved. 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
 *
 * Contributors:
 *     Ericsson - Initial API and implementation
 *     Wind River Systems - refactored to match pattern in package
 *     John Dallaway - GDB 7.x getOsId() pattern match too restrictive (Bug 325552)
 *******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.cdt.dsf.concurrent.Immutable;

/**
 * GDB/MI Thread tuple parsing.
 * 
 * @since 1.1
 */
@Immutable
public class MIThread {

	/** @since 4.1 */
	public final static String MI_THREAD_STATE_RUNNING = "running"; //$NON-NLS-1$
	/** @since 4.1 */
	public final static String MI_THREAD_STATE_STOPPED = "stopped"; //$NON-NLS-1$
	
	final private String       fThreadId;
	final private String       fTargetId;
	final private String       fOsId;
	final private String       fParentId;
	final private MIFrame      fTopFrame;
	final private String       fDetails;
	final private String       fState;
	final private String       fCore;
	
	private MIThread(String threadId, String targetId, String osId, String parentId,
			          MIFrame topFrame, String details, String state, String core) {
		fThreadId  = threadId;
		fTargetId  = targetId;
		fOsId      = osId;
		fParentId  = parentId;
		fTopFrame  = topFrame;
		fDetails   = details;
		fState     = state;
		fCore      = core;
	}

	public String getThreadId()       { return fThreadId; }
	public String getTargetId()       { return fTargetId; }
	public String getOsId()           { return fOsId;     }
	public String getParentId()       { return fParentId; }
	public MIFrame getTopFrame()      { return fTopFrame; } 
	public String getDetails()        { return fDetails;  }
	public String getState()          { return fState;    }
	/**
	 * Available since GDB 7.1
	 * @since 4.0
	 */
	public String getCore()           { return fCore; }
	
	public static MIThread parse(MITuple tuple) {
        MIResult[] results = tuple.getMIResults();

        String threadId = null;
        String targetId = null;
        String osId = null;
        String parentId = null;
        MIFrame topFrame = null;
        String state = null;
        String details = null;
        String core = null;

        for (int j = 0; j < results.length; j++) {
            MIResult result = results[j];
            String var = result.getVariable();
            if (var.equals("id")) { //$NON-NLS-1$
                MIValue val = results[j].getMIValue();
                if (val instanceof MIConst) {
                    threadId = ((MIConst) val).getCString().trim();
                }
            }
            else if (var.equals("target-id")) { //$NON-NLS-1$
                MIValue val = results[j].getMIValue();
                if (val instanceof MIConst) {
                    targetId = ((MIConst) val).getCString().trim();
                    osId = parseOsId(targetId);
                    parentId = parseParentId(targetId);
                }
            }
            else if (var.equals("frame")) { //$NON-NLS-1$
                MITuple val = (MITuple)results[j].getMIValue();
                topFrame = new MIFrame(val);
            }
            else if (var.equals("state")) { //$NON-NLS-1$
                MIValue val = results[j].getMIValue();
                if (val instanceof MIConst) {
                    state = ((MIConst) val).getCString().trim();
                }
            }
            else if (var.equals("details")) { //$NON-NLS-1$
                MIValue val = results[j].getMIValue();
                if (val instanceof MIConst) {
                    details = ((MIConst) val).getCString().trim();
                }
            }
            else if (var.equals("core")) { //$NON-NLS-1$
                MIValue val = results[j].getMIValue();
                if (val instanceof MIConst) {
                    core = ((MIConst) val).getCString().trim();
                }
            }
        }
        
        return new MIThread(threadId, targetId, osId, parentId, topFrame, details, state, core);
	}
	
	// Note that windows gdbs returns lower case "thread" , so the matcher needs to be case-insensitive. 
    private static Pattern fgOsIdPattern1 = Pattern.compile("([Tt][Hh][Rr][Ee][Aa][Dd]\\s*)(0x[0-9a-fA-F]+|-?\\d+)(\\s*\\([Ll][Ww][Pp]\\s*)(\\d*)", 0); //$NON-NLS-1$
    private static Pattern fgOsIdPattern2 = Pattern.compile("[Tt][Hh][Rr][Ee][Aa][Dd]\\s*\\d+\\.(\\d+)", 0); //$NON-NLS-1$
    private static Pattern fgOsIdPattern3 = Pattern.compile("[Tt][Hh][Rr][Ee][Aa][Dd]\\s*(\\S+)", 0); //$NON-NLS-1$

    static String parseOsId(String str) {
        // General format:
        //      "Thread 0xb7c8ab90 (LWP 7010)"
    	//                              ^^^^
        //      "Thread 162.32942"
    	//                  ^^^^^
        //      "thread abc123"
    	//              ^^^^^^
    	// PLEASE UPDATE MIThreadTests.java IF YOU TWEAK THIS CODE

        Matcher matcher = fgOsIdPattern1.matcher(str);
        if (matcher.find()) {
            return matcher.group(4);
        }
        
        matcher = fgOsIdPattern2.matcher(str);
        if (matcher.find()) {
            return matcher.group(1);
        }
        
        matcher = fgOsIdPattern3.matcher(str);
        if (matcher.find()) {
        	return matcher.group(1);
        }

        return null;
    }
    
    private static Pattern fgIdPattern = Pattern.compile("[Tt][Hh][Rr][Ee][Aa][Dd]\\s*(\\d+)\\.\\d+", 0); //$NON-NLS-1$ 

	/**
	 * This is used to parse the same ID fed to {@link #parseOsId(String)}. The
	 * difference is that we return the first portion when the ID is in format
	 * "Thread pppp.tttt". If the ID is not in that format, we return null.
	 */
    static String parseParentId(String str) {
        // General format:
        //      "Thread 162.32942"
    	//              ^^^
    	// PLEASE UPDATE MIThreadTests.java IF YOU TWEAK THIS CODE    	

        Matcher matcher = fgIdPattern.matcher(str);
        if (matcher.find()) {
            return matcher.group(1);
        }
        
        return null;
    }

}

Back to the top