euphoria

changeset 5391:51e87b308179

* merge 4.0 changes
author Shawn Pringle <shawn.pringle@gmail.com>
date Wed Dec 21 16:45:49 2011 -0300 (18 months ago)
parents cf65e80418ef 936421a1c6f3
children 26ea874aeaf9
files source/Makefile.gnu
line diff
     1.1 --- a/demo/simple_debug.e	Mon Dec 19 23:19:58 2011 -0300
     1.2 +++ b/demo/simple_debug.e	Wed Dec 21 16:45:49 2011 -0300
     1.3 @@ -100,6 +100,7 @@
     1.4  			printf( 1, " %s", { get_name( params[j] ) } )
     1.5  		end for
     1.6  		puts( 1, " )")
     1.7 +		
     1.8  	end if
     1.9  	puts( 1, "\n" )
    1.10  end procedure
     2.1 --- a/demo/win32/window.exw	Mon Dec 19 23:19:58 2011 -0300
     2.2 +++ b/demo/win32/window.exw	Wed Dec 21 16:45:49 2011 -0300
     2.3 @@ -8,254 +8,444 @@
     2.4  include std/os.e
     2.5  include std/machine.e
     2.6  include std/dll.e
     2.7 +include std/math.e
     2.8 +include std/error.e
     2.9 +include std/console.e
    2.10  
    2.11 -constant cbSize = 0,
    2.12 -	 style  = 4,
    2.13 -	 lpfnWndProc = 8,
    2.14 -	 cbClsExtra = 12,
    2.15 -	 cbWndExtra = 16,
    2.16 -	 hInstance  = 20,
    2.17 -	 hIcon      = 24,
    2.18 -	 hCursor    = 28,
    2.19 -	 hbrBackground = 32,
    2.20 -	 lpszMenuName  = 36,
    2.21 -	 lpszClassName = 40,
    2.22 -	 hIconSm = 44,
    2.23 -	 SIZE_OF_WNDCLASS = 48
    2.24 +include std/memstruct/windows.e
    2.25  
    2.26 -constant SIZE_OF_MESSAGE = 40
    2.27 +--****
    2.28 +-- === Windows Data Type constants for function/procedure calls
    2.29 +
    2.30 +public constant
    2.31 +	C_BYTE = C_UCHAR,
    2.32 +	C_BOOL = C_INT,
    2.33 +	C_ATOM = C_USHORT,
    2.34 +	C_WORD = C_USHORT,
    2.35 +	C_DWORD=  C_ULONG,
    2.36 +	C_WPARAM = C_POINTER,
    2.37 +	C_LPARAM = C_POINTER,
    2.38 +	C_HANDLE = C_POINTER,
    2.39 +	C_HWND = C_POINTER,
    2.40 +	C_LPSTR = C_POINTER,
    2.41 +	C_COLORREF =  C_DWORD,    --0x00bbggrr
    2.42 +	C_LANGID =  C_WORD,
    2.43 +	$
    2.44 +
    2.45 +public constant C_LONG_PTR = C_POINTER
    2.46 +
    2.47 +public constant C_LRESULT = C_LONG_PTR
    2.48 +
    2.49 +
    2.50 +
    2.51  
    2.52  constant CS_HREDRAW = 2,
    2.53 -	 CS_VREDRAW = 1
    2.54 +	CS_VREDRAW = 1
    2.55  
    2.56  constant SW_SHOWNORMAL = 1
    2.57  
    2.58  constant WM_CREATE = #01,
    2.59 -	 WM_PAINT  = #0F,
    2.60 -	 WM_DESTROY= #02
    2.61 +	WM_PAINT  = #0F,
    2.62 +	WM_DESTROY= #02
    2.63  
    2.64  constant SND_FILENAME = #00020000,
    2.65 -	 SND_ASYNC    = #00000001
    2.66 -	 
    2.67 +	SND_ASYNC    = #00000001
    2.68 +	
    2.69  constant DT_SINGLELINE = #0020,
    2.70 -	 DT_CENTER     = #0001,
    2.71 -	 DT_VCENTER    = #0004
    2.72 -	 
    2.73 -function or_all(sequence s)
    2.74 --- or together all elements of a sequence
    2.75 -    atom result
    2.76 -    
    2.77 -    result = 0
    2.78 -    for i = 1 to length(s) do
    2.79 -	result = or_bits(result, s[i])
    2.80 -    end for
    2.81 -    return result
    2.82 -end function
    2.83 +	DT_CENTER     = #0001,
    2.84 +	DT_VCENTER    = #0004
    2.85 +	
    2.86 +
    2.87  
    2.88  constant WS_OVERLAPPED  = #00000000,
    2.89 -	 WS_CAPTION     = #00C00000,
    2.90 -	 WS_SYSMENU     = #00080000,
    2.91 -	 WS_THICKFRAME  = #00040000,
    2.92 -	 WS_MINIMIZEBOX = #00020000,
    2.93 -	 WS_MAXIMIZEBOX = #00010000 
    2.94 +	WS_CAPTION     = #00C00000,
    2.95 +	WS_SYSMENU     = #00080000,
    2.96 +	WS_THICKFRAME  = #00040000,
    2.97 +	WS_MINIMIZEBOX = #00020000,
    2.98 +	WS_MAXIMIZEBOX = #00010000
    2.99  
   2.100 -constant IDC_ARROW = 32512,
   2.101 -	 WHITE_BRUSH = 0,
   2.102 -	 CW_USEDEFAULT = #80000000,
   2.103 -	 WS_OVERLAPPEDWINDOW = or_all({WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,
   2.104 -				       WS_THICKFRAME, WS_MINIMIZEBOX, 
   2.105 -				       WS_MAXIMIZEBOX})
   2.106 +constant
   2.107 +	IDC_ARROW = 32512,
   2.108 +	IDI_APPLICATION = 3,
   2.109 +	CW_USEDEFAULT = #80000000,
   2.110 +	WS_OVERLAPPEDWINDOW = or_all({WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU,
   2.111 +					WS_THICKFRAME, WS_MINIMIZEBOX,
   2.112 +				       WS_MAXIMIZEBOX}),
   2.113 +	WHITE_BRUSH = 0,
   2.114 +	LTGRAY_BRUSH = 1,
   2.115 +	GRAY_BRUSH = 2,
   2.116 +	DKGRAY_BRUSH = 3,
   2.117 +	BLACK_BRUSH = 4,
   2.118 +	NULL_BRUSH = 5,
   2.119 +-- 	HOLLOW_BRUSH = ?,
   2.120 +	WHITE_PEN = 6,
   2.121 +	BLACK_PEN = 7,
   2.122 +	NULL_PEN = 8,
   2.123 +	OEM_FIXED_FONT = 10,
   2.124 +	ANSI_FIXED_FONT = 11,
   2.125 +	ANSI_VAR_FONT = 12,
   2.126 +	SYSTEM_FONT = 13,
   2.127 +	DEVICE_DEFAULT_FONT = 14,
   2.128 +	DEFAULT_PALETTE = 15,
   2.129 +	SYSTEM_FIXED_FONT = 16,
   2.130  
   2.131 -	 
   2.132 +	STOCK_LAST = 16,
   2.133 +
   2.134 +	COLOR_SCROLLBAR = 0,
   2.135 +	COLOR_BACKGROUND = 1,
   2.136 +	COLOR_ACTIVECAPTION = 2,
   2.137 +	COLOR_INACTIVECAPTION = 3,
   2.138 +	COLOR_MENU = 4,
   2.139 +	COLOR_WINDOW = 5,
   2.140 +	COLOR_WINDOWFRAME = 6,
   2.141 +	COLOR_MENUTEXT = 7,
   2.142 +	COLOR_WINDOWTEXT = 8,
   2.143 +	COLOR_CAPTIONTEXT = 9,
   2.144 +	COLOR_ACTIVEBORDER = 10,
   2.145 +	COLOR_INACTIVEBORDER = 11,
   2.146 +	COLOR_APPWORKSPACE = 12,
   2.147 +	COLOR_HIGHLIGHT = 13,
   2.148 +	COLOR_HIGHLIGHTTEXT = 14,
   2.149 +	COLOR_BTNFACE = 15,
   2.150 +	COLOR_BTNSHADOW = 16,
   2.151 +	COLOR_GRAYTEXT = 17,
   2.152 +	COLOR_BTNTEXT = 18,
   2.153 +	COLOR_INACTIVECAPTIONTEXT = 19,
   2.154 +	COLOR_BTNHIGHLIGHT = 20,
   2.155 +
   2.156 +	LOGPIXELSX = 88,
   2.157 +	LOGPIXELSY = 90,
   2.158 +	OUT_DEFAULT_PRECIS = 0,
   2.159 +	OUT_STRING_PRECIS = 1,
   2.160 +	OUT_CHARACTER_PRECIS = 2,
   2.161 +	OUT_STROKE_PRECIS = 3,
   2.162 +	OUT_TT_PRECIS = 4,
   2.163 +	OUT_DEVICE_PRECIS = 5,
   2.164 +	OUT_RASTER_PRECIS = 6,
   2.165 +	OUT_TT_ONLY_PRECIS = 7,
   2.166 +	OUT_OUTLINE_PRECIS = 8,
   2.167 +	OUT_SCREEN_OUTLINE_PRECIS = 9,
   2.168 +	OUT_PS_ONLY_PRECIS = 10,
   2.169 +
   2.170 +	CLIP_DEFAULT_PRECIS = 0,
   2.171 +	CLIP_CHARACTER_PRECIS = 1,
   2.172 +	CLIP_STROKE_PRECIS = 2,
   2.173 +	CLIP_MASK = #F,
   2.174 +-- 	CLIP_LH_ANGLES = (1<<4),
   2.175 +
   2.176 +-- 	CLIP_TT_ALWAYS = (2<<4),
   2.177 +
   2.178 +-- 	CLIP_EMBEDDED = (8<<4),
   2.179 +
   2.180 +	DEFAULT_QUALITY = 0,
   2.181 +	DRAFT_QUALITY = 1,
   2.182 +	PROOF_QUALITY = 2,
   2.183 +
   2.184 +	DEFAULT_PITCH = 0,
   2.185 +	FIXED_PITCH = 1,
   2.186 +	VARIABLE_PITCH = 2,
   2.187 +
   2.188 +	ANSI_CHARSET = 0,
   2.189 +	DEFAULT_CHARSET = 1,
   2.190 +	SYMBOL_CHARSET = 2,
   2.191 +	SHIFTJIS_CHARSET = 128,
   2.192 +	HANGEUL_CHARSET = 129,
   2.193 +	HANGUL_CHARSET = 129,
   2.194 +	GB2312_CHARSET = 134,
   2.195 +	CHINESEBIG5_CHARSET = 136,
   2.196 +	OEM_CHARSET = 255,
   2.197 +
   2.198 +	FF_DONTCARE = shift_bits(0, -4),
   2.199 +
   2.200 +-- 	FF_ROMAN = (1<<4)  ,
   2.201 +
   2.202 +-- 	FF_SWISS = (2<<4)  ,
   2.203 +
   2.204 +-- 	FF_MODERN = (3<<4)  ,
   2.205 +
   2.206 +-- 	FF_SCRIPT = (4<<4)  ,
   2.207 +
   2.208 +-- 	FF_DECORATIVE = (5<<4)  ,
   2.209 +
   2.210 +	FW_DONTCARE = 0,
   2.211 +	FW_THIN = 100,
   2.212 +	FW_EXTRALIGHT = 200,
   2.213 +	FW_LIGHT = 300,
   2.214 +	FW_NORMAL = 400,
   2.215 +	FW_MEDIUM = 500,
   2.216 +	FW_SEMIBOLD = 600,
   2.217 +	FW_BOLD = 700,
   2.218 +	FW_EXTRABOLD = 800,
   2.219 +	FW_HEAVY = 900,
   2.220 +
   2.221 +-- 	FW_ULTRALIGHT = FW_EXTRALIGHT,
   2.222 +
   2.223 +-- 	FW_REGULAR = FW_NORMAL,
   2.224 +
   2.225 +-- 	FW_DEMIBOLD = FW_SEMIBOLD,
   2.226 +
   2.227 +-- 	FW_ULTRABOLD = FW_EXTRABOLD,
   2.228 +
   2.229 +-- 	FW_BLACK = FW_HEAVY,
   2.230 +	$
   2.231 +
   2.232  integer LoadIcon, LoadCursor, GetStockObject, RegisterClassEx,
   2.233  	CreateWindow, ShowWindow, UpdateWindow, GetMessage,
   2.234  	TranslateMessage, DispatchMessage, PlaySound, BeginPaint,
   2.235 -	GetClientRect, DrawText, EndPaint, PostQuitMessage, DefWindowProc
   2.236 +	GetClientRect, DrawText, EndPaint, PostQuitMessage, DefWindowProc,
   2.237 +    GetSysColor, SelectObject, SetTextColor, SetBkColor,
   2.238 +	xGetLastError, xSetLastError, xFormatMessage,
   2.239 +    GetDeviceCaps, CreateFont, MulDiv
   2.240  
   2.241  procedure not_found(sequence name)
   2.242 -    puts(1, "Couldn't find " & name & '\n')
   2.243 -    abort(1)
   2.244 +	crash( "Couldn't find " & name )
   2.245  end procedure
   2.246  
   2.247 +-- dynamically link a C routine as a Euphoria function
   2.248  function link_c_func(atom dll, sequence name, sequence args, atom result)
   2.249 --- dynamically link a C routine as a Euphoria function
   2.250 -    integer handle
   2.251 +	integer handle
   2.252  
   2.253 -    handle = define_c_func(dll, name, args, result)
   2.254 -    if handle = -1 then
   2.255 -	not_found(name)
   2.256 -    else
   2.257 -	return handle
   2.258 -    end if
   2.259 +	handle = define_c_func(dll, name, args, result)
   2.260 +	if handle = -1 then
   2.261 +		not_found(name)
   2.262 +	else
   2.263 +		return handle
   2.264 +	end if
   2.265  end function
   2.266  
   2.267 +-- dynamically link a C routine as a Euphoria function
   2.268  function link_c_proc(atom dll, sequence name, sequence args)
   2.269 --- dynamically link a C routine as a Euphoria function
   2.270 -    integer handle
   2.271 +	integer handle
   2.272  
   2.273 -    handle = define_c_proc(dll, name, args)
   2.274 -    if handle = -1 then
   2.275 -	not_found(name)
   2.276 -    else
   2.277 -	return handle
   2.278 -    end if
   2.279 +	handle = define_c_proc(dll, name, args)
   2.280 +	if handle = -1 then
   2.281 +		not_found(name)
   2.282 +	else
   2.283 +		return handle
   2.284 +	end if
   2.285  end function
   2.286  
   2.287 +-- get handles to all dll routines that we need
   2.288  procedure link_dll_routines()
   2.289 --- get handles to all dll routines that we need
   2.290 -    atom user32, gdi32, winmm
   2.291 -    
   2.292 -    user32 = open_dll("user32.dll")
   2.293 -    if user32 = NULL then
   2.294 -	not_found("user32.dll")
   2.295 -    end if
   2.296 -    gdi32 = open_dll("gdi32.dll")
   2.297 -    if gdi32 = NULL then
   2.298 -	not_found("gdi32.dll")
   2.299 -    end if
   2.300 -    winmm = open_dll("winmm.dll")
   2.301 -    if winmm = NULL then
   2.302 +	atom user32, gdi32, winmm, kernel32
   2.303 +	
   2.304 +	user32 = open_dll("user32.dll")
   2.305 +	if user32 = NULL then
   2.306 +		not_found("user32.dll")
   2.307 +	end if
   2.308 +	gdi32 = open_dll("gdi32.dll")
   2.309 +	if gdi32 = NULL then
   2.310 +		not_found("gdi32.dll")
   2.311 +	end if
   2.312 +	winmm = open_dll("winmm.dll")
   2.313 +	if winmm = NULL then
   2.314  	not_found("winmm.dll")
   2.315 -    end if
   2.316 -    
   2.317 -    LoadIcon = link_c_func(user32, "LoadIconA", {C_POINTER, C_INT}, C_INT)
   2.318 -    LoadCursor = link_c_func(user32, "LoadCursorA", {C_POINTER, C_INT}, C_INT)
   2.319 -    GetStockObject = link_c_func(gdi32, "GetStockObject", {C_INT}, C_INT)
   2.320 -    RegisterClassEx = link_c_func(user32, "RegisterClassExA", {C_POINTER}, C_INT)
   2.321 -    CreateWindow = link_c_func(user32, "CreateWindowExA", 
   2.322 -     {C_INT, C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT,C_INT},
   2.323 -      C_INT)
   2.324 -    ShowWindow = link_c_proc(user32, "ShowWindow", {C_INT, C_INT})
   2.325 -    UpdateWindow = link_c_proc(user32, "UpdateWindow", {C_INT})
   2.326 -    GetMessage = link_c_func(user32, "GetMessageA", 
   2.327 -			     {C_INT, C_INT, C_INT, C_INT}, C_INT)
   2.328 -    TranslateMessage = link_c_proc(user32, "TranslateMessage", {C_INT})
   2.329 -    DispatchMessage = link_c_proc(user32, "DispatchMessageA", {C_INT})
   2.330 -    PlaySound = link_c_proc(winmm, "PlaySound", {C_INT, C_INT, C_INT})
   2.331 -    BeginPaint = link_c_func(user32, "BeginPaint", {C_INT, C_POINTER}, C_INT)
   2.332 -    GetClientRect = link_c_proc(user32, "GetClientRect", {C_INT, C_POINTER})
   2.333 -    DrawText = link_c_proc(user32, "DrawTextA", 
   2.334 -			   {C_INT, C_INT, C_INT, C_INT, C_INT})
   2.335 -    EndPaint = link_c_proc(user32, "EndPaint", {C_INT, C_INT})
   2.336 -    PostQuitMessage = link_c_proc(user32, "PostQuitMessage", {C_INT})
   2.337 -    DefWindowProc = link_c_func(user32, "DefWindowProcA", 
   2.338 -				{C_INT, C_INT, C_INT, C_INT}, C_INT)
   2.339 +	end if
   2.340 +	
   2.341 +	kernel32 = open_dll( "kernel32.dll")
   2.342 +	if kernel32 = NULL then
   2.343 +		not_found("kernel32.dll")
   2.344 +	end if
   2.345 +
   2.346 +	--new code would use LoadImage
   2.347 +	LoadIcon = link_c_func(user32, "LoadIconA", {C_HANDLE, C_LPSTR}, C_HANDLE)
   2.348 +	LoadCursor = link_c_func(user32, "LoadCursorA", {C_HANDLE, C_LPSTR}, C_HANDLE)
   2.349 +
   2.350 +	GetStockObject = link_c_func(gdi32, "GetStockObject", {C_INT}, C_HANDLE)
   2.351 +	RegisterClassEx = link_c_func(user32, "RegisterClassExA", {C_POINTER}, C_ATOM)
   2.352 +	CreateWindow = link_c_func(user32, "CreateWindowExA",
   2.353 +		{C_DWORD, C_LPSTR, C_LPSTR,C_DWORD,C_INT,C_INT,C_INT,C_INT,
   2.354 +		C_HWND,C_HANDLE,C_HANDLE, C_POINTER},
   2.355 +	C_HWND)
   2.356 +	ShowWindow = link_c_proc(user32, "ShowWindow", {C_HWND, C_INT}) --BOOL
   2.357 +	UpdateWindow = link_c_proc(user32, "UpdateWindow", {C_HWND}) --BOOL
   2.358 +	GetMessage = link_c_func(user32, "GetMessageA",
   2.359 +				{C_LPSTR, C_HWND, C_UINT, C_UINT}, C_BOOL)
   2.360 +	TranslateMessage = link_c_proc(user32, "TranslateMessage", {C_LPSTR}) --BOOL
   2.361 +	DispatchMessage = link_c_proc(user32, "DispatchMessageA", {C_LPSTR}) --LRESULT
   2.362 +	PlaySound = link_c_proc(winmm, "PlaySound", {C_LPSTR, C_HANDLE, C_DWORD}) --BOOL
   2.363 +	BeginPaint = link_c_func(user32, "BeginPaint", {C_HWND, C_POINTER}, C_HANDLE)
   2.364 +	GetClientRect = link_c_proc(user32, "GetClientRect", {C_HWND, C_POINTER}) --BOOL
   2.365 +	DrawText = link_c_proc(user32, "DrawTextA",
   2.366 +			{C_HANDLE, C_LPSTR, C_INT, C_POINTER, C_UINT})  --INT
   2.367 +	EndPaint = link_c_proc(user32, "EndPaint", {C_HWND, C_POINTER}) --BOOL
   2.368 +	PostQuitMessage = link_c_proc(user32, "PostQuitMessage", {C_INT})
   2.369 +	DefWindowProc = link_c_func(user32, "DefWindowProcA",
   2.370 +				{C_HWND, C_UINT, C_WPARAM, C_LPARAM}, C_LRESULT)
   2.371 +
   2.372 +    GetSysColor = link_c_func(user32, "GetSysColor", {C_INT}, C_DWORD)
   2.373 +
   2.374 +    SelectObject = link_c_func(gdi32, "SelectObject", {C_HANDLE, C_HANDLE}, C_HANDLE)
   2.375 +    SetTextColor = link_c_func(gdi32, "SetTextColor", {C_HANDLE, C_COLORREF}, C_COLORREF)
   2.376 +    SetBkColor = link_c_func(gdi32, "SetBkColor", {C_HANDLE, C_COLORREF}, C_COLORREF)
   2.377 +
   2.378 +    GetDeviceCaps = link_c_func(gdi32, "GetDeviceCaps", {C_HANDLE, C_INT}, C_INT)
   2.379 +    CreateFont = link_c_func(gdi32, "CreateFontA", {
   2.380 +		C_INT, C_INT, C_INT, C_INT, C_INT, C_DWORD, C_DWORD, C_DWORD,
   2.381 +		C_DWORD, C_DWORD, C_DWORD, C_DWORD, C_DWORD, C_LPSTR
   2.382 +	},
   2.383 +	C_HANDLE)
   2.384 +	
   2.385 +	MulDiv = link_c_func( kernel32, "MulDiv", { C_INT, C_INT, C_INT }, C_INT )
   2.386 +
   2.387  end procedure
   2.388  
   2.389  link_dll_routines()
   2.390  
   2.391 -atom wav_file, Euphoria, ps, rect
   2.392 -wav_file = allocate_string("\\Windows\\Media\\tada.wav")
   2.393 -Euphoria = allocate_string("A Plain Vanilla Window using Euphoria!")
   2.394 -ps = allocate(64)
   2.395 -rect = allocate(16) 
   2.396 - 
   2.397 -global function WndProc(atom hwnd, atom iMsg, atom wParam, atom lParam)
   2.398 +atom
   2.399 + --get_env(media?)
   2.400 + wav_file = allocate_string(getenv("Windir")&`\Media\tada.wav`),
   2.401 + Euphoria = allocate_string("A Plain Vanilla Window using Euphoria!"),
   2.402 + my_title = allocate_string("Euphoria for WINDOWS"),
   2.403 + $
   2.404 +
   2.405 + --from Mike Duffy Units
   2.406 +-- create_font(hdc,"Courier New",12,FW_BOLD,0,0,0)
   2.407 +
   2.408 +public function create_font(atom hdc, sequence fontname="Veranda",
   2.409 +	integer points=12,
   2.410 +	integer weight=0, integer fitalic=0,
   2.411 +	integer funderline=0, integer fstrikeout=0, atom pandf=0
   2.412 +	)
   2.413 +	atom hfont, lpszFace, ppi, lfheight
   2.414 +
   2.415 +	ppi = c_func(GetDeviceCaps,{hdc,LOGPIXELSY})
   2.416 +	lfheight = -c_func( MulDiv, { points, ppi, 72})
   2.417 +	lpszFace = allocate_string(fontname, 1)
   2.418 +	hfont = c_func(CreateFont,
   2.419 +		{lfheight,	-- logical height of font
   2.420 +		 0,			-- logical average character width
   2.421 +		 0,			-- angle of escapement
   2.422 +		 0,			-- base-line orientation angle
   2.423 +		 weight,		-- font weight
   2.424 +		 fitalic,			-- italic attribute flag
   2.425 +		 funderline,		-- underline attribute flag
   2.426 +		 fstrikeout,		-- strikeout attribute flag
   2.427 +		 DEFAULT_CHARSET,	-- character set identifier
   2.428 +		 OUT_DEFAULT_PRECIS,	-- output precision
   2.429 +		 CLIP_DEFAULT_PRECIS,	-- clipping precision
   2.430 +		 DEFAULT_QUALITY,	-- output quality
   2.431 +		 or_all({DEFAULT_PITCH,FF_DONTCARE,pandf}),-- 0 pitch and family
   2.432 +		 lpszFace 			-- pointer to typeface name string
   2.433 +		}
   2.434 +	)
   2.435 +	return hfont
   2.436 +end function
   2.437 +
   2.438  -- callback routine to handle Window class
   2.439 -    atom hdc
   2.440 -    integer temp
   2.441 -    
   2.442 -    if iMsg = WM_CREATE then
   2.443 -	c_proc(PlaySound, {wav_file,
   2.444 -			   NULL,
   2.445 -			   or_bits(SND_FILENAME, SND_ASYNC)})
   2.446 -	return 0
   2.447 -    
   2.448 -    elsif iMsg = WM_PAINT then
   2.449 -	hdc = c_func(BeginPaint, {hwnd, ps})
   2.450 -	c_proc(GetClientRect, {hwnd, rect})
   2.451 -	c_proc(DrawText, {hdc, Euphoria, -1, rect, 
   2.452 -			  or_all({DT_SINGLELINE, DT_CENTER, DT_VCENTER})})
   2.453 -	c_proc(EndPaint, {hwnd, ps})
   2.454 +public function WndProc(atom hwnd, atom iMsg, atom wParam, atom lParam)
   2.455 +	
   2.456 +	if iMsg = WM_CREATE then
   2.457 +		c_proc(PlaySound, {wav_file,
   2.458 +				NULL,
   2.459 +				or_bits(SND_FILENAME, SND_ASYNC)})
   2.460 +		return 0
   2.461 +	
   2.462 +	elsif iMsg = WM_PAINT then
   2.463 +		atom
   2.464 +			hdc,
   2.465 +			oldFont,
   2.466 +			hCtrlFont,
   2.467 +			ps = allocate( sizeof(PAINTSTRUCT), 1),
   2.468 +			rect = allocate( sizeof(RECT), 1)
   2.469 +
   2.470 +		hdc = c_func(BeginPaint, {hwnd, ps})
   2.471 +		c_proc(GetClientRect, {hwnd, rect})
   2.472 +		hCtrlFont = create_font(hdc,"Verdana",12,FW_BOLD,0,0,0,0)
   2.473 +	
   2.474 +		--oldFont = c_func(SelectObject, {hdc, c_func(GetStockObject, {ANSI_VAR_FONT}) })
   2.475 +		oldFont = c_func(SelectObject, {hdc, hCtrlFont })
   2.476 +		c_func(SetTextColor, {hdc, c_func(GetSysColor, {COLOR_BTNTEXT}) })
   2.477 +		c_func(SetBkColor, {hdc, c_func(GetSysColor, {COLOR_BTNFACE}) })
   2.478 +
   2.479 +		c_proc(DrawText, {hdc, Euphoria, -1, rect,
   2.480 +				or_all({DT_SINGLELINE, DT_CENTER, DT_VCENTER})})
   2.481 +		c_proc(EndPaint, {hwnd, ps})
   2.482  	return 0
   2.483  	
   2.484 -    elsif iMsg = WM_DESTROY then
   2.485 -	c_proc(PostQuitMessage, {0})
   2.486 -	return 0
   2.487 +	elsif iMsg = WM_DESTROY then
   2.488 +		c_proc(PostQuitMessage, {0})
   2.489 +		return 0
   2.490 +	end if
   2.491  	
   2.492 -    end if
   2.493 -    
   2.494 -    temp = c_func(DefWindowProc, {hwnd, iMsg, wParam, lParam})
   2.495 -    return temp
   2.496 +    return c_func(DefWindowProc, {hwnd, iMsg, wParam, lParam})
   2.497  end function
   2.498  
   2.499 -atom my_title
   2.500 -my_title = allocate_string("Euphoria for WIN32")
   2.501  
   2.502  procedure WinMain()
   2.503 --- main routine 
   2.504 -    atom szAppName
   2.505 -    atom hwnd
   2.506 -    atom msg
   2.507 -    atom wndclass
   2.508 -    atom WndProcAddress
   2.509 -    atom class
   2.510 -    integer id
   2.511 -    atom icon_handle
   2.512 +-- main routine
   2.513 +	atom szAppName
   2.514 +	atom hwnd
   2.515 +	atom msg
   2.516 +	atom wndclass
   2.517 +	atom WndProcAddress
   2.518 +	atom class
   2.519 +	integer id
   2.520 +	atom icon_handle
   2.521  
   2.522 -    wndclass = allocate(SIZE_OF_WNDCLASS)
   2.523 -    msg = allocate(SIZE_OF_MESSAGE)
   2.524 -    szAppName = allocate_string("HelloWin")
   2.525 +	wndclass = allocate( sizeof(WNDCLASSEX), 1)
   2.526 +	msg = allocate( sizeof(MSG), 1)
   2.527 +	szAppName = allocate_string("winhello", 1)
   2.528  
   2.529 -    id = routine_id("WndProc")
   2.530 -    if id = -1 then
   2.531 -	puts(1, "routine_id failed!\n")
   2.532 -	abort(1)
   2.533 -    end if
   2.534 -    WndProcAddress = call_back(id) -- get 32-bit address for callback
   2.535 -    
   2.536 -    poke4(wndclass + cbSize, SIZE_OF_WNDCLASS)
   2.537 -    poke4(wndclass + style, or_bits(CS_HREDRAW, CS_VREDRAW))
   2.538 -    poke4(wndclass + lpfnWndProc, WndProcAddress)
   2.539 -    poke4(wndclass + cbClsExtra, 0)
   2.540 -    poke4(wndclass + cbWndExtra, 0)
   2.541 -    poke4(wndclass + hInstance, 0) --hInstance
   2.542 +	id = routine_id("WndProc")
   2.543 +	if id = -1 then
   2.544 +		crash( "routine_id failed!")
   2.545 +	end if
   2.546 +	WndProcAddress = call_back(id) -- get address for callback
   2.547 +	
   2.548 +	wndclass.WNDCLASSEX.cbSize      = sizeof(WNDCLASSEX)
   2.549 +	wndclass.WNDCLASSEX.style       = or_bits(CS_HREDRAW, CS_VREDRAW)
   2.550 +	wndclass.WNDCLASSEX.lpfnWndProc = WndProcAddress
   2.551 +	wndclass.WNDCLASSEX.cbClsExtra  = 0
   2.552 +	wndclass.WNDCLASSEX.cbWndExtra  = 0
   2.553 +	wndclass.WNDCLASSEX.hInstance   = 0
   2.554  
   2.555 -    -- set icon in top-left of window
   2.556 -    icon_handle = c_func(LoadIcon, {instance(), allocate_string("eui")})
   2.557 -    poke4(wndclass + hIcon, icon_handle)
   2.558 -    poke4(wndclass + hIconSm, icon_handle)
   2.559 -    
   2.560 -    -- Wolfgang Fritz observes that you can set an icon
   2.561 -    -- dynamically using:
   2.562 -    -- junk = sendMessage(YourWindow, 128, 1, icon_handle) 
   2.563 -    -- where 128 is WM_SETICON   
   2.564 -    
   2.565 -    poke4(wndclass + hCursor, c_func(LoadCursor, {NULL, IDC_ARROW}))
   2.566 -    poke4(wndclass + hbrBackground, c_func(GetStockObject, {WHITE_BRUSH}))
   2.567 -    poke4(wndclass + lpszMenuName, NULL)
   2.568 -    poke4(wndclass + lpszClassName, szAppName)
   2.569 +	-- set icon in top-left of window
   2.570 +	icon_handle = c_func(LoadIcon, {instance(), allocate_string( "eui", 1)})
   2.571 +	if icon_handle = 0 then
   2.572 +		c_proc( xSetLastError, {0} )
   2.573 +		icon_handle = c_func(LoadIcon, {NULL, IDI_APPLICATION})
   2.574 +	end if
   2.575 +	wndclass.WNDCLASSEX.hIcon   = icon_handle
   2.576 +	wndclass.WNDCLASSEX.hIconSm = icon_handle
   2.577 +	
   2.578 +	-- Wolfgang Fritz observes that you can set an icon
   2.579 +	-- dynamically using:
   2.580 +	-- sendMessage(YourWindow, WM_SETICON, 1, icon_handle)
   2.581 +	-- where WM_SETICON is 128
   2.582 +	
   2.583 +	wndclass.WNDCLASSEX.hCursor       = c_func(LoadCursor, {NULL, IDC_ARROW})
   2.584 +	wndclass.WNDCLASSEX.hbrBackground = c_func(GetStockObject, {WHITE_BRUSH})
   2.585 +	wndclass.WNDCLASSEX.lpszMenuName  = NULL
   2.586 +	wndclass.WNDCLASSEX.lpszClassName = szAppName
   2.587  
   2.588 -    class = c_func(RegisterClassEx, {wndclass})
   2.589 -    if class = 0 then
   2.590 -	puts(1, "Couldn't register class\n")
   2.591 -	abort(1)
   2.592 -    end if
   2.593 -    hwnd = c_func(CreateWindow, {
   2.594 -		    0,                       -- extended style
   2.595 -		    szAppName,               -- window class name
   2.596 -		    my_title,                -- window caption
   2.597 -		    WS_OVERLAPPEDWINDOW,     -- window style
   2.598 -		    CW_USEDEFAULT,           -- initial x position
   2.599 -		    CW_USEDEFAULT,           -- initial y position
   2.600 -		    CW_USEDEFAULT,           -- initial x size
   2.601 -		    CW_USEDEFAULT,           -- initial y size
   2.602 -		    NULL,                    -- parent window handle
   2.603 -		    NULL,                    -- window menu handle
   2.604 -		    0 ,                 --hInstance // program instance handle
   2.605 -		    NULL})              -- creation parameters
   2.606 -    if hwnd = 0 then
   2.607 -	puts(1, "Couldn't CreateWindow\n")
   2.608 -	abort(1)
   2.609 -    end if
   2.610 -    c_proc(ShowWindow, {hwnd, SW_SHOWNORMAL})
   2.611 -    c_proc(UpdateWindow, {hwnd})
   2.612 +	class = c_func(RegisterClassEx, {wndclass})
   2.613 +	if class = 0 then
   2.614 +		crash("could not register class")
   2.615 +	end if
   2.616 +	hwnd = c_func(CreateWindow, {
   2.617 +			0,                       -- extended style
   2.618 +			szAppName,               -- window class name
   2.619 +			my_title,                -- window caption
   2.620 +			WS_OVERLAPPEDWINDOW,     -- window style
   2.621 +			CW_USEDEFAULT,           -- initial x position
   2.622 +			CW_USEDEFAULT,           -- initial y position
   2.623 +			CW_USEDEFAULT,           -- initial x size
   2.624 +			CW_USEDEFAULT,           -- initial y size
   2.625 +			NULL,                    -- parent window handle
   2.626 +			NULL,                    -- window menu handle
   2.627 +			0 ,                 --hInstance // program instance handle
   2.628 +			NULL})              -- creation parameters
   2.629 +	if hwnd = 0 then
   2.630 +		crash("Couldn't CreateWindow")
   2.631 +	end if
   2.632 +	c_proc(ShowWindow, {hwnd, SW_SHOWNORMAL})
   2.633 +	c_proc(UpdateWindow, {hwnd})
   2.634  
   2.635 -    while c_func(GetMessage, {msg, NULL, 0, 0}) do
   2.636 -	c_proc(TranslateMessage, {msg})
   2.637 -	c_proc(DispatchMessage, {msg})
   2.638 -    end while
   2.639 +	while c_func(GetMessage, {msg, NULL, 0, 0}) do
   2.640 +		c_proc(TranslateMessage, {msg})
   2.641 +		c_proc(DispatchMessage, {msg})
   2.642 +	end while
   2.643  end procedure
   2.644  
   2.645  WinMain()
   2.646 -
     3.1 --- a/docs/refman_2.txt	Mon Dec 19 23:19:58 2011 -0300
     3.2 +++ b/docs/refman_2.txt	Wed Dec 21 16:45:49 2011 -0300
     3.3 @@ -4126,3 +4126,436 @@
     3.4  ##with inline## takes an optional integer parameter that defines the largest
     3.5  routine (by size of IL code) that will be considered for inlining.  The default
     3.6  is 30.
     3.7 +
     3.8 +%%output=lang_memstruct
     3.9 +== Memory Structures ==
    3.10 +@[memorystructures|]
    3.11 +:<<LEVELTOC level=2 depth=4>>
    3.12 +
    3.13 +=== Introduction
    3.14 +
    3.15 +Writing Euphoria code to interact with the operating system or external libraries often
    3.16 +requires communicating via data structures stored in memory.  In addition to using
    3.17 +peeks and pokes to read and write to memory locations, Euphoria programmers can also
    3.18 +define structures that can be used to more easily read and write values from and into
    3.19 +memory.
    3.20 +
    3.21 +The conventions used are similar to those found in the C programming language, since
    3.22 +that's the way the most commonly encountered structures are defined and meant to be
    3.23 +used.  This is meant to provide a familiar syntax to those who already know C, and
    3.24 +also to make it easy to define and use memory structures.
    3.25 +
    3.26 +=== Basic Syntax
    3.27 +
    3.28 +There are two keywords for defining memory structures: memstruct and memunion.
    3.29 +They are similar, except a memstruct is a way to define a data structure that
    3.30 +may contain many different, distinct elements, while a memunion (just like a union in C)
    3.31 +is a way to refer to the same locations in memory in different ways (e.g., either as an
    3.32 +integer or as a floating point number).
    3.33 +
    3.34 +Within a memstruct or memunion, different members are defined using names for data types
    3.35 +along with some data type modifiers. 
    3.36 +
    3.37 +It is also possible to declare fixed-length arrays of a member by adding the element count
    3.38 +inside square brackets after the member name.
    3.39 +
    3.40 +==== Assigning memstruct values
    3.41 +
    3.42 +Assigning a value to a memstruct is an alternative to using one of the ##[[:poke]]## built in
    3.43 +procedures.  The big advantage to using a ##[[:memstruct]]## over ##[[:poke]]## is that
    3.44 +euphoria handles data conversion and the calculation of offsets.
    3.45 +
    3.46 +The syntax for assigning a value to memory is the pointer to the memory,
    3.47 +followed by a dot, then the name of the memstruct, optionally followed by a dot and
    3.48 +then a member of the memstruct. If that member is an array and you wish to reference
    3.49 +a specific array element, then a 1-based index inside square brackets is also required.
    3.50 +
    3.51 +<eucode>
    3.52 +memstruct POINT
    3.53 +	int x
    3.54 +	int y
    3.55 +end memstruct
    3.56 +
    3.57 +memstruct BUFFER
    3.58 +    char name[12]  -- 'name' uses 12 bytes of space.
    3.59 +    int  next_element
    3.60 +    int  element[200] -- element uses 200 * 4 = 800 bytes of space.
    3.61 +end memstruct
    3.62 +   
    3.63 +atom point = allocate( sizeof( POINT ) )
    3.64 +point.POINT.x = 1
    3.65 +point.POINT.y = 2
    3.66 +
    3.67 +atom buf = allocate( sizeof( BUFFER ) )
    3.68 +
    3.69 +buf.BUFFER.name = "testname" -- assigns first 8 byte to string and zeros the remainder.
    3.70 +buf.BUFFER.element[1] = 543
    3.71 +buf.BUFFER.element[2] = 210
    3.72 +buf.BUFFER.element[3] = 987
    3.73 +buf.BUFFER.next_element = 4
    3.74 +
    3.75 +</eucode>
    3.76 +
    3.77 +When a member is itself a memstruct, the dot notation may be continued to access the 
    3.78 +nested members.  Continuing the ##POINT## example from above:
    3.79 +
    3.80 +<eucode>
    3.81 +memstruct RECT
    3.82 +	POINT upper_left
    3.83 +	POINT lower_right
    3.84 +end memstruct
    3.85 +
    3.86 +atom rect = allocate( sizeof( RECT ) )
    3.87 +rect.RECT.upper_left.x  = 0
    3.88 +rect.RECT.lower_right.x = 5
    3.89 +</eucode>
    3.90 +
    3.91 +Additionally, you can assign to multiple members of a memstruct at a time.  When the last
    3.92 +referenced member of the left hand side is itself a memstruct, the right hand side will
    3.93 +be assigned to the respective members of the memstruct:
    3.94 +
    3.95 +<eucode>
    3.96 +point.POINT = { 3, 6 }
    3.97 +rect.RECT.upper_left = { 0, 0 }
    3.98 +</eucode>
    3.99 +
   3.100 +If an atom is passed on the right hand side, it is treated as a single element sequence.
   3.101 +If the sequence has more elements than the memstruct has members, the extra elements are 
   3.102 +ignored.  If the sequence has fewer elements than the memstruct has members, then the
   3.103 +additional members are set to zero.  This provides for a simple way to zero out all
   3.104 +elements:
   3.105 +
   3.106 +<eucode>
   3.107 +point.POINT = {3}  -- x = 3, y = 0
   3.108 +point.POINT = {}   -- x = 0, y = 0
   3.109 +</eucode>
   3.110 +
   3.111 +Note that a ##[[:memunion]]## is treated as ##unsigned char## data.
   3.112 +
   3.113 +==== Reading memstruct values
   3.114 +
   3.115 +Reading from a memstruct is an alternative to using one of the ##peek## built in
   3.116 +procedures.    The big advantage to using a ##[[:memstruct]]## over ##[[:peek]]## is that
   3.117 +euphoria handles data conversion and the calculation of offsets.
   3.118 +
   3.119 +The syntax is the same as for [[:Assigning memstruct values]], except that it is applied
   3.120 +to the right hand side of an expression.
   3.121 +
   3.122 +==== Reading and assigning with pointers
   3.123 +
   3.124 +A memstruct member that is itself a pointer has an additional way to be used.  The normal
   3.125 +assignment and reading operations deal with the value of the pointer itself.  To access
   3.126 +the value to which the pointer points, use an additional dot, then an asterisk:
   3.127 +
   3.128 +<eucode>
   3.129 +memstruct PTR_TO_INT
   3.130 +    pointer int a
   3.131 +end memstruct
   3.132 +
   3.133 +atom ptr = allocate( sizeof( PTR_TO_INT ) )
   3.134 +ptr.PTR_TO_INT.a = allocate( sizeof( int ) )
   3.135 +
   3.136 +ptr.PTR_TO_INT.a.* = 5
   3.137 +ptr.PTR_TO_INT.a.* += 5
   3.138 +
   3.139 +? ptr.PTR_TO_INT.a.* -- prints 10
   3.140 +</eucode>
   3.141 +
   3.142 +@[memstruct|]
   3.143 +==== memstruct
   3.144 +
   3.145 +##memstruct## is used to declare a memory based structure to be used by a Euphoria program.
   3.146 +The format is similar to other declarations:
   3.147 +<eucode>
   3.148 +memstruct foo
   3.149 +    int a
   3.150 +    unsigned int b
   3.151 +    pointer int c
   3.152 +end foo
   3.153 +</eucode>
   3.154 +
   3.155 +Normal scope rules apply to ##memstruct## definitions, and so they can be local, ##export##,
   3.156 +##public## or ##global##.  The members are laid out in memory sequentially, though
   3.157 +based on their sizes, Euphoria may add some space in between members, just like a
   3.158 +C compiler would.
   3.159 +
   3.160 +The size of a ##memstruct## may be determined at runtime using ##[[:sizeof]]()##.
   3.161 +It is the sum of the sizes of its members.
   3.162 +
   3.163 +##memstructs## may contain other ##memstructs## or pointers to other ##memstructs##.
   3.164 +
   3.165 +@[memunion|]
   3.166 +==== memunion
   3.167 +
   3.168 +A ##memunion## is like a ##[[:memstruct]]##, except that the various data members
   3.169 +of a ##memunion## are all located at offset zero, which means that they all start
   3.170 +at the same RAM address.  A ##memunion##, like a union in C,
   3.171 +provides different ways to interpret the same location in memory.
   3.172 +
   3.173 +<eucode>
   3.174 +memunion conversion
   3.175 +	int i
   3.176 +	float f
   3.177 +	double d
   3.178 +end memunion
   3.179 +</eucode>
   3.180 +
   3.181 +The size of a ##memunion## may be determined at runtime using ##[[:sizeof]]()##. 
   3.182 +It is the size of the largest member.
   3.183 +
   3.184 +@[memtype|]
   3.185 +==== memtype
   3.186 +
   3.187 +A ##memtype## is an alias of another type that can be used in a ##[[:memstruct]]##
   3.188 +or a ##[[:memunion]]##.  They are used similarly to how ##typedef##s are used in C,
   3.189 +and can make porting C structs easier.  Especially on Windows, it is common for 
   3.190 +many common struct declarations to be typedefs.  The euphoria programmer can 
   3.191 +therefore create a ##memtype## and use the same terminology as the native structs.
   3.192 +
   3.193 +<eucode>
   3.194 +memtype object as HANDLE
   3.195 +
   3.196 +memtype int as BOOL
   3.197 +</eucode>
   3.198 +
   3.199 +
   3.200 +@[char|]
   3.201 +==== char
   3.202 +
   3.203 +A ##char## is a data type that is 1 byte long.  Elements of type ##char## are considered
   3.204 +to be ##[[:signed]]## by default.  The range of a ##signed char## is -128 to 127.  An
   3.205 +##unsigned char## has a range of 0 - 255.  They can only be declared inside of a 
   3.206 +##[[:memstruct]]## or ##[[:memunion]]##.
   3.207 +
   3.208 +<eucode>
   3.209 +memstruct char_types
   3.210 +	char          c   -- signed by default, -128 - 127
   3.211 +	unsigned char uc  -- 0 - 255
   3.212 +	signed char   sc  -- -128 - 127
   3.213 +end memstruct
   3.214 +</eucode>
   3.215 +
   3.216 +
   3.217 +@[short|]
   3.218 +==== short
   3.219 +A ##short## is a data type that is 2 bytes long.  Elements of type ##short## are considered
   3.220 +to be ##[[:signed]]## by default.  The range of a ##signed short## is −32,768 to 32,767.  An
   3.221 +##unsigned short## has a range of 0 - 65,535.  They can only be declared inside of a 
   3.222 +##[[:memstruct]]## or ##[[:memunion]]##.
   3.223 +
   3.224 +<eucode>
   3.225 +memstruct char_types
   3.226 +	short           s  -- signed by default, −32,768 to 32,767
   3.227 +	unsigned short us  -- −32,768 to 32,767
   3.228 +	signed short   ss  -- −32,768 to 32,767
   3.229 +end memstruct
   3.230 +</eucode>
   3.231 +
   3.232 +@[int|]
   3.233 +==== int
   3.234 +
   3.235 +An ##int## is a data type that is 4 bytes long.  Elements of type ##int## are considered
   3.236 +to be ##[[:signed]]## by default.  The range of a ##signed int## is  −2,147,483,648 to 
   3.237 +2,147,483,647.  An ##unsigned int## has a range of 0 - 4,294,967,295.  They can only be 
   3.238 +declared inside of a ##[[:memstruct]]## or ##[[:memunion]]##.
   3.239 +
   3.240 +<eucode>
   3.241 +memstruct char_types
   3.242 +	int           i  -- signed by default, −2,147,483,648 to 2,147,483,647
   3.243 +	unsigned int ui  -- 0 - 4,294,967,295
   3.244 +	signed int   si  --  −2,147,483,648 to 2,147,483,647
   3.245 +end memstruct
   3.246 +</eucode>
   3.247 +
   3.248 +@[long|]
   3.249 +==== long
   3.250 +
   3.251 +A ##long## (can also be ##long int##) varies in size based on the platform.  On Windows
   3.252 +and 32-bit Unix like operating systems, a ##long## is 4 bytes, or the same size as an
   3.253 +##[[:int]]##.  On 64-bit Unix-like operating systems, a ##long## is 64-bits, or the 
   3.254 +same size as a ##[[:long long]]##.
   3.255 +
   3.256 +
   3.257 +@[long long|]
   3.258 +==== long long
   3.259 +
   3.260 +A ##long long## (can also be ##long long int##) is an integer that is 8 bytes (64-bits) in size.
   3.261 +By default, it is signed (−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807).  An ##unsigned
   3.262 +long long## varies from  0 to 18,446,744,073,709,551,615.
   3.263 +
   3.264 +
   3.265 +@[object (memstruct)|]
   3.266 +==== object (memstruct)
   3.267 +
   3.268 +An ##object##, in a ##[[:memstruct]]## or ##[[:memunion]]##, is an integer the same size as a Euphoria
   3.269 +object, and is also the same size as a pointer.  By default, it is signed, but can be declared ##unsigned##.
   3.270 +
   3.271 +@[float|]
   3.272 +==== float
   3.273 +
   3.274 +A ##float## is a 32-bit floating point number, just like those used by ##[[:atom_to_float32]]##
   3.275 +and ##[[:float32_to_atom]]##.
   3.276 +
   3.277 +@[double|]
   3.278 +==== double
   3.279 +
   3.280 +A ##double## is a 64-bit floating point number, just like those used by ##[[:atom_to_float64]]##
   3.281 +and ##[[:float64_to_atom]]##.  This is the size of floating point numbers used by 32-bit
   3.282 +Euphoria.
   3.283 +
   3.284 +@[long double|]
   3.285 +==== long double
   3.286 +
   3.287 +A ##long double## is an 80-bit floating point number, just like those used by ##[[:atom_to_float80]]##
   3.288 +and ##[[:float80_to_atom]]##.  This is the size of floating point numbers used by 64-bit
   3.289 +Euphoria.  Although they only use 80 bits, in ##[[:memstructs]]## they require 16 bytes of storage
   3.290 +for alignment purposes.
   3.291 +
   3.292 +
   3.293 +@[eudouble|]
   3.294 +==== eudouble
   3.295 +
   3.296 +A ##eudouble## is a platform independent floating point data type.  On 32-bit Euphoria, a ##eudouble##
   3.297 +is the same size (64-bits) as a ##double##.  On 64-bit Euphoria, it is 80 bits, the same size
   3.298 +as a ##long double##.
   3.299 +
   3.300 +@[pointer|]
   3.301 +==== pointer
   3.302 +
   3.303 +Data members may have the ##pointer## modifier prepended to their declaration.  This signifies that
   3.304 +the ##memstruct## contains a pointer to that type of element, rather than the element itself.
   3.305 +
   3.306 +@[signed|]
   3.307 +==== signed
   3.308 +
   3.309 +Integer data types may be signed or unsiged.  The default is to be signed, but this can be made
   3.310 +explicit by using the ##signed## modifier.
   3.311 +
   3.312 +@[unsigned|]
   3.313 +==== unsigned
   3.314 +
   3.315 +Integer data types may be signed or unsiged.  The default is to be signed, but to use an ##unsigned##
   3.316 +integer type, use the ##unsigned## modifier.
   3.317 +
   3.318 +=== Using memstructs
   3.319 +
   3.320 +To use a ##[[:memstruct]]## requires a pointer to the memory where the structure is stored.
   3.321 +This can be created by ##[[:allocate]]()##, or as the result of a call to an external library.
   3.322 +No type information is ever stored with the pointer.  Instead, the memory may be manipulated
   3.323 +using a dot notation, where the name of the ##[[:memstruct]]## follows the pointer, and
   3.324 +the names of data elements 
   3.325 +
   3.326 +Example:
   3.327 +<eucode>
   3.328 +include std/machine.e
   3.329 +
   3.330 +memstruct point
   3.331 +    int x
   3.332 +    int y
   3.333 +end memstruct
   3.334 +
   3.335 +memstruct rect
   3.336 +    point upper_left
   3.337 +    point lower_right
   3.338 +end memstruct
   3.339 +
   3.340 +atom my_rect = allocate( sizeof( rect ) )
   3.341 +
   3.342 +my_rect.rect.upper_left.x = 50
   3.343 +my_rect.rect.upper_left.y = 100
   3.344 +
   3.345 +my_rect.rect.lower_right.x = 125
   3.346 +my_rect.rect.lower_right.y = 150
   3.347 +
   3.348 +? my_rect.rect.lower_right.x  -- outputs 125
   3.349 +</eucode>
   3.350 +It is possible to //abuse// the memstruct functionality because there is no type
   3.351 +information associated with the address pointer. For example ...
   3.352 +
   3.353 +<eucode>
   3.354 +include std/machine.e
   3.355 +
   3.356 +memstruct point
   3.357 +    int x
   3.358 +    int y
   3.359 +end memstruct
   3.360 +
   3.361 +memstruct rect
   3.362 +    point upper_left
   3.363 +    point lower_right
   3.364 +end memstruct
   3.365 +
   3.366 +atom my_rect = allocate( sizeof( rect ) )
   3.367 +
   3.368 +my_rect.rect.upper_left.x = 20
   3.369 +my_rect.rect.upper_left.y = 200
   3.370 +? my_rect.rect.upper_left.x  -- outputs 20
   3.371 +
   3.372 +my_rect.point.x = 50
   3.373 +my_rect.point.y = 100
   3.374 +
   3.375 +? my_rect.rect.upper_left.x  -- outputs 50
   3.376 +</eucode>
   3.377 +
   3.378 +
   3.379 +@[addressof|]
   3.380 +==== addressof
   3.381 +
   3.382 +A function that returns the address of a memstruct member. You must supply the
   3.383 +variable that contains the starting RAM address, the memstruct name, and
   3.384 +member name sing the dot notation described above.
   3.385 +
   3.386 +Example:
   3.387 +<eucode>
   3.388 +include std/machine.e
   3.389 +
   3.390 +memstruct point
   3.391 +    int x
   3.392 +    int y
   3.393 +end memstruct
   3.394 +
   3.395 +memstruct rect
   3.396 +    point upper_left
   3.397 +    point lower_right
   3.398 +end memstruct
   3.399 +
   3.400 +atom pa = allocate( sizeof( point ) )
   3.401 +
   3.402 +? addressof(pa.point.x) = pa      -- outputs 1 (true)
   3.403 +? addressof(pa.point.y) = pa + 4  -- outputs 1 (true)
   3.404 +
   3.405 +? addressof(pa.rect.lower_right.y) = pa + 12  -- outputs 1 (true)
   3.406 +
   3.407 +</eucode>
   3.408 +
   3.409 +@[offsetof|]
   3.410 +==== offsetof
   3.411 +
   3.412 +Returns the offset in bytes of a member inside of its memstruct. You can optionally
   3.413 +omit the address pointer variable when calling this, just the memstruct name
   3.414 +and member is required.
   3.415 +
   3.416 +Example:
   3.417 +<eucode>
   3.418 +include std/machine.e
   3.419 +
   3.420 +memstruct point
   3.421 +    int x
   3.422 +    int y
   3.423 +end memstruct
   3.424 +
   3.425 +memstruct rect
   3.426 +    point upper_left
   3.427 +    point lower_right
   3.428 +end memstruct
   3.429 +
   3.430 +atom pa = allocate( sizeof( point ) )
   3.431 +
   3.432 +? offsetof(point.x)    -- outputs 0
   3.433 +? offsetof(pa.point.x) -- outputs 0
   3.434 +? offsetof(point.y)    -- outputs 4
   3.435 +? offsetof(pa.point.y) -- outputs 4
   3.436 +
   3.437 +? offsetof(rect.lower_right.y) -- outputs 12
   3.438 +
   3.439 +</eucode>
     4.1 --- a/docs/release/4.1.0.txt	Mon Dec 19 23:19:58 2011 -0300
     4.2 +++ b/docs/release/4.1.0.txt	Wed Dec 21 16:45:49 2011 -0300
     4.3 @@ -26,3 +26,6 @@
     4.4  * -cc-prefix option for translator
     4.5  * Can [[assign to multiple variables -> :Multiple Assignment]] with one statement using sequence semantics.
     4.6  * Use ##?## to stand in for default parameters.
     4.7 +* [[ticket:735]] The number of lines to be used in ctrace.out by ##trace(3)## can be configured
     4.8 +  using ##-trace-lines n## command line switch. See [[Command line switches -> :command line switches]]
     4.9 +  for more information.
    4.10 \ No newline at end of file
     5.1 --- a/docs/using_euphoria.txt	Mon Dec 19 23:19:58 2011 -0300
     5.2 +++ b/docs/using_euphoria.txt	Wed Dec 21 16:45:49 2011 -0300
     5.3 @@ -541,6 +541,10 @@
     5.4    parameter which enables many editor/IDE programs to test the syntax of your
     5.5    Euphoria source in real time.
     5.6  
     5.7 +; ##-TRACE-LINES n## (all)
     5.8 +: Changes the number of lines that will be used in ctrace.out for lines traced
     5.9 +  under ##trace(3)##.  The default is 500.
    5.10 +
    5.11  ; ##-VERSION## (all)
    5.12  : Displays the version of euphoria that is running.
    5.13  
     6.1 --- a/include/euphoria.h	Mon Dec 19 23:19:58 2011 -0300
     6.2 +++ b/include/euphoria.h	Wed Dec 21 16:45:49 2011 -0300
     6.3 @@ -329,7 +329,8 @@
     6.4  extern IFILE last_w_file_ptr;
     6.5  extern object last_r_file_no;
     6.6  extern IFILE last_r_file_ptr;
     6.7 -extern int insert_pos;;
     6.8 +extern int insert_pos;
     6.9 +extern int trace_lines;
    6.10  
    6.11  object find_from(object,object,object);
    6.12  object e_match_from(object aobj, object bobj, object c);
     7.1 --- a/include/euphoria/debug/debug.e	Mon Dec 19 23:19:58 2011 -0300
     7.2 +++ b/include/euphoria/debug/debug.e	Wed Dec 21 16:45:49 2011 -0300
     7.3 @@ -2,7 +2,6 @@
     7.4  
     7.5  include std/dll.e
     7.6  include std/machine.e
     7.7 -include euphoria/symstruct.e
     7.8  
     7.9  without trace
    7.10  
    7.11 @@ -83,6 +82,59 @@
    7.12  	return machine_func( M_CALL_STACK, {} )
    7.13  end function
    7.14  
    7.15 +public memstruct Var
    7.16 +	pointer symtab_entry declared_in
    7.17 +end memstruct
    7.18 +
    7.19 +public memstruct Block
    7.20 +	unsigned int first_line
    7.21 +	unsigned int last_line
    7.22 +end memstruct
    7.23 +
    7.24 +public memstruct private_block
    7.25 +	int task_number
    7.26 +	pointer private_block next
    7.27 +	object block[2]
    7.28 +end memstruct
    7.29 +
    7.30 +public memstruct Subp
    7.31 +	pointer object code
    7.32 +	pointer symtab_entry temps
    7.33 +	pointer private_block saved_privates
    7.34 +	pointer object block
    7.35 +	pointer int linetab
    7.36 +	unsigned int firstline
    7.37 +	unsigned int num_args
    7.38 +	int resident_task
    7.39 +	unsigned int stack_space
    7.40 +end memstruct
    7.41 +
    7.42 +public memunion U
    7.43 +	Var var
    7.44 +	Subp subp
    7.45 +	Block block
    7.46 +end memunion
    7.47 +
    7.48 +public memstruct symtab_entry
    7.49 +	object obj
    7.50 +	pointer symtab_entry next
    7.51 +	pointer symtab_entry next_in_block
    7.52 +	char mode
    7.53 +	char scope
    7.54 +	unsigned char file_no
    7.55 +	unsigned char dummy
    7.56 +	int token
    7.57 +	pointer char name
    7.58 +	U u
    7.59 +end memstruct
    7.60 +
    7.61 +public memstruct source_line
    7.62 +	pointer char src
    7.63 +	short        line
    7.64 +	char         file_no
    7.65 +	char         options
    7.66 +end memstruct
    7.67 +
    7.68  
    7.69  atom
    7.70  	symbol_table    = 0,
    7.71 @@ -318,27 +370,27 @@
    7.72  end function
    7.73  
    7.74  public function get_name( atom sym )
    7.75 -	return peek_string( peek_pointer( sym + ST_NAME ) )
    7.76 +	return peek_string( sym.symtab_entry.name )
    7.77  end function
    7.78  
    7.79 -public function get_source( integer line )
    7.80 -	return peek_string( peek_pointer( slist + SL_SIZE * line + SL_SRC ) )
    7.81 +public function get_source( integer src_line )
    7.82 +	return peek_string( slist.source_line[src_line].src )
    7.83  end function
    7.84  
    7.85  public function get_file_no( integer line )
    7.86 -	return peek( slist + line * SL_SIZE + SL_FILE_NO )
    7.87 +	return slist.source_line[line].file_no
    7.88  end function
    7.89  
    7.90  public function get_file_name( integer file_no )
    7.91 -	return peek_string( peek_pointer( file_name_ptr + sizeof( C_POINTER ) * file_no ) )
    7.92 +	return peek_string( file_name_ptr + sizeof( pointer ) * file_no )
    7.93  end function
    7.94  
    7.95 -public function get_file_line( integer line )
    7.96 -	return peek2u( slist + line * SL_SIZE + SL_LINE )
    7.97 +public function get_file_line( integer line_no )
    7.98 +	return slist.source_line[line_no].line
    7.99  end function
   7.100  
   7.101  public function get_next( atom sym )
   7.102 -	return peek_pointer( sym + ST_NEXT )
   7.103 +	return sym.symtab_entry.next
   7.104  end function
   7.105  
   7.106  public function is_variable( atom sym_ptr )
   7.107 @@ -346,16 +398,16 @@
   7.108  		return 0
   7.109  	end if
   7.110  	
   7.111 -	return -100 = peek4s( sym_ptr + ST_TOKEN )
   7.112 +	return -100 = sym_ptr.symtab_entry.token
   7.113  end function
   7.114  
   7.115  public function get_parameter_syms( atom rtn_sym )
   7.116 -	integer param_count = peek4u( rtn_sym + ST_NUM_ARGS )
   7.117 +	integer param_count = rtn_sym.symtab_entry.u.subp.num_args
   7.118  	sequence syms = repeat( 0, param_count )
   7.119 -	atom next_sym = peek_pointer( rtn_sym + ST_NEXT )
   7.120 +	atom next_sym = rtn_sym.symtab_entry.next
   7.121  	for i = 1 to param_count do
   7.122 -		while peek( next_sym + ST_SCOPE ) != 3 do -- SC_PRIVATE = 3
   7.123 -			next_sym = peek_pointer( next_sym + ST_NEXT )
   7.124 +		while next_sym.symtab_entry.scope != 3 do -- SC_PRIVATE = 3
   7.125 +			next_sym = next_sym.symtab_entry.next
   7.126  		end while
   7.127  		syms[i] = next_sym
   7.128  	end for
     8.1 --- a/include/euphoria/keywords.e	Mon Dec 19 23:19:58 2011 -0300
     8.2 +++ b/include/euphoria/keywords.e	Wed Dec 21 16:45:49 2011 -0300
     8.3 @@ -25,6 +25,7 @@
     8.4  	"continue",
     8.5      "deprecate",
     8.6  	"do",
     8.7 +	"double",
     8.8  	"else",
     8.9  	"elsedef",
    8.10  	"elsif",
    8.11 @@ -35,6 +36,7 @@
    8.12  	"exit",
    8.13  	"export",
    8.14  	"fallthru",
    8.15 +	"float",
    8.16  	"for",
    8.17  	"function",
    8.18  	"global",
    8.19 @@ -42,21 +44,29 @@
    8.20  	"if",
    8.21  	"ifdef",
    8.22  	"include",
    8.23 +	"int",
    8.24  	"label",
    8.25 +	"long",
    8.26  	"loop",
    8.27 +	"memstruct",
    8.28 +	"memtype",
    8.29 +	"memunion",
    8.30  	"namespace",
    8.31  	"not",
    8.32  	"or",
    8.33  	"override",
    8.34 +	"pointer",
    8.35  	"procedure",
    8.36  	"public",
    8.37  	"retry",
    8.38  	"return",
    8.39  	"routine",
    8.40 +	"signed",
    8.41  	"switch",
    8.42  	"then",
    8.43  	"to",
    8.44  	"type",
    8.45 +	"unsigned",
    8.46  	"until",
    8.47  	"while",
    8.48  	"with",
     9.1 --- a/include/euphoria/symstruct.e	Mon Dec 19 23:19:58 2011 -0300
     9.2 +++ b/include/euphoria/symstruct.e	Wed Dec 21 16:45:49 2011 -0300
     9.3 @@ -28,6 +28,16 @@
     9.4  	ST_FIRST_LINE     = offset( C_INT, ST_DECLARED_IN ), -- 24,
     9.5  	ST_LAST_LINE      = offset( C_INT ), -- 28,
     9.6  	
     9.7 +	-- memstruct:
     9.8 +	ST_MEM_NEXT       = offset( C_POINTER, ST_DECLARED_IN  ),
     9.9 +	ST_MEM_STRUCT     = offset( C_POINTER ),
    9.10 +	ST_MEM_PARENT     = offset( C_POINTER ),
    9.11 +	ST_MEM_SIZE       = offset( C_INT ),
    9.12 +	ST_MEM_OFFSET     = offset( C_INT ),
    9.13 +	ST_MEM_ARRAY      = offset( C_INT ),
    9.14 +	ST_MEM_SIGNED     = offset( C_CHAR ),
    9.15 +	ST_MEM_POINTER    = offset( C_CHAR ),
    9.16 +	
    9.17  	-- routine:
    9.18  	ST_CODE           = offset( C_POINTER, ST_DECLARED_IN ), -- 24,
    9.19  	ST_TEMPS          = offset( C_POINTER ), -- 36,
    10.1 --- a/include/euphoria/tokenize.e	Mon Dec 19 23:19:58 2011 -0300
    10.2 +++ b/include/euphoria/tokenize.e	Wed Dec 21 16:45:49 2011 -0300
    10.3 @@ -1020,7 +1020,7 @@
    10.4  				Token[TDATA] &= Look
    10.5  
    10.6  				scan_char(state)
    10.7 -			else
    10.8 +			elsif find( Look, "0123456789" )  then
    10.9  				-- .number
   10.10  				Token[TTYPE] = T_NUMBER
   10.11  				Token[TDATA] = scan_fraction(0, state)
   10.12 @@ -1038,6 +1038,9 @@
   10.13  						Token[TDATA] = sprintf("%g",{Token[TDATA]})
   10.14  					end if
   10.15  				end if
   10.16 +			else
   10.17 +				-- memstruct
   10.18 +				scan_identifier( state )
   10.19  			end if
   10.20  
   10.21  		elsif (Look = '-') and (Token[TTYPE] = T_MINUS) then
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/include/std/memstruct/windows.e	Wed Dec 21 16:45:49 2011 -0300
    11.3 @@ -0,0 +1,318 @@
    11.4 +--****
    11.5 +-- == Common Windows Memstructs
    11.6 +--
    11.7 +-- <<LEVELTOC level=2 depth=5>>
    11.8 +--
    11.9 +
   11.10 +--****
   11.11 +-- === Windows Type constants for structs
   11.12 +
   11.13 +public memtype
   11.14 +	char as BYTE,
   11.15 +	int as BOOL,
   11.16 +	int as INT,
   11.17 +	unsigned int as UINT,
   11.18 +	long as LONG,
   11.19 +	unsigned long as ULONG,
   11.20 +	double as DOUBLE,
   11.21 +	short as WORD,
   11.22 +	long as DWORD,
   11.23 +	object as HANDLE,
   11.24 +	object as HWND,
   11.25 +	object as LPSTR,
   11.26 +	object as LPTSTR,
   11.27 +	object as WNDPROC,
   11.28 +	object as WPARAM,
   11.29 +	object as LPARAM,
   11.30 +	object as HINSTANCE,
   11.31 +	object as LPCSTR,
   11.32 +	object as LPCTSTR,
   11.33 +	object as LPOFNHOOKPROC,
   11.34 +	object as BFFCALLBACK,
   11.35 +	unsigned short as USHORT,
   11.36 +	object as LPCCHOOKPROC,
   11.37 +	long as COLORREF,
   11.38 +	object as INT_PTR,
   11.39 +	object as UINT_PTR,
   11.40 +	char as TCHAR,
   11.41 +	object as HICON,
   11.42 +	object as HTREEITEM,
   11.43 +	object as LPFRHOOKPROC,
   11.44 +	$
   11.45 +	
   11.46 +--****
   11.47 +-- === Windows structures
   11.48 +
   11.49 +public memstruct WNDCLASSEX
   11.50 +	UINT cbSize
   11.51 +	UINT style
   11.52 +	WNDPROC lpfnWndProc  	--WNDPROC
   11.53 +	INT cbClsExtra
   11.54 +	INT cbWndExtra
   11.55 +	HANDLE hInstance  	--HINSTANCE
   11.56 +	HANDLE hIcon   		--HICON
   11.57 +	HANDLE hCursor  	--HCURSOR
   11.58 +	HANDLE hbrBackground 	--HBRUSH
   11.59 +	LPSTR lpszMenuName  	--LPCSTR
   11.60 +	LPSTR lpszClassName	--LPCSTR
   11.61 +	HANDLE hIconSm		--HICON
   11.62 +end memstruct
   11.63 +
   11.64 +public memstruct POINT
   11.65 +	LONG x
   11.66 +	LONG y
   11.67 +end memstruct
   11.68 +
   11.69 +public memstruct RECT
   11.70 +	LONG left
   11.71 +	LONG top
   11.72 +	LONG right
   11.73 +	LONG bottom
   11.74 +end memstruct
   11.75 +
   11.76 +public memstruct PAINTSTRUCT
   11.77 +	HANDLE hdc		--HDC
   11.78 +	BOOL fErase
   11.79 +	RECT rcPaint		--RECT
   11.80 +	BOOL fRestore
   11.81 +	BOOL fIncUpdate
   11.82 +	BYTE rgbReserved[32]	--BYTE,32
   11.83 +end memstruct
   11.84 +
   11.85 +public memstruct MSG
   11.86 +	HWND hwnd
   11.87 +	UINT message
   11.88 +	WPARAM wParam
   11.89 +	LPARAM lParam
   11.90 +	DWORD time
   11.91 +	POINT pt
   11.92 +end memstruct
   11.93 +
   11.94 +public memstruct NMHDR
   11.95 +	HWND hwndFrom
   11.96 +	UINT_PTR idFrom
   11.97 +	UINT code
   11.98 +end memstruct
   11.99 +
  11.100 +public memstruct LVCOLUMN
  11.101 +	UINT mask
  11.102 +	int fmt
  11.103 +	int cx
  11.104 +	LPTSTR pszText
  11.105 +	int cchTextMax
  11.106 +	int iSubItem
  11.107 +	int iImage
  11.108 +	int iOrder
  11.109 +	int cxMin
  11.110 +	int cxDefault
  11.111 +	int cxIdeal
  11.112 +end memstruct
  11.113 +
  11.114 +public memstruct LVITEM
  11.115 +	UINT mask
  11.116 +	int    iItem
  11.117 +	int    iSubItem
  11.118 +	UINT   state
  11.119 +	UINT   stateMask
  11.120 +	LPTSTR pszText
  11.121 +	int    cchTextMax
  11.122 +	int    iImage
  11.123 +	object lParam
  11.124 +-- 	#if (_WIN32_IE >= 0x0300)
  11.125 +	int    iIndent
  11.126 +-- 	#endif 
  11.127 +-- 	#if (_WIN32_WINNT >= 0x0501)
  11.128 +	int    iGroupId
  11.129 +	UINT   cColumns
  11.130 +	UINT   puColumns
  11.131 +-- 	#endif 
  11.132 +-- 	#if (_WIN32_WINNT >= 0x0600)
  11.133 +	int    piColFmt
  11.134 +	int    iGroup
  11.135 +end memstruct
  11.136 +
  11.137 +public memstruct LV_DISPINFO
  11.138 +	NMHDR hdr
  11.139 +	LVITEM item
  11.140 +end memstruct
  11.141 +
  11.142 +public memstruct OPENFILENAME
  11.143 +  DWORD         lStructSize
  11.144 +  HWND          hwndOwner
  11.145 +  HINSTANCE     hInstance
  11.146 +  LPCTSTR       lpstrFilter
  11.147 +  LPTSTR        lpstrCustomFilter
  11.148 +  DWORD         nMaxCustFilter
  11.149 +  DWORD         nFilterIndex
  11.150 +  LPTSTR        lpstrFile
  11.151 +  DWORD         nMaxFile
  11.152 +  LPTSTR        lpstrFileTitle
  11.153 +  DWORD         nMaxFileTitle
  11.154 +  LPCTSTR       lpstrInitialDir
  11.155 +  LPCTSTR       lpstrTitle
  11.156 +  DWORD         Flags
  11.157 +  WORD          nFileOffset
  11.158 +  WORD          nFileExtension
  11.159 +  LPCTSTR       lpstrDefExt
  11.160 +  LPARAM        lCustData
  11.161 +  LPOFNHOOKPROC lpfnHook
  11.162 +  LPCTSTR       lpTemplateName
  11.163 +-- #if (_WIN32_WINNT >= 0x0500)
  11.164 +  object        pvReserved
  11.165 +  DWORD         dwReserved
  11.166 +  DWORD         FlagsEx
  11.167 +-- #endif 
  11.168 +end memstruct
  11.169 +
  11.170 +public memstruct SHITEMID
  11.171 +	USHORT cb
  11.172 +	pointer BYTE abID
  11.173 +end memstruct
  11.174 +
  11.175 +public memstruct BROWSEINFO
  11.176 +	HWND              hwndOwner
  11.177 +	pointer SHITEMID  pidlRoot
  11.178 +	LPTSTR            pszDisplayName
  11.179 +	LPCTSTR           lpszTitle
  11.180 +	UINT              ulFlags
  11.181 +	BFFCALLBACK       lpfn
  11.182 +	LPARAM            lParam
  11.183 +	int               iImage
  11.184 +end memstruct
  11.185 +
  11.186 +public memstruct CHOOSECOLOR
  11.187 +	DWORD        lStructSize
  11.188 +	HWND         hwndOwner
  11.189 +	HWND         hInstance
  11.190 +	COLORREF     rgbResult
  11.191 +	pointer COLORREF     lpCustColors
  11.192 +	DWORD        Flags
  11.193 +	LPARAM       lCustData
  11.194 +	LPCCHOOKPROC lpfnHook
  11.195 +	LPCTSTR      lpTemplateName
  11.196 +end memstruct
  11.197 +
  11.198 +public memstruct COMBOBOXEXITEM
  11.199 +	UINT    mask
  11.200 +	INT_PTR iItem
  11.201 +	LPTSTR  pszText
  11.202 +	int     cchTextMax
  11.203 +	int     iImage
  11.204 +	int     iSelectedImage
  11.205 +	int     iOverlay
  11.206 +	int     iIndent
  11.207 +	LPARAM  lParam
  11.208 +end memstruct
  11.209 +
  11.210 +public memstruct NMLISTVIEW
  11.211 +	NMHDR  hdr
  11.212 +	int    iItem
  11.213 +	int    iSubItem
  11.214 +	UINT   uNewState
  11.215 +	UINT   uOldState
  11.216 +	UINT   uChanged
  11.217 +	POINT  ptAction
  11.218 +	LPARAM lParam
  11.219 +end memstruct
  11.220 +
  11.221 +public memstruct SHFILEINFO
  11.222 +  HICON hIcon
  11.223 +  int   iIcon
  11.224 +  DWORD dwAttributes
  11.225 +  TCHAR szDisplayName[260]
  11.226 +  TCHAR szTypeName[80]
  11.227 +end memstruct
  11.228 +
  11.229 +public memstruct TVITEM
  11.230 +	UINT      mask
  11.231 +	HTREEITEM hItem
  11.232 +	UINT      state
  11.233 +	UINT      stateMask
  11.234 +	LPTSTR    pszText
  11.235 +	int       cchTextMax
  11.236 +	int       iImage
  11.237 +	int       iSelectedImage
  11.238 +	int       cChildren
  11.239 +	LPARAM    lParam
  11.240 +end memstruct
  11.241 +
  11.242 +public memstruct TVITEMEX
  11.243 +	UINT      mask
  11.244 +	HTREEITEM hItem
  11.245 +	UINT      state
  11.246 +	UINT      stateMask
  11.247 +	LPTSTR    pszText
  11.248 +	int       cchTextMax
  11.249 +	int       iImage
  11.250 +	int       iSelectedImage
  11.251 +	int       cChildren
  11.252 +	LPARAM    lParam
  11.253 +	int       iIntegral
  11.254 +-- 	#if (_WIN32_IE >= 0x0600)
  11.255 +	UINT      uStateEx
  11.256 +	HWND      hwnd
  11.257 +	int       iExpandedImage
  11.258 +-- -- 	#endif 
  11.259 +-- -- 	#if (NTDDI_VERSION >= NTDDI_WIN7)
  11.260 +	int       iReserved
  11.261 +-- 	#endif 
  11.262 +end memstruct
  11.263 +
  11.264 +public memunion TVINSERTUNION
  11.265 +	TVITEMEX itemex
  11.266 +	TVITEM   item
  11.267 +end memunion
  11.268 +
  11.269 +public memstruct TVINSERTSTRUCT
  11.270 +	HTREEITEM hParent
  11.271 +	HTREEITEM hInsertAfter
  11.272 +-- 	#if (_WIN32_IE >= 0x0400)
  11.273 +	TVINSERTUNION u
  11.274 +end memstruct
  11.275 +
  11.276 +public memstruct NMTVDISPINFO
  11.277 +	NMHDR hdr
  11.278 +	TVITEM item
  11.279 +end memstruct
  11.280 +
  11.281 +public memstruct NMTREEVIEW
  11.282 +	NMHDR  hdr
  11.283 +	UINT   action
  11.284 +	TVITEM itemOld
  11.285 +	TVITEM itemNew
  11.286 +	POINT  ptDrag
  11.287 +end memstruct
  11.288 +
  11.289 +public memstruct TVHITTESTINFO
  11.290 +	POINT     pt
  11.291 +	UINT      flags
  11.292 +	HTREEITEM hItem
  11.293 +end memstruct
  11.294 +
  11.295 +public memstruct NMCBEENDEDIT
  11.296 +	NMHDR hdr
  11.297 +	BOOL  fChanged
  11.298 +	int   iNewSelection
  11.299 +	TCHAR szText
  11.300 +	int   iWhy
  11.301 +end memstruct
  11.302 +
  11.303 +public memstruct NMUPDOWN
  11.304 +	NMHDR hdr
  11.305 +	int   iPos
  11.306 +	int   iDelta
  11.307 +end memstruct
  11.308 +
  11.309 +public memstruct FINDREPLACE
  11.310 +	DWORD        lStructSize
  11.311 +	HWND         hwndOwner
  11.312 +	HINSTANCE    hInstance
  11.313 +	DWORD        Flags
  11.314 +	LPTSTR       lpstrFindWhat
  11.315 +	LPTSTR       lpstrReplaceWith
  11.316 +	WORD         wFindWhatLen
  11.317 +	WORD         wReplaceWithLen
  11.318 +	LPARAM       lCustData
  11.319 +	LPFRHOOKPROC lpfnHook
  11.320 +	LPCTSTR      lpTemplateName
  11.321 +end memstruct
    12.1 --- a/source/Makefile.gnu	Mon Dec 19 23:19:58 2011 -0300
    12.2 +++ b/source/Makefile.gnu	Wed Dec 21 16:45:49 2011 -0300
    12.3 @@ -270,6 +270,7 @@
    12.4  	inline.e \
    12.5  	keylist.e \
    12.6  	main.e \
    12.7 +	memstruct.e \
    12.8  	msgtext.e \
    12.9  	mode.e \
   12.10  	opnames.e \
   12.11 @@ -295,6 +296,7 @@
   12.12  	buildsys.e \
   12.13  	c_decl.e \
   12.14  	c_out.e \
   12.15 +	c_struct.e \
   12.16  	cominit.e \
   12.17  	compile.e \
   12.18  	compress.e \
   12.19 @@ -334,6 +336,7 @@
   12.20  	$(BUILDDIR)/$(OBJDIR)/back/be_symtab.o \
   12.21  	$(BUILDDIR)/$(OBJDIR)/back/be_socket.o \
   12.22  	$(BUILDDIR)/$(OBJDIR)/back/be_w.o \
   12.23 +	$(BUILDDIR)/$(OBJDIR)/back/be_memstruct.o \
   12.24  	$(PREFIXED_PCRE_OBJECTS)
   12.25  
   12.26  EU_LIB_OBJECTS = \
   12.27 @@ -1005,18 +1008,18 @@
   12.28  # The dependencies below are automatically generated using the depend target above.
   12.29  # DO NOT DELETE
   12.30  
   12.31 -$(BUILDDIR)/intobj/back/be_alloc.o: be_alloc.h  alldefs.h global.h object.h symtab.h
   12.32 -$(BUILDDIR)/intobj/back/be_alloc.o: be_alloc.h  execute.h reswords.h be_runtime.h
   12.33 -$(BUILDDIR)/intobj/back/be_alloc.o: be_alloc.h  be_alloc.h
   12.34 +$(BUILDDIR)/intobj/back/be_alloc.o: alldefs.h global.h object.h symtab.h
   12.35 +$(BUILDDIR)/intobj/back/be_alloc.o: execute.h reswords.h be_runtime.h
   12.36 +$(BUILDDIR)/intobj/back/be_alloc.o: be_alloc.h
   12.37  $(BUILDDIR)/intobj/back/be_callc.o: alldefs.h global.h object.h symtab.h
   12.38  $(BUILDDIR)/intobj/back/be_callc.o: execute.h reswords.h be_runtime.h
   12.39  $(BUILDDIR)/intobj/back/be_callc.o: be_machine.h be_alloc.h
   12.40  $(BUILDDIR)/intobj/back/be_coverage.o: be_coverage.h be_machine.h global.h
   12.41  $(BUILDDIR)/intobj/back/be_coverage.o: object.h symtab.h execute.h
   12.42  $(BUILDDIR)/intobj/back/be_debug.o: execute.h global.h object.h symtab.h
   12.43 -$(BUILDDIR)/intobj/back/be_debug.o: be_alloc.h be_debug.h be_execute.h
   12.44 -$(BUILDDIR)/intobj/back/be_debug.o: be_machine.h be_rterror.h be_runtime.h
   12.45 -$(BUILDDIR)/intobj/back/be_debug.o: reswords.h
   12.46 +$(BUILDDIR)/intobj/back/be_debug.o: redef.h reswords.h be_alloc.h be_debug.h
   12.47 +$(BUILDDIR)/intobj/back/be_debug.o: be_execute.h be_machine.h be_rterror.h
   12.48 +$(BUILDDIR)/intobj/back/be_debug.o: be_runtime.h be_symtab.h
   12.49  $(BUILDDIR)/intobj/back/be_decompress.o: alldefs.h global.h object.h symtab.h
   12.50  $(BUILDDIR)/intobj/back/be_decompress.o: execute.h reswords.h be_alloc.h
   12.51  $(BUILDDIR)/intobj/back/be_decompress.o: be_runtime.h
   12.52 @@ -1026,6 +1029,7 @@
   12.53  $(BUILDDIR)/intobj/back/be_execute.o: be_inline.h be_machine.h be_task.h
   12.54  $(BUILDDIR)/intobj/back/be_execute.o: be_rterror.h be_symtab.h be_w.h
   12.55  $(BUILDDIR)/intobj/back/be_execute.o: be_callc.h be_coverage.h be_execute.h
   12.56 +$(BUILDDIR)/intobj/back/be_execute.o: be_debug.h be_memstruct.h
   12.57  $(BUILDDIR)/intobj/back/be_inline.o: alldefs.h global.h object.h symtab.h
   12.58  $(BUILDDIR)/intobj/back/be_inline.o: execute.h reswords.h be_alloc.h
   12.59  $(BUILDDIR)/intobj/back/be_machine.o: global.h object.h symtab.h alldefs.h
   12.60 @@ -1039,9 +1043,12 @@
   12.61  $(BUILDDIR)/intobj/back/be_main.o: execute.h reswords.h be_runtime.h
   12.62  $(BUILDDIR)/intobj/back/be_main.o: be_execute.h be_alloc.h be_rterror.h
   12.63  $(BUILDDIR)/intobj/back/be_main.o: be_w.h
   12.64 -$(BUILDDIR)/intobj/back/be_pcre.o: be_alloc.h  alldefs.h global.h object.h symtab.h
   12.65 -$(BUILDDIR)/intobj/back/be_pcre.o: be_alloc.h  execute.h reswords.h be_alloc.h
   12.66 -$(BUILDDIR)/intobj/back/be_pcre.o: be_alloc.h  be_runtime.h be_pcre.h pcre/pcre.h
   12.67 +$(BUILDDIR)/intobj/back/be_memstruct.o: execute.h global.h object.h symtab.h
   12.68 +$(BUILDDIR)/intobj/back/be_memstruct.o: reswords.h be_alloc.h be_machine.h
   12.69 +$(BUILDDIR)/intobj/back/be_memstruct.o: be_memstruct.h be_runtime.h
   12.70 +$(BUILDDIR)/intobj/back/be_pcre.o: alldefs.h global.h object.h symtab.h
   12.71 +$(BUILDDIR)/intobj/back/be_pcre.o: execute.h reswords.h be_alloc.h
   12.72 +$(BUILDDIR)/intobj/back/be_pcre.o: be_runtime.h be_pcre.h pcre/pcre.h
   12.73  $(BUILDDIR)/intobj/back/be_pcre.o: be_machine.h
   12.74  $(BUILDDIR)/intobj/back/be_rterror.o: alldefs.h global.h object.h symtab.h
   12.75  $(BUILDDIR)/intobj/back/be_rterror.o: execute.h reswords.h be_rterror.h
   12.76 @@ -1067,23 +1074,23 @@
   12.77  $(BUILDDIR)/intobj/back/be_task.o: reswords.h be_runtime.h be_task.h
   12.78  $(BUILDDIR)/intobj/back/be_task.o: be_alloc.h be_machine.h be_execute.h
   12.79  $(BUILDDIR)/intobj/back/be_task.o: be_symtab.h alldefs.h
   12.80 -$(BUILDDIR)/intobj/back/be_w.o: be_alloc.h  alldefs.h global.h object.h symtab.h
   12.81 -$(BUILDDIR)/intobj/back/be_w.o: be_alloc.h  execute.h reswords.h be_w.h be_machine.h
   12.82 -$(BUILDDIR)/intobj/back/be_w.o: be_alloc.h  be_runtime.h be_rterror.h be_alloc.h
   12.83 +$(BUILDDIR)/intobj/back/be_w.o: alldefs.h global.h object.h symtab.h
   12.84 +$(BUILDDIR)/intobj/back/be_w.o: execute.h reswords.h be_w.h be_machine.h
   12.85 +$(BUILDDIR)/intobj/back/be_w.o: be_runtime.h be_rterror.h be_alloc.h
   12.86  $(BUILDDIR)/intobj/back/rbt.o: rbt.h
   12.87  
   12.88 -$(BUILDDIR)/transobj/back/be_alloc.o: be_alloc.h  alldefs.h global.h object.h symtab.h
   12.89 -$(BUILDDIR)/transobj/back/be_alloc.o: be_alloc.h  execute.h reswords.h be_runtime.h
   12.90 -$(BUILDDIR)/transobj/back/be_alloc.o: be_alloc.h  be_alloc.h
   12.91 +$(BUILDDIR)/transobj/back/be_alloc.o: alldefs.h global.h object.h symtab.h
   12.92 +$(BUILDDIR)/transobj/back/be_alloc.o: execute.h reswords.h be_runtime.h
   12.93 +$(BUILDDIR)/transobj/back/be_alloc.o: be_alloc.h
   12.94  $(BUILDDIR)/transobj/back/be_callc.o: alldefs.h global.h object.h symtab.h
   12.95  $(BUILDDIR)/transobj/back/be_callc.o: execute.h reswords.h be_runtime.h
   12.96  $(BUILDDIR)/transobj/back/be_callc.o: be_machine.h be_alloc.h
   12.97  $(BUILDDIR)/transobj/back/be_coverage.o: be_coverage.h be_machine.h global.h
   12.98  $(BUILDDIR)/transobj/back/be_coverage.o: object.h symtab.h execute.h
   12.99  $(BUILDDIR)/transobj/back/be_debug.o: execute.h global.h object.h symtab.h
  12.100 -$(BUILDDIR)/transobj/back/be_debug.o: be_alloc.h be_debug.h be_execute.h
  12.101 -$(BUILDDIR)/transobj/back/be_debug.o: be_machine.h be_rterror.h be_runtime.h
  12.102 -$(BUILDDIR)/transobj/back/be_debug.o: reswords.h
  12.103 +$(BUILDDIR)/transobj/back/be_debug.o: redef.h reswords.h be_alloc.h
  12.104 +$(BUILDDIR)/transobj/back/be_debug.o: be_debug.h be_execute.h be_machine.h
  12.105 +$(BUILDDIR)/transobj/back/be_debug.o: be_rterror.h be_runtime.h be_symtab.h
  12.106  $(BUILDDIR)/transobj/back/be_decompress.o: alldefs.h global.h object.h
  12.107  $(BUILDDIR)/transobj/back/be_decompress.o: symtab.h execute.h reswords.h
  12.108  $(BUILDDIR)/transobj/back/be_decompress.o: be_alloc.h be_runtime.h
  12.109 @@ -1093,6 +1100,7 @@
  12.110  $(BUILDDIR)/transobj/back/be_execute.o: be_inline.h be_machine.h be_task.h
  12.111  $(BUILDDIR)/transobj/back/be_execute.o: be_rterror.h be_symtab.h be_w.h
  12.112  $(BUILDDIR)/transobj/back/be_execute.o: be_callc.h be_coverage.h be_execute.h
  12.113 +$(BUILDDIR)/transobj/back/be_execute.o: be_debug.h be_memstruct.h
  12.114  $(BUILDDIR)/transobj/back/be_inline.o: alldefs.h global.h object.h symtab.h
  12.115  $(BUILDDIR)/transobj/back/be_inline.o: execute.h reswords.h be_alloc.h
  12.116  $(BUILDDIR)/transobj/back/be_machine.o: global.h object.h symtab.h alldefs.h
  12.117 @@ -1107,9 +1115,13 @@
  12.118  $(BUILDDIR)/transobj/back/be_main.o: execute.h reswords.h be_runtime.h
  12.119  $(BUILDDIR)/transobj/back/be_main.o: be_execute.h be_alloc.h be_rterror.h
  12.120  $(BUILDDIR)/transobj/back/be_main.o: be_w.h
  12.121 -$(BUILDDIR)/transobj/back/be_pcre.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.122 -$(BUILDDIR)/transobj/back/be_pcre.o: be_alloc.h  execute.h reswords.h be_alloc.h
  12.123 -$(BUILDDIR)/transobj/back/be_pcre.o: be_alloc.h  be_runtime.h be_pcre.h pcre/pcre.h
  12.124 +$(BUILDDIR)/transobj/back/be_memstruct.o: execute.h global.h object.h
  12.125 +$(BUILDDIR)/transobj/back/be_memstruct.o: symtab.h reswords.h be_alloc.h
  12.126 +$(BUILDDIR)/transobj/back/be_memstruct.o: be_machine.h be_memstruct.h
  12.127 +$(BUILDDIR)/transobj/back/be_memstruct.o: be_runtime.h
  12.128 +$(BUILDDIR)/transobj/back/be_pcre.o: alldefs.h global.h object.h symtab.h
  12.129 +$(BUILDDIR)/transobj/back/be_pcre.o: execute.h reswords.h be_alloc.h
  12.130 +$(BUILDDIR)/transobj/back/be_pcre.o: be_runtime.h be_pcre.h pcre/pcre.h
  12.131  $(BUILDDIR)/transobj/back/be_pcre.o: be_machine.h
  12.132  $(BUILDDIR)/transobj/back/be_rterror.o: alldefs.h global.h object.h symtab.h
  12.133  $(BUILDDIR)/transobj/back/be_rterror.o: execute.h reswords.h be_rterror.h
  12.134 @@ -1136,23 +1148,23 @@
  12.135  $(BUILDDIR)/transobj/back/be_task.o: reswords.h be_runtime.h be_task.h
  12.136  $(BUILDDIR)/transobj/back/be_task.o: be_alloc.h be_machine.h be_execute.h
  12.137  $(BUILDDIR)/transobj/back/be_task.o: be_symtab.h alldefs.h
  12.138 -$(BUILDDIR)/transobj/back/be_w.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.139 -$(BUILDDIR)/transobj/back/be_w.o: be_alloc.h  execute.h reswords.h be_w.h be_machine.h
  12.140 -$(BUILDDIR)/transobj/back/be_w.o: be_alloc.h  be_runtime.h be_rterror.h be_alloc.h
  12.141 +$(BUILDDIR)/transobj/back/be_w.o: alldefs.h global.h object.h symtab.h
  12.142 +$(BUILDDIR)/transobj/back/be_w.o: execute.h reswords.h be_w.h be_machine.h
  12.143 +$(BUILDDIR)/transobj/back/be_w.o: be_runtime.h be_rterror.h be_alloc.h
  12.144  $(BUILDDIR)/transobj/back/rbt.o: rbt.h
  12.145  
  12.146 -$(BUILDDIR)/backobj/back/be_alloc.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.147 -$(BUILDDIR)/backobj/back/be_alloc.o: be_alloc.h  execute.h reswords.h be_runtime.h
  12.148 -$(BUILDDIR)/backobj/back/be_alloc.o: be_alloc.h  be_alloc.h
  12.149 +$(BUILDDIR)/backobj/back/be_alloc.o: alldefs.h global.h object.h symtab.h
  12.150 +$(BUILDDIR)/backobj/back/be_alloc.o: execute.h reswords.h be_runtime.h
  12.151 +$(BUILDDIR)/backobj/back/be_alloc.o: be_alloc.h
  12.152  $(BUILDDIR)/backobj/back/be_callc.o: alldefs.h global.h object.h symtab.h
  12.153  $(BUILDDIR)/backobj/back/be_callc.o: execute.h reswords.h be_runtime.h
  12.154  $(BUILDDIR)/backobj/back/be_callc.o: be_machine.h be_alloc.h
  12.155  $(BUILDDIR)/backobj/back/be_coverage.o: be_coverage.h be_machine.h global.h
  12.156  $(BUILDDIR)/backobj/back/be_coverage.o: object.h symtab.h execute.h
  12.157  $(BUILDDIR)/backobj/back/be_debug.o: execute.h global.h object.h symtab.h
  12.158 -$(BUILDDIR)/backobj/back/be_debug.o: be_alloc.h be_debug.h be_execute.h
  12.159 -$(BUILDDIR)/backobj/back/be_debug.o: be_machine.h be_rterror.h be_runtime.h
  12.160 -$(BUILDDIR)/backobj/back/be_debug.o: reswords.h
  12.161 +$(BUILDDIR)/backobj/back/be_debug.o: redef.h reswords.h be_alloc.h be_debug.h
  12.162 +$(BUILDDIR)/backobj/back/be_debug.o: be_execute.h be_machine.h be_rterror.h
  12.163 +$(BUILDDIR)/backobj/back/be_debug.o: be_runtime.h be_symtab.h
  12.164  $(BUILDDIR)/backobj/back/be_decompress.o: alldefs.h global.h object.h
  12.165  $(BUILDDIR)/backobj/back/be_decompress.o: symtab.h execute.h reswords.h
  12.166  $(BUILDDIR)/backobj/back/be_decompress.o: be_alloc.h be_runtime.h
  12.167 @@ -1162,6 +1174,7 @@
  12.168  $(BUILDDIR)/backobj/back/be_execute.o: be_inline.h be_machine.h be_task.h
  12.169  $(BUILDDIR)/backobj/back/be_execute.o: be_rterror.h be_symtab.h be_w.h
  12.170  $(BUILDDIR)/backobj/back/be_execute.o: be_callc.h be_coverage.h be_execute.h
  12.171 +$(BUILDDIR)/backobj/back/be_execute.o: be_debug.h be_memstruct.h
  12.172  $(BUILDDIR)/backobj/back/be_inline.o: alldefs.h global.h object.h symtab.h
  12.173  $(BUILDDIR)/backobj/back/be_inline.o: execute.h reswords.h be_alloc.h
  12.174  $(BUILDDIR)/backobj/back/be_machine.o: global.h object.h symtab.h alldefs.h
  12.175 @@ -1175,9 +1188,12 @@
  12.176  $(BUILDDIR)/backobj/back/be_main.o: execute.h reswords.h be_runtime.h
  12.177  $(BUILDDIR)/backobj/back/be_main.o: be_execute.h be_alloc.h be_rterror.h
  12.178  $(BUILDDIR)/backobj/back/be_main.o: be_w.h
  12.179 -$(BUILDDIR)/backobj/back/be_pcre.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.180 -$(BUILDDIR)/backobj/back/be_pcre.o: be_alloc.h  execute.h reswords.h be_alloc.h
  12.181 -$(BUILDDIR)/backobj/back/be_pcre.o: be_alloc.h  be_runtime.h be_pcre.h pcre/pcre.h
  12.182 +$(BUILDDIR)/backobj/back/be_memstruct.o: execute.h global.h object.h symtab.h
  12.183 +$(BUILDDIR)/backobj/back/be_memstruct.o: reswords.h be_alloc.h be_machine.h
  12.184 +$(BUILDDIR)/backobj/back/be_memstruct.o: be_memstruct.h be_runtime.h
  12.185 +$(BUILDDIR)/backobj/back/be_pcre.o: alldefs.h global.h object.h symtab.h
  12.186 +$(BUILDDIR)/backobj/back/be_pcre.o: execute.h reswords.h be_alloc.h
  12.187 +$(BUILDDIR)/backobj/back/be_pcre.o: be_runtime.h be_pcre.h pcre/pcre.h
  12.188  $(BUILDDIR)/backobj/back/be_pcre.o: be_machine.h
  12.189  $(BUILDDIR)/backobj/back/be_rterror.o: alldefs.h global.h object.h symtab.h
  12.190  $(BUILDDIR)/backobj/back/be_rterror.o: execute.h reswords.h be_rterror.h
  12.191 @@ -1203,23 +1219,23 @@
  12.192  $(BUILDDIR)/backobj/back/be_task.o: reswords.h be_runtime.h be_task.h
  12.193  $(BUILDDIR)/backobj/back/be_task.o: be_alloc.h be_machine.h be_execute.h
  12.194  $(BUILDDIR)/backobj/back/be_task.o: be_symtab.h alldefs.h
  12.195 -$(BUILDDIR)/backobj/back/be_w.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.196 -$(BUILDDIR)/backobj/back/be_w.o: be_alloc.h  execute.h reswords.h be_w.h be_machine.h
  12.197 -$(BUILDDIR)/backobj/back/be_w.o: be_alloc.h  be_runtime.h be_rterror.h be_alloc.h
  12.198 +$(BUILDDIR)/backobj/back/be_w.o: alldefs.h global.h object.h symtab.h
  12.199 +$(BUILDDIR)/backobj/back/be_w.o: execute.h reswords.h be_w.h be_machine.h
  12.200 +$(BUILDDIR)/backobj/back/be_w.o: be_runtime.h be_rterror.h be_alloc.h
  12.201  $(BUILDDIR)/backobj/back/rbt.o: rbt.h
  12.202  
  12.203 -$(BUILDDIR)/libobj/back/be_alloc.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.204 -$(BUILDDIR)/libobj/back/be_alloc.o: be_alloc.h  execute.h reswords.h be_runtime.h
  12.205 -$(BUILDDIR)/libobj/back/be_alloc.o: be_alloc.h  be_alloc.h
  12.206 +$(BUILDDIR)/libobj/back/be_alloc.o: alldefs.h global.h object.h symtab.h
  12.207 +$(BUILDDIR)/libobj/back/be_alloc.o: execute.h reswords.h be_runtime.h
  12.208 +$(BUILDDIR)/libobj/back/be_alloc.o: be_alloc.h
  12.209  $(BUILDDIR)/libobj/back/be_callc.o: alldefs.h global.h object.h symtab.h
  12.210  $(BUILDDIR)/libobj/back/be_callc.o: execute.h reswords.h be_runtime.h
  12.211  $(BUILDDIR)/libobj/back/be_callc.o: be_machine.h be_alloc.h
  12.212  $(BUILDDIR)/libobj/back/be_coverage.o: be_coverage.h be_machine.h global.h
  12.213  $(BUILDDIR)/libobj/back/be_coverage.o: object.h symtab.h execute.h
  12.214  $(BUILDDIR)/libobj/back/be_debug.o: execute.h global.h object.h symtab.h
  12.215 -$(BUILDDIR)/libobj/back/be_debug.o: be_alloc.h be_debug.h be_execute.h
  12.216 -$(BUILDDIR)/libobj/back/be_debug.o: be_machine.h be_rterror.h be_runtime.h
  12.217 -$(BUILDDIR)/libobj/back/be_debug.o: reswords.h
  12.218 +$(BUILDDIR)/libobj/back/be_debug.o: redef.h reswords.h be_alloc.h be_debug.h
  12.219 +$(BUILDDIR)/libobj/back/be_debug.o: be_execute.h be_machine.h be_rterror.h
  12.220 +$(BUILDDIR)/libobj/back/be_debug.o: be_runtime.h be_symtab.h
  12.221  $(BUILDDIR)/libobj/back/be_decompress.o: alldefs.h global.h object.h symtab.h
  12.222  $(BUILDDIR)/libobj/back/be_decompress.o: execute.h reswords.h be_alloc.h
  12.223  $(BUILDDIR)/libobj/back/be_decompress.o: be_runtime.h
  12.224 @@ -1229,6 +1245,7 @@
  12.225  $(BUILDDIR)/libobj/back/be_execute.o: be_inline.h be_machine.h be_task.h
  12.226  $(BUILDDIR)/libobj/back/be_execute.o: be_rterror.h be_symtab.h be_w.h
  12.227  $(BUILDDIR)/libobj/back/be_execute.o: be_callc.h be_coverage.h be_execute.h
  12.228 +$(BUILDDIR)/libobj/back/be_execute.o: be_debug.h be_memstruct.h
  12.229  $(BUILDDIR)/libobj/back/be_inline.o: alldefs.h global.h object.h symtab.h
  12.230  $(BUILDDIR)/libobj/back/be_inline.o: execute.h reswords.h be_alloc.h
  12.231  $(BUILDDIR)/libobj/back/be_machine.o: global.h object.h symtab.h alldefs.h
  12.232 @@ -1242,9 +1259,12 @@
  12.233  $(BUILDDIR)/libobj/back/be_main.o: execute.h reswords.h be_runtime.h
  12.234  $(BUILDDIR)/libobj/back/be_main.o: be_execute.h be_alloc.h be_rterror.h
  12.235  $(BUILDDIR)/libobj/back/be_main.o: be_w.h
  12.236 -$(BUILDDIR)/libobj/back/be_pcre.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.237 -$(BUILDDIR)/libobj/back/be_pcre.o: be_alloc.h  execute.h reswords.h be_alloc.h
  12.238 -$(BUILDDIR)/libobj/back/be_pcre.o: be_alloc.h  be_runtime.h be_pcre.h pcre/pcre.h
  12.239 +$(BUILDDIR)/libobj/back/be_memstruct.o: execute.h global.h object.h symtab.h
  12.240 +$(BUILDDIR)/libobj/back/be_memstruct.o: reswords.h be_alloc.h be_machine.h
  12.241 +$(BUILDDIR)/libobj/back/be_memstruct.o: be_memstruct.h be_runtime.h
  12.242 +$(BUILDDIR)/libobj/back/be_pcre.o: alldefs.h global.h object.h symtab.h
  12.243 +$(BUILDDIR)/libobj/back/be_pcre.o: execute.h reswords.h be_alloc.h
  12.244 +$(BUILDDIR)/libobj/back/be_pcre.o: be_runtime.h be_pcre.h pcre/pcre.h
  12.245  $(BUILDDIR)/libobj/back/be_pcre.o: be_machine.h
  12.246  $(BUILDDIR)/libobj/back/be_rterror.o: alldefs.h global.h object.h symtab.h
  12.247  $(BUILDDIR)/libobj/back/be_rterror.o: execute.h reswords.h be_rterror.h
  12.248 @@ -1270,7 +1290,7 @@
  12.249  $(BUILDDIR)/libobj/back/be_task.o: reswords.h be_runtime.h be_task.h
  12.250  $(BUILDDIR)/libobj/back/be_task.o: be_alloc.h be_machine.h be_execute.h
  12.251  $(BUILDDIR)/libobj/back/be_task.o: be_symtab.h alldefs.h
  12.252 -$(BUILDDIR)/libobj/back/be_w.o: be_alloc.h  alldefs.h global.h object.h symtab.h
  12.253 -$(BUILDDIR)/libobj/back/be_w.o: be_alloc.h  execute.h reswords.h be_w.h be_machine.h
  12.254 -$(BUILDDIR)/libobj/back/be_w.o: be_alloc.h  be_runtime.h be_rterror.h be_alloc.h
  12.255 +$(BUILDDIR)/libobj/back/be_w.o: alldefs.h global.h object.h symtab.h
  12.256 +$(BUILDDIR)/libobj/back/be_w.o: execute.h reswords.h be_w.h be_machine.h
  12.257 +$(BUILDDIR)/libobj/back/be_w.o: be_runtime.h be_rterror.h be_alloc.h
  12.258  $(BUILDDIR)/libobj/back/rbt.o: rbt.h
    13.1 --- a/source/Makefile.wat	Mon Dec 19 23:19:58 2011 -0300
    13.2 +++ b/source/Makefile.wat	Wed Dec 21 16:45:49 2011 -0300
    13.3 @@ -120,6 +120,7 @@
    13.4  	inline.e &
    13.5  	keylist.e &
    13.6  	main.e &
    13.7 +	memstruct.e &
    13.8  	msgtext.e &
    13.9  	mode.e &
   13.10  	opnames.e &
   13.11 @@ -176,6 +177,7 @@
   13.12  	$(BUILDDIR)\$(OBJDIR)\back\be_syncolor.obj &
   13.13  	$(BUILDDIR)\$(OBJDIR)\back\be_task.obj &
   13.14  	$(BUILDDIR)\$(OBJDIR)\back\be_w.obj &
   13.15 +	$(BUILDDIR)\$(OBJDIR)\back\be_memstruct.obj &
   13.16  	$(PCRE_OBJECTS)
   13.17  
   13.18  EU_LIB_OBJECTS = &
   13.19 @@ -800,7 +802,8 @@
   13.20  $(BUILDDIR)\$(OBJDIR)\back\be_symtab.obj : be_symtab.c *.h $(CONFIG) 
   13.21  $(BUILDDIR)\$(OBJDIR)\back\be_w.obj : be_w.c *.h $(CONFIG) 
   13.22  $(BUILDDIR)\$(OBJDIR)\back\be_socket.obj : be_socket.c *.h $(CONFIG)
   13.23 -$(BUILDDIR)\$(OBJDIR)\back\be_pcre.obj : be_pcre.c *.h $(CONFIG) 
   13.24 +$(BUILDDIR)\$(OBJDIR)\back\be_pcre.obj : be_pcre.c *.h $(CONFIG)
   13.25 +$(BUILDDIR)\$(OBJDIR)\back\be_memstruct.obj : be_memstruct.c *.h $(CONFIG) 
   13.26  
   13.27  # end of OBJDIR exists
   13.28  !endif
    14.1 --- a/source/backend.e	Mon Dec 19 23:19:58 2011 -0300
    14.2 +++ b/source/backend.e	Wed Dec 21 16:45:49 2011 -0300
    14.3 @@ -109,35 +109,52 @@
    14.4  			if eentry[S_MODE] = M_NORMAL then
    14.5  				-- vars and routines
    14.6  				
    14.7 -				if find(eentry[S_TOKEN], RTN_TOKS) then
    14.8 -					-- routines only
    14.9 -					if sequence(eentry[S_CODE]) and (get_backend() or eentry[S_OPCODE]=0) then  
   14.10 -						-- routines with code
   14.11 -						e_addr = allocate( sizeof( C_POINTER ) * (length(eentry[S_CODE]) + 1 ) ) -- IL code
   14.12 -						poke_pointer(e_addr, length(eentry[S_CODE]))
   14.13 -						poke_pointer(e_addr + sizeof( C_POINTER ), eentry[S_CODE])
   14.14 -						poke_pointer(addr + ST_CODE, e_addr)
   14.15 +				switch eentry[S_TOKEN] do
   14.16 +					case PROC, FUNC, TYPE then
   14.17 +						-- routines only
   14.18 +						if sequence(eentry[S_CODE]) and (get_backend() or eentry[S_OPCODE]=0) then  
   14.19 +							-- routines with code
   14.20 +							e_addr = allocate( sizeof( C_POINTER ) * (length(eentry[S_CODE]) + 1 ) ) -- IL code
   14.21 +							poke_pointer(e_addr, length(eentry[S_CODE]))
   14.22 +							poke_pointer(e_addr + sizeof( C_POINTER ), eentry[S_CODE])
   14.23 +							poke_pointer(addr + ST_CODE, e_addr)
   14.24 +						
   14.25 +							if sequence(eentry[S_LINETAB]) then
   14.26 +								-- line table
   14.27 +								l_addr = allocate( 4 * length(eentry[S_LINETAB])) 
   14.28 +								poke4(l_addr, eentry[S_LINETAB])
   14.29 +								poke_pointer(addr + ST_LINETAB, l_addr)
   14.30 +							else
   14.31 +								-- pointer to linetable will be NULL
   14.32 +							end if
   14.33 +						end if
   14.34 +						poke4(addr + ST_FIRSTLINE, eentry[S_FIRSTLINE])
   14.35 +						poke_pointer(addr + ST_TEMPS, eentry[S_TEMPS])
   14.36 +						poke4(addr + ST_NUM_ARGS, eentry[S_NUM_ARGS])
   14.37 +						--
   14.38 +						--
   14.39 +						poke4(addr + ST_STACK_SPACE, eentry[S_STACK_SPACE])
   14.40 +						poke_pointer(addr + ST_BLOCK, eentry[S_BLOCK])
   14.41  					
   14.42 -						if sequence(eentry[S_LINETAB]) then
   14.43 -							-- line table
   14.44 -							l_addr = allocate( 4 * length(eentry[S_LINETAB])) 
   14.45 -							poke4(l_addr, eentry[S_LINETAB])
   14.46 -							poke_pointer(addr + ST_LINETAB, l_addr)
   14.47 -						else
   14.48 -							-- pointer to linetable will be NULL
   14.49 +					case MEMSTRUCT, MEMUNION, MEMTYPE, MS_MEMBER, 
   14.50 +							MS_OBJECT, MS_CHAR, MS_SHORT, MS_INT,
   14.51 +							MS_LONG, MS_LONGLONG, 
   14.52 +							MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
   14.53 +						if SIZEOF_MEMSTRUCT_ENTRY = length( eentry ) then
   14.54 +							poke_pointer( addr + ST_MEM_NEXT, eentry[S_MEM_NEXT] )
   14.55 +							poke_pointer( addr + ST_MEM_STRUCT, eentry[S_MEM_STRUCT] )
   14.56 +							poke_pointer( addr + ST_MEM_PARENT, eentry[S_MEM_PARENT] )
   14.57 +							
   14.58 +							poke4( addr + ST_MEM_SIZE, eentry[S_MEM_SIZE] )
   14.59 +							poke4( addr + ST_MEM_OFFSET, eentry[S_MEM_OFFSET] )
   14.60 +							poke4( addr + ST_MEM_ARRAY, eentry[S_MEM_ARRAY] )
   14.61 +							poke( addr + ST_MEM_SIGNED, eentry[S_MEM_SIGNED] )
   14.62 +							poke( addr + ST_MEM_POINTER, eentry[S_MEM_POINTER] )
   14.63  						end if
   14.64 -					end if
   14.65 -					poke4(addr + ST_FIRSTLINE, eentry[S_FIRSTLINE])
   14.66 -					poke_pointer(addr + ST_TEMPS, eentry[S_TEMPS])
   14.67 -					poke4(addr + ST_NUM_ARGS, eentry[S_NUM_ARGS])
   14.68 -					--
   14.69 -					--
   14.70 -					poke4(addr + ST_STACK_SPACE, eentry[S_STACK_SPACE])
   14.71 -					poke_pointer(addr + ST_BLOCK, eentry[S_BLOCK])
   14.72 -					
   14.73 -				else
   14.74 -					poke_pointer(addr + ST_DECLARED_IN, eentry[S_BLOCK] )
   14.75 -				end if
   14.76 +						
   14.77 +					case else
   14.78 +						poke_pointer(addr + ST_DECLARED_IN, eentry[S_BLOCK] )
   14.79 +				end switch
   14.80  				
   14.81  			elsif eentry[S_MODE] = M_BLOCK then
   14.82  				poke_pointer(addr + ST_NEXT_IN_BLOCK, eentry[S_NEXT_IN_BLOCK] )
   14.83 @@ -146,7 +163,8 @@
   14.84  					poke4(addr + ST_FIRST_LINE, eentry[S_FIRST_LINE] )
   14.85  					poke4(addr + ST_LAST_LINE, eentry[S_LAST_LINE] )
   14.86  				end if
   14.87 -				
   14.88 +			
   14.89 +			
   14.90  			elsif (length(eentry) < S_NAME and eentry[S_MODE] = M_CONSTANT) or
   14.91  			(length(eentry) >= S_TOKEN and compare( eentry[S_OBJ], NOVALUE )) then
   14.92  				-- compress constants and literal values in memory
   14.93 @@ -287,6 +305,7 @@
   14.94  			routine_id( "write_coverage_db" ),
   14.95  			routine_id( "DisplayColorLine" ),
   14.96  			external_debugger_ptr,
   14.97 +			trace_lines,
   14.98  			$
   14.99  		})
  14.100  end procedure
    15.1 --- a/source/be_execute.c	Mon Dec 19 23:19:58 2011 -0300
    15.2 +++ b/source/be_execute.c	Wed Dec 21 16:45:49 2011 -0300
    15.3 @@ -73,6 +73,7 @@
    15.4  #include "be_coverage.h"
    15.5  #include "be_execute.h"
    15.6  #include "be_debug.h"
    15.7 +#include "be_memstruct.h"
    15.8  
    15.9  /******************/
   15.10  /* Local defines  */
   15.11 @@ -959,7 +960,7 @@
   15.12  void code_set_pointers(intptr_t **code)
   15.13  /* adjust code pointers, changing some indexes into pointers */
   15.14  {
   15.15 -	intptr_t len, i, j, n, sub, word;
   15.16 +	intptr_t len, i, j, n, sub, word, array;
   15.17  
   15.18  	len = (intptr_t) code[0];
   15.19  	i = 1;
   15.20 @@ -1017,6 +1018,7 @@
   15.21  			case DEREF_TEMP:
   15.22  			case REF_TEMP:
   15.23  			case NOVALUE_TEMP:
   15.24 +			case MEM_TYPE_CHECK:
   15.25  				// one operand
   15.26  				code[i+1] = SET_OPERAND(code[i+1]);
   15.27  				i += 2;
   15.28 @@ -1060,6 +1062,8 @@
   15.29  			case RAND:
   15.30  			case PEEK:
   15.31  			case SIZEOF:
   15.32 +			case ADDRESSOF:
   15.33 +			case OFFSETOF:
   15.34  			case PEEK_STRING:
   15.35  			case PEEKS:
   15.36  			case FLOOR:
   15.37 @@ -1165,13 +1169,31 @@
   15.38  			case TAIL:
   15.39  			case DELETE_ROUTINE:
   15.40  			case RETURNF:
   15.41 +			case MEMSTRUCT_READ:
   15.42  				// 3 operands follow
   15.43  				code[i+1] = SET_OPERAND(code[i+1]);
   15.44  				code[i+2] = SET_OPERAND(code[i+2]);
   15.45  				code[i+3] = SET_OPERAND(code[i+3]);
   15.46  				i += 4;
   15.47  				break;
   15.48 -
   15.49 +			case MEMSTRUCT_PLUS:
   15.50 +			case MEMSTRUCT_MINUS:
   15.51 +			case MEMSTRUCT_DIVIDE:
   15.52 +			case MEMSTRUCT_MULTIPLY:
   15.53 +			case MEMSTRUCT_ASSIGN:
   15.54 +				// 3 operands follow
   15.55 +				code[i+1] = SET_OPERAND(code[i+1]);
   15.56 +				code[i+2] = SET_OPERAND(code[i+2]);
   15.57 +				code[i+3] = SET_OPERAND(code[i+3]);
   15.58 +				i += 5;
   15.59 +				break;
   15.60 +			case PEEK_MEMBER:
   15.61 +				// 3 operands follow
   15.62 +				code[i+1] = SET_OPERAND(code[i+1]);
   15.63 +				code[i+2] = SET_OPERAND(code[i+2]);
   15.64 +				code[i+4] = SET_OPERAND(code[i+4]);
   15.65 +				i += 5;
   15.66 +				break;
   15.67  			case SC1_AND_IF:
   15.68  			case SC1_OR_IF:
   15.69  			case SC1_AND:
   15.70 @@ -1217,6 +1239,8 @@
   15.71  			case INSERT:
   15.72  			case REMOVE:
   15.73  			case OPEN:
   15.74 +			case MEMSTRUCT_ARRAY:
   15.75 +			case PEEK_ARRAY:
   15.76  				// 4 operands follow
   15.77  				code[i+1] = SET_OPERAND(code[i+1]);
   15.78  				code[i+2] = SET_OPERAND(code[i+2]);
   15.79 @@ -1328,7 +1352,25 @@
   15.80  
   15.81  				i += n + 3;
   15.82  				break;
   15.83 -
   15.84 +			case MEMSTRUCT_ACCESS:
   15.85 +			case ARRAY_ACCESS:
   15.86 +				n = (intptr_t)code[i+1] + 1;
   15.87 +				array = (word == ARRAY_ACCESS);
   15.88 +				for (j = 1; j <= n; j++) {
   15.89 +					word = (intptr_t)code[i+1+j];
   15.90 +					code[i+1+j] = SET_OPERAND(word);
   15.91 +				}
   15.92 +				
   15.93 +				word = (intptr_t)code[i+n+2];
   15.94 +				
   15.95 +				code[i+n+2] = SET_OPERAND(word);
   15.96 +				if( array ){
   15.97 +					word = (intptr_t)code[i+n+3];
   15.98 +					code[i+n+3] = SET_OPERAND( word );
   15.99 +				}
  15.100 +				
  15.101 +				i += n + 3 + array;
  15.102 +				break;
  15.103  			default:
  15.104  				RTFatal("UNKNOWN IL OPCODE");
  15.105  		}
  15.106 @@ -1374,6 +1416,15 @@
  15.107  				}
  15.108  				s->u.subp.block = (symtab_ptr)SET_OPERAND( s->u.subp.block );
  15.109  			}
  15.110 +			else if(s->token == MEMSTRUCT ||
  15.111 +					s->token == MEMUNION  ||
  15.112 +					s->token == MS_MEMBER ){
  15.113 +				
  15.114 +				s->u.memstruct.next        = (symtab_ptr)SET_OPERAND( s->u.memstruct.next );
  15.115 +				s->u.memstruct.struct_type = (symtab_ptr)SET_OPERAND( s->u.memstruct.struct_type );
  15.116 +				s->u.memstruct.parent      = (symtab_ptr)SET_OPERAND( s->u.memstruct.parent );
  15.117 +				
  15.118 +			}
  15.119  			else{
  15.120  				s->u.var.declared_in = (symtab_ptr)SET_OPERAND( s->u.var.declared_in );
  15.121  			}
  15.122 @@ -1399,6 +1450,7 @@
  15.123  			// M_TEMP - temps
  15.124  			// leave obj as 0
  15.125  		}
  15.126 +		
  15.127  		s++;
  15.128  	}
  15.129  }
  15.130 @@ -1816,8 +1868,17 @@
  15.131  /* 214 (previous) */
  15.132    &&L_POKE_POINTER, &&L_PEEK_POINTER,
  15.133  /* 215 (previous) */
  15.134 -  &&L_SIZEOF, &&L_STARTLINE_BREAK
  15.135 -  };
  15.136 +  &&L_SIZEOF, &&L_STARTLINE_BREAK,
  15.137 +  
  15.138 +  &&L_MEMSTRUCT_ACCESS, &&L_MEMSTRUCT_ARRAY, &&L_PEEK_MEMBER,
  15.139 +  &&L_MEMSTRUCT_READ, &&L_MEMSTRUCT_ASSIGN, &&L_MEMSTRUCT_PLUS,
  15.140 +  &&L_MEMSTRUCT_MINUS, &&L_MEMSTRUCT_MULTIPLY, &&L_MEMSTRUCT_DIVIDE,
  15.141 +  &&L_MEM_TYPE_CHECK, &&L_ADDRESSOF, &&L_OFFSETOF, &&L_PEEK_ARRAY,
  15.142 +  &&L_ARRAY_ACCESS
  15.143 +/* 232 (previous) */
  15.144 +  
  15.145 +
  15.146 +	};
  15.147  #endif
  15.148  #endif
  15.149  	if (start_pc == NULL) {
  15.150 @@ -2485,7 +2546,7 @@
  15.151  				BREAK;
  15.152  
  15.153  			case L_TYPE_CHECK: /* top has TRUE/FALSE */
  15.154 -			deprintf("case L_TYPE_CHECK:");
  15.155 +				deprintf("case L_TYPE_CHECK:");
  15.156  				/* type check for a user-defined type */
  15.157  				/* this always follows a type-call */
  15.158  				top = *(object_ptr)pc[-1];
  15.159 @@ -2509,6 +2570,29 @@
  15.160  				}
  15.161  				BREAK;
  15.162  
  15.163 +			case L_MEM_TYPE_CHECK:
  15.164 +				deprintf("case L_MEM_TYPE_CHECK:");
  15.165 +				top = *(object_ptr)pc[-1];
  15.166 +				pc += 2;
  15.167 +				if (top == ATOM_1) {
  15.168 +					thread();
  15.169 +					BREAK;  /* usual case L_*/
  15.170 +				}
  15.171 +				else if (IS_ATOM_INT(top)) {
  15.172 +					if (top == ATOM_0)
  15.173 +						RTFatalMemType(pc-4, pc[-1]);
  15.174 +				}
  15.175 +				else if (IS_ATOM_DBL(top)) {
  15.176 +					if (DBL_PTR(top)->dbl == 0.0)
  15.177 +						RTFatalMemType(pc-4, pc[-1]);
  15.178 +				}
  15.179 +				else  {/* sequence */
  15.180 +					type_error_msg =
  15.181 +						"\ntype_check failure (type returned a sequence!), ";
  15.182 +					RTFatalMemType(pc-4, pc[-1]);
  15.183 +				}
  15.184 +				BREAK;
  15.185 +				
  15.186  			case L_NOP2:
  15.187  			deprintf("case L_NOP2:");
  15.188  				thread2();
  15.189 @@ -4528,10 +4612,62 @@
  15.190  				BREAK;
  15.191  
  15.192  			case L_SIZEOF:
  15.193 -				a = *(object_ptr)pc[1]; /* the data type */
  15.194 +				tpc = pc;  // in case of machine exception
  15.195  				top = *(object_ptr)pc[2];
  15.196 -				tpc = pc;  // in case of machine exception
  15.197 -				*(object_ptr)pc[2] = eu_sizeof( a );
  15.198 +				if( ((symtab_ptr)pc[1])->token == MEMSTRUCT ||
  15.199 +					((symtab_ptr)pc[1])->token == MEMUNION ||
  15.200 +					((symtab_ptr)pc[1])->token == MS_MEMBER ||
  15.201 +					((symtab_ptr)pc[1])->token == MEMTYPE
  15.202 +				){
  15.203 +					*(object_ptr)pc[2] = ((symtab_ptr)pc[1])->u.memstruct.size;
  15.204 +				}
  15.205 +				else if( ((symtab_ptr)pc[1])->token == MS_CHAR       ){ *(object_ptr)pc[2] = sizeof( char ); }
  15.206 +				else if( ((symtab_ptr)pc[1])->token == MS_SHORT      ){ *(object_ptr)pc[2] = sizeof( short ); }
  15.207 +				else if( ((symtab_ptr)pc[1])->token == MS_INT        ){ *(object_ptr)pc[2] = sizeof( int ); }
  15.208 +				else if( ((symtab_ptr)pc[1])->token == MS_LONG       ){ *(object_ptr)pc[2] = sizeof( long ); }
  15.209 +				else if( ((symtab_ptr)pc[1])->token == MS_LONGLONG   ){ *(object_ptr)pc[2] = sizeof( long long ); }
  15.210 +				else if( ((symtab_ptr)pc[1])->token == MS_OBJECT     ){ *(object_ptr)pc[2] = sizeof( void * ); }
  15.211 +				else if( ((symtab_ptr)pc[1])->token == MS_FLOAT      ){ *(object_ptr)pc[2] = sizeof( float ); }
  15.212 +				else if( ((symtab_ptr)pc[1])->token == MS_DOUBLE     ){ *(object_ptr)pc[2] = sizeof( double ); }
  15.213 +				else if( ((symtab_ptr)pc[1])->token == MS_LONGDOUBLE ){ *(object_ptr)pc[2] = sizeof( long double ); }
  15.214 +				else if( ((symtab_ptr)pc[1])->token == MS_EUDOUBLE   ){ *(object_ptr)pc[2] = sizeof( eudouble ); }
  15.215 +				else{
  15.216 +					
  15.217 +					a = *(object_ptr)pc[1]; /* the data type */
  15.218 +					*(object_ptr)pc[2] = eu_sizeof( a );
  15.219 +				}
  15.220 +				DeRef( top );
  15.221 +				inc3pc();
  15.222 +				thread();
  15.223 +				BREAK;
  15.224 +			
  15.225 +			case L_ADDRESSOF:
  15.226 +				deprintf("case L_ADDRESSOF:");
  15.227 +				tpc = pc;
  15.228 +				top = *(object_ptr)pc[2];
  15.229 +#if INTPTR_MAX == INT32_MAX
  15.230 +				if ( (uintptr_t)*(object_ptr)pc[1] > (uintptr_t)MAXINT){
  15.231 +					top = NewDouble((eudouble) *(object_ptr)pc[1]);
  15.232 +				}
  15.233 +				else{
  15.234 +					*(object_ptr)pc[2] = *(object_ptr)pc[1];
  15.235 +				}
  15.236 +#else
  15.237 +				// 64-bit ptr always fits in an eu integer
  15.238 +				*(object_ptr)pc[2] = *(object_ptr)pc[1];
  15.239 +#endif
  15.240 +				Ref( *(object_ptr)pc[2] );
  15.241 +				DeRef( top );
  15.242 +				inc3pc();
  15.243 +				thread();
  15.244 +				BREAK;
  15.245 +				
  15.246 +			case L_OFFSETOF:
  15.247 +				deprintf("case L_ADDRESSOF:");
  15.248 +				tpc = pc;
  15.249 +				top = *(object_ptr)pc[2];
  15.250 +				*(object_ptr)pc[2] = ((symtab_ptr)pc[1])->u.memstruct.offset;
  15.251 +				Ref( *(object_ptr)pc[2] );
  15.252  				DeRef( top );
  15.253  				inc3pc();
  15.254  				thread();
  15.255 @@ -5282,6 +5418,112 @@
  15.256  				thread2();
  15.257  				BREAK;
  15.258  
  15.259 +			case L_MEMSTRUCT_ASSIGN:
  15.260 +				deprintf("case L_MEMSTRUCT_ASSIGN");
  15.261 +				tpc = pc;
  15.262 +				
  15.263 +				sym = (symtab_ptr) pc[2];
  15.264 +				if( sym->u.memstruct.pointer && !pc[4] ){
  15.265 +					poke_member( (object_ptr) pc[1], sym, (object_ptr) pc[3], 0 );
  15.266 +				}
  15.267 +				else if( sym->token == MEMSTRUCT ){
  15.268 +					write_member( (object_ptr) pc[1], sym, (object_ptr) pc[3], pc[4] );
  15.269 +				}
  15.270 +				else if( sym->token == MEMUNION ){
  15.271 +					write_union( (object_ptr) pc[1], sym, (object_ptr) pc[3], pc[4] );
  15.272 +				}
  15.273 +				else{
  15.274 +					poke_member( (object_ptr) pc[1], sym, (object_ptr) pc[3], pc[4] );
  15.275 +				}
  15.276 +				thread5();
  15.277 +				BREAK;
  15.278 +				
  15.279 +			case L_MEMSTRUCT_PLUS:
  15.280 +				deprintf("case LMEMSTRUCT_PLUS");
  15.281 +				a = MEMSTRUCT_PLUS;
  15.282 +				goto mem_assign_op;
  15.283 +				
  15.284 +			case L_MEMSTRUCT_MINUS:
  15.285 +				deprintf("case LMEMSTRUCT_MINUS");
  15.286 +				a = MEMSTRUCT_MINUS;
  15.287 +				goto mem_assign_op;
  15.288 +				
  15.289 +			case L_MEMSTRUCT_DIVIDE:
  15.290 +				deprintf("case LMEMSTRUCT_DIVIDE");
  15.291 +				a = MEMSTRUCT_DIVIDE;
  15.292 +				goto mem_assign_op;
  15.293 +				
  15.294 +			case L_MEMSTRUCT_MULTIPLY:
  15.295 +				deprintf("case LMEMSTRUCT_MULTIPLY");
  15.296 +				a = MEMSTRUCT_MULTIPLY;
  15.297 +				
  15.298 +				mem_assign_op:
  15.299 +				tpc = pc;
  15.300 +				memstruct_assignop( a, (object_ptr)pc[1], (symtab_ptr) pc[2], (object_ptr) pc[3], pc[4] );
  15.301 +				thread5();
  15.302 +				BREAK;
  15.303 +				
  15.304 +			case L_MEMSTRUCT_READ:
  15.305 +				deprintf("case L_MEMSTRUCT_READ");
  15.306 +				tpc = pc;
  15.307 +				a = read_memstruct( (object_ptr) pc[1], 0, (symtab_ptr) pc[2] );
  15.308 +				obj_ptr = (object_ptr) pc[3];
  15.309 +				DeRef( *obj_ptr );
  15.310 +				*obj_ptr = a;
  15.311 +				thread4();
  15.312 +				BREAK;
  15.313 +			case L_PEEK_MEMBER:
  15.314 +				deprintf("case L_PEEK_MEMBER");
  15.315 +				tpc = pc;
  15.316 +				a = peek_member( (object_ptr) pc[1], (symtab_ptr) pc[2], -1, 0, pc[3] );
  15.317 +				obj_ptr = (object_ptr) pc[4];
  15.318 +				DeRef( *obj_ptr );
  15.319 +				*obj_ptr = a;
  15.320 +				thread5();
  15.321 +				BREAK;
  15.322 +				
  15.323 +			case L_MEMSTRUCT_ACCESS:
  15.324 +				deprintf("case L_MEMSTRUCT_ACCESS");
  15.325 +				tpc = pc;
  15.326 +				b = pc[1];
  15.327 +				a = memstruct_access( b, (object_ptr) pc[2], (symtab_ptr *) pc + 3 );
  15.328 +				obj_ptr = (object_ptr) pc[b+3];
  15.329 +				DeRef( *obj_ptr );
  15.330 +				*obj_ptr = a;
  15.331 +				pc += b + 4;
  15.332 +				thread();
  15.333 +				BREAK;
  15.334 +			case L_ARRAY_ACCESS:
  15.335 +				deprintf("case L_ARRAY_ACCESS");
  15.336 +				tpc = pc;
  15.337 +				b = pc[1];
  15.338 +				a = array_access( b, (object_ptr) pc[2], (symtab_ptr *) pc + 3,  (symtab_ptr) pc[4]);
  15.339 +				obj_ptr = (object_ptr) pc[b+4];
  15.340 +				DeRef( *obj_ptr );
  15.341 +				*obj_ptr = a;
  15.342 +				pc += b + 5;
  15.343 +				thread();
  15.344 +				BREAK;
  15.345 +			case L_MEMSTRUCT_ARRAY:
  15.346 +				deprintf("case L_MEMSTRUCT_ARRAY");
  15.347 +				tpc = pc;
  15.348 +				a = memstruct_array( (object_ptr)pc[1], (symtab_ptr)pc[2], (object_ptr)pc[3] );
  15.349 +				obj_ptr = (object_ptr) pc[4];
  15.350 +				DeRef( *obj_ptr );
  15.351 +				*obj_ptr = a;
  15.352 +				thread5();
  15.353 +				BREAK;
  15.354 +			case L_PEEK_ARRAY:
  15.355 +				deprintf("case L_PEEK_ARRAY");
  15.356 +				
  15.357 +				tpc = pc;
  15.358 +				a = peek_array( (object_ptr)pc[1], (symtab_ptr)pc[2], (object_ptr)pc[3] );
  15.359 +				obj_ptr = (object_ptr) pc[4];
  15.360 +				DeRef( *obj_ptr );
  15.361 +				*obj_ptr = a;
  15.362 +				
  15.363 +				thread5();
  15.364 +				BREAK;
  15.365  			default:
  15.366  				RTFatal("Unsupported Op Code ");
  15.367  
    16.1 --- a/source/be_machine.c	Mon Dec 19 23:19:58 2011 -0300
    16.2 +++ b/source/be_machine.c	Wed Dec 21 16:45:49 2011 -0300
    16.3 @@ -224,7 +224,7 @@
    16.4  	if (IS_ATOM_INT(x))
    16.5  		return INT_VAL(x);
    16.6  	else if (IS_ATOM(x))
    16.7 -		return (unsigned long)(DBL_PTR(x)->dbl);
    16.8 +		return (uintptr_t)(DBL_PTR(x)->dbl);
    16.9  	else {
   16.10  		RTFatal("%s: an integer was expected, not a sequence", where);
   16.11  	}
   16.12 @@ -1833,7 +1833,7 @@
   16.13  }
   16.14  #endif
   16.15  
   16.16 -static object float_to_atom(object x, int flen)
   16.17 +object float_to_atom(object x, int flen)
   16.18  /* convert a sequence of 4, 8 or 10 bytes in IEEE format to an atom */
   16.19  {
   16.20  	int len, i;
   16.21 @@ -2767,8 +2767,8 @@
   16.22  
   16.23  	x_ptr = SEQ_PTR(x);
   16.24  
   16.25 -	if (IS_ATOM(x) || x_ptr->length != 12)
   16.26 -		RTFatal("BACKEND requires a sequence of length 12");
   16.27 +	if (IS_ATOM(x) || x_ptr->length != 13)
   16.28 +		RTFatal("BACKEND requires a sequence of length 13");
   16.29  
   16.30  	fe.st = (symtab_ptr)     get_pos_int(w, *(x_ptr->base+1));
   16.31  	fe.sl = (struct sline *) get_pos_int(w, *(x_ptr->base+2));
   16.32 @@ -2786,6 +2786,7 @@
   16.33  	
   16.34  	set_debugger( (char*) get_pos_int(w, *(x_ptr->base+12)) );
   16.35  	
   16.36 +	trace_lines = get_pos_int(w, *(x_ptr->base+13));
   16.37  	// This is checked when we try to write coverage to make sure
   16.38  	// we need to output an error message.
   16.39  	in_backend = 1;
    17.1 --- a/source/be_machine.h	Mon Dec 19 23:19:58 2011 -0300
    17.2 +++ b/source/be_machine.h	Wed Dec 21 16:45:49 2011 -0300
    17.3 @@ -82,4 +82,5 @@
    17.4  						   uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
    17.5  						   uintptr_t arg4, uintptr_t arg5, uintptr_t arg6,
    17.6  						   uintptr_t arg7, uintptr_t arg8, uintptr_t arg9);
    17.7 +
    17.8  #endif
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/source/be_memstruct.c	Wed Dec 21 16:45:49 2011 -0300
    18.3 @@ -0,0 +1,666 @@
    18.4 +#include <stdint.h>
    18.5 +#include <stdio.h>
    18.6 +
    18.7 +#include "execute.h"
    18.8 +#include "object.h"
    18.9 +#include "reswords.h"
   18.10 +#include "symtab.h"
   18.11 +#include "be_alloc.h"
   18.12 +#include "be_machine.h"
   18.13 +#include "be_memstruct.h"
   18.14 +#include "be_runtime.h"
   18.15 +
   18.16 +static object read_member( void *pointer, symtab_ptr member_sym );
   18.17 +static object read_memunion( void *pointer, symtab_ptr member_sym );
   18.18 +static int memaccess = 0;
   18.19 +
   18.20 +static object box_int( intptr_t x )
   18.21 +{
   18.22 +	if(x > NOVALUE && x < TOO_BIG_INT)
   18.23 +		return (object) x;
   18.24 +	else
   18.25 +		return (object)NewDouble((eudouble)x);
   18.26 +}	
   18.27 +
   18.28 +object peek_member_value( void *pointer, int data_type, int is_signed, symtab_ptr memsym ){
   18.29 +	switch( data_type ){
   18.30 +		case MS_CHAR:
   18.31 +			if( is_signed ) return *(char*) pointer;
   18.32 +			else            return *(unsigned char*) pointer;
   18.33 +		case MS_SHORT:
   18.34 +			if( is_signed ) return *(short*) pointer;
   18.35 +			else            return *(unsigned short*) pointer;
   18.36 +		case MS_INT:
   18.37 +			if( is_signed ) return box_int( *(int*) pointer );
   18.38 +			else            return box_int( *(unsigned int*) pointer );
   18.39 +		case MS_LONG:
   18.40 +			if( is_signed ) return box_int( *(long*) pointer );
   18.41 +			else            return box_int( *(unsigned long*) pointer );
   18.42 +		case MS_LONGLONG:
   18.43 +			if( is_signed ) return box_int( *(long long int*) pointer );
   18.44 +			else            return box_int( *(unsigned long long int*) pointer );
   18.45 +		case MS_OBJECT:
   18.46 +			if( is_signed ) return box_int( *(intptr_t*) pointer );
   18.47 +			else            return box_int( *(uintptr_t*) pointer );
   18.48 +		case MS_FLOAT:
   18.49 +			return NewDouble( (eudouble) *(float*)pointer );
   18.50 +		case MS_DOUBLE:
   18.51 +			return NewDouble( (eudouble) *(double*)pointer );
   18.52 +		case MS_LONGDOUBLE:
   18.53 +			return NewDouble( (eudouble) *(long double*)pointer );
   18.54 +		default:
   18.55 +			return read_member( pointer, memsym );
   18.56 +	}
   18.57 +}
   18.58 +
   18.59 +object peek_array( object_ptr source, symtab_ptr memsym, object_ptr subscript ){
   18.60 +	uintptr_t pointer;
   18.61 +	int array_index;
   18.62 +	int data_type;
   18.63 +	char is_signed;
   18.64 +	
   18.65 +	pointer = get_pos_int( "memstruct array", *source );
   18.66 +	array_index = get_pos_int( "memstruct array subscript", *subscript );
   18.67 +	pointer += memsym->u.memstruct.offset;
   18.68 +	pointer += memsym->u.memstruct.size / memsym->u.memstruct.array * array_index;
   18.69 +	data_type = memsym->token;
   18.70 +	is_signed = memsym->u.memstruct.is_signed;
   18.71 +	if( pointer == 0 ){
   18.72 +		pointer = get_pos_int( "peek member", *source );
   18.73 +	}
   18.74 +	
   18.75 +	if( memsym->u.memstruct.pointer ){
   18.76 +		data_type = MS_OBJECT;
   18.77 +		is_signed = 0;
   18.78 +	}
   18.79 +	
   18.80 +	return peek_member_value( (void*) pointer, data_type, is_signed, memsym );
   18.81 +}
   18.82 +
   18.83 +object peek_member( object_ptr source, symtab_ptr memsym, int array_index, void *pointer, intptr_t deref_ptr ){
   18.84 +	int data_type;
   18.85 +	char is_signed;
   18.86 +	s1_ptr s;
   18.87 +	int i;
   18.88 +	
   18.89 +	data_type  = memsym->token;
   18.90 +	is_signed = memsym->u.memstruct.is_signed;
   18.91 +	if( pointer == 0 ){
   18.92 +		pointer = (void*) get_pos_int( "peek member", *source );
   18.93 +	}
   18.94 +	
   18.95 +	if( deref_ptr ){
   18.96 +		pointer = *(void**)pointer;
   18.97 +	}
   18.98 +	else if( memsym->u.memstruct.pointer ){
   18.99 +		data_type = MS_OBJECT;
  18.100 +		is_signed = 0;
  18.101 +	}
  18.102 +	else if( array_index != -1 ){
  18.103 +		uintptr_t size = memsym->u.memstruct.size;
  18.104 +		if( memsym->u.memstruct.array ){
  18.105 +			size /= memsym->u.memstruct.array;
  18.106 +		}
  18.107 +		pointer = (void*) (((intptr_t)pointer) + (array_index * size));
  18.108 +	}
  18.109 +	else if( memsym->u.memstruct.array ){
  18.110 +		s = NewS1( memsym->u.memstruct.array );
  18.111 +		for( i = 0; i < memsym->u.memstruct.array; ++i ){
  18.112 +			s->base[i+1] = peek_member( 0, memsym, i, pointer, 0 );
  18.113 +		}
  18.114 +		return MAKE_SEQ( s );
  18.115 +	}
  18.116 +	return peek_member_value( (void*)pointer, data_type, is_signed, memsym );
  18.117 +	
  18.118 +}
  18.119 +
  18.120 +static object read_member( void *pointer, symtab_ptr member_sym ){
  18.121 +	
  18.122 +	int token;
  18.123 +	
  18.124 +	token      = member_sym->token;
  18.125 +	
  18.126 +	if( token >= MS_SIGNED && token <= MS_OBJECT ){
  18.127 +		// simple serialization of primitives
  18.128 +		return peek_member( 0, member_sym, -1, pointer, 0 );
  18.129 +	}
  18.130 +	
  18.131 +	token = member_sym->token;
  18.132 +	while(1){
  18.133 +		// should only go twice through at most
  18.134 +		if( token == MEMSTRUCT ){
  18.135 +			return read_memstruct( 0, pointer, member_sym );
  18.136 +		}
  18.137 +		else if( token == MEMUNION ){
  18.138 +			return read_memunion( pointer, member_sym );
  18.139 +		}
  18.140 +		
  18.141 +		// get the member's actual struct
  18.142 +		token = member_sym->u.memstruct.struct_type->token;
  18.143 +	}
  18.144 +}
  18.145 +
  18.146 +static object read_memunion( void *pointer, symtab_ptr member_sym ){
  18.147 +	s1_ptr s;
  18.148 +	int size;
  18.149 +	int i;
  18.150 +	unsigned char *source;
  18.151 +	object_ptr target;
  18.152 +	
  18.153 +	source = (unsigned char*) pointer;
  18.154 +	size = member_sym->u.memstruct.size;
  18.155 +	s = NewS1( size );
  18.156 +	target = s->base;
  18.157 +	for( i = 1; i <= size; ++i ){
  18.158 +		*(++target) = *(source++);
  18.159 +	}
  18.160 +	return MAKE_SEQ( s );
  18.161 +}
  18.162 +
  18.163 +object read_memstruct( object_ptr source, void *pointer, symtab_ptr member_sym ){
  18.164 +	symtab_ptr sym;
  18.165 +	int size;
  18.166 +	s1_ptr s;
  18.167 +	uintptr_t src_pointer;
  18.168 +	
  18.169 +	if( pointer == 0 ){
  18.170 +		src_pointer = (uintptr_t)get_pos_int( "read memstruct", *source );
  18.171 +	}
  18.172 +	else{
  18.173 +		src_pointer = (uintptr_t) pointer;
  18.174 +	}
  18.175 +	
  18.176 +	if( member_sym->token == MEMUNION ){
  18.177 +		// Unions are handled specially
  18.178 +		int i;
  18.179 +		unsigned char *target;
  18.180 +		
  18.181 +		size = member_sym->u.memstruct.size;
  18.182 +		target = (unsigned char*) src_pointer;
  18.183 +		s = NewS1( size );
  18.184 +		for( i = 1; i <= size; ++i, ++target ){
  18.185 +			s->base[i] = (object) *target;
  18.186 +		}
  18.187 +	}
  18.188 +	else{
  18.189 +		if( member_sym->token != MEMSTRUCT ){
  18.190 +			member_sym = member_sym->u.memstruct.struct_type;
  18.191 +		}
  18.192 +		size = 0;
  18.193 +		for( sym = member_sym->u.memstruct.next; sym != 0; sym = sym->u.memstruct.next ){
  18.194 +			++size;
  18.195 +		}
  18.196 +		s = NewS1( size );
  18.197 +		size = 0;
  18.198 +		for( sym = member_sym->u.memstruct.next; sym != 0; sym = sym->u.memstruct.next ){
  18.199 +			pointer = (void*) (src_pointer + sym->u.memstruct.offset);
  18.200 +			s->base[++size] = peek_member( 0, sym, -1, pointer, 0 );
  18.201 +			
  18.202 +		}
  18.203 +	}
  18.204 +	return MAKE_SEQ( s );
  18.205 +}
  18.206 +void write_member( object_ptr source, symtab_ptr sym, object_ptr val, intptr_t deref_ptr ){
  18.207 +	s1_ptr src;
  18.208 +	int free_src;
  18.209 +	symtab_ptr member;
  18.210 +	int i;
  18.211 +	uintptr_t pointer, src_pointer;
  18.212 +	intptr_t zero;
  18.213 +	#if INTPTR_MAX == INT32_MAX
  18.214 +	struct d dbl;
  18.215 +	object dbl_ptr;
  18.216 +	dbl_ptr = MAKE_DBL( &dbl );
  18.217 +	dbl.ref = -1;
  18.218 +	#endif
  18.219 +	zero = 0;
  18.220 +	
  18.221 +	if( IS_ATOM_INT( *val ) || IS_ATOM( *val ) ){
  18.222 +		src = NewS1( 1 );
  18.223 +		src->base[1] = *val;
  18.224 +		free_src = 1;
  18.225 +	}
  18.226 +	else{
  18.227 +		src = SEQ_PTR( *val );
  18.228 +		free_src = 0;
  18.229 +	}
  18.230 +	
  18.231 +	src_pointer = (uintptr_t)get_pos_int( "write member", *source );
  18.232 +	if( deref_ptr ){
  18.233 +		src_pointer = *(uintptr_t*) src_pointer;
  18.234 +	}
  18.235 +	for( member = sym->u.memstruct.next, i = 1; member && i <= src->length; ++i, member = member->u.memstruct.next ){
  18.236 +		pointer = src_pointer + member->u.memstruct.offset;
  18.237 +		#if INTPTR_MAX == INT32_MAX
  18.238 +		if( IS_ATOM_INT( (intptr_t)pointer ) )
  18.239 +		#endif
  18.240 +			poke_member( (object_ptr)&pointer, member, src->base + i, 0 );
  18.241 +		#if INTPTR_MAX == INT32_MAX
  18.242 +		else{
  18.243 +			dbl.dbl = (eudouble) pointer;
  18.244 +			poke_member( &dbl_ptr, member, src->base + i );
  18.245 +		}
  18.246 +		#endif
  18.247 +		
  18.248 +	}
  18.249 +	
  18.250 +	// Zero out the rest...
  18.251 +	for( ; member; ++i, member = member->u.memstruct.next ){
  18.252 +		pointer = src_pointer + member->u.memstruct.offset;
  18.253 +		#if INTPTR_MAX == INT32_MAX
  18.254 +		if( IS_ATOM_INT( (intptr_t)pointer ) )
  18.255 +		#endif
  18.256 +			poke_member( (object_ptr)&pointer, member, &zero, 0);
  18.257 +		#if INTPTR_MAX == INT32_MAX
  18.258 +		else{
  18.259 +			dbl.dbl = (eudouble) pointer;
  18.260 +			poke_member( &dbl_ptr, member, &zero, 0);
  18.261 +		}
  18.262 +		#endif
  18.263 +	}
  18.264 +	
  18.265 +	if( free_src ){
  18.266 +		EFree( (char*)src );
  18.267 +	}
  18.268 +}
  18.269 +
  18.270 +
  18.271 +void write_union( object_ptr source, symtab_ptr sym, object_ptr val, intptr_t deref_ptr ){
  18.272 +	
  18.273 +	s1_ptr src;
  18.274 +	int free_src;
  18.275 +	int i;
  18.276 +	char *pointer;
  18.277 +	
  18.278 +	if( IS_ATOM_INT( *val ) || IS_ATOM( *val ) ){
  18.279 +		src = NewS1( 1 );
  18.280 +		src->base[1] = *val;
  18.281 +		free_src = 1;
  18.282 +	}
  18.283 +	else{
  18.284 +		src = SEQ_PTR( *val );
  18.285 +		free_src = 0;
  18.286 +	}
  18.287 +	
  18.288 +	pointer = (char*)get_pos_int( "write union", *source );
  18.289 +	if( deref_ptr ){
  18.290 +		pointer = *(char**) pointer;
  18.291 +	}
  18.292 +	for( i = 1; i <= src->length && i <= sym->u.memstruct.size; ++i, ++pointer ){
  18.293 +		*pointer = src->base[i];
  18.294 +	}
  18.295 +	
  18.296 +	// Zero out the rest...
  18.297 +	for( ; i <= sym->u.memstruct.size; ++i, ++pointer ){
  18.298 +		*pointer = 0;
  18.299 +	}
  18.300 +	
  18.301 +	if( free_src ){
  18.302 +		EFree( (char*)src );
  18.303 +	}
  18.304 +}
  18.305 +
  18.306 +static uintptr_t mem_access(  int access_count, object_ptr source, symtab_ptr *access_sym ){
  18.307 +	uintptr_t pointer;
  18.308 +	int i;
  18.309 +	
  18.310 +	pointer = (uintptr_t)get_pos_int( "memstruct access", *source );
  18.311 +	for( i = 0; i < access_count; ++i ){
  18.312 +		pointer += access_sym[i]->u.memstruct.offset;
  18.313 +		if( access_sym[i]->u.memstruct.pointer && (i+1) < access_count ){
  18.314 +			pointer = *(uintptr_t*)pointer;
  18.315 +		}
  18.316 +	}
  18.317 +	return pointer;
  18.318 +}
  18.319 +object memstruct_access( int access_count, object_ptr source, symtab_ptr *access_sym ){
  18.320 +	uintptr_t pointer;
  18.321 +	memaccess = MEMSTRUCT_ACCESS;
  18.322 +	pointer = mem_access( access_count, source, access_sym );
  18.323 +	return box_int( pointer );
  18.324 +}
  18.325 +
  18.326 +object array_access( int access_count, object_ptr source, symtab_ptr *access_sym, symtab_ptr subscript ){
  18.327 +	uintptr_t pointer;
  18.328 +	uintptr_t element_size;
  18.329 +	intptr_t sub_val;
  18.330 +	memaccess = ARRAY_ACCESS;
  18.331 +	pointer = mem_access( access_count, source, access_sym );
  18.332 +	element_size = access_sym[access_count-1]->u.memstruct.size;
  18.333 +	if( access_sym[access_count-1]->u.memstruct.array ){
  18.334 +		element_size /= access_sym[access_count-1]->u.memstruct.array;
  18.335 +	}
  18.336 +	sub_val = get_pos_int( "array access subscript", subscript->obj);
  18.337 +	pointer += sub_val * element_size;
  18.338 +	return box_int( pointer );
  18.339 +}
  18.340 +
  18.341 +object memstruct_array( object_ptr source, symtab_ptr sym, object_ptr subscript ){
  18.342 +	uintptr_t pointer;
  18.343 +	int array_index;
  18.344 +	
  18.345 +	pointer = get_pos_int( "memstruct array", *source );
  18.346 +	array_index = get_pos_int( "memstruct array subscript", *subscript );
  18.347 +	
  18.348 +	pointer += sym->u.memstruct.size * array_index;
  18.349 +	return box_int( pointer );
  18.350 +}
  18.351 +
  18.352 +static void poke_member_value( void *pointer, int data_type, object_ptr val, int is_signed ){
  18.353 +	eudouble d;
  18.354 +	switch( data_type ){
  18.355 +		case MS_CHAR:
  18.356 +			if( is_signed) *(char*)pointer = (char) get_pos_int( "store char data", *val );
  18.357 +			else           *(unsigned char*)pointer = (unsigned char) get_pos_int( "store char data", *val );
  18.358 +			break;
  18.359 +		case MS_SHORT:
  18.360 +			if( is_signed) *(short*)pointer = (short) get_pos_int( "store short data", *val );
  18.361 +			else           *(unsigned short*)pointer = (unsigned short) get_pos_int( "store short data", *val );
  18.362 +			break;
  18.363 +		case MS_INT:
  18.364 +			if( is_signed) *(int*)pointer = (int) get_pos_int( "store int data", *val );
  18.365 +			else           *(unsigned int*)pointer = (unsigned int) get_pos_int( "store int data", *val );
  18.366 +			break;
  18.367 +		case MS_LONG:
  18.368 +			if( is_signed) *(long*)pointer =  (long) get_pos_int( "store long data", *val );
  18.369 +			else           *(unsigned long*)pointer = (unsigned long) get_pos_int( "store long data", *val );
  18.370 +			break;
  18.371 +		case MS_LONGLONG:
  18.372 +			if( is_signed) *(long long*)pointer = (long long) get_pos_int( "store long long int data", *val );
  18.373 +			else           *(unsigned long long*)pointer = (unsigned long long) get_pos_int( "store long long int data", *val );
  18.374 +			break;
  18.375 +		case MS_OBJECT:
  18.376 +			if( is_signed) *(intptr_t*)pointer = (intptr_t) get_pos_int( "store object data", *val );
  18.377 +			else           *(uintptr_t*)pointer = (uintptr_t) get_pos_int( "store object data", *val );
  18.378 +			break;
  18.379 +		case MS_FLOAT:
  18.380 +		case MS_DOUBLE:
  18.381 +		case MS_LONGDOUBLE:
  18.382 +		case MS_EUDOUBLE:
  18.383 +			if( IS_ATOM_INT( *val ) ){
  18.384 +				d = (eudouble) *val;
  18.385 +			}
  18.386 +			else if( IS_ATOM( *val ) ){
  18.387 +				d = DBL_PTR( *val )->dbl;
  18.388 +			}
  18.389 +			else{
  18.390 +				RTFatal( "Trying to store a sequence into a floating point memory location" );
  18.391 +			}
  18.392 +			if( data_type == MS_DOUBLE ){
  18.393 +				*(double*)pointer = d;
  18.394 +			}
  18.395 +			else if( data_type == MS_FLOAT ){
  18.396 +				*(float*)pointer = (float)d;
  18.397 +			}
  18.398 +			if( data_type == MS_EUDOUBLE ){
  18.399 +				*(eudouble*)pointer = d;
  18.400 +			}
  18.401 +			if( data_type == MS_LONGDOUBLE ){
  18.402 +#ifdef __GNUC__
  18.403 +				*(long double*)pointer = d;
  18.404 +#else
  18.405 +				RTFatal( "long doubles not implemented yet for storing into memory on non-gcc compilers" );
  18.406 +#endif
  18.407 +			}
  18.408 +			break;
  18.409 +		default:
  18.410 +			RTFatal( "Error assigning to a memstruct (%s) -- can only assign primitive data members" );
  18.411 +	}
  18.412 +}
  18.413 +
  18.414 +
  18.415 +void poke_member( object_ptr source, symtab_ptr sym, object_ptr val, intptr_t deref_ptr ){
  18.416 +	int data_type;
  18.417 +	int is_signed;
  18.418 +	uintptr_t pointer;
  18.419 +	
  18.420 +	data_type = sym->token;
  18.421 +	while( data_type == MEMTYPE ){
  18.422 +		sym = sym->u.memstruct.parent;
  18.423 +		data_type = sym->token;
  18.424 +	}
  18.425 +	is_signed = sym->u.memstruct.is_signed;
  18.426 +	
  18.427 +	
  18.428 +	
  18.429 +	pointer = get_pos_int( "storing memory data", *source );
  18.430 +	if( deref_ptr ){
  18.431 +		pointer = *(uintptr_t*) pointer;
  18.432 +	}
  18.433 +	else if( sym->u.memstruct.pointer ){
  18.434 +		data_type = MS_OBJECT;
  18.435 +		is_signed = 0;
  18.436 +	}
  18.437 +	
  18.438 +	if( sym->u.memstruct.array ){
  18.439 +		
  18.440 +		
  18.441 +		if( memaccess == ARRAY_ACCESS ){
  18.442 +			poke_member_value( (void*)pointer, data_type, val, is_signed );
  18.443 +		}
  18.444 +		else{
  18.445 +			int i, array_length, max, size;
  18.446 +			s1_ptr v;
  18.447 +			intptr_t zero = 0;
  18.448 +			array_length =  sym->u.memstruct.array;
  18.449 +			size = sym->u.memstruct.size / array_length;
  18.450 +			if( IS_ATOM( *val ) ){
  18.451 +				RTFatal( "expected a sequence to assign to the array" );
  18.452 +			}
  18.453 +			v = SEQ_PTR( *val );
  18.454 +			max = v->length;
  18.455 +			if( max > array_length ){
  18.456 +				max = array_length;
  18.457 +			}
  18.458 +			
  18.459 +			for( i = 0; i < max; ++i ){
  18.460 +				poke_member_value( (void*)pointer, data_type, v->base + i + 1, is_signed );
  18.461 +				pointer += size;
  18.462 +			}
  18.463 +			for( ; i < array_length; ++i ){
  18.464 +				poke_member_value( (void*)pointer, data_type, (object_ptr)&zero, is_signed );
  18.465 +				pointer += size;
  18.466 +			}
  18.467 +		}
  18.468 +	}
  18.469 +	else{
  18.470 +		poke_member_value( (void*)pointer, data_type, val, is_signed );
  18.471 +	}
  18.472 +	
  18.473 +}
  18.474 +
  18.475 +#define CALCULATE( type ) \
  18.476 +		type a, c;\
  18.477 +		a = *( type *) pointer;\
  18.478 +		if( IS_ATOM_INT( *opnd ) ){\
  18.479 +			c = (type) *opnd;\
  18.480 +		}\
  18.481 +		else if( IS_ATOM( *opnd ) ){\
  18.482 +			c = (type) DBL_PTR( *opnd )->dbl;\
  18.483 +		}\
  18.484 +		else{\
  18.485 +			c = (type) get_pos_int( "assign op for object", *opnd );\
  18.486 +		}\
  18.487 +		switch( op ){\
  18.488 +			case MEMSTRUCT_PLUS:\
  18.489 +				a += c;\
  18.490 +				break;\
  18.491 +			case MEMSTRUCT_MINUS:\
  18.492 +				a -= c;\
  18.493 +				break;\
  18.494 +			case MEMSTRUCT_MULTIPLY:\
  18.495 +				a *= c;\
  18.496 +				break;\
  18.497 +			case MEMSTRUCT_DIVIDE:\
  18.498 +				if( !c ){\
  18.499 +					RTFatal("attempt to divide by zero");\
  18.500 +				}\
  18.501 +				a /= c;\
  18.502 +				break;\
  18.503 +			default:\
  18.504 +				RTFatal("illegal assign op");\
  18.505 +		}\
  18.506 +		*(type*) pointer = a;
  18.507 +void ms_char( intptr_t op, void* pointer, object_ptr opnd, char is_signed ){
  18.508 +	
  18.509 +	if( is_signed ){
  18.510 +		CALCULATE( char )
  18.511 +	}
  18.512 +	else{
  18.513 +		CALCULATE( unsigned char )
  18.514 +	}
  18.515 +}
  18.516 +
  18.517 +void ms_short( intptr_t op, void* pointer, object_ptr opnd, char is_signed ){
  18.518 +	
  18.519 +	if( is_signed ){
  18.520 +		CALCULATE( short )
  18.521 +	}
  18.522 +	else{
  18.523 +		CALCULATE( unsigned short )
  18.524 +	}
  18.525 +}
  18.526 +
  18.527 +
  18.528 +void ms_int( intptr_t op, void* pointer, object_ptr opnd, char is_signed ){
  18.529 +	
  18.530 +	if( is_signed ){
  18.531 +		CALCULATE( int )
  18.532 +	}
  18.533 +	else{
  18.534 +		CALCULATE( unsigned int )
  18.535 +	}
  18.536 +}
  18.537 +
  18.538 +void ms_long( intptr_t op, void* pointer, object_ptr opnd, char is_signed ){
  18.539 +	
  18.540 +	if( is_signed ){
  18.541 +		CALCULATE( long )
  18.542 +	}
  18.543 +	else{
  18.544 +		CALCULATE( unsigned long )
  18.545 +	}
  18.546 +}
  18.547 +
  18.548 +
  18.549 +void ms_longlong( intptr_t op, void* pointer, object_ptr opnd, char is_signed ){
  18.550 +	
  18.551 +	if( is_signed ){
  18.552 +		CALCULATE( long long int )
  18.553 +	}
  18.554 +	else{
  18.555 +		CALCULATE( unsigned long long int )
  18.556 +	}
  18.557 +}
  18.558 +
  18.559 +
  18.560 +void ms_object( intptr_t op, void* pointer, object_ptr opnd, char is_signed ){
  18.561 +	
  18.562 +	if( is_signed ){
  18.563 +		CALCULATE( intptr_t )
  18.564 +	}
  18.565 +	else{
  18.566 +		CALCULATE( uintptr_t )
  18.567 +	}
  18.568 +}
  18.569 +
  18.570 +#define FLOAT_CALCULATE( type ) \
  18.571 +	type a, c;\
  18.572 +	if( IS_ATOM_INT(  *opnd ) ){\
  18.573 +		c = (type) *opnd;\
  18.574 +	}\
  18.575 +	else if( IS_ATOM( *opnd ) ){\
  18.576 +		c = (type) DBL_PTR( *opnd )->dbl;\
  18.577 +	}\
  18.578 +	else{\
  18.579 +		RTFatal( "Trying to assign a sequence to ##type data" );\
  18.580 +	}\
  18.581 +	a = *(type*)pointer;\
  18.582 +	switch( op ){\
  18.583 +		case MEMSTRUCT_PLUS:\
  18.584 +			a += c;\
  18.585 +			break;\
  18.586 +		case MEMSTRUCT_MINUS:\
  18.587 +			a -= c;\
  18.588 +			break;\
  18.589 +		case MEMSTRUCT_MULTIPLY:\
  18.590 +			a *= c;\
  18.591 +			break;\
  18.592 +		case MEMSTRUCT_DIVIDE:\
  18.593 +			if( c == (type) 0 ){\
  18.594 +				RTFatal("attempt to divide by zero");\
  18.595 +			}\
  18.596 +			a /= c;\
  18.597 +			break;\
  18.598 +		default:\
  18.599 +			RTFatal("illegal assign op");\
  18.600 +	}\
  18.601 +	*(type*)pointer = a;
  18.602 +	
  18.603 +void ms_float( intptr_t op, void* pointer, object_ptr opnd ){
  18.604 +	FLOAT_CALCULATE( float )
  18.605 +}
  18.606 +
  18.607 +void ms_double( intptr_t op, void* pointer, object_ptr opnd ){
  18.608 +	FLOAT_CALCULATE( double )
  18.609 +}
  18.610 +
  18.611 +void ms_longdouble( intptr_t op, void* pointer, object_ptr opnd ){
  18.612 +#ifdef __GNUC__
  18.613 +	FLOAT_CALCULATE( long double )
  18.614 +#else
  18.615 +	// TODO: convert to doubles and do arithmetic that way? Or more machine code hacks?
  18.616 +	RTFatal( "Extended precision arithmetic not available" );
  18.617 +#endif
  18.618 +}
  18.619 +
  18.620 +void ms_eudouble( intptr_t op, void* pointer, object_ptr opnd ){
  18.621 +	FLOAT_CALCULATE( eudouble )
  18.622 +}
  18.623 +
  18.624 +void memstruct_assignop( intptr_t op, object_ptr source, symtab_ptr sym, object_ptr opnd, intptr_t deref_ptr ){
  18.625 +	void *pointer;
  18.626 +	char is_signed;
  18.627 +	
  18.628 +	pointer   = (void*) get_pos_int( "memstruct assign op", *source );
  18.629 +	if( deref_ptr ){
  18.630 +		pointer = *(void**)pointer;
  18.631 +	}
  18.632 +	is_signed = sym->u.memstruct.is_signed;
  18.633 +	
  18.634 +	switch( sym->token ){
  18.635 +		case MS_CHAR:
  18.636 +			ms_char( op, pointer, opnd, is_signed );
  18.637 +			break;
  18.638 +		case MS_SHORT:
  18.639 +			ms_short( op, pointer, opnd, is_signed );
  18.640 +			break;
  18.641 +		case MS_INT:
  18.642 +			ms_int( op, pointer, opnd, is_signed );
  18.643 +			break;
  18.644 +		case MS_LONG:
  18.645 +			ms_long( op, pointer, opnd, is_signed );
  18.646 +			break;
  18.647 +		case MS_LONGLONG:
  18.648 +			ms_longlong( op, pointer, opnd, is_signed );
  18.649 +			break;
  18.650 +		case MS_OBJECT:
  18.651 +			ms_object( op, pointer, opnd, is_signed );
  18.652 +			break;
  18.653 +		case MS_FLOAT:
  18.654 +			ms_float( op, pointer, opnd );
  18.655 +			break;
  18.656 +		case MS_DOUBLE:
  18.657 +			ms_double( op, pointer, opnd );
  18.658 +			break;
  18.659 +		case MS_LONGDOUBLE:
  18.660 +			ms_longdouble( op, pointer, opnd );
  18.661 +			break;
  18.662 +		case MS_EUDOUBLE:
  18.663 +			ms_eudouble( op, pointer, opnd );
  18.664 +			break;
  18.665 +		default:
  18.666 +			RTFatal( "Target of the assignment must be a primitive data type" );
  18.667 +	}
  18.668 +	
  18.669 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/source/be_memstruct.h	Wed Dec 21 16:45:49 2011 -0300
    19.3 @@ -0,0 +1,22 @@
    19.4 +#ifndef BE_MEMSTRUCT_H_
    19.5 +#define BE_MEMSTRUCT_H_
    19.6 +
    19.7 +#include "execute.h"
    19.8 +#include "object.h"
    19.9 +#include "symtab.h"
   19.10 +
   19.11 +object peek_member( object_ptr source, symtab_ptr memsym, int array_index, void *pointer, intptr_t deref_ptr );
   19.12 +void poke_member( object_ptr source, symtab_ptr sym, object_ptr val, intptr_t deref_ptr );
   19.13 +void write_member( object_ptr source, symtab_ptr sym, object_ptr val, intptr_t deref_ptr );
   19.14 +void write_union( object_ptr source, symtab_ptr sym, object_ptr val, intptr_t deref_ptr );
   19.15 +
   19.16 +object memstruct_array( object_ptr source, symtab_ptr sym, object_ptr subscript );
   19.17 +object peek_array( object_ptr source, symtab_ptr sym, object_ptr subscript );
   19.18 +object memstruct_access( int access_count, object_ptr source, symtab_ptr* access_sym );
   19.19 +object array_access( int access_count, object_ptr source, symtab_ptr* access_sym, symtab_ptr subscript_sym );
   19.20 +object read_memstruct( object_ptr source, void *pointer, symtab_ptr member_sym );
   19.21 +
   19.22 +
   19.23 +void memstruct_assignop( intptr_t op, object_ptr source, symtab_ptr sym, object_ptr opnd, intptr_t deref_ptr );
   19.24 +
   19.25 +#endif
    20.1 --- a/source/be_rterror.c	Mon Dec 19 23:19:58 2011 -0300
    20.2 +++ b/source/be_rterror.c	Wed Dec 21 16:45:49 2011 -0300
    20.3 @@ -93,6 +93,7 @@
    20.4  int file_trace;                 /* log statements to ctrace.out */
    20.5  int trace_enabled = TRUE;       /* flag to disable tracing */
    20.6  char *type_error_msg = "\ntype_check failure, ";   /* changeable message */
    20.7 +char *type_check_sym = NULL;    /* used for memstruct type check errors */
    20.8  
    20.9  /*******************/
   20.10  /* Local variables */
   20.11 @@ -1200,7 +1201,11 @@
   20.12  			}
   20.13  			else {
   20.14  				sf_output(type_error_msg); // test
   20.15 -				snprintf(TPTempBuff, TPTEMP_BUFF_SIZE, "%s is ", s_ptr->name);
   20.16 +				if( type_check_sym == NULL ){
   20.17 +					type_check_sym = s_ptr->name;
   20.18 +				}
   20.19 +				snprintf(TPTempBuff, TPTEMP_BUFF_SIZE, "%s is ", type_check_sym);
   20.20 +				
   20.21  				TPTempBuff[TPTEMP_BUFF_SIZE-1] = 0;
   20.22  				sf_output(TPTempBuff);
   20.23  				if (screen_err_out)
   20.24 @@ -1414,6 +1419,15 @@
   20.25  	va_end(ap);
   20.26  }
   20.27  
   20.28 +void RTFatalMemType(intptr_t *pc, intptr_t member){
   20.29 +	symtab_ptr s_ptr;
   20.30 +	tpc = pc; /* points within the offending assignment/parm setting */
   20.31 +	s_ptr = *(symtab_ptr *)pc;
   20.32 +	type_check_sym = ((symtab_ptr)member)->name;
   20.33 +	CleanUpError(NULL, s_ptr);
   20.34 +
   20.35 +}
   20.36 +
   20.37  void RTFatalType(intptr_t *pc)
   20.38  /* handle type-check failures */
   20.39  /* pc points to variable in instruction stream */ 
    21.1 --- a/source/be_rterror.h	Mon Dec 19 23:19:58 2011 -0300
    21.2 +++ b/source/be_rterror.h	Wed Dec 21 16:45:49 2011 -0300
    21.3 @@ -4,7 +4,13 @@
    21.4  #include <stdint.h>
    21.5  
    21.6  void RTFatalType(intptr_t *pc)
    21.7 -#ifdef EUNIX
    21.8 +#ifdef __GNUC__
    21.9 +__attribute__ ((noreturn))
   21.10 +#endif
   21.11 +;
   21.12 +
   21.13 +void RTFatalMemType(intptr_t *pc, intptr_t member)
   21.14 +#ifdef __GNUC__
   21.15  __attribute__ ((noreturn))
   21.16  #endif
   21.17  ;
   21.18 @@ -38,7 +44,7 @@
   21.19  void NoValue(symtab_ptr s);
   21.20  
   21.21  void CleanUpError_va(char *msg, symtab_ptr s_ptr, va_list ap)
   21.22 -#if defined(EUNIX) || defined(EMINGW)
   21.23 +#ifdef __GNUC__
   21.24   __attribute__ ((noreturn))
   21.25  #else
   21.26  #pragma aux CleanUpError_va aborts;
    22.1 --- a/source/be_runtime.c	Mon Dec 19 23:19:58 2011 -0300
    22.2 +++ b/source/be_runtime.c	Wed Dec 21 16:45:49 2011 -0300
    22.3 @@ -4590,6 +4590,7 @@
    22.4  
    22.5  static int trace_line = 0;
    22.6  static IFILE trace_file;
    22.7 +int trace_lines = 500;
    22.8  
    22.9  static void one_trace_line(char *line)
   22.10  /* write a line to the ctrace.out file */
   22.11 @@ -4615,7 +4616,7 @@
   22.12  		}
   22.13  		if (trace_file != NULL) {
   22.14  			trace_line++;
   22.15 -			if (trace_line >= 500) {
   22.16 +			if (trace_line >= trace_lines) {
   22.17  				one_trace_line("");
   22.18  				one_trace_line("               "); // erase THE END
   22.19  				trace_line = 0;
    23.1 --- a/source/be_runtime.h	Mon Dec 19 23:19:58 2011 -0300
    23.2 +++ b/source/be_runtime.h	Wed Dec 21 16:45:49 2011 -0300
    23.3 @@ -50,6 +50,8 @@
    23.4  
    23.5  extern struct op_info optable[MAX_OPCODE+1];
    23.6  
    23.7 +extern int trace_lines;
    23.8 +
    23.9  void debug_msg(char *msg);
   23.10  
   23.11  void UserCleanup(int status)
    24.1 --- a/source/c_decl.e	Mon Dec 19 23:19:58 2011 -0300
    24.2 +++ b/source/c_decl.e	Wed Dec 21 16:45:49 2011 -0300
    24.3 @@ -1162,7 +1162,8 @@
    24.4  
    24.5  	c_puts("#include \"include/euphoria.h\"\n")
    24.6  
    24.7 -	c_puts("#include \"main-.h\"\n\n")
    24.8 +	c_puts("#include \"main-.h\"\n")
    24.9 +	c_puts("#include \"struct.h\"\n\n")
   24.10  
   24.11  	if not TUNIX then
   24.12  		name = lower(name)  -- for faster compare later
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/source/c_struct.e	Wed Dec 21 16:45:49 2011 -0300
    25.3 @@ -0,0 +1,1086 @@
    25.4 +-- Translator code for dealing with memstructs
    25.5 +
    25.6 +include c_decl.e
    25.7 +include c_out.e
    25.8 +include compile.e
    25.9 +include emit.e
   25.10 +include error.e
   25.11 +include global.e
   25.12 +include reswords.e
   25.13 +include symtab.e
   25.14 +
   25.15 +-- Use this to communicate between ops so we can avoid changing
   25.16 +-- pointers into doubles.
   25.17 +sequence target_is_pointer = {}
   25.18 +
   25.19 +integer memaccess = 0
   25.20 +
   25.21 +function is_pointer( integer pointer )
   25.22 +	return find( pointer, target_is_pointer )
   25.23 +end function
   25.24 +
   25.25 +procedure add_pointer( integer pointer )
   25.26 +	if not is_pointer( pointer ) then
   25.27 +		target_is_pointer &= pointer
   25.28 +	end if
   25.29 +end procedure
   25.30 +
   25.31 +procedure remove_pointer( integer pointer )
   25.32 +	integer px = is_pointer( pointer )
   25.33 +	if px then
   25.34 +		target_is_pointer = remove( target_is_pointer, px )
   25.35 +	end if
   25.36 +end procedure
   25.37 +
   25.38 +
   25.39 +function struct_type( symtab_index sym )
   25.40 +	sym = SymTab[sym][S_MEM_PARENT]
   25.41 +	integer token = sym_token( sym )
   25.42 +	sequence type_name = ""
   25.43 +	if token = MEMSTRUCT then
   25.44 +		type_name &= "struct "
   25.45 +	else
   25.46 +		type_name &= "union "
   25.47 +	end if
   25.48 +	return type_name & decorated_name( sym )
   25.49 +end function
   25.50 +
   25.51 +procedure get_pointer( integer pointer, integer target )
   25.52 +	if not is_pointer( target ) and pointer != target then
   25.53 +		CDeRef( target )
   25.54 +	end if
   25.55 +	
   25.56 +	if is_pointer( pointer ) then
   25.57 +		if target != pointer then
   25.58 +			
   25.59 +			c_stmt( "@ = @;\n", {target, pointer}, target )
   25.60 +		end if
   25.61 +	else
   25.62 +		c_stmt( "_0 = @;\n", pointer )
   25.63 +	
   25.64 +		if not TypeIs( pointer, TYPE_INTEGER ) then
   25.65 +			c_stmt0("if( !IS_ATOM_INT( _0 ) ){\n" )
   25.66 +				c_stmt0("_0 = (intptr_t) DBL_PTR( _0 )->dbl;\n" )
   25.67 +			c_stmt0( "}\n")
   25.68 +		end if
   25.69 +		
   25.70 +		c_stmt( "@ = _0;\n", target, target )
   25.71 +		if target != pointer then
   25.72 +			dispose_temp( pointer, compile:DISCARD_TEMP, REMOVE_FROM_MAP )
   25.73 +		end if
   25.74 +	end if
   25.75 +	
   25.76 +	add_pointer( target )
   25.77 +	SetBBType( target, TYPE_INTEGER, {MININT, MAXINT}, TYPE_INTEGER, 0 )
   25.78 +	
   25.79 +end procedure
   25.80 +
   25.81 +procedure mem_access( integer access_count, integer pointer, integer target )
   25.82 +	get_pointer( pointer, target )
   25.83 +	symtab_index sym = Code[pc+3]
   25.84 +	
   25.85 +	c_stmt( sprintf("@ = (intptr_t) &(((%s*)@)",{struct_type(sym)}), { target, target }, target )
   25.86 +	
   25.87 +	integer 
   25.88 +		first_pc    = pc + 3,
   25.89 +		last_pc     = pc + 2 + access_count,
   25.90 +		was_pointer = 1
   25.91 +	
   25.92 +	for i = first_pc to last_pc do
   25.93 +		if was_pointer then
   25.94 +			c_puts("->")
   25.95 +		else
   25.96 +			c_puts(".")
   25.97 +		end if
   25.98 +		CName( Code[i] )
   25.99 +		was_pointer = SymTab[Code[i]][S_MEM_POINTER]
  25.100 +	end for
  25.101 +	c_puts( ");\n")
  25.102 +end procedure
  25.103 +
  25.104 +export procedure opARRAY_ACCESS()
  25.105 +	integer 
  25.106 +		access_count = Code[pc+1],
  25.107 +		pointer      = Code[pc+2],
  25.108 +		subscript    = Code[pc + 3 + access_count],
  25.109 +		target       = Code[pc + 4 + access_count]
  25.110 +	mem_access( access_count, pointer, target )
  25.111 +	memaccess = ARRAY_ACCESS
  25.112 +	symtab_index sym = Code[pc + 2 + access_count]
  25.113 +	c_stmt( sprintf("@ = (intptr_t) (((%s *)@) + @);\n",{get_data_type(sym)}), { target, target, subscript }, target )
  25.114 +	
  25.115 +	pc += access_count + 5
  25.116 +end procedure
  25.117 +
  25.118 +export procedure opMEMSTRUCT_ACCESS()
  25.119 +	integer 
  25.120 +		access_count = Code[pc+1],
  25.121 +		pointer      = Code[pc+2],
  25.122 +		target       = Code[pc+ 3 + access_count]
  25.123 +	
  25.124 +	mem_access( access_count, pointer, target )
  25.125 +	memaccess = MEMSTRUCT_ACCESS
  25.126 +	pc += access_count + 4
  25.127 +end procedure
  25.128 +
  25.129 +export procedure opMEMSTRUCT_ARRAY()
  25.130 +	integer
  25.131 +		pointer   = Code[pc+1],
  25.132 +		member    = Code[pc+2],
  25.133 +		subscript = Code[pc+3],
  25.134 +		target    = Code[pc+4]
  25.135 +	
  25.136 +	get_pointer( pointer, target )
  25.137 +	sequence type_name
  25.138 +	integer data_type = sym_token( member )
  25.139 +	switch data_type do
  25.140 +		case MS_MEMBER then
  25.141 +			member = SymTab[member][S_MEM_STRUCT]
  25.142 +			fallthru
  25.143 +			
  25.144 +		case MEMSTRUCT, MEMUNION then
  25.145 +			sequence tag
  25.146 +			if data_type = MEMSTRUCT then
  25.147 +				tag = "struct"
  25.148 +			else
  25.149 +				tag = "union"
  25.150 +			end if
  25.151 +			type_name = sprintf( "%s %s", { tag, decorated_name( member ) } )
  25.152 +		case else
  25.153 +			type_name = mem_name( data_type )
  25.154 +	end switch
  25.155 +	
  25.156 +	integer is_integer = TypeIs( subscript, TYPE_INTEGER )
  25.157 +	if not is_integer then
  25.158 +		c_stmt("if( IS_ATOM_INT( @ ) ){\n", subscript )
  25.159 +	end if
  25.160 +	c_stmt("_1 = @;\n", subscript )
  25.161 +	
  25.162 +	if not is_integer then
  25.163 +		c_stmt0( "}\n" )
  25.164 +		c_stmt0( "else{\n" )
  25.165 +		c_stmt(  "_1 = (intptr_t)DBL_PTR( @ )->dbl;\n", subscript )
  25.166 +		c_stmt0( "}\n" )
  25.167 +	end if
  25.168 +	
  25.169 +	dispose_temp( subscript, compile:DISCARD_TEMP, REMOVE_FROM_MAP )
  25.170 +	c_stmt( sprintf( "@ = (intptr_t) &(((%s*)@)[_1]);\n", { type_name } ), { target, target }, target )
  25.171 +	
  25.172 +	pc += 5
  25.173 +end procedure
  25.174 +
  25.175 +function get_tagged_name( symtab_index sym )
  25.176 +	sequence tag
  25.177 +	
  25.178 +	while sym_token( sym ) = MEMTYPE do
  25.179 +		sym = SymTab[S_MEM_PARENT]
  25.180 +	end while
  25.181 +	
  25.182 +	if SymTab[sym][S_TOKEN] = MEMSTRUCT then
  25.183 +		tag = "struct"
  25.184 +	else
  25.185 +		tag = "union"
  25.186 +	end if
  25.187 +	return sprintf( "%s %s", { tag, decorated_name( sym ) } )
  25.188 +end function
  25.189 +
  25.190 +export procedure opPEEK_ARRAY()
  25.191 +	integer
  25.192 +		pointer   = Code[pc+1],
  25.193 +		sym       = Code[pc+2],
  25.194 +		subscript = Code[pc+3],
  25.195 +		target    = Code[pc+4],
  25.196 +		parent    = SymTab[sym][S_MEM_PARENT]
  25.197 +	
  25.198 +	integer data_type  = SymTab[sym][S_TOKEN]
  25.199 +	integer signed     = SymTab[sym][S_MEM_SIGNED]
  25.200 +	integer is_pointer = SymTab[sym][S_MEM_POINTER]
  25.201 +	sequence type_name, struct_name
  25.202 +	
  25.203 +	get_pointer( pointer, target )
  25.204 +	
  25.205 +	struct_name = get_tagged_name( parent )
  25.206 +	
  25.207 +	switch data_type do
  25.208 +		case MS_MEMBER then
  25.209 +			sym = SymTab[sym][S_MEM_STRUCT]
  25.210 +			fallthru
  25.211 +			
  25.212 +		case MEMSTRUCT, MEMUNION then
  25.213 +			type_name = struct_name
  25.214 +		case else
  25.215 +			type_name = mem_name( data_type )
  25.216 +	end switch
  25.217 +	
  25.218 +	sequence array_modifier = "[_1]"
  25.219 +	integer index_is_int = TypeIs( subscript, TYPE_INTEGER)
  25.220 +	if not index_is_int then
  25.221 +		c_stmt("if( !IS_ATOM_INT( @ ) && IS_ATOM( @ ) ){\n", { subscript, subscript}, subscript )
  25.222 +			c_stmt("_1 = (intptr_t)DBL_PTR( @)->dbl;\n", { subscript })
  25.223 +		c_stmt0("}\n")
  25.224 +		c_stmt0("else{\n")
  25.225 +	end if
  25.226 +	c_stmt( "_1 = @;\n", { subscript } )
  25.227 +	if not index_is_int then
  25.228 +		c_stmt0("}\n")
  25.229 +	end if
  25.230 +	
  25.231 +	c_stmt( sprintf("@ = (intptr_t)&((%s *)@)->%s;\n", {struct_name, decorated_name( sym ) }), { target, target } )
  25.232 +	
  25.233 +	peek_member_value( target, sym, data_type, is_pointer, array_modifier, type_name, signed, target )
  25.234 +	remove_pointer( pointer )
  25.235 +	remove_pointer( target )
  25.236 +	
  25.237 +	pc += 5
  25.238 +end procedure
  25.239 +
  25.240 +--**
  25.241 +-- Stores the value pointed to by _0 into the target.  If target is 0,
  25.242 +-- then the caller has already emitted the LHS, and peek_member will
  25.243 +-- only print the RHS.
  25.244 +procedure peek_member( integer pointer, integer sym, integer target, integer array_index = -1, integer deref_ptr = 0 )
  25.245 +	integer data_type  = SymTab[sym][S_TOKEN]
  25.246 +	integer signed     = SymTab[sym][S_MEM_SIGNED]
  25.247 +	integer is_pointer = SymTab[sym][S_MEM_POINTER]
  25.248 +	sequence type_name
  25.249 +	sequence array_modifier = ""
  25.250 +	
  25.251 +	type_name = mem_name( sym_token( sym ) )
  25.252 +	if is_pointer and not deref_ptr then
  25.253 +		data_type = MS_OBJECT
  25.254 +		signed    = 0
  25.255 +		type_name = "object"
  25.256 +	end if
  25.257 +	
  25.258 +	if target then
  25.259 +		CDeRef( target )
  25.260 +	end if
  25.261 +	
  25.262 +	if not signed then
  25.263 +		switch data_type do
  25.264 +			case MS_OBJECT then
  25.265 +				type_name = "uintptr_t"
  25.266 +			case MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
  25.267 +				-- nothing
  25.268 +			case else
  25.269 +				type_name = "unsigned " & type_name
  25.270 +		end switch
  25.271 +	end if
  25.272 +	
  25.273 +	if data_type = MS_MEMBER then
  25.274 +		data_type = sym_token( SymTab[sym][S_MEM_STRUCT] )
  25.275 +	end if
  25.276 +	
  25.277 +	if array_index != -1 then
  25.278 +		array_modifier = sprintf("[%d]", array_index )
  25.279 +	elsif SymTab[sym][S_MEM_ARRAY] and memaccess = MEMSTRUCT_ACCESS then
  25.280 +	
  25.281 +		c_stmt0( sprintf( "_2 = NewS1( %d );\n", SymTab[sym][S_MEM_ARRAY] ) )
  25.282 +		for i = 1 to SymTab[sym][S_MEM_ARRAY] do
  25.283 +			peek_member( pointer, sym, 0, i-1 )
  25.284 +			c_stmt0( sprintf( "((s1_ptr)_2)->base[%d] = _0;\n", i ) )
  25.285 +		end for
  25.286 +		if target then
  25.287 +			c_stmt( "@ = MAKE_SEQ( _2 );\n", target )
  25.288 +		else
  25.289 +			c_stmt0( "_0 = MAKE_SEQ( _2 );\n" )
  25.290 +		end if
  25.291 +		return
  25.292 +		
  25.293 +	end if
  25.294 +	
  25.295 +	if deref_ptr then
  25.296 +		c_stmt( "@ = *(intptr_t*)@;\n", { pointer, pointer }, pointer )
  25.297 +	end if
  25.298 +	peek_member_value( pointer, sym, data_type, is_pointer, array_modifier, type_name, signed, target )
  25.299 +	memaccess = MEMSTRUCT_ACCESS
  25.300 +end procedure
  25.301 +
  25.302 +procedure peek_member_value( integer pointer, integer sym, integer data_type,
  25.303 +							 integer is_pointer, sequence array_modifier,
  25.304 +							 sequence type_name, integer signed, integer target )
  25.305 +	integer parent
  25.306 +	switch data_type do
  25.307 +		case MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
  25.308 +			sequence indirect_float = ""
  25.309 +			if not length( array_modifier ) then
  25.310 +				indirect_float = "*"
  25.311 +			end if
  25.312 +			if target then
  25.313 +				c_stmt( sprintf("@ = NewDouble( (eudouble) %s((%s*)@)%s );\n",
  25.314 +								{indirect_float, type_name, array_modifier}),
  25.315 +								{ target, pointer }, target )
  25.316 +			else
  25.317 +				parent =  SymTab[sym][S_MEM_PARENT]
  25.318 +				sequence parent_struct
  25.319 +				switch sym_token( parent ) do
  25.320 +					case MEMSTRUCT, MEMUNION, QUALIFIED_MEMSTRUCT, QUALIFIED_MEMUNION then
  25.321 +						parent_struct = decorated_name( parent )
  25.322 +					case else
  25.323 +						parent_struct = decorated_name( SymTab[parent][S_MEM_STRUCT] )
  25.324 +				end switch
  25.325 +				
  25.326 +				c_stmt( 
  25.327 +						sprintf("_0 = NewDouble( (eudouble) %s(((%s*)@)%s) );\n", 
  25.328 +							{
  25.329 +								indirect_float,
  25.330 +								type_name,
  25.331 +								array_modifier
  25.332 +							}
  25.333 +						), 
  25.334 +						{ pointer }
  25.335 +					)
  25.336 +				
  25.337 +			end if
  25.338 +		
  25.339 +		case MEMUNION then
  25.340 +			read_memunion( pointer, sym )
  25.341 +			if target then
  25.342 +				c_stmt( "@ = _0;\n", target, target )
  25.343 +			end if
  25.344 +		case MEMSTRUCT then
  25.345 +			read_memstruct( pointer, sym )
  25.346 +			if target then
  25.347 +				c_stmt( "@ = _0;\n", target, target )
  25.348 +			end if
  25.349 +		case else
  25.350 +			sequence indirect_read = ""
  25.351 +			if not length( array_modifier ) then
  25.352 +				indirect_read = "*"
  25.353 +			end if
  25.354 +			if target then
  25.355 +				c_stmt( sprintf("@ = %s((%s*)@)%s;\n", {indirect_read, type_name, array_modifier}), { target, pointer }, target )
  25.356 +			else
  25.357 +				c_stmt( 
  25.358 +						sprintf("_0 = %s((%s*)@)%s;\n", 
  25.359 +							{
  25.360 +								indirect_read,
  25.361 +								type_name,
  25.362 +								array_modifier
  25.363 +							}
  25.364 +						),  { pointer } )
  25.365 +				
  25.366 +				if data_type != MS_CHAR and data_type != MS_SHORT label "convert" then
  25.367 +					ifdef E64 then
  25.368 +						ifdef WINDOWS then
  25.369 +							if data_type = MS_LONG then
  25.370 +								-- a long is still 32-bits on 64-bit windows
  25.371 +								break "convert"
  25.372 +							end if
  25.373 +						end ifdef
  25.374 +						
  25.375 +						if data_type = MS_INT /*or is_pointer*/ then
  25.376 +							-- these are always safe under 64-bit arch
  25.377 +							break "convert"
  25.378 +						end if
  25.379 +						
  25.380 +					end ifdef
  25.381 +					c_stmt0("if ((uintptr_t)_0 > (uintptr_t)MAXINT){\n" )
  25.382 +					if signed then
  25.383 +						c_stmt0("_0 = NewDouble((eudouble)(intptr_t)_0);\n" )
  25.384 +					else
  25.385 +						c_stmt0("_0 = NewDouble((eudouble)(uintptr_t)_0);\n" )
  25.386 +					end if
  25.387 +					c_stmt0("}\n")
  25.388 +				end if
  25.389 +			end if
  25.390 +			
  25.391 +	end switch
  25.392 +end procedure
  25.393 +
  25.394 +export procedure opPEEK_MEMBER()
  25.395 +	integer
  25.396 +		pointer = Code[pc+1],
  25.397 +		member  = Code[pc+2],
  25.398 +		deref   = Code[pc+3],
  25.399 +		target  = Code[pc+4]
  25.400 +	
  25.401 +	get_pointer( pointer, target )
  25.402 +	
  25.403 +	peek_member( pointer, member, target, /* array index */, deref )
  25.404 +	
  25.405 +	remove_pointer( pointer )
  25.406 +	remove_pointer( target )
  25.407 +	pc += 5
  25.408 +end procedure
  25.409 +
  25.410 +integer serialize_level = 0
  25.411 +
  25.412 +--**
  25.413 +-- Serialize the specified memstruct into a sequence and store the object in _2.
  25.414 +procedure read_memstruct( integer pointer, symtab_pointer member_sym )
  25.415 +	
  25.416 +	if sym_token( member_sym ) != MEMSTRUCT then
  25.417 +		-- we want to walk the actual struct
  25.418 +		member_sym = SymTab[member_sym][S_MEM_STRUCT]
  25.419 +	end if
  25.420 +	
  25.421 +	
  25.422 +	integer size = 0
  25.423 +	integer size_sym = member_sym
  25.424 +	while size_sym with entry do
  25.425 +		size += 1
  25.426 +	entry
  25.427 +		size_sym = SymTab[size_sym][S_MEM_NEXT]
  25.428 +	end while
  25.429 +	
  25.430 +	serialize_level += 1
  25.431 +	c_stmt0( "{\n" )
  25.432 +	c_stmt0( sprintf("s1_ptr serialize_%d;\n", serialize_level ) )
  25.433 +	c_stmt0( sprintf("serialize_%d = NewS1( %d );\n", { serialize_level, size } ) )
  25.434 +	c_stmt( "_1 = @;\n", pointer )
  25.435 +	integer ix = 0
  25.436 +	sequence parent = get_tagged_name( member_sym )
  25.437 +	while member_sym with entry do
  25.438 +		ifdef DEBUG then
  25.439 +			c_stmt0( sprintf("// peek member: %s.%s\n", {decorated_name( SymTab[member_sym][S_MEM_PARENT] ),  decorated_name( member_sym ) }))
  25.440 +		end ifdef
  25.441 +		c_stmt( sprintf("@ = (intptr_t) & ((%s*)_1)->%s;\n",  { parent, decorated_name( member_sym )}), pointer )
  25.442 +		peek_member( pointer, member_sym, 0  )
  25.443 +		ix += 1
  25.444 +		c_stmt0( sprintf( "serialize_%d->base[%d] = _0;\n", { serialize_level, ix } ) )
  25.445 +		
  25.446 +	entry
  25.447 +		member_sym = SymTab[member_sym][S_MEM_NEXT]
  25.448 +	end while
  25.449 +	
  25.450 +	c_stmt0( sprintf( "_0 = MAKE_SEQ( serialize_%d );\n", serialize_level ) )
  25.451 +	c_stmt( "@ = _1;\n", pointer, pointer )
  25.452 +	c_stmt0( "}\n" )
  25.453 +	serialize_level -= 1
  25.454 +end procedure
  25.455 +
  25.456 +--**
  25.457 +-- Serialize the specified memunion into a sequence and store the object in _0.
  25.458 +-- Also uses _1.
  25.459 +procedure read_memunion( integer pointer, symtab_pointer member_sym )
  25.460 +	integer size = SymTab[member_sym][S_MEM_SIZE]
  25.461 +	
  25.462 +	c_stmt0( sprintf( "_1 = NewS1( %d );\n", size ) )
  25.463 +	
  25.464 +	for i = 1 to size do
  25.465 +		c_stmt( sprintf( "((s1_ptr)_1)->base[%d] = ((unsigned char *) @)[%d];\n", {i, i-1} ), pointer )
  25.466 +	end for
  25.467 +	c_stmt0( "_0 = MAKE_SEQ( _1 );\n" )
  25.468 +end procedure
  25.469 +
  25.470 +function read_member( integer pointer, integer sym  )
  25.471 +	symtab_pointer member_sym = sym
  25.472 +	integer tid = sym_token( sym )
  25.473 +	if tid >= MS_SIGNED and tid <= MS_OBJECT then
  25.474 +		-- simple serialization of primitives...
  25.475 +		peek_member( pointer, sym, 0 )
  25.476 +		return 0
  25.477 +	end if
  25.478 +	
  25.479 +	integer member_token = sym_token( member_sym )
  25.480 +	if member_token = MEMSTRUCT then
  25.481 +		read_memstruct( pointer, member_sym )
  25.482 +	
  25.483 +	elsif member_token = MEMUNION then
  25.484 +		read_memunion( pointer, member_sym  )
  25.485 +		
  25.486 +	else
  25.487 +		member_token = SymTab[SymTab[member_sym][S_MEM_STRUCT]][S_TOKEN]
  25.488 +		if member_token = MEMSTRUCT then
  25.489 +			read_memstruct( pointer, member_sym )
  25.490 +			
  25.491 +		elsif member_token = MEMUNION then
  25.492 +			read_memunion( pointer, member_sym )
  25.493 +		else
  25.494 +			InternalErr( "Cannot serialize a: [1]", { LexName( member_token )  })
  25.495 +		end if
  25.496 +	end if
  25.497 +	return 1
  25.498 +end function
  25.499 +
  25.500 +export procedure opMEMSTRUCT_READ()
  25.501 +	integer
  25.502 +		pointer = Code[pc+1],
  25.503 +		member  = Code[pc+2],
  25.504 +		target  = Code[pc+3]
  25.505 +	
  25.506 +	CDeRef( target )
  25.507 +	get_pointer( pointer, target )
  25.508 +	
  25.509 +	integer is_sequence = read_member( target, member )
  25.510 +	
  25.511 +	c_stmt( "@ = _0;\n", target, target )
  25.512 +	if is_sequence then
  25.513 +		SetBBType( target, TYPE_SEQUENCE, {MININT, MAXINT}, TYPE_OBJECT, 0 )
  25.514 +	else
  25.515 +		SetBBType( target, TYPE_ATOM, {MININT, MAXINT}, TYPE_OBJECT, 0 )
  25.516 +	end if
  25.517 +	remove_pointer( pointer )
  25.518 +	
  25.519 +	pc += 4
  25.520 +end procedure
  25.521 +
  25.522 +procedure poke_member_value( symtab_index target, symtab_index val, integer data_type, sequence type_name, integer array_index )
  25.523 +	if array_index != -1 then
  25.524 +		c_stmt( sprintf( "_1 = SEQ_PTR( @ )->base[%d];\n", array_index + 1), val )
  25.525 +	end if
  25.526 +	switch data_type do
  25.527 +		case MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
  25.528 +			integer is_double = TypeIs( val, TYPE_DOUBLE )
  25.529 +			if not is_double then
  25.530 +				
  25.531 +				if array_index = -1 then
  25.532 +					c_stmt( "if( IS_ATOM_INT( @ ) ){\n", val )
  25.533 +					c_stmt( sprintf("*(%s*)@ = (%s)@;\n", {type_name, type_name}), { target, val }, target )
  25.534 +				else
  25.535 +					c_stmt0( "if( IS_ATOM_INT( _1 ) ){\n" )
  25.536 +					c_stmt( sprintf("((%s*)@)[%d] = (%s)_1;\n", {type_name, array_index, type_name}), { target }, target )
  25.537 +				end if
  25.538 +				c_stmt0( "}\n" )
  25.539 +				c_stmt0( "else{\n")
  25.540 +			end if
  25.541 +			if array_index = -1 then
  25.542 +				c_stmt( sprintf("*(%s*)@ = (%s)DBL_PTR( @ )->dbl;\n", {type_name, type_name}), { target, val }, target )
  25.543 +			else
  25.544 +				c_stmt( sprintf("((%s*)@)[%d] = (%s)DBL_PTR( _1 )->dbl;\n", {type_name, array_index, type_name}), { target }, target )
  25.545 +			end if
  25.546 +			
  25.547 +			if not is_double then
  25.548 +				c_stmt0( "}\n")
  25.549 +			end if
  25.550 +		
  25.551 +		case MEMUNION then
  25.552 +			-- TODO
  25.553 +		case MEMSTRUCT then
  25.554 +			-- TODO
  25.555 +		case else
  25.556 +			integer is_integer = TypeIs( val, TYPE_INTEGER )
  25.557 +			if not is_integer then
  25.558 +				if array_index = -1 then
  25.559 +					c_stmt( "if( IS_ATOM_INT( @ ) ){\n", val )
  25.560 +				else
  25.561 +					c_stmt0( "if( IS_ATOM_INT( _1 ) ){\n" )
  25.562 +				end if
  25.563 +			end if
  25.564 +			
  25.565 +			if array_index = -1 then
  25.566 +				c_stmt( sprintf("*(%s*) @ = (%s) @;\n", {type_name, type_name}), {target, val}, target )
  25.567 +			else
  25.568 +				c_stmt( sprintf("((%s*) @)[%d] = (%s) _1;\n", {type_name, array_index, type_name}), {target }, target )
  25.569 +			end if
  25.570 +			
  25.571 +			if not is_integer then
  25.572 +				c_stmt0("}\n" )
  25.573 +				c_stmt0( "else{\n")
  25.574 +				if array_index = -1 then
  25.575 +					c_stmt( sprintf("*(%s*) @ = (%s) DBL_PTR( @ )->dbl;\n", {type_name, type_name}), {target, val}, target )
  25.576 +				else
  25.577 +					c_stmt( sprintf("((%s*) @)[%d] = (%s) DBL_PTR( _1 )->dbl;\n", {type_name, array_index, type_name}), {target }, target )
  25.578 +				end if
  25.579 +				c_stmt0("}\n" )
  25.580 +			end if
  25.581 +	end switch
  25.582 +end procedure
  25.583 +
  25.584 +--**
  25.585 +-- Stores the value into the memory pointed to by _0
  25.586 +procedure poke_member( symtab_index target, symtab_index member, symtab_index val, integer deref_ptr )
  25.587 +	integer data_type = SymTab[member][S_TOKEN]
  25.588 +	integer signed    = SymTab[member][S_MEM_SIGNED]
  25.589 +	
  25.590 +	sequence type_name = mem_name( sym_token( member ) )
  25.591 +	
  25.592 +	if SymTab[member][S_MEM_POINTER] and not deref_ptr then
  25.593 +		data_type = MS_OBJECT
  25.594 +		signed    = 0
  25.595 +		type_name = "object"
  25.596 +	end if
  25.597 +	
  25.598 +	if not signed then
  25.599 +		switch data_type do
  25.600 +			case MS_OBJECT then
  25.601 +				type_name = "uintptr_t"
  25.602 +			case MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
  25.603 +			case else
  25.604 +				type_name = "unsigned " & type_name
  25.605 +		end switch
  25.606 +	end if
  25.607 +	
  25.608 +	if SymTab[member][S_MEM_ARRAY] and memaccess = MEMSTRUCT_ACCESS then
  25.609 +		c_stmt("switch( SEQ_PTR( @ )->length ){\n", val )
  25.610 +		c_stmt0("default:\n")
  25.611 +		for i = SymTab[member][S_MEM_ARRAY] to 1 by -1 do
  25.612 +			c_stmt0( sprintf("case %d:\n", i ) )
  25.613 +			poke_member_value( target, val, data_type, type_name, i-1 )
  25.614 +		end for
  25.615 +		c_stmt0("case 0: ;\n")
  25.616 +		c_stmt0("}\n")
  25.617 +	else
  25.618 +		poke_member_value( target, val, data_type, type_name, -1 )
  25.619 +	end if
  25.620 +	memaccess = MEMSTRUCT_ACCESS
  25.621 +end procedure
  25.622 +
  25.623 +procedure poke_memstruct( symtab_index target, symtab_index struct_sym, symtab_index member, integer subscript )
  25.624 +	integer data_type = SymTab[member][S_TOKEN]
  25.625 +	integer signed    = SymTab[member][S_MEM_SIGNED]
  25.626 +	
  25.627 +	sequence type_name
  25.628 +	
  25.629 +	if SymTab[member][S_MEM_POINTER] then
  25.630 +		data_type = MS_OBJECT
  25.631 +		signed    = 0
  25.632 +		type_name = "object"
  25.633 +	else
  25.634 +		type_name = mem_name( sym_token( member ) )
  25.635 +	end if
  25.636 +	
  25.637 +	sequence rhs
  25.638 +	if subscript then
  25.639 +		rhs = sprintf( "src_s1->base[%d]", subscript )
  25.640 +	else
  25.641 +		rhs = "0"
  25.642 +	end if
  25.643 +	
  25.644 +	switch data_type do
  25.645 +		case MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
  25.646 +			
  25.647 +			if subscript then
  25.648 +				c_stmt0( sprintf( "if( IS_ATOM_INT( %s ) ){\n", { rhs } ) )
  25.649 +			end if
  25.650 +				c_stmt( sprintf("((struct %s*)@)->%s = (%s)%s;\n",
  25.651 +								{ decorated_name( struct_sym), decorated_name( member) ,type_name, rhs}), { target }, target )
  25.652 +			if subscript then
  25.653 +				c_stmt0( "}\n" )
  25.654 +				c_stmt0( "else{\n")
  25.655 +					c_stmt( sprintf("((struct %s*)@)->%s = (%s)DBL_PTR( %s )->dbl;\n",
  25.656 +								{decorated_name( struct_sym), decorated_name( member) , type_name, rhs}), { target }, target )
  25.657 +				c_stmt0( "}\n")
  25.658 +			end if
  25.659 +		case MEMUNION then
  25.660 +			-- TODO
  25.661 +		case MEMSTRUCT then
  25.662 +			-- TODO
  25.663 +		case else
  25.664 +			if not signed then
  25.665 +				if data_type = MS_OBJECT then
  25.666 +					type_name = "uintptr_t"
  25.667 +				else
  25.668 +					type_name = "unsigned " & type_name
  25.669 +				end if
  25.670 +			end if
  25.671 +			if subscript then
  25.672 +				c_stmt0( sprintf("if( IS_ATOM_INT( %s ) ){\n", {rhs} ) )
  25.673 +			end if
  25.674 +				c_stmt( sprintf("((struct %s*) @)->%s = (%s) %s;\n",
  25.675 +							{decorated_name( struct_sym), decorated_name( member) , type_name, rhs}), {target}, target )
  25.676 +			if subscript then
  25.677 +				c_stmt0("}\n" )
  25.678 +				c_stmt0( "else{\n")
  25.679 +				c_stmt( sprintf("((struct %s*) @)->%s = (%s) DBL_PTR( %s )->dbl;\n",
  25.680 +								{decorated_name( struct_sym), decorated_name( member) , type_name, rhs}), {target}, target )
  25.681 +				c_stmt0("}\n" )
  25.682 +			end if
  25.683 +			
  25.684 +	end switch
  25.685 +end procedure
  25.686 +
  25.687 +function set_up_assign_sequence( integer source_val )
  25.688 +	
  25.689 +	atom seqlen
  25.690 +	integer is_sequence = TypeIs( source_val, TYPE_SEQUENCE )
  25.691 +	
  25.692 +	
  25.693 +	c_stmt0("s1_ptr src_s1;\n")	
  25.694 +	
  25.695 +	if is_sequence then
  25.696 +		-- see if we know how big the sequence is:
  25.697 +		seqlen = SeqLen( source_val )
  25.698 +		c_stmt("src_s1 = SEQ_PTR( @ );\n", source_val )
  25.699 +	else
  25.700 +		c_stmt0("int free_src;\n" )
  25.701 +		-- might be an atom
  25.702 +		seqlen = NOVALUE
  25.703 +		c_stmt("if( IS_ATOM( @ ) || IS_ATOM_INT( @ ) ){\n", { source_val, source_val } )
  25.704 +			c_stmt0("free_src = 1;\n")
  25.705 +			c_stmt0("src_s1 = NewS1( 1 );\n" )
  25.706 +			c_stmt("src_s1->base[1] = @;\n", source_val )
  25.707 +		c_stmt0("}\n")
  25.708 +		c_stmt0("else {\n" )
  25.709 +			c_stmt0("free_src = 0;\n")
  25.710 +			c_stmt("src_s1 = SEQ_PTR( @ );\n", source_val )
  25.711 +		c_stmt0("}\n")
  25.712 +	end if
  25.713 +	return is_sequence & seqlen
  25.714 +end function
  25.715 +
  25.716 +procedure assign_memstruct( integer pointer, integer struct_sym, integer source_val )
  25.717 +	-- use a private block
  25.718 +	c_stmt0("{\n")
  25.719 +	sequence seq_len     = set_up_assign_sequence( source_val )
  25.720 +	integer  is_sequence = seq_len[1]
  25.721 +	atom     seqlen      = seq_len[2]
  25.722 +	
  25.723 +	integer members = 0
  25.724 +	integer member_sym = struct_sym
  25.725 +	sequence member_list = {}
  25.726 +	while member_sym with entry do
  25.727 +		members += 1
  25.728 +		member_list &= member_sym
  25.729 +	entry
  25.730 +		member_sym = SymTab[member_sym][S_MEM_NEXT]
  25.731 +	end while
  25.732 +	
  25.733 +	if seqlen != NOVALUE then
  25.734 +		integer ix = 1
  25.735 +		member_sym = SymTab[struct_sym][S_MEM_NEXT]
  25.736 +		while ix <= seqlen and member_sym do
  25.737 +			poke_memstruct( pointer, struct_sym, member_sym, ix )
  25.738 +			ix += 1
  25.739 +			member_sym = SymTab[member_sym][S_MEM_NEXT]
  25.740 +		end while
  25.741 +		
  25.742 +		while member_sym do
  25.743 +			-- zero out the rest
  25.744 +			poke_memstruct( pointer, struct_sym, member_sym, 0 )
  25.745 +			member_sym = SymTab[member_sym][S_MEM_NEXT]
  25.746 +		end while
  25.747 +	else
  25.748 +		-- unknown length:
  25.749 +		c_stmt0( "switch( src_s1->length ){\n" )
  25.750 +			-- the sequence is bigger than the struct:
  25.751 +			c_stmt0("default:\n")
  25.752 +			for i = members to 1 by -1 do
  25.753 +				c_stmt0( sprintf( "case %d:\n", i ) )
  25.754 +				poke_memstruct( pointer, struct_sym, member_list[i], i )
  25.755 +			end for
  25.756 +			c_stmt0( "case 0: break;\n" )
  25.757 +		c_stmt0("}\n")
  25.758 +		
  25.759 +		c_stmt0( "switch( src_s1->length + 1 ){\n" )
  25.760 +			for i = 0 to members do
  25.761 +				c_stmt0( sprintf( "case %d:\n", i ) )
  25.762 +				if i then
  25.763 +					poke_memstruct( pointer, struct_sym, member_list[i], 0 )
  25.764 +				end if
  25.765 +			end for
  25.766 +			c_stmt0("default: break;\n")
  25.767 +		c_stmt0("}\n")
  25.768 +	end if
  25.769 +	
  25.770 +	if not is_sequence then
  25.771 +		c_stmt0("if( free_src ){\n")
  25.772 +		c_stmt0("DeRefDS( MAKE_SEQ(src_s1) );\n")
  25.773 +		c_stmt0("}\n" )
  25.774 +	end if
  25.775 +	
  25.776 +	c_stmt0("}\n")
  25.777 +end procedure
  25.778 +
  25.779 +procedure assign_memunion( integer pointer, integer struct_sym, integer source_val )
  25.780 +	c_stmt0("{\n")
  25.781 +	c_stmt0("unsigned char *ptr;\n")
  25.782 +	c_stmt0("int i;\n")
  25.783 +	sequence seq_len     = set_up_assign_sequence( source_val )
  25.784 +	integer  is_sequence = seq_len[1]
  25.785 +	atom     seqlen      = seq_len[2]
  25.786 +	
  25.787 +	integer union_size = SymTab[struct_sym][S_MEM_SIZE]
  25.788 +	
  25.789 +	c_stmt("ptr = (unsigned char *) @;\n", pointer )
  25.790 +	if seqlen = NOVALUE then
  25.791 +		-- unknown length
  25.792 +		c_stmt0(sprintf("for( i = 1; i <= src_s1->length && i <= %d; ++i, ++ptr ){\n", union_size ) )
  25.793 +			c_stmt0("*ptr = (unsigned char) src_s1->base[i];\n")
  25.794 +		c_stmt0("}\n")
  25.795 +		
  25.796 +		c_stmt0(sprintf("for( i = src_s1->length + 1; i <= %d; ++i, ++ptr ){\n", union_size ) )
  25.797 +			c_stmt0("*ptr = 0;\n")
  25.798 +		c_stmt0("}\n")
  25.799 +		
  25.800 +	else
  25.801 +		-- we know the length
  25.802 +		if seqlen > union_size then
  25.803 +			seqlen = union_size
  25.804 +		end if
  25.805 +		
  25.806 +		for i = 1 to seqlen do
  25.807 +			c_stmt0( sprintf("*ptr++ = (unsigned char) src_s1->base[%d];\n", i ) )
  25.808 +		end for
  25.809 +		
  25.810 +		for i = seqlen + 1 to union_size do
  25.811 +			c_stmt0( "*ptr++ = 0;\n" )
  25.812 +		end for
  25.813 +	end if
  25.814 +	
  25.815 +	if not is_sequence then
  25.816 +		c_stmt0("if( free_src ){\n")
  25.817 +		c_stmt0("DeRefDS( MAKE_SEQ(src_s1) );\n")
  25.818 +		c_stmt0("}\n" )
  25.819 +	end if
  25.820 +	c_stmt0("}\n")
  25.821 +end procedure
  25.822 +
  25.823 +
  25.824 +export procedure opMEMSTRUCT_ASSIGN()
  25.825 +	integer
  25.826 +		pointer   = Code[pc+1],
  25.827 +		member    = Code[pc+2],
  25.828 +		val       = Code[pc+3],
  25.829 +		deref_ptr = Code[pc+4]
  25.830 +	
  25.831 +	get_pointer( pointer, pointer )
  25.832 +	
  25.833 +	integer tok = sym_token( member )
  25.834 +	if SymTab[member][S_MEM_POINTER] then
  25.835 +		if deref_ptr then
  25.836 +			c_stmt( "@ = *(intptr_t*)@;\n", { pointer, pointer }, pointer )
  25.837 +		else
  25.838 +			tok = MS_MEMBER
  25.839 +		end if
  25.840 +	end if
  25.841 +	
  25.842 +	switch tok do
  25.843 +		case MEMSTRUCT then
  25.844 +			assign_memstruct( pointer, member, val )
  25.845 +		case MEMUNION then
  25.846 +			assign_memunion( pointer, member, val )
  25.847 +		case else
  25.848 +			poke_member( pointer, member, val, deref_ptr )
  25.849 +	end switch
  25.850 +	
  25.851 +	
  25.852 +	dispose_temp( val, compile:DISCARD_TEMP, REMOVE_FROM_MAP )
  25.853 +	remove_pointer( pointer )
  25.854 +	
  25.855 +	pc += 5
  25.856 +end procedure
  25.857 +
  25.858 +
  25.859 +export procedure opMEMSTRUCT_ASSIGNOP()
  25.860 +	integer
  25.861 +		op        = Code[pc],
  25.862 +		pointer   = Code[pc+1],
  25.863 +		member    = Code[pc+2],
  25.864 +		val       = Code[pc+3],
  25.865 +		deref_ptr = Code[pc+4]
  25.866 +	
  25.867 +	get_pointer( pointer, pointer )
  25.868 +	
  25.869 +	if deref_ptr then
  25.870 +		c_stmt( "@ = *(intptr_t**) @;\n", { pointer, pointer }, pointer )
  25.871 +	end if
  25.872 +	sequence optext
  25.873 +	switch op do
  25.874 +		case MEMSTRUCT_PLUS then
  25.875 +			optext = "+"
  25.876 +		case MEMSTRUCT_MINUS then
  25.877 +			optext = "-"
  25.878 +		case MEMSTRUCT_DIVIDE then
  25.879 +			optext = "/"
  25.880 +		case MEMSTRUCT_MULTIPLY then
  25.881 +			optext = "*"
  25.882 +	end switch
  25.883 +	
  25.884 +	integer data_type = sym_token( member )
  25.885 +	sequence type_name = mem_name( data_type )
  25.886 +	switch data_type do
  25.887 +		case MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE then
  25.888 +			integer is_double = TypeIs( val, TYPE_DOUBLE )
  25.889 +			if not is_double then
  25.890 +				c_stmt( "if( IS_ATOM_INT( @ ) ){\n", val )
  25.891 +					c_stmt( sprintf("*(%s*)@ %s= (%s)@;\n", {type_name, optext, type_name}), { pointer, val }, pointer )
  25.892 +				c_stmt0( "}\n" )
  25.893 +				c_stmt0( "else{\n")
  25.894 +			end if
  25.895 +			
  25.896 +			c_stmt( sprintf("*(%s*)@ %s= (%s)DBL_PTR( @ )->dbl;\n", {type_name, optext, type_name}), { pointer, val }, pointer )
  25.897 +			
  25.898 +			if not is_double then
  25.899 +				c_stmt0( "}\n")
  25.900 +			end if
  25.901 +		
  25.902 +		case MEMUNION then
  25.903 +			-- TODO
  25.904 +		case MEMSTRUCT then
  25.905 +			-- TODO
  25.906 +		case else
  25.907 +			integer is_integer = TypeIs( val, TYPE_INTEGER )
  25.908 +			if not is_integer then
  25.909 +				c_stmt( "if( IS_ATOM_INT( @ ) ){\n", val )
  25.910 +			end if
  25.911 +			
  25.912 +			c_stmt( sprintf("*(%s*) @ %s= (%s) @;\n", {type_name, optext, type_name}), {pointer, val}, pointer )
  25.913 +			
  25.914 +			if not is_integer then
  25.915 +				c_stmt0("}\n" )
  25.916 +				c_stmt0( "else{\n")
  25.917 +				c_stmt( sprintf("*(%s*) @ %s= (%s) DBL_PTR( @ )->dbl;\n", {type_name, optext, type_name}), {pointer, val}, pointer )
  25.918 +				c_stmt0("}\n" )
  25.919 +			end if
  25.920 +	end switch
  25.921 +	dispose_temp( val, compile:DISCARD_TEMP, REMOVE_FROM_MAP )
  25.922 +	remove_pointer( pointer )
  25.923 +	pc += 5
  25.924 +end procedure
  25.925 +
  25.926 +export procedure opADDRESSOF()
  25.927 +	integer
  25.928 +		ptr    = Code[pc+1],
  25.929 +		target = Code[pc+2]
  25.930 +	CDeRef( target )
  25.931 +	c_stmt("if( IS_ATOM_INT( @ ) ){\n", ptr )
  25.932 +		c_stmt("@ = @;\n", { target, ptr }, target )
  25.933 +	c_stmt0("}\n")
  25.934 +	c_stmt0("else {\n")
  25.935 +		c_stmt("@ = NewDouble( (eudouble) @ );\n", {target, ptr}, target )
  25.936 +	c_stmt0( "}\n")
  25.937 +	SetBBType( target, TYPE_ATOM, {MININT, MAXINT}, TYPE_OBJECT, 0 )
  25.938 +	
  25.939 +	pc += 3
  25.940 +end procedure
  25.941 +
  25.942 +export procedure opOFFSETOF()
  25.943 +	integer
  25.944 +		member  = Code[pc+1],
  25.945 +		target  = Code[pc+2],
  25.946 +		parent  = SymTab[member][S_MEM_PARENT]
  25.947 +	
  25.948 +	CDeRef( target )
  25.949 +	sequence 
  25.950 +		memstruct_name = decorated_name( parent ),
  25.951 +		member_name    = decorated_name( member )
  25.952 +	c_stmt( sprintf("@ = offsetof( %s %s, %s);\n", { mem_name( sym_token( parent ) ), memstruct_name, member_name } ), { target }, target )
  25.953 +	
  25.954 +	pc += 3
  25.955 +end procedure
  25.956 +
  25.957 +function decorated_name( symtab_index sym )
  25.958 +	return sprintf( "_%d%s", { SymTab[sym][S_FILE_NO], sym_name( sym ) } )
  25.959 +end function
  25.960 +
  25.961 +function mem_name( integer tid )
  25.962 +	switch tid do
  25.963 +		case MS_CHAR then
  25.964 +			return "char"
  25.965 +		case MS_SHORT then
  25.966 +			return "short"
  25.967 +		case MS_INT then
  25.968 +			return "int"
  25.969 +		case MS_LONG then
  25.970 +			return "long"
  25.971 +		case MS_OBJECT then
  25.972 +			return "object"
  25.973 +		case MS_LONGLONG then
  25.974 +			return "long long int"
  25.975 +		case MS_FLOAT then
  25.976 +			return "float"
  25.977 +		case MS_DOUBLE then
  25.978 +			return "double"
  25.979 +		case MS_LONGDOUBLE then
  25.980 +			return "long double"
  25.981 +		case MS_EUDOUBLE then
  25.982 +			return "eudouble"
  25.983 +		case MEMSTRUCT then
  25.984 +			return "struct"
  25.985 +		case MEMUNION then
  25.986 +			return "union"
  25.987 +		case MS_MEMBER then
  25.988 +			return ""
  25.989 +		case else
  25.990 +			InternalErr("error finding name for token: [1] [2]", { tid, LexName( tid ) })
  25.991 +	end switch
  25.992 +end function
  25.993 +
  25.994 +function get_data_type( symtab_index member )
  25.995 +	integer data_type = SymTab[member][S_TOKEN]
  25.996 +	sequence name = ""
  25.997 +	
  25.998 +-- 	printf(1, "Writing data type for: %s - %s\n", { sym_name(member), LexName( data_type )})
  25.999 +	-- signed / unsigned
 25.1000 +	if not SymTab[member][S_MEM_SIGNED]
 25.1001 +	and data_type != MS_OBJECT
 25.1002 +	and data_type != MS_MEMBER
 25.1003 +	and data_type != MS_FLOAT
 25.1004 +	and data_type != MS_DOUBLE 
 25.1005 +	and data_type != MS_LONGDOUBLE 
 25.1006 +	and data_type != MS_EUDOUBLE
 25.1007 +	then
 25.1008 +		-- floating points are always marked signed
 25.1009 +		name &= "unsigned "
 25.1010 +	end if
 25.1011 +	
 25.1012 +	if data_type = MS_OBJECT and not SymTab[member][S_MEM_SIGNED] then
 25.1013 +		-- this one can't just take an unsigned
 25.1014 +		name &= "uintptr_t "
 25.1015 +	elsif data_type != MS_MEMBER then
 25.1016 +		name &= sprintf( "%s ", { mem_name( data_type )})
 25.1017 +	else
 25.1018 +		data_type = SymTab[SymTab[member][S_MEM_STRUCT]][S_TOKEN]
 25.1019 +		if data_type = MEMUNION then
 25.1020 +			-- embedded union
 25.1021 +			name &= sprintf( "union %s ", {decorated_name( SymTab[member][S_MEM_STRUCT] ) } )
 25.1022 +		else
 25.1023 +			-- embedded struct
 25.1024 +			name &= sprintf( "struct %s ", {decorated_name( SymTab[member][S_MEM_STRUCT] ) } )
 25.1025 +		end if
 25.1026 +	end if
 25.1027 +	
 25.1028 +	if SymTab[member][S_MEM_POINTER] then
 25.1029 +		name &= "*"
 25.1030 +	end if
 25.1031 +	return name
 25.1032 +end function
 25.1033 +
 25.1034 +procedure write_data_type( atom struct_h, symtab_index member )
 25.1035 +	puts( struct_h, get_data_type( member ) )
 25.1036 +end procedure
 25.1037 +
 25.1038 +procedure write_memstruct( atom struct_h, symtab_index sym )
 25.1039 +	symtab_pointer member = sym
 25.1040 +	while member with entry do
 25.1041 +		puts( struct_h, "\t" )
 25.1042 +		write_data_type( struct_h, member )
 25.1043 +		puts( struct_h, decorated_name( member ) )
 25.1044 +		if SymTab[member][S_MEM_ARRAY] then
 25.1045 +			printf( struct_h, "[%d]", SymTab[member][S_MEM_ARRAY] )
 25.1046 +		end if
 25.1047 +		printf( struct_h, "; // %d\n", SymTab[member][S_TOKEN] )
 25.1048 +	entry
 25.1049 +		member = SymTab[member][S_MEM_NEXT]
 25.1050 +	end while
 25.1051 +	puts( struct_h, "};\n\n" )
 25.1052 +end procedure
 25.1053 +
 25.1054 +export procedure write_struct_header()
 25.1055 +	atom struct_h = open( output_dir & "struct.h", "w", 1 )
 25.1056 +	generated_files = append( generated_files, "struct.h" )
 25.1057 +	
 25.1058 +	puts( struct_h, "#ifndef STRUCT_H_\n" )
 25.1059 +	puts( struct_h, "#define STRUCT_H_\n\n" )
 25.1060 +	puts( struct_h, "#include <stdint.h>\n")
 25.1061 +	puts( struct_h, "#include <stddef.h>\n")
 25.1062 +	puts( struct_h, "#include \"include/euphoria.h\"\n\n" )
 25.1063 +	
 25.1064 +	sequence structs = {}
 25.1065 +	for i = TopLevelSub to length( SymTab ) do
 25.1066 +		integer tok = sym_token( i )
 25.1067 +		if tok = MEMSTRUCT then
 25.1068 +			printf( struct_h, "struct %s %s;\n", repeat( decorated_name( i ), 2 ) )
 25.1069 +			structs &= i
 25.1070 +		elsif tok = MEMUNION then
 25.1071 +			printf( struct_h, "union %s %s;\n", repeat( decorated_name( i ), 2 ) )
 25.1072 +			structs &= i
 25.1073 +		end if
 25.1074 +	end for
 25.1075 +	
 25.1076 +	for i = 1 to length( structs ) do
 25.1077 +		integer tok = sym_token( structs[i] )
 25.1078 +		if tok = MEMSTRUCT then
 25.1079 +			printf( struct_h, "struct %s{\n", { decorated_name( structs[i] )} )
 25.1080 +			write_memstruct( struct_h, structs[i] )
 25.1081 +		elsif tok = MEMUNION then
 25.1082 +			printf( struct_h, "union %s{\n", { decorated_name( structs[i])} )
 25.1083 +			write_memstruct( struct_h, structs[i] )
 25.1084 +		end if
 25.1085 +	end for
 25.1086 +	
 25.1087 +	puts( struct_h, "#endif\n" )
 25.1088 +	
 25.1089 +end procedure
    26.1 --- a/source/cominit.e	Mon Dec 19 23:19:58 2011 -0300
    26.2 +++ b/source/cominit.e	Wed Dec 21 16:45:49 2011 -0300
    26.3 @@ -15,6 +15,7 @@
    26.4  include std/console.e
    26.5  include std/error.e as error
    26.6  include std/filesys.e
    26.7 +include std/get.e
    26.8  include std/io.e
    26.9  include std/map.e as m
   26.10  include std/search.e
   26.11 @@ -47,6 +48,7 @@
   26.12  	{ "batch",     0, GetMsgText(279,0), { } },
   26.13  	{ "strict",    0, GetMsgText(288,0), { } },
   26.14  	{ "test",      0, GetMsgText(289,0), { } },
   26.15 +	{ "trace-lines",0, GetMsgText(TRACE_LINES_CMD, 0), { HAS_PARAMETER, "lines" } },
   26.16  	{ "copyright", 0, GetMsgText(281,0), { } },
   26.17  	{ "v", "version", GetMsgText(290,0), { } },
   26.18   	$
   26.19 @@ -534,7 +536,15 @@
   26.20  			
   26.21  			case "eudir" then
   26.22  				set_eudir( val )
   26.23 -				
   26.24 +			
   26.25 +			case "trace-lines" then
   26.26 +				val = value( val )
   26.27 +				if val[1] = GET_SUCCESS then
   26.28 +					trace_lines = floor( val[2] )
   26.29 +				else
   26.30 +					puts(2, GetMsgText( BAD_TRACE_LINES ) )
   26.31 +					abort( 1 )
   26.32 +				end if
   26.33  		end switch
   26.34  	end for
   26.35  
    27.1 --- a/source/compile.e	Mon Dec 19 23:19:58 2011 -0300
    27.2 +++ b/source/compile.e	Wed Dec 21 16:45:49 2011 -0300
    27.3 @@ -8,7 +8,7 @@
    27.4  -- values of each variable and operand. This allows it to emit C code that
    27.5  -- is more precise and efficient. It doesn't actually emit the C code
    27.6  -- until the final pass.
    27.7 -
    27.8 +namespace compile
    27.9  ifdef ETYPE_CHECK then
   27.10  	with type_check
   27.11  elsedef
   27.12 @@ -25,6 +25,7 @@
   27.13  include buildsys.e
   27.14  include c_decl.e
   27.15  include c_out.e
   27.16 +include c_struct.e
   27.17  include cominit.e
   27.18  include compress.e
   27.19  include emit.e
   27.20 @@ -40,7 +41,7 @@
   27.21  include fwdref.e
   27.22  
   27.23  
   27.24 -integer np, pc
   27.25 +export integer np, pc
   27.26  
   27.27  constant MAXLEN = MAXINT - 1000000  -- assumed maximum length of a sequence
   27.28  
   27.29 @@ -135,7 +136,7 @@
   27.30  -- Value: 1 = reference count incremented when created
   27.31  map:map dead_temp_walking = map:new()
   27.32  
   27.33 -enum
   27.34 +export constant
   27.35  	NO_REFERENCE = 0,
   27.36  	NEW_REFERENCE = 1,
   27.37  	KEEP_IN_MAP = 0,
   27.38 @@ -166,7 +167,7 @@
   27.39  -- If the object's reference count was incremented, then referenced
   27.40  -- should be NEW_REFERENCE, so that it can be cleaned up properly later.
   27.41  -- Otherwise, ##referenced## should be NO_REFERENCE.
   27.42 -procedure create_temp( symtab_index sym, integer referenced )
   27.43 +export procedure create_temp( symtab_index sym, integer referenced )
   27.44  	if is_temp( sym ) then
   27.45  		map:put( dead_temp_walking, sym, referenced )
   27.46  	end if
   27.47 @@ -180,7 +181,7 @@
   27.48  -- it was created.  If remove_from_map is REMOVE_FROM_MAP, then the temp will
   27.49  -- be cleared from the map.  If remove_from_map is KEEP_IN_MAP, then the
   27.50  -- temp will be left in the map.
   27.51 -procedure dispose_temp( symtab_index sym, integer keep, integer remove_from_map )
   27.52 +export procedure dispose_temp( symtab_index sym, integer keep, integer remove_from_map )
   27.53  	if is_temp( sym ) then
   27.54  		if find( sym, saved_temps ) then
   27.55  			-- this will be deref'd manually
   27.56 @@ -398,7 +399,7 @@
   27.57  	return local_t
   27.58  end function
   27.59  
   27.60 -function SeqLen(integer x)
   27.61 +export function SeqLen(integer x)
   27.62  -- the length of a sequence
   27.63  	symtab_index s
   27.64  	atom len, local_len
   27.65 @@ -740,7 +741,7 @@
   27.66  integer deref_elem_type
   27.67  integer deref_short
   27.68  
   27.69 -procedure CSaveStr(sequence target, integer v, integer a, integer b, integer c)
   27.70 +export procedure CSaveStr(sequence target, integer v, integer a, integer b, integer c)
   27.71  -- save a value (to be deref'd) in immediate target
   27.72  -- if value isn't known to be an integer
   27.73  	boolean deref_exist
   27.74 @@ -806,7 +807,7 @@
   27.75  	end if
   27.76  end procedure
   27.77  
   27.78 -procedure CDeRefStr(sequence s)
   27.79 +export procedure CDeRefStr(sequence s)
   27.80  -- DeRef a string name  - see CSaveStr()
   27.81  	if length(deref_str) = 0 then
   27.82  		return
   27.83 @@ -842,7 +843,7 @@
   27.84  	end if
   27.85  end procedure
   27.86  
   27.87 -procedure CDeRef(integer v)
   27.88 +export procedure CDeRef(integer v)
   27.89  -- DeRef a var or temp
   27.90  	integer temp_type, elem_type
   27.91  
   27.92 @@ -2225,6 +2226,63 @@
   27.93  sequence dblfn
   27.94  boolean all_done
   27.95  
   27.96 +procedure sizeof_struct( symtab_index datatype_sym, symtab_index target_sym )
   27.97 +	sequence tag
   27.98 +	if sym_token( datatype_sym ) = MEMSTRUCT then
   27.99 +		tag = "struct"
  27.100 +	else
  27.101 +		tag = "union"
  27.102 +	end if
  27.103 +	c_stmt( sprintf( "@ = sizeof( %s @);\n", {tag} ), { target_sym, datatype_sym } )
  27.104 +	CDeRef( target_sym )
  27.105 +end procedure
  27.106 +
  27.107 +procedure do_sizeof( symtab_index datatype_sym, symtab_index target_sym )
  27.108 +	switch sym_token( datatype_sym ) do
  27.109 +		case MEMSTRUCT, MEMUNION then
  27.110 +			sizeof_struct( datatype_sym, target_sym )
  27.111 +		
  27.112 +		case MEMTYPE then
  27.113 +			-- use whatever the actual type is...
  27.114 +			do_sizeof( SymTab[datatype_sym][S_MEM_PARENT], target_sym )
  27.115 +		
  27.116 +		-- memstruct primitives:
  27.117 +		case MS_CHAR       then c_stmt( "@ = sizeof( char );\n", target_sym, target_sym )
  27.118 +		case MS_SHORT      then c_stmt( "@ = sizeof( short );\n", target_sym, target_sym )
  27.119 +		case MS_SIGNED     then c_stmt( "@ = sizeof( int );\n", target_sym, target_sym )
  27.120 +		case MS_UNSIGNED   then c_stmt( "@ = sizeof( int );\n", target_sym, target_sym )
  27.121 +		case MS_INT        then c_stmt( "@ = sizeof( int );\n", target_sym, target_sym )
  27.122 +		case MS_LONG       then c_stmt( "@ = sizeof( long );\n", target_sym, target_sym )
  27.123 +		case MS_LONGLONG   then c_stmt( "@ = sizeof( long long );\n", target_sym, target_sym )
  27.124 +		case MS_FLOAT      then c_stmt( "@ = sizeof( float );\n", target_sym, target_sym )
  27.125 +		case MS_DOUBLE     then c_stmt( "@ = sizeof( double );\n", target_sym, target_sym )
  27.126 +		case MS_LONGDOUBLE then c_stmt( "@ = sizeof( long double );\n", target_sym, target_sym )
  27.127 +		case MS_EUDOUBLE   then c_stmt( "@ = sizeof( eudouble );\n", target_sym, target_sym )
  27.128 +		case MS_OBJECT     then c_stmt( "@ = sizeof( void * );\n", target_sym, target_sym )
  27.129 +		
  27.130 +		case else
  27.131 +			-- Will be evaluated like on of the C_* constants
  27.132 +			c_stmt("@ = eu_sizeof( @ );\n", { target_sym, datatype_sym }, target_sym )
  27.133 +			CSaveStr( "_0", target_sym, datatype_sym, 0, 0 )
  27.134 +			CDeRef( target_sym )
  27.135 +			dispose_temp( datatype_sym, compile:DISCARD_TEMP, compile:REMOVE_FROM_MAP )
  27.136 +			
  27.137 +	end switch
  27.138 +end procedure
  27.139 +
  27.140 +export procedure opSIZEOF()
  27.141 +	integer
  27.142 +		datatype_sym = Code[pc+1],
  27.143 +		target_sym   = Code[pc+2]
  27.144 +	
  27.145 +	do_sizeof( datatype_sym, target_sym )
  27.146 +	
  27.147 +	SetBBType( target_sym, TYPE_INTEGER, {0, MAXINT}, TYPE_INTEGER, 0 )
  27.148 +	create_temp( target_sym, 1 )
  27.149 +	pc += 3
  27.150 +end procedure
  27.151 +
  27.152 +
  27.153  procedure opSTARTLINE()
  27.154  -- common in Translator, not in Interpreter
  27.155  	sequence line
  27.156 @@ -3492,7 +3550,7 @@
  27.157  	pc += 5
  27.158  end procedure
  27.159  
  27.160 -procedure opTYPE_CHECK()
  27.161 +procedure opTYPE_CHECK() -- MEM_TYPE_CHECK
  27.162  -- type check for a user-defined type
  27.163  -- this always follows a type-call
  27.164  -- The Translator only performs the type-call and check,
  27.165 @@ -3511,7 +3569,13 @@
  27.166  		c_stmt0("}\n")
  27.167  		c_stmt0("}\n")
  27.168  	end if
  27.169 -	pc += 1
  27.170 +	
  27.171 +	if Code[pc] = TYPE_CHECK then
  27.172 +		pc += 1
  27.173 +	else
  27.174 +		pc += 2
  27.175 +	end if
  27.176 +	
  27.177  end procedure
  27.178  
  27.179  function is_temp( symtab_index sym )
  27.180 @@ -5651,22 +5715,6 @@
  27.181  	pc += 3
  27.182  end procedure
  27.183  
  27.184 -procedure opSIZEOF()
  27.185 -	integer
  27.186 -		datatype_sym = Code[pc+1],
  27.187 -		target_sym   = Code[pc+2]
  27.188 -	CSaveStr( "_0", target_sym, datatype_sym, 0, 0 )
  27.189 -	
  27.190 -	c_stmt("@ = eu_sizeof( @ );\n", { target_sym, datatype_sym }, target_sym )
  27.191 -	
  27.192 -	CDeRef( target_sym )
  27.193 -	
  27.194 -	dispose_temp( datatype_sym, DISCARD_TEMP, REMOVE_FROM_MAP )
  27.195 -	SetBBType( target_sym, TYPE_INTEGER, {0, MAXINT}, TYPE_INTEGER, 0 )
  27.196 -	create_temp( target_sym, 1 )
  27.197 -	pc += 3
  27.198 -end procedure
  27.199 -
  27.200  procedure opPOKE()
  27.201  -- generate code for poke/2/4/8
  27.202  -- should optimize constant address
  27.203 @@ -6412,6 +6460,7 @@
  27.204  	pc += 1
  27.205  end procedure
  27.206  
  27.207 +
  27.208  sequence operation -- routine ids for all opcode handlers
  27.209  
  27.210  export procedure init_opcodes()
  27.211 @@ -6425,6 +6474,9 @@
  27.212  		switch name do
  27.213  			case "AND_BITS" then
  27.214  				operation[i] = routine_id("opAND_BITS")
  27.215 +				
  27.216 +			case "ADDRESSOF" then
  27.217 +				operation[i] = routine_id("opADDRESSOF")
  27.218  
  27.219  			case "AND" then
  27.220  				operation[i] = routine_id("opAND")
  27.221 @@ -6651,6 +6703,27 @@
  27.222  			case "MEM_SET" then
  27.223  				operation[i] = routine_id("opMEM_SET")
  27.224  
  27.225 +			case "MEMSTRUCT_ACCESS" then
  27.226 +				operation[i] = routine_id("opMEMSTRUCT_ACCESS")
  27.227 +				
  27.228 +			case "PEEK_ARRAY" then
  27.229 +				operation[i] = routine_id("opPEEK_ARRAY")
  27.230 +			
  27.231 +			case "MEMSTRUCT_ARRAY" then
  27.232 +				operation[i] = routine_id("opMEMSTRUCT_ARRAY")
  27.233 +				
  27.234 +			case "PEEK_MEMBER" then
  27.235 +				operation[i] = routine_id("opPEEK_MEMBER")
  27.236 +				
  27.237 +			case "MEMSTRUCT_READ" then
  27.238 +				operation[i] = routine_id("opMEMSTRUCT_READ")
  27.239 +				
  27.240 +			case "MEMSTRUCT_ASSIGN" then
  27.241 +				operation[i] = routine_id("opMEMSTRUCT_ASSIGN")
  27.242 +				
  27.243 +			case "MEMSTRUCT_PLUS", "MEMSTRUCT_MINUS", "MEMSTRUCT_MULTIPLY", "MEMSTRUCT_DIVIDE" then
  27.244 +				operation[i] = routine_id("opMEMSTRUCT_ASSIGNOP")
  27.245 +				
  27.246  			case "MINUS" then
  27.247  				operation[i] = routine_id("opMINUS")
  27.248  
  27.249 @@ -6681,6 +6754,9 @@
  27.250  			case "NOTEQ" then
  27.251  				operation[i] = routine_id("opNOTEQ")
  27.252  
  27.253 +			case "OFFSETOF" then
  27.254 +				operation[i] = routine_id("opOFFSETOF")
  27.255 +			
  27.256  			case "OPEN" then
  27.257  				operation[i] = routine_id("opOPEN")
  27.258  
  27.259 @@ -6852,9 +6928,9 @@
  27.260  			case "TRACE" then
  27.261  				operation[i] = routine_id("opTRACE")
  27.262  
  27.263 -			case "TYPE_CHECK" then
  27.264 +			case "TYPE_CHECK", "MEM_TYPE_CHECK" then
  27.265  				operation[i] = routine_id("opTYPE_CHECK")
  27.266 -
  27.267 +			
  27.268  			case "UMINUS" then
  27.269  				operation[i] = routine_id("opUMINUS")
  27.270  
  27.271 @@ -6979,6 +7055,8 @@
  27.272  				operation[i] = routine_id("opDEREF_TEMP")
  27.273  			case "REF_TEMP" then
  27.274  				operation[i] = routine_id("opREF_TEMP")
  27.275 +			case "ARRAY_ACCESS" then
  27.276 +				operation[i] = routine_id("opARRAY_ACCESS")
  27.277  			case else
  27.278  				operation[i] = -1
  27.279  		end switch
  27.280 @@ -7137,7 +7215,7 @@
  27.281  
  27.282  	-- prevent conflicts
  27.283  	for i = TopLevelSub+1 to length(SymTab) do
  27.284 -		if sequence(SymTab[i][S_NAME]) and find( SymTab[i][S_TOKEN], {VARIABLE, CONSTANT, ENUM}) then
  27.285 +		if sequence(SymTab[i][S_NAME]) and  sym_mode( i ) = M_NORMAL and not find( sym_token( i ), { PROC, FUNC, TYPE} ) then --find( SymTab[i][S_TOKEN], {VARIABLE, CONSTANT, ENUM}) then
  27.286  			SymTab[i][S_NAME] &= sprintf( "_%d", i )
  27.287  		end if
  27.288  	end for
  27.289 @@ -7194,7 +7272,8 @@
  27.290  	end if
  27.291  	c_puts("#include <time.h>\n")
  27.292  	c_puts("#include \"include/euphoria.h\"\n")
  27.293 -	c_puts("#include \"main-.h\"\n\n")
  27.294 +	c_puts("#include \"main-.h\"\n")
  27.295 +	c_puts("#include \"struct.h\"\n\n")
  27.296  
  27.297  	if TUNIX then
  27.298  		c_puts("#include <unistd.h>\n")
  27.299 @@ -7372,6 +7451,8 @@
  27.300  		c_stmt0("eu_startup(_00, _01, _02, (object)CLOCKS_PER_SEC, (object)sysconf(_SC_CLK_TCK));\n")
  27.301  		c_puts("#endif\n")
  27.302  	end if
  27.303 +	
  27.304 +	c_stmt0( sprintf( "trace_lines = %d;\n", trace_lines ) )
  27.305  
  27.306  	-- options_switch initialization
  27.307  	switches = get_switches()
  27.308 @@ -7559,6 +7640,8 @@
  27.309  
  27.310  	close(c_code)
  27.311  	close(c_h)
  27.312 +	
  27.313 +	write_struct_header()
  27.314  
  27.315  	write_buildfile()
  27.316  end procedure
    28.1 --- a/source/configure	Mon Dec 19 23:19:58 2011 -0300
    28.2 +++ b/source/configure	Wed Dec 21 16:45:49 2011 -0300
    28.3 @@ -277,7 +277,7 @@
    28.4  		fi
    28.5  		ARCH=$VAL
    28.6  		case $ARCH in
    28.7 -			x86.64)
    28.8 +			x86*64)
    28.9  				ARCH=ix86_64
   28.10  				MFLAG=-m64
   28.11  				EFLAG=E64
    29.1 --- a/source/dis.e	Mon Dec 19 23:19:58 2011 -0300
    29.2 +++ b/source/dis.e	Wed Dec 21 16:45:49 2011 -0300
    29.3 @@ -64,7 +64,10 @@
    29.4  	end if
    29.5  end function
    29.6  
    29.7 -function names( sequence n )
    29.8 +function names( object n )
    29.9 +	if atom( n ) then
   29.10 +		n = { n }
   29.11 +	end if
   29.12  	sequence nl
   29.13  	nl = {}
   29.14  	for i = 1 to length(n) do
   29.15 @@ -473,7 +476,28 @@
   29.16      il( sprintf("%s => %s", names( {a,target} )), 2 )
   29.17      pc += 3
   29.18  end procedure
   29.19 ---
   29.20 +
   29.21 +procedure opMEMSTRUCT_ASSIGN()  -- or opASSIGN_I or SEQUENCE_COPY
   29.22 +    a = Code[pc+1]  -- pointer
   29.23 +    b = Code[pc+2]  -- member sym
   29.24 +    c = Code[pc+3]  -- new value
   29.25 +    sequence deref
   29.26 +    if Code[pc+4] then
   29.27 +		deref = ".*"
   29.28 +	else
   29.29 +		deref = ""
   29.30 +	end if
   29.31 +	sequence operator = ""
   29.32 +	switch Code[pc] do
   29.33 +		case MEMSTRUCT_PLUS     then   operator = "+"
   29.34 +		case MEMSTRUCT_MINUS    then   operator = "-"
   29.35 +		case MEMSTRUCT_MULTIPLY then   operator = "*"
   29.36 +		case MEMSTRUCT_DIVIDE   then   operator = "/"
   29.37 +	end switch
   29.38 +    il( sprintf("%s %s.%s%s %s= %s", {opnames[Code[pc]]} & names( {a, b } ) & {deref, operator} & names( {c} ) ), 4 )
   29.39 +    pc += 5
   29.40 +end procedure
   29.41 +
   29.42  procedure opELSE()  -- or EXIT, ENDWHILE}) then
   29.43  	il( sprintf("%s goto %04d", {opnames[Code[pc]], Code[pc+1]}),1 )
   29.44  --    pc = Code[pc+1]
   29.45 @@ -726,6 +750,13 @@
   29.46  
   29.47  end procedure
   29.48  
   29.49 +procedure opMEM_TYPE_CHECK()
   29.50 +
   29.51 +	punary()
   29.52 +
   29.53 +end procedure
   29.54 +
   29.55 +
   29.56  procedure is_an()
   29.57      a = Code[pc+1]
   29.58      target = Code[pc+2]
   29.59 @@ -887,6 +918,22 @@
   29.60      binary()
   29.61  end procedure
   29.62  
   29.63 +procedure opMEMSTRUCT_PLUS()
   29.64 +	opMEMSTRUCT_ASSIGN()
   29.65 +end procedure
   29.66 +
   29.67 +procedure opMEMSTRUCT_MINUS()
   29.68 +	opMEMSTRUCT_ASSIGN()
   29.69 +end procedure
   29.70 +
   29.71 +procedure opMEMSTRUCT_MULTIPLY()
   29.72 +	opMEMSTRUCT_ASSIGN()
   29.73 +end procedure
   29.74 +
   29.75 +procedure opMEMSTRUCT_DIVIDE()
   29.76 +	opMEMSTRUCT_ASSIGN()
   29.77 +end procedure
   29.78 +
   29.79  procedure opMINUS() -- or opMINUS_I then
   29.80      binary()
   29.81  end procedure
   29.82 @@ -1165,6 +1212,14 @@
   29.83  	unary()
   29.84  end procedure
   29.85  
   29.86 +procedure opADDRESSOF()
   29.87 +	unary()
   29.88 +end procedure
   29.89 +
   29.90 +procedure opOFFSETOF()
   29.91 +	unary()
   29.92 +end procedure
   29.93 +
   29.94  procedure opMEM_COPY()
   29.95  	ptrinary()
   29.96  end procedure
   29.97 @@ -1362,6 +1417,71 @@
   29.98  	punary()
   29.99  end procedure
  29.100  
  29.101 +procedure mem_access()
  29.102 +	-- pc+1 number of accesses
  29.103 +	-- pc+2 pointer to memstruct
  29.104 +	-- pc+3 .. pc+n+1 member syms for access
  29.105 +	
  29.106 +	-- MEMSTRUCT_ACCESS:
  29.107 +	-- pc+n+2 target for pointer
  29.108 +	
  29.109 +	-- ARRAY_ACCESS
  29.110 +	-- pc+n+2: subscript
  29.111 +	-- pc+n+3 target for pointer
  29.112 +	
  29.113 +	integer op = Code[pc]
  29.114 +	integer is_array = (op= ARRAY_ACCESS)
  29.115 +	integer members = Code[pc+1]
  29.116 +	sequence text = sprintf("%s %s %s(", {opnames[op]} & names( {Code[pc+2], SymTab[Code[pc+3]][S_MEM_PARENT]} ) )
  29.117 +	for i = pc+3 to pc+2+members do
  29.118 +		text &= sprintf(" %s", names( Code[i] ) )
  29.119 +	end for
  29.120 +	text &= " )"
  29.121 +	if is_array then
  29.122 +		text &= sprintf( "[%s]", {name_or_literal( Code[pc+members+3] )} )
  29.123 +	end if
  29.124 +	text &= sprintf(" => %s", names( Code[pc+members+3 + is_array] ) )
  29.125 +	il( text, members + 3 + is_array )
  29.126 +	pc += members + 4 + is_array
  29.127 +end procedure
  29.128 +
  29.129 +procedure opARRAY_ACCESS()
  29.130 +	mem_access()
  29.131 +end procedure
  29.132 +
  29.133 +procedure opMEMSTRUCT_ACCESS()
  29.134 +	mem_access()
  29.135 +end procedure
  29.136 +
  29.137 +procedure opMEMSTRUCT_ARRAY()
  29.138 +	trinary()
  29.139 +end procedure
  29.140 +
  29.141 +
  29.142 +procedure opMEMSTRUCT_READ()
  29.143 +	binary()
  29.144 +end procedure
  29.145 +
  29.146 +procedure opPEEK_ARRAY()
  29.147 +	trinary()
  29.148 +end procedure
  29.149 +include std/console.e
  29.150 +procedure opPEEK_MEMBER()
  29.151 +	sequence deref
  29.152 +	if Code[pc+3] then
  29.153 +		deref = "DEREFERENCE POINTER"
  29.154 +	else
  29.155 +		deref = "VALUE"
  29.156 +	end if
  29.157 +	il( sprintf( "%s: %s, %s  [%s] => %s",
  29.158 +				 {opnames[Code[pc]]} &
  29.159 +				 names(Code[pc+1..pc+2]) &
  29.160 +				 {deref} &
  29.161 +				 names( {Code[pc+4]}) ), 
  29.162 +		4)
  29.163 +	pc += 5
  29.164 +end procedure
  29.165 +
  29.166  function strip_path( sequence file )
  29.167  	for i = length( file ) to 1 by -1 do
  29.168  		if find( file[i], "/\\" ) then
  29.169 @@ -1471,7 +1591,7 @@
  29.170  
  29.171  constant MODES = {"M_NORMAL", "M_CONSTANT", "M_TEMP", "M_SCOPE" }
  29.172  constant SCOPES = {
  29.173 -	"SC_?",
  29.174 +	"SC_NONE",
  29.175  	"SC_LOOP_VAR",    -- "private" loop vars known within a single loop
  29.176  	"SC_PRIVATE",    -- private within subprogram
  29.177  	"SC_GLOOP_VAR",   -- "global" loop var
  29.178 @@ -1483,7 +1603,10 @@
  29.179  	"SC_MULTIPLY_DEFINED",  -- global symbol defined in 2 or more files
  29.180  	"SC_EXPORT",   -- visible to anyone that includes the file
  29.181  	"SC_OVERRIDE", -- override an internal
  29.182 -	"SC_PUBLIC" }   -- visible to any file that includes it, or via "public include"
  29.183 +	"SC_PUBLIC",   -- visible to any file that includes it, or via "public include"
  29.184 +	"SC_MEMSTRUCT",
  29.185 +	$
  29.186 +	}
  29.187  
  29.188  constant USAGE_VALUES = {
  29.189  	U_UNUSED,
  29.190 @@ -1783,7 +1906,7 @@
  29.191  			name = "GREATEREQ_IFW"
  29.192  		elsif equal(name, "LESSEQ_IFW_I") then
  29.193  			name = "LESSEQ_IFW"
  29.194 -		elsif match( "PEEK", name ) then
  29.195 +		elsif match( "PEEK", name ) and not match( "_MEMBER", name ) and not match( "_ARRAY", name ) then
  29.196  			name = "PEEK"
  29.197  		elsif match( "POKE", name ) then
  29.198  			name = "POKE"
  29.199 @@ -1820,6 +1943,70 @@
  29.200  	return b
  29.201  end function
  29.202  
  29.203 +function mem_name( symtab_index member_sym )
  29.204 +	integer tid = sym_token( member_sym )
  29.205 +	switch tid do
  29.206 +		case MS_CHAR then
  29.207 +			return "char"
  29.208 +		case MS_SHORT then
  29.209 +			return "short"
  29.210 +		case MS_INT then
  29.211 +			return "int"
  29.212 +		case MS_LONG then
  29.213 +			return "long"
  29.214 +		case MS_OBJECT then
  29.215 +			return "object"
  29.216 +		case MS_LONGLONG then
  29.217 +			return "long long int"
  29.218 +		case MS_FLOAT then
  29.219 +			return "float"
  29.220 +		case MS_DOUBLE then
  29.221 +			return "double"
  29.222 +		case MS_LONGDOUBLE then
  29.223 +			return "long double"
  29.224 +		case MS_EUDOUBLE then
  29.225 +			return "eudouble"
  29.226 +		case MS_MEMBER then
  29.227 +			return sym_name( SymTab[member_sym][S_MEM_STRUCT] )
  29.228 +	end switch
  29.229 +end function
  29.230 +
  29.231 +procedure dis_memstruct( integer ms )
  29.232 +	if sym_token( ms ) = MEMSTRUCT then
  29.233 +		puts( out, "\nMemStruct" )
  29.234 +	else
  29.235 +		puts( out, "\nMemUnion" )
  29.236 +	end if
  29.237 +	
  29.238 +	printf( out, " [%s-%s:%05d]\n",
  29.239 +		{known_files[SymTab[ms][S_FILE_NO]], SymTab[ms][S_NAME], ms })
  29.240 +	printf( out, "    SIZE: %d\n", SymTab[ms][S_MEM_SIZE] )
  29.241 +	symtab_pointer member_sym = ms
  29.242 +	printf( out, "            %-20s  %-15s Other Information\n", {"Name", "Type"})
  29.243 +	while member_sym with entry do
  29.244 +		printf( out, "    %06d: %-20s  %-15s pointer[%d] signed[%d] array[%d] offset[%3d] size[%d]\n", 
  29.245 +			{ 
  29.246 +				member_sym, 
  29.247 +				sym_name( member_sym ), 
  29.248 +				mem_name( member_sym ),
  29.249 +				SymTab[member_sym][S_MEM_POINTER],
  29.250 +				SymTab[member_sym][S_MEM_SIGNED],
  29.251 +				SymTab[member_sym][S_MEM_ARRAY],
  29.252 +				SymTab[member_sym][S_MEM_OFFSET],
  29.253 +				SymTab[member_sym][S_MEM_SIZE],
  29.254 +				$
  29.255 +				} )
  29.256 +		
  29.257 +	entry
  29.258 +		member_sym = SymTab[member_sym][S_MEM_NEXT]
  29.259 +	end while
  29.260 +	if sym_token( ms ) = MEMSTRUCT then
  29.261 +		puts( out, "End MemStruct" )
  29.262 +	else
  29.263 +		puts( out, "End MemUnion" )
  29.264 +	end if
  29.265 +	printf( out, " [%s:%05d]\n", {sym_name( ms ), ms} )
  29.266 +end procedure
  29.267  
  29.268  procedure dis( integer sub )
  29.269  	integer op, ix
  29.270 @@ -1925,6 +2112,10 @@
  29.271  		and sequence(SymTab[i][S_CODE])
  29.272  		and SymTab[i][S_SCOPE] != SC_PRIVATE then
  29.273  			dis( i )
  29.274 +		
  29.275 +		elsif length(SymTab[i])  = SIZEOF_MEMSTRUCT_ENTRY
  29.276 +		and (SymTab[i][S_TOKEN] = MEMSTRUCT or SymTab[i][S_TOKEN] = MEMUNION) then
  29.277 +			dis_memstruct( i )
  29.278  		else
  29.279  			-- other symbols?
  29.280  		end if
  29.281 @@ -1937,3 +2128,4 @@
  29.282  
  29.283  end procedure
  29.284  mode:set_backend( routine_id("BackEnd") )
  29.285 +
    30.1 --- a/source/emit.e	Mon Dec 19 23:19:58 2011 -0300
    30.2 +++ b/source/emit.e	Wed Dec 21 16:45:49 2011 -0300
    30.3 @@ -23,6 +23,7 @@
    30.4  include block.e
    30.5  include shift.e
    30.6  include coverage.e
    30.7 +include msgtext.e
    30.8  
    30.9  export integer op_info1, op_info2
   30.10  export integer optimized_while
   30.11 @@ -35,8 +36,8 @@
   30.12  -- temps needed for LHS subscripting
   30.13  export symtab_index lhs_subs1_copy_temp, lhs_target_temp
   30.14  -- Code generation Stack
   30.15 -sequence cg_stack -- expression stack
   30.16 -integer cgi -- expression stack top-of-stack index
   30.17 +export sequence cg_stack -- expression stack
   30.18 +export integer cgi -- expression stack top-of-stack index
   30.19  
   30.20  boolean assignable  = FALSE  -- did previous op have a re-assignable result?
   30.21  
   30.22 @@ -127,7 +128,30 @@
   30.23  	{WITH, "with"},
   30.24  	{WITHOUT, "without"},
   30.25  	{WHILE, "while"},
   30.26 -	{'?', "?"}
   30.27 +	{'?', "?"},
   30.28 +	{MEMSTRUCT, "a memstruct"},
   30.29 +	{MEMUNION, "a memunion"},
   30.30 +	{MEMSTRUCT_ASSIGN, "="},
   30.31 +	{MEMSTRUCT_PLUS, "+="},
   30.32 +	{MEMSTRUCT_MINUS, "-="},
   30.33 +	{MEMSTRUCT_MULTIPLY, "*="},
   30.34 +	{MEMSTRUCT_DIVIDE, "/="},
   30.35 +	{MS_CHAR, "char"},
   30.36 +	{MS_SHORT, "short"},
   30.37 +	{MS_INT, "int" },
   30.38 +	{MS_LONG, "long int" },
   30.39 +	{MS_LONGLONG, "long long int" },
   30.40 +	{MS_FLOAT, "float" },
   30.41 +	{MS_DOUBLE, "double" },
   30.42 +	{MS_LONGDOUBLE, "long double" },
   30.43 +	{MS_EUDOUBLE, "eudouble" },
   30.44 +	{MS_OBJECT, "object" },
   30.45 +	{MS_POINTER, "pointer" },
   30.46 +	{MS_SIGNED, "signed" },
   30.47 +	{MS_UNSIGNED, "unsigned" },
   30.48 +	{MS_MEMBER, "a memstruct member"},
   30.49 +	{MEMTYPE, "a memtype"},
   30.50 +	$
   30.51  }
   30.52  
   30.53  export procedure Push(symtab_pointer x)
   30.54 @@ -483,6 +507,7 @@
   30.55  op_result[TAIL] = T_SEQUENCE
   30.56  op_result[REMOVE] = T_SEQUENCE
   30.57  op_result[REPLACE] = T_SEQUENCE
   30.58 +op_result[PEEK_ARRAY] = T_SEQUENCE
   30.59  
   30.60  sequence op_temp_ref = repeat( NO_REFERENCE, MAX_OPCODE )
   30.61  op_temp_ref[RIGHT_BRACE_N]    = NEW_REFERENCE
   30.62 @@ -573,6 +598,9 @@
   30.63  op_temp_ref[GETS]             = NEW_REFERENCE
   30.64  op_temp_ref[GETENV]           = NEW_REFERENCE
   30.65  op_temp_ref[RAND]             = NEW_REFERENCE
   30.66 +op_temp_ref[PEEK_ARRAY]       = NEW_REFERENCE
   30.67 +op_temp_ref[PEEK_MEMBER]      = NEW_REFERENCE
   30.68 +op_temp_ref[MEMSTRUCT_READ]   = NEW_REFERENCE
   30.69  
   30.70  procedure cont11ii(integer op, boolean ii)
   30.71  -- if ii is TRUE then integer arg always produces integer result
   30.72 @@ -1401,9 +1429,36 @@
   30.73  	-- 2 inputs, 1 output
   30.74  	case MINUS, rw:APPEND, PREPEND, COMPARE, EQUAL,
   30.75  					SYSTEM_EXEC, rw:CONCAT, REPEAT, MACHINE_FUNC, C_FUNC,
   30.76 -					SPRINTF, TASK_CREATE, HASH, HEAD, TAIL, DELETE_ROUTINE then
   30.77 +					SPRINTF, TASK_CREATE, HASH, HEAD, TAIL, DELETE_ROUTINE,
   30.78 +					MEMSTRUCT_READ  then
   30.79  		cont21ii(op, FALSE)
   30.80  
   30.81 +	case ADDRESSOF, OFFSETOF then
   30.82 +		-- last OP should have been PEEK_MEMBER
   30.83 +		if length( Code ) < 4 then
   30.84 +			CompileErr( MISSING_MEMSTRUCT_MEMBER )
   30.85 +		elsif Code[$-4] != PEEK_MEMBER and Code[$-1] != MEMSTRUCT_READ then
   30.86 +			InternalErr("Expected to replace PEEK_MEMBER or MEMSTRUCT_READ")
   30.87 +		end if
   30.88 +		
   30.89 +		-- We'll replace PEEK_MEMBER with ADDRESSOF
   30.90 +		Pop()
   30.91 +		if op = ADDRESSOF then
   30.92 +			Push( Code[$-3] )
   30.93 +			Code = remove( Code, length( Code ) - 4, length( Code ) )
   30.94 +		else
   30.95 +			Push( Code[$-2] )
   30.96 +			for pc = length( Code ) - 8 to 1 by -1 do
   30.97 +				if Code[pc] = MEMSTRUCT_ACCESS then
   30.98 +					Code = remove( Code, pc, length( Code ) )
   30.99 +					exit
  30.100 +				end if
  30.101 +			end for
  30.102 +			
  30.103 +		end if
  30.104 +		
  30.105 +		cont11ii(op, FALSE)
  30.106 +		
  30.107  	case SC2_NULL then  -- correct the stack - we aren't emitting anything
  30.108  		c = Pop()
  30.109  		TempKeep(c)
  30.110 @@ -1435,7 +1490,8 @@
  30.111  		assignable = FALSE
  30.112  
  30.113  	-- 3 inputs, 1 output
  30.114 -	case RHS_SLICE, FIND, MATCH, FIND_FROM, MATCH_FROM, SPLICE, INSERT, REMOVE, OPEN then
  30.115 +	case RHS_SLICE, FIND, MATCH, FIND_FROM, MATCH_FROM, SPLICE, INSERT, REMOVE, OPEN,
  30.116 +		MEMSTRUCT_ARRAY, PEEK_ARRAY, PEEK_MEMBER then
  30.117  		emit_opcode(op)
  30.118  		c = Pop()
  30.119  		b = Pop()
  30.120 @@ -1690,6 +1746,13 @@
  30.121  		c = Pop()
  30.122  		assignable = FALSE
  30.123  
  30.124 +	case MEM_TYPE_CHECK then
  30.125 +		-- 1 input, 0 output
  30.126 +		emit_opcode(op)
  30.127 +		c = Pop()
  30.128 +		emit_addr( c )
  30.129 +		assignable = FALSE
  30.130 +	
  30.131  	-- 0 inputs, 1 output, special op
  30.132  	case DOLLAR then
  30.133  		if current_sequence[$] < 0 or SymTab[current_sequence[$]][S_SCOPE] = SC_UNDEFINED then
  30.134 @@ -1783,6 +1846,31 @@
  30.135  		end if
  30.136  		assignable = FALSE
  30.137  	
  30.138 +	case MEMSTRUCT_ACCESS, ARRAY_ACCESS then
  30.139 +		a = Pop() -- number of elements
  30.140 +		if op = ARRAY_ACCESS then
  30.141 +			-- subscript:
  30.142 +			b = Pop()
  30.143 +		end if
  30.144 +		sequence members = repeat( 0, a )
  30.145 +		for i = a to 1 by -1 do
  30.146 +			members[i] = Pop()
  30.147 +		end for
  30.148 +		
  30.149 +		emit_opcode( op )
  30.150 +		emit_addr( a )
  30.151 +		emit_addr( Pop() )
  30.152 +		for i = 1 to length( members ) do
  30.153 +			emit_addr( members[i] )
  30.154 +		end for
  30.155 +		if op = ARRAY_ACCESS then
  30.156 +			-- subscript:
  30.157 +			emit_addr( b )
  30.158 +		end if
  30.159 +		c = NewTempSym()
  30.160 +		Push( c )
  30.161 +		emit_addr( c )
  30.162 +		assignable = FALSE
  30.163  	case REF_TEMP then
  30.164  		-- Used by the Translator to save temps
  30.165  		emit_opcode( REF_TEMP )
  30.166 @@ -1791,7 +1879,22 @@
  30.167  	case DEREF_TEMP then
  30.168  		emit_opcode( DEREF_TEMP )
  30.169  		emit_addr( Pop() )
  30.170 +	
  30.171 +	case MEMSTRUCT_ASSIGN, MEMSTRUCT_PLUS, MEMSTRUCT_MINUS, 
  30.172 +			MEMSTRUCT_DIVIDE, MEMSTRUCT_MULTIPLY then
  30.173  		
  30.174 +		c = Pop() -- new value
  30.175 +		integer deref_ptr = Pop()
  30.176 +		b = Pop() -- member sym
  30.177 +		a = Pop() -- pointer
  30.178 +		
  30.179 +		emit_opcode( op )
  30.180 +		emit_addr( a )
  30.181 +		emit_addr( b )
  30.182 +		emit_addr( c )
  30.183 +		emit_addr( deref_ptr )
  30.184 +		assignable = FALSE
  30.185 +	
  30.186  	case else
  30.187  		InternalErr(259, {op})
  30.188  
    31.1 --- a/source/error.e	Mon Dec 19 23:19:58 2011 -0300
    31.2 +++ b/source/error.e	Wed Dec 21 16:45:49 2011 -0300
    31.3 @@ -9,6 +9,10 @@
    31.4  	without type_check
    31.5  end ifdef
    31.6  
    31.7 +ifdef CRASH_ON_ERROR then
    31.8 +	include std/error.e
    31.9 +end ifdef
   31.10 +
   31.11  include std/io.e
   31.12  include std/text.e
   31.13  
   31.14 @@ -294,7 +298,7 @@
   31.15  		close(TempErrFile)
   31.16  		TempErrFile = -2
   31.17  		ifdef CRASH_ON_ERROR then
   31.18 -			display( call_stack() )
   31.19 +			crash("Crashing on compiler error for internal traceback")
   31.20  		end ifdef
   31.21  		Cleanup(1)
   31.22  	end if
   31.23 @@ -310,14 +314,19 @@
   31.24  --**
   31.25  -- Handles internal compile-time errors
   31.26  -- see RTInternal() for run-time internal errors
   31.27 -export procedure InternalErr(integer  msgno, object args = {})
   31.28 +export procedure InternalErr(object  msgno, object args = {})
   31.29  
   31.30  	sequence msg
   31.31  	if atom(args) then
   31.32  		args = {args}
   31.33  	end if
   31.34 -
   31.35 -	msg = GetMsgText(msgno, 1, args)
   31.36 +	
   31.37 +	if atom( msgno ) then
   31.38 +		msg = GetMsgText(msgno, 1, args)
   31.39 +	else
   31.40 +		msg = format(msgno, args)
   31.41 +	end if
   31.42 +	
   31.43  	if TRANSLATE then
   31.44  		screen_output(STDERR, GetMsgText(211, 1, {msg}))
   31.45  	else
    32.1 --- a/source/execute.e	Mon Dec 19 23:19:58 2011 -0300
    32.2 +++ b/source/execute.e	Wed Dec 21 16:45:49 2011 -0300
    32.3 @@ -20,11 +20,14 @@
    32.4  	without type_check
    32.5  end ifdef
    32.6  
    32.7 +include std/convert.e
    32.8 +include std/dll.e
    32.9 +include std/error.e
   32.10 +include std/io.e
   32.11  include std/os.e
   32.12  include std/pretty.e
   32.13 -include std/io.e
   32.14 +include std/text.e
   32.15  include std/types.e
   32.16 -include std/text.e
   32.17  
   32.18  include global.e
   32.19  include opnames.e
   32.20 @@ -35,6 +38,7 @@
   32.21  include mode.e as mode
   32.22  include intinit.e
   32.23  include coverage.e
   32.24 +include emit.e
   32.25  
   32.26  include std/machine.e as dep
   32.27  without inline
   32.28 @@ -598,19 +602,24 @@
   32.29  
   32.30  procedure quit_after_error()
   32.31  -- final termination
   32.32 +puts(1, "quit!\n")
   32.33  	write_coverage_db()
   32.34  	
   32.35 +	ifdef CRASH_ON_ERROR then
   32.36 +		crash("crashing on error")
   32.37 +	end ifdef
   32.38 +	
   32.39  	ifdef WINDOWS then
   32.40  		if not batch_job and not test_only then
   32.41  			puts(2, "\nPress Enter...\n")
   32.42  			getc(0)
   32.43  		end if
   32.44  	end ifdef
   32.45 -
   32.46 +	
   32.47  	abort(1)
   32.48  end procedure
   32.49  
   32.50 -procedure RTFatalType(integer x)
   32.51 +procedure RTFatalType(integer x, integer member = 0 )
   32.52  -- handle a fatal run-time type-check error
   32.53  	sequence msg, v
   32.54  	sequence vname
   32.55 @@ -624,6 +633,9 @@
   32.56  		vname = "inlined variable"
   32.57  	end if
   32.58  	msg = sprintf("type_check failure, %s is ", {vname})
   32.59 +	if member then
   32.60 +		a = member
   32.61 +	end if
   32.62  	v = sprint(val[a])
   32.63  	if length(v) > 70 - length(vname) then
   32.64  		v = v[1..70 - length(vname)]
   32.65 @@ -1161,7 +1173,7 @@
   32.66  						slist[a][LINE],
   32.67  						line})
   32.68  		trace_line += 1
   32.69 -		if trace_line >= 5000 then
   32.70 +		if trace_line >= trace_lines then
   32.71  			-- wrap around to start of file
   32.72  			trace_line = 0
   32.73  			one_trace_line("")
   32.74 @@ -1463,6 +1475,31 @@
   32.75  	pc += 3
   32.76  end procedure
   32.77  
   32.78 +procedure opMEMSTRUCT_ASSIGN()
   32.79 +	atom pointer = val[Code[pc+1]]
   32.80 +	integer struct_sym = Code[pc+2]
   32.81 +	object source_val = val[Code[pc+3]]
   32.82 +	integer deref_ptr = Code[pc+4]
   32.83 +	integer tok = sym_token( struct_sym )
   32.84 +	if SymTab[struct_sym][S_MEM_POINTER] then
   32.85 +		if deref_ptr then
   32.86 +			pointer = peek_pointer( pointer )
   32.87 +		else
   32.88 +			tok = MS_MEMBER
   32.89 +		end if
   32.90 +	end if
   32.91 +	
   32.92 +	switch tok do
   32.93 +		case MEMSTRUCT then
   32.94 +			write_memstruct( pointer, struct_sym, source_val )
   32.95 +		case MEMUNION then
   32.96 +			poke( pointer, source_val & repeat( 0, SymTab[struct_sym][S_MEM_SIZE] - length( source_val ) ) )
   32.97 +		case else
   32.98 +			poke_member( pointer, struct_sym, source_val, deref_ptr )
   32.99 +	end switch
  32.100 +	pc += 5
  32.101 +end procedure
  32.102 +
  32.103  procedure opELSE()
  32.104  -- ELSE, EXIT, ENDWHILE
  32.105  	pc = Code[pc+1]
  32.106 @@ -2002,6 +2039,16 @@
  32.107  	pc += 1
  32.108  end procedure
  32.109  
  32.110 +procedure opMEM_TYPE_CHECK()
  32.111 +-- type check for a user-defined type
  32.112 +-- this always follows a type-call
  32.113 +	if val[Code[pc-1]] = 0 then
  32.114 +		RTFatalType(pc + 1, Code[pc - 2])
  32.115 +	end if
  32.116 +	pc += 2
  32.117 +end procedure
  32.118 +
  32.119 +
  32.120  procedure kill_temp( symtab_index sym )
  32.121  	if sym_mode( sym ) = M_TEMP then
  32.122  		val[sym] = NOVALUE
  32.123 @@ -2227,6 +2274,29 @@
  32.124  	pc += 4
  32.125  end procedure
  32.126  
  32.127 +procedure opMEMSTRUCT_ASSIGN_OP()
  32.128 +	atom pointer = val[Code[pc+1]]
  32.129 +	if Code[pc+4] then
  32.130 +		pointer = peek_pointer( pointer )
  32.131 +	end if
  32.132 +	atom v = peek_member( pointer, Code[pc+2], , -1 )
  32.133 +	atom x = val[Code[pc+3]]
  32.134 +	
  32.135 +	switch Code[pc] do
  32.136 +		case MEMSTRUCT_PLUS then
  32.137 +			v += x
  32.138 +		case MEMSTRUCT_MINUS then
  32.139 +			v -= x
  32.140 +		case MEMSTRUCT_DIVIDE then
  32.141 +			v /= x
  32.142 +		case MEMSTRUCT_MULTIPLY then
  32.143 +			v *= x
  32.144 +	end switch
  32.145 +	
  32.146 +	poke_member( pointer, Code[pc+2], v, -1 )
  32.147 +	pc += 5
  32.148 +end procedure
  32.149 +
  32.150  procedure opPLUS()
  32.151  -- PLUS, PLUS_I
  32.152  	a = Code[pc+1]
  32.153 @@ -3071,6 +3141,14 @@
  32.154  	val[target] = peek8s(val[a])
  32.155  	pc += 3
  32.156  end procedure
  32.157 +
  32.158 +procedure opPEEK_POINTER()
  32.159 +	a = Code[pc+1]
  32.160 +	target = Code[pc+2]
  32.161 +	val[target] = peek_pointer(val[a])
  32.162 +	pc += 3
  32.163 +end procedure
  32.164 +
  32.165  procedure opPEEK_STRING()
  32.166  	a = Code[pc+1]
  32.167  	target = Code[pc+2]
  32.168 @@ -3095,10 +3173,394 @@
  32.169  procedure opSIZEOF()
  32.170  	a = Code[pc+1]
  32.171  	b = Code[pc+2]
  32.172 -	val[b] = sizeof( val[a] )
  32.173 +	integer id = sym_token( a )
  32.174 +	switch id do
  32.175 +		case MEMSTRUCT, MEMUNION, MS_MEMBER, MEMTYPE then
  32.176 +			val[b] = SymTab[a][S_MEM_SIZE]
  32.177 +		case MS_CHAR       then val[b] = sizeof( char )
  32.178 +		case MS_SHORT      then val[b] = sizeof( short )
  32.179 +		case MS_INT        then val[b] = sizeof( int )
  32.180 +		case MS_LONG       then val[b] = sizeof( long )
  32.181 +		case MS_LONGLONG   then val[b] = sizeof( long long )
  32.182 +		case MS_OBJECT     then val[b] = sizeof( object ) 
  32.183 +		case MS_FLOAT      then val[b] = sizeof( float )
  32.184 +		case MS_DOUBLE     then val[b] = sizeof( double )
  32.185 +		case MS_LONGDOUBLE then val[b] = sizeof( long double )
  32.186 +		case MS_EUDOUBLE   then val[b] = sizeof( eudouble )
  32.187 +		case else
  32.188 +			val[b] = sizeof( val[a] )
  32.189 +	end switch
  32.190 +	
  32.191  	pc += 3
  32.192  end procedure
  32.193  
  32.194 +procedure opOFFSETOF()
  32.195 +	a = Code[pc+1]
  32.196 +	b = Code[pc+2]
  32.197 +	val[b] = SymTab[a][S_MEM_OFFSET]
  32.198 +	pc += 3
  32.199 +end procedure
  32.200 +
  32.201 +procedure opADDRESSOF()
  32.202 +	a = Code[pc+1]
  32.203 +	b = Code[pc+2]
  32.204 +	val[b] = val[a]
  32.205 +	pc += 3
  32.206 +end procedure
  32.207 +
  32.208 +function mem_access( integer member_count, atom ptr )
  32.209 +	
  32.210 +	b = pc + 2 + member_count -- the last member
  32.211 +	
  32.212 +	for i = pc+3 to b do
  32.213 +		ptr += SymTab[Code[i]][S_MEM_OFFSET]
  32.214 +		if SymTab[Code[i]][S_MEM_POINTER] and i < b then
  32.215 +			ptr = peek_pointer( ptr )
  32.216 +		end if
  32.217 +	end for
  32.218 +	return ptr
  32.219 +end function
  32.220 +
  32.221 +integer memaccess = 0
  32.222 +procedure opARRAY_ACCESS()
  32.223 +	-- pc+1 number of accesses
  32.224 +	-- pc+2 pointer to memstruct
  32.225 +	-- pc+2 .. pc+n+2 member syms for access
  32.226 +	-- pc+n+3 subscript sym
  32.227 +	-- pc+n+4 target for pointer
  32.228 +	memaccess = ARRAY_ACCESS
  32.229 +	integer
  32.230 +		member_count  = Code[pc+1],
  32.231 +		subscript_sym = Code[pc + member_count + 3],
  32.232 +		array_sym     = Code[pc + member_count + 2]
  32.233 +	atom ptr = mem_access( member_count, val[Code[pc+2]] )
  32.234 +	
  32.235 +	integer element_size = SymTab[array_sym][S_MEM_SIZE]
  32.236 +	if SymTab[array_sym][S_MEM_ARRAY] then
  32.237 +		element_size /= SymTab[array_sym][S_MEM_ARRAY]
  32.238 +	end if
  32.239 +	ptr += val[subscript_sym] * element_size
  32.240 +	val[Code[pc + member_count + 4]] = ptr
  32.241 +	
  32.242 +	pc += member_count + 5
  32.243 +end procedure
  32.244 +
  32.245 +procedure opMEMSTRUCT_ACCESS()
  32.246 +	-- pc+1 number of accesses
  32.247 +	-- pc+2 pointer to memstruct
  32.248 +	-- pc+2 .. pc+n+2 member syms for access
  32.249 +	-- pc+n+3 target for pointer
  32.250 +	memaccess = MEMSTRUCT_ACCESS
  32.251 +	integer
  32.252 +		member_count  = Code[pc+1]
  32.253 +	atom ptr = mem_access( member_count, val[Code[pc+2]] )
  32.254 +	val[Code[pc + member_count + 3]] = ptr
  32.255 +	pc += member_count + 4
  32.256 +end procedure
  32.257 +
  32.258 +procedure opMEMSTRUCT_ARRAY()
  32.259 +	-- pc+1 pointer
  32.260 +	-- pc+2 member sym
  32.261 +	-- pc+3 subscript
  32.262 +	-- pc+4 target
  32.263 +	atom    ptr  = val[Code[pc+1]]
  32.264 +	integer size = SymTab[Code[pc+2]][S_MEM_SIZE]
  32.265 +	ptr += val[Code[pc+3]] * size
  32.266 +	val[Code[pc+4]] = ptr
  32.267 +	pc += 5
  32.268 +end procedure
  32.269 +
  32.270 +procedure poke_member_value( atom pointer, integer data_type, object value )
  32.271 +	switch data_type do
  32.272 +		case MS_CHAR then
  32.273 +			poke( pointer, value )
  32.274 +		case MS_SHORT then
  32.275 +			poke2( pointer, value )
  32.276 +		case MS_INT then
  32.277 +			poke4( pointer, value )
  32.278 +		case MS_LONG then
  32.279 +			ifdef WINDOWS then
  32.280 +				poke4( pointer, value )
  32.281 +			elsedef
  32.282 +				poke_pointer( pointer, value )
  32.283 +			end ifdef
  32.284 +		case MS_LONGLONG then
  32.285 +			poke8( pointer, value )
  32.286 +		case MS_OBJECT then
  32.287 +			poke_pointer( pointer, value )
  32.288 +		case MS_FLOAT then
  32.289 +			poke( pointer, atom_to_float32( value ) )
  32.290 +		case MS_DOUBLE then
  32.291 +			poke( pointer, atom_to_float64( value ) )
  32.292 +		case MS_LONGDOUBLE then
  32.293 +			poke( pointer, atom_to_float80( value ) )
  32.294 +		case MS_EUDOUBLE then
  32.295 +			if sizeof( C_POINTER ) = 4 then
  32.296 +				poke( pointer, atom_to_float64( value ) )
  32.297 +			else
  32.298 +				poke( pointer, atom_to_float80( value ) )
  32.299 +			end if
  32.300 +		case else
  32.301 +			-- just return the struct in bytes
  32.302 +			RTFatal( "Error assigning to a memstruct -- can only assign primitive data members" )
  32.303 +	end switch
  32.304 +end procedure
  32.305 +
  32.306 +procedure poke_member( atom pointer, integer sym, object value, integer deref_ptr = 0 )
  32.307 +	integer data_type = SymTab[sym][S_TOKEN]
  32.308 +	integer signed    = SymTab[sym][S_MEM_SIGNED]
  32.309 +	
  32.310 +	if SymTab[sym][S_MEM_POINTER] and not deref_ptr then
  32.311 +		data_type = MS_OBJECT
  32.312 +		signed    = 0
  32.313 +	end if
  32.314 +	
  32.315 +	if SymTab[sym][S_MEM_ARRAY] then
  32.316 +		integer array_length = SymTab[sym][S_MEM_ARRAY]
  32.317 +		integer max = array_length
  32.318 +		integer size = SymTab[sym][S_MEM_SIZE] / array_length
  32.319 +		if memaccess = ARRAY_ACCESS then
  32.320 +			poke_member_value( pointer, data_type, value )
  32.321 +		else
  32.322 +			if array_length < length( value ) then
  32.323 +				max = length( value )
  32.324 +			end if
  32.325 +			for i = 1 to max do
  32.326 +				poke_member_value( pointer, data_type, value[i] )
  32.327 +				pointer += size
  32.328 +			end for
  32.329 +			for i = max + 1 to array_length do
  32.330 +				poke_member_value( pointer, data_type, 0 )
  32.331 +				pointer += size
  32.332 +			end for
  32.333 +		end if
  32.334 +	else
  32.335 +		poke_member_value( pointer, data_type, value )
  32.336 +	end if
  32.337 +	
  32.338 +end procedure
  32.339 +
  32.340 +procedure write_memstruct( atom pointer, integer sym, object value )
  32.341 +	if atom( value ) then
  32.342 +		value = {value}
  32.343 +	end if
  32.344 +	
  32.345 +	integer member = SymTab[sym][S_MEM_NEXT]
  32.346 +	
  32.347 +	for i = 1 to length( value ) do
  32.348 +		
  32.349 +		if not member then
  32.350 +			exit
  32.351 +		end if
  32.352 +		poke_member( pointer + SymTab[member][S_MEM_OFFSET], member, value[i] )
  32.353 +		
  32.354 +		member = SymTab[member][S_MEM_NEXT]
  32.355 +		
  32.356 +	end for
  32.357 +	
  32.358 +	-- zero out the rest
  32.359 +	integer ix = length( value ) + 1
  32.360 +	while member do
  32.361 +		poke_member( pointer + SymTab[member][S_MEM_OFFSET], member, 0 )
  32.362 +		
  32.363 +		member = SymTab[member][S_MEM_NEXT]
  32.364 +	end while
  32.365 +end procedure
  32.366 +
  32.367 +--**
  32.368 +-- Peek a member value.
  32.369 +--
  32.370 +-- deref_ptr: Identifies if the pointer needs to be dereferenced if the member is a pointer.
  32.371 +-- If deref_ptr is 0, then the pointer value is assigned.
  32.372 +-- If deref_ptr is 1, then the pointer is dereferenced and the assignment of the actual type is done.
  32.373 +-- If deref_ptr is anything else, the pointer is assumed to already be dereferenced, and the
  32.374 +-- value is assigned as the member's data type, since the caller has already dereferenced the pointer.
  32.375 +function peek_member( atom pointer, integer sym, integer array_index = -1, integer deref_ptr = 0 )
  32.376 +	integer data_type = SymTab[sym][S_TOKEN]
  32.377 +	integer signed    = SymTab[sym][S_MEM_SIGNED]
  32.378 +	
  32.379 +	if SymTab[sym][S_MEM_POINTER] then
  32.380 +		if deref_ptr = 1 then
  32.381 +			-- result of ptr.MEMSTRUCT.member.*
  32.382 +			pointer = peek_pointer( pointer )
  32.383 +		elsif deref_ptr = 0 then
  32.384 +			-- just return the pointer itself
  32.385 +			data_type = MS_OBJECT
  32.386 +			signed    = 0
  32.387 +		end if
  32.388 +	
  32.389 +	elsif array_index != -1 then
  32.390 +		integer element_size = SymTab[sym][S_MEM_SIZE] / SymTab[sym][S_MEM_ARRAY]
  32.391 +		pointer += element_size * array_index
  32.392 +	
  32.393 +	elsif SymTab[sym][S_MEM_ARRAY] then
  32.394 +		sequence s = repeat( 0, SymTab[sym][S_MEM_ARRAY] )
  32.395 +		for i = 1 to SymTab[sym][S_MEM_ARRAY] do
  32.396 +			s[i] = peek_member( pointer, sym, i-1)
  32.397 +		end for
  32.398 +		return s
  32.399 +	end if
  32.400 +	
  32.401 +	switch data_type do
  32.402 +		case MS_CHAR then
  32.403 +			if signed then
  32.404 +				return peeks( pointer )
  32.405 +			else
  32.406 +				return peek( pointer )
  32.407 +			end if
  32.408 +		case MS_SHORT then
  32.409 +			if signed then
  32.410 +				return peek2s( pointer )
  32.411 +			else
  32.412 +				return peek2u( pointer )
  32.413 +			end if
  32.414 +		case MS_INT then
  32.415 +			if signed then
  32.416 +				return peek4s( pointer )
  32.417 +			else
  32.418 +				return peek4u( pointer )
  32.419 +			end if
  32.420 +		case MS_LONG then
  32.421 +			ifdef WINDOWS then
  32.422 +				if signed then
  32.423 +					return peek4s( pointer )
  32.424 +				else
  32.425 +					return peek4u( pointer )
  32.426 +				end if
  32.427 +			elsedef
  32.428 +				if sizeof( C_LONG ) = 4 then
  32.429 +					if signed then
  32.430 +						return peek4s( pointer )
  32.431 +					else
  32.432 +						return peek4u( pointer )
  32.433 +					end if
  32.434 +				else
  32.435 +					if signed then
  32.436 +						return peek8s( pointer )
  32.437 +					else
  32.438 +						return peek8u( pointer )
  32.439 +					end if
  32.440 +				end if
  32.441 +			end ifdef
  32.442 +		case MS_LONGLONG then
  32.443 +			if signed then
  32.444 +				return peek8s( pointer )
  32.445 +			else
  32.446 +				return peek8u( pointer )
  32.447 +			end if
  32.448 +		case MS_OBJECT then
  32.449 +			if sizeof( C_POINTER ) = 4 then
  32.450 +				if signed then
  32.451 +					return peek4s( pointer )
  32.452 +				else
  32.453 +					return peek4u( pointer )
  32.454 +				end if
  32.455 +			else
  32.456 +				if signed then
  32.457 +					return peek8s( pointer )
  32.458 +				else
  32.459 +					return peek8u( pointer )
  32.460 +				end if
  32.461 +			end if
  32.462 +		case MS_FLOAT then
  32.463 +			return float32_to_atom( peek( { pointer, 4 } ) )
  32.464 +		case MS_DOUBLE then
  32.465 +			return float64_to_atom( peek( { pointer, 8 } ) )
  32.466 +		case MS_LONGDOUBLE then
  32.467 +			return float80_to_atom( peek( { pointer, 10 } ) )
  32.468 +		case MS_EUDOUBLE then
  32.469 +			if sizeof( C_POINTER ) = 4 then
  32.470 +				return float64_to_atom( peek( { pointer, 8 } ) )
  32.471 +			else
  32.472 +				return float80_to_atom( peek( { pointer, 10 } ) )
  32.473 +			end if
  32.474 +		case else
  32.475 +			-- just return the struct in bytes
  32.476 +			return read_member( pointer, sym )
  32.477 +	end switch
  32.478 +end function
  32.479 +
  32.480 +function read_memstruct( atom pointer, symtab_pointer member_sym )
  32.481 +	sequence s = {}
  32.482 +	if sym_token( member_sym ) != MEMSTRUCT then
  32.483 +		-- we want to walk the actual struct
  32.484 +		member_sym = SymTab[member_sym][S_MEM_STRUCT]
  32.485 +	end if
  32.486 +	while member_sym with entry do
  32.487 +		s = append( s, peek_member( pointer + SymTab[member_sym][S_MEM_OFFSET], member_sym ) )
  32.488 +	entry
  32.489 +		member_sym = SymTab[member_sym][S_MEM_NEXT]
  32.490 +	end while
  32.491 +	return s
  32.492 +end function
  32.493 +
  32.494 +function read_memunion( atom pointer, symtab_pointer member_sym )
  32.495 +	return peek( { pointer, SymTab[member_sym][S_MEM_SIZE] } )
  32.496 +end function
  32.497 +
  32.498 +function read_member( atom pointer, symtab_index sym )
  32.499 +
  32.500 +	symtab_pointer member_sym = sym
  32.501 +	integer tid = sym_token( sym )
  32.502 +	if tid >= MS_SIGNED and tid <= MS_OBJECT then
  32.503 +		-- simple serialization of primitives...
  32.504 +		return peek_member( pointer, sym )
  32.505 +	end if
  32.506 +	
  32.507 +	integer member_token = sym_token( member_sym )
  32.508 +	if member_token = MEMSTRUCT then
  32.509 +		return read_memstruct( pointer, member_sym )
  32.510 +	
  32.511 +	elsif member_token = MEMUNION then
  32.512 +		return read_memunion( pointer, member_sym )
  32.513 +	
  32.514 +	else
  32.515 +		member_token = SymTab[SymTab[member_sym][S_MEM_STRUCT]][S_TOKEN]
  32.516 +		if member_token = MEMSTRUCT then
  32.517 +			return read_memstruct( pointer, member_sym )
  32.518 +		
  32.519 +		elsif member_token = MEMUNION then
  32.520 +			return read_memunion( pointer, member_sym )
  32.521 +		else
  32.522 +			RTFatal( "Cannot serialize a: " & LexName( member_token ) )
  32.523 +		end if
  32.524 +	end if
  32.525 +end function
  32.526 +
  32.527 +procedure opMEMSTRUCT_READ()
  32.528 +	atom pointer = val[Code[pc+1]]
  32.529 +	val[Code[pc+3]] = read_member( pointer, Code[pc+2] )
  32.530 +	pc += 4
  32.531 +end procedure
  32.532 +
  32.533 +procedure opPEEK_ARRAY()
  32.534 +	-- pc+1 pointer
  32.535 +	-- pc+2 member sym
  32.536 +	-- pc+3 subscript
  32.537 +	-- pc+4 target
  32.538 +	atom 
  32.539 +		member_sym = Code[pc+2],
  32.540 +		ptr        = val[Code[pc+1]] + SymTab[member_sym][S_MEM_OFFSET],
  32.541 +		subscript  = val[Code[pc+3]]
  32.542 +	val[Code[pc+4]] = peek_member( ptr, member_sym, subscript )
  32.543 +	pc += 5
  32.544 +end procedure
  32.545 +
  32.546 +procedure opPEEK_MEMBER()
  32.547 +	-- pc+1 pointer
  32.548 +	-- pc+2 member
  32.549 +	-- pc+3 deref ptr
  32.550 +	-- pc+4 target
  32.551 +	
  32.552 +	atom pointer = val[Code[pc+1]]
  32.553 +	a = Code[pc+2]
  32.554 +	target = Code[pc+4]
  32.555 +	
  32.556 +	val[target] = peek_member( pointer, a, , Code[pc+3] )
  32.557 +	
  32.558 +	pc += 5
  32.559 +end procedure
  32.560 +
  32.561  procedure opPOKE()
  32.562  	a = Code[pc+1]
  32.563  	b = Code[pc+2]
  32.564 @@ -3120,6 +3582,14 @@
  32.565  	pc += 3
  32.566  end procedure
  32.567  
  32.568 +procedure opPOKE_POINTER()
  32.569 +	a = Code[pc+1]
  32.570 +	b = Code[pc+2]
  32.571 +	poke_pointer(val[a], val[b])
  32.572 +	pc += 3
  32.573 +end procedure
  32.574 +
  32.575 +
  32.576  procedure opPOKE2()
  32.577  	a = Code[pc+1]
  32.578  	b = Code[pc+2]
  32.579 @@ -3981,7 +4451,7 @@
  32.580  
  32.581  			case EQUALS then
  32.582  				opEQUALS()
  32.583 -
  32.584 +			
  32.585  			case EQUALS_IFW, EQUALS_IFW_I then
  32.586  				opEQUALS_IFW()
  32.587  
  32.588 @@ -4212,10 +4682,10 @@
  32.589  				opPOKE8()
  32.590  			
  32.591  			case POKE_POINTER then
  32.592 -				opPOKE4()
  32.593 +				opPOKE_POINTER()
  32.594  			
  32.595  			case PEEK_POINTER then
  32.596 -				opPEEK4U()
  32.597 +				opPEEK_POINTER()
  32.598  				
  32.599  			case POSITION then
  32.600  				opPOSITION()
  32.601 @@ -4378,6 +4848,9 @@
  32.602  
  32.603  			case TYPE_CHECK then
  32.604  				opTYPE_CHECK()
  32.605 +				
  32.606 +			case MEM_TYPE_CHECK then
  32.607 +				opMEM_TYPE_CHECK()
  32.608  
  32.609  			case UMINUS then
  32.610  				opUMINUS()
  32.611 @@ -4413,6 +4886,35 @@
  32.612  				
  32.613  			case SIZEOF then
  32.614  				opSIZEOF()
  32.615 +				
  32.616 +			case MEMSTRUCT_ACCESS then
  32.617 +				opMEMSTRUCT_ACCESS()
  32.618 +			
  32.619 +			case ARRAY_ACCESS then
  32.620 +				opARRAY_ACCESS()
  32.621 +			
  32.622 +			case MEMSTRUCT_ARRAY then
  32.623 +				opMEMSTRUCT_ARRAY()
  32.624 +			
  32.625 +			case PEEK_ARRAY then
  32.626 +				opPEEK_ARRAY()
  32.627 +			case PEEK_MEMBER then
  32.628 +				opPEEK_MEMBER()
  32.629 +			
  32.630 +			case MEMSTRUCT_READ then
  32.631 +				opMEMSTRUCT_READ()
  32.632 +			
  32.633 +			case MEMSTRUCT_ASSIGN then
  32.634 +				opMEMSTRUCT_ASSIGN()
  32.635 +			
  32.636 +			case MEMSTRUCT_PLUS, MEMSTRUCT_MINUS, MEMSTRUCT_MULTIPLY, MEMSTRUCT_DIVIDE then
  32.637 +				opMEMSTRUCT_ASSIGN_OP()
  32.638 +			
  32.639 +			case ADDRESSOF then
  32.640 +				opADDRESSOF()
  32.641 +			
  32.642 +			case OFFSETOF then
  32.643 +				opOFFSETOF()
  32.644  
  32.645  			case else
  32.646  				RTFatal( sprintf("Unknown opcode: %d", op ) )
    33.1 --- a/source/fwdref.e	Mon Dec 19 23:19:58 2011 -0300
    33.2 +++ b/source/fwdref.e	Wed Dec 21 16:45:49 2011 -0300
    33.3 @@ -23,7 +23,7 @@
    33.4  include reswords.e
    33.5  include block.e
    33.6  include emit.e
    33.7 -
    33.8 +include memstruct.e
    33.9  
   33.10  -- Tracking forward references
   33.11  sequence 
   33.12 @@ -31,7 +31,8 @@
   33.13  	active_subprogs     = {},
   33.14  	active_references   = {},
   33.15  	toplevel_references = {},
   33.16 -	inactive_references = {}
   33.17 +	inactive_references = {},
   33.18 +	$
   33.19  
   33.20  
   33.21  enum
   33.22 @@ -171,6 +172,9 @@
   33.23  end procedure
   33.24  
   33.25  export procedure add_data( integer ref, object data )
   33.26 +	if atom( forward_references[ref][FR_DATA] ) then
   33.27 +		forward_references[ref][FR_DATA] = { forward_references[ref][FR_DATA] }
   33.28 +	end if
   33.29  	forward_references[ref][FR_DATA] = append( forward_references[ref][FR_DATA], data )
   33.30  end procedure
   33.31  
   33.32 @@ -385,6 +389,98 @@
   33.33  	current_file_no = fr[FR_FILE]
   33.34  end procedure
   33.35  
   33.36 +
   33.37 +procedure patch_forward_msmember( token tok, integer ref )
   33.38 +	sequence fr = forward_references[ref]
   33.39 +	symtab_index sym = tok[T_SYM]
   33.40 +	
   33.41 +	if fr[FR_OP] = MEMSTRUCT_DECL then
   33.42 +		symtab_index member = fr[FR_DATA]
   33.43 +		switch tok[T_ID] do
   33.44 +			case MEMSTRUCT_DECL, MEMSTRUCT then
   33.45 +				-- a forward reference inside a declaration
   33.46 +				SymTab[member][S_MEM_STRUCT] = sym
   33.47 +			case  MEMTYPE then
   33.48 +				-- memtype alias
   33.49 +				integer real_type_sym = SymTab[sym][S_MEM_PARENT]
   33.50 +				SymTab[member][S_MEM_STRUCT] = real_type_sym
   33.51 +				SymTab[member][S_TOKEN]      = sym_token( real_type_sym )
   33.52 +			case else
   33.53 +				-- ?? not handled...leave it unreferenced 
   33.54 +				return
   33.55 +		end switch
   33.56 +		
   33.57 +		SymTab[member][S_SCOPE]    = SC_MEMSTRUCT
   33.58 +		SymTab[member][S_MEM_SIZE] = SymTab[sym][S_MEM_SIZE]
   33.59 +		
   33.60 +		if not SymTab[member][S_MEM_POINTER] then
   33.61 +			symtab_index parent_sym = SymTab[member][S_MEM_PARENT]
   33.62 +			recalculate_size( parent_sym )
   33.63 +		end if
   33.64 +		resolved_reference( ref )
   33.65 +	else
   33.66 +		
   33.67 +		InternalErr( sprintf("Unhandled memstruct member fwd ref op: %d", tok[T_ID] ) )
   33.68 +	end if
   33.69 +	
   33.70 +end procedure
   33.71 +
   33.72 +procedure patch_forward_memstruct( token tok, integer ref )
   33.73 +	sequence fr = forward_references[ref]
   33.74 +	symtab_index sym = tok[T_SYM]
   33.75 +	
   33.76 +	switch fr[FR_OP] do
   33.77 +		case MEMSTRUCT_DECL then
   33.78 +			-- need to check the size
   33.79 +			
   33.80 +			if sym_token( sym ) = MEMTYPE then
   33.81 +				recalculate_size( SymTab[sym][S_MEM_PARENT] )
   33.82 +			end if
   33.83 +			if recalculate_size( sym )> 0 then
   33.84 +				resolved_reference( ref )
   33.85 +			end if
   33.86 +		
   33.87 +		case VARIABLE then
   33.88 +			patch_var_use( ref, fr, sym, 1 )
   33.89 +		
   33.90 +		case MEMSTRUCT_ACCESS, SIZEOF, OFFSETOF, ADDRESSOF then
   33.91 +			integer pc = fr[FR_PC]
   33.92 +			set_code( ref )
   33.93 +			integer rx = find( -ref, Code, pc )
   33.94 +			if rx then
   33.95 +				-- these aren't always emitted
   33.96 +				Code[rx] = sym
   33.97 +			end if
   33.98 +			resolved_reference( ref )
   33.99 +			
  33.100 +			if fr[FR_OP] = SIZEOF then
  33.101 +				break
  33.102 +			end if
  33.103 +			
  33.104 +			for i = 2 to length( fr[FR_DATA] ) do
  33.105 +				-- clean up any members tied to this
  33.106 +				integer m_ref = fr[FR_DATA][i]
  33.107 +				rx = find( -m_ref, Code, pc )
  33.108 +				if rx then
  33.109 +					-- look it up
  33.110 +					integer m_sym = resolve_members( forward_references[m_ref][FR_DATA], sym )
  33.111 +					if m_sym then
  33.112 +						Code[rx] = m_sym
  33.113 +						resolved_reference( m_ref )
  33.114 +					end if
  33.115 +				else
  33.116 +					resolved_reference( m_ref )
  33.117 +				end if
  33.118 +			end for
  33.119 +			reset_code()
  33.120 +	
  33.121 +			case else
  33.122 +			-- TODO: ??
  33.123 +			CompileErr( "Unimplemented: patching forward memstruct with op - %d\n", fr[FR_OP] )
  33.124 +	end switch
  33.125 +	
  33.126 +end procedure
  33.127 +
  33.128  procedure patch_forward_variable( token tok, integer ref )
  33.129  -- forward reference for a variable
  33.130  	sequence fr = forward_references[ref]
  33.131 @@ -406,6 +502,20 @@
  33.132  		SymTab[sym][S_USAGE] = or_bits( U_READ, SymTab[sym][S_USAGE] )
  33.133  	end if
  33.134  	
  33.135 +	patch_var_use( ref, fr, sym )
  33.136 +	
  33.137 +end procedure
  33.138 +
  33.139 +procedure patch_forward_init_check( token tok, integer ref )
  33.140 +-- forward reference for a variable
  33.141 +	sequence fr = forward_references[ref]
  33.142 +	set_code( ref )
  33.143 +	Code[fr[FR_PC]+1] = tok[T_SYM]
  33.144 +	resolved_reference( ref )
  33.145 +	reset_code()
  33.146 +end procedure
  33.147 +
  33.148 +procedure patch_var_use( integer ref, sequence fr, integer sym, integer remove_init_check = 0 )
  33.149  	set_code( ref )
  33.150  	integer pc = fr[FR_PC]
  33.151  	if pc < 1 then
  33.152 @@ -421,19 +531,16 @@
  33.153  		end while
  33.154  		resolved_reference( ref )
  33.155  	end if
  33.156 +	
  33.157 +	if remove_init_check then
  33.158 +		if Code[pc] = GLOBAL_INIT_CHECK then
  33.159 +			replace_code( {}, pc, pc+1, fr[FR_SUBPROG])
  33.160 +		end if
  33.161 +	end if
  33.162 +		
  33.163  	reset_code()
  33.164  end procedure
  33.165  
  33.166 -procedure patch_forward_init_check( token tok, integer ref )
  33.167 --- forward reference for a variable
  33.168 -	sequence fr = forward_references[ref]
  33.169 -	set_code( ref )
  33.170 -	Code[fr[FR_PC]+1] = tok[T_SYM]
  33.171 -	resolved_reference( ref )
  33.172 -	reset_code()
  33.173 -end procedure
  33.174 -
  33.175 -
  33.176  function expected_name( integer id )
  33.177  	
  33.178  	switch id with fallthru do
  33.179 @@ -456,13 +563,22 @@
  33.180  
  33.181  procedure patch_forward_type( token tok, integer ref )
  33.182  	sequence fr = forward_references[ref]
  33.183 -	sequence syms = fr[FR_DATA]
  33.184 -	for i = 2 to length( syms ) do
  33.185 -		SymTab[syms[i]][S_VTYPE] = tok[T_SYM]
  33.186 -		if TRANSLATE then
  33.187 -			SymTab[syms[i]][S_GTYPE] = CompileType(tok[T_SYM])
  33.188 +	if sequence( fr[FR_DATA] ) then
  33.189 +		sequence syms = fr[FR_DATA]
  33.190 +		
  33.191 +		if fr[FR_OP] = MEMSTRUCT then
  33.192 +			for i = 2 to length( syms ) do
  33.193 +				SymTab[syms[i]][S_MEM_TYPE] = tok[T_SYM]
  33.194 +			end for
  33.195 +		else
  33.196 +			for i = 2 to length( syms ) do
  33.197 +				SymTab[syms[i]][S_VTYPE] = tok[T_SYM]
  33.198 +				if TRANSLATE then
  33.199 +					SymTab[syms[i]][S_GTYPE] = CompileType(tok[T_SYM])
  33.200 +				end if
  33.201 +			end for
  33.202  		end if
  33.203 -	end for
  33.204 +	end if
  33.205  	resolved_reference( ref )
  33.206  end procedure
  33.207  
  33.208 @@ -511,6 +627,23 @@
  33.209  	resolved_reference( ref )
  33.210  end procedure
  33.211  
  33.212 +procedure patch_forward_mem_type_check( token tok, integer ref )
  33.213 +	integer which_type = tok[T_SYM]
  33.214 +	sequence fr = forward_references[ref]
  33.215 +	set_code( ref )
  33.216 +	
  33.217 +	integer 
  33.218 +		c   = NewTempSym(),
  33.219 +		pc  = fr[FR_PC],
  33.220 +		var = Code[pc+1]
  33.221 +	
  33.222 +	SymTab[fr[FR_SUBPROG]][S_STACK_SPACE] += 1
  33.223 +	replace_code( { PROC, which_type, var, c }, pc, pc+2, fr[FR_SUBPROG] )
  33.224 +	
  33.225 +	reset_code()
  33.226 +	
  33.227 +	resolved_reference( ref )
  33.228 +end procedure
  33.229  
  33.230  procedure patch_forward_type_check( token tok, integer ref )
  33.231  	sequence fr = forward_references[ref]
  33.232 @@ -739,9 +872,12 @@
  33.233  	forward_references[ref][FR_QUALIFIED] = get_qualified_fwd()
  33.234  	forward_references[ref][FR_OP]        = op
  33.235  	
  33.236 -	if op = GOTO then
  33.237 -		forward_references[ref][FR_DATA] = { sym }
  33.238 -	end if
  33.239 +	switch op do
  33.240 +		case GOTO then
  33.241 +			forward_references[ref][FR_DATA] = { sym }
  33.242 +		case GLOBAL_INIT_CHECK then
  33.243 +			forward_references[ref][FR_DATA] = sym
  33.244 +	end switch
  33.245  	
  33.246  	-- If we're recording tokens (for a default parameter), this ref will never 
  33.247  	-- get resolved.  So ignore it for now, and when someone actually calls
  33.248 @@ -768,7 +904,6 @@
  33.249  		end if
  33.250  		fwdref_count += 1
  33.251  	end if
  33.252 -	
  33.253  	return ref
  33.254  end function
  33.255  
  33.256 @@ -825,6 +960,9 @@
  33.257  					case CONSTANT, ENUM, VARIABLE then
  33.258  						patch_forward_variable( tok, ref )
  33.259  						break "fr_type"
  33.260 +					case MEMSTRUCT, MEMUNION then
  33.261 +						patch_forward_memstruct( tok, ref )
  33.262 +						break "fr_type"
  33.263  					case else
  33.264  						forward_error( tok, ref )
  33.265  				end switch
  33.266 @@ -843,6 +981,15 @@
  33.267  			
  33.268  			case GOTO then
  33.269  				patch_forward_goto( tok, ref )
  33.270 +			
  33.271 +			case MS_MEMBER then
  33.272 +				patch_forward_msmember( tok, ref )
  33.273 +			
  33.274 +			case MEMSTRUCT, MEMTYPE then
  33.275 +				patch_forward_memstruct( tok, ref )
  33.276 +			
  33.277 +			case MEM_TYPE_CHECK then
  33.278 +				patch_forward_mem_type_check( tok, ref )
  33.279  				
  33.280  			case else
  33.281  				-- ?? what is it?
  33.282 @@ -890,14 +1037,12 @@
  33.283  		if (length( active_subprogs[i] ) or length(toplevel_references[i])) 
  33.284  		and (i = current_file_no or finished_files[i] or unincluded_ok)
  33.285  		then
  33.286 -			
  33.287  			for j = length( active_references[i] ) to 1 by -1 do
  33.288  				errors &= resolve_file( active_references[i][j], report_errors, unincluded_ok )
  33.289  			end for
  33.290  			errors &= resolve_file( toplevel_references[i], report_errors, unincluded_ok )
  33.291  		end if
  33.292  	end for
  33.293 -		
  33.294  	if report_errors and length( errors ) then
  33.295  		sequence msg = ""
  33.296  		sequence errloc
  33.297 @@ -930,8 +1075,17 @@
  33.298  								end if		
  33.299  							else
  33.300  								-- unqualified
  33.301 -								errloc = sprintf("\t\'%s\' (%s:%d) has not been declared.\n", 
  33.302 -									{ref[FR_NAME], abbreviate_path(known_files[ref[FR_FILE]]), ref[FR_LINE]})
  33.303 +								if ref[FR_TYPE] = MEMTYPE then
  33.304 +									if SymTab[ref[FR_DATA]][S_MEM_SIZE] then
  33.305 +										continue
  33.306 +									else
  33.307 +										errloc = sprintf("\tthe size of \'%s\' (%s:%d) could not be determined.\n", 
  33.308 +											{ref[FR_NAME], abbreviate_path(known_files[ref[FR_FILE]]), ref[FR_LINE]})
  33.309 +									end if
  33.310 +								else
  33.311 +									errloc = sprintf("\t\'%s\' (%s:%d) has not been declared.\n", 
  33.312 +										{ref[FR_NAME], abbreviate_path(known_files[ref[FR_FILE]]), ref[FR_LINE]})
  33.313 +								end if
  33.314  							end if
  33.315  						case SC_MULTIPLY_DEFINED then
  33.316  							sequence syms = tok[THESE_GLOBALS] -- there should be no forward references in here.
  33.317 @@ -1019,6 +1173,8 @@
  33.318  	else
  33.319  		integer file = SymTab[shifting_sub][S_FILE_NO]
  33.320  		integer sp   = find( shifting_sub, active_subprogs[file] )
  33.321 -		shift_these( active_references[file][sp], pc, amount )
  33.322 +		if sp then
  33.323 +			shift_these( active_references[file][sp], pc, amount )
  33.324 +		end if
  33.325  	end if
  33.326  end procedure
    34.1 --- a/source/global.e	Mon Dec 19 23:19:58 2011 -0300
    34.2 +++ b/source/global.e	Wed Dec 21 16:45:49 2011 -0300
    34.3 @@ -156,6 +156,20 @@
    34.4  	                         -- external call, e.g. call to a DLL
    34.5  	S_HAS_DELETE = 54
    34.6  
    34.7 +-- for memstructs / memunions only
    34.8 +export constant
    34.9 +	S_MEM_SIZE    = 14 - get_backend() * 5,
   34.10 +	S_MEM_OFFSET  = 15 - get_backend() * 5,
   34.11 +	S_MEM_SIGNED  = 16 - get_backend() * 5,
   34.12 +	S_MEM_POINTER = 17 - get_backend() * 5,
   34.13 +	S_MEM_ARRAY   = 18 - get_backend() * 5,
   34.14 +	S_MEM_NEXT    = 19 - get_backend() * 5,
   34.15 +	S_MEM_STRUCT  = 20 - get_backend() * 5,  -- for embedded structs
   34.16 +	S_MEM_PARENT  = 21 - get_backend() * 5,
   34.17 +	S_MEM_TYPE    = 22 - get_backend() * 5,
   34.18 +	S_MEM_RECALC  = 23 - get_backend() * 5,
   34.19 +	$
   34.20 +
   34.21  export procedure print_sym(integer s)
   34.22  	printf(1,"[%d]:\n", {s} )
   34.23  	object s_obj = SymTab[s][S_OBJ]
   34.24 @@ -184,8 +198,9 @@
   34.25  	SIZEOF_ROUTINE_ENTRY = 30 + 25 * TRANSLATE,
   34.26  	SIZEOF_VAR_ENTRY     = 17 + 37 * TRANSLATE,
   34.27  	SIZEOF_BLOCK_ENTRY   = 19 + 35 * TRANSLATE,
   34.28 -	SIZEOF_TEMP_ENTRY    =  6 + 32 * TRANSLATE
   34.29 -
   34.30 +	SIZEOF_TEMP_ENTRY    =  6 + 32 * TRANSLATE,
   34.31 +	SIZEOF_MEMSTRUCT_ENTRY = 23 + 32 * TRANSLATE - 5 * get_backend(),
   34.32 +	$
   34.33  -- Permitted values for various symbol table fields
   34.34  
   34.35  -- MODE values:
   34.36 @@ -199,7 +214,8 @@
   34.37  	
   34.38  -- SCOPE values:
   34.39  export enum
   34.40 -	SC_LOOP_VAR=2,    -- "private" loop vars known within a single loop
   34.41 +	SC_NONE,
   34.42 +	SC_LOOP_VAR,    -- "private" loop vars known within a single loop
   34.43  	SC_PRIVATE,    -- private within subprogram
   34.44  	SC_GLOOP_VAR,   -- "global" loop var
   34.45  	SC_LOCAL,    -- local to the file
   34.46 @@ -210,7 +226,8 @@
   34.47  	SC_MULTIPLY_DEFINED,  -- global symbol defined in 2 or more files
   34.48  	SC_EXPORT,   -- visible to anyone that includes the file
   34.49  	SC_OVERRIDE, -- override an internal
   34.50 -	SC_PUBLIC    -- visible to any file that includes it, or via "public include"
   34.51 +	SC_PUBLIC,   -- visible to any file that includes it, or via "public include"
   34.52 +	SC_MEMSTRUCT
   34.53  
   34.54  -- USAGE values          -- how symbol has been used (1,2 can be OR'd)
   34.55  export enum
   34.56 @@ -366,7 +383,7 @@
   34.57  		end if
   34.58  		return TRUE
   34.59  	end if
   34.60 -	if FUNC <= t[T_ID] and t[T_ID] <= NAMESPACE then
   34.61 +	if FUNC <= t[T_ID] and t[T_ID] < LAST_TOKEN then
   34.62  		return TRUE
   34.63  	end if
   34.64  	return FALSE
   34.65 @@ -588,4 +605,4 @@
   34.66  	return x = -1 or symtab_index(x) or forward_reference(x)
   34.67  end type
   34.68  				
   34.69 -
   34.70 +export integer trace_lines = 500
    35.1 --- a/source/il.e	Mon Dec 19 23:19:58 2011 -0300
    35.2 +++ b/source/il.e	Wed Dec 21 16:45:49 2011 -0300
    35.3 @@ -46,6 +46,7 @@
    35.4  		{ "quiet",       0, GetMsgText(304, 0), { } },
    35.5  		{ "copyright",   0, GetMsgText(312, 0), { } },
    35.6  		{ "eudir",     0, GetMsgText(328,0), { HAS_PARAMETER, "dir" } },
    35.7 +		{ "eub",         0, GetMsgText(345,0), { HAS_PARAMETER, "backend runner" } },
    35.8  		$
    35.9  	}
   35.10  elsedef
   35.11 @@ -120,9 +121,16 @@
   35.12  		for i = length(SymTab) to 1 by -1 do
   35.13  			if length(SymTab[i]) >= S_NREFS then
   35.14  				-- not temp or literal or constant, and not deleted yet
   35.15 -				if SymTab[i][S_MODE] = M_NORMAL and
   35.16 +				if 0 and  SymTab[i][S_SCOPE] = SC_MEMSTRUCT and
   35.17 +				   length(SymTab[i]) != SIZEOF_MEMSTRUCT_ENTRY then
   35.18 +				   
   35.19 +				   SymTab[i] = {0, SymTab[i][S_NEXT]} -- delete it
   35.20 +				   
   35.21 +				elsif SymTab[i][S_MODE] = M_NORMAL and
   35.22  				   SymTab[i][S_NREFS] = 0 and
   35.23 -				   SymTab[i][S_SCOPE] > SC_PRIVATE then -- tricky to delete privates
   35.24 +				   SymTab[i][S_SCOPE] > SC_PRIVATE and
   35.25 +				   SymTab[i][S_SCOPE] != SC_MEMSTRUCT and
   35.26 +				   length(SymTab[i]) != SIZEOF_MEMSTRUCT_ENTRY then -- tricky to delete privates
   35.27  					-- delete this symbol
   35.28  					if find(SymTab[i][S_TOKEN], RTN_TOKS) then
   35.29  						-- a routine
   35.30 @@ -197,7 +205,9 @@
   35.31  			SymTab[i] = SymTab[i][1..4] & SymTab[i][S_NEXT_IN_BLOCK]
   35.32  
   35.33  		else
   35.34 -			if find(SymTab[i][S_TOKEN], RTN_TOKS) then
   35.35 +			switch SymTab[i][S_TOKEN] do
   35.36 +			
   35.37 +			case PROC, FUNC, TYPE then
   35.38  				-- routine
   35.39  				if not full_debug then
   35.40  					SymTab[i][S_LINETAB] = 0
   35.41 @@ -210,8 +220,37 @@
   35.42  							SymTab[i][S_TEMPS],  SymTab[i][S_NUM_ARGS],
   35.43  							SymTab[i][S_FIRSTLINE],
   35.44  							SymTab[i][S_STACK_SPACE]}
   35.45 -
   35.46 -			else
   35.47 +			
   35.48 +			case MS_CHAR, MS_SHORT, MS_INT, MS_LONG, MS_LONGLONG,
   35.49 +				MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE,
   35.50 +				MS_OBJECT, MS_MEMBER, MEMSTRUCT, MEMUNION,
   35.51 +				MEMSTRUCT_DECL, MEMUNION_DECL, MEMTYPE
   35.52 +			then
   35.53 +				if length( SymTab[i] ) = SIZEOF_MEMSTRUCT_ENTRY then
   35.54 +					SymTab[i] = SymTab[i][1..4] & 
   35.55 +								{
   35.56 +									SymTab[i][S_NEXT_IN_BLOCK],
   35.57 +									SymTab[i][S_FILE_NO],
   35.58 +									SymTab[i][S_NAME],
   35.59 +									SymTab[i][S_TOKEN],
   35.60 +									$
   35.61 +								} &
   35.62 +								SymTab[i][S_MEM_SIZE..S_MEM_RECALC]
   35.63 +				elsif SymTab[i][S_SCOPE] = SC_MEMSTRUCT then
   35.64 +					-- We keep the primitive memstruct entries for their sizes
   35.65 +					SymTab[i] = SymTab[i][1..4] & 
   35.66 +								{
   35.67 +									SymTab[i][S_NEXT_IN_BLOCK],
   35.68 +									SymTab[i][S_FILE_NO],
   35.69 +									SymTab[i][S_NAME],
   35.70 +									SymTab[i][S_TOKEN],
   35.71 +									SymTab[i][S_MEM_SIZE],
   35.72 +									$
   35.73 +								}
   35.74 +								
   35.75 +				end if
   35.76 +			
   35.77 +			case else
   35.78  				-- variable
   35.79  				-- constants are deleted (but there will be an OBJ field
   35.80  				-- to hold their value at run-time)
   35.81 @@ -229,8 +268,9 @@
   35.82  								SymTab[i][S_NAME],
   35.83  								SymTab[i][S_TOKEN],{},
   35.84  								SymTab[i][S_BLOCK]}
   35.85 +								
   35.86  				end if
   35.87 -			end if
   35.88 +			end switch
   35.89  
   35.90  		end if
   35.91  	end for
    36.1 --- a/source/intinit.e	Mon Dec 19 23:19:58 2011 -0300
    36.2 +++ b/source/intinit.e	Wed Dec 21 16:45:49 2011 -0300
    36.3 @@ -26,7 +26,7 @@
    36.4  	{ "coverage-db",      0, GetMsgText(333,0), { NO_CASE, ONCE, HAS_PARAMETER, "file" } },
    36.5  	{ "coverage-erase",   0, GetMsgText(334,0), { NO_CASE, ONCE } },
    36.6  	{ "coverage-exclude", 0, GetMsgText(338,0), { NO_CASE, MULTIPLE, HAS_PARAMETER, "pattern"} },
    36.7 -	{ 0, "debugger", GetMsgText( 354, 0), {NO_CASE, ONCE, HAS_PARAMETER, "debugger"} },
    36.8 +	{ 0, "debugger", GetMsgText( 357, 0), {NO_CASE, ONCE, HAS_PARAMETER, "debugger"} },
    36.9  	$
   36.10  }
   36.11  
    37.1 --- a/source/keylist.e	Mon Dec 19 23:19:58 2011 -0300
    37.2 +++ b/source/keylist.e	Wed Dec 21 16:45:49 2011 -0300
    37.3 @@ -7,6 +7,7 @@
    37.4  elsedef
    37.5  	without type_check
    37.6  end ifdef
    37.7 +include std/dll.e
    37.8  
    37.9  include global.e
   37.10  include reswords.e
   37.11 @@ -21,7 +22,8 @@
   37.12  	K_EFFECT,    -- side effects
   37.13  	-- optional fields
   37.14  	K_CODE,
   37.15 -	K_DEF_ARGS
   37.16 +	K_DEF_ARGS,
   37.17 +	K_MEM_SIZE
   37.18  
   37.19  -- N.B. order and number of keywords and builtins
   37.20  -- is assumed by scanner.e, euphoria\bin\keywords.e, and others
   37.21 @@ -172,7 +174,26 @@
   37.22  	{"poke_pointer",     SC_PREDEF, PROC, POKE_POINTER,     2, E_OTHER_EFFECT},
   37.23  	{"peek_pointer",     SC_PREDEF, FUNC, PEEK_POINTER,     1, E_PURE},
   37.24  	{"sizeof",           SC_PREDEF, FUNC, SIZEOF,           1, E_PURE},
   37.25 +	{"memstruct",        SC_KEYWORD, MEMSTRUCT_DECL,        0, 0, 0 },
   37.26 +	{"memunion",         SC_KEYWORD, MEMUNION_DECL,         0, 0, 0 },
   37.27 +	{"pointer",          SC_MEMSTRUCT, MS_POINTER,          0, 0, 0, 0, 0, sizeof( C_POINTER ) },
   37.28 +	{"unsigned",         SC_MEMSTRUCT, MS_UNSIGNED,         0, 0, 0 },
   37.29 +	{"signed",           SC_MEMSTRUCT, MS_SIGNED,           0, 0, 0 },
   37.30 +	{"char",             SC_MEMSTRUCT, MS_CHAR,             0, 0, 0, 0, 0, sizeof( C_CHAR ) },
   37.31 +	{"short",            SC_MEMSTRUCT, MS_SHORT,            0, 0, 0, 0, 0, sizeof( C_SHORT ) },
   37.32 +	{"int",              SC_MEMSTRUCT, MS_INT,              0, 0, 0, 0, 0, sizeof( C_INT ) },
   37.33 +	{"long",             SC_MEMSTRUCT, MS_LONG,             0, 0, 0, 0, 0, sizeof( C_LONG ) },
   37.34 +	{"float",            SC_MEMSTRUCT, MS_FLOAT,            0, 0, 0, 0, 0, sizeof( C_FLOAT ) },
   37.35 +	{"double",           SC_MEMSTRUCT, MS_DOUBLE,           0, 0, 0, 0, 0, sizeof( C_DOUBLE ) },
   37.36 +	{"eudouble",         SC_MEMSTRUCT, MS_EUDOUBLE,         0, 0, 0, 0, 0, sizeof( C_POINTER ) * 2 },
   37.37 +	{"object",           SC_MEMSTRUCT, MS_OBJECT,           0, 0, 0, 0, 0, sizeof( C_POINTER ) },
   37.38 +	{"as",               SC_MEMSTRUCT, MS_AS,               0, 0, 0 },
   37.39 +	{"addressof",        SC_PREDEF, FUNC, ADDRESSOF,        1, E_PURE},
   37.40 +	{"offsetof",         SC_PREDEF, FUNC, OFFSETOF,         1, E_PURE},
   37.41  	{"deprecate",        SC_KEYWORD, DEPRECATE, 0, 0, 0},
   37.42 +	{"memtype",          SC_KEYWORD, MEMTYPE,               0, 0, 0 },
   37.43 +	{"long double",      SC_MEMSTRUCT, MS_LONGDOUBLE,       0, 0, 0, 0, 0, 16 },
   37.44 +	{"long long",    SC_MEMSTRUCT, MS_LONGLONG,         0, 0, 0, 0, 0, sizeof( C_LONGLONG ) },
   37.45  	$
   37.46  
   37.47  }
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/source/memstruct.e	Wed Dec 21 16:45:49 2011 -0300
    38.3 @@ -0,0 +1,1048 @@
    38.4 +include common.e
    38.5 +include emit.e
    38.6 +include error.e
    38.7 +include fwdref.e
    38.8 +include global.e
    38.9 +include msgtext.e
   38.10 +include parser.e
   38.11 +include platform.e
   38.12 +include reswords.e
   38.13 +include scanner.e
   38.14 +include symtab.e
   38.15 +
   38.16 +include std/dll.e
   38.17 +with trace
   38.18 +integer is_union = 0
   38.19 +symtab_pointer last_sym = 0
   38.20 +symtab_index mem_struct
   38.21 +
   38.22 +export procedure MemUnion_declaration( integer scope )
   38.23 +	is_union = 1
   38.24 +	MemStruct_declaration( scope )
   38.25 +	is_union = 0
   38.26 +end procedure
   38.27 +
   38.28 +function primitive_size( integer primitive )
   38.29 +	switch primitive do
   38.30 +		case MS_CHAR then
   38.31 +			return 1
   38.32 +		case MS_SHORT then
   38.33 +			return 2
   38.34 +		case MS_INT then
   38.35 +			return sizeof( C_INT )
   38.36 +		case MS_LONG then
   38.37 +			return sizeof( C_LONG )
   38.38 +		case MS_LONGLONG then
   38.39 +			return sizeof( C_LONGLONG )
   38.40 +		case MS_OBJECT then
   38.41 +			return sizeof( C_POINTER )
   38.42 +		case MS_FLOAT then
   38.43 +			return 4
   38.44 +		case MS_DOUBLE then
   38.45 +			return 8
   38.46 +		case MS_EUDOUBLE then
   38.47 +			ifdef E32 then
   38.48 +				return 8
   38.49 +			elsifdef E64 then
   38.50 +				-- same as long double
   38.51 +				return 16
   38.52 +			end ifdef
   38.53 +	end switch
   38.54 +end function
   38.55 +
   38.56 +constant
   38.57 +	MULTI_CHAR          = { MS_CHAR },
   38.58 +	MULTI_SHORT         = { MS_SHORT },
   38.59 +	MULTI_INT           = { MS_INT },
   38.60 +	MULTI_LONG          = { MS_LONG },
   38.61 +	MULTI_LONG_INT      = { MS_LONG, MS_INT },
   38.62 +	MULTI_LONG_LONG     = { MS_LONG, MS_LONG },
   38.63 +	MULTI_LONG_LONG_INT = { MS_LONG, MS_LONG, MS_INT },
   38.64 +	MULTI_LONG_DOUBLE   = { MS_LONG, MS_DOUBLE },
   38.65 +	$
   38.66 +
   38.67 +enum
   38.68 +	MULTI_PARSE_SIGNED,
   38.69 +	MULTI_PARSE_ID,
   38.70 +	MULTI_PARSE_SYM
   38.71 +
   38.72 +function multi_part_memtype( token tok, integer terminator = MS_AS )
   38.73 +	integer tid = tok[T_ID]
   38.74 +	integer sym = tok[T_SYM]
   38.75 +	integer signed = tid != MS_UNSIGNED
   38.76 +	integer sign_specified = 1
   38.77 +	sequence parts = {}
   38.78 +	if signed and tid != MS_SIGNED then
   38.79 +		putback( tok )
   38.80 +		sign_specified = 0
   38.81 +	end if
   38.82 +	
   38.83 +	for i = 1 to 4 do
   38.84 +		-- 3 is the most we can have, and then we better his an MS_AS...
   38.85 +		tok = next_token()
   38.86 +		tid = tok[T_ID]
   38.87 +		
   38.88 +		switch tid do
   38.89 +			case MS_CHAR, MS_SHORT, MS_INT then
   38.90 +				parts &= tid
   38.91 +				sym = tok[T_SYM]
   38.92 +				exit
   38.93 +			case MS_LONG then
   38.94 +				parts &= tid
   38.95 +				sym = tok[T_SYM]
   38.96 +			
   38.97 +			case MS_DOUBLE then
   38.98 +				if sign_specified then
   38.99 +					CompileErr( FP_NOT_SIGNED )
  38.100 +				end if
  38.101 +				parts &= tid
  38.102 +				sym = tok[T_SYM]
  38.103 +				exit
  38.104 +				
  38.105 +			case MS_FLOAT then
  38.106 +				if sign_specified or length( parts ) then
  38.107 +					CompileErr( FP_NOT_SIGNED )
  38.108 +				end if
  38.109 +				parts &= tid
  38.110 +				sym = tok[T_SYM]
  38.111 +				exit
  38.112 +			case else
  38.113 +				
  38.114 +				if tid = terminator then
  38.115 +					putback( tok )
  38.116 +					exit
  38.117 +				end if
  38.118 +				
  38.119 +				if sign_specified and not length( parts ) then
  38.120 +					CompileErr( EXPECTED_PRIMITIVE_MEMSTRUCT_TYPE )
  38.121 +				end if
  38.122 +				parts &= tid
  38.123 +				sym = tok[T_SYM]
  38.124 +				exit
  38.125 +		end switch
  38.126 +	end for
  38.127 +	
  38.128 +	-- validate...
  38.129 +	switch parts do
  38.130 +		case MULTI_CHAR, MULTI_SHORT, MULTI_INT then
  38.131 +			tid = parts[$]
  38.132 +		
  38.133 +		case MULTI_LONG, MULTI_LONG_INT then
  38.134 +			tok = MS_LONG
  38.135 +			
  38.136 +		case MULTI_LONG_LONG, MULTI_LONG_LONG_INT then
  38.137 +			tid = MS_LONGLONG
  38.138 +			sym = ms_longlong_sym
  38.139 +			
  38.140 +		case MULTI_LONG_DOUBLE then
  38.141 +			if not sign_specified then
  38.142 +				tid = MS_LONGDOUBLE
  38.143 +				sym = ms_longdouble_sym
  38.144 +			else
  38.145 +				-- error!
  38.146 +				CompileErr( FP_NOT_SIGNED )
  38.147 +			end if
  38.148 +		
  38.149 +	end switch
  38.150 +	return { signed, tid, sym }
  38.151 +end function
  38.152 +
  38.153 +--**
  38.154 +-- Special parser for sizeof().  Handles multi-part primitive
  38.155 +-- memstruct types.
  38.156 +-- 
  38.157 +-- Returns: 1 if the argument was parsed and emitted, otherwise,
  38.158 +--          returns 0, which means that normal argument parsing
  38.159 +--          should occur.
  38.160 +export function parse_sizeof()
  38.161 +	tok_match( LEFT_ROUND )
  38.162 +	enter_memstruct( 1 )
  38.163 +	integer parsed = 1
  38.164 +	
  38.165 +	token tok = next_token()
  38.166 +	switch tok[T_ID] do
  38.167 +		case MS_SIGNED, MS_UNSIGNED, MS_LONG then
  38.168 +			
  38.169 +			sequence multi = multi_part_memtype( tok, RIGHT_ROUND )
  38.170 +			emit_opnd( multi[MULTI_PARSE_SYM] )
  38.171 +			
  38.172 +		case MS_INT, MS_CHAR, MS_SHORT, MS_DOUBLE, MS_FLOAT, MS_EUDOUBLE,
  38.173 +			MEMSTRUCT, MEMTYPE, MEMUNION then
  38.174 +			
  38.175 +			emit_opnd( tok[T_SYM] )
  38.176 +		
  38.177 +		case OBJECT, MS_OBJECT, MS_POINTER then
  38.178 +				ifdef EU_EX then
  38.179 +					-- some extra stuff gets put in the eu backend
  38.180 +					-- at the beginning of the SymTab
  38.181 +					emit_opnd( 157 )
  38.182 +				elsedef
  38.183 +					-- WARNING: Magic number from the keylist!
  38.184 +					emit_opnd( 152 )
  38.185 +				end ifdef
  38.186 +		case else
  38.187 +			if SymTab[tok[T_SYM]][S_SCOPE] = SC_UNDEFINED then
  38.188 +				integer ref = new_forward_reference( MEMSTRUCT, tok[T_SYM], SIZEOF )
  38.189 +				emit_opnd( -ref )
  38.190 +			else
  38.191 +				putback( tok )
  38.192 +				parsed = 0
  38.193 +			end if
  38.194 +		
  38.195 +	end switch
  38.196 +	leave_memstruct()
  38.197 +	return parsed
  38.198 +end function
  38.199 +
  38.200 +--**
  38.201 +-- Parse a memstruct access for a memstruct base function
  38.202 +-- like offsetof, addressof
  38.203 +export procedure parse_memstruct_func( integer op )
  38.204 +	tok_match( LEFT_ROUND )
  38.205 +	-- The funcs eat this, so it doesn't need to be real
  38.206 +	Push( 0 )
  38.207 +	enter_memstruct( 1 )
  38.208 +	MemStruct_access( 1, FALSE )
  38.209 +	leave_memstruct()
  38.210 +	tok_match( RIGHT_ROUND )
  38.211 +end procedure
  38.212 +
  38.213 +--**
  38.214 +-- Parses one memtype declaration.
  38.215 +procedure parse_memtype( integer scope )
  38.216 +	token mem_type = next_token()
  38.217 +	if mem_type[T_ID] = DOLLAR then
  38.218 +		return
  38.219 +	end if
  38.220 +	
  38.221 +	
  38.222 +	
  38.223 +	sequence signed_type = multi_part_memtype( mem_type )
  38.224 +	
  38.225 +	symtab_index type_sym = signed_type[MULTI_PARSE_SYM]
  38.226 +	
  38.227 +	tok_match( MS_AS )
  38.228 +	
  38.229 +	token new_memtype = next_token()
  38.230 +	
  38.231 +	symtab_index sym = new_memtype[T_SYM]
  38.232 +	symtab:DefinedYet( sym )
  38.233 +	SymTab[sym] &= repeat( 0, SIZEOF_MEMSTRUCT_ENTRY - length( SymTab[sym] ) )
  38.234 +	SymTab[sym][S_SCOPE]      = scope
  38.235 +	SymTab[sym][S_TOKEN]      = MEMTYPE
  38.236 +	SymTab[sym][S_MODE]       = M_NORMAL
  38.237 +	SymTab[sym][S_MEM_SIGNED] = signed_type[MULTI_PARSE_SIGNED]
  38.238 +	
  38.239 +	switch signed_type[MULTI_PARSE_ID] do
  38.240 +		case MS_SIGNED, MS_UNSIGNED, 
  38.241 +			MS_LONG, MS_LONGLONG,
  38.242 +			MS_CHAR, MS_SHORT, MS_INT, 
  38.243 +			MS_FLOAT, MS_DOUBLE, MS_EUDOUBLE, 
  38.244 +			MS_OBJECT
  38.245 +		then
  38.246 +			SymTab[sym][S_MEM_TYPE]   = signed_type[MULTI_PARSE_ID]
  38.247 +			SymTab[sym][S_MEM_PARENT] = type_sym
  38.248 +			SymTab[sym][S_MEM_SIZE]   = primitive_size( signed_type[MULTI_PARSE_ID] )
  38.249 +		
  38.250 +		case else
  38.251 +			
  38.252 +			SymTab[sym][S_MEM_PARENT] = type_sym
  38.253 +			SymTab[sym][S_MEM_SIZE]   = SymTab[type_sym][S_MEM_SIZE]
  38.254 +			
  38.255 +			if not TRANSLATE and not SymTab[sym][S_MEM_SIZE] then
  38.256 +				SymTab[sym][S_MEM_SIZE] = recalculate_size( type_sym )
  38.257 +				-- mark it as a forward reference to have its size recalculated
  38.258 +				
  38.259 +				integer ref = new_forward_reference( MEMTYPE, sym, MEMSTRUCT_DECL )
  38.260 +				set_data( ref, sym )
  38.261 +				add_recalc( type_sym, sym )
  38.262 +				Show( sym ) -- creating a fwdref removes the symbol, but we just want to recalc the size later on
  38.263 +			end if
  38.264 +	end switch
  38.265 +end procedure
  38.266 +
  38.267 +--*
  38.268 +-- Creates an alias for a memstruct type.  May be a primitive or
  38.269 +-- a memstruct.  Multiple memtypes may be declared at once, separated
  38.270 +-- by commas, possibly ending with a list terminating $.
  38.271 +export procedure MemType( integer scope )
  38.272 +	enter_memstruct( 1 )
  38.273 +	
  38.274 +	token tok = { COMMA, 0 }
  38.275 +	while tok[T_ID] = COMMA do
  38.276 +		parse_memtype( scope )
  38.277 +		tok = next_token()
  38.278 +	end while
  38.279 +	putback( tok )
  38.280 +	
  38.281 +	leave_memstruct()
  38.282 +end procedure
  38.283 +
  38.284 +procedure DefinedYet( symtab_index sym )
  38.285 +	sequence name = sym_name( sym )
  38.286 +	symtab_pointer mem_entry = mem_struct
  38.287 +	
  38.288 +	while mem_entry with entry do
  38.289 +		if equal( sym_name( mem_entry ), name ) then
  38.290 +			CompileErr(31, {name})
  38.291 +		end if
  38.292 +	entry
  38.293 +		mem_entry = SymTab[mem_entry][S_MEM_NEXT]
  38.294 +	end while
  38.295 +end procedure
  38.296 +
  38.297 +export procedure MemStruct_declaration( integer scope )
  38.298 +	token tok = next_token() -- name
  38.299 +	mem_struct = tok[T_SYM]
  38.300 +	symtab:DefinedYet( mem_struct )
  38.301 +	enter_memstruct( mem_struct )
  38.302 +	last_sym = mem_struct
  38.303 +	SymTab[mem_struct] &= repeat( 0, SIZEOF_MEMSTRUCT_ENTRY - length( SymTab[mem_struct] ) )
  38.304 +	if is_union then
  38.305 +		SymTab[mem_struct][S_TOKEN] = MEMUNION
  38.306 +	else
  38.307 +		SymTab[mem_struct][S_TOKEN] = MEMSTRUCT
  38.308 +	end if
  38.309 +	SymTab[mem_struct][S_SCOPE] = scope
  38.310 +	
  38.311 +	integer pointer = 0
  38.312 +	integer signed  = -1
  38.313 +	integer long    = 0
  38.314 +	integer eu_type = 0
  38.315 +	while 1 with entry do
  38.316 +		integer tid = tok[T_ID]
  38.317 +		
  38.318 +		if tid = MEMTYPE then
  38.319 +			symtab_index memtype_sym = tok[T_SYM]
  38.320 +			tid = SymTab[memtype_sym][S_MEM_TYPE]
  38.321 +			if not tid then
  38.322 +				symtab_index type_sym = SymTab[memtype_sym][S_MEM_PARENT]
  38.323 +				tid = sym_token( type_sym )
  38.324 +				tok[T_SYM] = type_sym
  38.325 +				tok[T_ID]  = tid
  38.326 +			end if
  38.327 +		end if
  38.328 +		
  38.329 +		switch tid label "token" do
  38.330 +			case END then
  38.331 +				-- eventually, we probably need to handle ifdefs,
  38.332 +				-- which may be best handled by refactoring Ifdef_Statement in parser.e
  38.333 +				if is_union then
  38.334 +					tok_match( MEMUNION_DECL, END )
  38.335 +				else
  38.336 +					tok_match( MEMSTRUCT_DECL, END )
  38.337 +				end if
  38.338 +				exit
  38.339 +			
  38.340 +			case TYPE, QUALIFIED_TYPE then
  38.341 +				tok_match( MS_AS )
  38.342 +				eu_type = tok[T_SYM]
  38.343 +				
  38.344 +			case MEMSTRUCT, MEMUNION, QUALIFIED_MEMSTRUCT, QUALIFIED_MEMUNION then
  38.345 +				-- embedding
  38.346 +				MemStruct_member( tok, pointer )
  38.347 +				-- reset the flags
  38.348 +				pointer = 0
  38.349 +				long    = 0
  38.350 +				signed  = -1
  38.351 +			
  38.352 +			case VARIABLE, QUALIFIED_VARIABLE then
  38.353 +				if SC_UNDEFINED = SymTab[tok[T_SYM]][S_SCOPE] then
  38.354 +					-- forward reference
  38.355 +					
  38.356 +					if pointer then
  38.357 +						integer ref = new_forward_reference( TYPE, tok[T_SYM], MEMSTRUCT )
  38.358 +						MemStruct_member( tok, pointer, 1 )
  38.359 +					else
  38.360 +					
  38.361 +						token nt = next_token()
  38.362 +						if nt[T_ID] = MS_AS then
  38.363 +							-- a forward reference to a type
  38.364 +							integer ref = new_forward_reference( TYPE, tok[T_SYM], MEMSTRUCT )
  38.365 +							eu_type = -ref
  38.366 +							break "token"
  38.367 +						else
  38.368 +							putback( nt )
  38.369 +							MemStruct_member( tok, pointer, 1 )
  38.370 +						end if
  38.371 +					end if
  38.372 +					
  38.373 +				else
  38.374 +					CompileErr( EXPECTED_VALID_MEMSTRUCT )
  38.375 +				end if
  38.376 +				-- reset the flags
  38.377 +				pointer = 0
  38.378 +				long    = 0
  38.379 +				signed  = -1
  38.380 +				
  38.381 +			case MS_SIGNED then
  38.382 +				if signed != -1 then
  38.383 +					-- error...multiple signed modifiers
  38.384 +					CompileErr( EXPECTED_VALID_MEMSTRUCT )
  38.385 +				end if
  38.386 +				signed = 1
  38.387 +			
  38.388 +			case MS_UNSIGNED then
  38.389 +				if signed != -1 then
  38.390 +					-- error...multiple signed modifiers
  38.391 +					CompileErr( EXPECTED_VALID_MEMSTRUCT )
  38.392 +				end if
  38.393 +				signed = 0
  38.394 +				
  38.395 +			case MS_LONG then
  38.396 +				token check = next_token()
  38.397 +				integer id = check[T_ID]
  38.398 +				if id = MS_INT or id = MS_LONG or id = MS_DOUBLE then
  38.399 +					long = 1
  38.400 +					tid = id
  38.401 +					tok = check
  38.402 +				else
  38.403 +					putback( check )
  38.404 +				end if
  38.405 +				fallthru
  38.406 +			case MS_CHAR, MS_SHORT, MS_INT, MS_FLOAT, MS_DOUBLE, MS_EUDOUBLE, MS_OBJECT then
  38.407 +				
  38.408 +				switch tid do
  38.409 +					case MS_CHAR then
  38.410 +						Char( eu_type, pointer, signed )
  38.411 +					case MS_SHORT then
  38.412 +						Short( eu_type, pointer, signed )
  38.413 +					case MS_INT then
  38.414 +						if long then
  38.415 +							Long( eu_type, pointer, signed )
  38.416 +						else
  38.417 +							Int( eu_type, pointer, signed )
  38.418 +						end if
  38.419 +					case MS_LONG then
  38.420 +						token int_tok = next_token()
  38.421 +						
  38.422 +						if long then
  38.423 +							-- this is the second long...
  38.424 +							if int_tok[T_ID] = MS_INT then
  38.425 +								-- long long int
  38.426 +								LongLong( eu_type, pointer, signed )
  38.427 +							
  38.428 +							elsif int_tok[T_ID] = VARIABLE
  38.429 +							or int_tok[T_ID] = PROCEDURE
  38.430 +							or int_tok[T_ID] = FUNCTION
  38.431 +							or int_tok[T_ID] = TYPE
  38.432 +							or int_tok[T_ID] = NAMESPACE
  38.433 +							then
  38.434 +								-- long long
  38.435 +								putback( int_tok )
  38.436 +								LongLong( eu_type, pointer, signed )
  38.437 +							else
  38.438 +								CompileErr( 25, { sym_name( int_tok[T_SYM] ) } )
  38.439 +							end if
  38.440 +						elsif int_tok[T_ID] = MS_DOUBLE then
  38.441 +							long = 1
  38.442 +							putback( int_tok )
  38.443 +							-- need to skip the part where the flags get reset
  38.444 +							break "token"
  38.445 +						else
  38.446 +							putback( int_tok )
  38.447 +							Long( eu_type, pointer, signed )
  38.448 +						end if
  38.449 +						
  38.450 +					case MS_FLOAT, MS_DOUBLE, MS_EUDOUBLE then
  38.451 +						if signed != - 1 then
  38.452 +							-- can't have signed modifiers here
  38.453 +							CompileErr( FP_NOT_SIGNED )
  38.454 +						end if
  38.455 +						
  38.456 +						if long and tid != MS_DOUBLE then
  38.457 +							-- long modifier only for doubles
  38.458 +							CompileErr( ONLY_DOUBLE_FP_LONG )
  38.459 +						elsif long then
  38.460 +							tid = MS_LONGDOUBLE
  38.461 +						end if
  38.462 +						
  38.463 +						FloatingPoint( eu_type, tid, pointer )
  38.464 +					
  38.465 +					case MS_OBJECT then
  38.466 +						Object( eu_type, pointer, signed )
  38.467 +					
  38.468 +					case else
  38.469 +						
  38.470 +				end switch
  38.471 +				symtab_index type_sym = tok[T_SYM]
  38.472 +				
  38.473 +				-- reset the flags
  38.474 +				pointer = 0
  38.475 +				long    = 0
  38.476 +				signed  = -1
  38.477 +				eu_type = 0
  38.478 +			
  38.479 +			case MS_POINTER then
  38.480 +				-- pointer!
  38.481 +				pointer = 1
  38.482 +				
  38.483 +			case else
  38.484 +				CompileErr( EXPECTED_VALID_MEMSTRUCT )
  38.485 +		end switch
  38.486 +	entry
  38.487 +		tok = next_token()
  38.488 +	end while
  38.489 +	calculate_size()
  38.490 +	leave_memstruct()
  38.491 +end procedure
  38.492 +
  38.493 +
  38.494 +--*
  38.495 +-- Returns the size and offsets, or -1 if all
  38.496 +-- sizes have not been determined yet.
  38.497 +export function recalculate_size( symtab_index sym )
  38.498 +	mem_struct = sym
  38.499 +	is_union   = sym_token( sym ) = MEMUNION_DECL
  38.500 +	integer size = calculate_size()
  38.501 +	
  38.502 +	is_union = 0
  38.503 +	if size > 0 then
  38.504 +		for i = 2 to length( SymTab[sym][S_MEM_RECALC] ) do
  38.505 +			
  38.506 +			symtab_index recalc_sym =  SymTab[sym][S_MEM_RECALC][i]
  38.507 +			SymTab[recalc_sym][S_MEM_SIZE] = recalculate_size( recalc_sym )
  38.508 +			
  38.509 +		end for
  38.510 +	end if
  38.511 +	return size
  38.512 +end function
  38.513 +
  38.514 +procedure add_recalc( symtab_index parent_struct, symtab_index dependent_struct )
  38.515 +	if length( SymTab[parent_struct] ) >= SIZEOF_MEMSTRUCT_ENTRY
  38.516 +	and (atom( SymTab[parent_struct][S_MEM_RECALC] )
  38.517 +		or not find( dependent_struct, SymTab[parent_struct][S_MEM_RECALC] )) then
  38.518 +		SymTab[parent_struct][S_MEM_RECALC] &= dependent_struct
  38.519 +	end if
  38.520 +end procedure
  38.521 +
  38.522 +--**
  38.523 +-- Return the alignment required for the memstruct passed.
  38.524 +-- Returs 0 if the alignment cannot yet be determined.
  38.525 +function calculate_alignment( symtab_index member_sym )
  38.526 +	integer alignment = 0
  38.527 +	
  38.528 +	if SymTab[member_sym][S_MEM_STRUCT] then
  38.529 +		member_sym = SymTab[member_sym][S_MEM_STRUCT]
  38.530 +	end if
  38.531 +	
  38.532 +	integer sym = member_sym
  38.533 +	if SymTab[sym][S_MEM_SIZE] = -1 then
  38.534 +		-- we haven't determined the size yet for this
  38.535 +		return -1
  38.536 +	end if
  38.537 +	
  38.538 +	integer sub_alignment = 0
  38.539 +	while sym with entry do
  38.540 +		if SymTab[sym][S_MEM_POINTER] then
  38.541 +			sub_alignment = sizeof( C_POINTER )
  38.542 +		elsif sym_token( sym ) = MS_MEMBER then
  38.543 +			sub_alignment = calculate_alignment( sym )
  38.544 +			if not sub_alignment then
  38.545 +				return -1
  38.546 +			end if
  38.547 +		else
  38.548 +			-- 32-bit *nix aligns double on 4-byte boundary
  38.549 +			if IX86 and IUNIX and sym_token( sym ) = MS_DOUBLE then
  38.550 +				sub_alignment = 4
  38.551 +			else
  38.552 +				if SymTab[sym][S_MEM_ARRAY] then
  38.553 +					sub_alignment = SymTab[sym][S_MEM_SIZE] / SymTab[sym][S_MEM_ARRAY]
  38.554 +				else
  38.555 +					sub_alignment = SymTab[sym][S_MEM_SIZE]
  38.556 +				end if
  38.557 +			end if
  38.558 +		end if
  38.559 +		if sub_alignment > alignment then
  38.560 +			alignment = sub_alignment
  38.561 +		end if
  38.562 +	entry
  38.563 +		sym = SymTab[sym][S_MEM_NEXT]
  38.564 +	end while
  38.565 +	return alignment
  38.566 +end function
  38.567 +
  38.568 +--**
  38.569 +-- Calculates how much padding is needed
  38.570 +function calculate_padding( symtab_index member_sym, integer size, integer mem_size )
  38.571 +	integer padding = 0
  38.572 +	
  38.573 +	if SymTab[member_sym][S_MEM_POINTER] then
  38.574 +		padding = remainder( size, sizeof( C_POINTER ) )
  38.575 +	elsif sym_token( member_sym ) = MS_MEMBER then
  38.576 +		integer alignment = calculate_alignment( member_sym )
  38.577 +		if alignment = -1 then
  38.578 +			return -1
  38.579 +		elsif alignment then
  38.580 +			padding = remainder( size, alignment )
  38.581 +		end if
  38.582 +	else
  38.583 +		if SymTab[member_sym][S_MEM_ARRAY] then
  38.584 +			mem_size /= SymTab[member_sym][S_MEM_ARRAY]
  38.585 +		end if
  38.586 +		
  38.587 +		-- 32-bit *nix aligns double on 4-byte boundary
  38.588 +		if sym_token( member_sym ) = MS_DOUBLE and IX86 and IUNIX then
  38.589 +			padding = remainder( size, 4 )
  38.590 +		else
  38.591 +			padding = remainder( size, mem_size )
  38.592 +		end if
  38.593 +	end if
  38.594 +	return padding
  38.595 +end function
  38.596 +
  38.597 +--**
  38.598 +-- Returns the size and offsets for the memstruct, or -1 if all
  38.599 +-- sizes have not been determined yet.
  38.600 +function calculate_size()
  38.601 +	symtab_pointer member_sym = mem_struct
  38.602 +
  38.603 +	if sym_token( member_sym ) = MEMTYPE then
  38.604 +		if SymTab[SymTab[member_sym][S_MEM_PARENT]][S_MEM_SIZE] < 1 then
  38.605 +			SymTab[SymTab[member_sym][S_MEM_PARENT]][S_MEM_SIZE] = recalculate_size( SymTab[member_sym][S_MEM_PARENT] )
  38.606 +		end if
  38.607 +		return SymTab[SymTab[member_sym][S_MEM_PARENT]][S_MEM_SIZE]
  38.608 +	end if
  38.609 +	
  38.610 +	integer size = 0
  38.611 +	integer indeterminate = 0
  38.612 +	while member_sym and not indeterminate with entry do
  38.613 +		integer mem_size = SymTab[member_sym][S_MEM_SIZE]
  38.614 +		if mem_size < 1 then
  38.615 +			-- might be a struct that's been recalculated
  38.616 +			symtab_pointer struct_type = SymTab[member_sym][S_MEM_STRUCT]
  38.617 +			if struct_type then
  38.618 +				mem_size = SymTab[struct_type][S_MEM_SIZE]
  38.619 +				if mem_size < 1 then
  38.620 +					if length( SymTab[struct_type] ) >= SIZEOF_MEMSTRUCT_ENTRY then
  38.621 +						mem_size = recalculate_size( struct_type )
  38.622 +					end if
  38.623 +					if mem_size < 1 then
  38.624 +						indeterminate = 1
  38.625 +						add_recalc( struct_type, mem_struct )
  38.626 +					end if
  38.627 +				end if
  38.628 +			else
  38.629 +				indeterminate = 1
  38.630 +			end if
  38.631 +		end if
  38.632 +		if not indeterminate then
  38.633 +			if not is_union then
  38.634 +				-- make sure we're properly aligned
  38.635 +				integer padding = calculate_padding( member_sym, size, mem_size )
  38.636 +				
  38.637 +				if padding < 0 then
  38.638 +					indeterminate = 1
  38.639 +				elsif padding then
  38.640 +					size += padding
  38.641 +				end if
  38.642 +				
  38.643 +				SymTab[member_sym][S_MEM_OFFSET] = size
  38.644 +				size += mem_size
  38.645 +			else
  38.646 +				if mem_size > size then
  38.647 +					size = mem_size
  38.648 +				end if
  38.649 +			end if
  38.650 +		end if
  38.651 +	entry
  38.652 +		member_sym = SymTab[member_sym][S_MEM_NEXT]
  38.653 +	end while
  38.654 +	
  38.655 +	if indeterminate then
  38.656 +		SymTab[mem_struct][S_MEM_SIZE] = 0
  38.657 +		return 0
  38.658 +	else
  38.659 +		SymTab[mem_struct][S_MEM_SIZE] = size
  38.660 +		integer alignment = calculate_alignment( mem_struct )
  38.661 +		if alignment then
  38.662 +			integer padding = remainder( size, alignment )
  38.663 +			size += padding
  38.664 +		end if
  38.665 +		SymTab[mem_struct][S_MEM_SIZE] = size
  38.666 +		return size
  38.667 +	end if
  38.668 +end function
  38.669 +
  38.670 +function read_name()
  38.671 +	token tok = next_token()
  38.672 +	switch tok[T_ID] do
  38.673 +		case VARIABLE, PROC, FUNC, TYPE, 
  38.674 +				MS_CHAR, MS_SHORT, MS_INT, MS_LONG, MS_LONGLONG, MS_OBJECT, 
  38.675 +				MS_FLOAT, MS_DOUBLE, MS_LONGDOUBLE, MS_EUDOUBLE,
  38.676 +				MS_MEMBER then
  38.677 +			
  38.678 +			DefinedYet( tok[T_SYM] )
  38.679 +			
  38.680 +			symtab_index member = NewBasicEntry( sym_name( tok[T_SYM] ), 0, SC_MEMSTRUCT, MS_MEMBER, 0, 0, 00 )
  38.681 +			SymTab[member] &= repeat( 0, SIZEOF_MEMSTRUCT_ENTRY - length( SymTab[member] ) )
  38.682 +			
  38.683 +			return { MS_MEMBER, member }
  38.684 +		
  38.685 +		case else
  38.686 +			CompileErr( 68, {"identifier", LexName( tok[T_ID] )} )
  38.687 +	end switch
  38.688 +end function
  38.689 +
  38.690 +function member_array( symtab_index sym )
  38.691 +	token tok = next_token()
  38.692 +	if tok[T_ID] != LEFT_SQUARE then
  38.693 +		putback( tok )
  38.694 +		return 1
  38.695 +	end if
  38.696 +	
  38.697 +	tok = next_token()
  38.698 +	object size = sym_obj( tok[T_SYM] )
  38.699 +	if not integer( size ) or size < 1 then
  38.700 +		CompileErr( 68, {"positive integer", LexName( tok[T_ID] ) } )
  38.701 +	end if
  38.702 +	
  38.703 +	SymTab[sym][S_MEM_ARRAY] = sym_obj( tok[T_SYM] )
  38.704 +	tok_match( RIGHT_SQUARE )
  38.705 +	return size
  38.706 +end function
  38.707 +
  38.708 +procedure add_member( integer type_sym, token name_tok, object mem_type, integer size, integer pointer, integer signed = 0 )
  38.709 +	
  38.710 +	symtab_index sym = name_tok[T_SYM]
  38.711 +	
  38.712 +	SymTab[last_sym][S_MEM_NEXT] = sym
  38.713 +	
  38.714 +	SymTab[sym] &= repeat( 0, SIZEOF_MEMSTRUCT_ENTRY - length( SymTab[sym] ) )
  38.715 +	
  38.716 +	size *= member_array( sym )
  38.717 +	
  38.718 +	if token( mem_type ) then
  38.719 +		SymTab[sym][S_MEM_STRUCT] = mem_type[T_SYM]
  38.720 +		mem_type = MS_MEMBER
  38.721 +	end if
  38.722 +	
  38.723 +	if pointer then
  38.724 +		size = sizeof( C_POINTER )
  38.725 +	end if
  38.726 +	
  38.727 +	if signed = -1 then
  38.728 +		signed = 1
  38.729 +	end if
  38.730 +	
  38.731 +	SymTab[sym][S_SCOPE]       = SC_MEMSTRUCT
  38.732 +	SymTab[sym][S_TOKEN]       = mem_type
  38.733 +	SymTab[sym][S_MEM_SIZE]    = size
  38.734 +	SymTab[sym][S_MEM_POINTER] = pointer
  38.735 +	SymTab[sym][S_MEM_SIGNED]  = signed
  38.736 +	SymTab[sym][S_MEM_PARENT]  = mem_struct
  38.737 +	SymTab[sym][S_MEM_TYPE]    = type_sym
  38.738 +	
  38.739 +	if type_sym < 0 then
  38.740 +		register_forward_type( sym, -type_sym )
  38.741 +	end if
  38.742 +	last_sym = sym
  38.743 +end procedure
  38.744 +
  38.745 +procedure Char( integer eu_type, integer pointer, integer signed )
  38.746 +	add_member( eu_type, read_name(), MS_CHAR, 1, pointer, signed )
  38.747 +end procedure
  38.748 +
  38.749 +procedure Short( integer eu_type, integer pointer, integer signed )
  38.750 +	add_member( eu_type, read_name(), MS_SHORT, 2, pointer, signed )
  38.751 +end procedure
  38.752 +
  38.753 +procedure Int( integer eu_type, integer pointer, integer signed )
  38.754 +	add_member( eu_type, read_name(), MS_INT, sizeof( C_INT ), pointer, signed )
  38.755 +end procedure
  38.756 +
  38.757 +procedure Long( integer eu_type, integer pointer, integer signed )
  38.758 +	add_member( eu_type, read_name(), MS_LONG, sizeof( C_LONG ), pointer, signed )
  38.759 +end procedure
  38.760 +
  38.761 +procedure LongLong( integer eu_type, integer pointer, integer signed )
  38.762 +	add_member( eu_type, read_name(), MS_LONGLONG, sizeof( C_LONGLONG ), pointer, signed )
  38.763 +end procedure
  38.764 +
  38.765 +procedure FloatingPoint( integer eu_type, integer fp_type, integer pointer )
  38.766 +	token name_tok = read_name()
  38.767 +	integer size
  38.768 +	switch fp_type do
  38.769 +		case MS_FLOAT then
  38.770 +			size = 4
  38.771 +		case MS_DOUBLE then
  38.772 +			size = 8
  38.773 +		case MS_LONGDOUBLE then
  38.774 +			-- these get padded out in structs to a full 16 bytes
  38.775 +			-- the data is actually only 10 bytes in size
  38.776 +			size = 16
  38.777 +		case MS_EUDOUBLE then
  38.778 +			ifdef E32 then
  38.779 +				size = 8
  38.780 +			elsifdef E64 then
  38.781 +				-- same as long double
  38.782 +				size = 16
  38.783 +			end ifdef
  38.784 +	end switch
  38.785 +	add_member( eu_type, name_tok, fp_type, size, pointer )
  38.786 +end procedure
  38.787 +
  38.788 +procedure Object( integer eu_type, integer pointer, integer signed )
  38.789 +	token name_tok = read_name()
  38.790 +	
  38.791 +	add_member( eu_type, name_tok, MS_OBJECT, sizeof( E_OBJECT ), pointer, signed )
  38.792 +end procedure
  38.793 +
  38.794 +procedure MemStruct_member( token memstruct_tok, integer pointer, integer fwd = 0 )
  38.795 +	token name_tok = read_name()
  38.796 +	integer size = 0
  38.797 +	
  38.798 +	if fwd then
  38.799 +		integer ref = new_forward_reference( MS_MEMBER, memstruct_tok[T_SYM], MEMSTRUCT_DECL )
  38.800 +		set_data( ref, name_tok[T_SYM] )
  38.801 +	else
  38.802 +		size = SymTab[memstruct_tok[T_SYM]][S_MEM_SIZE]
  38.803 +	end if
  38.804 +	add_member( 0, name_tok, memstruct_tok, size, pointer )
  38.805 +	
  38.806 +	
  38.807 +end procedure
  38.808 +
  38.809 +export function resolve_member( sequence name, symtab_index struct_sym )
  38.810 +	symtab_pointer member_sym = struct_sym
  38.811 +	
  38.812 +	while member_sym with entry do
  38.813 +		if equal( name, sym_name( member_sym ) ) then
  38.814 +			return member_sym
  38.815 +		end if
  38.816 +	entry
  38.817 +		member_sym = SymTab[member_sym][S_MEM_NEXT]
  38.818 +	end while
  38.819 +	return 0
  38.820 +end function
  38.821 +
  38.822 +export function resolve_members( sequence names, symtab_index struct_sym )
  38.823 +	symtab_pointer parent = struct_sym
  38.824 +	symtab_pointer sym
  38.825 +	for i = 1 to length( names ) do
  38.826 +		sym = resolve_member( names[i], parent )
  38.827 +		if not sym then
  38.828 +			return 0
  38.829 +		end if
  38.830 +		parent = SymTab[sym][S_MEM_STRUCT]
  38.831 +	end for
  38.832 +	return sym
  38.833 +end function
  38.834 +
  38.835 +function parse_symstruct( token tok )
  38.836 +		
  38.837 +	symtab_index struct_sym = tok[T_SYM]
  38.838 +	integer ref = 0
  38.839 +	if SymTab[struct_sym][S_SCOPE] = SC_UNDEFINED then
  38.840 +		-- a forward reference
  38.841 +		ref = new_forward_reference( MEMSTRUCT, struct_sym, MEMSTRUCT_ACCESS )
  38.842 +		
  38.843 +	elsif tok[T_ID] != MEMSTRUCT
  38.844 +	and tok[T_ID]   != QUALIFIED_MEMSTRUCT
  38.845 +	and tok[T_ID]   != MEMUNION
  38.846 +	and tok[T_ID]   != QUALIFIED_MEMUNION
  38.847 +	and tok[T_ID]   != MEMTYPE then
  38.848 +		-- something else
  38.849 +		CompileErr( EXPECTED_VALID_MEMSTRUCT )
  38.850 +	end if
  38.851 +	
  38.852 +	tok = next_token()
  38.853 +	if tok[T_ID] = LEFT_SQUARE then
  38.854 +		emit_symstruct( struct_sym, ref )
  38.855 +		Expr()
  38.856 +		tok_match( RIGHT_SQUARE )
  38.857 +		emit_op( MEMSTRUCT_ARRAY )
  38.858 +		tok = next_token()
  38.859 +		
  38.860 +		if tok[T_ID] != DOT then
  38.861 +			putback( tok )
  38.862 +			return 0
  38.863 +		end if
  38.864 +		return { struct_sym, ref }
  38.865 +	elsif tok[T_ID] = DOT then
  38.866 +		return { struct_sym, ref }
  38.867 +	else
  38.868 +		putback( tok )
  38.869 +		return { struct_sym, ref, 0 }
  38.870 +	end if
  38.871 +end function
  38.872 +
  38.873 +procedure emit_member( integer member, integer ref, integer op, sequence names )
  38.874 +	if ref then
  38.875 +		integer m_ref = new_forward_reference( MS_MEMBER, member, op )
  38.876 +		add_data( ref, m_ref )
  38.877 +		emit_opnd( -m_ref )
  38.878 +		set_data( m_ref, names )
  38.879 +	else
  38.880 +		emit_opnd( member )
  38.881 +	end if
  38.882 +end procedure
  38.883 +
  38.884 +procedure emit_symstruct( integer symstruct, integer ref )
  38.885 +	if ref then
  38.886 +		emit_opnd( -ref )
  38.887 +	else
  38.888 +		emit_opnd( symstruct )
  38.889 +	end if
  38.890 +end procedure
  38.891 +
  38.892 +function is_pointer( symtab_index member )
  38.893 +	return SymTab[member][S_MEM_POINTER]
  38.894 +end function
  38.895 +
  38.896 +--**
  38.897 +-- Parse the dot notation of accessing a memstruct.
  38.898 +export procedure MemStruct_access( symtab_index sym, integer lhs )
  38.899 +	-- the sym is the pointer, and just before this, we found a DOT token
  38.900 +	-- First, figure out which memstruct we're using
  38.901 +	token tok = next_token()
  38.902 +	
  38.903 +	object sym_ref = parse_symstruct( tok )
  38.904 +	if atom( sym_ref ) then
  38.905 +		-- simple array access, nothing more needed
  38.906 +		return
  38.907 +	end if
  38.908 +	symtab_index struct_sym = sym_ref[1]
  38.909 +	integer      ref        = sym_ref[2]
  38.910 +	
  38.911 +	if length( sym_ref ) = 3 then
  38.912 +		-- just the sym...serialize it
  38.913 +		if lhs then
  38.914 +			emit_opnd( sym )
  38.915 +			emit_symstruct( struct_sym, ref )
  38.916 +			emit_opnd( 0 ) -- don't deref
  38.917 +			return
  38.918 +		else
  38.919 +			emit_symstruct( struct_sym, ref )
  38.920 +			emit_op( MEMSTRUCT_READ )
  38.921 +		end if
  38.922 +		return
  38.923 +	end if
  38.924 +	
  38.925 +	sequence names = {}
  38.926 +
  38.927 +	No_new_entry = 1
  38.928 +	integer members = 0
  38.929 +	symtab_pointer member = 0
  38.930 +	integer has_dot = 1
  38.931 +	while 1 with entry do
  38.932 +		integer tid = tok[T_ID]
  38.933 +		switch tid do
  38.934 +			case VARIABLE, FUNC, PROC, TYPE, NAMESPACE then
  38.935 +				
  38.936 +				if not has_dot then
  38.937 +					peek_member( members, member, ref, lhs, names )
  38.938 +					putback( tok )
  38.939 +					exit
  38.940 +				end if
  38.941 +				
  38.942 +				-- make it look like the IGNORED token
  38.943 +				tok= { IGNORED, SymTab[tok[T_SYM]][S_NAME] }
  38.944 +				fallthru
  38.945 +			
  38.946 +			case IGNORED then
  38.947 +				if not has_dot then
  38.948 +					peek_member( members, member, ref, lhs, names )
  38.949 +					if tid != IGNORED then
  38.950 +						putback( tok )
  38.951 +					else
  38.952 +						No_new_entry = 0
  38.953 +						putback( keyfind( tok[T_SYM], -1 ) )
  38.954 +					end if
  38.955 +					exit
  38.956 +				end if
  38.957 +				
  38.958 +				-- just look at it within this memstruct's context...
  38.959 +				names = append( names, tok[T_SYM] )
  38.960 +				if ref then
  38.961 +					-- we don't know the memstruct yet!
  38.962 +					member = NewBasicEntry( tok[T_SYM], 0, SC_MEMSTRUCT, MS_MEMBER, 0, 0, 00 )
  38.963 +					SymTab[member] &= repeat( 0, SIZEOF_MEMSTRUCT_ENTRY - length( SymTab[member] ) )
  38.964 +					emit_member( member, ref, MEMSTRUCT_ACCESS, names )
  38.965 +				else
  38.966 +					if member then
  38.967 +						-- going into an embedded / linked struct or union
  38.968 +						struct_sym = SymTab[member][S_MEM_STRUCT]
  38.969 +					end if
  38.970 +					if SymTab[struct_sym][S_TOKEN] = MEMTYPE then
  38.971 +						-- use whatever it really is
  38.972 +						struct_sym = SymTab[struct_sym][S_MEM_PARENT]
  38.973 +					end if
  38.974 +					member = resolve_member( tok[T_SYM], struct_sym )
  38.975 +					if not member then
  38.976 +						
  38.977 +						CompileErr( NOT_A_MEMBER, { tok[T_SYM], sym_name( struct_sym ) } )
  38.978 +					end if
  38.979 +					emit_opnd( member )
  38.980 +				end if
  38.981 +				
  38.982 +				members += 1
  38.983 +				has_dot = 0
  38.984 +				
  38.985 +			case MULTIPLY then
  38.986 +				-- ptr.struct.ptr_to_something.*  fetch the value pointed to
  38.987 +				if not ref then
  38.988 +					-- make sure it's actually a pointer...
  38.989 +					if not SymTab[member][S_MEM_POINTER] then
  38.990 +						CompileErr( DEREFERENCING_NONPOINTER )
  38.991 +					end if
  38.992 +				end if
  38.993 +				peek_member( members, member, ref, lhs, names, /* op */ , 1 )
  38.994 +				exit
  38.995 +				
  38.996 +			case DOT then
  38.997 +				-- another layer...
  38.998 +				if not member then
  38.999 +					CompileErr( 68, {"a member name", LexName( tid )} )
 38.1000 +				end if
 38.1001 +				has_dot = 1
 38.1002 +				
 38.1003 +			case LEFT_SQUARE then
 38.1004 +				-- array...
 38.1005 +				if has_dot then
 38.1006 +					-- can't do this...
 38.1007 +				end if
 38.1008 +				Expr()
 38.1009 +				tok_match( RIGHT_SQUARE )
 38.1010 +				
 38.1011 +				tok = next_token()
 38.1012 +				putback( tok )
 38.1013 +				if tok[T_ID] != DOT then
 38.1014 +					if lhs then
 38.1015 +						peek_member( members, member, ref, lhs, names, ARRAY_ACCESS )
 38.1016 +					else
 38.1017 +						emit_op( PEEK_ARRAY )
 38.1018 +					end if
 38.1019 +					exit
 38.1020 +				end if
 38.1021 +				
 38.1022 +				emit_op( MEMSTRUCT_ARRAY )
 38.1023 +				
 38.1024 +			case else
 38.1025 +				peek_member( members, member, ref, lhs, names )
 38.1026 +				putback( tok )
 38.1027 +				exit
 38.1028 +		end switch
 38.1029 +	entry
 38.1030 +		tok = next_token()
 38.1031 +	end while
 38.1032 +	No_new_entry = 0
 38.1033 +end procedure
 38.1034 +
 38.1035 +procedure peek_member( integer members, symtab_index member, integer ref, 
 38.1036 +					   integer lhs, sequence names, integer op = MEMSTRUCT_ACCESS,
 38.1037 +					   integer deref_ptr = 0
 38.1038 + 					)
 38.1039 +	
 38.1040 +	emit_opnd( members )
 38.1041 +	emit_op( op )
 38.1042 +	if lhs then
 38.1043 +		emit_member( member, ref, op, names )
 38.1044 +		emit_opnd( deref_ptr )
 38.1045 +	else
 38.1046 +		-- geting the value...peek it
 38.1047 +		emit_member( member, ref, PEEK_MEMBER, names )
 38.1048 +		emit_opnd( deref_ptr )
 38.1049 +		emit_op( PEEK_MEMBER )
 38.1050 +	end if
 38.1051 +end procedure
    39.1 --- a/source/msgtext.e	Mon Dec 19 23:19:58 2011 -0300
    39.2 +++ b/source/msgtext.e	Wed Dec 21 16:45:49 2011 -0300
    39.3 @@ -13,10 +13,22 @@
    39.4  include common.e
    39.5  
    39.6  export enum
    39.7 +	EXPECTED_VALID_MEMSTRUCT   = 358,
    39.8 +	FP_NOT_SIGNED,
    39.9 +	ONLY_DOUBLE_FP_LONG,
   39.10 +	ONLY_INT_LONG_LONG,
   39.11 +	NOT_A_MEMBER,
   39.12 +	NOT_A_POINTER_OR_MEMSTRUCT,
   39.13 +	CANNOT_ASSIGN_NONPRIMATIVE,
   39.14 +	EXPECTED_PRIMITIVE_MEMSTRUCT_TYPE,
   39.15 +	MISSING_MEMSTRUCT_MEMBER,
   39.16 +	DEREFERENCING_NONPOINTER,
   39.17 +	MISSING_CMD_PARAMETER = 353,
   39.18  	MSG_CC_PREFIX = 600,
   39.19  	NONSTANDARD_LIBRARY,
   39.20  	DUPLICATE_MULTI_ASSIGN,
   39.21 -	MISSING_CMD_PARAMETER = 353,
   39.22 +	TRACE_LINES_CMD,
   39.23 +	BAD_TRACE_LINES,
   39.24  	$
   39.25  
   39.26  -- don't change this please, but please look for -deleted- items before adding new options
   39.27 @@ -377,12 +389,25 @@
   39.28  	{352, "There is no watcom instalation under specified Watom Path [1]"},
   39.29  	{NONSTANDARD_LIBRARY, "Use a non-standard library when building a shared object"},
   39.30  	{354, "External debugger"},
   39.31 +	
   39.32  	{355, "Use the -mno-cygwin flag with MinGW"},
   39.33  	{356, "Specify the target architecture (X86, X86_64, ARM)"},
   39.34  	{357, "Unknown architecture: [1].  Supported architectures are: [2]"},
   39.35 +	{EXPECTED_VALID_MEMSTRUCT, "Expected to see a valid memory structure type" },
   39.36 +	{FP_NOT_SIGNED, "Floating point data cannot have signed or unsigned modifiers"},
   39.37 +	{ONLY_DOUBLE_FP_LONG, "Only 'double' floating point type can have the 'long' modifier"},
   39.38 +	{ONLY_INT_LONG_LONG, "Only 'int' or 'long' integers can have the 'long' modifier"},
   39.39 +	{NOT_A_MEMBER, "[1] is not a member of memstruct or memunion [2]"},
   39.40 +	{NOT_A_POINTER_OR_MEMSTRUCT, "Member is not a pointer or an embedded memstruct"},
   39.41 +	{CANNOT_ASSIGN_NONPRIMATIVE, "Cannot assign to a non-primitive, non-pointer memstruct" },
   39.42 +	{EXPECTED_PRIMITIVE_MEMSTRUCT_TYPE, "Expected to see a valid primitive memory structure type" },
   39.43  	{ MSG_CC_PREFIX, "Prefix for compiler and related binaries"},
   39.44  	{DUPLICATE_MULTI_ASSIGN, "duplicate variables in left hand side of multiple assignment"},
   39.45  	{MISSING_CMD_PARAMETER, "Command line argument [1] requires a parameter"},
   39.46 +	{MISSING_MEMSTRUCT_MEMBER, "Expected a valid memstruct and member expression"},
   39.47 +	{DEREFERENCING_NONPOINTER, "Cannot dereference a non-pointer memstruct member"},
   39.48 +	{TRACE_LINES_CMD, "Specify the number of lines to use in ctrace.out"},
   39.49 +	{BAD_TRACE_LINES, "the -trace-lines option requires a valid number\n"},
   39.50  	$
   39.51  }
   39.52  
    40.1 --- a/source/opnames.e	Mon Dec 19 23:19:58 2011 -0300
    40.2 +++ b/source/opnames.e	Wed Dec 21 16:45:49 2011 -0300
    40.3 @@ -227,5 +227,19 @@
    40.4  	"PEEK_POINTER",
    40.5  	"SIZEOF",
    40.6  	"STARTLINE_BREAK",
    40.7 +	"MEMSTRUCT_ACCESS",
    40.8 +	"MEMSTRUCT_ARRAY",
    40.9 +	"PEEK_MEMBER",
   40.10 +	"MEMSTRUCT_READ",
   40.11 +	"MEMSTRUCT_ASSIGN",
   40.12 +	"MEMSTRUCT_PLUS",
   40.13 +	"MEMSTRUCT_MINUS",
   40.14 +	"MEMSTRUCT_MULTIPLY",
   40.15 +	"MEMSTRUCT_DIVIDE",
   40.16 +	"MEM_TYPE_CHECK",
   40.17 +	"ADDRESSOF",
   40.18 +	"OFFSETOF",
   40.19 +	"PEEK_ARRAY",
   40.20 +	"ARRAY_ACCESS",
   40.21  	$
   40.22  }
    41.1 --- a/source/opnames.h	Mon Dec 19 23:19:58 2011 -0300
    41.2 +++ b/source/opnames.h	Wed Dec 21 16:45:49 2011 -0300
    41.3 @@ -217,5 +217,20 @@
    41.4  	"PEEK8U",
    41.5  	"POKE_POINTER",
    41.6  	"PEEK_POINTER",
    41.7 -	"SIZEOF"
    41.8 +	"SIZEOF",
    41.9 +	"STARTLINE_BREAK",
   41.10 +	"MEMSTRUCT_ACCESS",
   41.11 +	"MEMSTRUCT_ARRAY",
   41.12 +	"PEEK_MEMBER",
   41.13 +	"MEMSTRUCT_READ",
   41.14 +	"MEMSTRUCT_ASSIGN",
   41.15 +	"MEMSTRUCT_PLUS",
   41.16 +	"MEMSTRUCT_MINUS",
   41.17 +	"MEMSTRUCT_MULTIPLY",
   41.18 +	"MEMSTRUCT_DIVIDE",
   41.19 +	"MEM_TYPE_CHECK",
   41.20 +	"ADDRESSOF",
   41.21 +	"OFFSETOF",
   41.22 +	"PEEK_ARRAY,
   41.23 +	"ARRAY_ACCESS"
   41.24  };
    42.1 --- a/source/parser.e	Mon Dec 19 23:19:58 2011 -0300
    42.2 +++ b/source/parser.e	Wed Dec 21 16:45:49 2011 -0300
    42.3 @@ -31,12 +31,15 @@
    42.4  include block.e
    42.5  include keylist.e
    42.6  include coverage.e
    42.7 +include memstruct.e
    42.8  include msgtext.e
    42.9  
   42.10  constant UNDEFINED = -999
   42.11  constant DEFAULT_SAMPLE_SIZE = 25000  -- for time profile
   42.12  constant ASSIGN_OPS = {EQUALS, PLUS_EQUALS, MINUS_EQUALS, MULTIPLY_EQUALS,
   42.13  						DIVIDE_EQUALS, CONCAT_EQUALS}
   42.14 +constant MEMSTRUCT_ASSIGN_OPS = {MEMSTRUCT_ASSIGN, MEMSTRUCT_PLUS, MEMSTRUCT_MINUS, MEMSTRUCT_MULTIPLY,
   42.15 +						MEMSTRUCT_DIVIDE, 0}
   42.16  constant SCOPE_TYPES = {SC_LOCAL, SC_GLOBAL, SC_PUBLIC, SC_EXPORT, SC_UNDEFINED}
   42.17  
   42.18  --*****************
   42.19 @@ -271,9 +274,8 @@
   42.20  			set_qualified_fwd( SymTab[sym][S_FILE_NO] )
   42.21  		end if
   42.22  		ref = new_forward_reference( GLOBAL_INIT_CHECK, tok[T_SYM], GLOBAL_INIT_CHECK )
   42.23 -
   42.24  		emit_op( GLOBAL_INIT_CHECK )
   42.25 -		emit_addr( sym )
   42.26 +		emit_addr( 0 )
   42.27  	end if
   42.28  end procedure
   42.29  
   42.30 @@ -322,7 +324,6 @@
   42.31  	elsif ref and sym > 0 and sym_mode( sym ) = M_CONSTANT and equal( NOVALUE, sym_obj( sym ) ) then
   42.32  		emit_op( GLOBAL_INIT_CHECK )
   42.33  		emit_addr(sym)
   42.34 -	
   42.35  	end if
   42.36  	-- else .. ignore loop vars, constants
   42.37  end procedure
   42.38 @@ -471,7 +472,7 @@
   42.39  	exit_list = exit_list [1..exit_top]
   42.40  end procedure
   42.41  
   42.42 -procedure putback(token t)
   42.43 +export procedure putback(token t)
   42.44  -- push a scanner token back onto the input stream
   42.45  	backed_up_tok = append(backed_up_tok, t)
   42.46  	
   42.47 @@ -648,7 +649,7 @@
   42.48    	return t
   42.49  end function
   42.50  
   42.51 -function next_token()
   42.52 +export function next_token()
   42.53  -- read next scanner token
   42.54  	token t
   42.55  	sequence s
   42.56 @@ -728,7 +729,7 @@
   42.57  	return n
   42.58  end function
   42.59  
   42.60 -procedure tok_match(integer tok, integer prevtok = 0)
   42.61 +export procedure tok_match(integer tok, integer prevtok = 0)
   42.62  -- match token or else syntax error
   42.63  	token t
   42.64  	sequence expected, actual, prevname
   42.65 @@ -1053,7 +1054,6 @@
   42.66  		end switch
   42.67  	end while
   42.68  
   42.69 -	integer fc_pc = length( Code ) + 1
   42.70  	emit_opnd( args )
   42.71  
   42.72  	op_info1 = proc
   42.73 @@ -1173,7 +1173,26 @@
   42.74  	if id = FUNC or id = TYPE then
   42.75  		-- to warn if not in include tree
   42.76  		UndefinedVar( tok[T_SYM] )
   42.77 +		
   42.78 +		switch SymTab[tok[T_SYM]][S_OPCODE] do
   42.79 +			case SIZEOF then
   42.80 +				if parse_sizeof() then
   42.81 +					-- special parsing for multi-part memstruct types
   42.82 +					tok_match( RIGHT_ROUND )
   42.83 +					scope = SymTab[tok[T_SYM]][S_SCOPE]
   42.84 +					opcode = SymTab[tok[T_SYM]][S_OPCODE]
   42.85 +					goto "args_parsed"
   42.86 +				else
   42.87 +					goto "after left round"
   42.88 +				end if
   42.89 +			case OFFSETOF then
   42.90 +				parse_memstruct_func( SymTab[tok[T_SYM]][S_OPCODE] )
   42.91 +				scope = SymTab[tok[T_SYM]][S_SCOPE]
   42.92 +				opcode = SymTab[tok[T_SYM]][S_OPCODE]
   42.93 +				goto "args_parsed"
   42.94 +		end switch
   42.95  	end if
   42.96 +	
   42.97  
   42.98  	e = SymTab[tok[T_SYM]][S_EFFECT]
   42.99  	if e then
  42.100 @@ -1192,6 +1211,8 @@
  42.101  		end if
  42.102  	end if
  42.103  	tok_match(LEFT_ROUND)
  42.104 +	
  42.105 +	label "after left round"
  42.106  	scope = SymTab[tok[T_SYM]][S_SCOPE]
  42.107  	opcode = SymTab[tok[T_SYM]][S_OPCODE]
  42.108  	if equal(SymTab[tok[T_SYM]][S_NAME],"object") and scope = SC_PREDEF then
  42.109 @@ -1202,6 +1223,7 @@
  42.110  		ParseArgs(tok[T_SYM])
  42.111  	end if
  42.112  
  42.113 +	label "args_parsed"
  42.114  	if scope = SC_PREDEF then
  42.115  		emit_op(opcode)
  42.116  	else
  42.117 @@ -1214,6 +1236,7 @@
  42.118  			end if
  42.119  		end if
  42.120  	end if
  42.121 +	
  42.122  end procedure
  42.123  
  42.124  procedure Factor()
  42.125 @@ -1230,7 +1253,40 @@
  42.126  		tok = read_recorded_token(tok[T_SYM])
  42.127  		id = tok[T_ID]
  42.128  	end if
  42.129 +	
  42.130  	switch id label "factor" do
  42.131 +		case MEMTYPE then
  42.132 +			-- use its alias
  42.133 +			sym = tok[T_SYM]
  42.134 +			id = SymTab[sym][S_MEM_TYPE]
  42.135 +			
  42.136 +			if not id then
  42.137 +				sym = SymTab[sym][S_MEM_PARENT]
  42.138 +				id = sym_token( sym )
  42.139 +				tok[T_SYM] = sym
  42.140 +				tok[T_ID]  = id
  42.141 +			end if
  42.142 +			
  42.143 +			fallthru
  42.144 +		case MEMSTRUCT, QUALIFIED_MEMSTRUCT, MEMUNION, QUALIFIED_MEMUNION then
  42.145 +			-- probably needs error checking or something to make sure 
  42.146 +			-- the struct makes sense
  42.147 +			
  42.148 +			token look_ahead = next_token()
  42.149 +			putback( look_ahead )
  42.150 +			if look_ahead[T_ID] = DOT then
  42.151 +				-- a "naked" memstruct access...offsetof() uses this
  42.152 +				putback( tok )
  42.153 +				
  42.154 +				-- Need this extra push, used by MEMSTRUCT_ACCESS / PEEK_MEMBER
  42.155 +				-- which OFFSETOF will eat.  Otherwise, we corrupt the stack.
  42.156 +				Push( tok[T_SYM] )
  42.157 +				MemStruct_access( tok[T_SYM], FALSE )
  42.158 +			else
  42.159 +				
  42.160 +				emit_opnd( tok[T_SYM] )
  42.161 +			end if
  42.162 +			
  42.163  		case VARIABLE, QUALIFIED_VARIABLE then
  42.164  			sym = tok[T_SYM]
  42.165  			if sym < 0 or SymTab[sym][S_SCOPE] = SC_UNDEFINED then
  42.166 @@ -1256,35 +1312,42 @@
  42.167  
  42.168  			short_circuit -= 1
  42.169  			tok = next_token()
  42.170 -			current_sequence = append(current_sequence, sym)
  42.171 -			while tok[T_ID] = LEFT_SQUARE do
  42.172 -				subs_depth += 1
  42.173 -				if lhs_subs_level >= 0 then
  42.174 -					lhs_subs_level += 1
  42.175 -				end if
  42.176 -				save_factors = factors
  42.177 -				save_lhs_subs_level = lhs_subs_level
  42.178 -				call_proc(forward_expr, {})
  42.179 -				tok = next_token()
  42.180 -				if tok[T_ID] = SLICE then
  42.181 +			
  42.182 +			
  42.183 +			if tok[T_ID] = DOT then
  42.184 +				MemStruct_access( sym, FALSE )
  42.185 +			else
  42.186 +				current_sequence = append(current_sequence, sym)
  42.187 +				while tok[T_ID] = LEFT_SQUARE do
  42.188 +					subs_depth += 1
  42.189 +					if lhs_subs_level >= 0 then
  42.190 +						lhs_subs_level += 1
  42.191 +					end if
  42.192 +					save_factors = factors
  42.193 +					save_lhs_subs_level = lhs_subs_level
  42.194  					call_proc(forward_expr, {})
  42.195 -					emit_op(RHS_SLICE)
  42.196 -					tok_match(RIGHT_SQUARE)
  42.197  					tok = next_token()
  42.198 -					exit
  42.199 -				else
  42.200 -					putback(tok)
  42.201 -					tok_match(RIGHT_SQUARE)
  42.202 -					subs_depth -= 1
  42.203 -					current_sequence = head( current_sequence, length( current_sequence ) - 1 )
  42.204 -					emit_op(RHS_SUBS) -- current_sequence will be updated
  42.205 -				end if
  42.206 -				factors = save_factors
  42.207 -				lhs_subs_level = save_lhs_subs_level
  42.208 -				tok = next_token()
  42.209 -			end while
  42.210 -			current_sequence = head( current_sequence, length( current_sequence ) - 1 )
  42.211 -			putback(tok)
  42.212 +					if tok[T_ID] = SLICE then
  42.213 +						call_proc(forward_expr, {})
  42.214 +						emit_op(RHS_SLICE)
  42.215 +						tok_match(RIGHT_SQUARE)
  42.216 +						tok = next_token()
  42.217 +						exit
  42.218 +					else
  42.219 +						putback(tok)
  42.220 +						tok_match(RIGHT_SQUARE)
  42.221 +						subs_depth -= 1
  42.222 +						current_sequence = head( current_sequence, length( current_sequence ) - 1 )
  42.223 +						emit_op(RHS_SUBS) -- current_sequence will be updated
  42.224 +					end if
  42.225 +					factors = save_factors
  42.226 +					lhs_subs_level = save_lhs_subs_level
  42.227 +					tok = next_token()
  42.228 +				end while
  42.229 +				current_sequence = head( current_sequence, length( current_sequence ) - 1 )
  42.230 +				putback(tok)
  42.231 +			end if
  42.232 +			
  42.233  			short_circuit += 1
  42.234  
  42.235  		case DOLLAR then
  42.236 @@ -1416,7 +1479,7 @@
  42.237  constant boolOps = {OR, AND, XOR}
  42.238  export sequence ExprLine
  42.239  export integer expr_bp
  42.240 -procedure Expr()
  42.241 +export procedure Expr()
  42.242  -- Parse a general expression
  42.243  -- Use either short circuit or full evaluation.
  42.244  	token tok
  42.245 @@ -1480,6 +1543,59 @@
  42.246  
  42.247  forward_expr = routine_id("Expr")
  42.248  
  42.249 +procedure emit_mem_type_check( symtab_index var, symtab_index type_sym, symtab_index member_sym, symtab_index pointer, integer op )
  42.250 +	if op != MEMSTRUCT_ASSIGN then
  42.251 +		-- We have to read the value first via PEEK_MEMBER
  42.252 +		emit_opnd( pointer )
  42.253 +		emit_opnd( member_sym )
  42.254 +		emit_op( PEEK_MEMBER )
  42.255 +	else
  42.256 +		emit_opnd( var )
  42.257 +	end if
  42.258 +	
  42.259 +	if type_sym > 0 then
  42.260 +		op_info1 = type_sym
  42.261 +		emit_or_inline()
  42.262 +	else
  42.263 +		-- we haven't resolved the type yet!
  42.264 +		integer val_sym = Pop()
  42.265 +		integer ref = new_forward_reference( MEM_TYPE_CHECK, type_sym, TYPE_CHECK_FORWARD )
  42.266 +		Code &= { TYPE_CHECK_FORWARD, val_sym, OpTypeCheck }
  42.267 +	end if
  42.268 +	
  42.269 +	emit_opnd( member_sym )
  42.270 +	emit_op(MEM_TYPE_CHECK)
  42.271 +end procedure
  42.272 +
  42.273 +procedure MemTypeCheck( symtab_index var, symtab_index member_sym, symtab_index pointer, integer op )
  42.274 +	if member_sym < 0 then
  42.275 +		-- TODO: need to handle fwd refs here
  42.276 +		return
  42.277 +	end if
  42.278 +	if length( SymTab[member_sym] ) != SIZEOF_MEMSTRUCT_ENTRY then
  42.279 +		InternalErr( sprintf("Error on typechecking %s", { sym_name( member_sym ) }) )
  42.280 +	end if
  42.281 +	integer type_sym = SymTab[member_sym][S_MEM_TYPE]
  42.282 +	if 0 = type_sym then
  42.283 +		-- no type for this member
  42.284 +		return
  42.285 +	end if
  42.286 +	
  42.287 +	if TRANSLATE then
  42.288 +		if OpTypeCheck then
  42.289 +			if SymTab[type_sym][S_EFFECT] then
  42.290 +				-- only call those with side effects
  42.291 +				emit_mem_type_check( var, type_sym, member_sym, pointer, op )
  42.292 +			end if
  42.293 +		end if
  42.294 +	else
  42.295 +		if OpTypeCheck then
  42.296 +			emit_mem_type_check( var, type_sym, member_sym, pointer, op )
  42.297 +		end if
  42.298 +	end if
  42.299 +	
  42.300 +end procedure
  42.301 +
  42.302  procedure TypeCheck(symtab_index var)
  42.303  -- emit code to type-check a var (after it has been assigned-to)
  42.304  	integer which_type
  42.305 @@ -1574,6 +1690,35 @@
  42.306  	end if
  42.307  end procedure
  42.308  
  42.309 +function check_assign_op( token left_var )
  42.310 +	token tok = next_token()
  42.311 +	integer assign_op = tok[T_ID]
  42.312 +	
  42.313 +	if not find(assign_op, ASSIGN_OPS) then
  42.314 +		sequence lname = sym_name( left_var[T_SYM] )
  42.315 +		if assign_op = DOT then
  42.316 +			-- memstruct
  42.317 +			MemStruct_access( left_var[T_SYM], TRUE )
  42.318 +			assign_op = check_assign_op( left_var )
  42.319 +			integer ox = find( assign_op, ASSIGN_OPS )
  42.320 +			assign_op = 0
  42.321 +			if ox then
  42.322 +				assign_op = MEMSTRUCT_ASSIGN_OPS[ox]
  42.323 +			end if
  42.324 +			if not assign_op then
  42.325 +				CompileErr(76, {lname})
  42.326 +			end if
  42.327 +			return assign_op
  42.328 +		
  42.329 +		elsif assign_op = COLON then
  42.330 +			CompileErr(133, {lname})
  42.331 +		else
  42.332 +			CompileErr(76, {lname})
  42.333 +		end if
  42.334 +	end if
  42.335 +	return assign_op
  42.336 +end function
  42.337 +
  42.338  procedure Assignment(token left_var)
  42.339  -- parse an assignment statement
  42.340  	token tok
  42.341 @@ -1651,32 +1796,36 @@
  42.342  	end while
  42.343  
  42.344  	lhs_ptr = FALSE
  42.345 -
  42.346 -	assign_op = tok[T_ID]
  42.347 -	if not find(assign_op, ASSIGN_OPS) then
  42.348 -		sequence lname = SymTab[left_var[T_SYM]][S_NAME]
  42.349 -		if assign_op = COLON then
  42.350 -			CompileErr(133, {lname})
  42.351 -		else
  42.352 -			CompileErr(76, {lname})
  42.353 -		end if
  42.354 -	end if
  42.355 -
  42.356 -	if subs = 0 then
  42.357 +	
  42.358 +	putback( tok )
  42.359 +	assign_op = check_assign_op( left_var )
  42.360 +
  42.361 +	if subs = 0 label "subs_if" then
  42.362  		-- not subscripted
  42.363  		integer temp_len = length(Code)
  42.364 -		if assign_op = EQUALS then
  42.365 -			Expr() -- RHS expression
  42.366 -			InitCheck(left_sym, FALSE)
  42.367 -		else
  42.368 -			InitCheck(left_sym, TRUE)
  42.369 -			if left_sym > 0 then
  42.370 -				SymTab[left_sym][S_USAGE] = or_bits(SymTab[left_sym][S_USAGE], U_READ)
  42.371 -			end if
  42.372 -			emit_opnd(left_sym)
  42.373 -			Expr() -- RHS expression
  42.374 -			emit_assign_op(assign_op)
  42.375 -		end if
  42.376 +		switch assign_op do
  42.377 +			case EQUALS then
  42.378 +				Expr() -- RHS expression
  42.379 +				InitCheck(left_sym, FALSE)
  42.380 +			
  42.381 +			case MEMSTRUCT_ASSIGN, MEMSTRUCT_PLUS, MEMSTRUCT_MINUS, 
  42.382 +					MEMSTRUCT_MULTIPLY, MEMSTRUCT_DIVIDE then
  42.383 +				
  42.384 +				Expr()
  42.385 +				integer top = length( Code )
  42.386 +				emit_op( assign_op )
  42.387 +				MemTypeCheck( Code[$], Code[$-2], Code[top], assign_op )
  42.388 +				break "subs_if"
  42.389 +			case else
  42.390 +				InitCheck(left_sym, TRUE)
  42.391 +				if left_sym > 0 then
  42.392 +					SymTab[left_sym][S_USAGE] = or_bits(SymTab[left_sym][S_USAGE], U_READ)
  42.393 +				end if
  42.394 +				emit_opnd(left_sym)
  42.395 +				Expr() -- RHS expression
  42.396 +				emit_assign_op(assign_op)
  42.397 +				
  42.398 +		end switch
  42.399  		emit_op(ASSIGN)
  42.400  		TypeCheck(left_sym)
  42.401  	else
  42.402 @@ -4671,7 +4820,17 @@
  42.403  
  42.404  			elsif id = PROCEDURE or id = FUNCTION or id = TYPE_DECL then
  42.405  				SubProg(id, scope, deprecated)
  42.406 +				
  42.407 +
  42.408 +			elsif id = MEMSTRUCT_DECL then
  42.409 +				MemStruct_declaration( scope )
  42.410  			
  42.411 +			elsif id = MEMUNION_DECL then
  42.412 +				MemUnion_declaration( scope )
  42.413 +			
  42.414 +			elsif id = MEMTYPE then
  42.415 +				MemType( scope )
  42.416 +				
  42.417  			elsif (scope = SC_PUBLIC) and id = INCLUDE then
  42.418  				IncludeScan( 1 )
  42.419  				PushGoto()
  42.420 @@ -4857,8 +5016,18 @@
  42.421  			StartSourceLine( TRUE )
  42.422  			Multi_assign()
  42.423  
  42.424 +
  42.425 +		elsif id = MEMSTRUCT_DECL then
  42.426 +			MemStruct_declaration( SC_LOCAL )
  42.427 +		
  42.428 +		elsif id = MEMUNION_DECL then
  42.429 +			MemUnion_declaration( SC_LOCAL )
  42.430 +		
  42.431  		elsif id = ILLEGAL_CHAR then
  42.432  			CompileErr(102)
  42.433 +			
  42.434 +		elsif id = MEMTYPE then
  42.435 +			MemType( SC_LOCAL )
  42.436  
  42.437  		else
  42.438  			if nested then
    43.1 --- a/source/redef.h	Mon Dec 19 23:19:58 2011 -0300
    43.2 +++ b/source/redef.h	Wed Dec 21 16:45:49 2011 -0300
    43.3 @@ -209,4 +209,18 @@
    43.4  #define L_POKE_POINTER  POKE_POINTER
    43.5  #define L_PEEK_POINTER  PEEK_POINTER
    43.6  #define L_SIZEOF        SIZEOF
    43.7 -#define L_STARTLINE_BREAK STARTLINE_BREAK
    43.8 +#define L_STARTLINE_BREAK     STARTLINE_BREAK
    43.9 +#define L_MEMSTRUCT_ACCESS    MEMSTRUCT_ACCESS
   43.10 +#define L_MEMSTRUCT_ARRAY     MEMSTRUCT_ARRAY
   43.11 +#define L_PEEK_MEMBER         PEEK_MEMBER
   43.12 +#define L_MEMSTRUCT_READ MEMSTRUCT_SERIALIZE
   43.13 +#define L_MEMSTRUCT_ASSIGN    MEMSTRUCT_ASSIGN
   43.14 +#define L_MEMSTRUCT_PLUS      MEMSTRUCT_PLUS
   43.15 +#define L_MEMSTRUCT_MINUS     MEMSTRUCT_MINUS
   43.16 +#define L_MEMSTRUCT_MULTIPLY  MEMSTRUCT_MULTIPLY
   43.17 +#define L_MEMSTRUCT_DIVIDE    MEMSTRUCT_DIVIDE
   43.18 +#define L_MEM_TYPE_CHECK      MEM_TYPE_CHECK
   43.19 +#define L_ADDRESSOF           ADDRESSOF
   43.20 +#define L_OFFSETOF            OFFSETOF
   43.21 +#define L_PEEK_ARRAY          PEEK_ARRAY
   43.22 +#define L_ARRAY_ACCESS        ARRAY_ACCESS
    44.1 --- a/source/reswords.e	Mon Dec 19 23:19:58 2011 -0300
    44.2 +++ b/source/reswords.e	Wed Dec 21 16:45:49 2011 -0300
    44.3 @@ -227,7 +227,21 @@
    44.4  	PEEK_POINTER        = 216,
    44.5  	SIZEOF              = 217,
    44.6  	STARTLINE_BREAK     = 218,
    44.7 -	MAX_OPCODE          = 218
    44.8 +	MEMSTRUCT_ACCESS    = 219,
    44.9 +	MEMSTRUCT_ARRAY     = 220,
   44.10 +	PEEK_MEMBER         = 221,
   44.11 +	MEMSTRUCT_READ      = 222,
   44.12 +	MEMSTRUCT_ASSIGN    = 223, 
   44.13 +	MEMSTRUCT_PLUS      = 224,
   44.14 +	MEMSTRUCT_MINUS     = 225,
   44.15 +	MEMSTRUCT_MULTIPLY  = 226,
   44.16 +	MEMSTRUCT_DIVIDE    = 227,
   44.17 +	MEM_TYPE_CHECK      = 228,
   44.18 +	ADDRESSOF           = 229,
   44.19 +	OFFSETOF            = 230,
   44.20 +	PEEK_ARRAY          = 231,
   44.21 +	ARRAY_ACCESS        = 232,
   44.22 +	MAX_OPCODE          = 232
   44.23  
   44.24  
   44.25  -- adding new opcodes possibly affects reswords.h (C-coded backend),
   44.26 @@ -308,7 +322,11 @@
   44.27  	PUBLIC,
   44.28  	FALLTHRU,
   44.29  	ROUTINE,
   44.30 -	DEPRECATE
   44.31 +	MEMSTRUCT_DECL,
   44.32 +	MEMUNION_DECL,
   44.33 +	DEPRECATE,
   44.34 +	MEMTYPE,
   44.35 +	$
   44.36  
   44.37  export enum
   44.38  	FUNC = 501,
   44.39 @@ -333,7 +351,29 @@
   44.40  	QUALIFIED_FUNC,
   44.41  	QUALIFIED_PROC,
   44.42  	QUALIFIED_TYPE,
   44.43 -	NAMESPACE
   44.44 +	NAMESPACE,
   44.45 +	MEMSTRUCT,
   44.46 +	QUALIFIED_MEMSTRUCT,
   44.47 +	MEMUNION,
   44.48 +	QUALIFIED_MEMUNION,
   44.49 +	MS_SIGNED,
   44.50 +	MS_UNSIGNED,
   44.51 +	MS_POINTER,
   44.52 +	MS_CHAR,
   44.53 +	MS_SHORT,
   44.54 +	MS_INT,
   44.55 +	MS_LONG,
   44.56 +	MS_LONGLONG,
   44.57 +	MS_FLOAT,
   44.58 +	MS_DOUBLE,
   44.59 +	MS_LONGDOUBLE,
   44.60 +	MS_EUDOUBLE,
   44.61 +	MS_OBJECT,
   44.62 +	MS_MEMBER,
   44.63 +	MS_AS,
   44.64 +	
   44.65 +	LAST_TOKEN,
   44.66 +	$
   44.67  
   44.68  enum -- token category name id
   44.69  	TC_ILLCHAR,
    45.1 --- a/source/reswords.h	Mon Dec 19 23:19:58 2011 -0300
    45.2 +++ b/source/reswords.h	Wed Dec 21 16:45:49 2011 -0300
    45.3 @@ -229,7 +229,21 @@
    45.4  #define PEEK_POINTER        216
    45.5  #define SIZEOF              217
    45.6  #define STARTLINE_BREAK     218
    45.7 -#define MAX_OPCODE          218
    45.8 +#define MEMSTRUCT_ACCESS    219
    45.9 +#define MEMSTRUCT_ARRAY     220
   45.10 +#define PEEK_MEMBER         221
   45.11 +#define MEMSTRUCT_READ 222
   45.12 +#define MEMSTRUCT_ASSIGN    223 
   45.13 +#define MEMSTRUCT_PLUS      224
   45.14 +#define MEMSTRUCT_MINUS     225
   45.15 +#define MEMSTRUCT_MULTIPLY  226
   45.16 +#define MEMSTRUCT_DIVIDE    227
   45.17 +#define MEM_TYPE_CHECK      228
   45.18 +#define ADDRESSOF           229
   45.19 +#define OFFSETOF            230
   45.20 +#define PEEK_ARRAY          231
   45.21 +#define ARRAY_ACCESS        232
   45.22 +#define MAX_OPCODE          232
   45.23  
   45.24  /* remember to update reswords.e, opnames.e,
   45.25     opnames.h, optable[], localjumptab[]
   45.26 @@ -243,6 +257,29 @@
   45.27  #define FUNC              501
   45.28  #define TYPE              504
   45.29  
   45.30 +
   45.31 +#define MEMTYPE              436
   45.32 +
   45.33 +#define MEMSTRUCT            524
   45.34 +#define QUALIFIED_MEMSTRUCT  523
   45.35 +#define MEMUNION             526
   45.36 +#define QUALIFIED_MEMUNION   527
   45.37 +#define MS_SIGNED            528
   45.38 +#define MS_UNSIGNED          528
   45.39 +#define MS_POINTER           530
   45.40 +#define MS_CHAR              531
   45.41 +#define MS_SHORT             532
   45.42 +#define MS_INT               533
   45.43 +#define MS_LONG              534
   45.44 +#define MS_LONGLONG          535
   45.45 +#define MS_FLOAT             536
   45.46 +#define MS_DOUBLE            537
   45.47 +#define MS_LONGDOUBLE        538
   45.48 +#define MS_EUDOUBLE          539
   45.49 +#define MS_OBJECT            540
   45.50 +#define MS_MEMBER            541
   45.51 +#define MS_AS                542
   45.52 +
   45.53  //struct key {
   45.54  //  char *name;
   45.55  //  short int scope;    /* keyword or predefined */
    46.1 --- a/source/scanner.e	Mon Dec 19 23:19:58 2011 -0300
    46.2 +++ b/source/scanner.e	Wed Dec 21 16:45:49 2011 -0300
    46.3 @@ -1739,7 +1739,9 @@
    46.4  					ch = getch()
    46.5  				end while
    46.6  			elsif char_class[ch] = LETTER then
    46.7 -				CompileErr(127, {{ch}})
    46.8 +				ungetch()
    46.9 +				return { DOT, 0 }
   46.10 +				--CompileErr(127, {{ch}})
   46.11  			end if
   46.12  
   46.13  			ungetch()
   46.14 @@ -1767,6 +1769,10 @@
   46.15  				CompileErr(125, nbasecode[basetype])
   46.16  			end if
   46.17  
   46.18 +			if equal( ".", yytext ) then
   46.19 +				return { DOT, 0 }
   46.20 +			end if
   46.21 +			
   46.22  			-- f.p. or large int
   46.23  			d = my_sscanf(yytext)
   46.24  			if sequence(d) then
    47.1 --- a/source/shift.e	Mon Dec 19 23:19:58 2011 -0300
    47.2 +++ b/source/shift.e	Wed Dec 21 16:45:49 2011 -0300
    47.3 @@ -35,11 +35,13 @@
    47.4  procedure init_op_info()
    47.5  	op_info = repeat( 0, MAX_OPCODE )
    47.6  	op_info[ABORT               ] = { FIXED_SIZE, 2, {}, {}, {} }   -- ary: pun
    47.7 +	op_info[ADDRESSOF           ] = { FIXED_SIZE, 3, {}, {2}, {} }
    47.8  	op_info[AND                 ] = { FIXED_SIZE, 4, {}, {}, {} }   -- ary: bin
    47.9  	op_info[AND_BITS            ] = { FIXED_SIZE, 4, {}, {3}, {} }   -- ary: bin
   47.10  	op_info[APPEND              ] = { FIXED_SIZE, 4, {}, {3}, {} }   -- ary: bin
   47.11  	op_info[ARCTAN              ] = { FIXED_SIZE, 3, {}, {2}, {} }   -- ary: un
   47.12  	op_info[ASSIGN              ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.13 +	op_info[MEMSTRUCT_ASSIGN    ] = { FIXED_SIZE, 5, {}, {}, {} }
   47.14  	op_info[ASSIGN_I            ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.15  	op_info[ASSIGN_OP_SLICE     ] = { FIXED_SIZE, 5, {}, {4}, {} }
   47.16  	op_info[ASSIGN_OP_SUBS      ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.17 @@ -67,6 +69,7 @@
   47.18  	op_info[DELETE_OBJECT       ] = { FIXED_SIZE, 2, {}, {}, {} }
   47.19  	op_info[DIV2                ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.20  	op_info[DIVIDE              ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.21 +	op_info[MEMSTRUCT_DIVIDE    ] = { FIXED_SIZE, 5, {}, {},  {} }
   47.22  	op_info[ELSE                ] = { FIXED_SIZE, 2, {1}, {}, {} }
   47.23  	op_info[EXIT                ] = { FIXED_SIZE, 2, {1}, {}, {} }
   47.24  	op_info[EXIT_BLOCK          ] = { FIXED_SIZE, 2, {},  {}, {} }
   47.25 @@ -125,9 +128,13 @@
   47.26  	op_info[MATCH_FROM          ] = { FIXED_SIZE, 5, {}, {4}, {} }
   47.27  	op_info[MEM_COPY            ] = { FIXED_SIZE, 4, {}, {}, {} }
   47.28  	op_info[MEM_SET             ] = { FIXED_SIZE, 4, {}, {}, {} }
   47.29 +	op_info[MEMSTRUCT_ARRAY     ] = { FIXED_SIZE, 5, {}, {4}, {} }
   47.30 +	op_info[MEMSTRUCT_READ      ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.31  	op_info[MINUS               ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.32 +	op_info[MEMSTRUCT_MINUS     ] = { FIXED_SIZE, 5, {}, {},  {} }
   47.33  	op_info[MINUS_I             ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.34  	op_info[MULTIPLY            ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.35 +	op_info[MEMSTRUCT_MULTIPLY  ] = { FIXED_SIZE, 5, {}, {},  {} }
   47.36  	op_info[NOP1                ] = { FIXED_SIZE, 1, {}, {}, {} }
   47.37  	op_info[NOPWHILE            ] = { FIXED_SIZE, 1, {}, {}, {} }
   47.38  	op_info[NOP2                ] = { FIXED_SIZE, 2, {}, {}, {} }
   47.39 @@ -143,6 +150,7 @@
   47.40  	op_info[NOTEQ_IFW_I         ] = { FIXED_SIZE, 4, {3}, {}, {} }
   47.41  	op_info[NOT_BITS            ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.42  	op_info[NOT_IFW             ] = { FIXED_SIZE, 3, {2}, {}, {} }
   47.43 +	op_info[OFFSETOF            ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.44  	op_info[OPEN                ] = { FIXED_SIZE, 5, {}, {4}, {} }
   47.45  	op_info[OPTION_SWITCHES     ] = { FIXED_SIZE, 2, {}, {1}, {} }
   47.46  	op_info[OR                  ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.47 @@ -151,6 +159,8 @@
   47.48  	op_info[PASSIGN_OP_SUBS     ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.49  	op_info[PASSIGN_SLICE       ] = { FIXED_SIZE, 5, {}, {1}, {} }
   47.50  	op_info[PASSIGN_SUBS        ] = { FIXED_SIZE, 4, {}, {1}, {} }
   47.51 +	op_info[PEEK_ARRAY          ] = { FIXED_SIZE, 5, {}, {4}, {} }
   47.52 +	op_info[PEEK_MEMBER         ] = { FIXED_SIZE, 5, {}, {4}, {} }
   47.53  	op_info[PEEK_STRING         ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.54  	op_info[PEEK8U              ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.55  	op_info[PEEK8S              ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.56 @@ -164,6 +174,7 @@
   47.57  	op_info[PEEK_POINTER        ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.58  	op_info[PLENGTH             ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.59  	op_info[PLUS                ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.60 +	op_info[MEMSTRUCT_PLUS      ] = { FIXED_SIZE, 5, {}, {},  {} }
   47.61  	op_info[PLUS_I              ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.62  	op_info[PLUS1               ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.63  	op_info[PLUS1_I             ] = { FIXED_SIZE, 4, {}, {3}, {} }
   47.64 @@ -226,6 +237,7 @@
   47.65  	op_info[TIME                ] = { FIXED_SIZE, 2, {}, {1}, {} }
   47.66  	op_info[TRACE               ] = { FIXED_SIZE, 2, {}, {}, {} }
   47.67  	op_info[TYPE_CHECK          ] = { FIXED_SIZE, 1, {}, {}, {} }
   47.68 +	op_info[MEM_TYPE_CHECK      ] = { FIXED_SIZE, 2, {}, {}, {} }
   47.69  	op_info[UMINUS              ] = { FIXED_SIZE, 3, {}, {2}, {} }
   47.70  	op_info[UPDATE_GLOBALS      ] = { FIXED_SIZE, 1, {}, {}, {} }
   47.71  	op_info[WHILE               ] = { FIXED_SIZE, 3, {2}, {}, {} }
   47.72 @@ -262,6 +274,9 @@
   47.73  	op_info[CONCAT_N            ] = { VARIABLE_SIZE, 0, {}, {}, {} } -- target: [pc+1] + 2
   47.74  	op_info[PROC                ] = { VARIABLE_SIZE, 0, {}, {}, {} }
   47.75  	op_info[PROC_TAIL           ] = op_info[PROC]
   47.76 +	
   47.77 +	op_info[MEMSTRUCT_ACCESS    ] = { VARIABLE_SIZE, 0, {}, {}, {} } -- TARGET: [pc+1] + 2
   47.78 +	op_info[ARRAY_ACCESS        ] = { VARIABLE_SIZE, 0, {}, {}, {} } -- TARGET: [pc+1] + 3
   47.79  end procedure
   47.80  
   47.81  init_op_info()
   47.82 @@ -288,6 +303,12 @@
   47.83  			case RIGHT_BRACE_N, CONCAT_N then
   47.84  				int = code[pc+1]
   47.85  				int += 3
   47.86 +			case MEMSTRUCT_ACCESS then
   47.87 +				int = code[pc+1]
   47.88 +				int += 4
   47.89 +			case ARRAY_ACCESS then
   47.90 +				int = code[pc+1]
   47.91 +				int += 5
   47.92  			case else
   47.93  				InternalErr( 269, {op} )
   47.94  		end switch
   47.95 @@ -506,8 +527,11 @@
   47.96  			case FUNC_FORWARD then
   47.97  				return opseq[$]
   47.98  
   47.99 -			case RIGHT_BRACE_N, CONCAT_N then
  47.100 +			case RIGHT_BRACE_N, CONCAT_N, MEMSTRUCT_ACCESS then
  47.101  				return opseq[opseq[2]+2]
  47.102 +				
  47.103 +			case ARRAY_ACCESS then
  47.104 +				return opseq[opseq[2]+3]
  47.105  
  47.106  		end switch
  47.107  	end if
    48.1 --- a/source/symtab.e	Mon Dec 19 23:19:58 2011 -0300
    48.2 +++ b/source/symtab.e	Wed Dec 21 16:45:49 2011 -0300
    48.3 @@ -1,6 +1,7 @@
    48.4  -- (c) Copyright - See License.txt
    48.5  --
    48.6  -- Symbol Table Routines
    48.7 +namespace symtab
    48.8  
    48.9  ifdef ETYPE_CHECK then
   48.10  	with type_check
   48.11 @@ -29,6 +30,19 @@
   48.12  export symtab_index sequence_type     -- s.t. index of sequence type
   48.13  export symtab_index integer_type      -- s.t. index of integer type
   48.14  
   48.15 +export symtab_index ms_char_sym
   48.16 +export symtab_index ms_short_sym
   48.17 +export symtab_index ms_int_sym
   48.18 +export symtab_index ms_long_sym
   48.19 +export symtab_index ms_longlong_sym
   48.20 +export symtab_index ms_object_sym
   48.21 +export symtab_index ms_pointer_sym
   48.22 +export symtab_index ms_float_sym
   48.23 +export symtab_index ms_double_sym
   48.24 +export symtab_index ms_longdouble_sym
   48.25 +export symtab_index ms_eudouble_sym
   48.26 +
   48.27 +
   48.28  ifdef EUDIS then
   48.29  export sequence bucket_hits = repeat( 0, NBUCKETS ) -- count how many times we look at each bucket
   48.30  end ifdef
   48.31 @@ -74,7 +88,6 @@
   48.32  export procedure remove_symbol( symtab_index sym )
   48.33  	integer hash
   48.34  	integer st_ptr
   48.35 -	
   48.36  	hash = SymTab[sym][S_HASHVAL]
   48.37  	st_ptr = buckets[hash]
   48.38  	
   48.39 @@ -436,6 +449,29 @@
   48.40  	return p
   48.41  end function
   48.42  
   48.43 +procedure set_memsize( symtab_index sym, integer kx )
   48.44 +	sequence key = keylist[kx]
   48.45 +	if length( SymTab[sym] ) < SIZEOF_MEMSTRUCT_ENTRY then
   48.46 +		SymTab[sym] &= repeat( 0, SIZEOF_MEMSTRUCT_ENTRY - length( SymTab[sym] ) )
   48.47 +	end if
   48.48 +	if length( key ) >= K_MEM_SIZE then
   48.49 +		SymTab[sym][S_MEM_SIZE] = key[K_MEM_SIZE]
   48.50 +	end if
   48.51 +	switch key[K_NAME] do
   48.52 +		case "char"        then ms_char_sym       = sym
   48.53 +		case "short"       then ms_short_sym      = sym
   48.54 +		case "int"         then ms_int_sym        = sym
   48.55 +		case "long"        then ms_long_sym       = sym
   48.56 +		case "long long"   then ms_longlong_sym   = sym
   48.57 +		case "object"      then ms_object_sym     = sym
   48.58 +		case "float"       then ms_float_sym      = sym
   48.59 +		case "double"      then ms_double_sym     = sym
   48.60 +		case "long double" then ms_longdouble_sym = sym
   48.61 +		case "eudouble"    then ms_eudouble_sym   = sym
   48.62 +		case "pointer"     then ms_pointer_sym    = sym
   48.63 +	end switch
   48.64 +end procedure
   48.65 +
   48.66  export procedure InitSymTab()
   48.67  -- Initialize the Symbol Table
   48.68  	integer hashval, len
   48.69 @@ -460,6 +496,7 @@
   48.70  			SymTab[st_index][S_OPCODE] = keylist[k][K_OPCODE]
   48.71  			SymTab[st_index][S_EFFECT] = keylist[k][K_EFFECT]
   48.72  			SymTab[st_index][S_REFLIST] = {}
   48.73 +			
   48.74  			if length(keylist[k]) > K_EFFECT then
   48.75  			    SymTab[st_index][S_CODE] = keylist[k][K_CODE]
   48.76  			    SymTab[st_index][S_DEF_ARGS] = keylist[k][K_DEF_ARGS]
   48.77 @@ -480,6 +517,8 @@
   48.78  			elsif equal(kname, "sequence") then
   48.79  				sequence_type = st_index
   48.80  			end if
   48.81 +		elsif keylist[k][K_SCOPE] = SC_MEMSTRUCT then
   48.82 +			set_memsize( st_index, k )
   48.83  		end if
   48.84  		if buckets[hashval] = 0 then
   48.85  			buckets[hashval] = st_index
   48.86 @@ -689,6 +728,16 @@
   48.87  end function
   48.88  
   48.89  export integer No_new_entry = 0
   48.90 +
   48.91 +integer inside_memstruct = 0
   48.92 +export procedure enter_memstruct( symtab_index mem_struct )
   48.93 +	inside_memstruct = mem_struct
   48.94 +end procedure
   48.95 +
   48.96 +export procedure leave_memstruct()
   48.97 +	inside_memstruct = 0
   48.98 +end procedure
   48.99 +
  48.100  export function keyfind(sequence word, integer file_no, integer scanning_file = current_file_no, integer namespace_ok = 0, 
  48.101  						integer hashval = hashfn( word ) )
  48.102  -- Uses hashing algorithm to try to match 'word' in the symbol
  48.103 @@ -821,6 +870,13 @@
  48.104  						return tok
  48.105  					end if
  48.106  					break
  48.107 +				
  48.108 +				case SC_MEMSTRUCT then
  48.109 +				
  48.110 +					if inside_memstruct then
  48.111 +						return tok
  48.112 +					end if
  48.113 +					break
  48.114  				case else
  48.115  
  48.116  					if BIND then
  48.117 @@ -1034,7 +1090,6 @@
  48.118  	tok = {VARIABLE, NewEntry(word, 0, defined,
  48.119  					   VARIABLE, hashval, buckets[hashval], 0)}
  48.120  	buckets[hashval] = tok[T_SYM]
  48.121 -	
  48.122  	if file_no != -1 then
  48.123  		SymTab[tok[T_SYM]][S_FILE_NO] = file_no
  48.124  	end if
  48.125 @@ -1046,7 +1101,6 @@
  48.126  -- remove the visibility of a symbol
  48.127  -- by deleting it from its hash chain
  48.128  	symtab_index prev, p
  48.129 -	
  48.130  	p = buckets[SymTab[s][S_HASHVAL]]
  48.131  	prev = 0
  48.132  	
    49.1 --- a/source/symtab.h	Mon Dec 19 23:19:58 2011 -0300
    49.2 +++ b/source/symtab.h	Wed Dec 21 16:45:49 2011 -0300
    49.3 @@ -79,6 +79,17 @@
    49.4  			unsigned int first_line;
    49.5  			unsigned int last_line;
    49.6  		} block;
    49.7 +		struct {
    49.8 +			// for memstructs / memunions only
    49.9 +			struct symtab_entry *next;
   49.10 +			struct symtab_entry *struct_type;
   49.11 +			struct symtab_entry *parent;
   49.12 +			unsigned int size;
   49.13 +			unsigned int offset;
   49.14 +			int array;
   49.15 +			char is_signed;
   49.16 +			char pointer;
   49.17 +		} memstruct;
   49.18  		
   49.19  	} u;
   49.20  	
    50.1 --- a/source/traninit.e	Mon Dec 19 23:19:58 2011 -0300
    50.2 +++ b/source/traninit.e	Wed Dec 21 16:45:49 2011 -0300
    50.3 @@ -330,6 +330,7 @@
    50.4  	c_puts("include/euphoria.h\"\n")
    50.5  
    50.6  	c_puts("#include \"main-.h\"\n\n")
    50.7 +	c_puts("#include \"struct.h\"\n\n")
    50.8  	c_h = open(output_dir & "main-.h", "w")
    50.9  	if c_h = -1 then
   50.10  		CompileErr(47)
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tests/t_memstruct.e	Wed Dec 21 16:45:49 2011 -0300
    51.3 @@ -0,0 +1,301 @@
    51.4 +with trace
    51.5 +
    51.6 +
    51.7 +include std/unittest.e
    51.8 +
    51.9 +include std/machine.e
   51.10 +
   51.11 +type token_id( object id )
   51.12 +	if integer(id) then
   51.13 +		if id < 542 then
   51.14 +			if id > -101 then
   51.15 +				return 1
   51.16 +			end if
   51.17 +		end if
   51.18 +	end if
   51.19 +	return 0
   51.20 +end type
   51.21 +
   51.22 +set_test_verbosity( TEST_SHOW_ALL )
   51.23 +memstruct Var
   51.24 +	pointer symtab_entry declared_in
   51.25 +end memstruct
   51.26 +
   51.27 +memstruct Block
   51.28 +	unsigned int first_line
   51.29 +	unsigned int last_line
   51.30 +end memstruct
   51.31 +
   51.32 +memstruct private_block
   51.33 +	int task_number
   51.34 +	pointer private_block next
   51.35 +	object block[2]
   51.36 +end memstruct
   51.37 +
   51.38 +memstruct Subp
   51.39 +	pointer object code
   51.40 +	pointer symtab_entry temps
   51.41 +	pointer private_block saved_privates
   51.42 +	pointer object block
   51.43 +	pointer int linetab
   51.44 +	unsigned int firstline
   51.45 +	unsigned int num_args
   51.46 +	int resident_task
   51.47 +	unsigned int stack_space
   51.48 +end memstruct
   51.49 +
   51.50 +memunion U
   51.51 +	Var var
   51.52 +	Subp subp
   51.53 +	Block block
   51.54 +end memunion
   51.55 +
   51.56 +memstruct symtab_entry
   51.57 +	object obj
   51.58 +	pointer symtab_entry next
   51.59 +	pointer symtab_entry next_in_block
   51.60 +	char mode
   51.61 +	char scope
   51.62 +	unsigned char file_no
   51.63 +	unsigned char dummy
   51.64 +	token_id as int token
   51.65 +	pointer char name
   51.66 +	U u
   51.67 +end memstruct
   51.68 +
   51.69 +memstruct SymbolTable
   51.70 +	symtab_entry entries[5]
   51.71 +end memstruct
   51.72 +
   51.73 +memtype SymbolTable as SymTab5
   51.74 +
   51.75 +integer bits32 = (sizeof( pointer ) = 4)
   51.76 +procedure basic()
   51.77 +	atom symtab = allocate( sizeof( SymTab5 ) )
   51.78 +	poke( symtab,  repeat( 0, 5 * sizeof( symtab_entry ) ) )
   51.79 +	symtab.symtab_entry.obj = 9
   51.80 +	symtab.symtab_entry.obj += 5
   51.81 +	symtab.symtab_entry.obj -= 2
   51.82 +	symtab.symtab_entry.obj *= 6
   51.83 +	symtab.symtab_entry.obj /= 3
   51.84 +	
   51.85 +	test_equal("object read / write assignment / read", peek_pointer( symtab ), symtab.symtab_entry.obj )
   51.86 +	
   51.87 +	test_equal("addressof 1", symtab, addressof( symtab.symtab_entry.obj ) )
   51.88 +	
   51.89 +	test_equal("offsetof 1", 0, offsetof( symtab_entry.obj ) )
   51.90 +	
   51.91 +	symtab.symtab_entry[1].obj = 1
   51.92 +	symtab.symtab_entry.next = symtab.symtab_entry[1]
   51.93 +	
   51.94 +	integer offset
   51.95 +	if bits32 then
   51.96 +		offset = 4
   51.97 +	else
   51.98 +		offset = 8
   51.99 +	end if
  51.100 +	
  51.101 +	test_equal("pointer read / write", peek_pointer( symtab + offset ), symtab.symtab_entry.next)
  51.102 +	
  51.103 +	symtab.symtab_entry.next.obj = -42
  51.104 +	if bits32 then
  51.105 +		test_equal( "read / write following pointer (32)", peek4s( symtab + sizeof( symtab_entry)), symtab.symtab_entry.next.obj )
  51.106 +	else
  51.107 +		test_equal( "read / write following pointer (64)", peek8s( symtab + sizeof( symtab_entry)), symtab.symtab_entry.next.obj )
  51.108 +	end if
  51.109 +	
  51.110 +	symtab.symtab_entry.u.var.declared_in = 0x01010101
  51.111 +	test_equal("read / write union member", 0x01010101, symtab.symtab_entry.u.var.declared_in )
  51.112 +	
  51.113 +	object serialized = symtab.symtab_entry.u
  51.114 +	test_equal( "addressof vs offsetof", symtab + offsetof( symtab_entry.u ), addressof( symtab.symtab_entry.u ) )
  51.115 +	test_equal("serialize union", {1,1,1,1} & repeat( 0, sizeof( U ) - 4), serialized )
  51.116 +	serialized = {
  51.117 +				symtab.symtab_entry.obj,
  51.118 +				symtab.symtab_entry.next,
  51.119 +				symtab.symtab_entry.next_in_block,
  51.120 +				symtab.symtab_entry.mode,
  51.121 +				symtab.symtab_entry.scope,
  51.122 +				symtab.symtab_entry.file_no,
  51.123 +				symtab.symtab_entry.dummy,
  51.124 +				symtab.symtab_entry.token,
  51.125 +				symtab.symtab_entry.name,
  51.126 +				symtab.symtab_entry.u
  51.127 +			}
  51.128 +	test_equal("serialize struct", serialized, symtab.symtab_entry )
  51.129 +	test_equal("serialize union", 
  51.130 +			peek( { addressof( symtab.symtab_entry.u ), sizeof( U ) } ),
  51.131 +			symtab.symtab_entry.u )
  51.132 +	
  51.133 +	sequence SymTab_Serialized = symtab.SymbolTable
  51.134 +	test_equal( "sizeof arrays of structs", sizeof( symtab_entry ) * 5, sizeof( SymbolTable ) )
  51.135 +	test_equal( "serialize array length", 5, length( SymTab_Serialized[1] ) )
  51.136 +end procedure
  51.137 +basic()
  51.138 +
  51.139 +memstruct ASSIGN
  51.140 +	char a
  51.141 +	unsigned short b
  51.142 +	int c
  51.143 +	long d
  51.144 +	float e
  51.145 +	double f
  51.146 +	long long g
  51.147 +	object h
  51.148 +end memstruct
  51.149 +
  51.150 +memunion UNION_ASSIGN
  51.151 +	char a
  51.152 +	short b
  51.153 +	int c
  51.154 +	long d
  51.155 +	long long e
  51.156 +end memunion
  51.157 +
  51.158 +procedure bulk_assign()
  51.159 +	atom ptr = allocate( sizeof( ASSIGN ), 1 )
  51.160 +	ptr.ASSIGN = {}
  51.161 +	test_equal( "assign an empty sequence -> memset 0", repeat( 0, 8 ), ptr.ASSIGN )
  51.162 +	
  51.163 +	ptr.ASSIGN = { 1, 2, 3, 4, 5, 6, 7, 8}
  51.164 +	test_equal( "bulk assign #1", { 1, 2, 3, 4, 5, 6, 7, 8}, ptr.ASSIGN )
  51.165 +	
  51.166 +	ptr = allocate( sizeof( UNION_ASSIGN ), 1 )
  51.167 +	ptr.UNION_ASSIGN = 0
  51.168 +	test_equal( "union assign atom", repeat( 0, sizeof( UNION_ASSIGN ) ), ptr.UNION_ASSIGN )
  51.169 +	
  51.170 +	ptr.UNION_ASSIGN = {255, 255, 255, 255}
  51.171 +	test_equal( "union assign sequence", -1, ptr.UNION_ASSIGN.c )
  51.172 +	
  51.173 +end procedure
  51.174 +bulk_assign()
  51.175 +
  51.176 +-- Make sure we correctly parse all of these multi-part primitive types:
  51.177 +memtype unsigned int as uint
  51.178 +export memtype signed int as sint
  51.179 +
  51.180 +global memtype long int as lint
  51.181 +memtype signed long int as slint
  51.182 +memtype unsigned long int as ulint
  51.183 +
  51.184 +memtype long long as llong
  51.185 +memtype signed long long as sllong
  51.186 +memtype unsigned long long as ullong
  51.187 +
  51.188 +-- list of memtypes
  51.189 +public memtype 
  51.190 +	long long int as llint,
  51.191 +	signed long long int as sllint,
  51.192 +	unsigned long long int as ullint,
  51.193 +	$
  51.194 +
  51.195 +memtype long double as ldouble
  51.196 +
  51.197 +test_pass( "multi-part memtype declarations" )
  51.198 +
  51.199 +test_equal("sizeof( memtype ) vs sizeof( primitive )", sizeof( uint ), sizeof( unsigned int ) )
  51.200 +
  51.201 +memstruct one_pointer
  51.202 +	pointer int p
  51.203 +end memstruct
  51.204 +test_equal( "sizeof( object ) same as pointer", sizeof( object ), sizeof( one_pointer ) )
  51.205 +
  51.206 +test_equal( "sizeof( float ) = 4", 4, sizeof( float ) )
  51.207 +test_equal( "sizeof( double ) = 8", 8, sizeof( double ) )
  51.208 +
  51.209 +ifdef BITS32 then
  51.210 +	test_equal( "sizeof( eudouble ) = sizeof( double )", sizeof( double ), sizeof( eudouble ) )
  51.211 +elsedef
  51.212 +	test_equal( "sizeof( eudouble ) = sizeof( long double )", sizeof( long double), sizeof( eudouble ) )
  51.213 +end ifdef
  51.214 +
  51.215 +test_equal( "sizeof( pointer ) = sizeof( object )", sizeof( pointer ), sizeof( object ) )
  51.216 +
  51.217 +test_equal( "sizeof( signed int) = sizeof( sint )", sizeof( signed int ), sizeof( sint ) )
  51.218 +test_equal( "sizeof( unsigned int) = sizeof( uint )", sizeof( unsigned int ), sizeof( uint ) )
  51.219 +
  51.220 +test_equal( "sizeof( long int) = sizeof( lint )", sizeof( long int ), sizeof( lint ) )
  51.221 +test_equal( "sizeof( signed long int) = sizeof( slint )", sizeof( signed long int ), sizeof( slint ) )
  51.222 +test_equal( "sizeof( unsigned long int) = sizeof( ulint )", sizeof( unsigned long int ), sizeof( ulint ) )
  51.223 +
  51.224 +test_equal( "sizeof( long long ) = sizeof( llong )", sizeof( long long ), sizeof( llong ) )
  51.225 +test_equal( "sizeof( signed long long ) = sizeof( sllong )", sizeof( signed long long ), sizeof( sllong ) )
  51.226 +test_equal( "sizeof( unsigned long long ) = sizeof( ullong )", sizeof( unsigned long long ), sizeof( ullong ) )
  51.227 +
  51.228 +memstruct ARRAYS
  51.229 +	int   five_ints[5]
  51.230 +	long  ten_longs[10]
  51.231 +	float three_floats[3]
  51.232 +	double four_doubles[4]
  51.233 +end memstruct
  51.234 +
  51.235 +procedure arrays()
  51.236 +	atom ptr = allocate( sizeof( ARRAYS ), 1 )
  51.237 +	
  51.238 +	ptr.ARRAYS.five_ints = { 1, 2, 3, 4, 5 }
  51.239 +	test_equal( "array bulk assign and peek ints", {1,2,3,4,5}, ptr.ARRAYS.five_ints )
  51.240 +	ptr.ARRAYS.five_ints[0] = -1
  51.241 +	test_equal( "array assign and peek element ints", -1, ptr.ARRAYS.five_ints[0] )
  51.242 +	
  51.243 +	ptr.ARRAYS.ten_longs = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
  51.244 +	test_equal( "array bulk assign and peek longs", { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, ptr.ARRAYS.ten_longs )
  51.245 +	ptr.ARRAYS.ten_longs[9] = -1
  51.246 +	test_equal( "array assign and peek element longs", -1, ptr.ARRAYS.ten_longs[9] )
  51.247 +	
  51.248 +	ptr.ARRAYS.three_floats = {1.25, 1.5, 1.375 }
  51.249 +	test_equal( "array bulk assign and peek floats", {1.25, 1.5, 1.375 }, ptr.ARRAYS.three_floats )
  51.250 +	ptr.ARRAYS.three_floats[1] = -1
  51.251 +	test_equal( "array assign and peek element floats", -1, ptr.ARRAYS.three_floats[1] )
  51.252 +	
  51.253 +	ptr.ARRAYS.four_doubles = {1.1, 1.2, 1.3, 4.1 }
  51.254 +	test_equal( "array bulk assign and peek doubles", {1.1, 1.2, 1.3, 4.1 }, ptr.ARRAYS.four_doubles )
  51.255 +	ptr.ARRAYS.four_doubles[2] = 8.6
  51.256 +	test_equal( "array assign and peek element doubles", 8.6, ptr.ARRAYS.four_doubles[2] )
  51.257 +	
  51.258 +end procedure
  51.259 +arrays()
  51.260 +
  51.261 +memstruct POINTERS
  51.262 +	pointer int a
  51.263 +	pointer object b
  51.264 +	pointer unsigned long c
  51.265 +	pointer float d
  51.266 +	pointer double dbl
  51.267 +end memstruct
  51.268 +
  51.269 +procedure pointers()
  51.270 +	atom ptr = allocate( sizeof( POINTERS ), 1 )
  51.271 +	atom secondary = allocate( 1024 )
  51.272 +	ptr.POINTERS = repeat( secondary, 5 )
  51.273 +	
  51.274 +	ptr.POINTERS.a.* = 1234
  51.275 +	test_equal( "dereferenced pointer assign / read int", 1234, ptr.POINTERS.a.* )
  51.276 +	
  51.277 +	ptr.POINTERS.a.* += 5
  51.278 +	test_equal( "dereferenced pointer += int", 1239, ptr.POINTERS.a.* )
  51.279 +	
  51.280 +	ptr.POINTERS.b.* = 123456
  51.281 +	test_equal( "dereferenced pointer assign / read object", 123456, ptr.POINTERS.b.* )
  51.282 +	
  51.283 +	ptr.POINTERS.b.* -= 4
  51.284 +	test_equal( "dereferenced pointer -= object", 123452, ptr.POINTERS.b.* )
  51.285 +	
  51.286 +	ptr.POINTERS.c.* = 51234
  51.287 +	test_equal( "dereferenced pointer assign / read unsigned long", 51234, ptr.POINTERS.c.* )
  51.288 +	
  51.289 +	ptr.POINTERS.c.* *= 2
  51.290 +	test_equal( "dereferenced pointer *= unsigned long", 51234 * 2, ptr.POINTERS.c.* )
  51.291 +	
  51.292 +	ptr.POINTERS.d.* = 3.5
  51.293 +	test_equal( "dereferenced pointer assign / read float", 3.5, ptr.POINTERS.d.* )
  51.294 +	
  51.295 +	ptr.POINTERS.d.* /= 2
  51.296 +	test_equal( "dereferenced pointer /= float", 1.75, ptr.POINTERS.d.* )
  51.297 +	
  51.298 +	ptr.POINTERS.dbl.* = 9.75
  51.299 +	test_equal( "dereferenced pointer assign / read double", 9.75, ptr.POINTERS.dbl.* )
  51.300 +	
  51.301 +end procedure
  51.302 +pointers()
  51.303 +
  51.304 +test_report()

SCM Home | OpenEuphoria.org Home