/*******************************************************************************
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.apache.kato.katoview.commands;
import java.util.HashMap;
import java.util.Stack;
import java.util.Vector;
import javax.tools.diagnostics.image.Image;
import org.apache.kato.katoview.Output;
import org.apache.kato.katoview.commands.xcommands.XDCommand;
import org.apache.kato.katoview.commands.xcommands.XJCommand;
import org.apache.kato.katoview.commands.xcommands.XKCommand;
import org.apache.kato.katoview.commands.xcommands.XXCommand;
public class XCommand extends Command {
public XCommand(Output o){
super(o, "x/", "works like \"x/\" in gdb (including use of defaults): passes " +
"number of items to display and unit " +
"size ('b' for byte, 'h' for halfword, 'w' for word, 'g' for giant " +
"word) to sub-command (ie. x/12bd)",
""
);
child_commands = new Vector();
child_commands.add(new XJCommand(o));
child_commands.add(new XDCommand(o));
child_commands.add(new XXCommand(o));
child_commands.add(new XKCommand(o));
// note: do NOT add any of the following:
// - XBCommand
// - XHCommand
// - XWCommand
// - XGCommand
// why not? because 'b', 'h', 'w', and 'g' represent unit sizes and
// the parser won't know whether you mean a unit size or a display format
// if you use any of the above characters for a display format
}
public void doCommand(Stack args, Image loadedImage, HashMap properties)
{
String arg;
if (!args.isEmpty())
{
arg = (String)args.pop();
}
else
{
out.error("\"x/\" command requires additional parameters");
return;
}
int n;
Character unitSize;
Character displayFormat;
if (null == arg || arg.equals(""))
{
// user didn't specify any parameters; use the defaults
n = 1;
unitSize = getDefaultUnitSize(properties);
displayFormat = getDefaultDisplayFormat(properties);
}
else
{
n = 0;
int i;
for (i = 0; i < arg.length() && Character.isDigit(arg.charAt(i)); i++)
{
n *= 10;
n += Character.getNumericValue(arg.charAt(i));
}
if (0 == n)
n = 1;
displayFormat = null;
unitSize = null;
if (i < arg.length())
{
char currChar = arg.charAt(i);
switch (currChar)
{
case 'b':
case 'h':
case 'w':
case 'g':
unitSize = new Character(currChar);
break;
default:
displayFormat = new Character(currChar);
break;
}
i++;
}
if (i < arg.length())
{
char currChar = arg.charAt(i);
switch (currChar)
{
case 'b':
case 'h':
case 'w':
case 'g':
if (null == unitSize)
{
unitSize = new Character(currChar);
}
else
{
out.error("first letter after \"x/\" was a unit size character; " +
"second letter (if specified) must be a display " +
"format letter but it was also a unit size character");
return;
}
break;
default:
if (null == displayFormat)
{
displayFormat = new Character(currChar);
}
else
{
out.error("first letter after \"x/\" was a display format character; " +
"second letter (if specified) must be a unit size " +
"letter but it was also a display format character");
return;
}
break;
}
i++;
}
if (arg.length() != i)
{
out.error("too many letters after \"x/\"; the \"x/\" command accepts at " +
"most two letters, a display format character and a unit " +
"size character");
return;
}
// we now have all the necessary information to put on the stack (except
// for the unspecified parameters that assume use of defaults) so let's
// get the required default values and push some parameters back on to
// the argument stack
if (null == unitSize) {
unitSize = getDefaultUnitSize(properties);
} else {
setDefaultUnitSize(properties, unitSize);
}
if (null == displayFormat) {
displayFormat = getDefaultDisplayFormat(properties);
} else {
setDefaultDisplayFormat(properties, displayFormat);
}
}
Integer nUnitSize = null;
char cUnitSize = unitSize.charValue();
switch (cUnitSize)
{
case 'b':
nUnitSize = new Integer(1);
break;
case 'h':
nUnitSize = new Integer(2);
break;
case 'w':
nUnitSize = new Integer(4);
break;
case 'g':
nUnitSize = new Integer(8);
break;
}
// we can pretty much guarantee that nUnitSize is not null here because
// unitSize has to be one of the above 4 characters if it isn't null
args.push(nUnitSize); // add the unit size to the stack
args.push(new Integer(n)); // add the number of units to print to the stack
args.push(displayFormat.toString()); // add the display format as a String
super.doCommand(args, loadedImage, properties);
}
private Character getDefaultUnitSize(HashMap properties)
{
Character defaultUnitSize = (Character)properties.get("x_default_unit_size");
if (null == defaultUnitSize)
return new Character('w');
else
return defaultUnitSize;
}
private Character getDefaultDisplayFormat(HashMap properties)
{
Character defaultDisplayFormat = (Character)properties.get("x_default_display_format");
if (null == defaultDisplayFormat)
return new Character('x');
else
return defaultDisplayFormat;
}
private void setDefaultUnitSize(HashMap properties, Character defaultUnitSize)
{
properties.put("x_default_unit_size", defaultUnitSize);
}
private void setDefaultDisplayFormat(HashMap properties, Character defaultDisplayFormat)
{
properties.put("x_default_display_format", defaultDisplayFormat);
}
}