too many changes to list

This commit is contained in:
Andreas Rumpf 2008-08-23 11:16:44 +02:00
commit 07d5a8085b
200 changed files with 24344 additions and 17809 deletions

View file

@ -17,9 +17,9 @@ proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".}
type
C_TextFile {.importc: "FILE", nodecl.} = record # empty record for
# data hiding
C_BinaryFile {.importc: "FILE", nodecl.} = record
C_TextFile {.importc: "FILE", nodecl, final.} = object # empty record for
# data hiding
C_BinaryFile {.importc: "FILE", nodecl, final.} = object
C_TextFileStar = ptr CTextFile
C_BinaryFileStar = ptr CBinaryFile

View file

@ -18,13 +18,13 @@ proc raiseDivByZero {.exportc: "raiseDivByZero".} =
raise newException(EDivByZero, "divison by zero")
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a + b
result = a +% b
if (result xor a) >= int64(0) or (result xor b) >= int64(0):
return result
raiseOverflow()
proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a - b
result = a -% b
if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
return result
raiseOverflow()
@ -74,7 +74,7 @@ proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
proc mulInt64(a, b: int64): int64 {.compilerproc.} =
var
resAsFloat, floatProd: float64
result = a * b
result = a *% b
floatProd = float64(a) # conversion
floatProd = floatProd * float64(b)
resAsFloat = float64(result)
@ -211,7 +211,7 @@ when defined(asmVersion) and not defined(gcc):
"""
elif defined(asmVersion) and defined(gcc):
proc addInt(a, b: int): int =
proc addInt(a, b: int): int =
asm """ "addl %1,%%eax\n"
"jno 1\n"
"call _raiseOverflow\n"
@ -219,7 +219,7 @@ elif defined(asmVersion) and defined(gcc):
:"=a"(`a`)
:"a"(`a`), "r"(`b`)
"""
proc subInt(a, b: int): int =
asm """ "subl %1,%%eax\n"
"jno 1\n"
@ -228,7 +228,7 @@ elif defined(asmVersion) and defined(gcc):
:"=a"(`a`)
:"a"(`a`), "r"(`b`)
"""
proc negInt(a: int): int =
asm """ "negl %%eax\n"
"jno 1\n"
@ -237,7 +237,7 @@ elif defined(asmVersion) and defined(gcc):
:"=a"(`a`)
:"a"(`a`)
"""
proc divInt(a, b: int): int =
asm """ "xorl %%edx, %%edx\n"
"idivl %%ecx\n"
@ -276,13 +276,13 @@ else:
# Platform independant versions of the above (slower!)
proc addInt(a, b: int): int =
result = a + b
result = a +% b
if (result xor a) >= 0 or (result xor b) >= 0:
return result
raiseOverflow()
proc subInt(a, b: int): int =
result = a - b
result = a -% b
if (result xor a) >= 0 or (result xor not b) >= 0:
return result
raiseOverflow()
@ -327,7 +327,7 @@ else:
var
resAsFloat, floatProd: float
result = a * b
result = a *% b
floatProd = toFloat(a) * toFloat(b)
resAsFloat = toFloat(result)

View file

@ -55,7 +55,8 @@ proc genericAssign(dest, src: Pointer, mt: PNimType) =
var dstseq = cast[PGenericSeq](dst)
dstseq.len = seq.len
dstseq.space = seq.len
of tyRecord, tyObject, tyTuple:
of tyObject, tyTuple, tyPureObject:
# we don't need to copy m_type field for tyObject, as they are equal anyway
genericAssignAux(dest, src, mt.node)
of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1:
@ -75,6 +76,7 @@ proc genericAssign(dest, src: Pointer, mt: PNimType) =
copyMem(dest, src, mt.size) # copy raw bits
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
var src = src # ugly, but I like to stress the parser sometimes :-)
genericAssign(dest, addr(src), mt)
proc genericAssignOpenArray(dest, src: pointer, len: int,
@ -110,7 +112,7 @@ proc objectInit(dest: Pointer, typ: PNimType) =
var pint = cast[ptr PNimType](dest)
pint^ = typ
objectInitAux(dest, typ.node)
of tyRecord:
of tyTuple, tyPureObject:
objectInitAux(dest, typ.node)
of tyArray, tyArrayConstr:
for i in 0..(typ.size div typ.base.size)-1:

View file

@ -149,13 +149,13 @@ type
cdecl.}
cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
cdecl.}
cairo_t* = record #OPAQUE
cairo_surface_t* = record #OPAQUE
cairo_pattern_t* = record #OPAQUE
cairo_scaled_font_t* = record #OPAQUE
cairo_font_face_t* = record #OPAQUE
cairo_font_options_t* = record #OPAQUE
cairo_matrix_t* = record
cairo_t* {.final.} = object #OPAQUE
cairo_surface_t* {.final.} = object #OPAQUE
cairo_pattern_t* {.final.} = object #OPAQUE
cairo_scaled_font_t* {.final.} = object #OPAQUE
cairo_font_face_t* {.final.} = object #OPAQUE
cairo_font_options_t* {.final.} = object #OPAQUE
cairo_matrix_t* {.final.} = object
xx: float64
yx: float64
xy: float64
@ -163,15 +163,15 @@ type
x0: float64
y0: float64
cairo_user_data_key_t* = record
cairo_user_data_key_t* {.final.} = object
unused: int32
cairo_glyph_t* = record
cairo_glyph_t* {.final.} = object
index: int32
x: float64
y: float64
cairo_text_extents_t* = record
cairo_text_extents_t* {.final.} = object
x_bearing: float64
y_bearing: float64
width: float64
@ -179,28 +179,28 @@ type
x_advance: float64
y_advance: float64
cairo_font_extents_t* = record
cairo_font_extents_t* {.final.} = object
ascent: float64
descent: float64
height: float64
max_x_advance: float64
max_y_advance: float64
cairo_path_data_t* = record #* _type : cairo_path_data_type_t;
# length : LongInt;
# end
cairo_path_data_t* {.final.} = object #* _type : cairo_path_data_type_t;
# length : LongInt;
# end
x: float64
y: float64
cairo_path_t* = record
cairo_path_t* {.final.} = object
status: cairo_status_t
data: Pcairo_path_data_t
num_data: int32
cairo_rectangle_t* = record
cairo_rectangle_t* {.final.} = object
x, y, width, height: float64
cairo_rectangle_list_t* = record
cairo_rectangle_list_t* {.final.} = object
status: cairo_status_t
rectangles: Pcairo_rectangle_t
num_rectangles: int32

View file

@ -56,7 +56,7 @@ type
ATK_LAYER_INVALID, ATK_LAYER_BACKGROUND, ATK_LAYER_CANVAS, ATK_LAYER_WIDGET,
ATK_LAYER_MDI, ATK_LAYER_POPUP, ATK_LAYER_OVERLAY
PAtkPropertyValues* = ptr TAtkPropertyValues
TAtkPropertyValues* = record
TAtkPropertyValues* {.final.} = object
property_name*: cstring
old_value*: TGValue
new_value*: TGValue
@ -379,7 +379,7 @@ type
TAtkAttributeSet* = TGSList
PAtkAttribute* = ptr TAtkAttribute
TAtkAttribute* = record
TAtkAttribute* {.final.} = object
name*: cstring
value*: cstring
@ -453,7 +453,7 @@ type
TAtkEventListenerInitProc* = proc ()
TAtkEventListenerInit* = proc (para1: TAtkEventListenerInitProc){.cdecl.}
PAtkKeyEventStruct* = ptr TAtkKeyEventStruct
TAtkKeyEventStruct* = record
TAtkKeyEventStruct* {.final.} = object
`type`*: gint
state*: guint
keyval*: guint

View file

@ -32,7 +32,7 @@ type
TGdkVisualClass* = object of TGObjectClass
PGdkColor* = ptr TGdkColor
TGdkColor* = record
TGdkColor* {.final.} = object
pixel*: guint32
red*: guint16
green*: guint16
@ -52,7 +52,7 @@ type
TGdkFontType* = enum
GDK_FONT_FONT, GDK_FONT_FONTSET
PGdkFont* = ptr TGdkFont
TGdkFont* = record
TGdkFont* {.final.} = object
`type`*: TGdkFontType
ascent*: gint
descent*: gint
@ -79,7 +79,7 @@ type
PGdkGCValuesMask* = ptr TGdkGCValuesMask
TGdkGCValuesMask* = int32
PGdkGCValues* = ptr TGdkGCValues
TGdkGCValues* = record
TGdkGCValues* {.final.} = object
foreground*: TGdkColor
background*: TGdkColor
font*: PGdkFont
@ -125,7 +125,7 @@ type
TGdkInputCondition* = int32
PGdkStatus* = ptr TGdkStatus
TGdkStatus* = int32
TGdkPoint* = record
TGdkPoint* {.final.} = object
x*: gint
y*: gint
@ -135,14 +135,14 @@ type
PGdkWChar* = ptr TGdkWChar
TGdkWChar* = guint32
PGdkSegment* = ptr TGdkSegment
TGdkSegment* = record
TGdkSegment* {.final.} = object
x1*: gint
y1*: gint
x2*: gint
y2*: gint
PGdkRectangle* = ptr TGdkRectangle
TGdkRectangle* = record
TGdkRectangle* {.final.} = object
x*: gint
y*: gint
width*: gint
@ -190,7 +190,7 @@ type
PGdkCursorType* = ptr TGdkCursorType
TGdkCursorType* = gint
PGdkCursor* = ptr TGdkCursor
TGdkCursor* = record
TGdkCursor* {.final.} = object
`type`*: TGdkCursorType
ref_count*: guint
@ -220,14 +220,14 @@ type
PGdkRegionBox* = ptr TGdkRegionBox
TGdkRegionBox* = TGdkSegment
PGdkRegion* = ptr TGdkRegion
TGdkRegion* = record
TGdkRegion* {.final.} = object
size*: int32
numRects*: int32
rects*: PGdkRegionBox
extents*: TGdkRegionBox
PPOINTBLOCK* = ptr TPOINTBLOCK
TPOINTBLOCK* = record
TPOINTBLOCK* {.final.} = object
pts*: array[0..(NUMPTSTOBUFFER) - 1, TGdkPoint]
next*: PPOINTBLOCK
@ -336,13 +336,13 @@ type
GDK_SETTING_ACTION_NEW, GDK_SETTING_ACTION_CHANGED,
GDK_SETTING_ACTION_DELETED
PGdkEventAny* = ptr TGdkEventAny
TGdkEventAny* = record
TGdkEventAny* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
PGdkEventExpose* = ptr TGdkEventExpose
TGdkEventExpose* = record
TGdkEventExpose* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -351,20 +351,20 @@ type
count*: gint
PGdkEventNoExpose* = ptr TGdkEventNoExpose
TGdkEventNoExpose* = record
TGdkEventNoExpose* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
PGdkEventVisibility* = ptr TGdkEventVisibility
TGdkEventVisibility* = record
TGdkEventVisibility* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
state*: TGdkVisibilityState
PGdkEventMotion* = ptr TGdkEventMotion
TGdkEventMotion* = record
TGdkEventMotion* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -379,7 +379,7 @@ type
y_root*: gdouble
PGdkEventButton* = ptr TGdkEventButton
TGdkEventButton* = record
TGdkEventButton* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -394,7 +394,7 @@ type
y_root*: gdouble
PGdkEventScroll* = ptr TGdkEventScroll
TGdkEventScroll* = record
TGdkEventScroll* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -408,7 +408,7 @@ type
y_root*: gdouble
PGdkEventKey* = ptr TGdkEventKey
TGdkEventKey* = record
TGdkEventKey* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -421,7 +421,7 @@ type
group*: guint8
PGdkEventCrossing* = ptr TGdkEventCrossing
TGdkEventCrossing* = record
TGdkEventCrossing* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -437,14 +437,14 @@ type
state*: guint
PGdkEventFocus* = ptr TGdkEventFocus
TGdkEventFocus* = record
TGdkEventFocus* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
`in`*: gint16
PGdkEventConfigure* = ptr TGdkEventConfigure
TGdkEventConfigure* = record
TGdkEventConfigure* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -454,7 +454,7 @@ type
height*: gint
PGdkEventProperty* = ptr TGdkEventProperty
TGdkEventProperty* = record
TGdkEventProperty* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -464,7 +464,7 @@ type
TGdkNativeWindow* = pointer
PGdkEventSelection* = ptr TGdkEventSelection
TGdkEventSelection* = record
TGdkEventSelection* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -475,7 +475,7 @@ type
requestor*: TGdkNativeWindow
PGdkEventProximity* = ptr TGdkEventProximity
TGdkEventProximity* = record
TGdkEventProximity* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -483,11 +483,11 @@ type
device*: PGdkDevice
PmatDUMMY* = ptr TmatDUMMY
TmatDUMMY* = record
TmatDUMMY* {.final.} = object
b*: array[0..19, char]
PGdkEventClient* = ptr TGdkEventClient
TGdkEventClient* = record
TGdkEventClient* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -496,7 +496,7 @@ type
b*: array[0..19, char]
PGdkEventSetting* = ptr TGdkEventSetting
TGdkEventSetting* = record
TGdkEventSetting* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -504,7 +504,7 @@ type
name*: cstring
PGdkEventWindowState* = ptr TGdkEventWindowState
TGdkEventWindowState* = record
TGdkEventWindowState* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -512,7 +512,7 @@ type
new_window_state*: TGdkWindowState
PGdkEventDND* = ptr TGdkEventDND
TGdkEventDND* = record
TGdkEventDND* {.final.} = object
`type`*: TGdkEventType
window*: PGdkWindow
send_event*: gint8
@ -521,7 +521,7 @@ type
x_root*: gshort
y_root*: gshort
TGdkEvent* = record
TGdkEvent* {.final.} = object
data*: array[0..255, char] # union of
# `type`: TGdkEventType
# any: TGdkEventAny
@ -585,12 +585,12 @@ type
PGdkAxisUse* = ptr TGdkAxisUse
TGdkAxisUse* = int32
PGdkDeviceKey* = ptr TGdkDeviceKey
TGdkDeviceKey* = record
TGdkDeviceKey* {.final.} = object
keyval*: guint
modifiers*: TGdkModifierType
PGdkDeviceAxis* = ptr TGdkDeviceAxis
TGdkDeviceAxis* = record
TGdkDeviceAxis* {.final.} = object
use*: TGdkAxisUse
min*: gdouble
max*: gdouble
@ -605,12 +605,12 @@ type
num_keys*: gint
keys*: PGdkDeviceKey
TGdkTimeCoord* = record
TGdkTimeCoord* {.final.} = object
time*: guint32
axes*: array[0..(GDK_MAX_TIMECOORD_AXES) - 1, gdouble]
PGdkKeymapKey* = ptr TGdkKeymapKey
TGdkKeymapKey* = record
TGdkKeymapKey* {.final.} = object
keycode*: guint
group*: gint
level*: gint
@ -624,12 +624,12 @@ type
direction_changed*: proc (keymap: PGdkKeymap){.cdecl.}
PGdkPangoAttrStipple* = ptr TGdkPangoAttrStipple
TGdkPangoAttrStipple* = record
TGdkPangoAttrStipple* {.final.} = object
attr*: TPangoAttribute
stipple*: PGdkBitmap
PGdkPangoAttrEmbossed* = ptr TGdkPangoAttrEmbossed
TGdkPangoAttrEmbossed* = record
TGdkPangoAttrEmbossed* {.final.} = object
attr*: TPangoAttribute
embossed*: gboolean
@ -653,7 +653,7 @@ type
GDK_OVERLAP_RECTANGLE_PART
TGdkSpanFunc* = proc (span: PGdkSpan, data: gpointer){.cdecl.}
PGdkRgbCmap* = ptr TGdkRgbCmap
TGdkRgbCmap* = record
TGdkRgbCmap* {.final.} = object
colors*: array[0..255, guint32]
n_colors*: gint
info_list*: PGSList
@ -698,7 +698,7 @@ type
TGdkInputFunction* = proc (data: gpointer, source: gint,
condition: TGdkInputCondition){.cdecl.}
TGdkDestroyNotify* = proc (data: gpointer){.cdecl.}
TGdkSpan* = record
TGdkSpan* {.final.} = object
x*: gint
y*: gint
width*: gint
@ -731,7 +731,7 @@ type
GDK_WINDOW_EDGE_SOUTH_WEST, GDK_WINDOW_EDGE_SOUTH,
GDK_WINDOW_EDGE_SOUTH_EAST
PGdkWindowAttr* = ptr TGdkWindowAttr
TGdkWindowAttr* = record
TGdkWindowAttr* {.final.} = object
title*: cstring
event_mask*: gint
x*: gint
@ -748,7 +748,7 @@ type
override_redirect*: gboolean
PGdkGeometry* = ptr TGdkGeometry
TGdkGeometry* = record
TGdkGeometry* {.final.} = object
min_width*: gint
min_height*: gint
max_width*: gint
@ -762,7 +762,7 @@ type
win_gravity*: TGdkGravity
PGdkPointerHooks* = ptr TGdkPointerHooks
TGdkPointerHooks* = record
TGdkPointerHooks* {.final.} = object
get_pointer*: proc (window: PGdkWindow, x: Pgint, y: Pgint,
mask: PGdkModifierType): PGdkWindow{.cdecl.}
window_at_pointer*: proc (screen: PGdkScreen, win_x: Pgint, win_y: Pgint): PGdkWindow{.

View file

@ -191,12 +191,12 @@ proc gdk_pixbuf_get_option*(pixbuf: PGdkPixbuf, key: cstring): cstring{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_option".}
type
PGdkPixbufLoader* = ptr TGdkPixbufLoader
TGdkPixbufLoader* = record
TGdkPixbufLoader* {.final.} = object
parent_instance*: TGObject
priv*: gpointer
PGdkPixbufLoaderClass* = ptr TGdkPixbufLoaderClass
TGdkPixbufLoaderClass* = record
TGdkPixbufLoaderClass* {.final.} = object
parent_class*: TGObjectClass
area_prepared*: proc (loader: PGdkPixbufLoader){.cdecl.}
area_updated*: proc (loader: PGdkPixbufLoader, x: int32, y: int32,

View file

@ -61,7 +61,7 @@ type
TGHFunc* = proc (key, value, user_data: gpointer){.cdecl.}
PGFreeFunc* = proc (data: gpointer){.cdecl.}
PGTimeVal* = ptr TGTimeVal
TGTimeVal* = record
TGTimeVal* {.final.} = object
tv_sec*: glong
tv_usec*: glong
@ -88,17 +88,17 @@ type
TGQuark* = guint32
PGQuark* = ptr TGQuark
PGTypeCValue* = ptr TGTypeCValue
TGTypeCValue* = record
TGTypeCValue* {.final.} = object
v_double*: gdouble
GType* = gulong
PGType* = ptr GType
PGTypeClass* = ptr TGTypeClass
TGTypeClass* = record
TGTypeClass* {.final.} = object
g_type*: GType
PGTypeInstance* = ptr TGTypeInstance
TGTypeInstance* = record
TGTypeInstance* {.final.} = object
g_class*: PGTypeClass
PGTypeInterface* = ptr TGTypeInterface
@ -107,14 +107,14 @@ type
g_instance_type*: GType
PGTypeQuery* = ptr TGTypeQuery
TGTypeQuery* = record
TGTypeQuery* {.final.} = object
theType*: GType
type_name*: cstring
class_size*: guint
instance_size*: guint
PGValue* = ptr TGValue
TGValue* = record
TGValue* {.final.} = object
g_type*: GType
data*: array[0..1, gdouble]
@ -122,12 +122,12 @@ type
PGData* = pointer
PGSList* = ptr TGSList
PPGSList* = ptr PGSList
TGSList* = record
TGSList* {.final.} = object
data*: gpointer
next*: PGSList
PGList* = ptr TGList
TGList* = record
TGList* {.final.} = object
data*: gpointer
next*: PGList
prev*: PGList
@ -136,7 +136,7 @@ type
TGParamFlags* = int32
PGParamSpec* = ptr TGParamSpec
PPGParamSpec* = ptr PGParamSpec
TGParamSpec* = record
TGParamSpec* {.final.} = object
g_type_instance*: TGTypeInstance
name*: cstring
flags*: TGParamFlags
@ -149,7 +149,7 @@ type
param_id*: guint
PGParamSpecClass* = ptr TGParamSpecClass
TGParamSpecClass* = record
TGParamSpecClass* {.final.} = object
g_type_class*: TGTypeClass
value_type*: GType
finalize*: proc (pspec: PGParamSpec){.cdecl.}
@ -160,7 +160,7 @@ type
dummy*: array[0..3, gpointer]
PGParameter* = ptr TGParameter
TGParameter* = record
TGParameter* {.final.} = object
name*: cstring
value*: TGValue
@ -305,7 +305,7 @@ const
type
PGTypeValueTable* = ptr TGTypeValueTable
TGTypeValueTable* = record
TGTypeValueTable* {.final.} = object
value_init*: proc (value: PGValue){.cdecl.}
value_free*: proc (value: PGValue){.cdecl.}
value_copy*: proc (src_value: PGValue, dest_value: PGValue){.cdecl.}
@ -320,7 +320,7 @@ type
cdecl.}
PGTypeInfo* = ptr TGTypeInfo
TGTypeInfo* = record
TGTypeInfo* {.final.} = object
class_size*: guint16
base_init*: TGBaseInitFunc
base_finalize*: TGBaseFinalizeFunc
@ -333,11 +333,11 @@ type
value_table*: PGTypeValueTable
PGTypeFundamentalInfo* = ptr TGTypeFundamentalInfo
TGTypeFundamentalInfo* = record
TGTypeFundamentalInfo* {.final.} = object
type_flags*: TGTypeFundamentalFlags
PGInterfaceInfo* = ptr TGInterfaceInfo
TGInterfaceInfo* = record
TGInterfaceInfo* {.final.} = object
interface_init*: TGInterfaceInitFunc
interface_finalize*: TGInterfaceFinalizeFunc
interface_data*: gpointer
@ -449,7 +449,7 @@ const
type
PGValueArray* = ptr TGValueArray
TGValueArray* = record
TGValueArray* {.final.} = object
n_values*: guint
values*: PGValue
n_prealloced*: guint
@ -628,7 +628,7 @@ proc g_value_set_param_take_ownership*(value: PGValue, param: PGParamSpec){.
cdecl, dynlib: gliblib, importc: "g_value_set_param_take_ownership".}
type
PGParamSpecTypeInfo* = ptr TGParamSpecTypeInfo
TGParamSpecTypeInfo* = record
TGParamSpecTypeInfo* {.final.} = object
instance_size*: guint16
n_preallocs*: guint16
instance_init*: proc (pspec: PGParamSpec){.cdecl.}
@ -668,7 +668,7 @@ type
PGClosure* = ptr TGClosure
PGClosureNotifyData* = ptr TGClosureNotifyData
TGClosureNotify* = proc (data: gpointer, closure: PGClosure){.cdecl.}
TGClosure* = record
TGClosure* {.final.} = object
flag0*: int32
marshal*: proc (closure: PGClosure, return_value: PGValue,
n_param_values: guint, param_values: PGValue,
@ -682,7 +682,7 @@ type
n_param_values: guint, param_values: PGValue,
invocation_hint: gpointer, marshal_data: gpointer){.
cdecl.}
TGClosureNotifyData* = record
TGClosureNotifyData* {.final.} = object
data*: gpointer
notify*: TGClosureNotify
@ -734,7 +734,7 @@ proc is_invalid*(a: var TGClosure): guint
proc set_is_invalid*(a: var TGClosure, is_invalid: guint)
type
PGCClosure* = ptr TGCClosure
TGCClosure* = record
TGCClosure* {.final.} = object
closure*: TGClosure
callback*: gpointer
@ -797,13 +797,13 @@ type
data: gpointer): gboolean{.cdecl.}
PGSignalFlags* = ptr TGSignalFlags
TGSignalFlags* = int32
TGSignalInvocationHint* = record
TGSignalInvocationHint* {.final.} = object
signal_id*: guint
detail*: TGQuark
run_type*: TGSignalFlags
PGSignalQuery* = ptr TGSignalQuery
TGSignalQuery* = record
TGSignalQuery* {.final.} = object
signal_id*: guint
signal_name*: cstring
itype*: GType
@ -952,7 +952,7 @@ type
TGTypePluginCompleteInterfaceInfo* = proc (plugin: PGTypePlugin,
instance_type: GType, interface_type: GType, info: PGInterfaceInfo){.cdecl.}
PGTypePluginClass* = ptr TGTypePluginClass
TGTypePluginClass* = record
TGTypePluginClass* {.final.} = object
base_iface*: TGTypeInterface
use_plugin*: TGTypePluginUse
unuse_plugin*: TGTypePluginUnuse
@ -1011,7 +1011,7 @@ type
notify*: proc (anObject: PGObject, pspec: PGParamSpec){.cdecl.}
pdummy*: array[0..7, gpointer]
TGObjectConstructParam* = record
TGObjectConstructParam* {.final.} = object
pspec*: PGParamSpec
value*: PGValue
@ -1125,27 +1125,27 @@ proc GUINT32_SWAP_LE_BE_CONSTANT*(val: guint32): guint32
type
PGEnumClass* = ptr TGEnumClass
PGEnumValue* = ptr TGEnumValue
TGEnumClass* = record
TGEnumClass* {.final.} = object
g_type_class*: TGTypeClass
minimum*: gint
maximum*: gint
n_values*: guint
values*: PGEnumValue
TGEnumValue* = record
TGEnumValue* {.final.} = object
value*: gint
value_name*: cstring
value_nick*: cstring
PGFlagsClass* = ptr TGFlagsClass
PGFlagsValue* = ptr TGFlagsValue
TGFlagsClass* = record
TGFlagsClass* {.final.} = object
g_type_class*: TGTypeClass
mask*: guint
n_values*: guint
values*: PGFlagsValue
TGFlagsValue* = record
TGFlagsValue* {.final.} = object
value*: guint
value_name*: cstring
value_nick*: cstring
@ -1203,7 +1203,7 @@ const
G_MAXUSHORT* = 2 * G_MAXSHORT + 1
G_MAXINT* = 2147483647
G_MININT* = - G_MAXINT - 1
G_MAXUINT* = 4294967295
G_MAXUINT* = -1
G_MINLONG* = G_MININT
G_MAXLONG* = G_MAXINT
G_MAXULONG* = G_MAXUINT
@ -1224,7 +1224,7 @@ const
type
PGSystemThread* = ptr TGSystemThread
TGSystemThread* = record
TGSystemThread* {.final.} = object
data*: array[0..3, char]
dummy_double*: float64
dummy_pointer*: pointer
@ -1350,7 +1350,7 @@ proc g_set_prgname*(prgname: cstring){.cdecl, dynlib: gliblib,
importc: "g_set_prgname".}
type
PGDebugKey* = ptr TGDebugKey
TGDebugKey* = record
TGDebugKey* {.final.} = object
key*: cstring
value*: guint
@ -1390,7 +1390,7 @@ proc g_bit_storage*(number: gulong): guint{.cdecl, dynlib: gliblib,
type
PPGTrashStack* = ptr PGTrashStack
PGTrashStack* = ptr TGTrashStack
TGTrashStack* = record
TGTrashStack* {.final.} = object
next*: PGTrashStack
@ -1466,7 +1466,7 @@ const
type
PGMemVTable* = ptr TGMemVTable
TGMemVTable* = record
TGMemVTable* {.final.} = object
malloc*: proc (n_bytes: gsize): gpointer{.cdecl.}
realloc*: proc (mem: gpointer, n_bytes: gsize): gpointer{.cdecl.}
free*: proc (mem: gpointer){.cdecl.}
@ -1679,7 +1679,7 @@ type
TGCompletionStrncmpFunc* = proc (s1: cstring, s2: cstring, n: gsize): gint{.
cdecl.}
PGCompletion* = ptr TGCompletion
TGCompletion* = record
TGCompletion* {.final.} = object
items*: PGList
func*: TGCompletionFunc
prefix*: cstring
@ -1809,7 +1809,7 @@ type
PGDateDay* = ptr TGDateDay
TGDateDay* = guint8
Ptm* = ptr Ttm
Ttm* = record
Ttm* {.final.} = object
tm_sec*: gint
tm_min*: gint
tm_hour*: gint
@ -1872,7 +1872,7 @@ const
type
PGDate* = ptr TGDate
TGDate* = record
TGDate* {.final.} = object
flag0*: int32
flag1*: int32
@ -2028,7 +2028,7 @@ proc g_file_open_tmp*(tmpl: cstring, name_used: PPchar, error: pointer): int32{.
cdecl, dynlib: gliblib, importc: "g_file_open_tmp".}
type
PGHook* = ptr TGHook
TGHook* = record
TGHook* {.final.} = object
data*: gpointer
next*: PGHook
prev*: PGHook
@ -2047,7 +2047,7 @@ type
TGHookFunc* = proc (data: gpointer){.cdecl.}
TGHookCheckFunc* = proc (data: gpointer): gboolean{.cdecl.}
TGHookFinalizeFunc* = proc (hook_list: PGHookList, hook: PGHook){.cdecl.}
TGHookList* = record
TGHookList* {.final.} = object
seq_id*: gulong
flag0*: int32
hooks*: PGHook
@ -2138,7 +2138,7 @@ proc g_hook_list_marshal_check*(hook_list: PGHookList, may_recurse: gboolean,
importc: "g_hook_list_marshal_check".}
type
PGThreadPool* = ptr TGThreadPool
TGThreadPool* = record
TGThreadPool* {.final.} = object
func*: TGFunc
user_data*: gpointer
exclusive*: gboolean
@ -2352,7 +2352,7 @@ proc g_utf8_collate_key*(str: cstring, len: gssize): cstring{.cdecl,
dynlib: gliblib, importc: "g_utf8_collate_key".}
type
PGString* = ptr TGString
TGString* = record
TGString* {.final.} = object
str*: cstring
len*: gsize
allocated_len*: gsize
@ -2468,7 +2468,7 @@ type
TGIOFunc* = proc (source: PGIOChannel, condition: TGIOCondition,
data: gpointer): gboolean{.cdecl.}
PGIOFuncs* = ptr TGIOFuncs
TGIOFuncs* = record
TGIOFuncs* {.final.} = object
io_read*: proc (channel: PGIOChannel, buf: cstring, count: gsize,
bytes_read: Pgsize, err: pointer): TGIOStatus{.cdecl.}
io_write*: proc (channel: PGIOChannel, buf: cstring, count: gsize,
@ -2483,7 +2483,7 @@ type
cdecl.}
io_get_flags*: proc (channel: PGIOChannel): TGIOFlags{.cdecl.}
TGIOChannel* = record
TGIOChannel* {.final.} = object
ref_count*: guint
funcs*: PGIOFuncs
encoding*: cstring
@ -2699,7 +2699,7 @@ type
PGMarkupParseContext* = ptr TGMarkupParseContext
TGMarkupParseContext* = pointer
PGMarkupParser* = ptr TGMarkupParser
TGMarkupParser* = record
TGMarkupParser* {.final.} = object
start_element*: proc (context: PGMarkupParseContext, element_name: cstring,
attribute_names: PPgchar, attribute_values: PPgchar,
user_data: gpointer, error: pointer){.cdecl.}
@ -2733,7 +2733,7 @@ proc g_markup_escape_text*(text: cstring, length: gssize): cstring{.cdecl,
dynlib: gliblib, importc: "g_markup_escape_text".}
type
PGNode* = ptr TGNode
TGNode* = record
TGNode* {.final.} = object
data*: gpointer
next*: PGNode
prev*: PGNode
@ -2886,7 +2886,7 @@ proc g_qsort_with_data*(pbase: gconstpointer, total_elems: gint, size: gsize,
cdecl, dynlib: gliblib, importc: "g_qsort_with_data".}
type
PGQueue* = ptr TGQueue
TGQueue* = record
TGQueue* {.final.} = object
head*: PGList
tail*: PGList
length*: guint
@ -2947,7 +2947,7 @@ proc g_random_double_range*(`begin`: gdouble, `end`: gdouble): gdouble{.cdecl,
dynlib: gliblib, importc: "g_random_double_range".}
type
PGTuples* = ptr TGTuples
TGTuples* = record
TGTuples* {.final.} = object
len*: guint
PGRelation* = pointer
@ -3003,12 +3003,12 @@ type
PGScanner* = ptr TGScanner
PGScannerConfig* = ptr TGScannerConfig
PGTokenValue* = ptr TGTokenValue
TGTokenValue* = record
TGTokenValue* {.final.} = object
v_float*: gdouble
TGScannerMsgFunc* = proc (scanner: PGScanner, message: cstring,
error: gboolean){.cdecl.}
TGScanner* = record
TGScanner* {.final.} = object
user_data*: gpointer
max_parse_errors*: guint
parse_errors*: guint
@ -3031,7 +3031,7 @@ type
scope_id*: guint
msg_handler*: TGScannerMsgFunc
TGScannerConfig* = record
TGScannerConfig* {.final.} = object
cset_skip_characters*: cstring
cset_identifier_first*: cstring
cset_identifier_nth*: cstring

View file

@ -155,17 +155,17 @@ type
TGtkSignalFunc* = proc (para1: TGtkSignalFuncProc){.cdecl.}
PGtkSignalMarshaller* = ptr TGtkSignalMarshaller
TGtkSignalMarshaller* = TGSignalCMarshaller
TGtkArgSignalData* = record
TGtkArgSignalData* {.final.} = object
f*: TGtkSignalFunc
d*: gpointer
TGtkArg* = record
TGtkArg* {.final.} = object
`type`*: TGtkType
name*: cstring
d*: gdouble # was a union type
PGtkTypeInfo* = ptr TGtkTypeInfo
TGtkTypeInfo* = record
TGtkTypeInfo* {.final.} = object
type_name*: cstring
object_size*: guint
class_size*: guint
@ -188,7 +188,7 @@ type
TGtkAllocation* = TGdkRectangle
TGtkCallback* = proc (widget: PGtkWidget, data: gpointer){.cdecl.}
PGtkRequisition* = ptr TGtkRequisition
TGtkRequisition* = record
TGtkRequisition* {.final.} = object
width*: gint
height*: gint
@ -323,7 +323,7 @@ type
gtk_reserved8*: proc (){.cdecl.}
PGtkWidgetAuxInfo* = ptr TGtkWidgetAuxInfo
TGtkWidgetAuxInfo* = record
TGtkWidgetAuxInfo* {.final.} = object
x*: gint
y*: gint
width*: gint
@ -331,7 +331,7 @@ type
flag0*: guint16
PGtkWidgetShapeInfo* = ptr TGtkWidgetShapeInfo
TGtkWidgetShapeInfo* = record
TGtkWidgetShapeInfo* {.final.} = object
offset_x*: gint16
offset_y*: gint16
shape_mask*: PGdkBitmap
@ -370,12 +370,12 @@ type
gtk_reserved4: proc (){.cdecl.}
PGtkAccelKey* = ptr TGtkAccelKey
TGtkAccelKey* = record
TGtkAccelKey* {.final.} = object
accel_key*: guint
accel_mods*: TGdkModifierType
flag0*: guint16
TGtkAccelGroupEntry* = record
TGtkAccelGroupEntry* {.final.} = object
key*: TGtkAccelKey
closure*: PGClosure
accel_path_quark*: TGQuark
@ -595,7 +595,7 @@ type
PGtkBindingSignal* = ptr TGtkBindingSignal
PGtkBindingArg* = ptr TGtkBindingArg
PGtkBindingSet* = ptr TGtkBindingSet
TGtkBindingSet* = record
TGtkBindingSet* {.final.} = object
set_name*: cstring
priority*: gint
widget_path_pspecs*: PGSList
@ -605,7 +605,7 @@ type
current*: PGtkBindingEntry
flag0*: guint16
TGtkBindingEntry* = record
TGtkBindingEntry* {.final.} = object
keyval*: guint
modifiers*: TGdkModifierType
binding_set*: PGtkBindingSet
@ -614,13 +614,13 @@ type
hash_next*: PGtkBindingEntry
signals*: PGtkBindingSignal
TGtkBindingSignal* = record
TGtkBindingSignal* {.final.} = object
next*: PGtkBindingSignal
signal_name*: cstring
n_args*: guint
args*: PGtkBindingArg
TGtkBindingArg* = record
TGtkBindingArg* {.final.} = object
arg_type*: TGtkType
d*: gdouble
@ -634,7 +634,7 @@ type
TGtkBoxClass* = object of TGtkContainerClass
PGtkBoxChild* = ptr TGtkBoxChild
TGtkBoxChild* = record
TGtkBoxChild* {.final.} = object
widget*: PGtkWidget
padding*: guint16
flag0*: guint16
@ -906,12 +906,12 @@ type
TGtkCListCompareFunc* = proc (clist: PGtkCList, ptr1: gconstpointer,
ptr2: gconstpointer): gint{.cdecl.}
PGtkCListCellInfo* = ptr TGtkCListCellInfo
TGtkCListCellInfo* = record
TGtkCListCellInfo* {.final.} = object
row*: gint
column*: gint
PGtkCListDestInfo* = ptr TGtkCListDestInfo
TGtkCListDestInfo* = record
TGtkCListDestInfo* {.final.} = object
cell*: TGtkCListCellInfo
insert_pos*: TGtkCListDragPos
@ -1014,7 +1014,7 @@ type
PGPtrArray = pointer
PGArray = pointer
TGtkCListColumn* = record
TGtkCListColumn* {.final.} = object
title*: cstring
area*: TGdkRectangle
button*: PGtkWidget
@ -1025,7 +1025,7 @@ type
justification*: TGtkJustification
flag0*: guint16
TGtkCListRow* = record
TGtkCListRow* {.final.} = object
cell*: PGtkCell
state*: TGtkStateType
foreground*: TGdkColor
@ -1036,7 +1036,7 @@ type
flag0*: guint16
PGtkCellText* = ptr TGtkCellText
TGtkCellText* = record
TGtkCellText* {.final.} = object
`type`*: TGtkCellType
vertical*: gint16
horizontal*: gint16
@ -1044,7 +1044,7 @@ type
text*: cstring
PGtkCellPixmap* = ptr TGtkCellPixmap
TGtkCellPixmap* = record
TGtkCellPixmap* {.final.} = object
`type`*: TGtkCellType
vertical*: gint16
horizontal*: gint16
@ -1053,7 +1053,7 @@ type
mask*: PGdkBitmap
PGtkCellPixText* = ptr TGtkCellPixText
TGtkCellPixText* = record
TGtkCellPixText* {.final.} = object
`type`*: TGtkCellType
vertical*: gint16
horizontal*: gint16
@ -1064,14 +1064,14 @@ type
mask*: PGdkBitmap
PGtkCellWidget* = ptr TGtkCellWidget
TGtkCellWidget* = record
TGtkCellWidget* {.final.} = object
`type`*: TGtkCellType
vertical*: gint16
horizontal*: gint16
style*: PGtkStyle
widget*: PGtkWidget
TGtkCell* = record
TGtkCell* {.final.} = object
`type`*: TGtkCellType
vertical*: gint16
horizontal*: gint16
@ -1212,7 +1212,7 @@ type
action: TGtkCTreeExpansionType){.cdecl.}
PGtkCTreeRow* = ptr TGtkCTreeRow
TGtkCTreeRow* = record
TGtkCTreeRow* {.final.} = object
row*: TGtkCListRow
parent*: PGtkCTreeNode
sibling*: PGtkCTreeNode
@ -1224,7 +1224,7 @@ type
level*: guint16
GtkCTreeRow_flag0*: guint16
TGtkCTreeNode* = record
TGtkCTreeNode* {.final.} = object
list*: TGList
PGtkDrawingArea* = ptr TGtkDrawingArea
@ -1479,7 +1479,7 @@ type
TGtkFixedClass* = object of TGtkContainerClass
PGtkFixedChild* = ptr TGtkFixedChild
TGtkFixedChild* = record
TGtkFixedChild* {.final.} = object
widget*: PGtkWidget
x*: gint
y*: gint
@ -1632,7 +1632,7 @@ type
gtk_reserved363: proc (){.cdecl.}
gtk_reserved364: proc (){.cdecl.}
TGtkRulerMetric* = record
TGtkRulerMetric* {.final.} = object
metric_name*: cstring
abbrev*: cstring
pixels_per_unit*: gdouble
@ -1657,7 +1657,7 @@ type
TGtkSettingsClass* = object of TGObjectClass
PGtkSettingsValue* = ptr TGtkSettingsValue
TGtkSettingsValue* = record
TGtkSettingsValue* {.final.} = object
origin*: cstring
value*: TGValue
@ -1708,7 +1708,7 @@ type
GTK_RC_TOKEN_IM_MODULE_FILE, GTK_RC_TOKEN_STOCK, GTK_RC_TOKEN_LTR,
GTK_RC_TOKEN_RTL, GTK_RC_TOKEN_LAST
PGtkRcProperty* = ptr TGtkRcProperty
TGtkRcProperty* = record
TGtkRcProperty* {.final.} = object
type_name*: TGQuark
property_name*: TGQuark
origin*: cstring
@ -1877,7 +1877,7 @@ type
gtk_reserved3812: proc (){.cdecl.}
PGtkBorder* = ptr TGtkBorder
TGtkBorder* = record
TGtkBorder* {.final.} = object
left*: gint
right*: gint
top*: gint
@ -1978,27 +1978,27 @@ type
PGtkIconSet* = pointer
PGtkImagePixmapData* = ptr TGtkImagePixmapData
TGtkImagePixmapData* = record
TGtkImagePixmapData* {.final.} = object
pixmap*: PGdkPixmap
PGtkImageImageData* = ptr TGtkImageImageData
TGtkImageImageData* = record
TGtkImageImageData* {.final.} = object
image*: PGdkImage
PGtkImagePixbufData* = ptr TGtkImagePixbufData
TGtkImagePixbufData* = record
TGtkImagePixbufData* {.final.} = object
pixbuf*: PGdkPixbuf
PGtkImageStockData* = ptr TGtkImageStockData
TGtkImageStockData* = record
TGtkImageStockData* {.final.} = object
stock_id*: cstring
PGtkImageIconSetData* = ptr TGtkImageIconSetData
TGtkImageIconSetData* = record
TGtkImageIconSetData* {.final.} = object
icon_set*: PGtkIconSet
PGtkImageAnimationData* = ptr TGtkImageAnimationData
TGtkImageAnimationData* = record
TGtkImageAnimationData* {.final.} = object
anim*: PGdkPixbufAnimation
iter*: PGdkPixbufAnimationIter
frame_timeout*: guint
@ -2111,7 +2111,7 @@ type
gtk_reserved474: proc (){.cdecl.}
PGtkItemFactoryEntry* = ptr TGtkItemFactoryEntry
TGtkItemFactoryEntry* = record
TGtkItemFactoryEntry* {.final.} = object
path*: cstring
accelerator*: cstring
callback*: TGtkItemFactoryCallback
@ -2120,7 +2120,7 @@ type
extra_data*: gconstpointer
PGtkItemFactoryItem* = ptr TGtkItemFactoryItem
TGtkItemFactoryItem* = record
TGtkItemFactoryItem* {.final.} = object
path*: cstring
widgets*: PGSList
@ -2173,7 +2173,7 @@ type
cdecl.}
PGtkTreeModelFlags* = ptr TGtkTreeModelFlags
TGtkTreeModelFlags* = int32
TGtkTreeIter* = record
TGtkTreeIter* {.final.} = object
stamp*: gint
user_data*: gpointer
user_data2*: gpointer
@ -2435,12 +2435,12 @@ type
GtkPreview_flag0*: guint16
PGtkPreviewInfo* = ptr TGtkPreviewInfo
TGtkPreviewInfo* = record
TGtkPreviewInfo* {.final.} = object
lookup*: Pguchar
gamma*: gdouble
PGtkDitherInfo* = ptr TGtkDitherInfo
TGtkDitherInfo* = record
TGtkDitherInfo* {.final.} = object
c*: array[0..3, guchar]
PGtkPreviewClass* = ptr TGtkPreviewClass
@ -2533,7 +2533,7 @@ type
gtk_reserved603: proc (){.cdecl.}
gtk_reserved604: proc (){.cdecl.}
TGtkSelectionData* = record
TGtkSelectionData* {.final.} = object
selection*: TGdkAtom
target*: TGdkAtom
thetype*: TGdkAtom
@ -2543,18 +2543,18 @@ type
display*: PGdkDisplay
PGtkTargetEntry* = ptr TGtkTargetEntry
TGtkTargetEntry* = record
TGtkTargetEntry* {.final.} = object
target*: cstring
flags*: guint
info*: guint
PGtkTargetList* = ptr TGtkTargetList
TGtkTargetList* = record
TGtkTargetList* {.final.} = object
list*: PGList
ref_count*: guint
PGtkTargetPair* = ptr TGtkTargetPair
TGtkTargetPair* = record
TGtkTargetPair* {.final.} = object
target*: TGdkAtom
flags*: guint
info*: guint
@ -2635,7 +2635,7 @@ type
gtk_reserved634: proc (){.cdecl.}
PGtkStockItem* = ptr TGtkStockItem
TGtkStockItem* = record
TGtkStockItem* {.final.} = object
stock_id*: cstring
label*: cstring
modifier*: TGdkModifierType
@ -2681,7 +2681,7 @@ type
TGtkTableClass* = object of TGtkContainerClass
PGtkTableChild* = ptr TGtkTableChild
TGtkTableChild* = record
TGtkTableChild* {.final.} = object
widget*: PGtkWidget
left_attach*: guint16
right_attach*: guint16
@ -2691,7 +2691,7 @@ type
ypadding*: guint16
GtkTableChild_flag0*: guint16
TGtkTableRowCol* = record
TGtkTableRowCol* {.final.} = object
requisition*: guint16
allocation*: guint16
spacing*: guint16
@ -2710,7 +2710,7 @@ type
PGtkTextFont* = pointer
PGtkPropertyMark* = ptr TGtkPropertyMark
TGtkPropertyMark* = record
TGtkPropertyMark* {.final.} = object
`property`*: PGList
offset*: guint
index*: guint
@ -2764,7 +2764,7 @@ type
PGtkTextSearchFlags* = ptr TGtkTextSearchFlags
TGtkTextSearchFlags* = int32
PGtkTextIter* = ptr TGtkTextIter
TGtkTextIter* = record
TGtkTextIter* {.final.} = object
dummy1*: gpointer
dummy2*: gpointer
dummy3*: gint
@ -2802,7 +2802,7 @@ type
gtk_reserved664: proc (){.cdecl.}
PGtkTextAppearance* = ptr TGtkTextAppearance
TGtkTextAppearance* = record
TGtkTextAppearance* {.final.} = object
bg_color*: TGdkColor
fg_color*: TGdkColor
bg_stipple*: PGdkBitmap
@ -2811,7 +2811,7 @@ type
padding1*: gpointer
flag0*: guint16
TGtkTextAttributes* = record
TGtkTextAttributes* {.final.} = object
refcount*: guint
appearance*: TGtkTextAppearance
justification*: TGtkJustification
@ -2860,7 +2860,7 @@ type
gtk_reserved4: proc (){.cdecl.}
PGtkTextMarkBody* = ptr TGtkTextMarkBody
TGtkTextMarkBody* = record
TGtkTextMarkBody* {.final.} = object
obj*: PGtkTextMark
name*: cstring
tree*: PGtkTextBTree
@ -2879,11 +2879,11 @@ type
gtk_reserved4: proc (){.cdecl.}
PGtkTextPixbuf* = ptr TGtkTextPixbuf
TGtkTextPixbuf* = record
TGtkTextPixbuf* {.final.} = object
pixbuf*: PGdkPixbuf
PGtkTextChildBody* = ptr TGtkTextChildBody
TGtkTextChildBody* = record
TGtkTextChildBody* {.final.} = object
obj*: PGtkTextChildAnchor
widgets*: PGSList
tree*: PGtkTextBTree
@ -2892,17 +2892,17 @@ type
PGtkTextLineSegment* = ptr TGtkTextLineSegment
PGtkTextLineSegmentClass* = ptr TGtkTextLineSegmentClass
PGtkTextTagInfo* = ptr TGtkTextTagInfo
TGtkTextTagInfo* = record
TGtkTextTagInfo* {.final.} = object
tag*: PGtkTextTag
tag_root*: PGtkTextBTreeNode
toggle_count*: gint
PGtkTextToggleBody* = ptr TGtkTextToggleBody
TGtkTextToggleBody* = record
TGtkTextToggleBody* {.final.} = object
info*: PGtkTextTagInfo
inNodeCounts*: gboolean
TGtkTextLineSegment* = record
TGtkTextLineSegment* {.final.} = object
`type`*: PGtkTextLineSegmentClass
next*: PGtkTextLineSegment
char_count*: int32
@ -2919,7 +2919,7 @@ type
line: PGtkTextLine){.cdecl.}
TGtkTextSegCheckFunc* = proc (seg: PGtkTextLineSegment, line: PGtkTextLine){.
cdecl.}
TGtkTextLineSegmentClass* = record
TGtkTextLineSegmentClass* {.final.} = object
name*: cstring
leftGravity*: gboolean
splitFunc*: TGtkTextSegSplitFunc
@ -2929,13 +2929,13 @@ type
checkFunc*: TGtkTextSegCheckFunc
PGtkTextLineData* = ptr TGtkTextLineData
TGtkTextLineData* = record
TGtkTextLineData* {.final.} = object
view_id*: gpointer
next*: PGtkTextLineData
height*: gint
flag0*: int32
TGtkTextLine* = record
TGtkTextLine* {.final.} = object
parent*: PGtkTextBTreeNode
next*: PGtkTextLine
segments*: PGtkTextLineSegment
@ -3020,18 +3020,18 @@ type
gtk_reserved4: proc (){.cdecl.}
PGtkTextAttrAppearance* = ptr TGtkTextAttrAppearance
TGtkTextAttrAppearance* = record
TGtkTextAttrAppearance* {.final.} = object
attr*: TPangoAttribute
appearance*: TGtkTextAppearance
PGtkTextCursorDisplay* = ptr TGtkTextCursorDisplay
TGtkTextCursorDisplay* = record
TGtkTextCursorDisplay* {.final.} = object
x*: gint
y*: gint
height*: gint
flag0*: guint16
TGtkTextLineDisplay* = record
TGtkTextLineDisplay* {.final.} = object
layout*: PPangoLayout
cursors*: PGSList
shaped_objects*: PGSList
@ -3152,7 +3152,7 @@ type
PGtkTooltips* = ptr TGtkTooltips
PGtkTooltipsData* = ptr TGtkTooltipsData
TGtkTooltipsData* = record
TGtkTooltipsData* {.final.} = object
tooltips*: PGtkTooltips
widget*: PGtkWidget
tip_text*: cstring
@ -3184,7 +3184,7 @@ type
TGtkToolbarSpaceStyle* = enum
GTK_TOOLBAR_SPACE_EMPTY, GTK_TOOLBAR_SPACE_LINE
PGtkToolbarChild* = ptr TGtkToolbarChild
TGtkToolbarChild* = record
TGtkToolbarChild* {.final.} = object
`type`*: TGtkToolbarChildType
widget*: PGtkWidget
icon*: PGtkWidget
@ -3365,13 +3365,13 @@ type
PGtkRBNode* = ptr TGtkRBNode
TGtkRBTreeTraverseFunc* = proc (tree: PGtkRBTree, node: PGtkRBNode,
data: gpointer){.cdecl.}
TGtkRBTree* = record
TGtkRBTree* {.final.} = object
root*: PGtkRBNode
`nil`*: PGtkRBNode
parent_tree*: PGtkRBTree
parent_node*: PGtkRBNode
TGtkRBNode* = record
TGtkRBNode* {.final.} = object
flag0*: guint16
left*: PGtkRBNode
right*: PGtkRBNode
@ -3386,14 +3386,14 @@ type
TGtkTreeViewSearchDialogPositionFunc* = proc (tree_view: PGtkTreeView,
search_dialog: PGtkWidget){.cdecl.}
PGtkTreeViewColumnReorder* = ptr TGtkTreeViewColumnReorder
TGtkTreeViewColumnReorder* = record
TGtkTreeViewColumnReorder* {.final.} = object
left_align*: gint
right_align*: gint
left_column*: PGtkTreeViewColumn
right_column*: PGtkTreeViewColumn
PGtkTreeViewPrivate* = ptr TGtkTreeViewPrivate
TGtkTreeViewPrivate* = record
TGtkTreeViewPrivate* {.final.} = object
model*: PGtkTreeModel
flags*: guint
tree*: PGtkRBTree
@ -11304,96 +11304,127 @@ proc GTK_FUNDAMENTAL_TYPE*(thetype: GType): GType =
result = G_TYPE_FUNDAMENTAL(thetype)
proc GTK_VALUE_CHAR*(a: TGtkArg): gchar =
var a = a
Result = cast[ptr gchar](addr(a.d))^
proc GTK_VALUE_UCHAR*(a: TGtkArg): guchar =
var a = a
Result = cast[ptr guchar](addr(a.d))^
proc GTK_VALUE_BOOL*(a: TGtkArg): gboolean =
var a = a
Result = cast[ptr gboolean](addr(a.d))^
proc GTK_VALUE_INT*(a: TGtkArg): gint =
var a = a
Result = cast[ptr gint](addr(a.d))^
proc GTK_VALUE_UINT*(a: TGtkArg): guint =
var a = a
Result = cast[ptr guint](addr(a.d))^
proc GTK_VALUE_LONG*(a: TGtkArg): glong =
var a = a
Result = cast[ptr glong](addr(a.d))^
proc GTK_VALUE_ULONG*(a: TGtkArg): gulong =
var a = a
Result = cast[ptr gulong](addr(a.d))^
proc GTK_VALUE_FLOAT*(a: TGtkArg): gfloat =
var a = a
Result = cast[ptr gfloat](addr(a.d))^
proc GTK_VALUE_DOUBLE*(a: TGtkArg): gdouble =
var a = a
Result = cast[ptr gdouble](addr(a.d))^
proc GTK_VALUE_STRING*(a: TGtkArg): cstring =
var a = a
Result = cast[ptr cstring](addr(a.d))^
proc GTK_VALUE_ENUM*(a: TGtkArg): gint =
var a = a
Result = cast[ptr gint](addr(a.d))^
proc GTK_VALUE_FLAGS*(a: TGtkArg): guint =
var a = a
Result = cast[ptr guint](addr(a.d))^
proc GTK_VALUE_BOXED*(a: TGtkArg): gpointer =
var a = a
Result = cast[ptr gpointer](addr(a.d))^
proc GTK_VALUE_OBJECT*(a: TGtkArg): PGtkObject =
var a = a
Result = cast[ptr PGtkObject](addr(a.d))^
proc GTK_VALUE_POINTER*(a: TGtkArg): GPointer =
var a = a
Result = cast[ptr gpointer](addr(a.d))^
proc GTK_VALUE_SIGNAL*(a: TGtkArg): TGtkArgSignalData =
var a = a
Result = cast[ptr TGtkArgSignalData](addr(a.d))^
proc GTK_RETLOC_CHAR*(a: TGtkArg): cstring =
var a = a
Result = cast[ptr cstring](addr(a.d))^
proc GTK_RETLOC_UCHAR*(a: TGtkArg): Pguchar =
var a = a
Result = cast[ptr pguchar](addr(a.d))^
proc GTK_RETLOC_BOOL*(a: TGtkArg): Pgboolean =
var a = a
Result = cast[ptr pgboolean](addr(a.d))^
proc GTK_RETLOC_INT*(a: TGtkArg): Pgint =
var a = a
Result = cast[ptr pgint](addr(a.d))^
proc GTK_RETLOC_UINT*(a: TGtkArg): Pguint =
var a = a
Result = cast[ptr pguint](addr(a.d))^
proc GTK_RETLOC_LONG*(a: TGtkArg): Pglong =
var a = a
Result = cast[ptr pglong](addr(a.d))^
proc GTK_RETLOC_ULONG*(a: TGtkArg): Pgulong =
var a = a
Result = cast[ptr pgulong](addr(a.d))^
proc GTK_RETLOC_FLOAT*(a: TGtkArg): Pgfloat =
var a = a
Result = cast[ptr pgfloat](addr(a.d))^
proc GTK_RETLOC_DOUBLE*(a: TGtkArg): Pgdouble =
var a = a
Result = cast[ptr pgdouble](addr(a.d))^
proc GTK_RETLOC_STRING*(a: TGtkArg): Ppgchar =
var a = a
Result = cast[ptr Ppgchar](addr(a.d))^
proc GTK_RETLOC_ENUM*(a: TGtkArg): Pgint =
var a = a
Result = cast[ptr Pgint](addr(a.d))^
proc GTK_RETLOC_FLAGS*(a: TGtkArg): Pguint =
var a = a
Result = cast[ptr pguint](addr(a.d))^
proc GTK_RETLOC_BOXED*(a: TGtkArg): Pgpointer =
var a = a
Result = cast[ptr pgpointer](addr(a.d))^
proc GTK_RETLOC_OBJECT*(a: TGtkArg): PPGtkObject =
var a = a
Result = cast[ptr ppgtkobject](addr(a.d))^
proc GTK_RETLOC_POINTER*(a: TGtkArg): Pgpointer =
var a = a
Result = cast[ptr pgpointer](addr(a.d))^
proc GTK_TYPE_WIDGET*(): GType =
@ -15108,7 +15139,7 @@ proc gtk_signal_handler_pending_by_func*(anObject: PGtkObject, signal_id: guint,
G_SIGNAL_MATCH_DATA)
if not may_be_blocked:
t = t or cast[int](G_SIGNAL_MATCH_UNBLOCKED)
Result = g_signal_handler_find(anObject, t, signal_id, 0, nil, addr(func_),
Result = g_signal_handler_find(anObject, t, signal_id, 0, nil, func_,
data) != 0
proc GTK_TYPE_SIZE_GROUP*(): GType =
@ -17045,7 +17076,7 @@ type
GTK_FILE_FILTER_FILENAME = 1 shl 0, GTK_FILE_FILTER_URI = 1 shl 1,
GTK_FILE_FILTER_DISPLAY_NAME = 1 shl 2, GTK_FILE_FILTER_MIME_TYPE = 1 shl 3
PGtkFileFilterInfo* = ref TGtkFileFilterInfo
TGtkFileFilterInfo* = record
TGtkFileFilterInfo* {.final.} = object
contains*: TGtkFileFilterFlags
filename*: cstring
uri*: cstring

View file

@ -68,12 +68,12 @@ type
exc: PDomException): PDomString{.cdecl.}
PDomDocument* = ptr TDomDocument
TDomDocument* = record
TDomDocument* {.final.} = object
parent*: PDomNode
iterators*: PGSList
PDomDocumentClass* = ptr TDomDocumentClass
TDomDocumentClass* = record
TDomDocumentClass* {.final.} = object
parent_class*: PDomNodeClass
PHtmlFocusIterator* = ptr THtmlFocusIterator

View file

@ -50,7 +50,7 @@ type
PPangoGlyph* = ptr TPangoGlyph
TPangoGlyph* = guint32
PPangoRectangle* = ptr TPangoRectangle
TPangoRectangle* = record
TPangoRectangle* {.final.} = object
x*: int32
y*: int32
width*: int32
@ -61,7 +61,7 @@ type
PANGO_DIRECTION_LTR, PANGO_DIRECTION_RTL, PANGO_DIRECTION_TTB_LTR,
PANGO_DIRECTION_TTB_RTL
PPangoColor* = ptr TPangoColor
TPangoColor* = record
TPangoColor* {.final.} = object
red*: guint16
green*: guint16
blue*: guint16
@ -72,12 +72,12 @@ type
TPangoUnderline* = int32
PPangoAttribute* = ptr TPangoAttribute
PPangoAttrClass* = ptr TPangoAttrClass
TPangoAttribute* = record
TPangoAttribute* {.final.} = object
klass*: PPangoAttrClass
start_index*: int
end_index*: int
TPangoAttrClass* = record
TPangoAttrClass* {.final.} = object
`type`*: TPangoAttrType
copy*: proc (attr: PPangoAttribute): PPangoAttribute{.cdecl.}
destroy*: proc (attr: PPangoAttribute){.cdecl.}
@ -85,43 +85,43 @@ type
cdecl.}
PPangoAttrString* = ptr TPangoAttrString
TPangoAttrString* = record
TPangoAttrString* {.final.} = object
attr*: TPangoAttribute
value*: cstring
PPangoAttrLanguage* = ptr TPangoAttrLanguage
TPangoAttrLanguage* = record
TPangoAttrLanguage* {.final.} = object
attr*: TPangoAttribute
value*: PPangoLanguage
PPangoAttrInt* = ptr TPangoAttrInt
TPangoAttrInt* = record
TPangoAttrInt* {.final.} = object
attr*: TPangoAttribute
value*: int32
PPangoAttrFloat* = ptr TPangoAttrFloat
TPangoAttrFloat* = record
TPangoAttrFloat* {.final.} = object
attr*: TPangoAttribute
value*: gdouble
PPangoAttrColor* = ptr TPangoAttrColor
TPangoAttrColor* = record
TPangoAttrColor* {.final.} = object
attr*: TPangoAttribute
color*: TPangoColor
PPangoAttrShape* = ptr TPangoAttrShape
TPangoAttrShape* = record
TPangoAttrShape* {.final.} = object
attr*: TPangoAttribute
ink_rect*: TPangoRectangle
logical_rect*: TPangoRectangle
PPangoAttrFontDesc* = ptr TPangoAttrFontDesc
TPangoAttrFontDesc* = record
TPangoAttrFontDesc* {.final.} = object
attr*: TPangoAttribute
desc*: PPangoFontDescription
PPangoLogAttr* = ptr TPangoLogAttr
TPangoLogAttr* = record
TPangoLogAttr* {.final.} = object
flag0*: guint16
PPangoCoverageLevel* = ptr TPangoCoverageLevel
@ -129,25 +129,25 @@ type
PANGO_COVERAGE_NONE, PANGO_COVERAGE_FALLBACK, PANGO_COVERAGE_APPROXIMATE,
PANGO_COVERAGE_EXACT
PPangoBlockInfo* = ptr TPangoBlockInfo
TPangoBlockInfo* = record
TPangoBlockInfo* {.final.} = object
data*: Pguchar
level*: TPangoCoverageLevel
PPangoCoverage* = ptr TPangoCoverage
TPangoCoverage* = record
TPangoCoverage* {.final.} = object
ref_count*: int
n_blocks*: int32
data_size*: int32
blocks*: PPangoBlockInfo
PPangoEngineRange* = ptr TPangoEngineRange
TPangoEngineRange* = record
TPangoEngineRange* {.final.} = object
start*: int32
theEnd*: int32
langs*: cstring
PPangoEngineInfo* = ptr TPangoEngineInfo
TPangoEngineInfo* = record
TPangoEngineInfo* {.final.} = object
id*: cstring
engine_type*: cstring
render_type*: cstring
@ -155,7 +155,7 @@ type
n_ranges*: gint
PPangoEngine* = ptr TPangoEngine
TPangoEngine* = record
TPangoEngine* {.final.} = object
id*: cstring
`type`*: cstring
length*: gint
@ -165,7 +165,7 @@ type
attrs: PPangoLogAttr, attrs_len: int32){.
cdecl.}
PPangoEngineLang* = ptr TPangoEngineLang
TPangoEngineLang* = record
TPangoEngineLang* {.final.} = object
engine*: TPangoEngine
script_break*: TPangoEngineLangScriptBreak
@ -176,7 +176,7 @@ type
language: PPangoLanguage): PPangoCoverage{.
cdecl.}
PPangoEngineShape* = ptr TPangoEngineShape
TPangoEngineShape* = record
TPangoEngineShape* {.final.} = object
engine*: TPangoEngine
script_shape*: TPangoEngineShapeScript
get_coverage*: TPangoEngineShapeGetCoverage
@ -194,28 +194,28 @@ type
PPangoGlyphUnit* = ptr TPangoGlyphUnit
TPangoGlyphUnit* = gint32
PPangoGlyphGeometry* = ptr TPangoGlyphGeometry
TPangoGlyphGeometry* = record
TPangoGlyphGeometry* {.final.} = object
width*: TPangoGlyphUnit
x_offset*: TPangoGlyphUnit
y_offset*: TPangoGlyphUnit
PPangoGlyphVisAttr* = ptr TPangoGlyphVisAttr
TPangoGlyphVisAttr* = record
TPangoGlyphVisAttr* {.final.} = object
flag0*: int16
PPangoGlyphInfo* = ptr TPangoGlyphInfo
TPangoGlyphInfo* = record
TPangoGlyphInfo* {.final.} = object
glyph*: TPangoGlyph
geometry*: TPangoGlyphGeometry
attr*: TPangoGlyphVisAttr
TPangoGlyphString* = record
TPangoGlyphString* {.final.} = object
num_glyphs*: gint
glyphs*: PPangoGlyphInfo
log_clusters*: Pgint
space*: gint
TPangoAnalysis* = record
TPangoAnalysis* {.final.} = object
shape_engine*: PPangoEngineShape
lang_engine*: PPangoEngineLang
font*: PPangoFont
@ -223,7 +223,7 @@ type
language*: PPangoLanguage
extra_attrs*: PGSList
TPangoItem* = record
TPangoItem* {.final.} = object
offset*: gint
length*: gint
num_chars*: gint
@ -236,14 +236,14 @@ type
TPangoWrapMode* = enum
PANGO_WRAP_WORD, PANGO_WRAP_CHAR
PPangoLayoutLine* = ptr TPangoLayoutLine
TPangoLayoutLine* = record
TPangoLayoutLine* {.final.} = object
layout*: PPangoLayout
start_index*: gint
length*: gint
runs*: PGSList
PPangoLayoutRun* = ptr TPangoLayoutRun
TPangoLayoutRun* = record
TPangoLayoutRun* {.final.} = object
item*: PPangoItem
glyphs*: PPangoGlyphString

View file

@ -12,7 +12,7 @@ type
regMN,
regNewline
TRegex = record
TRegex = object of TObject
case kind: TRegexKind
of regChar: c: char
of regSet: s: ref set[char]

View file

@ -162,7 +162,7 @@ type
# Data passed back in callouts
# Const before type ignored
# Pointer to character tables
Tpcre_extra* = record
Tpcre_extra* {.final.} = object
flags: cuint
study_data: pointer
match_limit: cuint
@ -189,7 +189,7 @@ type
# Offset to next item in the pattern
# Length of next item in the pattern
# ------------------------------------------------------------------
TPcre_callout_block* = record
TPcre_callout_block* {.final.} = object
version: cint
callout_number: cint
offset_vector: ptr cint

View file

@ -19,10 +19,8 @@ import
math
type
TComplex* = record ## a complex number, consisting of a real and an
## imaginary part
re*: float ## real part of the complex number
im*: float ## imarginary part of the complex number
TComplex* = tuple[re, im: float]
## a complex number, consisting of a real and an imaginary part
proc `==` *(x, y: TComplex): bool =
## Compare two complex numbers `x` and `y` for equality.

View file

@ -25,23 +25,24 @@ type
dbQuiting, # debugger wants to quit
dbBreakpoints # debugger is only interested in breakpoints
TDbgBreakpoint = record
TDbgBreakpoint {.final.} = object
low, high: int # range from low to high; if disabled
# both low and high are set to their negative values
# this makes the check faster and safes memory
filename: string
name: string # name of breakpoint
TVarSlot {.compilerproc.} = record # variable slots used for debugger:
TVarSlot {.compilerproc, final.} = object # variable slots used for debugger:
address: pointer
typ: PNimType
name: cstring # for globals this is "module.name"
PExtendedFrame = ptr TExtendedFrame
TExtendedFrame = record # If the debugger is enabled the compiler provides
# an extended frame. Of course only slots that are
# needed are allocated and not 10_000, except for
# the global data description.
TExtendedFrame {.final.} = object # If the debugger is enabled the compiler
# provides an extended frame. Of course
# only slots that are
# needed are allocated and not 10_000,
# except for the global data description.
f: TFrame
slots: array[0..10_000, TVarSlot]
@ -69,7 +70,7 @@ proc findBreakpoint(name: string): int =
return -1
proc ListBreakPoints() =
write(stdout, "*** emdb| Breakpoints:\n")
write(stdout, "*** endb| Breakpoints:\n")
for i in 0 .. dbgBPlen-1:
write(stdout, dbgBP[i].name & ": " & $abs(dbgBP[i].low) & ".." &
$abs(dbgBP[i].high) & dbgBP[i].filename)
@ -101,13 +102,13 @@ proc writeVariable(stream: TFile, slot: TVarSlot) =
writeln(stream, dbgRepr(slot.address, slot.typ))
proc ListFrame(stream: TFile, f: PExtendedFrame) =
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n")
write(stream, "*** endb| Frame (" & $f.f.len & " slots):\n")
for i in 0 .. f.f.len-1:
writeVariable(stream, f.slots[i])
write(stream, "***\n")
proc ListVariables(stream: TFile, f: PExtendedFrame) =
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n")
write(stream, "*** endb| Frame (" & $f.f.len & " slots):\n")
for i in 0 .. f.f.len-1:
writeln(stream, f.slots[i].name)
write(stream, "***\n")
@ -115,7 +116,7 @@ proc ListVariables(stream: TFile, f: PExtendedFrame) =
proc debugOut(msg: cstring) =
# the *** *** markers are for easy recognition of debugger
# output for external frontends.
write(stdout, "*** emdb| ")
write(stdout, "*** endb| ")
write(stdout, msg)
write(stdout, "***\n")
@ -131,14 +132,14 @@ proc findVariable(frame: PExtendedFrame, varname: cstring): int =
proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
if dbgFramePointer != nil:
write(stdout, "*** emdb| now in proc: ")
write(stdout, "*** endb| now in proc: ")
write(stdout, dbgFramePointer.procname)
write(stdout, " ***\n")
else:
write(stdout, "*** emdb| (procedure name not available) ***\n")
write(stdout, "*** endb| (procedure name not available) ***\n")
proc dbgShowExecutionPoint() =
write(stdout, "*** emdb| " & $framePtr.filename & "(" & $framePtr.line &
write(stdout, "*** endb| " & $framePtr.filename & "(" & $framePtr.line &
") " & $framePtr.procname & " ***\n")
when defined(windows) or defined(dos) or defined(os2):
@ -219,26 +220,26 @@ h, help display this help message
q, quit quit the debugger and the program
<ENTER> repeat the previous debugger command
EXECUTING
s, stepinto single step, stepping into routine calls
n, stepover single step, without stepping into routine calls
s, step single step, stepping into routine calls
n, next single step, without stepping into routine calls
f, skipcurrent continue execution until the current routine finishes
c, continue continue execution until the next breakpoint
i, ignore continue execution, ignore all breakpoints
BREAKPOINTS
b, setbreak <name> [fromline [toline]] [file]
b, break <name> [fromline [toline]] [file]
set a new breakpoint named 'name' for line and file
if line or file are omitted the current one is used
breakpoints display the entire breakpoint list
disable <name> disable a breakpoint
enable <name> enable a breakpoint
DATA DISPLAY
e, eval <exp> evaluate the expression <exp>
o, out <file> <exp> evaluate <exp> and write it to <file>
e, eval <expr> evaluate the expression <expr>
o, out <file> <expr> evaluate <expr> and write it to <file>
w, where display the current execution point
stackframe [file] display current stack frame [and write it to file]
u, up go up in the call stack
d, down go down in the call stack
callstack display the entire call stack
bt, backtrace display the entire call stack
l, locals display available local variables
g, globals display available global variables
maxdisplay <integer> set the display's recursion maximum
@ -352,7 +353,7 @@ proc CommandPrompt() =
dbgDown: int = 0 # how often we did go down
while again:
write(stdout, "*** emdb| >>")
write(stdout, "*** endb| >>")
var tmp = readLine(stdin)
if tmp.len > 0: dbgUser = tmp
# now look what we have to do:
@ -360,10 +361,10 @@ proc CommandPrompt() =
var i = scanWord(dbgUser, dbgTemp, 0)
case dbgTemp
of "": InvalidCommand()
of "s", "stepinto":
of "s", "step":
dbgState = dbStepInto
again = false
of "n", "stepover":
of "n", "next":
dbgState = dbStepOver
dbgSkipToFrame = framePtr
again = false
@ -412,9 +413,9 @@ proc CommandPrompt() =
dbgShowCurrentProc(dbgFramePtr)
else:
debugOut("[Warning] cannot go down any further ")
of "callstack":
of "bt", "backtrace":
WriteStackTrace()
of "b", "setbreak":
of "b", "break":
setBreakPoint(dbgUser, i)
of "breakpoints":
ListBreakPoints()
@ -443,7 +444,7 @@ proc endbStep() =
proc checkForBreakpoint() =
var i = dbgBreakpointReached(framePtr.line)
if i >= 0:
write(stdout, "*** emdb| reached ")
write(stdout, "*** endb| reached ")
write(stdout, dbgBP[i].name)
write(stdout, " in ")
write(stdout, framePtr.filename)

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@ -35,35 +35,34 @@ proc chckNil(p: pointer) {.inline, compilerproc.}
type
PSafePoint = ptr TSafePoint
TSafePoint {.compilerproc.} = record
TSafePoint {.compilerproc, final.} = object
prev: PSafePoint # points to next safe point ON THE STACK
exc: ref E_Base
status: int
context: C_JmpBuf
var
excHandler {.compilerproc, volatile.}: PSafePoint = nil
excHandler {.compilerproc.}: PSafePoint = nil
# list of exception handlers
# a global variable for the root of all try blocks
proc reraiseException() =
if excHandler != nil:
if excHandler == nil:
raise newException(ENoExceptionToReraise, "no exception to reraise")
else:
c_longjmp(excHandler.context, 1)
type
PFrame = ptr TFrame
TFrame {.importc, nodecl.} = record
TFrame {.importc, nodecl, final.} = object
prev: PFrame
procname: CString
line: int # current line number
filename: CString
len: int # length of slots (when not debugging always zero)
TTempFrame = record # used for recursion elimination in WriteStackTrace
procname: CString
line: int
TTempFrame = tuple[ # used for recursion elimination in WriteStackTrace
procname: CString, line: int]
var
buf: string # cannot be allocated on the stack!
@ -71,7 +70,7 @@ var
# assert, as it raises an exception and
# exception handler needs the buffer too
framePtr {.exportc, volatile.}: PFrame
framePtr {.exportc.}: PFrame
tempFrames: array [0..255, TTempFrame] # cannot be allocated
# on the stack!
@ -82,8 +81,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
i = 0
total = 0
while it != nil and i <= high(tempFrames):
tempFrames[i].procname = it.procname
tempFrames[i].line = it.line
tempFrames[i] = (it.procname, it.line)
inc(i)
inc(total)
it = it.prev
@ -110,10 +108,10 @@ proc rawWriteStackTrace(s: var string) =
auxWriteStackTrace(framePtr, s)
proc quitOrDebug() {.inline.} =
when not defined(emdb):
when not defined(endb):
quit(1)
else:
emdbStep() # call the debugger
endbStep() # call the debugger
proc raiseException(e: ref E_Base, ename: CString) =
GC_disable() # a bad thing is an error in the GC while raising an exception
@ -122,7 +120,7 @@ proc raiseException(e: ref E_Base, ename: CString) =
excHandler.exc = e
c_longjmp(excHandler.context, 1)
else:
if cast[pointer](buf) != nil:
if not isNil(buf):
setLen(buf, 0)
rawWriteStackTrace(buf)
if e.msg != nil and e.msg[0] != '\0':
@ -135,9 +133,7 @@ proc raiseException(e: ref E_Base, ename: CString) =
add(buf, "]\n")
writeToStdErr(buf)
else:
writeToStdErr("*** FATAL ERROR *** ")
writeToStdErr(ename)
writeToStdErr("\n")
quitOrDebug()
GC_enable()
@ -147,7 +143,8 @@ var
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
if not cond:
GC_disable() # BUGFIX: `$` allocates a new string object!
if cast[pointer](assertBuf) != nil: # BUGFIX: when debugging the GC, assertBuf may be nil
if not isNil(assertBuf):
# BUGFIX: when debugging the GC, assertBuf may be nil
setLen(assertBuf, 0)
add(assertBuf, "[Assertion failure] file: ")
add(assertBuf, file)
@ -164,6 +161,11 @@ proc WriteStackTrace() =
rawWriteStackTrace(s)
writeToStdErr(s)
#proc stackTraceWrapper {.noconv.} =
# writeStackTrace()
#addQuitProc(stackTraceWrapper)
var
dbgAborting: bool # whether the debugger wants to abort
@ -171,6 +173,7 @@ proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
# print stack trace and quit
var
s = int(sig)
GC_disable()
setLen(buf, 0)
rawWriteStackTrace(buf)
@ -185,6 +188,7 @@ proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
else: add(buf, "unknown signal\n")
writeToStdErr(buf)
dbgAborting = True # play safe here...
GC_enable()
quit(1) # always quit when SIGABRT
proc registerSignalHandler() =
@ -195,8 +199,8 @@ proc registerSignalHandler() =
c_signal(SIGILL, signalHandler)
c_signal(SIGBUS, signalHandler)
registerSignalHandler() # call it in initialization section
# for easier debugging of the GC, this memory is only allocated after the
registerSignalHandler() # call it in initialization section
# for easier debugging of the GC, this memory is only allocated after the
# signal handlers have been registered
new(gAssertionFailed)
buf = newString(2048)
@ -204,12 +208,15 @@ assertBuf = newString(2048)
setLen(buf, 0)
setLen(assertBuf, 0)
proc raiseRangeError() {.compilerproc, noreturn.} =
raise newException(EOutOfRange, "value out of range")
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn.} =
raise newException(EOutOfRange, "value " & $val & " out of range")
proc raiseIndexError() {.compilerproc, noreturn.} =
raise newException(EInvalidIndex, "index out of bounds")
proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
raise newException(EInvalidField, f & " is not accessible")
proc chckIndx(i, a, b: int): int =
if i >= a and i <= b:
return i
@ -220,19 +227,19 @@ proc chckRange(i, a, b: int): int =
if i >= a and i <= b:
return i
else:
raiseRangeError()
raiseRangeError(i)
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
if i >= a and i <= b:
return i
else:
raiseRangeError()
raiseRangeError(i)
proc chckRangeF(x, a, b: float): float =
if x >= a and x <= b:
return x
else:
raiseRangeError()
raise newException(EOutOfRange, "value " & $x & " out of range")
proc chckNil(p: pointer) =
if p == nil: c_raise(SIGSEGV)

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@ -13,33 +13,39 @@
# For a description of the algorithms used here see:
# intern.html
#{.define: debugGC.} # we wish to debug the GC...
{.define: debugGC.} # we wish to debug the GC...
#when defined(debugGC):
# {.define: logGC.} # define if the GC should log some of its activities
{.define: cycleGC.}
const
traceGC = false # extensive debugging
reallyDealloc = true # for debugging purposes this can be set to false
# Guess the page size of the system; if it is the
# wrong value, performance may be worse (this is not
# for sure though), but GC still works; must be a power of two!
const
PageSize = 1024 * sizeof(int)
RC_Increase = 7 * PageSize # is an additive increase
PageShift = if sizeof(pointer) == 4: 12 else: 13
PageSize = 1 shl PageShift # on 32 bit systems 4096
CycleIncrease = 2 # is a multiplicative increase
InitialCycleThreshold = 8*1024*1024 # X MB because cycle checking is slow
ZctThreshold = 512 # we collect garbage if the ZCT's size
# reaches this threshold
# this needs benchmarking...
when defined(debugGC):
const InitialThreshold = 64*1024
const stressGC = True # GC is debugged; no need to stress it
const stressGC = False
else:
const stressGC = False
const InitialThreshold = RC_Increase
# this may need benchmarking...
# things the System module thinks should be available:
when defined(useDL) or defined(nativeDL):
type
TMallocInfo {.importc: "struct mallinfo", nodecl.} = record
TMallocInfo {.importc: "struct mallinfo", nodecl, final.} = object
arena: cint # non-mmapped space allocated from system
ordblks: cint # number of free chunks
smblks: cint # number of fastbin blocks
@ -68,8 +74,7 @@ else: # not available:
proc getTotalMem(): int = return -1
var
rcThreshold: int = InitialThreshold
cycleThreshold: int = InitialThreshold
cycleThreshold: int = InitialCycleThreshold
memUsed: int = 0 # we have to keep track how much we have allocated
@ -113,11 +118,12 @@ type
waNone, waRelease, waZctDecRef, waCycleDecRef, waCycleIncRef, waDebugIncRef
TCollectorData = int
TCell = record
TCell {.final.} = object
refcount: TCollectorData # the refcount and bit flags
typ: PNimType
stackcount: int # stack counter for debugging
drefc: int # real reference counter for debugging
when stressGC:
stackcount: int # stack counter for debugging
drefc: int # real reference counter for debugging
PCell = ptr TCell
@ -145,6 +151,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
result = int(usrToCell(p).refcount)
if result < 0: result = 0
proc gcAlloc(size: int): pointer =
result = alloc0(size)
@ -162,7 +169,7 @@ proc GC_setStrategy(strategy: TGC_Strategy) =
of gcOptimizeTime: nil
proc GC_enableMarkAndSweep() =
cycleThreshold = InitialThreshold
cycleThreshold = InitialCycleThreshold
proc GC_disableMarkAndSweep() =
cycleThreshold = high(cycleThreshold)-1
@ -174,7 +181,7 @@ proc nextTry(h, maxHash: int): int {.inline.} =
# generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof).
# ------------------ Zero count table (ZCT) and any table (AT) -------------
# ------------------ Any table (AT) -------------
# these values are for DL-malloc known for sure (and other allocators
# can only be worse):
@ -200,8 +207,7 @@ when BitsPerPage mod BitsPerUnit != 0:
# ------------------- cell set handling ------------------------------
# A cellset consists of a hash table of page descriptors. A page
# descriptor has a bit for
# every Memalignment'th byte in the page.
# descriptor has a bit for every Memalignment'th byte in the page.
# However, only bits corresponding to addresses that start memory blocks
# are set.
# Page descriptors are also linked to a list; the list
@ -217,17 +223,59 @@ type
TBitIndex = range[0..UnitsPerPage-1]
TPageDesc = record
TPageDesc {.final.} = object
next: PPageDesc # all nodes are connected with this pointer
key: TAddress # start address at bit 0
bits: array[TBitIndex, int] # a bit vector
PPageDescArray = ptr array[0..1000_000, PPageDesc]
TCellSet = record
TCellSet {.final.} = object
counter, max: int
head: PPageDesc
data: PPageDescArray
PCellArray = ptr array[0..100_000_000, PCell]
TCellSeq {.final.} = object
len, cap: int
d: PCellArray
TSlowSet {.final.} = object # used for debugging purposes only
L: int # current length
cap: int # capacity
d: PCellArray
TGcHeap {.final.} = object # this contains the zero count and
# non-zero count table
mask: TAddress # mask for fast pointer detection
zct: TCellSeq # the zero count table
at: TCellSet # a table that contains all references
newAT: TCellSet
stackCells: TCellSeq # cells that need to be decremented because they
# are in the hardware stack; a cell may occur
# several times in this data structure
var
stackBottom: pointer
gch: TGcHeap
proc add(s: var TCellSeq, c: PCell) {.inline.} =
if s.len >= s.cap:
s.cap = s.cap * 3 div 2
s.d = cast[PCellArray](realloc(s.d, s.cap * sizeof(PCell)))
if s.d == nil: raiseOutOfMem()
s.d[s.len] = c
inc(s.len)
proc inOperator(s: TCellSeq, c: PCell): bool {.inline.} =
for i in 0 .. s.len-1:
if s.d[i] == c: return True
return False
proc init(s: var TCellSeq, cap: int = 1024) =
s.len = 0
s.cap = cap
s.d = cast[PCellArray](gcAlloc(cap * sizeof(PCell)))
const
InitCellSetSize = 1024 # must be a power of two!
@ -284,7 +332,8 @@ proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
if x.key == key: return x
h = nextTry(h, t.max)
if (t.max+1) * 2 < t.counter * 3: CellSetEnlarge(t)
if ((t.max+1)*2 < t.counter*3) or ((t.max+1)-t.counter < 4):
CellSetEnlarge(t)
inc(t.counter)
h = cast[int](key) and t.max
while t.data[h] != nil: h = nextTry(h, t.max)
@ -303,7 +352,7 @@ proc in_Operator(s: TCellSet, cell: PCell): bool =
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize)
t = CellSetGet(s, u shr PageShift)
if t != nil:
u = (u %% PageSize) /% MemAlignment
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
@ -315,7 +364,7 @@ proc incl(s: var TCellSet, cell: PCell) =
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetPut(s, u /% PageSize)
t = CellSetPut(s, u shr PageShift)
u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
(1 shl (u %% BitsPerUnit))
@ -325,7 +374,7 @@ proc excl(s: var TCellSet, cell: PCell) =
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize)
t = CellSetGet(s, u shr PageShift)
if t != nil:
u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
@ -342,7 +391,7 @@ iterator elements(t: TCellSet): PCell {.inline.} =
var j = 0
while w != 0: # test all remaining bits for zero
if (w and 1) != 0: # the bit is set!
yield cast[PCell]((r.key *% PageSize) +%
yield cast[PCell]((r.key shl PageShift) or # +%
(i*%BitsPerUnit+%j) *% MemAlignment)
inc(j)
w = w shr 1
@ -354,68 +403,121 @@ iterator elements(t: TCellSet): PCell {.inline.} =
proc testPageDescs() =
var root: TCellSet
CellSetInit(root)
var u = 10_000
while u <= 20_000:
incl(root, cast[PCell](u))
inc(u, 8)
for cell in elements(root):
c_fprintf(c_stdout, "%ld\n", cast[int](cell))
#var u = 10_000
#while u <= 20_000:
# incl(root, cast[PCell](u))
# inc(u, 8)
# testPageDescs()
incl(root, cast[PCell](0x81cdfb8))
for cell in elements(root):
c_fprintf(c_stdout, "%p\n", cast[int](cell))
#testPageDescs()
when defined(debugGC):
proc writeCell(msg: CString, c: PCell) =
c_fprintf(c_stdout, "%s: %p\n", msg, c)
if c.typ != nil:
if c.typ.kind == tyString:
c_fprintf(c_stdout, "%s\n", cast[TAddress](cellToUsr(c)) + sizeof(int)*2)
c_fprintf(c_stdout, "%s: %p %d\n", msg, c, c.typ.kind)
else: c_fprintf(c_stdout, "%s: %p (nil type)\n", msg, c)
proc writePtr(msg: CString, p: Pointer) =
c_fprintf(c_stdout, "%s: %p\n", msg, p)
when traceGC:
# traceGC is a special switch to enable extensive debugging
type
TCellState = enum
csAllocated, csZctFreed, csCycFreed
proc cellSetInit(s: var TSlowSet) =
s.L = 0
s.cap = 4096
s.d = cast[PCellArray](gcAlloc(s.cap * sizeof(PCell)))
proc cellSetDeinit(s: var TSlowSet) =
s.L = 0
s.cap = 0
dealloc(s.d)
proc incl(s: var TSlowSet, c: PCell) =
if s.L >= s.cap:
s.cap = s.cap * 3 div 2
s.d = cast[PCellArray](realloc(s.d, s.cap * sizeof(PCell)))
if s.d == nil: raiseOutOfMem()
s.d[s.L] = c
inc(s.L)
proc excl(s: var TSlowSet, c: PCell) =
var i = 0
while i < s.L:
if s.d[i] == c:
s.d[i] = s.d[s.L-1]
dec(s.L)
break
inc(i)
proc inOperator(s: TSlowSet, c: PCell): bool =
var i = 0
while i < s.L:
if s.d[i] == c: return true
inc(i)
iterator elements(s: TSlowSet): PCell =
var i = 0
while i < s.L:
yield s.d[i]
inc(i)
var
states: array[TCellState, TSlowSet] # TCellSet]
proc traceCell(c: PCell, state: TCellState) =
case state
of csAllocated:
if c in states[csAllocated]:
writeCell("attempt to alloc a already allocated cell", c)
assert(false)
excl(states[csCycFreed], c)
excl(states[csZctFreed], c)
of csZctFreed:
if c notin states[csAllocated]:
writeCell("attempt to free a not allocated cell", c)
assert(false)
if c in states[csZctFreed]:
writeCell("attempt to free zct cell twice", c)
assert(false)
if c in states[csCycFreed]:
writeCell("attempt to free with zct, but already freed with cyc", c)
assert(false)
excl(states[csAllocated], c)
of csCycFreed:
if c notin states[csAllocated]:
writeCell("attempt to free a not allocated cell", c)
assert(false)
if c in states[csCycFreed]:
writeCell("attempt to free cyc cell twice", c)
assert(false)
if c in states[csZctFreed]:
writeCell("attempt to free with cyc, but already freed with zct", c)
assert(false)
excl(states[csAllocated], c)
incl(states[state], c)
template gcTrace(cell, state: expr): stmt =
when traceGC: traceCell(cell, state)
# -------------------------------------------------------------------------
type
PStackCells = ptr array[0..1000_0000, PCell]
TCountTables = record # this contains the zero count and
# non-zero count table
mask: TAddress # mask for fast pointer detection
zct: TCellSet # the zero count table
at: TCellSet # a table that contains all references
newAT: TCellSet
newZCT: TCellSet
stackCells: PStackCells # cells that need to be decremented because they
# are in the hardware stack; a cell may occur
# several times in this data structure
stackLen, stackMax: int # for managing the stack cells
# forward declarations:
proc collectCT(gch: var TGcHeap)
proc IsOnStack(p: pointer): bool
proc forAllChildren(cell: PCell, op: TWalkOp)
proc collectCycles(gch: var TGcHeap)
proc addStackCell(ct: var TCountTables, cell: PCell) =
if ct.stackLen >= ct.stackMax:
ct.stackMax = ct.stackMax * 3 div 2
ct.stackCells = cast[PStackCells](realloc(ct.stackCells, ct.stackMax *
sizeof(PCell)))
if ct.stackCells == nil: raiseOutOfMem()
ct.stackCells[ct.stackLen] = cell
inc(ct.stackLen)
var
stackBottom: pointer
ct: TCountTables
proc GC_invariant(): bool =
result = True
when stressGC:
if recGcLock == 0:
GC_disable()
for cell in elements(ct.at):
var t = cell.typ # getCellType(cell)
if t == nil or t.kind notin {tySequence, tyString, tyRef}:
writeCell("corrupt cell?", cell)
result = false
GC_enable()
when stressGC:
proc GCdebugHook() =
if not GC_invariant():
assert(false)
dbgLineHook = GCdebugHook
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
# we need the prototype here for debugging purposes
proc prepareDealloc(cell: PCell) =
if cell.typ.finalizer != nil:
@ -433,79 +535,95 @@ proc prepareDealloc(cell: PCell) =
else:
memUsed = memUsed - cell.typ.size
proc checkZCT(): bool =
if recGcLock >= 1: return true # prevent endless recursion
inc(recGcLock)
result = true
for i in 0..gch.zct.len-1:
var c = gch.zct.d[i]
if c.refcount > 0: # should be in the ZCT!
writeCell("wrong ZCT entry", c)
result = false
elif gch.zct.d[-c.refcount] != c:
writeCell("wrong ZCT position", c)
result = false
dec(recGcLock)
proc GC_invariant(): bool =
if recGcLock >= 1: return true # prevent endless recursion
inc(recGcLock)
result = True
block checks:
if not checkZCT():
result = false
break checks
# set counters back to zero:
for c in elements(gch.AT):
var t = c.typ
if t == nil or t.kind notin {tySequence, tyString, tyRef}:
writeCell("corrupt cell?", c)
result = false
break checks
when stressGC: c.drefc = 0
for c in elements(gch.AT):
forAllChildren(c, waDebugIncRef)
when stressGC:
for c in elements(gch.AT):
var rc = c.refcount
if rc < 0: rc = 0
if c.drefc > rc + c.stackcount:
result = false # failed
c_fprintf(c_stdout,
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
c, c.refcount, c.stackcount, c.drefc)
break checks
dec(recGcLock)
when stressGC:
proc GCdebugHook() =
if not GC_invariant():
assert(false)
dbgLineHook = GCdebugHook
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
stackBottom = theStackBottom
proc initGC() =
when traceGC:
for i in low(TCellState)..high(TCellState): CellSetInit(states[i])
# init the rt
CellSetInit(ct.zct)
CellSetInit(ct.at)
ct.stackLen = 0
ct.stackMax = 255
ct.stackCells = cast[PStackCells](gcAlloc((ct.stackMax+1) * sizeof(PCell)))
ct.mask = 0
init(gch.zct)
CellSetInit(gch.at)
init(gch.stackCells)
gch.mask = 0
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
assert(GC_invariant())
# forward declarations:
proc collectCT(ct: var TCountTables)
proc IsOnStack(p: pointer): bool
proc forAllChildren(cell: PCell, op: TWalkOp)
proc collectCycles()
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
# we need the prototype here for debugging purposes
proc outputCell(c: PCell) =
inc(recGcLock)
write(stdout, reprAny(cellToUsr(c), c.typ))
dec(recGcLock)
proc writeGraph() =
{.checkpoint.}
block:
inc(recGcLock)
for c in elements(ct.AT): outputCell(c)
dec(recGcLock)
proc checkRefc(): bool =
if recGcLock >= 1: return true # prevent endless recursion
inc(recGcLock)
result = True
# set counters back to zero:
for c in elements(ct.AT):
c.drefc = 0
for c in elements(ct.AT):
forAllChildren(c, waDebugIncRef)
for c in elements(ct.AT):
if c.drefc > c.refcount - c.stackcount:
result = false # failed
c_fprintf(c_stdout,
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
c, c.refcount, c.stackcount, c.drefc)
dec(recGcLock)
proc seqCheck(cell: PCell): bool =
assert(cell.typ != nil)
if cell.typ.kind in {tySequence, tyString}:
result = cell.refcount - cell.stackcount <= 1
else:
result = true
proc decRef(cell: PCell) {.inline.} =
assert(cell in ct.AT)
when defined(debugGC):
if cell.refcount == 0:
writePtr("decref broken", cellToUsr(cell))
assert(cell.refcount > 0) # this should be the case!
assert(seqCheck(cell))
when stressGC: assert(cell in gch.AT)
dec(cell.refcount)
if cell.refcount == 0:
incl(ct.zct, cell)
cell.refcount = -gch.zct.len
when stressGC: assert(cell notin gch.zct)
add(gch.zct, cell)
when stressGC: assert(checkZCT())
proc incRef(cell: PCell) {.inline.} =
assert(seqCheck(cell))
inc(cell.refcount)
var rc = cell.refcount
if rc <= 0:
# remove from zero count table:
when stressGC: assert(gch.zct.len > -rc)
when stressGC: assert(gch.zct.d[-rc] == cell)
gch.zct.d[-rc] = gch.zct.d[gch.zct.len-1]
gch.zct.d[-rc].refcount = rc
dec(gch.zct.len)
cell.refcount = 1
when stressGC: assert(checkZCT())
else:
inc(cell.refcount)
when stressGC: assert(checkZCT())
proc asgnRef(dest: ppointer, src: pointer) =
# the code generator calls this proc!
@ -514,18 +632,18 @@ proc asgnRef(dest: ppointer, src: pointer) =
if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
#assert(checkRefc())
when stressGC: assert(GC_invariant())
proc unsureAsgnRef(dest: ppointer, src: pointer) =
if not IsOnStack(dest):
if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
#assert(checkRefc())
when stressGC: assert(GC_invariant())
proc restore(cell: PCell) =
if cell notin ct.newAT:
incl(ct.newAT, Cell)
if cell notin gch.newAT:
incl(gch.newAT, Cell)
forAllChildren(cell, waCycleIncRef)
proc doOperation(p: pointer, op: TWalkOp) =
@ -536,19 +654,15 @@ proc doOperation(p: pointer, op: TWalkOp) =
of waNone: assert(false)
of waRelease: decRef(cell) # DEAD CODE!
of waZctDecRef:
assert(cell.refcount > 0)
assert(seqCheck(cell))
dec(cell.refcount)
if cell.refcount == 0:
incl(ct.newZCT, cell)
decRef(cell)
of waCycleDecRef:
assert(cell.refcount != 0)
assert(cell.refcount > 0)
dec(cell.refcount)
of waCycleIncRef:
inc(cell.refcount) # restore proper reference counts!
restore(cell)
of waDebugIncRef:
inc(cell.drefc)
when stressGC: inc(cell.drefc)
type
TByteArray = array[0..1000_0000, byte]
@ -590,16 +704,20 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
if m != nil: forAllSlotsAux(dest, m, op)
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
const
handledTypes = {tyArray, tyArrayConstr, tyOpenArray, tyRef,
tyString, tySequence, tyObject, tyPureObject, tyTuple}
var
d = cast[TAddress](dest)
if dest == nil: return # nothing to do
case mt.Kind
of tyArray, tyArrayConstr, tyOpenArray:
for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
if mt.base.kind in handledTypes:
for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
of tyRef, tyString, tySequence: # leaf:
doOperation(cast[ppointer](d)^, op)
of tyRecord, tyObject, tyTuple:
of tyObject, tyTuple, tyPureObject:
forAllSlotsAux(dest, mt.node, op)
else: nil
@ -608,6 +726,13 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
when defined(debugGC):
if cell.typ == nil:
writeCell("cell has no type descriptor", cell)
when traceGC:
if cell notin states[csAllocated]:
writeCell("cell has never been allocated!", cell)
if cell in states[csCycFreed]:
writeCell("cell has been freed by Cyc", cell)
if cell in states[csZctFreed]:
writeCell("cell has been freed by Zct", cell)
assert(cell.typ != nil)
case cell.typ.Kind
of tyRef: # common case
@ -625,36 +750,36 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
proc checkCollection() {.inline.} =
# checks if a collection should be done
if recGcLock == 0:
if memUsed >= rcThreshold or stressGC:
collectCT(ct)
when defined(debugGC):
write(stdout, "threshold is now: ")
writeln(stdout, rcThreshold)
collectCT(gch)
proc newObj(typ: PNimType, size: int): pointer =
# generates a new object and sets its reference counter to 0
var
res: PCell
when stressGC: assert(checkZCT())
assert(typ.kind in {tyRef, tyString, tySequence})
# check if we have to collect:
checkCollection()
res = cast[PCell](Alloc0(size + sizeof(TCell)))
when stressGC: assert((cast[TAddress](res) and (MemAlignment-1)) == 0)
if res == nil: raiseOutOfMem()
when defined(nimSize):
memUsed = memUsed + nimSize(res)
else:
memUsed = memUsed + size
res.refcount = 0
# now it is buffered in the ZCT
res.typ = typ
incl(ct.zct, res) # its refcount is zero, so add it to the ZCT
incl(ct.at, res) # add it to the any table too
ct.mask = ct.mask or cast[TAddress](res)
res.refcount = -gch.zct.len
add(gch.zct, res) # its refcount is zero, so add it to the ZCT
incl(gch.at, res) # add it to the any table too
gch.mask = gch.mask or cast[TAddress](res)
when defined(debugGC):
writeCell("new cell", res)
assert(gcInvariant())
when defined(logGC): writeCell("new cell", res)
gcTrace(res, csAllocated)
result = cellToUsr(res)
assert(res.typ == typ)
when stressGC: assert(checkZCT())
proc newSeq(typ: PNimType, len: int): pointer =
# XXX: overflow checks!
@ -665,16 +790,19 @@ proc newSeq(typ: PNimType, len: int): pointer =
proc growObj(old: pointer, newsize: int): pointer =
var
res, ol: PCell
when stressGC: assert(checkZCT())
checkCollection()
ol = usrToCell(old)
assert(ol.typ.kind in {tyString, tySequence})
assert(seqCheck(ol))
when defined(nimSize):
memUsed = memUsed - nimSize(ol)
else:
memUsed = memUsed - ol.size # this is not exact
# pity that we don't know the old size
# pity that we don't know the old size
res = cast[PCell](realloc(ol, newsize + sizeof(TCell)))
#res = cast[PCell](gcAlloc(newsize + sizeof(TCell)))
#copyMem(res, ol, nimSize(ol))
assert((cast[TAddress](res) and (MemAlignment-1)) == 0)
when defined(nimSize):
memUsed = memUsed + nimSize(res)
else:
@ -682,74 +810,69 @@ proc growObj(old: pointer, newsize: int): pointer =
if res != ol:
if res == nil: raiseOutOfMem()
excl(ct.zct, ol) # remove old pointer in any case:
# It may have a refcount > 0 and is still in the ZCT.
# So do it safe here and remove it anyway.
excl(ct.at, ol)
if res.refcount == 0:
# store new pointer in ZCT, if refcount == 0:
incl(ct.zct, res)
incl(ct.at, res)
ct.mask = ct.mask or cast[TAddress](res)
when defined(debugGC):
if res.refcount <= 0:
assert(gch.zct.d[-res.refcount] == ol)
gch.zct.d[-res.refcount] = res
excl(gch.at, ol)
incl(gch.at, res)
gch.mask = gch.mask or cast[TAddress](res)
when defined(logGC):
writeCell("growObj old cell", ol)
writeCell("growObj new cell", res)
gcTrace(ol, csZctFreed)
gcTrace(res, csAllocated)
result = cellToUsr(res)
#assert(checkRefc())
when stressGC: assert(checkZCT())
proc collectCycles() =
when defined(debugGC):
echo("collecting cycles!\n")
proc collectCycles(gch: var TGcHeap) =
when defined(logGC):
c_fprintf(c_stdout, "collecting cycles!\n")
# step 1: pretend that any node is dead
for c in elements(ct.at):
for c in elements(gch.at):
forallChildren(c, waCycleDecRef)
CellSetInit(ct.newAt)
CellSetInit(gch.newAt)
# step 2: restore life cells
for c in elements(ct.at):
for c in elements(gch.at):
if c.refcount > 0: restore(c)
# step 3: free dead cells:
for cell in elements(ct.at):
for cell in elements(gch.at):
if cell.refcount == 0:
assert(cell notin ct.zct)
# We free an object that is part of a cycle here. Its children
# may have been freed already. Thus the finalizer could access
# garbage. To handle this case properly we need two passes for
# freeing here which is too expensive. We just don't call the
# finalizer for now. YYY: Any better ideas?
prepareDealloc(cell)
dealloc(cell)
when defined(debugGC):
gcTrace(cell, csCycFreed)
when defined(logGC):
writeCell("cycle collector dealloc cell", cell)
CellSetDeinit(ct.at)
ct.at = ct.newAt
#ct.newAt = nil
when reallyDealloc: dealloc(cell)
CellSetDeinit(gch.at)
gch.at = gch.newAt
proc gcMark(p: pointer) =
proc gcMark(gch: var TGcHeap, p: pointer) =
# the addresses are not as objects on the stack, so turn them to objects:
var cell = usrToCell(p)
var c = cast[TAddress](cell)
if ((c and ct.mask) == c) and cell in ct.at:
if ((c and gch.mask) == c) and cell in gch.at:
# is the page that p "points to" in the AT? (All allocated pages are
# always in the AT)
inc(cell.refcount)
inc(cell.stackcount)
addStackCell(ct, cell)
incRef(cell)
when stressGC: inc(cell.stackcount)
add(gch.stackCells, cell)
proc unmarkStackAndRegisters() =
for i in 0 .. ct.stackLen-1:
var cell = ct.stackCells[i]
proc unmarkStackAndRegisters(gch: var TGcHeap) =
when stressGC: assert(checkZCT())
for i in 0 .. gch.stackCells.len-1:
var cell = gch.stackCells.d[i]
assert(cell.refcount > 0)
when defined(debugGC):
if cell.stackcount == 0:
writeGraph()
writePtr("broken stackcount", cellToUsr(cell))
assert(cell.stackcount > 0)
dec(cell.refcount)
dec(cell.stackcount)
if cell.refcount == 0:
incl(ct.zct, cell)
ct.stackLen = 0 # reset to zero
when stressGC:
assert(cell.stackcount > 0)
dec(cell.stackcount)
decRef(cell)
gch.stackCells.len = 0 # reset to zero
when stressGC: assert(checkZCT())
# ----------------- stack management --------------------------------------
# inspired from Smart Eiffel (c)
@ -765,7 +888,7 @@ when defined(sparc): # For SPARC architecture.
stackTop: array[0..1, pointer]
result = p >= addr(stackTop[0]) and p <= stackBottom
proc markStackAndRegisters() =
proc markStackAndRegisters(gch: var TGcHeap) =
when defined(sparcv9):
asm " flushw"
else:
@ -780,7 +903,7 @@ when defined(sparc): # For SPARC architecture.
sp = addr(stackTop[0])
# Addresses decrease as the stack grows.
while sp <= max:
gcMark(sp^)
gcMark(gch, sp^)
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
elif defined(ELATE):
@ -802,7 +925,7 @@ elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
# a little hack to get the size of a TJmpBuf in the generated C code
# in a platform independant way
proc markStackAndRegisters() =
proc markStackAndRegisters(gch: var TGcHeap) =
var
max = stackBottom
registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
@ -814,7 +937,7 @@ elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
# sp will traverse the JMP_BUF as well (jmp_buf size is added,
# otherwise sp would be below the registers structure).
while sp >= max:
gcMark(sp^)
gcMark(gch, sp^)
sp = cast[ppointer](cast[TAddress](sp) -% sizeof(pointer))
else:
@ -826,7 +949,7 @@ else:
stackTop: array [0..1, pointer]
result = p >= addr(stackTop[0]) and p <= stackBottom
proc markStackAndRegisters() =
proc markStackAndRegisters(gch: var TGcHeap) =
var
max = stackBottom
registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
@ -835,63 +958,58 @@ else:
c_setjmp(registers) # To fill the C stack with registers.
sp = cast[ppointer](addr(registers))
while sp <= max:
gcMark(sp^)
gcMark(gch, sp^)
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
# ----------------------------------------------------------------------------
# end of non-portable code
# ----------------------------------------------------------------------------
proc CollectZCT =
CellSetInit(ct.newZCT)
for c in elements(ct.zct):
if c.refcount == 0:
# if != 0 the reference count has been increased, so this does not
# belong to the ZCT. We simply do nothing - it won't appear in the newZCT
# anyway.
# We are about to free the object, call the finalizer BEFORE its
# children are deleted as well, because otherwise the finalizer may
# access invalid memory. This is done by prepareDealloc():
prepareDealloc(c)
forAllChildren(c, waZctDecRef)
assert(c.refcount == 0) # should still be zero
excl(ct.at, c)
excl(ct.newZCT, c) # BUGFIX
when defined(debugGC):
writeCell("zct dealloc cell", c)
dealloc(c)
CellSetDeinit(ct.zct)
ct.zct = ct.newZCT
#ct.newZCT = nil
proc CollectZCT(gch: var TGcHeap) =
while gch.zct.len > 0:
var c = gch.zct.d[0]
assert(c.refcount <= 0)
# remove from ZCT:
gch.zct.d[0] = gch.zct.d[gch.zct.len-1]
gch.zct.d[0].refcount = 0
dec(gch.zct.len)
# We are about to free the object, call the finalizer BEFORE its
# children are deleted as well, because otherwise the finalizer may
# access invalid memory. This is done by prepareDealloc():
gcTrace(c, csZctFreed)
prepareDealloc(c)
forAllChildren(c, waZctDecRef)
excl(gch.at, c)
when defined(logGC):
writeCell("zct dealloc cell", c)
#when defined(debugGC) and defined(nimSize): zeroMem(c, nimSize(c))
when reallyDealloc: dealloc(c)
proc collectCT(ct: var TCountTables) =
when defined(debugGC):
proc collectCT(gch: var TGcHeap) =
when defined(logGC):
c_fprintf(c_stdout, "collecting zero count table; stack size: %ld\n",
stackSize())
markStackAndRegisters()
assert(GC_invariant())
while True:
collectZCT()
if ct.zct.counter == 0: break
# ``counter`` counts the pages, but zero pages means zero cells
when defined(cycleGC):
# still over the cycle threshold?
if memUsed >= cycleThreshold or stressGC:
# collect the cyclic things:
assert(ct.zct.counter == 0)
assert(GC_invariant())
collectCycles()
# recompute the thresholds:
rcThreshold = (memUsed div RC_increase + 1) * RC_Increase
cycleThreshold = memUsed * cycleIncrease
assert(GC_invariant())
unmarkStackAndRegisters()
when stressGC: assert(checkZCT())
if gch.zct.len >= ZctThreshold or memUsed >= cycleThreshold or stressGC:
markStackAndRegisters(gch)
when stressGC: assert(GC_invariant())
collectZCT(gch)
when stressGC: assert(GC_invariant())
assert(gch.zct.len == 0)
when defined(cycleGC):
if memUsed >= cycleThreshold or stressGC:
when defined(logGC):
c_fprintf(c_stdout, "collecting cycles; memory used: %ld\n", memUsed)
collectCycles(gch)
cycleThreshold = max(InitialCycleThreshold, memUsed * cycleIncrease)
when defined(logGC):
c_fprintf(c_stdout, "now used: %ld; threshold: %ld\n",
memUsed, cycleThreshold)
unmarkStackAndRegisters(gch)
when stressGC: assert(GC_invariant())
proc GC_fullCollect() =
var oldThreshold = cycleThreshold
cycleThreshold = 0 # forces cycle collection
collectCT(ct)
collectCT(gch)
cycleThreshold = oldThreshold

View file

@ -10,29 +10,38 @@
type # This should be he same as ast.TTypeKind
# some enum fields are not used at runtime
TNimKind = enum
tyNone, tyBool, tyChar,
tyEmptySet, tyArrayConstr, tyNil, tyRecordConstr,
tyGeneric,
tyGenericInst,
tyGenericParam,
tyEnum, tyAnyEnum,
tyArray,
tyRecord,
tyObject,
tyTuple,
tySet,
tyRange,
tyPtr, tyRef,
tyVar,
tySequence,
tyProc,
tyPointer, tyOpenArray,
tyString, tyCString, tyForward,
tyNone, # 0
tyBool, # 1
tyChar, # 2
tyEmptySet, # 3
tyArrayConstr, # 4
tyNil, # 5
tyGeneric, # 6
tyGenericInst, # 7
tyGenericParam, # 8
tyEnum, # 9
tyAnyEnum, # 10
tyArray, # 11
tyObject, # 12
tyTuple, # 13
tySet, # 14
tyRange, # 15
tyPtr, # 16
tyRef, # 17
tyVar, # 18
tySequence, # 19
tyProc, # 20
tyPointer, # 21
tyOpenArray, # 22
tyString, # 23
tyCString, # 24
tyForward, # 25
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyFloat, tyFloat32, tyFloat64, tyFloat128
tyFloat, tyFloat32, tyFloat64, tyFloat128,
tyPureObject # 35: signals that object has no `n_type` field
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
TNimNode {.compilerproc.} = record
TNimNode {.compilerproc, final.} = object
kind: TNimNodeKind
offset: int
typ: ptr TNimType
@ -40,7 +49,7 @@ type # This should be he same as ast.TTypeKind
len: int
sons: ptr array [0..0x7fff, ptr TNimNode]
TNimType {.compilerproc.} = record
TNimType {.compilerproc, final.} = object
size: int
kind: TNimKind
base: ptr TNimType

View file

@ -10,8 +10,7 @@
# 64 bit integers for platforms that don't have those
type
IInt64 = record # "internal" int64
lo, hi: int32
IInt64 = tuple[lo, hi: int32]
proc cmpI64(x, y: IInt64): int32 {.compilerproc.} =
result = x.hi -% y.hi

View file

@ -1,75 +1,22 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# math routines
# interface
## Basic math routines for Nimrod.
## This module is available for the ECMAScript target.
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
{.push checks:off, line_dir:off, stack_trace:off.}
proc nextPowerOfTwo*(x: int): int
## returns the nearest power of two, so that
## result**2 >= x > (result-1)**2.
proc isPowerOfTwo*(x: int): bool {.noSideEffect.}
## returns true, if x is a power of two, false otherwise.
## Negative numbers are not a power of two.
proc countBits*(n: int32): int {.noSideEffect.}
## counts the set bits in `n`.
proc random*(max: int): int
## returns a random number in the range 0..max-1. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc randomize*()
## initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
## computes the square root of `x`.
proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
## computes ln(x).
proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
## computes e**x.
proc frexp*(x: float, exponent: var int): float {.
importc: "frexp", header: "<math.h>".}
## Split a number into mantissa and exponent.
## `frexp` calculates the mantissa m (a float greater than or equal to 0.5
## and less than 1) and the integer value n such that `x` (the original
## float value) equals m * 2**n. frexp stores n in `exponent` and returns
## m.
proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
## Calculate the arc tangent of `y` / `x`.
## `atan2` returns the arc tangent of `y` / `x`; it produces correct
## results even when the resulting angle is near pi/2 or -pi/2
## (`x` near 0).
proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
proc hypot*(x: float): float {.importc: "hypot", header: "<math.h>".}
proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
proc pow*(x, y: float): float {.importc: "pos", header: "<math.h>".}
## computes x to power raised of y.
when defined(Posix):
{.passl: "-lm".}
type
TFloatClass* = enum ## describes the class a floating point value belongs to.
@ -82,34 +29,11 @@ type
fcInf, ## value is positive infinity
fcNegInf ## value is negative infinity
proc classify*(x: float): TFloatClass
proc classify*(x: float): TFloatClass =
## classifies a floating point value. Returns `x`'s class as specified by
## `TFloatClass`
# implementation
include cntbits
proc nextPowerOfTwo(x: int): int =
result = x - 1
when defined(cpu64):
result = result or (result shr 32)
result = result or (result shr 16)
result = result or (result shr 8)
result = result or (result shr 4)
result = result or (result shr 2)
result = result or (result shr 1)
Inc(result)
# C procs:
proc gettime(dummy: ptr cint): cint {.
importc: "time", header: "<time.h>".}
proc srand(seed: cint) {.
importc: "srand", nodecl.}
proc rand(): cint {.importc: "rand", nodecl.}
# most C compilers have no classify:
proc classify(x: float): TFloatClass =
## `TFloatClass`.
# ECMAScript and most C compilers have no classify:
if x == 0.0:
if 1.0/x == 1.0/0.0:
return fcZero
@ -122,10 +46,130 @@ proc classify(x: float): TFloatClass =
return fcNormal
# XXX: fcSubnormal is not detected!
proc randomize() = srand(gettime(nil))
proc random(max: int): int = return rand() mod max
proc isPowerOfTwo(x: int): bool = return (x and -x) == x
proc isPowerOfTwo*(x: int): bool {.noSideEffect.} =
## returns true, if x is a power of two, false otherwise.
## Negative numbers are not a power of two.
return (x and -x) == x
proc nextPowerOfTwo*(x: int): int =
## returns the nearest power of two, so that
## result**2 >= x > (result-1)**2.
result = x - 1
when defined(cpu64):
result = result or (result shr 32)
result = result or (result shr 16)
result = result or (result shr 8)
result = result or (result shr 4)
result = result or (result shr 2)
result = result or (result shr 1)
Inc(result)
proc countBits*(n: int32): int {.noSideEffect.}
## counts the set bits in `n`.
include cntbits
when not defined(ECMAScript):
proc random*(max: int): int
## returns a random number in the range 0..max-1. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc randomize*()
## initializes the random number generator with a "random"
## number, i.e. a tickcount. Note: Does nothing for the ECMAScript target,
## as ECMAScript does not support this.
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
## computes the square root of `x`.
proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
## computes ln(x).
proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
proc log2*(x: float): float = return ln(x) / ln(2.0)
proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
## computes e**x.
proc frexp*(x: float, exponent: var int): float {.
importc: "frexp", header: "<math.h>".}
## Split a number into mantissa and exponent.
## `frexp` calculates the mantissa m (a float greater than or equal to 0.5
## and less than 1) and the integer value n such that `x` (the original
## float value) equals m * 2**n. frexp stores n in `exponent` and returns
## m.
proc round*(x: float): int {.importc: "lrint", nodecl.}
## converts a float to an int by rounding.
proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
## Calculate the arc tangent of `y` / `x`.
## `atan2` returns the arc tangent of `y` / `x`; it produces correct
## results even when the resulting angle is near pi/2 or -pi/2
## (`x` near 0).
proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
proc hypot*(x, y: float): float {.importc: "hypot", header: "<math.h>".}
## same as ``sqrt(x*x + y*y)``.
proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
proc pow*(x, y: float): float {.importc: "pow", header: "<math.h>".}
## computes x to power raised of y.
# C procs:
proc gettime(dummy: ptr cint): cint {.importc: "time", header: "<time.h>".}
proc srand(seed: cint) {.importc: "srand", nodecl.}
proc rand(): cint {.importc: "rand", nodecl.}
proc randomize() = srand(gettime(nil))
proc random(max: int): int = return rand() mod max
else:
proc mathrandom(): float {.importc: "Math.random", nodecl.}
proc mathfloor(x: float): float {.importc: "Math.floor", nodecl.}
proc random*(max: int): int = return mathfloor(mathrandom() * max)
proc randomize*() = nil
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
proc ln*(x: float): float {.importc: "Math.log", nodecl.}
proc log10*(x: float): float = return ln(x) / ln(10.0)
proc log2*(x: float): float = return ln(x) / ln(2.0)
proc exp*(x: float): float {.importc: "Math.exp", nodecl.}
proc round*(x: float): int {.importc: "Math.round", nodecl.}
proc pow*(x, y: float): float {.importc: "Math.pow", nodecl.}
proc frexp*(x: float, exponent: var int): float =
if x == 0.0:
exponent = 0.0
result = 0.0
elif x < 0.0:
result = -frexp(-x, exponent)
else:
var ex = mathfloor(log2(x))
exponent = round(ex)
result = x / pow(2.0, ex)
proc arccos*(x: float): float {.importc: "Math.acos", nodecl.}
proc arcsin*(x: float): float {.importc: "Math.asin", nodecl.}
proc arctan*(x: float): float {.importc: "Math.atan", nodecl.}
proc arctan2*(y, x: float): float {.importc: "Math.atan2", nodecl.}
proc cos*(x: float): float {.importc: "Math.cos", nodecl.}
proc cosh*(x: float): float = return (exp(x)+exp(-x))*0.5
proc hypot*(x, y: float): float = return sqrt(x*x + y*y)
proc sinh*(x: float): float = return (exp(x)-exp(-x))*0.5
proc tan*(x: float): float {.importc: "Math.tan", nodecl.}
proc tanh*(x: float): float =
var y = exp(2.0*x)
return (y-1.0)/(y+1.0)
{.pop.}
{.pop.}

View file

@ -37,24 +37,24 @@ const
realFli = MaxFli - fliOffset
type
TFreePtr = record
TFreePtr {.final.} = object
prev, next: PBhdr
Pbhdr = ptr Tbhdr
Tbhdr = record
Tbhdr {.final.} = object
prevHdr: Pbhdr # this is just valid if the first bit of size is set
size: int # the size is stored in bytes
# bit 0 indicates whether the block is used and
# bit 1 allows to know whether the previous block is free
freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the
# C version)
TAreaInfo = record # This structure is embedded at the beginning of each
# area, giving us enough information to cope with a set
# of areas
TAreaInfo {.final.} = object # This structure is embedded at the beginning
# of each area, giving us enough information
# to cope with a set of areas
theEnd: Pbhdr
next: PAreaInfo
PAreaInfo = ptr TAreaInfo
TLSF = record
TLSF {.final.} = object
tlsf_signature: int32 # the TLSF's structure signature
usedSize, maxSize: int
areaHead: PAreaInfo # A linked list holding all the existing areas
@ -147,6 +147,7 @@ elif defined(windows):
if result == nil: raiseOutOfMem()
else:
{.warning: "Generic code for allocating pages is used".}
# generic implementation relying on malloc:
proc malloc(size: int): pointer {.nodecl, importc.}
@ -155,6 +156,124 @@ else:
result = malloc(size)
if result == nil: raiseOutOfMem()
# ---------------------------------------------------------------------------
# small fixed size allocator:
# Design: We manage pages. A page is of constant size, but not necessarily
# the OS's page size. Pages are managed in a hash table taking advantage of
# the fact that the OS is likely to give us pages with contingous numbers.
# A page contains either small fixed size objects of the same size or
# variable length objects. An object's size is always aligned at 16 byte
# boundry. Huge objects are dealt with the TLSF algorithm.
# The design supports iterating over any object in a fast way.
# A bitset contains any page that starts an allocated page. The page may be
# empty however. This bitset can be used to quickly determine if a given
# page belongs to the GC heap. The design of the memory allocator makes it
# simple to return unused pages back to the OS.
# Small bocks
# -----------
#
# If we use a list in the free object's space. Allocation and deallocation are
# O(1). Since any object is of the same size, iteration is quite efficient too.
# However, pointer detection is easy too: Just check if the type-field is nil.
# Deallocation sets it to nil.
# Algorithm:
# i = 0
# f = b.f # first free address
# while i < max:
# if a[i] == f: # not a valid block
# f = f.next # next free address
# else:
# a[i] is a valid object of size s
# inc(i)
# The zero count table is an array. Since we know that the RC is zero, we can
# use the bits for an index into this array. Thus multiple ZCT tables are not
# difficult to support and insertion and removal is O(1). We use negative
# indexes for this. This makes it even fast enough (and necessary!) to do a ZCT
# removal if the RC is incremented.
#
# Huge blocks
# -----------
#
# Huge blocks are always rounded up to a multiple of the page size. These are
# called *strides*. We also need to keep an index structure
# of (stridesize, pagelist).
#
const
MemAlign = 8
PageShift = if sizeof(int) == 4: 12 else: 13
PageSize = 1 shl PageShift
type
TFreeList {.final.} = object
next, prev: ptr TFreeList
TPageDesc {.final.} = object # the start of a stride always starts with this!
size: int # lowest bit is set, if it is a huge block
free: ptr TFreeList # only used if it manages multiple cells
snext, sprev: ptr TPageDesc # next and prev pagedescs with the same size
TCellArray {.final.} = object
i: int # length
d: ptr array [0..1000_000, TCell]
TPageManager = table[page, ptr TPageDesc]
TGcHeap {.final.} = object
# structure that manages the garbage collected heap
zct: TCellArray
stackCells: TCellArray
smallBlocks: array [PageSize div MemAlign, ptr TPageDesc]
pages: TPageManager
usedPages: TPageList
freePages: TPageList
# small blocks:
proc allocSmall(var h: TGcHeap, size: int): pointer =
var s = align(size)
var p = h.smallBlocks[s]
if p == nil or p.free == nil:
p = newSmallBlock(s, p)
h.smallBlocks[s] = p
proc decRef(cell: PCell) {.inline.} =
assert(cell in ct.AT)
assert(cell.refcount > 0) # this should be the case!
assert(seqCheck(cell))
dec(cell.refcount)
if cell.refcount == 0:
# add to zero count table:
zct.d[zct.i] = cell
cell.recfcount = -zct.i
inc(zct.i)
proc incRef(cell: PCell) {.inline.} =
assert(seqCheck(cell))
if cell.refcount < 0:
# remove from zero count table:
zct.d[-cell.refcount] = zct.d[zct.i-1]
dec(zct.i)
cell.refcount = 1
else:
inc(cell.refcount)
proc asgnRef(dest: ppointer, src: pointer) =
# the code generator calls this proc!
assert(not isOnStack(dest))
# BUGFIX: first incRef then decRef!
if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
# ----------------------------------------------------------------------------
# helpers
@ -261,7 +380,7 @@ proc extractBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
proc insertBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
b.freePtr.prev = nil
b.freePtr.next = t.matrix[fl][sl]
if t.matrix[fl][sl] != 0:
if t.matrix[fl][sl] != nil:
t.matrix[fl][sl].freePtr.prev = b
t.matrix[fl][sl] = b
set_bit(sl, t.slBitmap[fl])
@ -295,9 +414,6 @@ proc processArea(area: pointer, size: int): Pbhdr =
# ----------------------------------------------------------------------------
# Begin of the allocator code
var
mp: pointer # default memory pool.
proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
var
t: PLSF
@ -307,16 +423,14 @@ proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
writeToStdErr("initMemoryPool(): memory_pool invalid\n")
return -1
if (memPool and ptrMask) != 0:
if (cast[TAddress](memPool) and ptrMask) != 0:
writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n")
return -1
t = cast[PLSF](memPool)
# Check if already initialised
if t.signature == tlsfSignature:
mp = memPool
b = getNextBlock(mp, roundupSize(sizeof(TLSF)))
b = getNextBlock(memPool, roundupSize(sizeof(TLSF)))
return b.size and blockSize
mp = memPool
zeroMem(memPool, sizeof(TLSF))
t.signature = tlsfSignature
@ -456,7 +570,7 @@ proc freeEx(p: pointer, t: var TLSF) =
b.freePtr.prev = nil
b.freePtr.next = nil
tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
if tmpB.size and freeBlock != 0:
if (tmpB.size and freeBlock) != 0:
mappingInsert(tmpB.size and blockSize, fl, sl)
extractBlock(tmpB, t, fl, sl)
inc(b.size, (tmpB.size and blockSize) + bhdrOverhead)
@ -549,51 +663,30 @@ proc ansiCrealloc(p: pointer, newSize: int, t: var TLSF): pointer =
else:
result = reallocEx(p, newSize, t)
proc InitTLSF(t: var TLSF) =
var areaSize = sizeof(TLSF) + BHDR_OVERHEAD * 8 # Just a safety constant
areaSize = max(areaSize, DEFAULT_areaSize)
var area = getNewArea(areaSize)
initMemoryPool(areaSize, area)
void *tlsf_malloc(size_t size)
{
void *ret
var
t: PLSF
b, ib: Pbhdr
#if USE_MMAP || USE_SBRK
if (!mp) {
size_t areaSize
void *area
t = cast[PLSF](memPool)
zeroMem(area, areaSize)
areaSize = sizeof(tlsf_t) + BHDR_OVERHEAD * 8 # Just a safety constant
areaSize = (areaSize > DEFAULT_areaSize) ? areaSize : DEFAULT_areaSize
area = get_new_area(&areaSize)
if (area == ((void *) ~0))
return NULL # Not enough system memory
initMemoryPool(areaSize, area)
}
#endif
t.signature = tlsfSignature
var ib = processArea(getNextBlock(memPool, roundupSize(sizeof(TLSF))),
rounddownSize(memPoolSize - sizeof(TLSF)))
var b = getNextBlock(getBuffer(ib), ib.size and blockSize)
freeEx(getBuffer(b), t)
t.areaHead = cast[PAreaInfo](getBuffer(ib))
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
t.used_size = memPoolSize - (b.size and blockSize)
t.max_size = t.used_size
ret = malloc_ex(size, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
return ret
}
void tlsf_free(void *p)
{
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
free_ex(p, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
}
void *tlsf_realloc(void *p, size_t size)
{
void *ret
#if USE_MMAP || USE_SBRK
if (!mp) {
return tlsf_malloc(size)
}
#endif
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
ret = realloc_ex(p, size, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
return ret
}
# XXX

View file

@ -1,7 +1,7 @@
/*
Nimrod's Runtime Library
(c) Copyright 2006 Andreas Rumpf
(c) Copyright 2008 Andreas Rumpf
See the file "copying.txt", included in this
distribution, for details about the copyright.
@ -11,7 +11,8 @@
#define NIMBASE_H
/* calling convention mess ----------------------------------------------- */
#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__)
#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \
|| defined(__TINYC__)
/* these should support C99's inline */
/* the test for __POCC__ has to come before the test for _MSC_VER,
because PellesC defines _MSC_VER too. This is brain-dead. */
@ -30,10 +31,18 @@
# define N_INLINE(rettype, name) rettype __inline name
#endif
#if defined(_MSC_VER)
#if defined(__POCC__) || defined(_MSC_VER)
# define HAVE_LRINT 1
#endif
#if defined(__POCC__)
# define NIM_CONST /* PCC is really picky with const modifiers */
#elif defined(__cplusplus)
# define NIM_CONST /* C++ is picky with const modifiers */
#else
# define NIM_CONST const
#endif
/* --------------- how int64 constants should be declared: ----------- */
#if defined(__GNUC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__DMC__)
@ -136,8 +145,7 @@
** long int lrint (double x);
*/
#if defined(__LCC__) || defined(__POCC__) \
|| (defined(__GNUC__) && defined(WIN32))
#if defined(__LCC__) || (defined(__GNUC__) && defined(WIN32))
/* Linux' GCC does not seem to have these. Why? */
# define HAVE_LRINT
# define HAVE_LRINTF
@ -159,7 +167,7 @@
# include <math.h>
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
&& !defined(__BORLANDC__)
&& !defined(__BORLANDC__) && !defined(__POCC__)
# include <math.h>
@ -206,6 +214,17 @@ static N_INLINE(long int, lrintf)(float flt) {
#include <signal.h>
#include <setjmp.h>
#ifndef NAN
static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
# define NAN (*(double*) nimNaN)
#endif
/*
#ifndef INF
static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
# define INF (*(double*) nimInf)
#endif */
/* compiler symbols:
__BORLANDC__
_MSC_VER
@ -214,6 +233,7 @@ __LCC__
__GNUC__
__DMC__
__POCC__
__TINYC__
*/
/* C99 compiler? */
@ -250,50 +270,41 @@ __POCC__
#endif
#define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
the generated code does not rely on it anymore */
the generated code does not rely on it anymore */
#if defined(HAVE_STDINT_H)
# include <stdint.h>
typedef int8_t NS8;
typedef int16_t NS16;
typedef int32_t NS32;
typedef int64_t NS64;
typedef int8_t NI8;
typedef int16_t NI16;
typedef int32_t NI32;
typedef int64_t NI64;
typedef uint64_t NU64;
typedef uint8_t NU8;
typedef uint16_t NU16;
typedef uint32_t NU32;
#elif defined(__BORLANDC__) || defined(__DMC__) \
|| defined(__WATCOMC__) || defined(_MSC_VER)
typedef signed char NS8;
typedef signed short int NS16;
typedef signed int NS32;
typedef signed char NI8;
typedef signed short int NI16;
typedef signed int NI32;
/* XXX: Float128? */
typedef unsigned char NU8;
typedef unsigned short int NU16;
typedef unsigned __int64 NU64;
typedef __int64 NS64;
typedef __int64 NI64;
typedef unsigned int NU32;
#else
typedef signed char NS8;
typedef signed short int NS16;
typedef signed int NS32;
typedef signed char NI8;
typedef signed short int NI16;
typedef signed int NI32;
/* XXX: Float128? */
typedef unsigned char NU8;
typedef unsigned short int NU16;
typedef unsigned long long int NU64;
typedef long long int NS64;
typedef long long int NI64;
typedef unsigned int NU32;
#endif
#if defined(_MSC_VER) && (defined(AMD64) || defined(_M_AMD64))
/* Microsoft C is brain-dead in this case; long is still not an int64 */
typedef unsigned long long int NU;
typedef signed long long int NS;
#else
typedef unsigned long int NU; /* note: int would be wrong for AMD64 */
typedef signed long int NS;
#endif
typedef float NF32;
typedef double NF64;
typedef double NF;
@ -307,13 +318,13 @@ typedef char* NCSTRING;
# define NIM_IMAN 0
#endif
static N_INLINE(NS32, float64ToInt32)(double val) {
static N_INLINE(NI32, float64ToInt32)(double val) {
val = val + 68719476736.0*1.5;
/* 2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor */
return ((NS32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */
return ((NI32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */
}
static N_INLINE(NS32, float32ToInt32)(float val) {
static N_INLINE(NI32, float32ToInt32)(float val) {
return float64ToInt32((double)val);
}
@ -322,7 +333,7 @@ static N_INLINE(NS32, float32ToInt32)(float val) {
#define STRING_LITERAL(name, str, length) \
static const struct { \
NS len, space; \
NI len, space; \
NIM_CHAR data[length + 1]; \
} name = {length, length, str}
@ -357,7 +368,7 @@ typedef struct TStringDesc* string;
/*
typedef struct TSafePoint TSafePoint;
struct TSafePoint {
NS exc;
NI exc;
NCSTRING excname;
NCSTRING msg;
TSafePoint* prev;
@ -368,19 +379,19 @@ typedef struct TFrame TFrame;
struct TFrame {
TFrame* prev;
NCSTRING procname;
NS line;
NI line;
NCSTRING filename;
NS len;
NI len;
};
extern TFrame* volatile framePtr;
/*extern TSafePoint* volatile excHandler; */
extern TFrame* framePtr;
/*extern TSafePoint* excHandler; */
#if defined(__cplusplus)
struct NimException {
TSafePoint sp;
NimException(NS aExc, NCSTRING aExcname, NCSTRING aMsg) {
NimException(NI aExc, NCSTRING aExcname, NCSTRING aMsg) {
sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg;
sp.prev = excHandler;
excHandler = &sp;
@ -389,13 +400,13 @@ struct NimException {
#endif
typedef struct TStringDesc {
NS len;
NS space;
NI len;
NI space;
NIM_CHAR data[1]; /* SEQ_DECL_SIZE]; */
} TStringDesc;
typedef struct {
NS len, space;
NI len, space;
} TGenericSeq;
typedef TGenericSeq* PGenericSeq;

View file

@ -1,39 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module provides a command line parser.
## It supports one iterator over all command line options.
#interface
{.push debugger: off.}
import
os
proc findSep(s: string): int {.nostatic.} =
for i in 0 .. high(s)-1:
if s[i] in {'=', ':'}: return i
return high(s)+1
iterator getopt*(): tuple[string, string] =
# returns a (cmd, arg) tuple.
for k in 1 .. ParamCount():
var param = paramStr(k)
if param[0] == '-':
var j = findSep(param)
cmd = copy(param, 0, j-1)
arg = copy(param, j+1)
else:
cmd = ""
arg = param
yield cmd, arg
{.pop.}

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@ -10,7 +10,9 @@
## Basic operating system facilities like retrieving environment variables,
## reading command line arguments, working with directories, running shell
## commands, etc. This module is -- like any other basic library --
## platform independant.
## platform independant. However, the ECMAScript target is not supported,
## as there is no way to perform these operations in ECMAScript portably
## or at all.
{.push debugger:off.}
@ -18,7 +20,7 @@ import
strutils, times
# copied from excpt.nim, because I don't want to make this template public
template newException(exceptn, message: expr): expr =
template newException(exceptn, message: expr): expr =
block: # open a new scope
var
e: ref exceptn
@ -294,7 +296,7 @@ proc existsDir*(dir: string): bool
proc getLastModificationTime*(file: string): TTime
## Gets the time of the `file`'s last modification.
proc fileNewer*(a, b: string): bool
proc fileNewer*(a, b: string): bool
## returns true if the file `a` is newer than file `b`, i.e. if `a`'s
## modification time is later than `b`'s.
@ -371,8 +373,11 @@ proc UnixToNativePath(path: string): string =
# interface to C library:
const
cunder = if defined(pcc): "_" else: ""
type
TStat {.importc: "struct stat".} = record
TStat {.importc: "struct " & cunder & "stat", final.} = object
st_dev: int16
st_ino: int16
st_mode: int16
@ -397,7 +402,8 @@ else:
{.error: "os library not ported to your OS. Please help!".}
proc chdir(path: CString): cint {.importc: "chdir", header: dirHeader.}
proc chdir(path: CString): cint {.
importc: cunder & "chdir", header: dirHeader.}
when defined(unix):
proc mkdir(dir: CString, theAccess: cint): cint {.
@ -412,7 +418,7 @@ elif defined(windows):
proc fullpath(buffer, file: CString, size: int): CString {.
importc: "_fullpath", header: "<stdlib.h>".}
proc getcwd(buf: CString, buflen: cint): CString {.
importc: "getcwd", header: "<direct.h>".}
importc: cunder & "getcwd", header: "<direct.h>".}
proc CreateDirectory(pathName: cstring, security: Pointer): cint {.
importc: "CreateDirectory", header: "<windows.h>".}
@ -421,7 +427,8 @@ else:
{.error: "os library not ported to your OS. Please help!".}
proc rmdir(dir: CString): cint {.importc: "rmdir", header: "<time.h>".}
proc rmdir(dir: CString): cint {.
importc: cunder & "rmdir", header: "<time.h>".}
# rmdir is of course in ``dirHeader``, but we check here to include
# time.h which is needed for stat(). stat() needs time.h and
# sys/stat.h; we workaround a C library issue here.
@ -432,17 +439,7 @@ proc free(c: cstring) {.importc: "free", nodecl.}
proc strlen(str: CString): int {.importc: "strlen", nodecl.}
proc stat(f: CString, res: var TStat): cint {.
importc: "stat", header: "<sys/stat.h>".}
proc sameFile*(path1, path2: string): bool =
## Returns True if both pathname arguments refer to the same file or
## directory (as indicated by device number and i-node number).
## Raises an exception if an os.stat() call on either pathname fails.
var
a, b: TStat
if stat(path1, a) < 0 or stat(path2, b) < 0:
raise newException(EOS, "stat() call failed")
return int(a.st_dev) == b.st_dev and int(a.st_ino) == b.st_ino
importc: cunder & "stat", header: "<sys/stat.h>".}
when defined(windows):
proc getModuleFilename(handle: int32, buf: CString, size: int32): int32 {.
@ -456,13 +453,13 @@ proc getLastModificationTime(file: string): TTime =
proc setCurrentDir(newDir: string) =
if chdir(newDir) != 0:
raise newException(EOS, "cannot change the working directory to '$1'" %
raise newException(EOS, "cannot change the working directory to '$1'" %
newDir)
when defined(linux) or defined(solaris) or defined(bsd):
proc readlink(link, buf: cstring, size: int): int {.
header: "<unistd.h>", cdecl.}
proc getApplAux(procPath: string): string =
result = newString(256)
var len = readlink(procPath, result, 256)
@ -473,6 +470,13 @@ when defined(linux) or defined(solaris) or defined(bsd):
when defined(solaris) or defined(bsd):
proc getpid(): int {.importc, header: "<unistd.h>", cdecl.}
elif defined(macosx):
# a really hacky solution: since we like to include 2 headers we have to
# define two procs which in reality are the same
proc getExecPath1(c: cstring, size: var int32) {.
importc: "_NSGetExecutablePath", header: "<sys/param.h>".}
proc getExecPath2(c: cstring, size: var int32): bool {.
importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".}
proc getApplicationFilename(): string =
# Linux: /proc/<pid>/exe
@ -491,6 +495,12 @@ proc getApplicationFilename(): string =
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
elif defined(bsd):
result = getApplAux("/proc/" & $getpid() & "file")
elif defined(macosx):
var size: int32
getExecPath1(nil, size)
result = newString(int(size))
if getExecPath2(result, size):
result = "" # error!
else:
# little heuristic that may work on other POSIX-like systems:
result = getEnv("_")
@ -612,7 +622,7 @@ when defined(wcc):
proc cputenv(env: CString): cint {.importc: "putenv", header: "<process.h>".}
else: # is in <stdlib.h>
proc cputenv(env: CString): cint {.importc: "putenv", noDecl.}
proc cputenv(env: CString): cint {.importc: cunder & "putenv", noDecl.}
proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
@ -621,7 +631,7 @@ proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
#int _findclose(long);
when defined(windows):
type
TFindData {.importc: "struct _finddata_t".} = record
TFindData {.importc: "struct _finddata_t", final.} = object
attrib {.importc: "attrib".}: cint
time_create {.importc: "time_create".}: cint
time_access {.importc: "time_access".}: cint
@ -636,7 +646,7 @@ when defined(windows):
proc findclose(handle: cint) {.importc: "_findclose", header: "<io.h>".}
else:
type
TFindData {.importc: "glob_t".} = record
TFindData {.importc: "glob_t", final.} = object
gl_pathc: int # count of paths matched by pattern
gl_pathv: ptr array[0..1000_000, CString] # list of matched path names
gl_offs: int # slots to reserve at beginning of gl_pathv
@ -649,6 +659,30 @@ else:
proc globfree(pglob: PFindData) {.
importc: "globfree", header: "<glob.h>".}
proc sameFile*(path1, path2: string): bool =
## Returns True if both pathname arguments refer to the same file or
## directory (as indicated by device number and i-node number).
## Raises an exception if an os.stat() call on either pathname fails.
when defined(Windows):
var
a, b: TFindData
var resA = findfirst(path1, addr(a))
var resB = findfirst(path2, addr(b))
if resA != -1 and resB != -1:
result = $a.name == $b.name
else:
# work around some ``findfirst`` bugs
result = cmpPaths(path1, path2) == 0
if resA != -1: findclose(resA)
if resB != -1: findclose(resB)
else:
var
a, b: TStat
if stat(path1, a) < 0 or stat(path2, b) < 0:
result = cmpPaths(path1, path2) == 0 # be consistent with Windows
else:
result = int(a.st_dev) == b.st_dev and int(a.st_ino) == b.st_ino
proc cremove(filename: CString): cint {.importc: "remove", noDecl.}
proc crename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
@ -776,9 +810,9 @@ proc findEnvVar(key: string): int =
proc getEnv(key: string): string =
var i = findEnvVar(key)
if i >= 0:
if i >= 0:
return copy(environment[i], findSubStr("=", environment[i])+1)
else:
else:
var env = cgetenv(key)
if env == nil: return ""
result = $env
@ -787,7 +821,7 @@ proc existsEnv(key: string): bool =
if cgetenv(key) != nil: return true
else: return findEnvVar(key) >= 0
iterator iterOverEnvironment*(): tuple[string, string] =
iterator iterOverEnvironment*(): tuple[key, value: string] =
## Iterate over all environments varialbes. In the first component of the
## tuple is the name of the current variable stored, in the second its value.
getEnvVarsC()
@ -798,7 +832,7 @@ iterator iterOverEnvironment*(): tuple[string, string] =
proc putEnv(key, val: string) =
# Note: by storing the string in the environment sequence,
# we gurantee that we don't free the memory before the program
# ends (this is needed for POSIX compliance). It is also needed so that
# ends (this is needed for POSIX compliance). It is also needed so that
# the process itself may access its modified environment variables!
var indx = findEnvVar(key)
if indx >= 0:

View file

@ -14,7 +14,7 @@
## This is a raw POSIX interface module. It does not not provide any
## convenience: cstrings are used instead of proper Nimrod strings and
## return codes indicate errors. If you want exceptions
## and a proper Nimrod-like interface, use the OS module.
## and a proper Nimrod-like interface, use the OS module or write a wrapper.
## Coding conventions:
## ALL types are named the same as in the POSIX standard except that they start
@ -60,7 +60,7 @@ const
STDOUT_FILENO = 1 ## File number of stdout;
type
Taiocb* {.importc: "struct aiocb", header: "<aio.h>".} = record
Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final.} = object
aio_fildes*: cint ## File descriptor.
aio_offset*: TOff ## File offset.
aio_buf*: pointer ## Location of buffer.
@ -69,14 +69,14 @@ type
aio_sigevent*: TSigEvent ## Signal number and value.
aio_lio_opcode: cint ## Operation to be performed.
TDIR* {.importc: "DIR", header: "<dirent.h>".} = record
TDIR* {.importc: "DIR", header: "<dirent.h>", final.} = object
## A type representing a directory stream.
Tdirent* {.importc: "struct dirent", header: "<dirent.h>".} = record
Tdirent* {.importc: "struct dirent", header: "<dirent.h>", final.} = object
d_ino*: TIno ## File serial number.
d_name*: array [0..255, char] ## Name of entry.
Tflock* {.importc: "flock", header: "<fcntl>".} = record
Tflock* {.importc: "flock", header: "<fcntl>", final.} = object
l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
l_whence*: cshort ## Flag for starting offset.
l_start*: Toff ## Relative offset in bytes.
@ -84,13 +84,13 @@ type
l_pid*: TPid ## Process ID of the process holding the lock;
## returned with F_GETLK.
Tfenv* {.importc: "fenv_t", header: "<fenv.h>".} =
record ## Represents the entire floating-point environment. The
Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final.} =
object ## Represents the entire floating-point environment. The
## floating-point environment refers collectively to any
## floating-point status flags and control modes supported
## by the implementation.
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>".} =
record ## Represents the floating-point status flags collectively,
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final.} =
object ## Represents the floating-point status flags collectively,
## including any status the implementation associates with the
## flags. A floating-point status flag is a system variable
## whose value is set (but never cleared) when a floating-point
@ -100,25 +100,25 @@ type
## whose value may be set by the user to affect the subsequent
## behavior of floating-point arithmetic.
TFTW* {.importc: "struct FTW", header: "<ftw.h>".} = record
TFTW* {.importc: "struct FTW", header: "<ftw.h>", final.} = object
base*: cint
level*: cint
TGlob* {.importc: "glob_t", header: "<glob.h>".} = record
TGlob* {.importc: "glob_t", header: "<glob.h>", final.} = object
gl_pathc*: int ## Count of paths matched by pattern.
gl_pathv*: ptr cstring ## Pointer to a list of matched pathnames.
gl_offs*: int ## Slots to reserve at the beginning of gl_pathv.
TGroup* {.importc: "struct group", header: "<grp.h>".} = record
TGroup* {.importc: "struct group", header: "<grp.h>", final.} = object
gr_name*: cstring ## The name of the group.
gr_gid*: TGid ## Numerical group ID.
gr_mem*: cstringArray ## Pointer to a null-terminated array of character
## pointers to member names.
Ticonv* {.importc: "iconv_t", header: "<iconv.h>".} =
record ## Identifies the conversion from one codeset to another.
Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final.} =
object ## Identifies the conversion from one codeset to another.
Tlconv* {.importc: "struct lconv", header: "<locale.h>".} = record
Tlconv* {.importc: "struct lconv", header: "<locale.h>", final.} = object
currency_symbol*: cstring
decimal_point*: cstring
frac_digits*: char
@ -144,14 +144,14 @@ type
p_sign_posn*: char
thousands_sep*: cstring
TMqd* {.importc: "mqd_t", header: "<mqueue.h>".} = record
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>".} = record
TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final.} = object
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final.} = object
mq_flags*: int ## Message queue flags.
mq_maxmsg*: int ## Maximum number of messages.
mq_msgsize*: int ## Maximum message size.
mq_curmsgs*: int ## Number of messages currently queued.
TPasswd* {.importc: "struct passwd", header: "<pwd.h>".} = record
TPasswd* {.importc: "struct passwd", header: "<pwd.h>", final.} = object
pw_name*: cstring ## User's login name.
pw_uid*: TUid ## Numerical user ID.
pw_gid*: TGid ## Numerical group ID.
@ -198,7 +198,7 @@ type
Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int
Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
Tutsname* {.importc: "struct utsname", header: "<sys/utsname.h>".} = record
Tutsname* {.importc: "struct utsname", header: "<sys/utsname.h>", final.} = object
sysname*, ## Name of this implementation of the operating system.
nodename*, ## Name of this node within the communications
## network to which this node is attached, if any.
@ -207,15 +207,15 @@ type
machine*: array [0..255, char] ## Name of the hardware type on which the
## system is running.
TSem* {.importc: "sem_t", header: "<semaphore.h>".} = record
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>".} = record
TSem* {.importc: "sem_t", header: "<semaphore.h>", final.} = object
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final.} = object
uid*: tuid ## Owner's user ID.
gid*: tgid ## Owner's group ID.
cuid*: Tuid ## Creator's user ID.
cgid*: Tgid ## Creator's group ID.
mode*: TMode ## Read/write permission.
TStat* {.importc: "struct stat", header: "<sys/stat.h>".} = record
TStat* {.importc: "struct stat", header: "<sys/stat.h>", final.} = object
st_dev*: TDev ## Device ID of device containing file.
st_ino*: TIno ## File serial number.
st_mode*: TMode ## Mode of file (see below).
@ -239,7 +239,7 @@ type
st_blocks*: Tblkcnt ## Number of blocks allocated for this object.
TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>".} = record
TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", final.} = object
f_bsize*: int ## File system block size.
f_frsize*: int ## Fundamental file system block size.
f_blocks*: Tfsblkcnt ## Total number of blocks on file system in units of f_frsize.
@ -255,10 +255,10 @@ type
f_namemax*: int ## Maximum filename length.
Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info",
header: "<sys/mman.h>".} = record
header: "<sys/mman.h>", final.} = object
posix_tmi_length*: int
Ttm* {.importc: "struct tm", header: "<time.h>".} = record
Ttm* {.importc: "struct tm", header: "<time.h>", final.} = object
tm_sec*: cint ## Seconds [0,60].
tm_min*: cint ## Minutes [0,59].
tm_hour*: cint ## Hour [0,23].
@ -268,10 +268,10 @@ type
tm_wday*: cint ## Day of week [0,6] (Sunday =0).
tm_yday*: cint ## Day of year [0,365].
tm_isdst*: cint ## Daylight Savings flag.
Ttimespec* {.importc: "struct timespec", header: "<time.h>".} = record
Ttimespec* {.importc: "struct timespec", header: "<time.h>", final.} = object
tv_sec*: Ttime ## Seconds.
tv_nsec*: int ## Nanoseconds.
titimerspec* {.importc: "struct itimerspec", header: "<time.h>".} = record
titimerspec* {.importc: "struct itimerspec", header: "<time.h>", final.} = object
it_interval*: ttimespec ## Timer period.
it_value*: ttimespec ## Timer expiration.
@ -279,19 +279,19 @@ type
## Possibly volatile-qualified integer type of an object that can be
## accessed as an atomic entity, even in the presence of asynchronous
## interrupts.
Tsigset* {.importc: "sigset_t", header: "<signal.h>".} = record
Tsigset* {.importc: "sigset_t", header: "<signal.h>", final.} = object
TsigEvent* {.importc: "struct sigevent", header: "<signal.h>".} = record
TsigEvent* {.importc: "struct sigevent", header: "<signal.h>", final.} = object
sigev_notify*: cint ## Notification type.
sigev_signo*: cint ## Signal number.
sigev_value*: Tsigval ## Signal value.
sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function.
sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes.
TsigVal* {.importc: "union sigval", header: "<signal.h>".} = record
TsigVal* {.importc: "union sigval", header: "<signal.h>", final.} = object
sival_ptr*: pointer ## pointer signal value;
## integer signal value not defined!
TSigaction* {.importc: "struct sigaction", header: "<signal.h>".} = record
TSigaction* {.importc: "struct sigaction", header: "<signal.h>", final.} = object
sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching
## function or one of the macros
## SIG_IGN or SIG_DFL.
@ -300,16 +300,16 @@ type
sa_flags*: cint ## Special flags.
sa_sigaction*: proc (x: cint, y: var TSigInfo, z: pointer) {.noconv.}
TStack* {.importc: "stack_t", header: "<signal.h>".} = record
TStack* {.importc: "stack_t", header: "<signal.h>", final.} = object
ss_sp*: pointer ## Stack base or pointer.
ss_size*: int ## Stack size.
ss_flags*: cint ## Flags.
TSigStack* {.importc: "struct sigstack", header: "<signal.h>".} = record
TSigStack* {.importc: "struct sigstack", header: "<signal.h>", final.} = object
ss_onstack*: cint ## Non-zero when signal stack is in use.
ss_sp*: pointer ## Signal stack pointer.
TsigInfo* {.importc: "siginfo_t", header: "<signal.h>".} = record
TsigInfo* {.importc: "siginfo_t", header: "<signal.h>", final.} = object
si_signo*: cint ## Signal number.
si_code*: cint ## Signal code.
si_errno*: cint ## If non-zero, an errno value associated with
@ -324,7 +324,7 @@ type
Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint
Tsched_param* {.importc: "struct sched_param", header: "<sched.h>".} = record
Tsched_param* {.importc: "struct sched_param", header: "<sched.h>", final.} = object
sched_priority*: cint
sched_ss_low_priority*: cint ## Low scheduling priority for
## sporadic server.
@ -334,15 +334,15 @@ type
sched_ss_max_repl*: cint ## Maximum pending replenishments for
## sporadic server.
Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>".} = record
Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", final.} = object
tv_sec*: ttime ## Seconds.
tv_usec*: tsuseconds ## Microseconds.
Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>".} = record
Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", final.} = object
Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>".} = cint
Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>".} = cint
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>".} = record
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>".} = record
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final.} = object
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final.} = object
uc_link*: ptr Tucontext ## Pointer to the context that is resumed
## when this context returns.
uc_sigmask*: Tsigset ## The set of signals that are blocked when this
@ -729,7 +729,7 @@ var
GLOB_NOSORT* {.importc, header: "<glob.h>".}: cint
## Do not sort the pathnames returned.
GLOB_ABORTED* {.importc, header: "<glob.h>".}: cint
## The scan was stopped because GLOB_ERR was set or (*errfunc)()
## The scan was stopped because GLOB_ERR was set or errfunc()
## returned non-zero.
GLOB_NOMATCH* {.importc, header: "<glob.h>".}: cint
## The pattern does not match any existing pathname, and GLOB_NOCHECK

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.

View file

@ -18,7 +18,7 @@ type
PPointer = ptr pointer
TCollectorData = int
TCell = record
TCell {.final.} = object
refcount: TCollectorData # the refcount and bit flags
typ: PNimType
stackcount: int # stack counter for debugging
@ -67,18 +67,18 @@ type
TBitIndex = range[0..UnitsPerPage-1]
TPageDesc = record
TPageDesc {.final.} = object
next: PPageDesc # all nodes are connected with this pointer
key: TAddress # start address at bit 0
bits: array[TBitIndex, int] # a bit vector
PPageDescArray = ptr array[0..1000_000, PPageDesc]
TCellSet = record
TCellSet {.final.} = object
counter, max: int
head: PPageDesc
data: PPageDescArray
TSetNode = record
TSetNode {.final.} = object
n: array[0.. (1 shl bitsPerNode)-1, PSetNode]
PSetNode = ptr TSetNode

View file

@ -1,233 +1,247 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# The generic ``repr`` procedure. It is an invaluable debugging tool.
#proc cstrToNimStrDummy(s: cstring): string {.inline.} =
# result = cast[string](cstrToNimStr(s))
proc reprInt(x: int64): string {.compilerproc.} = return $x
proc reprFloat(x: float): string {.compilerproc.} = return $x
proc reprPointer(x: pointer): string {.compilerproc.} =
var buf: array [0..59, char]
c_sprintf(buf, "%p", x)
return $buf
proc reprStrAux(result: var string, s: string) =
if cast[pointer](s) == nil:
add result "nil"
return
add result, reprPointer(cast[pointer](s)) & "\""
for c in items(s):
case c
of '"': add result "\\\""
of '\\': add result, "\\\\" # BUGFIX: forgotten
of '\10': add result, "\\10\"\n\"" # " \n " # better readability
of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
add result, "\\" & reprInt(ord(c))
else: result.add(c)
add result, "\""
proc reprStr(s: string): string {.compilerproc.} =
result = ""
reprStrAux(result, s)
proc reprBool(x: bool): string {.compilerproc.} =
if x: result = "true"
else: result = "false"
proc reprChar(x: char): string {.compilerproc.} =
result = "\'"
case x
of '"': add result, "\\\""
of '\\': add result, "\\\\"
of '\128' .. '\255', '\0'..'\31': add result, "\\" & reprInt(ord(x))
else: add result, x
add result, "\'"
proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} =
if e <% typ.node.len: # BUGFIX
result = $typ.node.sons[e].name
else:
result = $e & " (invalid data!)"
type
pbyteArray = ptr array[0.. 0xffff, byte]
proc addSetElem(result: var string, elem: int, typ: PNimType) =
case typ.kind
of tyEnum: add result, reprEnum(elem, typ)
of tyBool: add result, reprBool(bool(elem))
of tyChar: add result, reprChar(chr(elem))
of tyRange: addSetElem(result, elem, typ.base)
of tyInt..tyInt64: add result, reprInt(elem)
else: # data corrupt --> inform the user
add result, " (invalid data!)"
proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
# "typ.slots.len" field is for sets the "first" field
var elemCounter = 0 # we need this flag for adding the comma at
# the right places
add result, "{"
var u: int64
case typ.size
of 1: u = ze64(cast[ptr int8](p)^)
of 2: u = ze64(cast[ptr int16](p)^)
of 4: u = ze64(cast[ptr int32](p)^)
of 8: u = ze64(cast[ptr int64](p)^)
else:
var a = cast[pbyteArray](p)^
for i in 0 .. typ.size*8-1:
if (a[i div 8] and (1 shl (i mod 8))) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)
if typ.size <= 8:
for i in 0..sizeof(int64)*8-1:
if (u and (1 shl i)) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)
add result, "}"
proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
result = ""
reprSetAux(result, p, typ)
type
TReprClosure = record # we cannot use a global variable here
# as this wouldn't be thread-safe
marked: TCellSet
recdepth: int # do not recurse endless
indent: int # indentation
proc initReprClosure(cl: var TReprClosure) =
CellSetInit(cl.marked)
cl.recdepth = -1 # default is to display everything!
cl.indent = 0
proc deinitReprClosure(cl: var TReprClosure) =
CellSetDeinit(cl.marked)
proc reprBreak(result: var string, cl: TReprClosure) =
add result, "\n"
for i in 0..cl.indent-1: add result, ' '
proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure)
proc reprArray(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
add result, "["
var bs = typ.base.size
for i in 0..typ.size div bs - 1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
add result, "]"
proc reprSequence(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
if p == nil:
add result, "nil"
return
result.add(reprPointer(p) & "[")
var bs = typ.base.size
for i in 0..cast[PGenericSeq](p).len-1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
typ.Base, cl)
add result, "]"
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
cl: var TReprClosure) =
case n.kind
of nkNone: assert(false)
of nkSlot:
add result, $n.name
add result, " = "
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
of nkList:
for i in 0..n.len-1:
if i > 0: add result, ",\n"
reprRecordAux(result, p, n.sons[i], cl)
of nkCase:
var m = selectBranch(p, n)
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
if m != nil: reprRecordAux(result, p, m, cl)
proc reprRecord(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
add result, "["
reprRecordAux(result, p, typ.node, cl)
add result, "]"
proc reprRef(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
# we know that p is not nil here:
var cell = usrToCell(p)
add result, "ref " & reprPointer(p)
if cell notin cl.marked:
# only the address is shown:
incl(cl.marked, cell)
add result, " --> "
reprAux(result, p, typ.base, cl)
proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
if cl.recdepth == 0:
add result, "..."
return
dec(cl.recdepth)
case typ.kind
of tySet: reprSetAux(result, p, typ)
of tyArray: reprArray(result, p, typ, cl)
of tyRecord: reprRecord(result, p, typ, cl)
of tyObject: # result = reprRecord(p, typ, cl)
var t = cast[ptr PNimType](p)^
reprRecord(result, p, t, cl)
of tyRef, tyPtr:
assert(p != nil)
if cast[ppointer](p)^ == nil: add result, "nil"
else: reprRef(result, cast[ppointer](p)^, typ, cl)
of tySequence:
reprSequence(result, cast[ppointer](p)^, typ, cl)
of tyInt: add result, $(cast[ptr int](p)^)
of tyInt8: add result, $int(cast[ptr Int8](p)^)
of tyInt16: add result, $int(cast[ptr Int16](p)^)
of tyInt32: add result, $int(cast[ptr Int32](p)^)
of tyInt64: add result, $(cast[ptr Int64](p)^)
of tyFloat: add result, $(cast[ptr float](p)^)
of tyFloat32: add result, $(cast[ptr float32](p)^)
of tyFloat64: add result, $(cast[ptr float64](p)^)
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
of tyBool: add result, reprBool(cast[ptr bool](p)^)
of tyChar: add result, reprChar(cast[ptr char](p)^)
of tyString: reprStrAux(result, cast[ptr string](p)^)
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
of tyRange: reprAux(result, p, typ.base, cl)
of tyProc, tyPointer:
if cast[ppointer](p)^ == nil: add result, "nil"
else: add result, reprPointer(cast[ppointer](p)^)
else:
add result, "(invalid data!)"
inc(cl.recdepth)
proc reprAny(p: pointer, typ: PNimType): string =
var
cl: TReprClosure
initReprClosure(cl)
result = ""
if typ.kind in {tyObject, tyRecord, tyArray, tySet}:
reprAux(result, p, typ, cl)
else:
reprAux(result, addr(p), typ, cl)
add result, "\n"
deinitReprClosure(cl)
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# The generic ``repr`` procedure. It is an invaluable debugging tool.
#proc cstrToNimStrDummy(s: cstring): string {.inline.} =
# result = cast[string](cstrToNimStr(s))
proc reprInt(x: int64): string {.compilerproc.} = return $x
proc reprFloat(x: float): string {.compilerproc.} = return $x
proc reprPointer(x: pointer): string {.compilerproc.} =
var buf: array [0..59, char]
c_sprintf(buf, "%p", x)
return $buf
proc reprStrAux(result: var string, s: string) =
if cast[pointer](s) == nil:
add result "nil"
return
add result, reprPointer(cast[pointer](s)) & "\""
for c in items(s):
case c
of '"': add result "\\\""
of '\\': add result, "\\\\" # BUGFIX: forgotten
of '\10': add result, "\\10\"\n\"" # " \n " # better readability
of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
add result, "\\" & reprInt(ord(c))
else: result.add(c)
add result, "\""
proc reprStr(s: string): string {.compilerproc.} =
result = ""
reprStrAux(result, s)
proc reprBool(x: bool): string {.compilerproc.} =
if x: result = "true"
else: result = "false"
proc reprChar(x: char): string {.compilerproc.} =
result = "\'"
case x
of '"': add result, "\\\""
of '\\': add result, "\\\\"
of '\128' .. '\255', '\0'..'\31': add result, "\\" & reprInt(ord(x))
else: add result, x
add result, "\'"
proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} =
if e <% typ.node.len: # BUGFIX
result = $typ.node.sons[e].name
else:
result = $e & " (invalid data!)"
type
pbyteArray = ptr array[0.. 0xffff, byte]
proc addSetElem(result: var string, elem: int, typ: PNimType) =
case typ.kind
of tyEnum: add result, reprEnum(elem, typ)
of tyBool: add result, reprBool(bool(elem))
of tyChar: add result, reprChar(chr(elem))
of tyRange: addSetElem(result, elem, typ.base)
of tyInt..tyInt64: add result, reprInt(elem)
else: # data corrupt --> inform the user
add result, " (invalid data!)"
proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
# "typ.slots.len" field is for sets the "first" field
var elemCounter = 0 # we need this flag for adding the comma at
# the right places
add result, "{"
var u: int64
case typ.size
of 1: u = ze64(cast[ptr int8](p)^)
of 2: u = ze64(cast[ptr int16](p)^)
of 4: u = ze64(cast[ptr int32](p)^)
of 8: u = cast[ptr int64](p)^
else:
var a = cast[pbyteArray](p)
for i in 0 .. typ.size*8-1:
if (a[i div 8] and (1 shl (i mod 8))) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)
if typ.size <= 8:
for i in 0..sizeof(int64)*8-1:
if (u and (1 shl i)) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)
add result, "}"
proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
result = ""
reprSetAux(result, p, typ)
type
TReprClosure {.final.} = object # we cannot use a global variable here
# as this wouldn't be thread-safe
marked: TCellSet
recdepth: int # do not recurse endless
indent: int # indentation
proc initReprClosure(cl: var TReprClosure) =
CellSetInit(cl.marked)
cl.recdepth = -1 # default is to display everything!
cl.indent = 0
proc deinitReprClosure(cl: var TReprClosure) =
CellSetDeinit(cl.marked)
proc reprBreak(result: var string, cl: TReprClosure) =
add result, "\n"
for i in 0..cl.indent-1: add result, ' '
proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure)
proc reprArray(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
add result, "["
var bs = typ.base.size
for i in 0..typ.size div bs - 1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
add result, "]"
proc reprSequence(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
if p == nil:
add result, "nil"
return
result.add(reprPointer(p) & "[")
var bs = typ.base.size
for i in 0..cast[PGenericSeq](p).len-1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
typ.Base, cl)
add result, "]"
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
cl: var TReprClosure) =
case n.kind
of nkNone: assert(false)
of nkSlot:
add result, $n.name
add result, " = "
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
of nkList:
for i in 0..n.len-1:
if i > 0: add result, ",\n"
reprRecordAux(result, p, n.sons[i], cl)
of nkCase:
var m = selectBranch(p, n)
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
if m != nil: reprRecordAux(result, p, m, cl)
proc reprRecord(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
add result, "["
reprRecordAux(result, p, typ.node, cl)
add result, "]"
proc reprRef(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
# we know that p is not nil here:
var cell = usrToCell(p)
add result, "ref " & reprPointer(p)
if cell notin cl.marked:
# only the address is shown:
incl(cl.marked, cell)
add result, " --> "
reprAux(result, p, typ.base, cl)
proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
if cl.recdepth == 0:
add result, "..."
return
dec(cl.recdepth)
case typ.kind
of tySet: reprSetAux(result, p, typ)
of tyArray: reprArray(result, p, typ, cl)
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
of tyObject:
var t = cast[ptr PNimType](p)^
reprRecord(result, p, t, cl)
of tyRef, tyPtr:
assert(p != nil)
if cast[ppointer](p)^ == nil: add result, "nil"
else: reprRef(result, cast[ppointer](p)^, typ, cl)
of tySequence:
reprSequence(result, cast[ppointer](p)^, typ, cl)
of tyInt: add result, $(cast[ptr int](p)^)
of tyInt8: add result, $int(cast[ptr Int8](p)^)
of tyInt16: add result, $int(cast[ptr Int16](p)^)
of tyInt32: add result, $int(cast[ptr Int32](p)^)
of tyInt64: add result, $(cast[ptr Int64](p)^)
of tyFloat: add result, $(cast[ptr float](p)^)
of tyFloat32: add result, $(cast[ptr float32](p)^)
of tyFloat64: add result, $(cast[ptr float64](p)^)
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
of tyBool: add result, reprBool(cast[ptr bool](p)^)
of tyChar: add result, reprChar(cast[ptr char](p)^)
of tyString: reprStrAux(result, cast[ptr string](p)^)
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
of tyRange: reprAux(result, p, typ.base, cl)
of tyProc, tyPointer:
if cast[ppointer](p)^ == nil: add result, "nil"
else: add result, reprPointer(cast[ppointer](p)^)
else:
add result, "(invalid data!)"
inc(cl.recdepth)
proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
compilerproc.} =
var
cl: TReprClosure
initReprClosure(cl)
result = "["
var bs = elemtyp.size
for i in 0..length - 1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), elemtyp, cl)
add result, "]"
deinitReprClosure(cl)
proc reprAny(p: pointer, typ: PNimType): string =
var
cl: TReprClosure
initReprClosure(cl)
result = ""
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
reprAux(result, p, typ, cl)
else:
var p = p
reprAux(result, addr(p), typ, cl)
add result, "\n"
deinitReprClosure(cl)

View file

@ -7,16 +7,16 @@
# distribution, for details about the copyright.
#
## This module contains various string utility routines.
## See the module `regexprs` for regular expression support.
## All the routines here are avaiable for the EMCAScript target
## too!
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
# copied from excpt.nim, because I don't want to make this template public
template newException(exceptn, message: expr): expr =
template newException(exceptn, message: expr): expr =
block: # open a new scope
var
e: ref exceptn
@ -153,6 +153,10 @@ proc ParseInt*(s: string): int {.noSideEffect.}
## a valid integer, `EInvalidValue` is raised.
# XXX: make this biggestint!
proc ParseBiggestInt*(s: string): biggestInt {.noSideEffect.}
## Parses a decimal integer value contained in `s`. If `s` is not
## a valid integer, `EInvalidValue` is raised.
proc ParseFloat*(s: string): float {.noSideEffect.}
## Parses a decimal floating point value contained in `s`. If `s` is not
## a valid floating point number, `EInvalidValue` is raised.
@ -187,7 +191,7 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
##
## "The cat eats fish."
##
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
## raised if an ill-formed format string has been passed to the `%` operator.
proc `%` *(formatstr, a: string): string {.noSideEffect.}
@ -213,7 +217,13 @@ proc allCharsInSet*(s: string, theSet: TCharSet): bool =
if not (c in theSet): return false
return true
proc c_strcmp(a, b: CString): int {.importc: "strcmp", nodecl.}
proc quoteIfSpaceExists*(s: string): string =
## returns ``'"' & s & '"'`` if `s` contains a space and does not
## start with a quote, else returns `s`
if findSubStr(' ', s) >= 0 and s[0] != '"':
result = '"' & s & '"'
else:
result = s
proc startsWith(s, prefix: string): bool =
var i = 0
@ -262,7 +272,7 @@ proc findNormalized(x: string, inArray: openarray[string]): int =
while i < high(inArray):
if cmpIgnoreStyle(x, inArray[i]) == 0: return i
inc(i, 2) # incrementing by 1 would probably result in a
# security whole ...
# security whole ...
return -1
proc `%`(formatstr: string, a: openarray[string]): string =
@ -306,11 +316,9 @@ proc `%`(formatstr: string, a: openarray[string]): string =
proc cmpIgnoreCase(a, b: string): int =
# makes usage of the fact that strings are zero-terminated
var
aa, bb: char
for i in 0..len(a)-1:
aa = toLower(a[i])
bb = toLower(b[i])
var aa = toLower(a[i])
var bb = toLower(b[i])
result = ord(aa) - ord(bb)
if result != 0: break
@ -319,14 +327,13 @@ proc cmpIgnoreCase(a, b: string): int =
proc cmpIgnoreStyle(a, b: string): int =
var
aa, bb: char
i = 0
j = 0
while True:
while a[i] == '_': inc(i)
while b[j] == '_': inc(j) # BUGFIX: typo
aa = toLower(a[i])
bb = toLower(b[j])
var aa = toLower(a[i])
var bb = toLower(b[j])
result = ord(aa) - ord(bb)
if result != 0 or aa == '\0': break
inc(i)
@ -475,15 +482,12 @@ proc deleteStr(s: var string, first, last: int) =
# parsing numbers:
proc sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
proc toHex(x: BiggestInt, len: int): string =
const
HexChars = "0123456789ABCDEF"
var
shift: BiggestInt
result = newString(len)
shift = 0
for j in countdown(len-1, 0):
result[j] = HexChars[toU32(x shr shift) and 0xF]
shift = shift + 4
@ -497,11 +501,8 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
# one more valid negative than prositive integer. Thus we perform the
# computation as a negative number and then change the sign at the end.
var
i: int
sign: BiggestInt
i = index
# a local i is more efficient than accessing an in out parameter
sign = -1
i: int = index # a local i is more efficient than accessing a var parameter
sign: BiggestInt = -1
if s[i] == '+':
inc(i)
elif s[i] == '-':
@ -523,10 +524,8 @@ proc rawParseInt(s: string, index: var int): BiggestInt =
proc parseInt(s: string): int =
var
index: int
res: BiggestInt
index = strStart
res = rawParseInt(s, index)
index: int = 0
res = rawParseInt(s, index)
if index == -1:
raise newException(EInvalidValue, "invalid integer: " & s)
elif (sizeof(int) <= 4) and
@ -535,17 +534,20 @@ proc parseInt(s: string): int =
else:
result = int(res) # convert to smaller integer type
proc ParseBiggestInt(s: string): biggestInt =
var
index: int = 0
result = rawParseInt(s, index)
if index == -1:
raise newException(EInvalidValue, "invalid integer: " & s)
proc ParseFloat(s: string): float =
var
hd, esign, sign: float
esign = 1.0
sign = 1.0
exponent, i: int
flags: int
result = 0.0
i = 0
exponent = 0
esign = 1.0
flags = 0
sign = 1.0
if s[i] == '+': inc(i)
elif s[i] == '-':
sign = -1.0
@ -558,7 +560,7 @@ proc ParseFloat(s: string): float =
while s[i] == '_': inc(i)
# Decimal?
if s[i] == '.':
hd = 1.0
var hd = 1.0
inc(i)
while s[i] in {'0'..'9'}:
# Read fractional part
@ -579,14 +581,14 @@ proc ParseFloat(s: string): float =
elif s[i] == '-':
esign = -1.0
inc(i)
if s[i] notin {'0'..'9'}:
if s[i] notin {'0'..'9'}:
raise newException(EInvalidValue, "invalid float: " & s)
while s[i] in {'0'..'9'}:
exponent = exponent * 10 + ord(s[i]) - ord('0')
inc(i)
while s[i] == '_': inc(i)
# Calculate Exponent
hd = 1.0
var hd = 1.0
for j in 1..exponent:
hd = hd * 10.0
if esign > 0.0: result = result * hd
@ -600,11 +602,10 @@ proc toOct*(x: BiggestInt, len: int): string =
## converts `x` into its octal representation. The resulting string is
## always `len` characters long. No leading ``0c`` prefix is generated.
var
mask, shift: BiggestInt
mask: BiggestInt = 7
shift: BiggestInt = 0
assert(len > 0)
result = newString(len)
mask = 7
shift = 0
for j in countdown(len-1, 0):
result[j] = chr(int((x and mask) shr shift) + ord('0'))
shift = shift + 3
@ -614,11 +615,10 @@ proc toBin*(x: BiggestInt, len: int): string =
## converts `x` into its binary representation. The resulting string is
## always `len` characters long. No leading ``0b`` prefix is generated.
var
mask, shift: BiggestInt
mask: BiggestInt = 1
shift: BiggestInt = 0
assert(len > 0)
result = newString(len)
mask = 1
shift = 0
for j in countdown(len-1, 0):
result[j] = chr(int((x and mask) shr shift) + ord('0'))
shift = shift + 1

View file

@ -33,10 +33,6 @@ var
IOFBF {.importc: "_IOFBF", nodecl.}: cint
IONBF {.importc: "_IONBF", nodecl.}: cint
# copied here to remove dependancy on strutils:
#proc toNimstr(x: Cstring, len: int): string {.
# noSideEffect, importc: "toNimStr".}
proc rawReadLine(f: TFile, result: var string) {.noStatic.} =
# of course this could be optimized a bit; but IO is slow anyway...
# and it was difficult to get this CORRECT with Ansi C's methods
@ -81,6 +77,8 @@ proc write(f: TFile, b: bool) =
else: write(f, "false")
proc write(f: TFile, r: float) = fprintf(f, "%g", r)
proc write(f: TFile, c: Char) = putc(c, f)
proc write(f: TFile, a: openArray[string]) =
for x in items(a): write(f, x)
proc EndOfFile(f: TFile): bool =
# do not blame me; blame the ANSI C standard this is so brain-damaged
@ -93,6 +91,11 @@ proc EndOfFile(f: TFile): bool =
proc writeln[Ty](f: TFile, x: Ty) =
write(f, x)
write(f, "\n")
proc writeln[Ty](f: TFile, x: openArray[Ty]) =
write(f, x)
write(f, "\n")
proc echo[Ty](x: Ty) = writeln(stdout, x)
# interface to the C procs:
@ -128,7 +131,6 @@ proc ftell(f: TFile): int {.importc: "ftell", noDecl.}
proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fwrite", noDecl.}
# size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
proc readBuffer(f: TFile, buffer: pointer, len: int): int =
result = fread(buffer, 1, len, f)
@ -140,9 +142,11 @@ proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
result = readBuffer(f, addr(a[start]), len)
proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int =
result = writeBuffer(f, addr(a[start]), len)
var x = cast[ptr array[0..1000_000_000, byte]](a)
result = writeBuffer(f, addr(x[start]), len)
proc writeChars(f: TFile, a: openarray[char], start, len: int): int =
result = writeBuffer(f, addr(a[start]), len)
var x = cast[ptr array[0..1000_000_000, byte]](a)
result = writeBuffer(f, addr(x[start]), len)
proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
result = fwrite(buffer, 1, len, f)

View file

@ -16,7 +16,7 @@
# the programmer may not want
type
TStringDesc {.importc, nodecl.} = record
TStringDesc {.importc, nodecl, final.} = object
len, space: int # len and space without counting the terminating zero
data: array[0..0, char] # for the '\0' character
@ -25,7 +25,6 @@ type
# implementation:
proc resize(old: int): int {.inline.} =
assert(old < 65536 * 4)
if old <= 0: return 1
elif old < 65536: return old * 2
else: return old * 3 div 2 # for large arrays * 3/2 is better
@ -64,6 +63,7 @@ proc cstrToNimstr(str: CString): mstring {.compilerProc.} =
return toNimstr(str, c_strlen(str))
proc copyString(src: mstring): mstring {.compilerProc.} =
if src == nil: return nil
result = rawNewString(src.space)
result.len = src.len
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(Char))
@ -220,7 +220,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
result.len = newLen
# --------------- other string routines ----------------------------------
proc `$`(x: int): string =
proc nimIntToStr(x: int): string {.compilerproc.} =
result = newString(sizeof(x)*4)
var i = 0
var y = x
@ -238,14 +238,12 @@ proc `$`(x: int): string =
for j in 0..i div 2 - 1:
swap(result[j], result[i-j-1])
{.push warnings: off.}
proc `$`(x: float): string =
proc nimFloatToStr(x: float): string {.compilerproc.} =
var buf: array [0..59, char]
c_sprintf(buf, "%#g", x)
return $buf
{.pop.}
proc `$`(x: int64): string =
proc nimInt64ToStr(x: int64): string {.compilerproc.} =
# we don't rely on C's runtime here as some C compiler's
# int64 support is weak
result = newString(sizeof(x)*4)
@ -265,19 +263,13 @@ proc `$`(x: int64): string =
for j in 0..i div 2 - 1:
swap(result[j], result[i-j-1])
proc `$`(x: bool): string =
if x: result = "true"
else: result = "false"
proc nimBoolToStr(x: bool): string {.compilerproc.} =
return if x: "true" else: "false"
proc `$`(x: char): string =
proc nimCharToStr(x: char): string {.compilerproc.} =
result = newString(1)
result[0] = x
proc `$`(x: string): string =
# this is useful for generic code!
return x
proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} =
var
a = 0

View file

@ -58,10 +58,10 @@ proc new*[T](a: var ref T) {.magic: "New".}
proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {.magic: "NewFinalize".}
## creates a new object of type ``T`` and returns a safe (traced)
## reference to it in ``a``. When the garbage collector frees the object,
## `finalizer` is called. The `finalizer` may not keep a reference to the
## `finalizer` is called. The `finalizer` may not keep a reference to the
## object pointed to by `x`. The `finalizer` cannot prevent the GC from
## freeing the object. Note: The `finalizer` refers to the type `T`, not to
## the object! This means that for each object of type `T` the finalizer
## the object! This means that for each object of type `T` the finalizer
## will be called!
# for low and high the return type T may not be correct, but
@ -86,7 +86,6 @@ type
## length field.
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
set*{.magic: "Set".}[T] ## Generic type to construct bit sets.
tuple*{.magic: "Tuple".}[T] ## Generic type to construct tuple types.
Byte* = Int8 ## this is an alias for ``int8``, that is a signed
## int 8 bits wide.
@ -104,14 +103,15 @@ type
## objects that have no ancestor are allowed.
PObject* = ref TObject ## reference to TObject
E_Base* {.compilerproc.} = object of TObject ## base exception class;
E_Base* {.compilerproc.} = object of TObject ## base exception class;
## each exception has to
## inherit from `E_Base`.
name*: cstring ## The exception's name is its Nimrod identifier.
## This field is filled automatically in the
## ``raise`` statement.
msg*: cstring ## the exception's message. Not providing an
## exception message is bad style.
msg* {.exportc: "message".}: cstring ## the exception's message. Not
## providing an
## exception message is bad style.
EAsynch* = object of E_Base ## Abstract exception class for
## *asynchronous exceptions* (interrupts).
@ -129,18 +129,21 @@ type
## could not be fullfilled.
EArithmetic* = object of ESynch ## raised if any kind of arithmetic
## error occured.
EDivByZero* = object of EArithmetic ## is the exception class for integer
## divide-by-zero errors.
EOverflow* = object of EArithmetic ## is the exception class for integer
## calculations whose results are too
## large to fit in the provided bits.
EDivByZero* {.compilerproc.} =
object of EArithmetic ## is the exception class for integer divide-by-zero
## errors.
EOverflow* {.compilerproc.} =
object of EArithmetic ## is the exception class for integer calculations
## whose results are too large to fit in the
## provided bits.
EAccessViolation* = object of ESynch ## the exception class for
## invalid memory access errors
EAccessViolation* {.compilerproc.} =
object of ESynch ## the exception class for invalid memory access errors
EAssertionFailed* = object of ESynch ## is the exception class for Assert
## procedures that is raised if the
## assertion proves wrong
EAssertionFailed* {.compilerproc.} =
object of ESynch ## is the exception class for Assert
## procedures that is raised if the
## assertion proves wrong
EControlC* = object of EAsynch ## is the exception class for Ctrl+C
## key presses in console applications.
@ -154,6 +157,9 @@ type
EInvalidIndex* = object of ESynch ## is raised if an array index is out
## of bounds.
EInvalidField* = object of ESynch ## is raised if a record field is not
## accessible because its dicriminant's
## value does not fit.
EOutOfRange* = object of ESynch ## is raised if a range check error
## occured.
@ -164,13 +170,13 @@ type
ENoExceptionToReraise* = object of ESynch ## is raised if there is no
## exception to reraise.
EInvalidObjectAssignment* = object of ESynch ## is raised if an object
## gets assigned to its
## farther's object.
EInvalidObjectAssignment* =
object of ESynch ## is raised if an object gets assigned to its
## farther's object.
EInvalidObjectConversion* = object of ESynch ## is raised if an object is
## converted to an incompatible
## object type.
EInvalidObjectConversion* =
object of ESynch ## is raised if an object is converted to an incompatible
## object type.
TResult* = enum Failure, Success
@ -394,7 +400,7 @@ proc in_Operator*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
## writeln(stdout, 'b' in s)
##
## If ``in`` had been declared as ``[T](elem: T, s: set[T])`` then ``T`` would
## have been bound to ``char``. But ``s`` is not compatible with type
## have been bound to ``char``. But ``s`` is not compatible to type
## ``set[char]``! The solution is to bind ``T`` to ``range['a'..'z']``. This
## is achieved by reversing the parameters for ``in_operator``; ``in`` then
## passes its arguments in reverse order.
@ -418,25 +424,31 @@ proc cmp*(x, y: string): int {.noSideEffect.}
## Compare proc for strings. More efficient than the generic version.
# concat operator:
proc `&` * (x: string, y: char): string {.
magic: "ConStrStr", noSideEffect, returnsNew.}
proc `&` * (x: char, y: char): string {.
magic: "ConStrStr", noSideEffect, returnsNew.}
proc `&` * (x, y: string): string {.
magic: "ConStrStr", noSideEffect, returnsNew.}
proc `&` * (x: char, y: string): string {.
magic: "ConStrStr", noSideEffect, returnsNew.}
## is the `concatenation operator`. It
## concatenates `x` and `y`.
proc `&` * (x: string, y: char): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x: char, y: char): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x, y: string): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x: char, y: string): string {.magic: "ConStrStr", noSideEffect.}
## is the `concatenation operator`. It concatenates `x` and `y`.
proc add * (x: var string, y: char) {.magic: "AppendStrCh".}
proc add * (x: var string, y: string) {.magic: "AppendStrStr".}
proc add* (x: var string, y: cstring) =
var i = 0
while y[i] != '\0':
add(x, y[i])
inc(i)
when not defined(ECMAScript):
proc add* (x: var string, y: cstring) =
var i = 0
while y[i] != '\0':
add(x, y[i])
inc(i)
else:
proc add* (x: var string, y: cstring) {.pure.} =
asm """
var len = `x`[0].length-1;
for (var i = 0; i < `y`.length; ++i) {
`x`[0][len] = `y`.charCodeAt(i);
++len;
}
`x`[0][len] = 0
"""
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem".}
proc add *[T](x: var seq[T], y: seq[T]) {.magic: "AppendSeqSeq".}
@ -493,7 +505,7 @@ type # these work for most platforms:
TEndian* = enum ## is a type describing the endianness of a processor.
littleEndian, bigEndian
PFloat32* = ptr Float32 ## an alias for ``ptr float32``
PFloat64* = ptr Float64 ## an alias for ``ptr float64``
PInt64* = ptr Int64 ## an alias for ``ptr int64``
@ -675,20 +687,27 @@ proc swap*[T](a, b: var T) {.magic: "Swap".}
## swaps the values `a` and `b`. This is often more efficient than
## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms.
proc ze*(x: int8): int {.magic: "Ze", noSideEffect.}
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned.
proc ze*(x: int16): int {.magic: "Ze", noSideEffect.}
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned.
proc ze64*(x: int32): int64 {.magic: "Ze64", noSideEffect.}
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze*(x: int): int64 {.magic: "Ze", noDecl, noSideEffect.}
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noDecl, noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
## (This is the case an 64 bit processors.)
## (This is the case on 64 bit processors.)
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
@ -749,39 +768,39 @@ template `>%` *(x, y: expr): expr = y <% x
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) > unsigned(y)``.
proc `$` *(x: int): string {.noSideEffect.}
proc `$` *(x: int): string {.magic: "IntToStr", noSideEffect.}
## The stingify operator for an integer argument. Returns `x`
## converted to a decimal string.
proc `$` *(x: int64): string {.noSideEffect.}
proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
## The stingify operator for an integer argument. Returns `x`
## converted to a decimal string.
proc `$` *(x: float): string {.noSideEffect.}
proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.}
## The stingify operator for a float argument. Returns `x`
## converted to a decimal string.
proc `$` *(x: bool): string {.noSideEffect.}
proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.}
## The stingify operator for a boolean argument. Returns `x`
## converted to the string "false" or "true".
proc `$` *(x: char): string {.noSideEffect.}
proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.}
## The stingify operator for a character argument. Returns `x`
## converted to a string.
proc `$` *(x: Cstring): string {.noSideEffect, importc: "cstrToNimstr".}
proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.}
## The stingify operator for a CString argument. Returns `x`
## converted to a string.
proc `$` *(x: string): string {.noSideEffect.}
proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
## The stingify operator for a string argument. Returns `x`
## as it is. This operator is useful for generic code, so
## that ``$expr`` works if ``expr`` is already a string.
## that ``$expr`` also works if ``expr`` is already a string.
# undocumented:
proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".}
## retrieves the reference count of an heap-allocated object. The
## value is implementation-dependant.
## value is implementation-dependant.
#proc writeStackTrace() {.export: "writeStackTrace".}
proc getCurrentExceptionMsg*(): string {.exportc.}
@ -790,10 +809,12 @@ proc getCurrentExceptionMsg*(): string {.exportc.}
# new constants:
const
inf* = 1.0 / 0.0
inf* {.magic: "Inf".} = 0.0
## contains the IEEE floating point value of positive infinity.
nan* = 0.0 / 0.0
## contains the IEEE floating point value of *Not A Number*. Note
neginf* {.magic: "NegInf".} = 0.0
## contains the IEEE floating point value of negative infinity.
nan* {.magic: "NaN".} = 0.0
## contains an IEEE floating point value of *Not A Number*. Note
## that you cannot compare a floating point value to this value
## and expect a reasonable result - use the `classify` procedure
## in the module ``math`` for checking for NaN.
@ -805,18 +826,18 @@ var
## Only code compiled with the ``debugger:on`` switch calls this hook.
# GC interface:
when defined(Unix) and not defined(macosX) and not defined(linux):
when defined(Unix) and not defined(macosX) and not defined(linux):
# BUGFIX for macosX
{.define: nativeDL.}
when defined(useDL) or defined(nativeDL):
proc getOccupiedMem*(): int
## returns the number of bytes that are owned by the process and hold data.
proc getFreeMem*(): int
## returns the number of bytes that are owned by the process, but do not
## hold any meaningful data.
proc getTotalMem*(): int
## returns the number of bytes that are owned by the process.
@ -885,11 +906,22 @@ iterator items*(a: cstring): char {.inline.} =
yield a[i]
inc(i)
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
## Fast check whether `x` is nil. This is sometimes more efficient than
## ``== nil``.
# Fixup some magic symbols here:
{.fixup_system.} # This is an undocumented pragma that can only be used
# once in the system module.
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} =
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
result = []
setLen(result, x.len + y.len)
for i in 0..x.len-1:
@ -897,76 +929,92 @@ proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} =
for i in 0..y.len-1:
result[i] = y[i]
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect, returnsNew.} =
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
result = []
setLen(x.len + 1)
for i in 0..x.len-1:
result[i] = x[i]
result[x.len] = y
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect, returnsNew.} =
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
result = []
setLen(y.len + 1)
for i in 0..y.len-1:
result[i] = y[i]
result[y.len] = x
proc `&` *[T](x, y: T): seq[T] {.noSideEffect, returnsNew.} =
proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} =
return [x, y]
when not defined(ECMAScript): # XXX make this local procs
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
result = cast[pointer](x)
else:
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} =
asm """return `x`"""
proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
## Generic equals operator for sequences: relies on a equals operator for
## the element type `T`.
if cast[pointer](x) == cast[pointer](y):
if seqToPtr(x) == seqToPtr(y):
result = true
elif cast[pointer](x) == nil or cast[pointer](y) == nil:
elif seqToPtr(x) == nil or seqToPtr(y) == nil:
result = false
elif x.len == y.len:
for i in 0..x.len-1:
if x[i] != y[i]: return false
result = true
# ----------------- FPU ------------------------------------------------------
#proc disableFPUExceptions*()
# disables all floating point unit exceptions
#proc enableFPUExceptions*()
# enables all floating point unit exceptions
# ----------------- GC interface ---------------------------------------------
proc GC_disable*()
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
## reactivate the GC. Note that in most circumstances one should only disable
## the mark and sweep phase with `GC_disableMarkAndSweep`.
proc GC_enable*()
## enables the GC again.
proc GC_fullCollect*()
## forces a full garbage collection pass.
## Ordinary code does not need to call this.
type
TGC_Strategy* = enum ## the strategy the GC should use for the application
gcThroughput, ## optimize for throughput
gcResponsiveness, ## optimize for responsiveness (default)
gcOptimizeTime, ## optimize for speed
gcOptimizeSpace ## optimize for memory footprint
proc GC_setStrategy*(strategy: TGC_Strategy)
## tells the GC the desired strategy for the application.
proc GC_enableMarkAndSweep*()
proc GC_disableMarkAndSweep*()
## the current implementation uses a reference counting garbage collector
## with a seldomly run mark and sweep phase to free cycles. The mark and
## sweep phase may take a long time and is not needed if the application
## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC.
{.push checks: off, line_dir: off, debugger: off,
assertions: on.} # obviously we cannot generate checking operations here :-)
# because it would yield into an endless recursion
# however, stack-traces are available for most parts
# of the code
include hti
proc initGC()
var
strDesc: TNimType
strDesc.size = sizeof(string)
strDesc.kind = tyString
initGC() # BUGFIX: need to be called here!
{.push stack_trace: off.}
include ansi_c
proc cmp(x, y: string): int =
return c_strcmp(x, y)
when defined(windows):
# work-around C's sucking abstraction:
# BUGFIX: stdin and stdout should be binary files!
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
proc setmode(handle, mode: int) {.importc: pccHack & "setmode",
header: "<io.h>".}
proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno",
header: "<fcntl.h>".}
var
O_BINARY {.importc: pccHack & "O_BINARY", nodecl.}: int
# we use binary mode in Windows:
setmode(fileno(c_stdin), O_BINARY)
setmode(fileno(c_stdout), O_BINARY)
when defined(endb):
proc endbStep()
proc echo*[Ty](x: Ty) {.inline.}
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
## available for the ECMAScript target too!
template newException(exceptn, message: expr): expr =
@ -976,209 +1024,223 @@ template newException(exceptn, message: expr): expr =
new(e)
e.msg = message
e
# ----------------- GC interface ---------------------------------------------
proc GC_disable*()
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
## reactivate the GC. Note that in most circumstances one should only disable
## the mark and sweep phase with `GC_disableMarkAndSweep`.
when not defined(EcmaScript):
proc GC_enable*()
## enables the GC again.
proc GC_fullCollect*()
## forces a full garbage collection pass.
## Ordinary code does not need to call this.
include hti
type
TGC_Strategy* = enum ## the strategy the GC should use for the application
gcThroughput , ## optimize for throughput
gcResponsiveness, ## optimize for responsiveness (default)
gcOptimizeTime, ## optimize for speed
gcOptimizeSpace ## optimize for memory footprint
proc initGC()
proc GC_setStrategy*(strategy: TGC_Strategy)
## tells the GC the desired strategy for the application.
proc GC_enableMarkAndSweep*()
proc GC_disableMarkAndSweep*()
## the current implementation uses a reference counting garbage collector
## with a seldomly run mark and sweep phase to free cycles. The mark and
## sweep phase may take a long time and is not needed if the application
## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC.
# ----------------- IO Part --------------------------------------------------
type
CFile {.importc: "FILE", nodecl.} = record # empty record for
# data hiding
TFile* = ptr CFile ## The type representing a file handle.
TFileMode* = enum ## The file mode when opening a file.
fmRead, ## Open the file for read access only.
fmWrite, ## Open the file for write access only.
fmReadWrite, ## Open the file for read and write access.
## If the file does not exist, it will be
## created.
fmReadWriteExisting, ## Open the file for read and write access.
## If the file does not exist, it will not be
## created.
fmAppend ## Open the file for writing only; append data
## at the end.
# text file handling:
var
stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream.
stdout* {.importc: "stdout", noDecl.}: TFile ## The standard output stream.
stderr* {.importc: "stderr", noDecl.}: TFile
## The standard error stream.
##
## Note: In my opinion, this should not be used -- the concept of a
## separate error stream is a design flaw of UNIX. A seperate *message
## stream* is a good idea, but since it is named ``stderr`` there are few
## programs out there that distinguish properly between ``stdout`` and
## ``stderr``. So, that's what you get if you don't name your variables
## appropriately. It also annoys people if redirection via ``>output.txt``
## does not work because the program writes to ``stderr``.
proc OpenFile*(f: var TFile, filename: string,
mode: TFileMode = fmRead, bufSize: int = -1): Bool
## Opens a file named `filename` with given `mode`.
##
## Default mode is readonly. Returns true iff the file could be opened.
## This throws no exception if the file could not be opened. The reason is
## that the programmer needs to provide an appropriate error message anyway
## (yes, even in scripts).
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.}
## Closes the file.
proc EndOfFile*(f: TFile): Bool
## Returns true iff `f` is at the end.
proc readChar*(f: TFile): char {.importc: "fgetc", nodecl.}
## Reads a single character from the stream `f`. If the stream
## has no more characters, `EEndOfFile` is raised.
proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.}
## Flushes `f`'s buffer.
proc readFile*(filename: string): string
## Opens a file name `filename` for reading. Then reads the
## file's content completely into a string and
## closes the file afterwards. Returns the string. Returns nil if there was
## an error. Does not throw an IO exception.
proc write*(f: TFile, r: float)
proc write*(f: TFile, i: int)
proc write*(f: TFile, s: string)
proc write*(f: TFile, b: Bool)
proc write*(f: TFile, c: char)
proc write*(f: TFile, c: cstring)
## Writes a value to the file `f`. May throw an IO exception.
proc readLine*(f: TFile): string
## reads a line of text from the file `f`. May throw an IO exception.
## Reading from an empty file buffer, does not throw an exception, but
## returns nil. A line of text may be delimited by ``CR``, ``LF`` or
## ``CRLF``. The newline character(s) are not part of the returned string.
proc writeln*[Ty](f: TFile, x: Ty) {.inline.}
## writes a value `x` to `f` and then writes "\n". May throw an IO exception.
proc echo*[Ty](x: Ty) {.inline.}
## equivalent to ``writeln(stdout, x); flush(stdout)``.
proc getFileSize*(f: TFile): int64
## retrieves the file size (in bytes) of `f`.
proc ReadBytes*(f: TFile, a: var openarray[byte], start, len: int): int
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater.
proc ReadChars*(f: TFile, a: var openarray[char], start, len: int): int
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater.
proc readBuffer*(f: TFile, buffer: pointer, len: int): int
## reads `len` bytes into the buffer pointed to by `buffer`. Returns
## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater.
proc writeBytes*(f: TFile, a: openarray[byte], start, len: int): int
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
## the number of actual written bytes, which may be less than `len` in case
## of an error.
proc writeChars*(f: tFile, a: openarray[char], start, len: int): int
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
## the number of actual written bytes, which may be less than `len` in case
## of an error.
proc writeBuffer*(f: TFile, buffer: pointer, len: int): int
## writes the bytes of buffer pointed to by the parameter `buffer` to the
## file `f`. Returns the number of actual written bytes, which may be less
## than `len` in case of an error.
proc setFilePos*(f: TFile, pos: int64)
## sets the position of the file pointer that is used for read/write
## operations. The file's first byte has the index zero.
proc getFilePos*(f: TFile): int64
## retrieves the current position of the file pointer that is used to
## read from the file `f`. The file's first byte has the index zero.
include sysio
iterator lines*(filename: string): string =
## Iterate over any line in the file named `filename`.
## If the file does not exist `EIO` is raised.
var
f: TFile
if not openFile(f, filename):
raise newException(EIO, "cannot open: " & filename)
var res = ""
while not endOfFile(f):
rawReadLine(f, res)
yield res
CloseFile(f)
strDesc: TNimType
# ----------------------------------------------------------------------------
strDesc.size = sizeof(string)
strDesc.kind = tyString
initGC() # BUGFIX: need to be called here!
include excpt
# we cannot compile this with stack tracing on
# as it would recurse endlessly!
include arithm
{.pop.} # stack trace
{.push stack_trace: off.}
# sequence type declarations here because the GC needs them too:
type
TGenericSeq {.importc, nodecl.} = record
len, space: int
include ansi_c
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq
proc cmp(x, y: string): int =
return c_strcmp(x, y)
const
GenericSeqSize = (2 * sizeof(int))
when defined(windows):
# work-around C's sucking abstraction:
# BUGFIX: stdin and stdout should be binary files!
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
proc setmode(handle, mode: int) {.importc: pccHack & "setmode",
header: "<io.h>".}
proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno",
header: "<fcntl.h>".}
var
O_BINARY {.importc: pccHack & "O_BINARY", nodecl.}: int
when not defined(boehmgc) and not defined(nogc):
include gc
# we use binary mode in Windows:
setmode(fileno(c_stdin), O_BINARY)
setmode(fileno(c_stdout), O_BINARY)
include sysstr
include assign
include dyncalls
include repr
when defined(endb):
proc endbStep()
# we have to implement it here after gentostr for the cstrToNimStrDummy proc
proc getCurrentExceptionMsg(): string =
if excHandler == nil: return ""
return $excHandler.exc.msg
# ----------------- IO Part --------------------------------------------------
type
CFile {.importc: "FILE", nodecl, final.} = object # empty record for
# data hiding
TFile* = ptr CFile ## The type representing a file handle.
TFileMode* = enum ## The file mode when opening a file.
fmRead, ## Open the file for read access only.
fmWrite, ## Open the file for write access only.
fmReadWrite, ## Open the file for read and write access.
## If the file does not exist, it will be
## created.
fmReadWriteExisting, ## Open the file for read and write access.
## If the file does not exist, it will not be
## created.
fmAppend ## Open the file for writing only; append data
## at the end.
# text file handling:
var
stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream.
stdout* {.importc: "stdout", noDecl.}: TFile ## The standard output stream.
stderr* {.importc: "stderr", noDecl.}: TFile
## The standard error stream.
##
## Note: In my opinion, this should not be used -- the concept of a
## separate error stream is a design flaw of UNIX. A seperate *message
## stream* is a good idea, but since it is named ``stderr`` there are few
## programs out there that distinguish properly between ``stdout`` and
## ``stderr``. So, that's what you get if you don't name your variables
## appropriately. It also annoys people if redirection via ``>output.txt``
## does not work because the program writes to ``stderr``.
proc OpenFile*(f: var TFile, filename: string,
mode: TFileMode = fmRead, bufSize: int = -1): Bool
## Opens a file named `filename` with given `mode`.
##
## Default mode is readonly. Returns true iff the file could be opened.
## This throws no exception if the file could not be opened. The reason is
## that the programmer needs to provide an appropriate error message anyway
## (yes, even in scripts).
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.}
## Closes the file.
proc EndOfFile*(f: TFile): Bool
## Returns true iff `f` is at the end.
proc readChar*(f: TFile): char {.importc: "fgetc", nodecl.}
## Reads a single character from the stream `f`. If the stream
## has no more characters, `EEndOfFile` is raised.
proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.}
## Flushes `f`'s buffer.
proc readFile*(filename: string): string
## Opens a file name `filename` for reading. Then reads the
## file's content completely into a string and
## closes the file afterwards. Returns the string. Returns nil if there was
## an error. Does not throw an IO exception.
proc write*(f: TFile, r: float)
proc write*(f: TFile, i: int)
proc write*(f: TFile, s: string)
proc write*(f: TFile, b: Bool)
proc write*(f: TFile, c: char)
proc write*(f: TFile, c: cstring)
proc write*(f: TFile, a: openArray[string])
## Writes a value to the file `f`. May throw an IO exception.
proc readLine*(f: TFile): string
## reads a line of text from the file `f`. May throw an IO exception.
## Reading from an empty file buffer, does not throw an exception, but
## returns nil. A line of text may be delimited by ``CR``, ``LF`` or
## ``CRLF``. The newline character(s) are not part of the returned string.
proc writeln*[Ty](f: TFile, x: Ty) {.inline.}
## writes a value `x` to `f` and then writes "\n".
## May throw an IO exception.
proc writeln*[Ty](f: TFile, x: openArray[Ty]) {.inline.}
## writes a value `x` to `f` and then writes "\n".
## May throw an IO exception.
proc getFileSize*(f: TFile): int64
## retrieves the file size (in bytes) of `f`.
proc ReadBytes*(f: TFile, a: var openarray[byte], start, len: int): int
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater.
proc ReadChars*(f: TFile, a: var openarray[char], start, len: int): int
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater.
proc readBuffer*(f: TFile, buffer: pointer, len: int): int
## reads `len` bytes into the buffer pointed to by `buffer`. Returns
## the actual number of bytes that have been read which may be less than
## `len` (if not as many bytes are remaining), but not greater.
proc writeBytes*(f: TFile, a: openarray[byte], start, len: int): int
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
## the number of actual written bytes, which may be less than `len` in case
## of an error.
proc writeChars*(f: tFile, a: openarray[char], start, len: int): int
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
## the number of actual written bytes, which may be less than `len` in case
## of an error.
proc writeBuffer*(f: TFile, buffer: pointer, len: int): int
## writes the bytes of buffer pointed to by the parameter `buffer` to the
## file `f`. Returns the number of actual written bytes, which may be less
## than `len` in case of an error.
proc setFilePos*(f: TFile, pos: int64)
## sets the position of the file pointer that is used for read/write
## operations. The file's first byte has the index zero.
proc getFilePos*(f: TFile): int64
## retrieves the current position of the file pointer that is used to
## read from the file `f`. The file's first byte has the index zero.
include sysio
iterator lines*(filename: string): string =
## Iterate over any line in the file named `filename`.
## If the file does not exist `EIO` is raised.
var
f: TFile
if not openFile(f, filename):
raise newException(EIO, "cannot open: " & filename)
var res = ""
while not endOfFile(f):
rawReadLine(f, res)
yield res
CloseFile(f)
# ----------------------------------------------------------------------------
include excpt
# we cannot compile this with stack tracing on
# as it would recurse endlessly!
include arithm
{.pop.} # stack trace
# sequence type declarations here because the GC needs them too:
type
TGenericSeq {.importc, nodecl, final.} = object
len, space: int
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq
const
GenericSeqSize = (2 * sizeof(int))
when not defined(boehmgc) and not defined(nogc):
include gc
include sysstr
include assign
include dyncalls
include repr
# we have to implement it here after gentostr for the cstrToNimStrDummy proc
proc getCurrentExceptionMsg(): string =
if excHandler == nil: return ""
return $excHandler.exc.msg
{.push stack_trace: off.}
when defined(endb):
include debugger
{.pop.} # stacktrace
else:
include ecmasys
include macros
{.push stack_trace: off.}
when defined(endb):
include debugger
{.pop.} # stacktrace
{.pop.} # checks
{.pop.} # hints

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@ -9,6 +9,7 @@
## This module contains routines and types for dealing with time.
## This module is available for the ECMAScript target.
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
@ -22,9 +23,49 @@ type
TWeekDay* = enum ## represents a weekday
dMon, dTue, dWed, dThu, dFri, dSat, dSun
TTime* {.importc: "time_t".} = record ## abstract type that represents a time
TTime* {.importc: "time_t", final.} = object ## abstract type that
## represents a time
when defined(ECMAScript):
getDay: proc (): int
getFullYear: proc (): int
getHours: proc (): int
getMilliseconds: proc (): int
getMinutes: proc (): int
getMonth: proc (): int
getSeconds: proc (): int
getTime: proc (): int
getTimezoneOffset: proc (): int
getUTCDate: proc (): int
getUTCFullYear: proc (): int
getUTCHours: proc (): int
getUTCMilliseconds: proc (): int
getUTCMinutes: proc (): int
getUTCMonth: proc (): int
getUTCSeconds: proc (): int
getYear: proc (): int
parse: proc (s: cstring): TTime
setDate: proc (x: int)
setFullYear: proc (x: int)
setHours: proc (x: int)
setMilliseconds: proc (x: int)
setMinutes: proc (x: int)
setMonth: proc (x: int)
setSeconds: proc (x: int)
setTime: proc (x: int)
setUTCDate: proc (x: int)
setUTCFullYear: proc (x: int)
setUTCHours: proc (x: int)
setUTCMilliseconds: proc (x: int)
setUTCMinutes: proc (x: int)
setUTCMonth: proc (x: int)
setUTCSeconds: proc (x: int)
setYear: proc (x: int)
toGMTString: proc (): cstring
toLocaleString: proc (): cstring
UTC: proc (): int
TTimeInfo* = record ## represents a time in different parts
TTimeInfo* = object of TObject ## represents a time in different parts
second*: range[0..61] ## The number of seconds after the minute,
## normally in the range 0 to 59, but can
## be up to 61 to allow for leap seconds.
@ -38,6 +79,7 @@ type
weekday*: TWeekDay ## The current day of the week.
yearday*: range[0..365] ## The number of days since January 1,
## in the range 0 to 365.
## Always 0 if the target is ECMAScript.
proc getTime*(): TTime ## gets the current calendar time
proc getLocalTime*(t: TTime): TTimeInfo
@ -54,7 +96,7 @@ proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
## them from the other information in the broken-down time structure.
proc `$` *(timeInfo: TTimeInfo): string
## converts a `TTimeInfo` record to a
## converts a `TTimeInfo` object to a
## string representation.
proc `$` *(time: TTime): string
## converts a calendar time to a
@ -72,92 +114,149 @@ proc `-` *(a, b: TTime): int64
proc getStartMilsecs*(): int
## get the miliseconds from the start of the program
#implementation
# C wrapper:
type
structTM {.importc: "struct tm".} = record
second {.importc: "tm_sec".},
minute {.importc: "tm_min".},
hour {.importc: "tm_hour".},
monthday {.importc: "tm_mday".},
month {.importc: "tm_mon".},
year {.importc: "tm_year".},
weekday {.importc: "tm_wday".},
yearday {.importc: "tm_yday".},
isdst {.importc: "tm_isdst".}: cint
when not defined(ECMAScript):
# C wrapper:
type
structTM {.importc: "struct tm", final.} = object
second {.importc: "tm_sec".},
minute {.importc: "tm_min".},
hour {.importc: "tm_hour".},
monthday {.importc: "tm_mday".},
month {.importc: "tm_mon".},
year {.importc: "tm_year".},
weekday {.importc: "tm_wday".},
yearday {.importc: "tm_yday".},
isdst {.importc: "tm_isdst".}: cint
PTimeInfo = ptr structTM
PTime = ptr TTime
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
proc localtime(timer: PTime): PTimeInfo {.
importc: "localtime", header: "<time.h>".}
proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
proc timec(timer: PTime): TTime {.importc: "time", header: "<time.h>".}
proc mktime(t: structTM): TTime {.importc: "mktime", header: "<time.h>".}
proc asctime(tblock: structTM): CString {.
importc: "asctime", header: "<time.h>".}
proc ctime(time: PTime): CString {.importc: "ctime", header: "<time.h>".}
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
# importc: "strftime", header: "<time.h>".}
proc clock(): TClock {.importc: "clock", header: "<time.h>".}
proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
var
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
# our own procs on top of that:
proc tmToTimeInfo(tm: structTM): TTimeInfo =
const
weekDays: array [0..6, TWeekDay] = [
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
result.second = int(tm.second)
result.minute = int(tm.minute)
result.hour = int(tm.hour)
result.monthday = int(tm.monthday)
result.month = TMonth(tm.month)
result.year = tm.year + 1900
result.weekday = weekDays[int(tm.weekDay)]
result.yearday = int(tm.yearday)
proc timeInfoToTM(t: TTimeInfo): structTM =
const
weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
result.second = t.second
result.minute = t.minute
result.hour = t.hour
result.monthday = t.monthday
result.month = ord(t.month)
result.year = t.year - 1900
result.weekday = weekDays[t.weekDay]
result.yearday = t.yearday
result.isdst = -1
proc `-` (a, b: TTime): int64 =
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
# Nim does not support it!
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
proc getTime(): TTime = return timec(nil)
proc getLocalTime(t: TTime): TTimeInfo =
var a = t
result = tmToTimeInfo(localtime(addr(a))^)
# copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive
proc getGMTime(t: TTime): TTimeInfo =
var a = t
result = tmToTimeInfo(gmtime(addr(a))^)
# copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
var cTimeInfo = timeInfo # for C++ we have to make a copy,
# because the header of mktime is broken in my version of libc
return mktime(timeInfoToTM(cTimeInfo))
proc `$`(timeInfo: TTimeInfo): string =
return $asctime(timeInfoToTM(timeInfo))
proc `$`(time: TTime): string =
var a = time
return $ctime(addr(a))
PTimeInfo = ptr structTM
PTime = ptr TTime
else:
proc getTime(): TTime {.importc: "new Date", nodecl.}
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
proc localtime(timer: PTime): PTimeInfo {.
importc: "localtime", header: "<time.h>".}
proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
proc timec(timer: PTime): TTime {.importc: "time", header: "<time.h>".}
proc mktime(t: structTM): TTime {.importc: "mktime", header: "<time.h>".}
proc asctime(tblock: structTM): CString {.
importc: "asctime", header: "<time.h>".}
proc ctime(time: PTime): CString {.importc: "ctime", header: "<time.h>".}
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
# importc: "strftime", header: "<time.h>".}
proc clock(): TClock {.importc: "clock", header: "<time.h>".}
proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
var
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
# our own procs on top of that:
proc tmToTimeInfo(tm: structTM): TTimeInfo =
const
weekDays: array [0..6, TWeekDay] = [
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
result.second = int(tm.second)
result.minute = int(tm.minute)
result.hour = int(tm.hour)
result.monthday = int(tm.monthday)
result.month = TMonth(tm.month)
result.year = tm.year + 1900
result.weekday = weekDays[int(tm.weekDay)]
result.yearday = int(tm.yearday)
proc getLocalTime(t: TTime): TTimeInfo =
result.second = t.getSeconds()
result.minute = t.getMinutes()
result.hour = t.getHours()
result.monthday = t.getDate()
result.month = TMonth(t.getMonth())
result.year = t.getFullYear()
result.weekday = weekDays[t.getDay()]
result.yearday = 0
proc timeInfoToTM(t: TTimeInfo): structTM =
const
weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
result.second = t.second
result.minute = t.minute
result.hour = t.hour
result.monthday = t.monthday
result.month = ord(t.month)
result.year = t.year - 1900
result.weekday = weekDays[t.weekDay]
result.yearday = t.yearday
result.isdst = -1
proc `-` (a, b: TTime): int64 =
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
# Nim does not support it!
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
proc getTime(): TTime = return timec(nil)
proc getLocalTime(t: TTime): TTimeInfo =
var a = t
result = tmToTimeInfo(localtime(addr(a))^)
# copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive
proc getGMTime(t: TTime): TTimeInfo =
var a = t
result = tmToTimeInfo(gmtime(addr(a))^)
# copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
var cTimeInfo = timeInfo # for C++ we have to make a copy,
# because the header of mktime is broken in my version of libc
return mktime(timeInfoToTM(cTimeInfo))
proc getGMTime(t: TTime): TTimeInfo =
result.second = t.getUTCSeconds()
result.minute = t.getUTCMinutes()
result.hour = t.getUTCHours()
result.monthday = t.getUTCDate()
result.month = TMonth(t.getUTCMonth())
result.year = t.getUTCFullYear()
result.weekday = weekDays[t.getDay()]
result.yearday = 0
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime =
result = getTime()
result.setSeconds(timeInfo.second)
result.setMinutes(timeInfo.minute)
result.setHours(timeInfo.hour)
result.setMonth(ord(timeInfo.month))
result.setFullYear(timeInfo.year)
result.setDate(timeInfo.monthday)
proc `$`(timeInfo: TTimeInfo): string = return $(TimeInfoToTIme(timeInfo))
proc `$`(time: TTime): string = $time.toLocaleString()
proc `-` (a, b: TTime): int64 =
return a.getTime() - b.getTime()
var
startMilsecs = getTime()
proc getStartMilsecs(): int =
## get the miliseconds from the start of the program
return int(getTime() - startMilsecs)
proc getDateStr(): string =
var ti = getLocalTime(getTime())
@ -169,11 +268,4 @@ proc getClockStr(): string =
result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &
':' & intToStr(ti.second, 2)
proc `$`(timeInfo: TTimeInfo): string =
return $asctime(timeInfoToTM(timeInfo))
proc `$`(time: TTime): string =
var a = time
return $ctime(addr(a))
{.pop.}

View file

@ -1,221 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# type-info module for Nimrod
include hti
proc typeid(x: any): PNimType
type
Variant = opaque record
# contains the address and a typeinfo
a: pointer # an address
k: TNimTypeKind
# conversions to any and from any are inserted by the compiler!
# x.attr is supported, as well as x[]!
# here is a special iterator for variants:
iterator fields(x: variant): (fieldname: string, value: variant) =
proc setField(structure: variant, fieldname: string, value: variant)
proc getField(structure: variant, fieldname: string)
# any is implemented as a pair (val: pointer, info: PTypeInfo)
# val is for:
# an array - its address
# a record - its address
# an object - its address
# a string - the address of the pointer to the string data
# a sequence - the address of the pointer to the sequence data
# a float - the address of a memory location where the float is stored
# this is a given address; storage comes from compiler or is
# already there (in a container)
# an int - the address of a memory location where the int is stored
# storage comes from compiler or is
# already there (in a container)
# a cstring - the address of an address of an array of chars
# a ref - the address of the ref! (not the ref itself!)
# But this does not work too well...
# Better: any is a ref to Object; than we define intObj, floatObj,
# etc.; for strings this not needed as they already fit into the
# scheme!
#
type
TAnyImpl {.exportc: "TAnyImpl".} = record
typ {.exportc: "info".}: PNimType
val {.exportc: "val".}: pointer
proc
typeKind(p: PNimType): TTypeKind {.inline.}
getAnyLength(x: any): int
isContainer(x: any): bool
writeAny(container: any, index: int, val: any)
readAny(container: any, index: int): any
writeAny(container: any, name: string, val: any)
readAny(container: any, name: string): any
getAttr(container: any, index: int, out name: string, out val: any)
getEnumStrings(enumeration: any): sequence of string
anyToInt(x: any): biggestint
anyToFloat(x: any): biggestfloat
anyToString(x: any): string
anyToChar(x: any): char
anyToBool(x: any): bool
#anyToT{T}(x: any, out result: T)
# etc...
#write(a: array of any) # also possible!
#generic proc
# deepCopy{T}(x: T): T
import
strutils
proc anyToImpl(a: any): TAnyImpl {.inline.} =
result = cast{TAnyImpl}(a)
proc typeKind(p: PNimType): TTypeKind =
result = p.typeKind
type
Pint = untraced ref int
Pint8 = untraced ref int8
Pint16 = untraced ref int16
Pint32 = untraced ref int32
Pint64 = untraced ref int64
Puint = untraced ref uint
Puint8 = untraced ref uint8
Puint16 = untraced ref uint16
Puint32 = untraced ref uint32
Puint64 = untraced ref uint64
Pfloat = untraced ref float
Pfloat32 = untraced ref float32
Pfloat64 = untraced ref float64
Pstring = untraced ref string
Pbool = untraced ref bool
Pchar = untraced ref char
proc anyToInt(x: any): biggestint =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyInt, tyEnum: result = cast{pint}(x.val)^
of tySInt8: result = cast{pint8}(x.val)^
of tySInt16: result = cast{pint16}(x.val)^
of tySInt32: result = cast{pint32}(x.val)^
of tySInt64: result = cast{pint64}(x.val)^
of tyUInt: result = cast{puint}(x.val)^
of tyUInt8: result = cast{puint8}(x.val)^
of tyUInt16: result = cast{puint16}(x.val)^
of tyUInt32: result = cast{puint32}(x.val)^
of tyUInt64: result = cast{puint64}(x.val)^
else: raise EConvertError
proc anyToFloat(x: any): biggestfloat =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyReal: result = cast{pfloat}(x.val)^
of tyReal32: result = cast{pfloat32}(x.val)^
of tyReal64: result = cast{pfloat64}(x.val)^
# of tyReal128:
else: raise EConvertError
proc anyToString(x: any): string =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyString: result = cast{pstring}(x.val)^
else: raise EConvertError
proc anyToChar(x: any): char =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyChar: result = cast{pchar}(x.val)^
else: raise EConvertError
proc anyToBool(x: any): bool =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyBool: result = cast{pbool}(x.val)^
else: raise EConvertError
proc getAnyLength(x: any): int =
result = anyToImpl(x).typ.len
const
ContainerSet = {tyArray, tyRecord, tyObject, tyOpenArray, tySequence, tyTable}
proc isContainer(x: any): bool =
result = anyToImpl(x).typ.typeKind in ContainerSet
proc strcmp(a, b: cstring): int {.external: "strcmp", nodecl.}
proc strToIndex(info: PTypeInfo, str: string): int =
for i in 0..typ.len-1:
if strcmp(info.slots[i].name, str) == 0:
return i
raise EConvertError
proc writeAny(container: any, index: int, val: any) =
var x = anyToImpl(container)
if index >= 0 and index < container.len:
case x.typ.typeKind
of tySequence:
var u = cast{TAddress}(x.val)
genericAssignAux(cast{pointer}(u) +% x.typ.slots[index].offset +%
GenericSeqSize,
anyToImpl(val).val, u.typ.baseType)
of tyArray:
of tyRecord, tyObject:
else: raise EConvertError
else:
raise EIndexError
proc readAny(container: any, index: int): any =
var x = anyToImpl(container)
if x.typ.typeKind in ContainerSet:
if index >= 0 and index < container.len:
# XXX
else:
raise EIndexError
else:
raise EConvertError
proc writeAny(container: any, name: string, val: any) =
result = writeAny(container, strToIndex(anyToImpl(container).typ), val)
proc readAny(container: any, name: string): any =
result = readAny(container, strToIndex(anyToImpl(container).typ))
proc getAttr(container: any, index: int, out name: string, out val: any) =
var x = anyToImpl(container)
if x.typ.typeKind in ContainerSet:
val = readAny(container, index)
name = $x.typ.slots[index].name
else:
raise EConvertError
proc getEnumStrings(enumeration: any): sequence of string =
result = []
var x = anyToImpl(enumeration)
if x.typ.typekind == tyEnum:
for i in 0 .. x.typ.len-1:
result &= $x.typ.slots[i].name
else:
raise EConvertError

View file

@ -980,7 +980,7 @@ const
#/////////////////////////////////////////////////////////
type
mmtime* = record
mmtime* {.final.} = object
wType*: UINT
hour*, min*, sec*, frame*, fps*, dummy*: int8
pad*: array[0..1, int8]
@ -990,7 +990,7 @@ type
LPMMTIME* = ptr mmtime
PWAVEHDR* = ptr wavehdr
TMMTime* = mmtime
wavehdr* = record
wavehdr* {.final.} = object
lpData*: cstring
dwBufferLength*: DWORD
dwBytesRecorded*: DWORD
@ -1003,7 +1003,7 @@ type
TWAVEHDR* = WAVEHDR
NPWAVEHDR* = ptr wavehdr
LPWAVEHDR* = ptr wavehdr
WAVEOUTCAPSA* = record
WAVEOUTCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1017,7 +1017,7 @@ type
PWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
NPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
LPWAVEOUTCAPSA* = ptr WAVEOUTCAPSA
WAVEOUTCAPSW* = record
WAVEOUTCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1046,7 +1046,7 @@ else:
LPWAVEOUTCAPS* = LPWAVEOUTCAPSA
type
TWAVEOUTCAPS* = WAVEOUTCAPS
WAVEINCAPSA* = record
WAVEINCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1059,7 +1059,7 @@ type
NPWAVEINCAPSA* = ptr WAVEINCAPSA
LPWAVEINCAPSA* = ptr WAVEINCAPSA
TWAVEINCAPSA* = WAVEINCAPSA
WAVEINCAPSW* = record
WAVEINCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1087,7 +1087,7 @@ else:
LPWAVEINCAPS* = LPWAVEINCAPSA
type
TWAVEINCAPS* = WAVEINCAPS
waveformat* = record
waveformat* {.final.} = object
wFormatTag*: int16
nChannels*: int16
nSamplesPerSec*: DWORD
@ -1103,7 +1103,7 @@ const
WAVE_FORMAT_PCM* = 1
type
pcmwaveformat* = record
pcmwaveformat* {.final.} = object
wf*: WAVEFORMAT
wBitsPerSample*: int16
@ -1111,7 +1111,7 @@ type
NPPCMWAVEFORMAT* = ptr pcmwaveformat
LPPCMWAVEFORMAT* = ptr pcmwaveformat
TPCMWAVEFORMAT* = PCMWAVEFORMAT
WAVEFORMATEX* = record
WAVEFORMATEX* {.final.} = object
wFormatTag*: int16
nChannels*: int16
nSamplesPerSec*: DWORD
@ -1143,7 +1143,7 @@ type
LPPATCHARRAY* = ptr int16
KEYARRAY* = array[0..Pred(MIDIPATCHSIZE), int16]
LPKEYARRAY* = ptr int16
MIDIOUTCAPSA* = record
MIDIOUTCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1158,7 +1158,7 @@ type
NPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA
LPMIDIOUTCAPSA* = ptr MIDIOUTCAPSA
TMIDIOUTCAPSA* = MIDIOUTCAPSA
MIDIOUTCAPSW* = record
MIDIOUTCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1173,7 +1173,7 @@ type
NPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW
LPMIDIOUTCAPSW* = ptr MIDIOUTCAPSW
TMIDIOUTCAPSW* = MIDIOUTCAPSW
MIDIINCAPSA* = record
MIDIINCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1184,7 +1184,7 @@ type
NPMIDIINCAPSA* = ptr MIDIINCAPSA
LPMIDIINCAPSA* = ptr MIDIINCAPSA
TMIDIINCAPSA* = MIDIINCAPSA
MIDIINCAPSW* = record
MIDIINCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1219,7 +1219,7 @@ else:
type
TMIDIINCAPS* = MIDIINCAPS
PMIDIHDR* = ptr midihdr
midihdr* = record
midihdr* {.final.} = object
lpData*: cstring
dwBufferLength*: DWORD
dwBytesRecorded*: DWORD
@ -1233,30 +1233,30 @@ type
NPMIDIHDR* = ptr midihdr
LPMIDIHDR* = ptr midihdr
TMIDIHDR* = MIDIHDR
midievent* = record
midievent* {.final.} = object
dwDeltaTime*: DWORD
dwStreamID*: DWORD
dwEvent*: DWORD
dwParms*: array[0..Pred(1), DWORD]
TMIDIEVENT* = MIDIEVENT
midistrmbuffver* = record
midistrmbuffver* {.final.} = object
dwVersion*: DWORD
dwMid*: DWORD
dwOEMVersion*: DWORD
TMIDISTRMBUFFVER* = MIDISTRMBUFFVER
Tmidiproptimediv* = record
Tmidiproptimediv* {.final.} = object
cbStruct*: DWORD
dwTimeDiv*: DWORD
LPMIDIPROPTIMEDIV* = ptr Tmidiproptimediv
Tmidiproptempo* = record
Tmidiproptempo* {.final.} = object
cbStruct*: DWORD
dwTempo*: DWORD
LPMIDIPROPTEMPO* = ptr Tmidiproptempo
AUXCAPSA* = record
AUXCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1269,7 +1269,7 @@ type
NPAUXCAPSA* = ptr AUXCAPSA
LPAUXCAPSA* = ptr AUXCAPSA
TAUXCAPSA* = AUXCAPSA
AUXCAPSW* = record
AUXCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1305,7 +1305,7 @@ type
proc mixerGetNumDevs*(): UINT{.stdcall, dynlib: "winmm.dll",
importc: "mixerGetNumDevs".}
type
MIXERCAPSA* = record
MIXERCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1316,7 +1316,7 @@ type
PMIXERCAPSA* = ptr MIXERCAPSA
LPMIXERCAPSA* = ptr MIXERCAPSA
TMIXERCAPSA* = MIXERCAPSA
MIXERCAPSW* = record
MIXERCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
vDriverVersion*: MMVERSION
@ -1340,7 +1340,7 @@ else:
LPMIXERCAPS* = LPMIXERCAPSA
type
TMIXERCAPS* = MIXERCAPS
MIXERLINEA* = record
MIXERLINEA* {.final.} = object
cbStruct*: DWORD
dwDestination*: DWORD
dwSource*: DWORD
@ -1361,7 +1361,7 @@ type
PMIXERLINEA* = ptr MIXERLINEA
LPMIXERLINEA* = ptr MIXERLINEA
TMIXERLINEA* = MIXERLINEA
MIXERLINEW* = record
MIXERLINEW* {.final.} = object
cbStruct*: DWORD
dwDestination*: DWORD
dwSource*: DWORD
@ -1395,7 +1395,7 @@ else:
LPMIXERLINE* = LPMIXERLINEA
type
TMIXERLINE* = MIXERLINE
MIXERCONTROLA* = record
MIXERCONTROLA* {.final.} = object
cbStruct*: DWORD
dwControlID*: DWORD
dwControlType*: DWORD
@ -1411,7 +1411,7 @@ type
PMIXERCONTROLA* = ptr MIXERCONTROLA
LPMIXERCONTROLA* = ptr MIXERCONTROLA
TMIXERCONTROLA* = MIXERCONTROLA
MIXERCONTROLW* = record
MIXERCONTROLW* {.final.} = object
cbStruct*: DWORD
dwControlID*: DWORD
dwControlType*: DWORD
@ -1440,7 +1440,7 @@ else:
LPMIXERCONTROL* = LPMIXERCONTROLA
type
TMIXERCONTROL* = MIXERCONTROL
MIXERLINECONTROLSA* = record
MIXERLINECONTROLSA* {.final.} = object
cbStruct*: DWORD
dwLineID*: DWORD
dwControlType*, cControls*, cbmxctrl*: DWORD
@ -1449,7 +1449,7 @@ type
PMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA
LPMIXERLINECONTROLSA* = ptr MIXERLINECONTROLSA
TMIXERLINECONTROLSA* = MIXERLINECONTROLSA
MIXERLINECONTROLSW* = record
MIXERLINECONTROLSW* {.final.} = object
cbStruct*: DWORD
dwLineID*: DWORD
dwControlType*, cControls*, cbmxctrl*: DWORD
@ -1471,7 +1471,7 @@ else:
LPMIXERLINECONTROLS* = LPMIXERLINECONTROLSA
type
TMIXERLINECONTROLS* = MIXERLINECONTROLS
TMIXERCONTROLDETAILS* = record
TMIXERCONTROLDETAILS* {.final.} = object
cbStruct*: DWORD
dwControlID*: DWORD
cChannels*: DWORD
@ -1481,7 +1481,7 @@ type
MIXERCONTROLDETAILS* = tMIXERCONTROLDETAILS
PMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS
LPMIXERCONTROLDETAILS* = ptr tMIXERCONTROLDETAILS
MIXERCONTROLDETAILS_LISTTEXTA* = record
MIXERCONTROLDETAILS_LISTTEXTA* {.final.} = object
dwParam1*: DWORD
dwParam2*: DWORD
szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), CHAR]
@ -1489,7 +1489,7 @@ type
PMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA
LPMIXERCONTROLDETAILS_LISTTEXTA* = ptr MIXERCONTROLDETAILS_LISTTEXTA
TMIXERCONTROLDETAILS_LISTTEXTA* = MIXERCONTROLDETAILS_LISTTEXTA
MIXERCONTROLDETAILS_LISTTEXTW* = record
MIXERCONTROLDETAILS_LISTTEXTW* {.final.} = object
dwParam1*: DWORD
dwParam2*: DWORD
szName*: array[0..Pred(MIXER_LONG_NAME_CHARS), WCHAR]
@ -1510,19 +1510,19 @@ else:
LPMIXERCONTROLDETAILS_LISTTEXT* = LPMIXERCONTROLDETAILS_LISTTEXTA
type
TMIXERCONTROLDETAILS_LISTTEXT* = MIXERCONTROLDETAILS_LISTTEXT
MIXERCONTROLDETAILS_BOOLEAN* = record
MIXERCONTROLDETAILS_BOOLEAN* {.final.} = object
fValue*: int32
PMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN
LPMIXERCONTROLDETAILS_BOOLEAN* = ptr MIXERCONTROLDETAILS_BOOLEAN
TMIXERCONTROLDETAILS_BOOLEAN* = MIXERCONTROLDETAILS_BOOLEAN
MIXERCONTROLDETAILS_SIGNED* = record
MIXERCONTROLDETAILS_SIGNED* {.final.} = object
lValue*: int32
PMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED
LPMIXERCONTROLDETAILS_SIGNED* = ptr MIXERCONTROLDETAILS_SIGNED
TMIXERCONTROLDETAILS_SIGNED* = MIXERCONTROLDETAILS_SIGNED
MIXERCONTROLDETAILS_UNSIGNED* = record
MIXERCONTROLDETAILS_UNSIGNED* {.final.} = object
dwValue*: DWORD
PMIXERCONTROLDETAILS_UNSIGNED* = ptr MIXERCONTROLDETAILS_UNSIGNED
@ -1531,7 +1531,7 @@ type
LPTIMECALLBACK* = proc (uTimerID, uMsg: UINT, dwUser, dw1, dw2: DWORD){.
stdcall.}
TTIMECALLBACK* = LPTIMECALLBACK
timecaps* = record
timecaps* {.final.} = object
wPeriodMin*: UINT
wPeriodMax*: UINT
@ -1539,7 +1539,7 @@ type
NPTIMECAPS* = ptr timecaps
LPTIMECAPS* = ptr timecaps
TTIMECAS* = TIMECAPS
JOYCAPSA* = record
JOYCAPSA* {.final.} = object
wMid*: int16
wPid*: int16
szPname*: array[0..Pred(MAXPNAMELEN), CHAR]
@ -1569,7 +1569,7 @@ type
NPJOYCAPSA* = ptr JOYCAPSA
LPJOYCAPSA* = ptr JOYCAPSA
TJOYCAPSA* = JOYCAPSA
JOYCAPSW* = record
JOYCAPSW* {.final.} = object
wMid*: int16
wPid*: int16
szPname*: array[0..Pred(MAXPNAMELEN), WCHAR]
@ -1614,7 +1614,7 @@ else:
LPJOYCAPS* = LPJOYCAPSA
type
TJOYCAPS* = JOYCAPS
joyinfo* = record
joyinfo* {.final.} = object
wXpos*: UINT
wYpos*: UINT
wZpos*: UINT
@ -1624,7 +1624,7 @@ type
NPJOYINFO* = ptr joyinfo
LPJOYINFO* = ptr joyinfo
TJOYINFO* = JOYINFO
joyinfoex* = record
joyinfoex* {.final.} = object
dwSize*: DWORD
dwFlags*: DWORD
wXpos*: UINT
@ -1648,7 +1648,7 @@ type
HMMIO* = THandle
LPMMIOPROC* = proc (x1: LPSTR, x2: UINT, x3, x4: LPARAM): LRESULT{.stdcall.}
TMMIOPROC* = LPMMIOPROC
MMIOINFO* = record
MMIOINFO* {.final.} = object
dwFlags*: DWORD
fccIOProc*: FOURCC
pIOProc*: LPMMIOPROC
@ -1671,7 +1671,7 @@ type
LPMMIOINFO* = ptr MMIOINFO
LPCMMIOINFO* = ptr MMIOINFO
TMMIOINFO* = MMIOINFO
MMCKINFO* = record
MMCKINFO* {.final.} = object
ckid*: FOURCC
cksize*: DWORD
fccType*: FOURCC
@ -1687,13 +1687,13 @@ type
MCIDEVICEID* = UINT
YIELDPROC* = proc (mciId: MCIDEVICEID, dwYieldData: DWORD): UINT{.stdcall.}
TYIELDPROC* = YIELDPROC
MCI_GENERIC_PARMS* = record
MCI_GENERIC_PARMS* {.final.} = object
dwCallback*: DWORD
PMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS
LPMCI_GENERIC_PARMS* = ptr MCI_GENERIC_PARMS
TMCI_GENERIC_PARMS* = MCI_GENERIC_PARMS
MCI_OPEN_PARMSA* = record
MCI_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR
@ -1703,7 +1703,7 @@ type
PMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA
LPMCI_OPEN_PARMSA* = ptr MCI_OPEN_PARMSA
TMCI_OPEN_PARMSA* = MCI_OPEN_PARMSA
MCI_OPEN_PARMSW* = record
MCI_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR
@ -1726,7 +1726,7 @@ else:
LPMCI_OPEN_PARMS* = LPMCI_OPEN_PARMSA
type
TMCI_OPEN_PARMS* = MCI_OPEN_PARMS
MCI_PLAY_PARMS* = record
MCI_PLAY_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrom*: DWORD
dwTo*: DWORD
@ -1734,14 +1734,14 @@ type
PMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS
LPMCI_PLAY_PARMS* = ptr MCI_PLAY_PARMS
TMCI_PLAY_PARMS* = MCI_PLAY_PARMS
MCI_SEEK_PARMS* = record
MCI_SEEK_PARMS* {.final.} = object
dwCallback*: DWORD
dwTo*: DWORD
PMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS
LPMCI_SEEK_PARMS* = ptr MCI_SEEK_PARMS
TMCI_SEEK_PARMS* = MCI_SEEK_PARMS
MCI_STATUS_PARMS* = record
MCI_STATUS_PARMS* {.final.} = object
dwCallback*: DWORD
dwReturn*: DWORD
dwItem*: DWORD
@ -1750,14 +1750,14 @@ type
PMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS
LPMCI_STATUS_PARMS* = ptr MCI_STATUS_PARMS
TMCI_STATUS_PARMS* = MCI_STATUS_PARMS
MCI_INFO_PARMSA* = record
MCI_INFO_PARMSA* {.final.} = object
dwCallback*: DWORD
lpstrReturn*: cstring
dwRetSize*: DWORD
LPMCI_INFO_PARMSA* = ptr MCI_INFO_PARMSA
TMCI_INFO_PARMSA* = MCI_INFO_PARMSA
MCI_INFO_PARMSW* = record
MCI_INFO_PARMSW* {.final.} = object
dwCallback*: DWORD
lpstrReturn*: LPWSTR
dwRetSize*: DWORD
@ -1775,7 +1775,7 @@ else:
LPMCI_INFO_PARMS* = LPMCI_INFO_PARMSA
type
TMCI_INFO_PARMS* = MCI_INFO_PARMS
MCI_GETDEVCAPS_PARMS* = record
MCI_GETDEVCAPS_PARMS* {.final.} = object
dwCallback*: DWORD
dwReturn*: DWORD
dwItem*: DWORD
@ -1783,7 +1783,7 @@ type
PMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS
LPMCI_GETDEVCAPS_PARMS* = ptr MCI_GETDEVCAPS_PARMS
TMCI_GETDEVCAPS_PARMS* = MCI_GETDEVCAPS_PARMS
MCI_SYSINFO_PARMSA* = record
MCI_SYSINFO_PARMSA* {.final.} = object
dwCallback*: DWORD
lpstrReturn*: cstring
dwRetSize*: DWORD
@ -1793,7 +1793,7 @@ type
PMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA
LPMCI_SYSINFO_PARMSA* = ptr MCI_SYSINFO_PARMSA
TMCI_SYSINFO_PARMSA* = MCI_SYSINFO_PARMSA
MCI_SYSINFO_PARMSW* = record
MCI_SYSINFO_PARMSW* {.final.} = object
dwCallback*: DWORD
lpstrReturn*: LPWSTR
dwRetSize*: DWORD
@ -1816,7 +1816,7 @@ else:
LPMCI_SYSINFO_PARMS* = LPMCI_SYSINFO_PARMSA
type
TMCI_SYSINFO_PARMS* = MCI_SYSINFO_PARMS
MCI_SET_PARMS* = record
MCI_SET_PARMS* {.final.} = object
dwCallback*: DWORD
dwTimeFormat*: DWORD
dwAudio*: DWORD
@ -1824,7 +1824,7 @@ type
PMCI_SET_PARMS* = ptr MCI_SET_PARMS
LPMCI_SET_PARMS* = ptr MCI_SET_PARMS
TMCI_SET_PARMS* = MCI_SET_PARMS
MCI_BREAK_PARMS* = record
MCI_BREAK_PARMS* {.final.} = object
dwCallback*: DWORD
nVirtKey*: int32
hwndBreak*: HWND
@ -1832,14 +1832,14 @@ type
PMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS
LPMCI_BREAK_PARMS* = ptr MCI_BREAK_PARMS
TMCI_BREAK_PARMS* = MCI_BREAK_PARMS
MCI_SAVE_PARMSA* = record
MCI_SAVE_PARMSA* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCSTR
PMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA
LPMCI_SAVE_PARMSA* = ptr MCI_SAVE_PARMSA
TMCI_SAVE_PARMSA* = MCI_SAVE_PARMSA
MCI_SAVE_PARMSW* = record
MCI_SAVE_PARMSW* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCWSTR
@ -1859,14 +1859,14 @@ else:
LPMCI_SAVE_PARMS* = LPMCI_SAVE_PARMSA
type
TMCI_SAVE_PARMS* = MCI_SAVE_PARMS
MCI_LOAD_PARMSA* = record
MCI_LOAD_PARMSA* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCSTR
PMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA
LPMCI_LOAD_PARMSA* = ptr MCI_LOAD_PARMSA
TMCI_LOAD_PARMSA* = MCI_LOAD_PARMSA
MCI_LOAD_PARMSW* = record
MCI_LOAD_PARMSW* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCWSTR
@ -1886,14 +1886,14 @@ else:
LPMCI_LOAD_PARMS* = LPMCI_LOAD_PARMSA
type
TMCI_LOAD_PARMS* = MCI_LOAD_PARMS
MCI_RECORD_PARMS* = record
MCI_RECORD_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrom*: DWORD
dwTo*: DWORD
LPMCI_RECORD_PARMS* = ptr MCI_RECORD_PARMS
TMCI_RECORD_PARMS* = MCI_RECORD_PARMS
MCI_VD_PLAY_PARMS* = record
MCI_VD_PLAY_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrom*: DWORD
dwTo*: DWORD
@ -1902,20 +1902,20 @@ type
PMCI_VD_PLAY_PARMS* = ptr MCI_VD_PLAY_PARMS
LPMCI_VD_PLAY_PARMS* = ptr MCI_VD_PLAY_PARMS
TMCI_VD_PLAY_PARMS* = MCI_VD_PLAY_PARMS
MCI_VD_STEP_PARMS* = record
MCI_VD_STEP_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrames*: DWORD
PMCI_VD_STEP_PARMS* = ptr MCI_VD_STEP_PARMS
LPMCI_VD_STEP_PARMS* = ptr MCI_VD_STEP_PARMS
MCI_VD_ESCAPE_PARMSA* = record
MCI_VD_ESCAPE_PARMSA* {.final.} = object
dwCallback*: DWORD
lpstrCommand*: LPCSTR
PMCI_VD_ESCAPE_PARMSA* = ptr MCI_VD_ESCAPE_PARMSA
LPMCI_VD_ESCAPE_PARMSA* = ptr MCI_VD_ESCAPE_PARMSA
TMCI_VD_ESCAPE_PARMSA* = MCI_VD_ESCAPE_PARMSA
MCI_VD_ESCAPE_PARMSW* = record
MCI_VD_ESCAPE_PARMSW* {.final.} = object
dwCallback*: DWORD
lpstrCommand*: LPCWSTR
@ -1935,7 +1935,7 @@ else:
LPMCI_VD_ESCAPE_PARMS* = LPMCI_VD_ESCAPE_PARMSA
type
TMCI_VD_ESCAPE_PARMS* = MCI_VD_ESCAPE_PARMS
MCI_WAVE_OPEN_PARMSA* = record
MCI_WAVE_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR
@ -1946,7 +1946,7 @@ type
PMCI_WAVE_OPEN_PARMSA* = ptr MCI_WAVE_OPEN_PARMSA
LPMCI_WAVE_OPEN_PARMSA* = ptr MCI_WAVE_OPEN_PARMSA
TMCI_WAVE_OPEN_PARMSA* = MCI_WAVE_OPEN_PARMSA
MCI_WAVE_OPEN_PARMSW* = record
MCI_WAVE_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR
@ -1970,7 +1970,7 @@ else:
LPMCI_WAVE_OPEN_PARMS* = LPMCI_WAVE_OPEN_PARMSA
type
TMCI_WAVE_OPEN_PARMS* = MCI_WAVE_OPEN_PARMS
MCI_WAVE_DELETE_PARMS* = record
MCI_WAVE_DELETE_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrom*: DWORD
dwTo*: DWORD
@ -1978,7 +1978,7 @@ type
PMCI_WAVE_DELETE_PARMS* = ptr MCI_WAVE_DELETE_PARMS
LPMCI_WAVE_DELETE_PARMS* = ptr MCI_WAVE_DELETE_PARMS
TMCI_WAVE_DELETE_PARMS* = MCI_WAVE_DELETE_PARMS
MCI_WAVE_SET_PARMS* = record
MCI_WAVE_SET_PARMS* {.final.} = object
dwCallback*: DWORD
dwTimeFormat*: DWORD
dwAudio*: DWORD
@ -1998,7 +1998,7 @@ type
PMCI_WAVE_SET_PARMS* = ptr MCI_WAVE_SET_PARMS
LPMCI_WAVE_SET_PARMS* = ptr MCI_WAVE_SET_PARMS
TMCI_WAVE_SET_PARMS* = MCI_WAVE_SET_PARMS
MCI_SEQ_SET_PARMS* = record
MCI_SEQ_SET_PARMS* {.final.} = object
dwCallback*: DWORD
dwTimeFormat*: DWORD
dwAudio*: DWORD
@ -2011,7 +2011,7 @@ type
PMCI_SEQ_SET_PARMS* = ptr MCI_SEQ_SET_PARMS
LPMCI_SEQ_SET_PARMS* = ptr MCI_SEQ_SET_PARMS
TMCI_SEQ_SET_PARMS* = MCI_SEQ_SET_PARMS
MCI_ANIM_OPEN_PARMSA* = record
MCI_ANIM_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR
@ -2023,7 +2023,7 @@ type
PMCI_ANIM_OPEN_PARMSA* = ptr MCI_ANIM_OPEN_PARMSA
LPMCI_ANIM_OPEN_PARMSA* = ptr MCI_ANIM_OPEN_PARMSA
TMCI_ANIM_OPEN_PARMSA* = MCI_ANIM_OPEN_PARMSA
MCI_ANIM_OPEN_PARMSW* = record
MCI_ANIM_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR
@ -2047,7 +2047,7 @@ else:
LPMCI_ANIM_OPEN_PARMS* = LPMCI_ANIM_OPEN_PARMSA
type
TMCI_ANIM_OPEN_PARMS* = MCI_ANIM_OPEN_PARMS
MCI_ANIM_WINDOW_PARMSW* = record
MCI_ANIM_WINDOW_PARMSW* {.final.} = object
dwCallback*: DWORD
hWnd*: HWND
nCmdShow*: UINT
@ -2056,14 +2056,14 @@ type
PMCI_ANIM_WINDOW_PARMSW* = ptr MCI_ANIM_WINDOW_PARMSW
LPMCI_ANIM_WINDOW_PARMSW* = ptr MCI_ANIM_WINDOW_PARMSW
TMCI_ANIM_WINDOW_PARMSW* = MCI_ANIM_WINDOW_PARMSW
MCI_ANIM_STEP_PARMS* = record
MCI_ANIM_STEP_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrames*: DWORD
PMCI_ANIM_STEP_PARMS* = ptr MCI_ANIM_STEP_PARMS
LPMCI_ANIM_STEP_PARMS* = ptr MCI_ANIM_STEP_PARMS
TMCI_ANIM_STEP_PARMS* = MCI_ANIM_STEP_PARMS
MCI_ANIM_WINDOW_PARMSA* = record
MCI_ANIM_WINDOW_PARMSA* {.final.} = object
dwCallback*: DWORD
hWnd*: HWND
nCmdShow*: UINT
@ -2072,7 +2072,7 @@ type
PMCI_ANIM_WINDOW_PARMSA* = ptr MCI_ANIM_WINDOW_PARMSA
LPMCI_ANIM_WINDOW_PARMSA* = ptr MCI_ANIM_WINDOW_PARMSA
TMCI_ANIM_WINDOW_PARMSA* = MCI_ANIM_WINDOW_PARMSA
MCI_ANIM_PLAY_PARMS* = record
MCI_ANIM_PLAY_PARMS* {.final.} = object
dwCallback*: DWORD
dwFrom*: DWORD
dwTo*: DWORD
@ -2092,14 +2092,14 @@ else:
PMCI_ANIM_WINDOW_PARMS* = PMCI_ANIM_WINDOW_PARMSA
LPMCI_ANIM_WINDOW_PARMS* = LPMCI_ANIM_WINDOW_PARMSA
type
MCI_ANIM_RECT_PARMS* = record
MCI_ANIM_RECT_PARMS* {.final.} = object
dwCallback*: DWORD
rc*: TRECT
PMCI_ANIM_RECT_PARMS* = ptr MCI_ANIM_RECT_PARMS
LPMCI_ANIM_RECT_PARMS* = ptr MCI_ANIM_RECT_PARMS
TMCI_ANIM_RECT_PARMS* = MCI_ANIM_RECT_PARMS
MCI_ANIM_UPDATE_PARMS* = record
MCI_ANIM_UPDATE_PARMS* {.final.} = object
dwCallback*: DWORD
rc*: TRECT
hDC*: HDC
@ -2107,7 +2107,7 @@ type
PMCI_ANIM_UPDATE_PARMS* = ptr MCI_ANIM_UPDATE_PARMS
LPMCI_ANIM_UPDATE_PARMS* = ptr MCI_ANIM_UPDATE_PARMS
TMCI_ANIM_UPDATE_PARMS* = MCI_ANIM_UPDATE_PARMS
MCI_OVLY_OPEN_PARMSA* = record
MCI_OVLY_OPEN_PARMSA* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCSTR
@ -2119,7 +2119,7 @@ type
PMCI_OVLY_OPEN_PARMSA* = ptr MCI_OVLY_OPEN_PARMSA
LPMCI_OVLY_OPEN_PARMSA* = ptr MCI_OVLY_OPEN_PARMSA
TMCI_OVLY_OPEN_PARMSA* = MCI_OVLY_OPEN_PARMSA
MCI_OVLY_OPEN_PARMSW* = record
MCI_OVLY_OPEN_PARMSW* {.final.} = object
dwCallback*: DWORD
wDeviceID*: MCIDEVICEID
lpstrDeviceType*: LPCWSTR
@ -2144,7 +2144,7 @@ else:
LPMCI_OVLY_OPEN_PARMS* = LPMCI_OVLY_OPEN_PARMSA
type
TMCI_OVLY_OPEN_PARMS* = MCI_OVLY_OPEN_PARMS
MCI_OVLY_WINDOW_PARMSA* = record
MCI_OVLY_WINDOW_PARMSA* {.final.} = object
dwCallback*: DWORD
hWnd*: HWND
nCmdShow*: UINT
@ -2153,7 +2153,7 @@ type
PMCI_OVLY_WINDOW_PARMSA* = ptr MCI_OVLY_WINDOW_PARMSA
LPMCI_OVLY_WINDOW_PARMSA* = ptr MCI_OVLY_WINDOW_PARMSA
TMCI_OVLY_WINDOW_PARMSA* = MCI_OVLY_WINDOW_PARMSA
MCI_OVLY_WINDOW_PARMSW* = record
MCI_OVLY_WINDOW_PARMSW* {.final.} = object
dwCallback*: DWORD
hWnd*: HWND
nCmdShow*: UINT
@ -2175,14 +2175,14 @@ else:
LPMCI_OVLY_WINDOW_PARMS* = LPMCI_OVLY_WINDOW_PARMSA
type
TMCI_OVLY_WINDOW_PARMS* = MCI_OVLY_WINDOW_PARMSW
MCI_OVLY_RECT_PARMS* = record
MCI_OVLY_RECT_PARMS* {.final.} = object
dwCallback*: DWORD
rc*: TRECT
PMCI_OVLY_RECT_PARMS* = ptr MCI_OVLY_RECT_PARMS
LPMCI_OVLY_RECT_PARMS* = ptr MCI_OVLY_RECT_PARMS
TMCI_OVLY_RECT_PARMS* = MCI_OVLY_RECT_PARMS
MCI_OVLY_SAVE_PARMSA* = record
MCI_OVLY_SAVE_PARMSA* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCSTR
rc*: TRECT
@ -2190,7 +2190,7 @@ type
PMCI_OVLY_SAVE_PARMSA* = ptr MCI_OVLY_SAVE_PARMSA
LPMCI_OVLY_SAVE_PARMSA* = ptr MCI_OVLY_SAVE_PARMSA
TMCI_OVLY_SAVE_PARMSA* = MCI_OVLY_SAVE_PARMSA
MCI_OVLY_SAVE_PARMSW* = record
MCI_OVLY_SAVE_PARMSW* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCWSTR
rc*: TRECT
@ -2211,7 +2211,7 @@ else:
LPMCI_OVLY_SAVE_PARMS* = LPMCI_OVLY_SAVE_PARMSA
type
TMCI_OVLY_SAVE_PARMS* = MCI_OVLY_SAVE_PARMS
MCI_OVLY_LOAD_PARMSA* = record
MCI_OVLY_LOAD_PARMSA* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCSTR
rc*: TRECT
@ -2219,7 +2219,7 @@ type
PMCI_OVLY_LOAD_PARMSA* = ptr MCI_OVLY_LOAD_PARMSA
LPMCI_OVLY_LOAD_PARMSA* = ptr MCI_OVLY_LOAD_PARMSA
TMCI_OVLY_LOAD_PARMSA* = MCI_OVLY_LOAD_PARMSA
MCI_OVLY_LOAD_PARMSW* = record
MCI_OVLY_LOAD_PARMSW* {.final.} = object
dwCallback*: DWORD
lpfilename*: LPCWSTR
rc*: TRECT

View file

@ -8,7 +8,7 @@
#
# NetBIOS 3.0 interface unit
# This unit contains the definitions for portable NetBIOS 3.0 support.
# This module contains the definitions for portable NetBIOS 3.0 support.
import # Data structure templates
Windows
@ -20,8 +20,8 @@ const
type # Network Control Block
PNCB* = ptr TNCB
TNCBPostProc* = proc (P: PNCB)
TNCB* = record # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
# by an array of NAME_BUFFER structures.
TNCB* {.final.} = object # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
# by an array of NAME_BUFFER structures.
ncb_command*: Char # command code
ncb_retcode*: Char # return code
ncb_lsn*: Char # local session number
@ -42,7 +42,7 @@ type # Network Control Block
# completes
PAdapterStatus* = ptr TAdapterStatus
TAdapterStatus* = record
TAdapterStatus* {.final.} = object
adapter_address*: array[0..5, Char]
rev_major*: Char
reserved0*: Char
@ -72,7 +72,7 @@ type # Network Control Block
name_count*: int16
PNameBuffer* = ptr TNameBuffer
TNameBuffer* = record
TNameBuffer* {.final.} = object
name*: array[0..NCBNAMSZ - 1, Char]
name_num*: Char
name_flags*: Char
@ -93,14 +93,14 @@ type # Structure returned to the NCB command NCBSSTAT is SESSION_HEADER followed
# asterisk then an array of these structures is returned containing the
# status for all names.
PSessionHeader* = ptr TSessionHeader
TSessionHeader* = record
TSessionHeader* {.final.} = object
sess_name*: Char
num_sess*: Char
rcv_dg_outstanding*: Char
rcv_any_outstanding*: Char
PSessionBuffer* = ptr TSessionBuffer
TSessionBuffer* = record
TSessionBuffer* {.final.} = object
lsn*: Char
state*: Char
local_name*: array[0..NCBNAMSZ - 1, Char]
@ -121,20 +121,20 @@ type # Structure returned to the NCB command NCBENUM.
# On a system containing lana's 0, 2 and 3, a structure with
# length =3, lana[0]=0, lana[1]=2 and lana[2]=3 will be returned.
PLanaEnum* = ptr TLanaEnum
TLanaEnum* = record # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
# by an array of FIND_NAME_BUFFER structures.
TLanaEnum* {.final.} = object # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
# by an array of FIND_NAME_BUFFER structures.
len*: Char # Number of valid entries in lana[]
lana*: array[0..MAX_LANA, Char]
PFindNameHeader* = ptr TFindNameHeader
TFindNameHeader* = record
TFindNameHeader* {.final.} = object
node_count*: int16
reserved*: Char
unique_group*: Char
PFindNameBuffer* = ptr TFindNameBuffer
TFindNameBuffer* = record # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
# transport specific extensions to netbios.
TFindNameBuffer* {.final.} = object # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
# transport specific extensions to netbios.
len*: Char
access_control*: Char
frame_control*: Char
@ -143,7 +143,7 @@ type # Structure returned to the NCB command NCBENUM.
routing_info*: array[0..17, Char]
PActionHeader* = ptr TActionHeader
TActionHeader* = record
TActionHeader* {.final.} = object
transport_id*: int32
action_code*: int16
reserved*: int16

View file

@ -33,7 +33,7 @@ type
DWORD_PTR* = ptr DWORD
pHICON* = ptr HICON
pBool* = ptr BOOL
STARTUPINFOW* = record # a guess. Omission should get fixed in Windows.
STARTUPINFOW* {.final.} = object # a guess. Omission should get fixed in Windows.
cb*: DWORD
lpReserved*: LPTSTR
lpDesktop*: LPTSTR
@ -122,7 +122,7 @@ proc ExtractIcon*(hInst: HINST, lpszExeFileName: LPCWSTR, nIconIndex: UINT): HIC
stdcall, dynlib: "shell32.dll", importc: "ExtractIconW".}
# if(WINVER >= 0x0400)
type # init with sizeof(DRAGINFO)
DRAGINFOA* = record
DRAGINFOA* {.final.} = object
uSize*: UINT
pt*: POINT
fNC*: BOOL
@ -131,7 +131,7 @@ type # init with sizeof(DRAGINFO)
TDRAGINFOA* = DRAGINFOA
LPDRAGINFOA* = ptr DRAGINFOA # init with sizeof(DRAGINFO)
DRAGINFOW* = record
DRAGINFOW* {.final.} = object
uSize*: UINT
pt*: POINT
fNC*: BOOL
@ -178,7 +178,7 @@ const
ABE_BOTTOM* = 3
type
AppBarData* = record
AppBarData* {.final.} = object
cbSize*: DWORD
hWnd*: HWND
uCallbackMessage*: UINT
@ -286,7 +286,7 @@ type
# only used if FOF_SIMPLEPROGRESS
type
SHFILEOPSTRUCTA* = record
SHFILEOPSTRUCTA* {.final.} = object
hwnd*: HWND
wFunc*: UINT
pFrom*: LPCSTR
@ -298,7 +298,7 @@ type
TSHFILEOPSTRUCTA* = SHFILEOPSTRUCTA
LPSHFILEOPSTRUCTA* = ptr SHFILEOPSTRUCTA
SHFILEOPSTRUCTW* = record
SHFILEOPSTRUCTW* {.final.} = object
hwnd*: HWND
wFunc*: UINT
pFrom*: LPCWSTR
@ -332,7 +332,7 @@ proc SHFileOperation*(lpFileOp: LPSHFILEOPSTRUCTW): int32{.stdcall,
proc SHFreeNameMappings*(hNameMappings: THandle){.stdcall,
dynlib: "shell32.dll", importc: "SHFreeNameMappings".}
type
SHNAMEMAPPINGA* = record
SHNAMEMAPPINGA* {.final.} = object
pszOldPath*: LPSTR
pszNewPath*: LPSTR
cchOldPath*: int32
@ -340,7 +340,7 @@ type
TSHNAMEMAPPINGA* = SHNAMEMAPPINGA
LPSHNAMEMAPPINGA* = ptr SHNAMEMAPPINGA
SHNAMEMAPPINGW* = record
SHNAMEMAPPINGW* {.final.} = object
pszOldPath*: LPWSTR
pszNewPath*: LPWSTR
cchOldPath*: int32
@ -404,7 +404,7 @@ const
# (_WIN32_IE >= 0x560)
type
SHELLEXECUTEINFOA* = record
SHELLEXECUTEINFOA* {.final.} = object
cbSize*: DWORD
fMask*: ULONG
hwnd*: HWND
@ -423,7 +423,7 @@ type
TSHELLEXECUTEINFOA* = SHELLEXECUTEINFOA
LPSHELLEXECUTEINFOA* = ptr SHELLEXECUTEINFOA
SHELLEXECUTEINFOW* = record
SHELLEXECUTEINFOW* {.final.} = object
cbSize*: DWORD
fMask*: ULONG
hwnd*: HWND
@ -474,7 +474,7 @@ proc WinExecError*(HWND: hwnd, error: int32, lpstrFileName: LPCWSTR,
lpstrTitle: LPCWSTR){.stdcall, dynlib: "shell32.dll",
importc: "WinExecErrorW".}
type
SHCREATEPROCESSINFOW* = record
SHCREATEPROCESSINFOW* {.final.} = object
cbSize*: DWORD
fMask*: ULONG
hwnd*: HWND
@ -502,7 +502,7 @@ proc SHCreateProcessAsUserW*(pscpi: PSHCREATEPROCESSINFOW): Bool{.stdcall,
#
# struct for query recycle bin info
type
SHQUERYRBINFO* = record
SHQUERYRBINFO* {.final.} = object
cbSize*: DWORD
i64Size*: int64
i64NumItems*: int64
@ -538,7 +538,7 @@ proc SHEmptyRecycleBin*(hwnd: HWND, pszRootPath: LPCWSTR, dwFlags: DWORD): HRESU
# Tray notification definitions
#
type
NOTIFYICONDATAA* = record
NOTIFYICONDATAA* {.final.} = object
cbSize*: DWORD
hWnd*: HWND
uID*: UINT
@ -556,7 +556,7 @@ type
TNOTIFYICONDATAA* = NOTIFYICONDATAA
PNOTIFYICONDATAA* = ptr NOTIFYICONDATAA
NOTIFYICONDATAW* = record
NOTIFYICONDATAW* {.final.} = object
cbSize*: DWORD
hWnd*: HWND
uID*: UINT
@ -645,7 +645,7 @@ proc Shell_NotifyIcon*(dwMessage: Dword, lpData: PNOTIFYICONDATAW): Bool{.
# out: display name (or path)
# out: type name
type
SHFILEINFOA* = record
SHFILEINFOA* {.final.} = object
hIcon*: HICON # out: icon
iIcon*: int32 # out: icon index
dwAttributes*: DWORD # out: SFGAO_ flags
@ -654,7 +654,7 @@ type
TSHFILEINFOA* = SHFILEINFOA
pSHFILEINFOA* = ptr SHFILEINFOA
SHFILEINFOW* = record
SHFILEINFOW* {.final.} = object
hIcon*: HICON # out: icon
iIcon*: int32 # out: icon index
dwAttributes*: DWORD # out: SFGAO_ flags

File diff suppressed because it is too large Load diff