Tue Apr 26 17:44:27 1994 Stan Shebs (shebs@andros.cygnus.com)

* mpw-make.in (MacGDB): New target, standalone Mac-hosted gdb.
	(XDEPFILES): Define.
	(main.c.o): Compile with gC instead of C.
	* mac-defs.h: New file, menu etc definitions shared between
	C and Rez files.
	* macgdb.r: New file, Rez (resource compiler) resource
	definitions.
	* mac-xdep.c: New file, Mac host interface code.
	* config/m68k/xm-mpw.h (PATHNAME_SEPARATOR): Rename to
	DIRNAME_SEPARATOR.
	(PATHNAME_SEPARATOR_STRING): Remove.
	(SIGQUIT, SIGHUP): Define.
	(fileno, R_OK): Define.
This commit is contained in:
Stan Shebs 1994-04-27 00:55:59 +00:00
parent 028f887219
commit 939baabee2
6 changed files with 864 additions and 5 deletions

View File

@ -1,3 +1,19 @@
Tue Apr 26 17:44:27 1994 Stan Shebs (shebs@andros.cygnus.com)
* mpw-make.in (MacGDB): New target, standalone Mac-hosted gdb.
(XDEPFILES): Define.
(main.c.o): Compile with gC instead of C.
* mac-defs.h: New file, menu etc definitions shared between
C and Rez files.
* macgdb.r: New file, Rez (resource compiler) resource
definitions.
* mac-xdep.c: New file, Mac host interface code.
* config/m68k/xm-mpw.h (PATHNAME_SEPARATOR): Rename to
DIRNAME_SEPARATOR.
(PATHNAME_SEPARATOR_STRING): Remove.
(SIGQUIT, SIGHUP): Define.
(fileno, R_OK): Define.
Thu Mar 10 15:49:05 1994 Stan Shebs (shebs@andros.cygnus.com)
* mpw-config.in: New file, MPW configuration fragment.

View File

@ -86,10 +86,29 @@ char *strdup (char *s1);
#define GDBINIT_FILENAME "_gdbinit"
#define PATHNAME_SEPARATOR ','
/* Commas are more common to separate dirnames in a path on Macs. */
#define PATHNAME_SEPARATOR_STRING ","
#define DIRNAME_SEPARATOR ','
/* This is a real crufty hack. */
#define HAVE_TERMIO
/* Addons to the basic MPW-supported signal list. */
#ifndef SIGQUIT
#define SIGQUIT (1<<6)
#endif
#ifndef SIGHUP
#define SIGHUP (1<<7)
#endif
/* If __STDC__ is on, then this definition will be missing. */
#ifndef fileno
#define fileno(p) (p)->_file
#endif
#ifndef R_OK
#define R_OK 4
#endif

34
gdb/mac-defs.h Normal file
View File

@ -0,0 +1,34 @@
/* Definitions shared between C and Rez files. */
#define mbMain 128
#define mApple 128
#define miAbout 1
#define mFile 129
#define miFileNew 1
#define miFileOpen 2
/* 3 */
#define miFileQuit 4
#define mEdit 130
#define miEditCut 1
#define miEditCopy 2
#define miEditPaste 3
#define miEditClear 4
#define mDebug 131
#define miDebugTarget 1
/* 2 */
#define miDebugRun 3
#define miDebugContinue 4
#define miDebugStep 5
#define miDebugNext 6
#define wConsole 128

630
gdb/mac-xdep.c Normal file
View File

@ -0,0 +1,630 @@
/* Top level support for Mac interface to GDB, the GNU debugger.
Copyright 1994 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Stan Shebs for Cygnus.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include <Values.h>
#include <Types.h>
#include <Resources.h>
#include <QuickDraw.h>
#include <Fonts.h>
#include <Events.h>
#include <Windows.h>
#include <Menus.h>
#include <TextEdit.h>
#include <Dialogs.h>
#include <Desk.h>
#include <ToolUtils.h>
#include <Memory.h>
#include <SegLoad.h>
#include <Files.h>
#include <Folders.h>
#include <OSUtils.h>
#include <OSEvents.h>
#include <DiskInit.h>
#include <Packages.h>
#include <Traps.h>
#include <Lists.h>
#include <GestaltEqu.h>
#include <PPCToolbox.h>
#include <AppleEvents.h>
#include <StandardFile.h>
#include <Sound.h>
#ifdef MPW
#define QD(whatever) (qd.##whatever)
#define QDPat(whatever) (&(qd.##whatever))
#endif
#ifdef THINK_C
#define QD(whatever) (whatever)
#endif
#define p2c(pstr,cbuf) \
strncpy(cbuf, ((char *) (pstr) + 1), pstr[0]); \
cbuf[pstr[0]] = '\0';
#define pascalify(STR) \
sprintf(tmpbuf, " %s", STR); \
tmpbuf[0] = strlen(STR);
#include "gdbcmd.h"
#include "call-cmds.h"
#include "symtab.h"
#include "inferior.h"
#include "signals.h"
#include "target.h"
#include "breakpoint.h"
#include "gdbtypes.h"
#include "expression.h"
#include "language.h"
#include "terminal.h" /* For job_control. */
#include "mac-defs.h"
int useWNE;
int hasColorQD;
int inbackground;
Rect dragrect = { -32000, -32000, 32000, 32000 };
Rect sizerect;
int sbarwid = 15;
/* Globals for the console window. */
WindowPtr console_window;
ControlHandle console_v_scrollbar;
Rect console_v_scroll_rect;
TEHandle console_text;
Rect console_text_rect;
mac_init ()
{
SysEnvRec se;
int eventloopdone = 0;
Boolean gotevent;
Point mouse;
EventRecord event;
WindowPtr win;
RgnHandle cursorRgn;
int i;
Handle menubar;
MenuHandle menu;
/* Do the standard Mac environment setup. */
InitGraf (&QD (thePort));
InitFonts ();
FlushEvents (everyEvent, 0);
InitWindows ();
InitMenus ();
TEInit ();
InitDialogs (NULL);
InitCursor ();
/* Color Quickdraw is different from Classic QD. */
SysEnvirons(2, &se);
hasColorQD = se.hasColorQD;
sizerect.top = 50;
sizerect.left = 50;
sizerect.bottom = 1000;
sizerect.right = 1000;
#if 0
sizerect.bottom = screenBits.bounds.bottom - screenBits.bounds.top;
sizerect.right = screenBits.bounds.right - screenBits.bounds.left;
#endif
/* Set up the menus. */
menubar = GetNewMBar (mbMain);
SetMenuBar (menubar);
/* Add the DAs etc as usual. */
menu = GetMHandle (mApple);
if (menu != nil) {
AddResMenu (menu, 'DRVR');
}
DrawMenuBar ();
/* Create the main window we're going to play in. */
if (hasColorQD)
console_window = GetNewCWindow (wConsole, NULL, (WindowPtr) -1L);
else
console_window = GetNewWindow (wConsole, NULL, (WindowPtr) -1L);
if (1) DebugStr("\pnear beginning");
SetPort (console_window);
console_text_rect = console_window->portRect;
console_text_rect.bottom -= sbarwid - 1;
console_text_rect.right -= sbarwid - 1;
console_text = TENew (&console_text_rect, &console_text_rect);
TESetSelect (0, 32767, console_text);
TEDelete (console_text);
TEInsert ("(gdb)", strlen("(gdb)"), console_text);
console_v_scroll_rect = console_window->portRect;
console_v_scroll_rect.bottom -= sbarwid - 1;
console_v_scroll_rect.left = console_v_scroll_rect.right - sbarwid;
console_v_scrollbar =
NewControl (console_window, &console_v_scroll_rect,
"\p", 1, 0, 0, 0, scrollBarProc, 0L);
ShowWindow (console_window);
SelectWindow (console_window);
/* force_update (console_window); */
return 1;
}
mac_command_loop()
{
SysEnvRec se;
int eventloopdone = 0;
Boolean gotevent;
Point mouse;
EventRecord event;
WindowPtr win;
RgnHandle cursorRgn;
int i;
Handle menubar;
MenuHandle menu;
/* Figure out if the WaitNextEvent Trap is available. */
useWNE =
(NGetTrapAddress (0x60, ToolTrap) != NGetTrapAddress (0x9f, ToolTrap));
/* Pass WNE an empty region the 1st time thru. */
cursorRgn = NewRgn ();
/* Go into the main event-handling loop. */
while (!eventloopdone)
{
/* Use WaitNextEvent if it is available, otherwise GetNextEvent. */
if (useWNE)
{
get_global_mouse (&mouse);
adjust_cursor (mouse, cursorRgn);
gotevent = WaitNextEvent (everyEvent, &event, 0L, cursorRgn);
}
else
{
SystemTask ();
gotevent = GetNextEvent (everyEvent, &event);
}
/* First decide if the event is for a dialog or is just any old event. */
if (FrontWindow () != nil && IsDialogEvent (&event))
{
short itemhit;
DialogPtr dialog;
/* Handle all the modeless dialogs here. */
if (DialogSelect (&event, &dialog, &itemhit))
{
}
}
else if (gotevent)
{
/* Make sure we have the right cursor before handling the event. */
adjust_cursor (event.where, cursorRgn);
do_event (&event);
}
}
}
get_global_mouse (mouse)
Point *mouse;
{
EventRecord evt;
OSEventAvail (0, &evt);
*mouse = evt.where;
}
adjust_cursor (mouse, region)
Point mouse;
RgnHandle region;
{
}
/* Decipher an event, maybe do something with it. */
do_event (evt)
EventRecord *evt;
{
short part, err, rslt = 0;
WindowPtr win;
Boolean hit;
char key;
Point pnt;
switch (evt->what)
{
case mouseDown:
/* See if the click happened in a special part of the screen. */
part = FindWindow (evt->where, &win);
switch (part)
{
case inMenuBar:
adjust_menus ();
do_menu_command (MenuSelect (evt->where));
break;
case inSysWindow:
SystemClick (evt, win);
break;
case inContent:
if (win != FrontWindow ())
{
/* Bring the clicked-on window to the front. */
SelectWindow (win);
/* Fix the menu to match the new front window. */
adjust_menus ();
/* We always want to discard the event now, since clicks in a
windows are often irreversible actions. */
} else
/* Mouse clicks in the front window do something useful. */
do_mouse_down (win, evt);
break;
case inDrag:
/* Standard drag behavior, no tricks necessary. */
DragWindow (win, evt->where, &dragrect);
break;
case inGrow:
grow_window (win, evt->where);
break;
case inZoomIn:
case inZoomOut:
zoom_window (win, evt->where, part);
break;
case inGoAway:
close_window (win);
break;
}
break;
case keyDown:
case autoKey:
key = evt->message & charCodeMask;
/* Check for menukey equivalents. */
if (evt->modifiers & cmdKey)
{
if (evt->what == keyDown)
{
adjust_menus ();
do_menu_command (MenuKey (key));
}
}
else
{
if (evt->what == keyDown)
{
/* Random keypress, interpret it. */
do_keyboard_command (key);
}
}
break;
case activateEvt:
activate_window ((WindowPtr) evt->message, evt->modifiers & activeFlag);
break;
case updateEvt:
update_window ((WindowPtr) evt->message);
break;
case diskEvt:
/* Call DIBadMount in response to a diskEvt, so that the user can format
a floppy. (from DTS Sample) */
if (HiWord (evt->message) != noErr)
{
SetPt (&pnt, 50, 50);
err = DIBadMount (pnt, evt->message);
}
break;
case app4Evt:
/* Grab only a single byte. */
switch ((evt->message >> 24) & 0xFF)
{
case 0xfa:
break;
case 1:
inbackground = !(evt->message & 1);
activate_window (FrontWindow (), !inbackground);
break;
}
break;
case kHighLevelEvent:
AEProcessAppleEvent (evt);
break;
case nullEvent:
rslt = 1;
break;
default:
break;
}
return rslt;
}
grow_window (win, where)
WindowPtr win;
Point where;
{
long winsize;
int h, v;
GrafPtr oldport;
winsize = GrowWindow (win, where, &sizerect);
if (winsize != 0)
{
GetPort (&oldport);
SetPort (win);
EraseRect (&win->portRect);
h = LoWord (winsize);
v = HiWord (winsize);
SizeWindow (win, h, v, 1);
if (win == console_window)
{
MoveControl(console_v_scrollbar, h - sbarwid, 0);
SizeControl(console_v_scrollbar, sbarwid + 1, v - sbarwid + 1);
}
InvalRect (&win->portRect);
SetPort (oldport);
}
}
zoom_window (win, where, part)
WindowPtr win;
Point where;
short part;
{
}
close_window (win)
WindowPtr win;
{
}
do_mouse_down (win, event)
WindowPtr win;
EventRecord *event;
{
short part;
Point mouse;
ControlHandle control;
if (1 /*is_app_window(win)*/)
{
SetPort (win);
mouse = event->where;
GlobalToLocal (&mouse);
part = FindControl(mouse, win, &control);
if (control == console_v_scrollbar)
{
SysBeep(20);
}
else
{
TEClick (mouse, 0, console_text);
}
}
}
activate_window (win, activate)
WindowPtr win;
int activate;
{
if (win == nil) return;
/* It's convenient to make the activated window also be the
current GrafPort. */
if (activate)
SetPort(win);
/* Activate the console window's scrollbar. */
if (win == console_window)
HiliteControl (console_v_scrollbar, (activate ? 0 : 255));
}
update_window (win)
WindowPtr win;
{
int controls = 1, growbox = 0;
GrafPtr oldport;
/* Set the updating window to be the current grafport. */
GetPort (&oldport);
SetPort (win);
/* recalc_depths(); */
BeginUpdate (win);
if (win == console_window)
{
draw_console ();
controls = 1;
growbox = 1;
}
if (controls)
UpdateControls (win, win->visRgn);
if (growbox)
DrawGrowIcon (win);
EndUpdate (win);
SetPort (oldport);
}
adjust_menus ()
{
}
do_menu_command (which)
long which;
{
short menuid, menuitem;
short itemHit;
Str255 daname;
short daRefNum;
Boolean handledbyda;
WindowPtr win;
short ditem;
int i;
menuid = HiWord (which);
menuitem = LoWord (which);
switch (menuid)
{
case mApple:
switch (menuitem)
{
case miAbout:
/* Alert(aAbout, nil); */
break;
default:
GetItem (GetMHandle (mApple), menuitem, daname);
daRefNum = OpenDeskAcc (daname);
}
break;
case mFile:
switch (menuitem)
{
case miFileQuit:
ExitToShell ();
break;
}
break;
case mEdit:
/* handledbyda = SystemEdit(menuitem-1); */
switch (menuitem)
{
case miEditCut:
break;
case miEditCopy:
break;
case miEditPaste:
break;
case miEditClear:
break;
}
break;
}
HiliteMenu (0);
}
char commandbuf[1000];
do_keyboard_command (key)
char key;
{
int startpos, endpos, i;
char buf[10], *text_str, *command;
CharsHandle text;
if (key == '\015' || key == '\003')
{
/* (should) Interpret the line as a command. */
text = TEGetText (console_text);
HLock ((Handle) text);
startpos = (*console_text)->selStart;
endpos = (*console_text)->selEnd;
if (startpos != endpos)
{
strncpy (commandbuf + 1, *text + startpos, endpos - startpos);
commandbuf[1 + endpos - startpos] = 0;
command = commandbuf + 1;
}
else
{
for (i = startpos; i > 0; --i)
{
strncpy (buf, *text + i, 5);
buf[5] = 0;
if (strncmp (buf, "(gdb)") == 0)
break;
}
if (i > 0)
{
strncpy (commandbuf + 1, *text + i + 5, startpos - i);
commandbuf[1 + startpos - i] = '\0';
}
else
{
SysBeep (20);
commandbuf[1] = '\0';
}
command = commandbuf + 1;
}
HUnlock ((Handle) text);
commandbuf[0] = strlen(command);
DebugStr(commandbuf);
/* Insert a newline and redraw before doing the command. */
buf[0] = '\015';
TEInsert (buf, 1, console_text);
TESetSelect (100000, 100000, console_text);
draw_console ();
execute_command (commandbuf, 0);
bpstat_do_actions (&stop_bpstat);
}
else if (0 /* editing chars... */)
{
}
else
{
/* A self-inserting character. */
buf[0] = key;
TEInsert (buf, 1, console_text);
TESetSelect (100000, 100000, console_text);
draw_console ();
}
}
draw_console ()
{
GrafPtr oldport;
GetPort (&oldport);
SetPort (console_window);
TEUpdate (&(console_window->portRect), console_text);
SetPort (oldport);
/* adjust_help_scrollbar(); */
}
/* Cause an update of a window's entire contents. */
force_update (win)
WindowPtr win;
{
GrafPtr oldport;
if (win == nil) return;
GetPort (&oldport);
SetPort (win);
EraseRect (&win->portRect);
InvalRect (&win->portRect);
SetPort (oldport);
}
adjust_console_scrollbars ()
{
int lines, newmax, value;
lines = (*console_text)->nLines;
newmax = lines - (((*console_text)->viewRect.bottom - (*console_text)->viewRect.top)
/ (*console_text)->lineHeight);
if (newmax < 0) newmax = 0;
SetCtlMax(console_v_scrollbar, newmax);
value = ((*console_text)->viewRect.top - (*console_text)->destRect.top)
/ (*console_text)->lineHeight;
SetCtlValue(console_v_scrollbar, value);
}

153
gdb/macgdb.r Normal file
View File

@ -0,0 +1,153 @@
/* Resource file for MacGDB. */
#include "Types.r"
#include "mac-defs.h"
resource 'MBAR' (128) {
{ mApple, mFile, mEdit, mDebug };
};
resource 'MENU' (mApple, preload) {
mApple,
textMenuProc,
0x7FFFFFFD,
enabled,
apple,
{
"About...", noIcon, noKey, noMark, plain,
"-", noIcon, noKey, noMark, plain
}
};
resource 'MENU' (mFile, preload) {
mFile,
textMenuProc,
0xFFF,
enabled,
"File",
{
"New", noIcon, "N", noMark, plain,
"Open...", noIcon, "O", noMark, plain,
"-", noIcon, noKey, noMark, plain,
"Quit", noIcon, "Q", noMark, plain
}
};
resource 'MENU' (mEdit, preload) {
mEdit,
textMenuProc,
0x3400,
enabled,
"Edit",
{
"Undo", noIcon, "Z", noMark, plain,
"-", noIcon, noKey, noMark, plain,
"Cut", noIcon, "X", noMark, plain,
"Copy", noIcon, "C", noMark, plain,
"Paste", noIcon, "V", noMark, plain,
"Clear", noIcon, noKey, noMark, plain
}
};
resource 'MENU' (mDebug, preload) {
mDebug,
textMenuProc,
0x7FFFFFDD,
enabled,
"Debug",
{
"Target", noIcon, "T", noMark, plain,
"-", noIcon, noKey, noMark, plain,
"Run", noIcon, "R", noMark, plain,
"Continue", noIcon, noKey, noMark, plain,
"Step", noIcon, noKey, noMark, plain,
"Next", noIcon, noKey, noMark, plain
}
};
resource 'ALRT' (128) {
{40, 40, 229, 363},
128,
{ /* array: 4 elements */
/* [1] */
OK, visible, sound1,
/* [2] */
OK, visible, sound1,
/* [3] */
OK, visible, sound1,
/* [4] */
OK, visible, sound1
}
};
resource 'DITL' (128) {
{ /* array DITLarray: 4 elements */
/* [1] */
{164, 115, 184, 185},
Button {
enabled,
"OK"
},
/* [2] */
{5, 10, 43, 290},
StaticText {
disabled,
"MacGDB"
},
/* [3] */
{76, 3, 154, 301},
StaticText {
disabled,
"GNU Debugger"
"\nCopyright © 1994 Free Software Foundation Inc.\n"
"Written by Stan Shebs."
},
/* [4] */
{53, 82, 71, 227},
StaticText {
disabled,
"version 4.12.1"
}
}
};
resource 'WIND' (wConsole, preload, purgeable) {
{40, 40, 310, 572},
documentProc,
visible,
noGoAway,
0x0,
"GDB Console"
};
resource 'SIZE' (-1) {
reserved,
acceptSuspendResumeEvents,
reserved,
canBackground,
multiFinderAware,
backgroundAndForeground,
dontGetFrontClicks,
ignoreChildDiedEvents,
not32BitCompatible,
isHighLevelEventAware,
localAndRemoteHLEvents,
notStationeryAware,
dontUseTextEditServices,
reserved,
reserved,
reserved,
50000,
50000
};
resource 'DLOG' (128) {
{40, 40, 240, 280},
documentProc,
visible,
goAway,
0x0,
128,
""
};

View File

@ -5,6 +5,8 @@ XM_CDEPS =
TM_CDEPS =
NAT_CDEPS =
XDEPFILES = "{o}"mac-xdep.c.o
CC_LD = Link
gC = gC1
@ -646,7 +648,7 @@ TARFILES = {SFILES} {HFILES_NO_SRCDIR} {HFILES_WITH_SRCDIR} \Option-d
{ALLPARAM} {INFOFILES} {POSSLIBS} {REMOTE_EXAMPLES}
OBS = "{o}"version.c.o "{o}"main.gc.o "{o}"blockframe.c.o "{o}"breakpoint.gc.o "{o}"findvar.c.o "{o}"stack.c.o "{o}"thread.c.o \Option-d
OBS = "{o}"version.c.o "{o}"main.c.o "{o}"blockframe.c.o "{o}"breakpoint.gc.o "{o}"findvar.c.o "{o}"stack.c.o "{o}"thread.c.o \Option-d
"{o}"source.gc.o "{o}"values.c.o "{o}"eval.c.o "{o}"valops.c.o "{o}"valarith.c.o "{o}"valprint.c.o "{o}"printcmd.gc.o \Option-d
"{o}"symtab.c.o "{o}"symfile.c.o "{o}"symmisc.c.o "{o}"infcmd.c.o "{o}"infrun.gc.o "{o}"command.c.o \Option-d
"{o}"utils.c.o "{o}"expprint.c.o "{o}"environ.c.o "{o}"gdbtypes.c.o "{o}"copying.c.o {DEPFILES} \Option-d
@ -745,6 +747,11 @@ saber_gdb \Option-f {SFILES} {DEPFILES} "{s}"copying.c "{s}"version.c
#load `echo " "{DEPFILES} | sed -e 's:\.o:.c:g' -e 's, , ::,g'`
echo "Load "{s}".c corresponding to \Option-f " {DEPFILES}
MacGDB \Option-f {OBS} {TSOBS} {ADD_DEPS} {CDEPS} "{o}"init.c.o
Delete -i -y MacGDB
Rez -rd -o MacGDB "{s}"macgdb.r -append
Link -d -model far -o MacGDB -t 'APPL' -c 'gdb ' \Option-d
"{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES}
# This is useful when debugging GDB, because some Unix's don't let you run GDB
# on itself without copying the executable. So "make gdb1" will make
@ -1235,10 +1242,10 @@ MAKEOVERRIDES=
"{o}"m88k-pinsn.c.o \Option-f "{s}"m88k-pinsn.c {defs_h} {symtab_h}
"{o}"m88k-tdep.c.o \Option-f "{s}"m88k-tdep.c {defs_h} {gdbcore_h} {inferior_h}
"{o}"main.gc.o \Option-f "{s}"main.c {bfd_h} {getopt_h} {readline_headers} "{s}"call-cmds.h \Option-d
"{o}"main.c.o \Option-f "{s}"main.c {bfd_h} {getopt_h} {readline_headers} "{s}"call-cmds.h \Option-d
{defs_h} {gdbcmd_h} {inferior_h} "{s}"language.h "{s}"signals.h \Option-d
{remote_utils_h}
{gC} {INTERNAL_CFLAGS} {READLINE_CFLAGS} "{srcdir}"main.c -o "{o}"main.gc.o
{CC} {INTERNAL_CFLAGS} {READLINE_CFLAGS} "{srcdir}"main.c -o "{o}"main.c.o
"{o}"maint.c.o \Option-f "{s}"maint.c {defs_h} {gdbcmd_h} {gdbtypes_h} {symtab_h} "{s}"language.h \Option-d
{expression_h}