Win32 FAQ

Programming Questions
This section covers many common programming questions. Because the possible ways in which a windows program does not
work is probably provably infinite, only a small subset of the possible questions are covered here. Other useful Internet
Resources are listed near the end of the FAQ.

5.1. How do I port my 16 bit app to 32 bits?
Trying to compile your program with a 32 bit compiler is usually the first big step: fix all the errors it shows and then see if it
works when it is run. A raw API app can just be rebuilt, using PORTTOOL.EXE to help you. Using the "windowsx.h" macros
and message crackers can assist you here. Class libraries often provide the message cracking for you, so make life a bit easier.
MFC Apps can be ported fairly quickly by opening up the project in Visual C++ and rebuilding. For OWL apps, just create a
new 32 bit target or a new project with a 32 bit exe as the destination.

You may be disappointed to find little or no performance improvement, or even worse a slowdown. The latter is most likely on
Windows 95, where a lot of the OS is still 16 bits wide. The real speedup of win32 comes with higher power processors, and
Windows NT. The new features of Win32 will still benefit application son Win95, and with some extra programming (threads
& async IO) performance can be significantly improved.

5.2. Common Pitfalls in porting from 16 to 32 bits

Integers are bigger. This can break IPC and reading old files.
Fix: For legacy structures redefine int references to short
Structure alignment has changed. Causes the same problems as above.
Fix: return packing to BYTE alignment for these structures. The include files "pushpack1.h" and "poppack.h" can be
used around these structure to fix them.
0xffff is no longer equivalent to (UINT)-1. Use the macros in "limits.h"
No DIB.DRV. Use CreateDIBSection() to create a DIB which you can apply GDI calls to, and use BitBlt() to draw it
A changed comms API. Some thing like DCBs remain, but comms ports are just another type of file now, with blocking
I/O being the easiest way to wait for input.
Long file names. Make sure that MAX_PATH is used to declare all string that can hold a path, and do not assume that
file names have an 8.3 format.
The implementation of Unicode or ANSI in the Win32 API is assisted by lots of macros to bind to different actual
functions. For example TextOut is a macro mapping to TextOutA()or TextOutW(). This can cause problems in C++
when you have a member function whose name matches a windows API function as the macro renames it.
No VBX support. Actually Borland 4.5 manages this with a mixture of thunking (Win32s, win95) and inter-app message
redirection (NT3.5 onwards) .
Fix: Use OCXs instead. C++ users will need BC5.0 or VCC4.0 to use these.
Passing handles to GDI & memory objects between applications in PostMessage calls. System objects must be
duplicated using DuplicateHandle(). Memory can only be exchanged via shared memory or WM_COPYDATA
Calling DOS and other interrupts direct. You will probably find an API substitute somewhere in all the documentation,
but BIOS calls are pretty much off-limits.

5.3. How do I read/write the serial port?

Win16 used to have lots of special functions such as ReadComm() and WriteComm() to do this, but in win32 you just open a
serial port like any other file:-

//open COM1 for read and write

Standard ReadFile() and WriteFile() functions can then be used to read or write to the port. To set the port up reliably,
COMM port specific functions need to be used, so look up the online help for details on the following functions:-
GetCommModemStatus(), SetCommState(), SetCommMask(), SetupComm(), PurgeComm(), ClearCommError(),


1.Even on win95, you can use overlapped IO with a com port
2.The Signalled state of a port seems to indicates it is ready for reading or writing, even if you only opened the port

[Top of Section] [Index]

5.4. How do I read/write the parallel port?

Open it as per a serial port, using "LPT1" or "LPT2" as the port name. This works provided the device which you are talking to
uses the standard ECP/EPP protocols. If you are trying to use the parallel port as a non standard IO port, then you have to
access the port using port IO instructions -something you are not meant to do from a user mode application.
[Top of Section] [Index]

5.5. How can two programs communicate now they have separate memory spaces?

SendMessage & PostMessage
Only works for the data which can be fitted in to the two 32 bit parameters WPARAM and LPARAM, unless you can
pass a pointer to shared memory.
Easy, good for small quantities of data. Works between 16 & 32 bit programs. NB: you need to manually add it to your
16 bit header files.
OLE Automation.
Fairly easy but restricts you to automation data types and is not as fast as other methods.
Fast but requires interface declarations and the MIDL compiler.
Memory mapped files
Only for 32:32 IPC. Needs some synchronisation mechanism/objects too.
Named Pipes
Distributable, but you can't create the server side on win95.

[Top of Section] [Index]

5.6. How can two programs communicate across a network?

There are lots of ways to do this: the most popular are probably sockets and DCOM.

Powerful & cross platform, but often a bit low level. Winsock 2 provides more protocol independence so socket apps
can run over IPX, IP and other protocols. Beware of byte ordering and structure packing issues when talking to
non-Win32 platforms.
OLE Automation.
Only possible with VB4 enterprise edition at present.
Distributed COM
This is built into NT4 and available as an update for Win95 -and with all IE4 upgrades
DCE/Microsoft RPC
You need the win32 SDK to use this.
Named Pipes
Note that you can't create the server side on win95.
When broadcasting a message to all clients in a workgroup, the message is sent over every transport: clients may
therefore receive multiple copies. Design your protocol to handle this.
Using an email system such as Exchange as the transport.

[Top of Section] [Index]

5.7. How can I tell what version of windows I'm running?

With the function GetVersionEx().
[Top of Section] [Index]

5.8. How do I write a screen saver?

You look in the on line help: "Screen Savers", or in the example code which your compiler ships with for a sample saver. The
main points to know are

1.a saver is just an executable with a .scr extension
2.the setup dialog is invoked with a /c argument; otherwise the app just shows the saver.
3.when invoked with "/p hwnd" then it's preview mode

The best documentation and example code is at the Win95 Screensaver programming home page.

[Top of Section] [Index]

5.9. How do applications start up in the same place they were before windows shut down in windows 95?

Add a string value to the registry below HKEY_CURRENT_USER\Software\Windows\CurrentVersion\RunOnce
= "full command line"

and also save your window state when you handle WM_ENDSESSION, reloading your state on startup.

[Top of Section] [Index]

5.10. How do you do those pop-up menus on the right mouse button?

Traditionally this was done with a handler for WM_RBUTTONDOWN [or UP] which mapped the client co-ordinates to the
screen and then called TrackPopupMenu() passing the handle of a pop-up menu which you have created. In win95/NT3.51
onwards, you can opt to handle the message WM_CONTEXTMENU. This is generated by the system if the
WM_RBUTTON* messages are not handled by the app. This has two advantages

the co-ordinates are translated for you so that x = HIWORD(lParam), and y = LOWORD(lParam)
It works with that new button on Microsoft natural and other windows keyboards.

[Top of Section] [Index]

5.11. How do I access hardware via IO ports or mapped memory?

You can get away with port IO in user level code on Windows 95 & 98 through assembly language instructions like "__asm in
al,dx" and "_asm out dx,al" . The VC5 header file defines _outp() and _inp() functions which you can use -even if
you aren't supposed to.

For NT, or serious device access in win95, you'll need a device driver. Have a look at the device driver FAQ , or some of the
driver programming groups -none of which have the word driver in their title to improve the signal to noise ratio. (key words:
VxD and kernel mode)

The NT DDK samples you need to look at are DDK\SRC\GENERAL\{MAPMEM, PORTIO}

Doctor Dobbs Journal in May 96 had an article called DirectIO which showed how to add a device driver to tweak the NT
task protection masks so that in and out instructions are allowed in user mode code. This is an invaluable trick for non
commercial & prototype applications, but not really acceptable for shipping products. NT separates device drivers from user
code for valid reasons: performance, reliability on multi-processor systems and to enable applications to be more portable.

There are a pair of low cost shareware device drivers which claim to support device IO and interrupts from user mode code.
The commercial product WinRT from Blue Water Systems can do this and more.
[Top of Section] [Index]

5.12. How do I handle interrupts in my windows 32 program?

Usually you have to write a device driver or VxD. Writing device drivers is not as hard as it sounds -especially WDM drivers.
It just needs extra learning and a more complex debugging setup. Otherwise, follow up some of the URLS in the previous
section to see if their products meet your needs.

Some device drivers (such as the standard serial port driver) can set Event objects in response to external state changes (r.e.
some of the RS232 lines) These can be used by normal applications.
[Top of Section] [Index]

5.13. Can I use Win9x, NT or CE as a real time OS?

Not as far as the authors of the comp.realtime FAQ are concerned. The lack of priority inheritance can make priority inversion
deadlocks possible, and there are not enough process and thread priorities for their scheduling needs.

Win9x should certainly be avoided for time critical code -unless you want to write assembler routines in VxDs, which is the
only reliable way to do so.

Windows NT can be used more easily for "soft real time" applications; it's interrupt handling architecture (interrupt handlers
should just schedule deferred procedure calls) make hard real time tasks (such as soft modems) very hard to implement

WDM is emerging as a single driver model for new bus (1394, USB) drivers on both platforms. The related video handling
driver architecture "WDM Streaming" could be useful not just for time critical video processing, but also as a way of gluing
together other bigh bandwdith kernel mode data sources and sinks.

Windows CE has some potential as a lighter weight alternative. However there is a fundamental problem in the Win32 system
architecture: applications and device drivers are cleanly split. This is great for hardware independent applications, and
application independent hardware, but not so good for anyone trying to write a custom application coupled directly to a piece
of non standard hardware. That's what DOSDR-DOS, and RTOS products like QNX and VxWorks are for. There are stated
plans for CE to evolve to become a hard RTOS, but as this platform's evolution seems to follow the needs of high visibility
product categories (WebTV, HP/C & others), it is hard to predict when CE will reach this state -if indeed it ever does.

Neither Win9x or NT are very good for time critical user mode code. Win9x, lacking a re-entrant Win16 subsystem, cannot be
used very determinstically. (I.e. you cant predict whether or not you thread gets locked out from an API call). NT does have
real time priority process and threads, which can be used to get as close to real time as you can hope to do with Windows.
[Top of Section] [Index]

5.14. How do I do system wide keyboard and mouse hooks?

You need to put the hooks into a DLL which is then mapped into the address space of all applications.
[Top of Section] [Index]

5.15. How do I get SetCapture to work the way it did I Win31?

In 32 bit windows SetCapture only captures the mouse for the current input thread. However, if you set a journalling hook the
system input queue will be serialised and you can magically call SetCapture() to grab the mouse regardless of it's on screen
position. See [MSJ April 1995 v10#4].
[Top of Section] [Index]

5.16. How do I get my program to start even if a user is not logged on?

NT: Make it a service.
Win95: add it to the list of registered apps under HKCU\Software\Windows\CurrentVersion\RunOnce
[Top of Section] [Index]

5.17. How do I load/display a 256 color bitmap using LoadBitmap (or CBitmap)?

You can't, it throws away the palette. Use {Find, Lock, Load}Resource() to load a device independent bitmap (DIB) instead.
Or example code:

Borland's TDib class
The example MFC DIB classes in "Animation in Win32", Inside Visual C++, or some MSJ articles by Paul di Lascia
Use Microsoft's DIBAPI32.DLL
Use IMGLIB.DLL. This is a $50 library which can read and halftone bitmaps, JPEG, TIFF and PCD files into DIB
memory blocks.
Stingray Software's MFC extension classes.
The function LoadImage() can also load deep color images.

You will also have to learn about palettes and their management. "Animation in Win32" has some good explanations of this.
[Top of Section] [Index]

5.18. How can my 32 bit program call a 16 bit library?

NT: You can't do this directly. You will have to write a 16 bit stub app which forwards commands and responses via some
IPC mechanism such as COM.

Win9x: Use flat thunks. The thunk compiler is in the SDK, and the documentation is in the Programmer's guide to win95.

Win32s: Generic Thunks

[Top of Section] [Index]

5.19. How do I play a sound?

With PlaySound, MessageBeep or the low level waveOut calls. You will probably need to link in the multimedia libraries too.
(add WINMM.LIB to your project). The games sound API, DirectSound, permits advanced techniques: mixing, 3D
positioning of sources and provides low latency access to the sound buffers.
[Top of Section] [Index]

5.20. How do I play multiple sounds?

You have to use the DirectSound API to do this.
[Top of Section] [Index]

5.21. What is the file format of .{exe, ico, bmp, ttf, wav, avi,doc,xls, ...etc} files?

Common file formats are documented on the MSDN disks. TrueType fonts are documented somewhere on Microsoft's ftp site
and are more complicated than you'd think.

The best on line site for file formats is Wotsit
[Top of Section] [Index]

5.22. How do I patch API entry points?

Unlike the Win16 world, you are not allowed to patch the API calls for all applications by editing USER, KERNEL and GDI.
However, patching the API calls a single app makes is easier in Win32 than Win16: you just modify the jump table at then end
of the application. To modify all applications' entry points you need to apply the same technique but also inject your DLL into
each ones' address space.

Consult [MSJ Dec 1994 v9#12], and Richter's Advanced Windows.
[Top of Section] [Index]

5.23. How do I translate the value returned by GetLastError() into a string?

With FormatMessage(), asking for the system message tables. This is a good i18n technique, as the OS can return translated
strings itself. NB: does not work in CE.

BOOL GetFormattedError(LPTSTR dest,int size)
DWORD dwLastError=GetLastError();
return 0;
BYTE width=0;
DWORD flags;
return 0 != FormatMessage(flags,

[Top of Section] [Index]

5.24. Why are all my Exe files so big?

Either you have all the debug and browse info included in it, or you have statically linked to MFC/OWL instead of using the
DLL versions.
[Top of Section] [Index]

5.25. Why do I get Undefined External errors when linking?

You have either not added the appropriate library to match a newly added header file to your project, or there is some
case/name mangling problem.

WINMM.LIB is required for all the multimedia functions (like PlaySound)
WSOCK32.LIB is required for windows sockets
Remember to put extern "C" {} around all C declarations imported around C++

[Top of Section] [Index]

5.26. How do I create a link to a file?

The only equivalent of a symbolic link is the "shortcut" file, which is like a symlink except bigger, containing an icon and enough
information about the destination to be able to look for it if it moves. -or even on other machines. These are documented in the
MSDN disks, and a COM API exists to create and manipulate them. Hard links can be created on NTFS disks by using the
backup API.

NT5 appears to extend linking significantly, with files referable by their ObjectID, rather than just absolute or relative paths, the
OS then doing the work of finding the file's location. This will only work on NTFS drives, however.
[Top of Section] [Index]

5.27. How do I create/use Shortcuts (.lnk files)?

You have to use IShellLink to manipulate these. To invoke the shortcut, use ShellExecuteEx(): ShellExecute does not work on
all link types -e.g. dial up networking links.
[Top of Section] [Index]

5.28. How many threads can a program have?

Each thread takes up space in the operating system, so the number of threads a system will support is memory-bound and so
varies from machine to machine. Often a bit of re-engineering -the use of IO Completion ports- can be used to reduce the
thread count a service will require.

A NT4 (service patch 3) and NT5 support "fibers" which are threads scheduled by the applications themselves. These are
possibly lighter weight than standard threads, but seem so rarely used that the limits have never been explored.
[Top of Section] [Index]

5.29. What are shell extensions?

These are in-process COM objects which implement a sparsely documented set of interfaces (see MSDN/MSDN on the web)
and enable anyone to write their own "folder" within the Windows Explorer shell
[Top of Section] [Index]

5.30. How do I get the shell to automatically create new documents of my type?

By adding a shellNew handler. The default is to get the shell to create a zero length file of the appropriate name. Your
application's file loading code must handle this case and treat it as creating a new blank but named file, instead of as an error.

Note that although this is a Win95 integration guideline, it is now often considered good form to ask the user if they actually
want you to extend their shell in this way -as once you have 20+ applications installed, that pop up menu ceases to be too
[Top of Section] [Index]

5.31. Why doesn't my app have nice 16x16 and 48x48 icons? (aka: Why does my app still have the MFC icon?)

Because you haven't written any. Use your icon editor to create new device images of the appropriate size within each existing
icon. Then update your windows by using either RegisterClassEx or WM_SETICON. The latter is a message which can be
posted to any window to get it to change its icons and is very useful for dialogs and other situations where the class is registered
out of your control.

When the MFC App wizard is used to generate an application, it generated 16x16 and 32x32 icons: you need to modify both
when customising your program.
[Top of Section] [Index]

5.32. How do I hide my window from the task bar?

A window will show up in the taskbar button area if

1.The window is visible
2.The window is not a child window.
3.The window is not owned.
4.The window is not a tool window.

There are some exceptions to the above rules, but they apply only to legacy ("designed for Windows 3.1 or earlier")

[Top of Section] [Index]

5.33. How I give my application a tray icon? (one of those little icons at the end of the start bar)

Look in the manuals for the Shell_NotifyIcon() API call. This lets you add new Icons to the tray

MSJ March 1995 has a good article covering the whole subject, although sadly it is no longer in the MSJ section of MSDN.
Otherwise see "Adding and Deleting Taskbar Icons" in MSDN or the "Programming the Win95 User Interface" .
[Top of Section] [Index]

5.34. How do I get Internet Explorer/Office 97 menus & toolbars?

You can do these with the Rebar/Coolbar common control, available from the COMMCTRL.DLL library distributed with IE3
and IE4. Documentation for using this control comes with the Internet SDK, and VC++ preview for IE4.

Note that once you use this control, you end up in a complex situation regarding redistribution: you have to redistribute a
common controls update One strategy here is to design an application which only uses the rebar if the library is up to date, and
drop to the previous version if not.
[Top of Section] [Index]

5.35. How do I measure Time in my program?

There are lots of ways of measuring time, each with their own advantages and disadvantages. Variables are accuracy,
portability, overhead and ease of use.

part of ANSI standard C, found in time.h and measuring seconds since 1/Jan/1970. Works reliably until January 2038.
Portable, and good for both external displaying (via ctime()) and for arithmetic. Also integrates well with time zone
settings. Not useful for dates before 1970.
Returns elapsed CPU tick count to nominally millisecond resolution. On Win95, each tick is 55mS, on WinNT it is
usually a smaller value (such as 10-20mS). Wraps every couple of months, and bears little relation to the outside
world. Also, laptops and OnNow PCs may suspend the timer while in some sleep states.
Returns system time in a fairly complex SYSTEMTIME structure. Converting it to a FILETIME format makes
comparisons and differences easier. The resolution is probably no better than that of the GetTickCount() call.
A higher resolution counter, whose frequency and accuracy varies from OS to OS, and from CPU to CPU. You need to
use QueryPerformanceFrequency() to discover the frequency. On a single processor NT platform the counter frequency
is 1+ MHz, so is accurate to microseconds. On a multiprocessor system it uses the RDTSC opcode to measure CPU
clock ticks. Good for low level performance measurement, although the switch to kernel mode adds enough overhead to
hamper profiling of small routines.
x86 assembler: rdtsc
The "Read Time Stamp Counter" instruFONT>
class Set { //normally this would be a template
virtual void insert(int); //Set of `int'
virtual int remove();
virtual Set& clone() const = 0; //pure virtual; Set is an ABC
virtual Set& fresh() const = 0;
virtual ~Set() { } //see on `virtual destructors' for more

class SetHT : public Set {
//a hash table in here
Set& clone() const { return *new SetHT(*this); }
Set& fresh() const { return *new SetHT(); }

`new SetHT(...)' returns a `SetHT*', so `*new' returns a SetHT&. A SetHT is-a
Set, so the return value is correct. The invocation of `SetHT(*this)' is that
of copy construction (`*this' has type `SetHT&'). Although `clone()' returns a
new SetHT, the caller of clone() merely knows he has a Set, not a SetHT (which
is desirable in the case of wanting a `virtual ctor'). `fresh()' is similar,
but it constructs an `empty' SetHT.

Clients can use this as if they were `virtual constructors':
void client_code(Set& s)
Set& s2 = s.clone();
Set& s3 = s.fresh();
delete &s2; //relies on destructor being virtual!!
delete &s3; // ditto

This fn will work correctly regardless of how the Set is implemented (hash
table based, AVL tree based, etc).

See above on `separation of interface from implementation' for more.

Q106: How can I call a C function `f()' from C++ code?
A: Tell the C++ compiler that it is a C function: extern "C" void f();

Q107: How can I create a C++ function `f()' that is callable by my C code?
A: Use the same `extern "C" f()' construct as detailed in the previous
question, only then proceed to actually define the function in your C++ module.
The compiler will ensure that the external information sent to the linker uses
C calling conventions and name mangling (ex: preceded by a single underscore).
Obviously you can't make several overloaded fns simultaneously callable by a C
program, since name overloading isn't supported by C.

Caveats and implementation dependencies:
* your `main()' should be compiled with your C++ compiler.
* your C++ compiler should direct the linking process.

Q109: How can I pass an object of a C++ class to/from a C function?
A: Here's an example of one that will work (be sure to read the tail of this
answer which details when such a scheme will *not* work):

/****** C/C++ header file: X.h ******/
#ifdef __cplusplus /*`__cplusplus' is #defined iff compiler is C++*/
extern "C" {

#ifdef __STDC__
extern int c_fn(struct X*); /* ANSI-C prototypes */
extern struct X* cplusplus_callback_fn(struct X*);
extern int c_fn(); /* K&R style */
extern struct X* cplusplus_callback_fn();

#ifdef __cplusplus

#ifdef __cplusplus
class X {
int a;
void frob(int);

Then, in file `X.C':
#include "X.h"
X::X() : a(0) { }
void X::frob(int aa) { a = aa; }
X* cplusplus_callback_fn(X* x)
return x;

In C++ file `main.C':
#include "X.h"
int main()
X x;
return 0;

Finally, in a C file `c-fn.c':
/* C source file c-fn.c */
#include "X.h"
int c_fn(struct X* x)
if (cplusplus_callback_fn(x))
return something();

Passing ptrs to C++ objects to/from C fns will FAIL if you pass and get back
something that isn't *exactly* the same pointer, such as passing a base class
ptr and receiving a derived class ptr (this fails when multiple inheritance is
involved, since C fails to do pointer-conversion properly).

Q110: Can my C function access data in an object of a C++ class?
A: Sometimes.

(First read the previous question on passing C++ objects to/from C functions.)
You can safely access a C++ object's data from a C function if the C++ class:
* has no virtual functions (including inherited virtual fns)
* has all its data in the same access-level section (private/protected/public)
* has no fully-contained subobjects with virtual fns

If the C++ class has any base classes at all (or if any fully contained
subobjects have base classes), accessing the data will *technically* be
non-portable, since class layout under inheritance isn't imposed by the
language. However in practice, all C++ compilers do it the same way: the base
class object appears first (in left-to-right order in the event of multiple
inheritance), and subobjects follow.

Furthermore you can often (but less than always) assume a `void*' appears in
the object at the location of the first virtual function. This is trickier,
since the first virtual function is often in a different access specifier
section than the data members. Even the use of a single pointer is not
required by the language (but this is the way `everyone' does it).

If the class has any virtual base classes, it is more complicated and less
portable. One common implementation technique is for objects to contain an
object of the virtual base class (V) last (regardless of where `V' shows up as
a virtual base class in the inheritance DAG), with the rest of the object's
parts appearing in the normal order. Every class that has V as a virtual base
class actually has a *pointer* to the V part of the final object.

ART 17

Q112: What is the type of `ptr-to-member-fn'? Is it diffn't from `ptr-to-fn'?
A: A member fn of class X has type: Returntype (X::*)(Argtypes)
while a plain function has type: Returntype (*) (Argtypes)

Q113: How can I ensure `X's objects are only created with new, not on the stack?
A: Make constructors protected and define `friend' or `static' fns that return
a ptr to objects created via `new' (the ctors must be protected rather than
private, otherwise you couldn't derive from the class). Ex:

class X { //only want to allow dynamicly allocated X's
X(int i);
X(const X& x);
virtual ~X();
static X* create() { return new X(); }
static X* create(int i) { return new X(i); }
static X* create(const X& x) { return new X(x); }

X* Xptr = X::create(5);

Q114: How do I pass a ptr to member fn to a signal handler,X event callback,etc?
A: Because a member function is meaningless without an object to invoke it on,
you can't do this directly (if `X' were rewritten in C++, it would probably
pass references to *objects* around, not just pointers to fns; naturally the
objects would embody the required function and probably a whole lot more).

As a patch for existing software, use a free function as a wrapper which takes
an object obtained through some other technique (held in a global, perhaps) and
calls the desired member function. There is one exception: static member
functions do not require an actual object to be invoked, and ptrs-to-static-
member-fns are type compatible with regular ptrs-to-fns (see ARM p.25, 158).

Ex: suppose you want to call X::memfn() on interrupt:

class X {
void memfn();
static void staticmemfn(); //a static member fn can handle it

//wrapper fn remembers the object on which to invoke memfn in a static var:
static X* object_which_will_handle_signal;
void X_memfn_wrapper() { object_which_will_handle_signal.memfn(); }

/* signal(SIGINT, X::memfn); */ //Can NOT do this
signal(SIGINT, X_memfn_wrapper); //Ok
signal(SIGINT, X::staticmemfn); //Also Ok

Q115: Why am I having trouble taking the address of a C++ function?
Short ans: Please read previous question first; this is a corollary.

Long ans: In C++, member fns have an implicit parameter which points to the
object (the `this' ptr inside the member fn). Normal C fns can be thought of
as having a different calling convention from member fns, so the types of their
ptrs (ptr-to-member-fn vs ptr-to-fn) are different and incompatible. C++
introduces a new type of ptr, called a ptr-to-member, which can only be invoked
by providing an object (see ARM 5.5). Do NOT attempt to `cast' a ptr-to-mem-fn
into a ptr-to-fn; the result is undefined and probably disastrous; a ptr-to-
member-fn is NOT required to contain the machine addr of the appropriate fn
(see ARM, 8.1.2c, p.158). As was said in the last example, if you want a
regular C fn ptr, use either a top-level (non-class) fn, or a `static' (class)
member fn.

Q116: How do I declare an array of pointers to member functions?
A: Use the following declaration:

class Frob {
Rettype f(T1 x, T2 y);
Rettype g(T1 x, T2 y);
Rettype h(T1 x, T2 y);
Rettype i(T1 x, T2 y);

Rettype (Frob::*fn_ptr[3])(T1,T2) = { &Frob::f, &Frob::g, &Frob::h };

You can make the array declaration somewhat clearer with a typedef:
typedef Rettype (Frob::*Frob_member_ptr)(T1,T2);
Frob_member_ptr fn_ptr[3] = { &Frob::f, &Frob::g, &Frob::h };

To call one of the functions on an object `frob', use:
Frob frob;
(frob.*fn_ptr[i])(x, y);

You can make the call somewhat clearer using a #define:
#define apply_member_fn(object,fn) ((object).*(fn))
apply_member_fn(frob,fn_ptr[i])(x, y)


Q117: How can I insert/access/change elements from a linked list/hashtable/etc?
A: I'll use a `inserting into a linked list' as a prototypical example. The
obvious approach is to allow insertion at the head and tail of the list, but
that would produce a library that is too weak (a weak library is almost worse
than no library). Whenever encapsulation frustrates rather than helps a user,
it may be that the class' public interface needs enhancing. If class List only
supports adding at the front and tail, it *definitely* needs more strength.

This answer will be a lot to swallow for novice C++'ers, so I'll give a couple
of options. As usual, the first is easiest, while the second option is better.
I also give a thumbnail sketch of a third option, which has certain advantages
and disadvantages over the second option.

[1] Empower the List with a `viewport' or `cursor' that references an arbitrary
list element. Implies adding member fns to List such as advance(), backup(),
atend(), atbegin(), rewind(), fastforward(), and current(). `current()'
returns the element of the List that is currently `under the cursor'. Finally
you'll need to add a few more member fns to *mutate* the list, such as
changeto(X), insert(X), remove(), etc.

[2] Provide a separate class called ListIter. ListIter has member fns named
similar to the above (though probably with operator overloading, but that's
just syntactic sugar for member fns). The List itself would have none of the
above mentioned member fns, and the ListIter would be a `friend' of List
(ListIter would have to have access to the innards of List; this allows the
world to have safe access abilities to List without violating encapsulation).

The reason option [2] is better becomes apparent when you use classes that only
support [1]. In particular, if you pass a List off to a subcall, you'd better
hope the subcall didn't warp the `cursor' around, or your code may fail. Also,
if you try to get all pairs of elements, it's very hard if you only have one
cursor. The distinct-class iterator concept removes these restrictions. My
own class library uses these extensively, as will most any other commercial
grade class library.

Note that the options are not mutually exclusive; it is possible to provide
both [2] *and* [1], giving rise to the notion of a `primary' list position,
with instances of ListIter being somewhat secondary.

[3] The third possibility considers the entire iteration as an atomic event. A
class is created which embodies this event. The nice thing about this third
alternative is that the public access methods (which may be virtual fns) can be
avoided during the inner loop, thus enhancing performance. The down side is
that you get extra object code in the application, since templates gain speed
by duplicating code. This third technique is due to Andrew Koenig in a paper
published recently in JOOP [`Templates as interfaces', JOOP, 4, 5 (Sept 91)].
You can also see a taste of it in Bjarne Stroustrup's book, The C++ Programming
Language Second Edition (look for `Comparator' in the index).

Q118: What's the idea behind `templates'?
A: A template is a cookie-cutter that specifies how to cut cookies that all
look pretty much the same (although the cookies can be made of various kinds of
dough, they'll all have the same basic shape). In the same way, a class
template is a cookie cutter to description of how to build classes that all
look basically the same, and a function template describes how to build similar
looking functions.

The questions about templates are in the `Containers' section since templates
are often used to build type safe containers (although this only scratches the
surface for how they can be used). We will see how to use templates to build
container classes below.

Q119: What's the syntax / semantics for a `function template'?
A: Consider this function that swaps its two integer arguments:

void swap(int& x, int& y)
int tmp = x;
x = y;
y = tmp;

If we also had to swap floats, longs, Strings, Sets, and FileSystems, we'd get
pretty tired of coding lines that look almost identical except for the type.
Mindless repetition is an ideal job for a computer, hence a function template:

void swap(T& x, T& y)
T tmp = x;
x = y;
y = tmp;

Every time we used `swap()' with a given pair of types, the compiler will go to
the above definition and will create yet another `template function' as an
instantiation of the above. Ex:

int i,j; /*...*/ swap(i,j); //instantiates a swap for `int'
float a,b; /*...*/ swap(a,b); //instantiates a swap for `float'
char c,d; /*...*/ swap(c,d); //instantiates a swap for `char'
String s,t; /*...*/ swap(s,t); //instantiates a swap for `String'

(note: a `template function' is the instantiation of a `function template').

Q120: What's the syntax / semantics for a `class template'?
A: Consider this container class of that acts like an array of integers:

//this would go into a header file such as `Vec.h':
class Vec {
int xlen;
int* xdata;
int check(int i); //return i if i>=0 && i= xlen) throw BoundsViol("Vec", i, xlen);
return i;

Just as with `swap()' above, repeating the above over and over for Vec of
float, char, String, Vec, Vec-of-Vec-of-Vec, etc, will become tedious. Hence
we create a single class template:

//this would go into a header file such as `Vec.h':
class Vec {
int xlen;
T* xdata;
int check(int i); //return i if i>=0 && i
int Vec::check(int i)
if (i < 0 || i >= xlen) throw BoundsViol("Vec", i, xlen);
return i;

Unlike template functions, template classes (instantiations of class templates)
need to be explicit about the parameters over which they are instantiating:

Vec vi;
Vec vf;
Vec vc;
Vec vs;
Vec< Vec > vv;
} // ^^^-- note the space; do NOT use Vec> since the
// `maximal munch' rule would grab a single `>>' token

Q121: What is a `parameterized type'?
A: A parameterized type is a type that is parameterized over another value or
type. Ex: List is a type that is parameterized over another type, `int'.
Therefore the C++ rendition of parameterized types is provided by class

Q122: What is `genericity'?
A: Not to be confused with `generality' (which just means avoiding solutions
which are overly specific), `genericity' means parameterized types. In C++,
this is provided by class templates.

Q123: How can I fake templates if I don't have a compiler that supports them?
A: The best answer is: buy a compiler that supports templates. When this is
not feasible, the next best answer is to buy or build a template preprocessor
(ex: reads C++-with-templates, outputs C++-with-expanded-template-classes; such
a system needn't be perfect; it cost my company about three man-weeks to
develop such a preprocessor). If neither of these is feasible, you can use the
macro preprocessor to fake templates. But beware: it's tedious; templates are
a better solution wrt development and maintenance costs.

Here's how you'd declare my `Vec' example from above. First we define `Vec(T)'
to concatenate the name `Vec' with that of the type T (ex: Vec(String) becomes
`VecString'). This would go into a header file such as Vec.h:

#include //to get the `name2()' macro
#define Vec(T) name2(Vec,T)

Next we declare the class Vec(T) using the name `Vecdeclare(T)' (in general you
would postfix the name of the class with `declare', such as `Listdeclare' etc):

#define Vecdeclare(T) \
class Vec(T) { \
int xlen; \
T* xdata; \
int check(int i); /*return i if in bounds else throw*/ \
public: \
int len() const { return xlen; } \
const T& operator[](int i) const { xdata[check(i)]; } \
T& operator[](int i) { xdata[check(i)]; } \
Vec(T)(int L=10): xlen(L), xdata(new T[L]) {/*...*/}\
~Vec(T)() { delete [] xdata; } \

Note how each occurrence of `Vec' has the `(T)' postfixed. Finally we set up
another macro that `implements' the non-inline member function(s) of Vec:

//strangely enough this can also go into Vec.h
#define Vecimplement(T) \
int Vec(T)::check(int i) \
{ \
if (i < 0 || i >= xlen) throw BoundsViol("Vec", i, xlen); \
return i; \

When you wish to use a Vec-of-String and Vec-of-int, you would say:

#include "Vec.h" //pulls in too; see below...
declare(Vec,String) //`declare()' is a macro defined in
Vec(String) vs; //Vec(String) becomes the single token `VecString'
Vec(int) vi;

In exactly one source file in the system, you must provide implementations for
the non-inlined member functions:

#include "Vec.h"
declare (Vec,String) declare (Vec,int) declare (Vec,float)
implement(Vec,String) implement(Vec,int) implement(Vec,float)

Note that types whose names are other than a single identifier do not work
properly. Ex: Vec(char*) creates a class whose name is `Vecchar*'. The patch
is to create a typedef for the appropriate type:

#include "Vec.h"
typedef char* charP;

It is important that every declaration of what amounts to `Vec' must all
use exactly the same typedef, otherwise you will end up with several equivalent
classes, and you'll have unnecessary code duplication. This is the sort of
tedium which a template mechanism can handle for you.


Miscellaneous technical issues:

Q131: Why are classes with static data members getting linker errors?
A: Static member variables must be given an explicit definition in exactly one
module. Ex:
class X {
static int i; //*declare* static member X::i
The linker will holler at you (`X::i is not defined') unless (exactly) one of
your source files has something like the following:
int X::i = some_expression_evaluating_to_an_int; //*define* X::i
int X::i; //define --but don't initialize-- X::i

The usual place to define static member variables of class `X' is file `X.C'
(or X.cpp,, X.c++, X.c or X.cxx; see question on file naming conventions).

Q132: What's the difference between the keywords struct and class?
A: The members and base classes of a struct are public by default, while in
class, they default to private. Base classes of a struct are public by default
while they are private by default with `class' (however you should make your
base classes *explicitly* public, private, or protected). `Struct' and `class'
are otherwise functionally equivalent.

Q133: Why can't I overload a function by its return type?

Ex: the compiler says the following two are an error:
char f(int i);
float f(int i);

A: Return types are not considered when determining unique signatures for
overloading functions; only the number and type of parameters are considered.
Reason: which function should be called if the return value is ignored? Ex:

f(3); //which should be invoked??

Q134: What is `persistence'? What is a `persistent object'?
A: Loosely speaking, a persistent object is one that lives on after the
program which created it has stopped. Persistent objects can even outlive
various versions of the creating program, can outlive the disk system, the
operating system, or even the hardware on which the OS was running when
they were created.

The challenge with persistent objects is to effectively store their method
code out on secondary storage along with their data bits (and the data bits
and method code of all subobjects, and of all their subobjects, etc). This
is non-trivial when you have to do it yourself. In C++, you have to do it
yourself. C++/OO databases can help hide the mechanism for all this.

Miscellaneous environmental issues:

Q135: Is there a TeX or LaTeX macro that fixes the spacing on `C++'?
A: Yes, here are two:

\def\CC{C\raise.22ex\hbox{{\footnotesize +}}\raise.22ex\hbox{\footnotesize +}}

\def\CC{{C\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}

Q136: Where can I access C++2LaTeX, a LaTeX pretty printer for C++ source?
A: Here are a few ftp locations:

Host ( Last updated 15:41 26 Apr 1991
Location: /tex
FILE rw-rw-r-- 59855 May 5 1990 C++2LaTeX-1.1.tar.Z
Host ( Last updated 05:06 20 Apr 1991
Location: /TeX/macros
FILE rw-r--r-- 59855 Mar 4 08:16 C++2LaTeX-1.1.tar.Z
Host ( Last updated 05:23 9 Apr 1991
Location: /TeX/tools
FILE rw-rw-r-- 59855 Oct 23 16:05 C++2LaTeX-1.1.tar.Z
Host ( Last updated 05:06 4 Apr 1991
Location: /TeX
FILE rw-r--r-- 59855 Apr 25 1990 C++2LaTeX-1.1.tar.Z
Host ( Last updated 05:06 4 Apr 1991
Location: /TeX
FILE rw-r--r-- 51737 Apr 30 1990
Host ( Last updated 05:07 18 Apr 1991
Location: /pub/textproc/TeX
FILE rw-r--r-- 72957 Oct 25 13:51 C++2LaTeX-1.1-PL4.tar.Z
Host ( Last updated 23:25 30 Apr 1991
Location: /packages/tex/tex/
FILE rw-rw-r-- 49104 Apr 10 1990 C++2LaTeX-PL2.tar.Z
FILE rw-rw-r-- 25835 Apr 10 1990 C++2LaTeX.tar.Z
Host ( Last updated 05:07 18 Apr 1991
Location: /pub/textproc/TeX
FILE rw-r--r-- 74015 Mar 22 16:23 C++2LaTeX-1.1-PL5.tar.Z
Location: /pub
FILE rw-r--r-- 74015 Mar 22 16:23 C++2LaTeX-1.1-PL5.tar.Z
Host ( Last updated 05:10 15 Apr 1991
Location: /TEX/TOOLS
FILE rw-r--r-- 74015 Apr 4 21:02x C++2LaTeX-1.1-PL5.tar.Z
Host ( Last updated 05:07 18 Apr 1991
Location: /pub/textproc/TeX
FILE rw-r--r-- 4792 Sep 11 1990 C++2LaTeX-1.1-patch#1
FILE rw-r--r-- 2385 Sep 11 1990 C++2LaTeX-1.1-patch#2
FILE rw-r--r-- 5069 Sep 11 1990 C++2LaTeX-1.1-patch#3
FILE rw-r--r-- 1587 Oct 25 13:58 C++2LaTeX-1.1-patch#4
FILE rw-r--r-- 8869 Mar 22 16:23 C++2LaTeX-1.1-patch#5
FILE rw-r--r-- 1869 Mar 22 16:23 C++2LaTeX.README
Host ( Last updated 05:13 13 Apr 1991
Location: /soft/tex/utilities
FILE rw-rw-r-- 163840 Jul 16 1990 C++2LaTeX-1.1.tar

Q137: Where can I access `tgrind', a pretty printer for C++/C/etc source?
A: `tgrind' reads the file to be printed and a command line switch to see what
the source language is. It then reads a language definition database file and
learns the syntax of the language (list of keywords, literal string delimiters,
comment delimiters, etc).

`tgrind' usually comes with the public distribution of TeX and LaTeX. Look in
the directory:

A more up-to-date version of tgrind by Jerry Leichter can be found on: in [.TGRIND]

Q138: Is there a C++-mode for GNU emacs? If so, where can I get it?
A: Yes, there is a C++-mode for GNU emacs. You can get it via:

c++-mode-2 (1.0) 87-12-08
Bruce Eckel,Thomas Keffer,

Another C++ major mode.
c++-mode 89-11-07
Dave Detlefs, et al,

C++ major mode.
c++ 90-02-01
David Detlefs, Stewart Clamen,
C++ code editing commands for Emacs

c-support (46) 89-11-04
Lynn Slater,
Partial support for team C/C++ development.

Q139: What is `InterViews'?
A: A non-proprietary toolkit for graphic user interface programming in C++,
developed by Mark Linton and others when he was at Stanford. Unlike C++
wrappers for C libraries such as Motif, InterViews is a true object library.
Commercially maintained versions are available from Quest, while freely
redistributable versions (running on top of X) from (an
ftp site). Copies of this are (were?) distributed with the regular X
distribution. Other sources of information include,
which has its own FAQ.

Q140: Where can I get OS-specific questions answered (ex:BC++,DOS,Windows,etc)?
A: see comp.os.msdos.programmer, BC++ and Zortech mailing lists, BC++ and
Zortech bug lists,, comp.unix.programmer, etc.

You can subscribe to the BC++ mailing list by sending email to:
| Subject: SUB TCPLUS-L
| Reply-to: <---ie: put your return address here

The BC++ bug report is available via anonymous ftp from
[] from the file ~ftp/pub/Turbo-C++/bug-report
(also, I post it on comp.lang.c++ on the first each month).

Relevant email addresses: General requests and discussion Requests to be added to ztc-list For _short_ bug reports

Q141: Why does my DOS C++ program says `Sorry: floating point code not linked'?
A: The compiler attempts to save space in the executable by not including the
float-to-string format conversion routines unless they are necessary, and
sometimes does not recognize some code that does require it. Taking the address
of a float in an argument list of a function call seems to trigger it, but
taking the address of a float element of a struct may fool the compiler. A
"%f" in a printf/scanf format string doesn't trigger it because format strings
aren't examined at compile-time.

You can fix it by (1) using instead of , or (2) by
including the following function definition somewhere in your compilation (but
don't call it!):
static void dummyfloat(float *x) { float y; dummyfloat(&y); }

See question on stream I/O for more reasons to use vs .

Q18: What are inline fns? What are their advantages? How are they declared?
A: An inline function is a function which gets textually inserted by the
compiler, much like a macro. Like macros, performance is improved by avoiding
the overhead of the call itself, and (especially!) by the compiler being able
to optimize *through* the call (`procedural integration'). Unlike macros,
arguments to inline fns are always evaluated exactly once, so the `call' is
semantically like a regular function call only faster. Also unlike macros,
argument types are checked and necessary conversions are performed correctly.

Beware that overuse of inline functions can cause code bloat, which can in
turn have a negative performance impact in paging environments.

They are declared by using the `inline' keyword when the function is defined:
inline void f(int i, char c) { /*...*/ } //an inline function
or by including the function definition itself within a class:
class X {
void f(int i, char c) { /*...*/ } //inline function within a class
or by defining the member function as `inline' outside the class:
class X {
void f(int i, char c);
inline void X::f(int i, char c) {/*...*/} //inline fn outside the class

Generally speaking, a function cannot be defined as `inline' after it has been
called. Inline functions should be defined in a header file, with `outlined'
functions appearing in a `.C' file (or .cpp, etc; see question on file naming

---2138437061-33463914-899838444=:28808 Content-Type: text/html; name="cpp.html" Content-Description: cpp.html Content-Disposition: inline; filename="cpp.html" cpp [10.6] Should my constructors use "initialization lists" or "assignment"?

[Recently created (on 5/98). Click here to go to the next FAQ in the "chain" of recent changes.]

Constructors should initialize all member objects in the initialization list.

For example, this constructor initializes member object x_ using an initialization list: Fred::Fred() : x(whatever) { }.
From a performance perspective, it is important to note that the whatever expression doesn't automatically cause a separate
object to be created and copied into x_: if the types are the same the result of ...whatever... will be constructed directly inside

In contrast the following constructor uses assignment: Fred::Fred() { x_ = whatever; }. In this case the expression
whatever causes a separate, temporary object to be created, and this temporary object is passed into the x_ object's
assignment operator, then is destructed at the ;. That's inefficient.

There's another source of inefficiency as well: in the second (assignment) case, the object's default constructor (implicitly called
before the constructor body's "{") might, for example, allocate some default amount of memory or open some default file. All
this work could be for naught if the whatever expression and/or assignment operator causes the object to close that file and/or
release that memory (e.g., if the default constructor didn't allocate a large enough pool of memory or if it opened the wrong

Conclusion: All other things being equal, your code will run faster if you use initialization lists rather than assignment.

[ Top | Bottom | Previous section | Next section ]

[10.7] What is the "Named Constructor Idiom"?

A technique that provides more intuitive and/or safer construction operations for users of your class.

The problem is that constructors always have the same name as the class. Therefore the only way to differentiate between the
various constructors of a class is by the parameter list. But if there are lots of constructors, the differences between the
constructors becomes somewhat subtle and error prone.

With the Named Constructor Idiom, you declare all the class's constructors in the private: or protected: sections, and
you provide public static methods that return an object. These static methods are the so-called "Named Constructors."
In general there is one such static method for each different way to construct an object.

For example, suppose we are building a Point class that represents a position on the X-Y plane. Turns out there are two
common ways to specify a 2-space coordinate: rectangular coordinates (X+Y), polar coordinates (Radius+Angle). (Don't
worry if you can't remember these; the point isn't the particulars of coordinate systems; the point is that there are several ways
to create a Point object). Unfortunately the parameters for these two coordinate systems are the same: two floats. This
would create an ambiguity error in the overloaded constructors:

class Point {
Point(float x, float y); // Rectangular coordinates
Point(float r, float a); // Polar coordinates (radius and angle)
// ERROR: Overload is Ambiguous: Point::Point(float,float)

Point p = Point(5.7, 1.2); // Ambiguous: Which coordinate system?

One way to solve this ambiguity is to use the Named Constructor Idiom:

#include // To get sin() and cos()

class Point {
static Point rectangular(float x, float y); // Rectangular coord's
static Point polar(float radius, float angle); // Polar coordinates
// These static methods are the so-called "named constructors"
// ...
Point(float x, float y); // Rectangular coordinates
float x_, y_;

inline Point::Point(float x, float y)
: x_(x), y_(y) { }

inline Point Point::rectangular(float x, float y)
{ return Point(x, y); }

inline Point Point::polar(float radius, float angle)
{ return Point(radius*cos(angle), radius*sin(angle)); }

Now the users of Point have a clear and unambiguous syntax for creating Points in either coordinate system:

Point p1 = Point::rectangular(5.7, 1.2); // Obviously rectangular
Point p2 = Point::polar(5.7, 1.2); // Obviously polar

Make sure your constructors are in the protected: section if you expect Fred to have derived classes.

The Named Constructor Idiom can also be used to make sure your objects are always created via new.

[ Top | Bottom | Previous section | Next section ]

[10.8] Why can't I initialize my static member data in my constructor's initialization list?

Because you must explicitly define your class's static data members.


class Fred {
// ...
int i_;
static int j_;

Fred.cpp (or Fred.C or whatever):

: i_(10) // OK: you can (and should) initialize member data this way
j_(42) // Error: you cannot initialize static member data like this
// ...

// You must define static data members this way:
int Fred::j_ = 42;

[ Top | Bottom | Previous section | Next section ]

[10.9] Why are classes with static data members getting linker errors?

Because static data members must be explicitly defined in exactly one compilation unit. If you didn't do this, you'll probably
get an "undefined external" linker error. For example:

// Fred.h

class Fred {
// ...
static int j_; // Declares static data member Fred::j_
// ...

The linker will holler at you ("Fred::j_ is not defined") unless you define (as opposed to merely declare) Fred::j_ in
(exactly) one of your source files:

// Fred.cpp

#include "Fred.h"

int Fred::j_ = some_expression_evaluating_to_an_int;

// Alternatively, if you wish to use the implicit 0 value for static ints:
// int Fred::j_;

The usual place to define static data members of class Fred is file Fred.cpp (or Fred.C or whatever source file extension
you use).

[ Top | Bottom | Previous section | Next section ]

[10.10] What's the "static initialization order fiasco"?

[Recently created (on 9/97). Click here to go to the next FAQ in the "chain" of recent changes.]

A subtle way to kill your project.

The static initialization order fiasco is a very subtle and commonly misunderstood aspect of C++. Unfortunately it's very
hard to detect -- the errors occur before main() begins.

In short, suppose you have two static objects x and y which exist in separate source files, say x.cpp and y.cpp. Suppose
further that the constructor for the y object calls some method on the x object.

That's it. It's that simple.

The tragedy is that you have a 50%-50% chance of dying. If the compilation unit for x.cpp happens to get initialized first, all is
well. But if the compilation unit for y.cpp get initialized first, then y's constructor will get run before x's constructor, and you're
toast. I.e., y's constructor will call a method on the x object, yet the x object hasn't yet been constructed.

I hear they're hiring down at McDonalds. Enjoy your new job flipping burgers.

If you think it's "exciting" to play Russian Roulette with live rounds in half the chambers, you can stop reading here. On the other
hand if you like to improve your chances of survival by preventing disasters in a systematic way, you probably want to read the
next FAQ.

Note: The static initialization order fiasco does not apply to builtin/intrinsic types like int or char*. For example if you create
a static float object, there is never a problem with static initialization order. The only time the static initialization order is
truly a fiasco is when your static or global objects have a constructor.

[ Top | Bottom | Previous section | Next section ]

[10.11] How do I prevent the "static initialization order fiasco"?

[Recently created (on 9/97). Click here to go to the next FAQ in the "chain" of recent changes.]

Use the "construct on first use" idiom, which simply means to wrap your static object inside a function.

For example, suppose you have two classes, Fred and Barney. There is a global Fred object called x, and a global Barney
object called y. Barney's constructor invokes the goBowling() method on the x object. The file x.cpp defines the x object:

// File x.cpp
#include "Fred.hpp"
Fred x;

The file y.cpp defines the y object:

// File y.cpp
#include "Barney.hpp"
Barney y;

For completeness the Barney constructor might look something like this:

// File Barney.cpp
#include "Barney.hpp"

// ...
// ...

As described above, the disaster occurs if y is constructed before x, which happens 50% of the time since they're in different
source files.

There are many solutions to this problem, but a very simple and completely portable solution is to replace the global Fred
object, x, with a global function, x(), that returns the Fred object by reference.

// File x.cpp

#include "Fred.hpp"

Fred& x()
static Fred* ans = new Fred();
return *ans;

Since static local objects are constructed the first time control flows over their declaration (only), the above new Fred()
statement will only happen once: the first time x() is called. Every subsequent call will return the same Fred object (the one
pointed to by ans). Then all you do is change your usages of x to x():

// File Barney.cpp
#include "Barney.hpp"

// ...
// ...

This is called the Construct On First Use Idiom because it does just that: the global Fred object is constructed on its first use.

The downside of this approach is that the Fred object is never destructed. The C++ FAQ Book has a second technique that
answers this concern (but at the cost of opening a "static de-initialization order fiasco").

Note: You don't have to do this for builtin/intrinsic types like int or char*. For example if you create a static or global
float object, there is no need to wrap it within a function. The only time the static initialization order is truly a fiasco is when
your static or global objects have a constructor.

[11.4] Can I overload the destructor for my class?


You can have only one destructor for a class Fred. It's always called Fred::~Fred(). It never takes any parameters, and it
never returns anything.

You can't pass parameters to the destructor anyway, since you never explicitly call a destructor (well, almost never).
[11.3] What's the order that objects in an array are destructed?

In reverse order of construction: First constructed, last destructed.

In the following example, the order for destructors will be a[9], a[8], ..., a[1], a[0]:

void userCode()
Fred a[10];
// ...

8.1 What is a reference?

An alias (an alternate name) for an object.

14.2] Do friends violate encapsulation?
If they're used properly, they actually enhance encapsulation.

[14.3] What are some advantages/disadvantages of using friend functions?

They provide a degree of freedom in the interface design options.
---2138437061-33463914-899838444=:28808 Content-Type: text/html; name="winsock.html" Content-Description: winsock.html Content-Disposition: inline; filename="winsock.html" winsock Example - Getting the Local IP Address

This example shows how to get the local machine's IP address(es). Note especially the loop near the bottom of the doit()
function. Although the majority of machines have only a single IP address, it is becoming common for a machine to have two or
more IP addresses. On my home machine, for example, there is one IP address for the Ethernet network board, and one for
the modem when it's connected to my ISP.


// Borland C++ 5.0: bcc32.cpp getlocalip.cpp
// Visual C++ 5.0: cl getlocalip.cpp wsock32.lib


int doit(int, char**)
char ac[80];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
cerr << "Error " << WSAGetLastError() <<
" when getting local host name." << endl;
return 1;
cout << "Host name is " << ac << "." << endl;

struct hostent* phe = gethostbyname(ac);
if (phe == 0) {
cerr << "Yow! Bad host lookup." << endl;
return 1;

for (int i = 0; phe->h_addr_list[i] != 0; ++i) {
struct in_addr addr;
memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
cout << "Address " << i << ": " << inet_ntoa(addr) << endl;

return 0;

int main(int argc, char* argv[])
WSAData wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
return 255;

int retval = doit(argc, argv);

return retval;

This example is based on the example in the Microsoft documentation for the _pipe() run-time library function. It was brought
to my attention by Valerie Puffet-Michel. I took the example and made it a bit more robust, partly to catch the Borland C++
bug described below.

Essentially, this example works on the Win32 rule that a child process can inherit the file handles that the parent opened. The
program passes the file handle IDs on the command line to the child that it spawns. Since file handles and socket descriptors
are the same thing in Win32, this works just as well for sockets as it does for the pipe handles used in the example. Note that
you cannot pass file handles to arbitrary processes. They have to somehow inherit those handles, which implies that the process
that created the handles has to have some sort of parental relationship to the process that wants to use those handles.

This example will not work under Borland C++ 5.0 because of a run-time library bug, documented in bug report 43101. The
report does not give any workarounds for this problem, so you may be out of luck if you're trying to do this with Borland C++.
Still, it will compile now. B-)


// Borland C++ 5.0: bcc32 fdpass.cpp
// Visual C++ 5.0: cl fdpass.cpp


enum PIPES {
READ = 0,
#define NUMPROBLEM 8

#ifdef _MSC_VER
#define CWAIT _cwait
#define CWAIT cwait

void main(int argc, char *argv[])
int hpipe[2];
char hstr[20];
int pid, problem, c;
int termstat;

if (argc == 1) {
//// No arguments, so this must be the parent process
// Open a set of pipes
if (_pipe(hpipe, 256, O_BINARY) == -1) {
perror("pipe failed");

// Convert read side of pipe to string and pass as an argument
// to the child process.
itoa(hpipe[READ], hstr, 10);
if ((pid = spawnl(P_NOWAIT, argv[0], argv[0], hstr, NULL)) == -1) {
perror("Spawn failed");

// Put problem in write pipe; it will appear in child's read pipe.
for (problem = 1000; problem <= NUMPROBLEM * 1000; problem += 1000) {
if (write(hpipe[WRITE], (char*)&problem, sizeof(int)) == -1) {
perror("parent write failed");
else {
printf("Son, what is the square root of %d?\n", problem);

// Wait until spawned program is done processing.
CWAIT(&termstat, pid, WAIT_CHILD);
if (termstat & 0x0) {
perror("Child failed");

else {
//// There is a command line argument, so we must be a child process
// Convert argument to integer handle value.
hpipe[READ] = atoi(argv[1]);

// Read problem from pipe and calculate solution.
for (c = 0; c < NUMPROBLEM; c++) {
if (read(hpipe[READ], (char*)&problem, sizeof(int)) == -1) {
perror("child read failed");
else {
printf("Dad, the square root of %d is %3.2f.\n", problem,
Example - How to Get the Local User Name

The Win32 API has a simple function called GetUserName() that works under Windows 95 and Windows NT. The
GetUserName() function is very easy to use:

Example - How to Get the MAC Address of an Ethernet Adapter,
NetBIOS Method

This example shows you how to use the NetBIOS API to retrieve the MAC addresses of the network adapters in a system.
There are two weaknesses to this approach. The first is that you have to have the NetBEUI protocol installed and bound to the
network adapter whose address you want. The second is that if you have more than one network adapter, you may have to do
extra work to figure out which address you really want. If these weaknesses are a problem, you might look at the RPC
variation for getting the MAC address.

Note that there is a line below that reads "Ncb.ncb_buffer = (unsigned char*)&Adapter" under MSIE 3.0, due to a bug in their
rendering engine that I seem to be unable to work around. This line does properly show a semicolon at the end under
Navigator. (If anyone has some fun HTML tricks that will work around this problem, please let me know. Know, however that
I think I've tried all the obvious and even some less obvious tricks.)

This code is based on that presented in Microsoft Knowledge Base article Q118623. Of course, my code is cleaner and
smarter than theirs is. B-)


// Visual C++ 5.0: cl -GX getmac-netbios.cpp netapi32.lib
// Borland C++ 5.0: bcc32 getmac-netbios.cpp


using namespace std;

bool GetAdapterInfo(int nAdapterNum, string& sMAC)
// Reset the LAN adapter so that we can begin querying it
NCB Ncb;
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lana_num = nAdapterNum;
if (Netbios(&Ncb) != NRC_GOODRET) {
char acTemp[80];
ostrstream outs(acTemp, sizeof(acTemp));
outs << "error " << Ncb.ncb_retcode << " on reset" << ends;
sMAC = acTemp;
return false;

// Prepare to get the adapter status block
memset(&Ncb, 0, sizeof(Ncb));
Ncb.ncb_command = NCBASTAT;
Ncb.ncb_lana_num = nAdapterNum;
strcpy((char*)Ncb.ncb_callname, "*");
struct ASTAT {
NAME_BUFFER NameBuff[30];
} Adapter;
memset(&Adapter, 0, sizeof(Adapter));
Ncb.ncb_buffer = (unsigned char*)&Adapter;
Ncb.ncb_length = sizeof(Adapter);

// Get the adapter's info and, if this works, return it in standard,
// colon-delimited form.
if (Netbios(&Ncb) == 0) {
char acMAC[18];
sprintf(acMAC, "%02X:%02X:%02X:%02X:%02X:%02X",
sMAC = acMAC;
return true;
else {
char acTemp[80];
ostrstream outs(acTemp, sizeof(acTemp));
outs << "error " << Ncb.ncb_retcode << " on ASTAT" << ends;
sMAC = acTemp;
return false;

void main()
// Get adapter list
LANA_ENUM AdapterList;
NCB Ncb;
memset(&Ncb, 0, sizeof(NCB));
Ncb.ncb_command = NCBENUM;
Ncb.ncb_buffer = (unsigned char*)&AdapterList;
Ncb.ncb_length = sizeof(AdapterList);

// Get all of the local ethernet addresses
string sMAC;
for (int i = 0; i < AdapterList.length - 1; ++i) {
if (GetAdapterInfo(AdapterList.lana[i], sMAC)) {
cout << "Adapter " << int(AdapterList.lana[i]) <<
"'s MAC is " << sMAC << endl;
else {
cerr << "Failed to get MAC address! Do you" << endl;
cerr << "have the NetBIOS protocol installed?" << endl;

Example - How to Get the MAC Address of an Ethernet Adapter, RPC

This example shows you how to use the RPC API to retrieve the MAC addresses of at least one of the network adapters in a
system. Just like with the NetBIOS method, there are two weaknesses to this approach. The first is that it is not guaranteed to
work. All it does is rely on the way UUIDs are defined by RPC, which is that the last six bytes are derived from the hardware
address of the machine's network adapter. The second, potentially more important problem is that this won't work if there is
more than one Ethernet adapter in the system. I've not tried it, but I suspect that this program will return the address of the
"first" Ethernet adapter. If you need the second as well, better try the NetBIOS method.

On the other hand, this method has several advantages. First, it does not require anything extra to be installed on the user's
machine -- RPC comes with all Win32 variants. (Excepting WinCE, probably.) Second, it's a lot smaller, codewise, than the
NetBIOS method. Third, it doesn't have the 00:00:00:00:00:00 problem of the NetBIOS code. That could probably be fixed,
but that would make the second advantage (code size) even more obvious.

This demented kludge is entirely my own creation. Caveat hacker.


// Visual C++ 5.0: cl -GX getmac-rpc.cpp rpcrt4.lib
// Borland C++ 5.0: bcc32 getmac-rpc.cpp


#ifdef __BORLANDC__
namespace std {

using namespace std;

void main()
cout << "MAC address is: ";

// Ask RPC to create a UUID for us. If this machine has an Ethernet
// adapter, the last six bytes of the UUID (bytes 2-7 inclusive in
// the Data4 element) should be the MAC address of the local
// Ethernet adapter.
UUID uuid;

// Spit the address out
for (int i = 2; i < 8; ++i) {
cout << hex;
cout << int(uuid.Data4[i]);
if (i < 7) {
cout << ":";
cout << endl;
Example - Getting the Interface List

This example shows how to get the computer's network interface list, along with associated information like the broadcast
addresses, the netmasks, and some of the interface's capabilities. This program is actually a semi-useful tool, sort of like an
output-only version of the UNIX ifconfig program. However, its output is significantly more readable.

This program only works under Winsock 2. Also, I have tested it under Windows NT 4.0 SP 3, and reports indicate that it
also runs under Windows 95. (If you know differently, please email me.) Also, notice that Service Pack 3 is actually required
under NT, as a bug exists in previous implementations of SIO_GET_INTERFACE_LIST.


// Borland C++ 5.0: bcc32.cpp getifaces.cpp ws2_32.lib
// Visual C++ 5.0: cl getifaces.cpp ws2_32.lib


int doit()
SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
if (sd == SOCKET_ERROR) {
cerr << "Failed to get a socket. Error " <<
WSAGetLastError() << endl;
return 1;

INTERFACE_INFO InterfaceList[20];
unsigned long nBytesReturned;
if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
sizeof(InterfaceList), &nBytesReturned, 0, 0) ==
cerr << "Failed calling WSAIoctl: error " <<
WSAGetLastError() << endl;
return 1;

int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
cout << "There are " << nNumInterfaces << " interfaces:" << endl;
for (int i = 0; i < nNumInterfaces; ++i) {
cout << endl;

sockaddr_in* pAddress;
pAddress = (sockaddr_in*)&(InterfaceList[i].iiAddress);
cout << " " << inet_ntoa(pAddress->sin_addr);

pAddress = (sockaddr_in*)&(InterfaceList[i].iiBroadcastAddress);
cout << " has bcast " << inet_ntoa(pAddress->sin_addr);

pAddress = (sockaddr_in*)&(InterfaceList[i].iiNetmask);
cout << " and netmask " << inet_ntoa(pAddress->sin_addr) << endl;

cout << " Iface is ";
u_long nFlags = InterfaceList[i].iiFlags;
if (nFlags & IFF_UP) cout << "up";
else cout << "down";
if (nFlags & IFF_POINTTOPOINT) cout << ", is point-to-point";
if (nFlags & IFF_LOOPBACK) cout << ", is a loopback iface";
cout << ", and can do: ";
if (nFlags & IFF_BROADCAST) cout << "bcast ";
if (nFlags & IFF_MULTICAST) cout << "multicast ";
cout << endl;

return 0;

int main()
WSADATA WinsockData;
if (WSAStartup(MAKEWORD(2, 2), &WinsockData) != 0) {
cerr << "Failed to find Winsock 2.2!" << endl;
return 2;

int nRetVal = doit();


return nRetVal;
What Kind of Socket Should I Use?

by Warren Young

Winsock presents a bewildering array of communication conventions. Naturally, this broad selection exists because each
method has distinct advantages. The question of the hour is, what are these advantages, and how do I choose the convention
that makes the most sense for my application? The choices are:

Blocking sockets - These are the default socket type. When you call a Winsock function on a blocking socket, it will
not return until it has completed its task, or has failed while trying.
Non-blocking sockets - Calls on non-blocking sockets return immediately, even if they cannot complete their task.
Although this allows the program to do other things while the (relatively slow) network operations finish, it requires that
the program constantly "poll" the network to keep appraised of its current state.
Asynchronous sockets - These are similar to non-blocking sockets in that calls on them will return immediately. The
difference is that Winsock sends the program a special window message whenever something "interesting" happens, so
the program always knows what state the network is in without having to specifically ask.
Overlapped I/O - One of Winsock 2's major features is that it ties sockets into Win32's unified I/O mechanism. One of
the most useful features for Winsock programs is overlapped I/O, which allows a single thread to simply and efficiently
manage several concurrent I/O streams.

As it happens, network programs are easily stereotyped, and each of these kinds of programs tends to work well with specific
kinds of sockets.

Clients Are Easy

The typical client program has several distinct properties:

1.It has a user interface, typically a GUI.
2.It has to run on Windows 95 and/or Windows 3.1. Corollary to this is that it can only count on having Winsock 1.1
3.It only makes a single network connection, and all data on that connection is under the client's control to some degree.
That is, the client sends all requests, and it has some idea of what the reply will be. A typical server never sends data that
the client did not specifically request.

Item 2 limits us to blocking, non-blocking and asynchronous sockets. Of these choices, asynchronous sockets turn out to be
the clear winner, mainly because blocking and non-blocking sockets are more trouble than they are worth in a client program.

For client programs, blocking sockets are less problematic than non-blocking sockets. Their main problem on Win16 is that
when a Winsock call blocks on Win16, Winsock does the friendly, cooperative thing and lets other programs run. The problem
is that the user it is then free, through the program's GUI, to make your program "re-enter" the function that is currently
blocking. If that function manipulates non-local variables or makes calls you don't want to repeat, you have "reentrancy"
problems. Win32 doesn't have this problem, because when a Winsock call blocks in Win32, it stops the thread until the call
finishes. The problem is, if you make that blocking call from within your main thread, your UI will stop responding because the
program's message loop will also be also blocked.

Non-blocking sockets are even worse. For one thing, programs using them have to yield to other programs explicitly. If you fail
to yield under Win32, your program wastes the processor's time as it spins waiting for something to happen on the network. If
you fail to yield under Win16, the whole system will stop responding while you spin waiting for data. Or, if you do yield, the
same reentrancy ghosts that appear with blocking sockets begin to visit your program. In summary, non-blocking sockets have
no advantages and plenty of disadvantages for client programs.

Asynchronous sockets have none of these problems. They also have two big advantages. The first is feedback. When you set
up an asynchronous socket, Winsock will tell you any time something interesting happens on the socket -- your program
doesn't have to continually "poll" the socket to know what state it is in. You can get feedback with blocking and non-blocking
sockets with select(), but this is a significantly cruder form of feedback, requiring you to maintain a lot of extra state
information to figure out what select()'s information actually means to your program. Plus, you have to explicitly make the
select() call, whereas asynchronous notifications happen automatically. Worst of all, select() is fairly inefficient, and all of
those calls can add up.

The second big advantage of asynchronous sockets in a client program is synchronization. In a typical network client, the UI
code and the network code must interact. In a Telnet client for example, the user's keystrokes must be sent to the remote
computer, and the remote computer's replies usually result in some change to the UI. Since the UI affects the network, and the
network affects the UI, the potential for synchronization problems is great. Asynchronous sockets eliminate these problems
because both the UI messages and the network messages are serialized through a single message loop. The effect is that either
a UI message is being processed or a network message is being processed. This simple but powerful fact results in simpler,
more error-free code because there is a whole class of problems that don't exist when the network and UI code execute in
strictly separate slices of time. Don't make the mistake of minimizing this advantage.

Servers Are...Not As Easy

Like clients, the typical server exhibits several distinct qualities:

1.It does not have a user interface, and therefore usually has no ties to the system's GUI.
2.It must be able to handle dozens or even hundreds of network connections simultaneously. Corollary to this is that it is a
distinct advantage to be as efficient as possible, in order to minimize the hardware requirements to handle a given client
3.They are usually run on advanced operating systems because of their superior I/O and process control facilities.

Both of the above qualities remove asynchronous sockets from our consideration. Obviously, if we have no GUI, we probably
don't have any windows, and therefore can't receive asynchronous event notifications from Winsock. Less obviously, window
messages have a significant amount of overhead, so quality 2 above also disqualifies asynchronous sockets.

There are two major ways to program a Win32 network server:

1.The main thread of the server sets up the network listener. Then, each new client connection is accepted and sent off to a
new thread, which handles that connection exclusively.
2.Each thread handles a several sockets, homogeonously. In the degenerate case, there is only one thread which handles
all client connections.

In the first style of server, each client handler thread spends more time waiting for the client to make requests than doing actual
work. In keeping with server quality 2 above, we need to be able to do this waiting very efficiently. As you might guess, this is a
tailor-made application for blocking sockets. When a program blocks, the system immediately lets another thread begin
executing. Only when something happens that allows the original thread to un-block will it be allowed to execute again.

In the other major style of server, whole groups of sockets are handled together. This method has the advantage that there are
fewer threads in the system, which reduces the amount of time the kernel spends switching between threads. Winsock inherited
a call from BSD sockets that provides a way to handle this kind of server: the select() call. The select call lets you block on
a whole collection of sockets, waiting for one or more of them to become writable, to have data ready, or to go into an error
condition. The problem is that select() is slow. Each time you want to check a group of sockets, you must set up a timer, set
up three socket arrays with the FD_* macros (as many as three calls per socket you want to watch), call select() and then
figure out what happened by parsing the socket collections with more FD_* macro calls.

Fortunately, Winsock 2 gives us a more efficient alternative in the form of overlapped I/O. Using event objects and the
WSAWaitForMultipleEvents() call, you can block on a group of sockets similarly to select(), but you only need to set
this up once. Also, this method uses native Win32 kernel mechanisms, so it is very efficient. The major problem with this
method is that it only works under Winsock 2, which currently only ships with Windows NT 4.0. You can get Winsock 2 for
Windows 95, but even then, some things that work under Winsock 2 on Windows NT don't work under Windows 95. The
moral of the story is that if you're after high performance, you should seriously consider writing specifically for Windows NT
4.0. If you must write for Windows 95, you will have to choose one of the two alternative methods above.

The "But what about...?" Cases

Every rule needs an exception or two, and the rules listed above have their share.

In client programs, it can sometimes be beneficial to partition the work among several threads, much like a typical server. An
example of this is a WWW browser, because it must handle several simultaneous streams of data. For example, it might have
one thread handling a large download you started earlier, another thread downloading an HTML page, another three threads
downloading some of the images on that page, and another thread or two downloading a Java applet on the page. Since each
thread is separate from the UI thread, they can block without affecting the rest of the program. On the other hand, this leaves
the synchronization issues up to you, as you try to fold all those simultaneous streams of network data into a single, cohesive UI
display -- no trivial task.

In some server programs, efficiency might not matter much. In that case, you're free to use any kind of socket you like. Also,
some servers only need to handle one connection at a time, so they can dispense with a lot of complexity. An example of this is
the data connection in an FTP session. When an FTP client requests a file, it first sets up a server socket on an arbitrary port.
Then it tells the FTP server on the control connection what port number it is listening on. The server then connects to that
socket and sends the requested file. If that FTP client is a modern GUI one, it may actually elect to implement that server
socket with asynchronous sockets to keep things simple.

Other "But what about..." conditions usually have to do with compatibility. If you must be compatible with Win16, you can't do
overlapped I/O, threads, etc. If you must remain compatible with BSD sockets, you cannot do asynchronous sockets.

The Short List

Aside from the strange cases, most Winsock programs fall into one of these three categories:

1.Client programs: use asynchronous sockets.
2.Server programs running under Windows NT 4.0: use overlapped I/O.
3.All other server programs: use one thread per connection, each of which uses a blocking socket.

In summary, your choices are usually limited to a single choice by strictly practical reasons -- a program architect's dream,

Back to the Winsock Programmer's FAQ...

Go to my home page
Go to my Important RFC Lists
Go to the main Programming
Resources page

Please send updates and corrections to .


// Borland C++ 5.0: bcc32.cpp getusername.cpp
// Visual C++ 5.0: cl getusername.cpp advapi32.lib


int main()
char acUserName[100];
DWORD nUserName = sizeof(acUserName);
if (GetUserName(acUserName, &nUserName) == 0) {
cerr << "Failed to lookup user name, error code " <<
GetLastError() << "." << endl;

cout << "User name is " << acUserName << "." << endl;

return 0;
Section 7 - Glossary

There's not much to say about this section, except that I frequently refer you to corresponding and related entries in an online
copy of The New Hacker's Dictionary (known online as The Jargon File), an excellent resource for understanding some of
the culture and jargon of the original Internet. I link you there when I think that the TNHD reference clarifies or enhances the
more straightforward definition I provide.

asynchronous - In Winsock terms, an asynchronous call is one that returns before performing the requested function. (You
make a socket asynchronous by calling the WSAAsyncSelect() function on it.) This allows your program to go about its
business until Winsock manages to complete the requested function. Once Winsock completes the request, it notifies your
program with a window message. This is a Good Thing, because networks are so slow and unreliable, compared to the
internals of a computer. Asynchronous calls allow you to decouple the rest of your program from the network portions, so that
a network fault or delay does not unduly impact your program's performance. See also blocking and non-blocking.

blocking - A function is said to "block" when it waits until it completes the requested function (or fails trying) before returning.
(Sockets are blocking by default under Winsock.) The main use for blocking calls in a Winsock program are when your
program's only job in life is to communicate with the network, because while a call blocks, your program can do nothing else.
This mode of operation is also called "synchronous." See also asynchronous and non-blocking.

bridge - A bridge is a multi-homed host that operates at layers 1 and 2 of the OSI model. Bridges connect two networks,
usually of the same type. A bridge is somewhat smarter than a simple repeater, in that it is somewhat intelligent about the way it
decides to move data from one network to the other. Some bridges even reach up into layers 3 and 4 (traditional router and
gateway territory) to add even more intelligence; these smarter devices are often called "brouters."

BSD UNIX - The Berkeley Software Distribution of UNIX took an early lead over originator AT&T's offerings by providing
extra features and functionality that didn't appear in AT&T UNIX until later. One of these features was the "sockets" system for
communicating over TCP/IP networks. Between that and its adoption by Sun Microsystems, Digital Equipment Corporation
and others, BSD UNIX was the most popular choice for Internet hosts from the mid 80's through to at least the early 90's. This
popularity continues today, and was responsible for Winsock being based on BSD's sockets model. See also the BSD and
UNIX entries in TNHD.

client - A client, in network parlance, is the program that initiates a network connection. By extension, a client usually has some
kind of user interface (often a GUI). Also, in a typical client/server protocol, the client is the active participant, in that it makes
requests and the server responds. See also server.

datagram protocol - A datagram protocol, such as IP or UDP, delivers data in packets the same size as those that were sent.
For example, if one host sends another two 50-byte datagrams, that host will receive two discrete 50-byte datagrams.
Compare stream protocol.

DNS - The Domain Name Service is one of the core Internet protocols and mechanisms. DNS is what translates
human-readable names (e.g. "") into the IP addresses ("") that are actually used to move
data packets around on the Internet. Winsock accesses the DNS when you give the gethostbyname() and
gethostbyaddr() calls.

gateway - A multi-homed network host that operates at layer 4 of the OSI model. A gateway understands the transport layer
protocols at the least (TCP, UDP, etc.) and sometimes understands elements from layer 5 (e.g. the FTP protocol). A gateway
uses this information to filter data -- for example, it can reject disallowed operations, for example; and to translate items in the
data stream -- for example, it can translate the network addresses from an internal format to an external format. Related terms
include "packet filter" and "firewall:" a packet filter can be part of a gateway, and a gateway is one component of a firewall.

Also note that looser definitions exist, such as for a mail gateway, which lets people using one email system to send mail to
people using another system.

MTU - The Maximum Transmission Unit is the largest packet that a given network medium can carry. Ethernet, for example,
has a fixed MTU of 1500 bytes, ATM has a fixed MTU of 48 bytes, and PPP has a negotiated MTU that is usually between
500 and 2000 bytes.

multi-homed - A host with more than one network adapter. Sometimes a host is multi-homed to link two networks (as with a
router). More commonly, a multi-homed host is simply connected to two networks, such as a machine on a LAN which also
has a modem for connecting to an ISP.

Nagle algorithm - The Nagle algorithm delays sending small packets over the network on the theory that further packets
might follow soon. If so, those packets can be transmitted as a single unit, thus reducing the impact of protocol overhead.

An example might help to show why this is important. First, the most basic TCP/IP protocol header is 40 bytes, and it can be
larger if optional fields are used. Now, consider a program that sends many small, two-byte packets. Without the Nagle
algorithm, each of these packets would be transmitted separately, with at least 20 bytes of overhead for every byte of data.
Obviously, this is quite wasteful. The Nagle algorithm counteracts this effect by delaying the transmission of small packets for
some short time, such as 200 milliseconds. A packet is sent when this Nagle timer times out, or when a full MTU is

This option is on by default in Winsock, but it can be turned off with the TCP_NODELAY option of setsockopt(). See
Question 3.15 for information on why you might want to turn this algorithm off.

non-blocking - This mode of operation is a sort of hybrid between blocking and asynchronous modes. Like calls on an
asynchronous socket, non-blocking calls return immediately. Unlike asynchronous sockets, Winsock does not tell you when
that operation completes, or when it is safe to try another similar operation. Instead, you have to either use a "spin loop" to
repeatedly re-try a function until it succeeds (a Very Bad Thing), or use select() which will block until the socket(s) you pass
to it are ready to do something. (You make a socket non-blocking in Winsock by calling the ioctlsocket() function with the
FIONBIO option.)

OSI model - Of all the standards to come out of the Open Systems Interconnect specifications, the OSI network model is the
most common and enduring. The OSI model is a seven-layer view of looking at the network. It is presented below, with rough
analogues from TCP/IP and Winsock.

Layer 7
Application (e.g. an FTP or email client)
Layer 6
Presentation (formats data, such as encrypting or compressing it)
Layer 5
Session (manages the logical client/server connection; e.g. the FTP protocol)
Layer 4
Transport (understands low-level client/server association; e.g. UDP or TCP)
Layer 3
Network (routable packet level of the protocol; e.g. IP)
Layer 2
Data Link (e.g. packet driver)
Layer 1
Physical (e.g. Ethernet hardware)

Layers 1 through 4 are the hardware and network stack (including the Winsock layer). Layers 5 through 7 are all under the
application's control.

RFC - Request for Comments. RFCs are the Internet's standards mechanism; they document most of the "open" aspects of the
Internet. See also the entry in TNHD.

router - A router is a multi-homed host that operates at OSI layer 3. A router moves packets between two or more networks,
usually based on configurable rules, based on the contents of layer 3 (e.g. the IP addresses in a packet). Most modern network
hosts have at least some rudimentary routing capability. A simplistic example: Consider a PC on a LAN that also has a modem
for connecting to the Internet. It might have a "LAN route" so that all traffic destined for the LAN goes out the LAN adapter,
and a "default route" so that all other traffic goes out the modem. Try the "route" and "netstat -r" commands on a Windows 95
or Windows NT machine.

server - A server, in network parlance, is the program that waits for a network connection. By extension, a server usually has
no user interface, and it usually can accept multiple network connections. Also, in a typical client/server protocol, the server is
the passive participant, simply responding to client requests. See also client.

stack - In network parlance, a stack is a set of layered programs, each of which talks to the ones above and below it. Below is
an illustration of the most common kind of network stack, showing how an application program talks through the stack to the
low-level network:

Winsock application
Winsock API
Proprietary Winsock DLL (WINSOCK.DLL, WSOCK32.DLL, WS2-32.DLL)
Protocol stack API
Protocol stack (TCP/IP, IPX/SPX, DECnet, etc.)
Hardware driver API (packet driver, NDIS, ODI, etc.)
Hardware driver
Hardware API (specific to the networking hardware)
Networking hardware (network interface card, modem, CSU/DSU)
The network (Ethernet, DEC LAT, serial line)

You might have noticed that there is a stack within the stack: the protocol stack. Just like the network stack, the protocol stack
is a layered architecture, where higher-level components talk to lower-level components, and vice versa. In TCP/IP, for
example, TCP is the high-level network transport that most applications use, while IP is the lower-level packet protocol that
TCP uses.

stream protocol - A stream protocol, such as TCP, delivers data in variable-length packets whose size have no necessary
relationship with the size of the packets that were sent. For example, if one host sends two 50-byte packets to the other host,
that host may receive them as 100 single-byte packets, as a single 100-byte packet, or as a handful of smaller packets.
Compare datagram protocol.

Go to my home page
Go to my Important RFC Lists
Go to the main Programming
Resources page

Please send updates and corrections to .
---2138437061-33463914-899838444=:28808-- XE|bm501E|bm502E|bm503E|bm504E|bm505}E|bm506E|bm507aE|bm5084E|bm5094E|bm51|bm510E|bm511E|bm512E|bm513sE|bm514EF|bm515 #F|bm516)F|bm5171F|bm5189F|bm519GF|bm52|bm53y|bm533_|bm534[v|bm535ю|bm536k< |bm4836D|bm484ޯD|bm485ӷD|bm486D|bm487D|bm488D|bm489D|bm49|bm490E|bm491 E|bm492E|bm493E|bm4942E|bm495HE|bm496OE|bm497\E|bm498FoE|bm499wE|bm5|bm50|bm500XE|bm501E|bm502E|bm503E|bm504E|bm505}E|bm506E|bm507aE|bm5084E|bm5094E|bm51|bm510E|bm511E|bm512E|bm513sE|bm514EF|bm515 #F|bm516)F|bm5171F|bm5189F|bm519GF|bm52|bm520SUF|bm521W/D|bm522׎F|bm5236F|bm524F|bm525F|bm526ʨF|bm527AF|bm528F|bm529,F|bm53y|bm530F|bm531F|bm532F|bm533_|bm534[v|bm535ю|bm536.|CF1|CONTEXT"|CTXOMAP< |FONTG |KWBTREE |KWDATA7 |KWMAP |SYSTEM|TOPIC|TTLBTREEj|bm0|bm1|bm10z)|bm100|bm101|bm102-|bm103|bm104x|bm105|bm106>'|bm1078|bm108|bm109V|bm11-|bm110|bm111M |bm112|bm113a|bm114|bm115?|bm116 |bm117%|bm118*|bm119?|bm12r2|bm120T|bm121;k|bm122s|bm123j|bm124*|bm125ѓ|bm126W|bm127|bm128?|bm129:|bm137h$h$+CLONE BUTTON.BMPJGCLONE_BUTT.BMP4HCLR_PAL_BUT.BMP)ICLR_REPL_BUT.BMP;HCOLORCHALK_VB.BMP!NCOLORPENCIL_VB.BMP MCOLORS_CHANNEL_COMBINE_FROM_RGB_VB.BMP[NCOLORS_CHANNEL_SPLITTING_SPLIT_RGB_VB.BMPrNCOLORS_NEGATIVE_VB.BMPNCONTROLPAL_BUT.BMP0ICOPY BUTTON.BMP{GCROP_BUT.BMPICROP_YB.BMPJCTRL_PAL_B.BMPشICURLYQS_VB.BMP=8MCUST BRUSH.BMP5GCUSTO_BR.BMP3qGCUST_BR.BMPBHCUT BUTTON.BMPdGCUTOUT_VB.BMPMDECR256_YB.BMPϞJDECR2_YB.BMPJDEFORM_YEL.BMP~JDELIM_B.BMP[IDELIM_YB.BMPPJDROPSHADOW_VB.BMPMEDITFULL_B.BMPHEDITFULL_YB.BMPyIEDIT_PASTE_AS_NEW_IMAGE_VB.BMPѪNEDIT_PASTE_AS_NEW_LAYER_VB.BMPNEDIT_PASTE_AS_NEW_SELECTION_VB.BMPNEDIT_PASTE_AS_TRANSPARENT_SELECTION_VB.BMPNEDIT_PASTE_INTO_SELECTION_VB.BMP-NEMBEDWATERMARK_VB.BMP;NERASER BUTTON.BMPWGERASE_BUTT.BMPa&HEYEDROP_YBUT.BMP\{JFEEDBACK_VB.BMPiMFILE_PRINT_MULTIPLE_IMAGES_VB.BMPNFILE_SAVE_COPY_AS_VB.BMPNFLIP_B.BMP7IFLIP_YB.BMP1JFLOAT_B.BMPH)MAGIC BUTTON.BMP HMARQUEE_B.BMP,HMARQUEE_YB.BMP_JMASKS_LOAD_FROM_ALPHA_CHANNEL_VB.BMPNMASKS_LOAD_FROM_DISK_VB.BMPNMASKS_SAVE_TO_ALPHA_CHANNEL_VB.BMPuNMASKS_SAVE_TO_DISK_VB.BMPNMIPAUTOA_YB.BMPLMIPFIT_YB.BMPLMIPGRID_YB.BMPLMIPSETUPDB_YB.BMP?QIMOVER_YBUT.BMPJNEONGLOW_VB.BMP$MNEW BUTTON.BMPjGNEWIMAGE_B.BMPINEW_BUT.BMPνHOPEN BUTTON.BMP5dGOPENIMAGE_B.BMPIOPEN_BUT.BMPHOUTERBEVEL_VB.BMPfNPAGESETUP_B.BMPPHPAGESETUP_YB.BMPv4JPAINT_BR_BUTT.BMPIHPALLETTE4.BMPJPATTERN_VB.BMPbMPENTAGON_VB.BMPWLPICTUBES_BUT.BMPHPINCH_VB.BMPMPRINTBUTTON.BMP3HPRINT_BUT.BMP IPRINT_YBUT.BMPIJPRNTPREV_B.BMPnIPRNTPREV_YB.BMP;JPROMOTESEL_B.BMP{HPROMOTESEL_YB.BMP.mJPSP_PAL.BMPFPUNCH_VB.BMP MREADWATERMARK_VB.BMP4NREDO_YB.BMP9JREPLACER BUTTON.BMPjCGRESIZE_B.BMPILPAL_B.BMP=IUNDOHIS_B.BMP HUNDOHIS_YB.BMPKIUNDO_BUT.BMPHUNDO_YB.BMP4IY_FLIP_MIRROR.BMPJY_FLOAT_DEFLOAT.BMP+JZOOM_BUT.BMPH0 RESIZE_YB.BMPJRETOUCH BUTTON.BMPQGRETOUC_BUT.BMPx-HREVERT_YB.BMPgJRIPPLE_VB.BMPMROTATE_B.BMP#IROTATE_YB.BMPH&JROTATINGMIRROR_VB.BMPT?MRULER_B.BMP]HRULER_YB.BMPIRUNAS_YB.BMPBNSAVE_BUT.BMPJISAVE_YBUT.BMP_-JSCREENCAP_B.BMPlHSCREENCAP_BY.BMPISCULPTURE_VB.BMP}NSELALL_B.BMPHSELECT BUTTON.BMPGSELECTIONS_LOAD_FROM_ALPHA_CHANNEL_VB.BMPT{NSELECTIONS_LOAD_FROM_DISK_VB.BMPkNSELECTIONS_SAVE_TO_ALPHA_CHANNEL_VB.BMP&mNSELECTIONS_SAVE_TO_DISK_VB.BMP=tNSELNONE_B.BMPʣHSELNONE_YB.BMPEtJSEND_MAIL_YB.BMPPJSHAPE_YBUT.BMPJSKEW_VB.BMPMSPIKYHALO_VB.BMPkFMTEXT BUTTON.BMPGTEXTURE_VB.BMP&NTILES_VB.BMP-NTOOLPAL_B.BMP=ITWIRL_VB.BMP"MUNDOHIS_B.BMP HUNDOHIS_YB.BMPKIUNDO_BUT.BMPHUNDO_YB.BMP4IVECTLAY_YB.BMP0_NVEC_OBSEL_YB.BMPXNVERTCYLINDDEFORM_VB.BMP@LVERTPERSPECT_VB.BMPLWARP_VB.BMPMMWAVE_VB.BMP*MWEAVE_VB.BMPֆLWIND_VB.BMP&1MY_FLIP_MIRROR.BMPJY_FLOAT_DEFLOAT.BMP+JZOOM_BUT.BMPH| FLOAT_YB.BMPfJFLOOD FILL BUTTON.BMP]GFLOOD_BUTTON.BMPJHFULLSCRNPREV_BUT.BMPIFULLSCRNPREV_YBUT.BMPBJGAMMA CORRECT BUTTON.BMP6GGLASSMOSAIC_VB.BMPTMGLOWINGEDGES_VB.BMPRMGREYSCALE_B.BMPHGREYSCALE_YB.BMPJGRID_B.BMPHGRID_YB.BMPIHELP_YB.BMPINHISTO_TOGGL.BMPhHHORIZCYLINDDEFORM_YB.BMP)LHORIZPERSPECT_VB.BMPnLIMAGE_ARITHMETIC_VB.BMPNIMAGE_PICTURE_FRAME_VB.BMPDNINCR16M_YB.BMPJINCR16_YB.BMPsJINCR256_YB.BMPJINFO_B.BMPYHINFO_YB.BMPbIINNERBEVEL_VB.BMP;MINVERT_YB.BMPWJKALEIDOSCOPE_VB.BMPiMLASSO.BMPHLAYER_B.BMPILAYER_BUT.BMP;7ILINE TOOL BUTTON.BMPGBM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׹׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬׬׬׬׬ׁ׬ׁׁ׬ׁׁ׬ׁׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬׬׬ׁ׬׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬################׬##׬##׬##׬##׬##׬##׬##׬##׬##׬##׬##׬##׬##׬################׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬ׁ׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬׬׬ׁׁ׬ׁ׬׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬ׁ׬׬ׁ׬׬ׁ׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬V׬VV׬Vׁ׬VV׬Vׁ׬V׬ׁ׬VVV׬VVVׁ׬VVV׬HlHVV׬HlV׬׬HlV׬l׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬~~~~~~~~~~~~~~׬~׬~׬~~׬~~׬~~׬~~׬~~׬~~׬~~׬~~~~~~~~~~~׬~׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fׁ׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬׬BM6(  3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f333f3333f3ffffff3f̙3f3f3f333f3333f3ffffff3f̙3f3fPK in kYu!/ 1/NOWAY1.TXT[sٕ.>"& xTUu@Xś Rr: $p^(RGCaXq7Ƙ3g %^ktwrΜq>|`ͣߘM:5*ihZq9g٢OB޺{hi'z6OG<^ʪae4 3Ⱦ}G&O|r uZkAQ0 ߙ>1u80tб%ЄQBIa:mX<|0 &47= QFGync_i7N&ЛޙfZ$eaVd 5$!ibG뭇h="zȂeU M<ë$&*J{^Y>|&c'IYty7fXvFt헴XQ|'v0I,9O8,81JgechfaR/K|qeEv:2.J: :gi {Y8jnL̛_ʈ/tDI'x͛Ü\FJoڍn&y]γl>UeM7 M:,@h <4f 44@tჼ BIE%}Tbdކ4,>K+%t )94 dXπL@,Q>2r̀]T0,(L55CSC@d>:P:;/qyZAaF&Y frmNq:",#yt h%|9i8 @7d„=!D| 8yge M54 =$Q>0Ao6̈L50+vN.UN8&V‡6{sF\n? CF(fLOҀj҈ MxC']ga?kuH롷9` 8:@ٜ+0^&K`jFG8JW #0j-y $/>HFIxH䅷$sfa"\n0 #bѰ/G_ 5m.|wti/譿`k[ڂ$s5yS>@>8ӥBHG`Ef:E^ދ0#GhDpIl9> JNGTFk9i2sȀ421񵴘wyжl\#>B Y0L0C^r:5gq@H,8FX`>HO:A qfr̀@`Q]Ղ2IRC2IB7Ì0_;GKO@IE#hFڤ(݂rRӈȖئL_,w'CsFCm^|ݴ Yet'_G<YHpY HD(H4οtwnA‰˃H*,(p4ouE=!mq=e4 hIU 0I,-(ԨEr1G5MW'Hot").нGHCE qQɱ@D̺%'xZD=#eA|5F wc ֮E7&3+/hA0DP²X)EQ '>ngq`6[W ˅э<zkY˜^f ^476ҶRw<0M)՜9(4">4 DŽY/!>9]!muA$-D " ,gf($ #kfC\ AmDu.NP$/9DNz] nn~ic8yg:K$lA;1ؠseK^2-A+kTl122Q cZjmܬb*Ӏ@ ̬ʨ߇7T[!ykVљ9$-!x@g֋E< 2!]d<ˠ1J:gey2NRd eoSh]"jԴLt5zu \1,ق)G/ "i8*s @?8f1$h =4EJOE!X35^Ewڅ\'DyN@3(-qVL%҄OXG` M zr@HM;^F8#'?0qzzrv^ۚhң4]51o~\O9Fג5QDrN@X3n |E%f,s32%L"A$bU%V5PeE4} V`N0)+a_ ]2kBR X 1r`y&\P%; *6n/ \ES̱ t@|L[[%s"d+9vhrT%;a]W42̳Ad{f簘M"1w<|Hld- 6gijHX3Wщkra pvv%1' A##7Q;,oQ@rU펰7ne DաE*":P!q4e|WbALHz}Ddts(M?~>?xs>0-~@0z`eva.a)f{ta0]!|4v|-o{)~ZSL sM:_/\f;)Stv}Oh>Ksv@jUab~K{pB3)ןESҚmtb`|@WR K~xtprMvh.Q*(ҴÈHƆZ:ןssy̪ ,lm2鏠{jq-hѻ|,/um:?~PG6uo ή9R?D@ȔO跂xos.-l%%D~-~l=qz/:'{kz73ǛHڅO2I韋996~t"C=/CO)OG~fz,tt1FI1i@{Fn}NHBҔTa˜0-HL6E#!-$eNٱ{:JxM)'K70e PlOh 3u'ۺhf*VR|ٸngbLqHME^瓔tfP΃SdIqˤ%f*RhrxMͿb$18|ں<:T$lMgsz"My68-a20ά׸q %e.UX\f,XfWjtsx&+lWvB3vX/a Y0 #ѥ1YE{=#D%o&J$fVAdS0z0Hb6̰nF+l>\O2I G#bx|XGM_0y.fQ.y&j;d^^+>!S&|hmiIS6BX ۫z`وᬔBVJSqKRW &)L 6t4'HS tReU]N  3196S=W3 Abtya48h.q sL6F5'W3T{(8ÿA< ';QO\zkD;oMQ ?-FuE:k4-y/휩 R68˜(PKk3C +Ӆ`JaBX15|Ѐ^QňID[5WjF\🙋pgH l0G4sAkq/IX6\ߘĥخi`PaoS H3;4kx$4dyJ Do@K~cGԀ;x-.^ dOh= ?ߋ:VR G60oٵ9ʡB8KnȀ&c&!P-$$p$T `r(30)1pBg, ԇ.n$EiDBҰZƫC^"`8.۝v}N G&q>*E`C=Lr,,x2gXV%*9ՎL|tFDq us(sG\Qv^$m!Z3^T S'˖~*%_2b2t6%[ 1[D8YUGU(>`0Ai.Ll$XpRyY >] WYE%kL1BA/tU/Eu?,`o7o6zj\۪U =#VϹ2oJ4ʾ[y_򏵡i?V_zૃq?>oy:?"^>ka=knj^{o?!cX9woqHe2}cyozXHtvnLopQc{ƼxMaްg]yi{f/^1ݽcթ#{_ş;^RҶ74FQ,/_GyCjз8?+ge]͜(vH 9=A-zY4󏠥@&z>y0X% yEe!M9S -ݑbHvH]6cU'6Od~]9HFM]LpJL)DWHBS'ɬޫVxjٷU;{".atTF t][St*,{Q#[7>kT TmSRs$մL7=&!@`lZ;X߈3Y?.A1Ibe G?H(A2ɚRR$saFWb!iAe3,^ja,y-ՉSV1i%oJh8嬑j@~$sGБx.waYSA$-'ⴱ0evXnF-QIYh}\Rnץ5(Uesfj16d_ՙm,5Z,;舮$q2o@-ә9 HCi@&%"k?i՛EPׁ#V f'1ҽYD/Ւ]Eq-7b6Ć>I 5S?kllsbLHq*I߶8uFR EDuY!XXc3F&'LT0)/})tM'p~ObW܆I`8,'o58Bqvnfs6ĻxFXBJ. +XucOAet@JkHZ#+vܖp}@i _e~$ MwHFK6sBX]q!-Lv;O'Wq,r?:9뙣΋MŮws ze$^K O*F#ڏ@ ]?њe*YH[:_3åMt:y[&J΢̜h䈄Sv3I*0JEN8 T.g*!sЧŖ=fA]4II-M"EiBI9!\L? fǂS$AXD&iB$*[9Y4)(i`8]e\tw@u:x⢷bu "+;yJJ,~S ~`,D#I}y?,zF)Qg $'bJ?xy9M.J- 9戓*9Yi6@,$U:b?*KnN4.Uǰ샂x,TB0C'd_]2fz)udy9$G+R;()kh$eߝ R-8DFpgOr7iqc dU'8PY)Sz}.ʖ^ 1cXtZ6TG$:%j67a֓YJ:6.>,:5aA{Yl= ټL$[nh] +/#DZQXc̣DJ"4 GSlH1BjA'}^ .iOGD 9q|d4'*?S?F.yo$rxL,vnÍ/mABEdlQu]^fl4/lbt GLnyޣA=H¢]G#9(IjS @Z8BIiJl?d:,##QkP+| =ih(B|-"v6ϋrj/?Q DS}~sC[: -\m@ G9 Z!N2MZp͎=+w|%@b \a `, ha:%i61'$2rE&0T>duV9?(QDvV>g^TLȅuio{fLwF~tXkް9<zc7[v],lGs=u lel4D*&2U8z 6ZRxR4y2ʡJd# 2#KB, !8Q>`nA㏉s%3.N Ys!P60aC4.<¦4 J|1P!K|#VDWa;gOW:4 QļQ]|A,[+Hk (Gc$:O][Ju^ U5 a[S 7)J`V`w"+*Ա*އp뮜}0([ltmMX (Hqv>#M?Aqi@j1q1Xjm>k&Qlb F=1C`"ltf΢- mö1 cG1>"8k" _S~.qVRÿrЈ).c~Uq߳ K'a\ҵso!"Oν q?HhYTgO9cňrE?7mUbޓd—$}kYO~͢p!8#MZzk&Q4]$ W~3{P`j^Dy Eoj^BmcNS Fw `_zsb]e`˧7Φ :Q)k'5DD qôrGHKonJ?ƌnAK"$m|VOaB,j-PZ^1 غvM8rH.*D|5=/U`|rUޔY4j PN˸Laǜ3/0D}Ǵx5TL$>Q#=g[71띌#; G5BR@eDDZBIP 碶yleSdc$b"lH,M惃5n>la-}IR6VĈu F \!]*kQ^նDH+6P7\#M<{Idf;m-,-E1 $tQٴC`}a$(L2JjLī`MKd;7~oz/fI(KDdFɦ սfkSpL-ؾKςat&ήߦ8Ps:ReQ/"hVZO<,^17s.1ǁ:ʵD9eN~ϽT^h"gQ@zm66 YVrd#f1.,T.+m=q%T5?}W^E d-Ml!MJֵakq < Y:)%‰H d,I`H6%]+leFKB39\dfb;K,E"b&562˓lF"Gms:_ahs_x7;k;3fҪm˭tmp\jZꘈbY֚1(9-6a58" # *^~G94SaKq]Ɖvc #1,?wfRz=j#K w$nͶ<#3j\(b15Q$S^לr♂<A2Jy'tB/-싳\!NuUbs$ @SGkLZZ1VW+Oq+,42(d}m̍N~vii1@C ,5Ҳ=χp31Ox+vr̗g,D &䁖JZ^R~AQ)`6A䉲8p"+ RcizZ!^ @n3C8/+|!MQ,dDճ{p?Q[}T*W\ DjzoY 0/46Cj[ZfȿM]P;MI fh;$-mYEyiiOjH<s//͋[UoAjN\jr/L$:ImRX[Ʒ."O/&vkؽ$ mٞ,%aCgq-ĿQh# L:\X?8ϛYں$X(#u*4LBY9(ˑ]'cG]lY:Syc*Ig wTհQ]5਻i ԞJ}7qtJ_$]BBp××* sIc6m,!ց< Vw%K =ޮ [4Ruԇ4oQ}\ I%ҙ爉pR~m p^+mH`oLs .D>=-)'d0щYT!D[ R۪ӶV0y>/VOC`-w$(gUenx!<`[9U__"smp]旖%a{ K3n2mC*lM60֙[ F9a` cqpUBNJn౟Zչ^0k8ڥƒ &sF:Q+ 6H"5$}Pˆjx.7Ѵ2Q%2t*jUۅF-I,,ϻmb dxճQe7mk?g V$䶮xum:C̴,0! 8 W)} f(5u80W-akڮ>QOX|s2ۮbr ̡<,;-_[H %/ U8) ijZ'#nu%Ү>hL iM$M11| JR.`kr-+2SaIf6#Rɓ9EOz+YNWWiy30{s'm3M=P$Ob$6ChGT!MPXU9ʸa05/<f|@pL͸ j"g*ǙRM+[Y#88A86rG|%9G$P?tJQ5;:uI[İc1BJs<e8dt`.-z8+XT^RN*GhY&ıjrш{VpOh&D[+Ke*H:ؾ q>"}Z)Z&7l9$B'!vr(HeTz^[Kjb ɤ[|Jϥ RBAxXm 3T!h8_rJם)~ ɐYw|c]13s44 `_ fA?5F֦#N5./BudKK5ВrmXD#hHqݪjɎ%;u^l *`o͔fn ]El.q#TM-լ iVЫJ=%J8EG ]Gy\"_$DFbބ\B-qG}]TAle \&Y6(m2+ɄFj=Tvp~ẗJA j ԅ(pmZ< nob5:©8BEWQۙ"KRYS/J*IW#^<mƣ槴yY"(bݐ3Po6FPf}X)L#;( wp"6}J΂[l[^u5fnp%]yWY(RƩ&a%\۾SA1|]nj pm fZ=Z_vZjjpSE(YtNm %5ݭ#T]y0#8@$M0mQOP%uA#;<%hN8_&,@3&s! :!\gPm ˼fKVOH-ȭU¼z wcD,:y+RDWPaI8͔LۛdTBπ5f4IpORHB2e^@\Xg֯I03/4p>b OOhkꭍo bRc@m ku Hy@h[.;AZfCA]kNFv:_N, E/RWXXS<mk/F8X(7xd e# oK9:̼Eb-i޴]RUCBŠ. R NMl  1aPLm LtYT.#\Ba=NJ76L3. `tiDL]{εQ_ >UlǪ@)&kb$)p8FESC&VV Q:aUµ@4ku lU zԗCsQ%kR#U}U6[FǺdZ:pPd8C.02bl&[vb )!DՒVuLKVo|`nՄ~Ԫ(\:!՚,dczA gc?_< ˪lT$5Mr]#d܄p`Sa4'=bqa!k;;5'%HAG-eYt'*Z `z : +Bg0m LbθԅXPm.]U8h =[ {nPGsKUs-cX4UTFh?ȘVa3vFq!;%u9J5lahpam1ڍo[6HSDsT~&< Z@+%]'~BpmT~m^mG2m$)2hG&bHfP(x(U `ę>mRL$Qk"m0”/%?j3іEeٶ6g!WYT`JI:ԢmU `SPVRJBcR\"9Ā"!&Yh4b# }/7xyez'gLjR'O wei.;3D7%ѳonYh\0 w5ځ+SZJ:_omRF9iXlPxPN;C*S0EL"i/Ⱦ2E|~%ӼDUp$[O=_qgHtYE] ʊ1pAos\"U1S@h?bN,Z ,I C )Pä*1 /;"YU- XH}*(%V^?.Mkodm 1;]|ӄ ZLY\q_3B]RlQ$G$ vۂ^tZ_lGR{DVp.q=y ZAQܖ ^sLYuvw\F9,=y6tszwNQ>( qwa3<|YDޔ0~)bE^{^$r%-xÀ^jPp/m+ʇs#zٶD f8i"bɈ(0W--RTh-qzTkrtU8.8.(^Q{RCNRJUg3cQ'jL󛧿߅^/sI|i4N1Y ]Jjs.g{{QLm6Ygʎ2󜣛o[|.Ԃq겂`gtZ0c*~~War-o~qߛ_wt)}f?`D֍*o$_UݣW(Yk5vi+5qA+>o9аPk3^hα9p+`irD2^I\VC{\'jF%e\f ] }7paq㖁(i,F _Sɚ /wɐlSwR6#H=|@@ͻ B d9~e(k`8PlG@pj8PTm@x aWTDG!mIT8d$N:҄U;JؕkοmDB![eHS76{8ub˰& %'wS>0~Zdf{1kATAeaۚ\P,Hckt^ -J#rf]Uf`YlM kp24iis0^]t]}1gkcܚz{Y_u1J36Ѱb4!t'tNrʆXW_(kz[Yq%#t>p:'<"2д5&Ǐ\-b (/c5{l(.)&'XՊ,Hu53lpe/ GcwUoNzU+Љf꽢H6`B>$Ïaf+0CxWTFFnXp0R3PWߣ,bf&L*Qa'mE%SUHu,p@J56FjY} 9%HŒF|ɚ{r=!4֫*kYIk2 @"!+Fb{szD&;c:qPXoeRjJlwU|?q񧕍e )P/Kγ34>QPajgMvr-(q8;tVVvR[ V_Z!Y: g>Gp!iR!LF|jx%WBk<.9?&Ko.*siNpwF(Fs#-!hqK oLU8f̭A39lITlmi>7Rz5`Yb co] ~z {2n۟] qFݲ6wWhwWA9JotM{x?xfrt^RqB`|N9fz N *qk8ch F̟:[*Q,cǽmSL2 R18;Kd M:Obhkg= wdpS\ leʆ\QAFMke?M:ܤ8Z;ba@|>d QL &zQ&6M9cM"Eػ ^%eг'co_5LB^iҞZ- ȧ+qntL/,MuZ # -GLB"VGuQ9Ώ Ud`"%uW\ѾR3oE~g֕GwYH,ӄcYsCҸ$ [7]UVf+)e8c͈&;f?Lvh3klt&$q@H&Qƣ |YNٱ 9G]D o@a!UɠU. U?״{xtpn+y_wܿ8`wv3 -YUk {$,$T-j ĹQ** Zj1HI^mn4cLh޵-B-eHk‡LX̃1hed 6i˪fJpɮip@)ɐ7e "YV̖hu%]N)$W.+_aY ,NT+.sTZO-9ܹ5ǡƽIe9.2%(Bg 5DdH-&:ݹ-T5sЦt#1H$r%Ө4v ЕKx65$V(ȹd<~$h[цG%4pONL+S04 (fHB֘B\ʓAX=zTk. ]!nɓZBЅ ZvPD]CoNu>?qO/Kb LйځOJZVi$%OBJ0h!7$պ"K.t`sWВk1?0j#קWfsik;S3jxqK_\>u-xM{|q0. n@[K= -5qo܏8g37܆~Ԃ{+ 嶐m! ,ǝ"3[ H(-Pעg]VrP2nSpsrAڊ`iLosZJft muI**IB:I4¿IBg^,XɎQxc1-A.RpNJ6WjdMfeDyr@cs )wFqF-/\4ZR/o^Cv^葻Y2MG3i.3Xlyի;ŕz޵y<⤼`aymg2JE&hwrMgłM79e_  )"W)xNׅn 5ޙ4扟.WQl`眳l&-i *Zq=fT=.·lAj0PԊ0B\;tzN2ɀy[ NaqAuݶoZBoM9[aKYUhtf#Jօg27xa\Ùf c7oE>ؘM%\J(58 D:4mI]"Wԁ䪄k~Y 0[iEx$O9zψkiqb: ;咝}Y /4rNoG6tR|HS%Dx$1ut.Gq"@D͆XCP"A^܌X(`=W#-*oh q>޳B#%T)Mg乮9 `.p-?]^Egǂ-H(uE+zqw3'g"\-dP%3qAsL(U6ڈ({83).=gp,&tU_F)dyBCH%2VYLYlUF/ADj*iSsis;B)v[/ H=?(K[U2\KD Gj;@YosSM ^@$&/wv9iS"T0fq?;b`Jr*=I zYVBˆ0ljs"]lC;^)HQt,Du ," 3\HTh!ֲcdʹI)B^%bբ}^KɎDN)b=sDe6vjs""s'{PML|[жl*;h)mJSj*+Ͳʲ9>t~vB@Q#U6c^ w5۬5uňvrf3@B+e2}k]B V(#gn_M׉jR6+E:ۨXµ/TC&9V:L +bv%9*f.3!8Ck_r}M X6-Km^i@G'l #q.QxݭM4W6!K85cP)J3e9'9nŪN}6\Y:FoYh9ʔmәM\#LE;*]a((!Q}RrPCrge' jϳ1!w@hR@-?H/Yr=WP,g*DnM{y7`O"j A|&qpi'>W6Fa5ʹҌ.>4J]%l\d87u$!XuPA+K"3c>tmr3%YgCTe1]աp:nީ;@Z7@!6uhj?ceJDzpE|[|i-+Mt:!lby~u%?G0dzrγcv@Wj% ;4q`xGސX '}O?&b<|/Bh) ʄ;<.5QTEMK  Q`g%ޝsW ,_=NÔ+ PZiSI g 1&C ]τsQrŠR܂8#d &!SQ6Miv#w=$0 +ҥ?/}BuT0_|E+|$1- [˗hۃ__~Hc+ǛSEIpB|T 7+9>z:eiw6g<ġw%c\x4 DX}KthCe2Fw('8ِEPEߋi#wjr/)p/݁)S}+]`w { uD>ÙҤװ̈́ {k +ڪhѓfI}v'9IE{ 2Q R $߯=zD*D:]w%|ycҭ2G~ILm4!XLd]IwMivҰ{i+.x}[{8/X_pBȂwS:gZR(u4`mtאJL7./wS6ISBgAEeRqbӘ`7;Q [_|>/wˀ %XDdtNuU"|t!¨p"$ɛX Q529_UCyK, ;ŭEP/'StTk!vǩGrM=}+z- "Hl@ٜ4XgXת1XfWD`ߧ!)!FԳ hî j1C MX2!i_!&"=ddւb[IPY8JUb$e`9P [fXtyWz>%*4A !1#y@Ļ+*ݰN9:8ywލx`$>\F8Ywy&g+bacS=!J  tI~Ƨq4A9EUId%臒I% TBKFO 6 о?dP)%2ޑD8DFxͦOX fkVm|CrV'4|k z9@m쵊w4Q5|@[c>I@L‘YJ9iz6nӜ,ijɨ ~κu4HTt?C@a\>MKƁVJcKp{7!?Q5TB}~?>2ėupMγ䅓? -X_'|fSZ>pMNǴ`w)$5a AKB @0!&-w?6{yo+Ģ{/}݅ng I @Q2AH`QmV&T))-O4)D$0`Pa:kǂl5^f>O:EꢊcesKkQ‹ҋȖFX‡]4Wl`{N}>p]%_ò((6YvT/SN1I\erA%цɑBCnxȨLxYa$ݨXXEY@Ex~ SK]r589>|y>Udl)eV?3aUzNE _2Hވ _Iy)2n~dUS {w{kP, u#0󳩹*~VYkvEy:W8G2Y\QX qR;oԖvfY WQ +&i/=,5.e(`2Aj9CbUswK.̿gr~p+'=|9L4n!7%pb%ZLm~~ v"!G' -VS ߚ~ . V˼Dzx!5IUIAy䨿9/iA-V+tC!fI)Ɩ,5 At0QŢhg]5\x|wd8F0FҦ|o%WՄq&C[* }VpXfh8&Ff:3t0=/H`}y(|tɄK4#"zK'NV_Q [6ytp=@VѠ$F/ s'-Y^~@?*Q8UA)tYp! 9ɡPA![FM{~=E4BJ]xSBH|~rAsu6l2!GiL8C]Uzk\zGcI2}CtMI`y|t&c?ՆwP}Yft94q?qVCVt5.̸)6lE]ofaB9:d߈*#U7ӥųWI~}aDl@onx3^ҸoU4D&k'%7Ŏy_/mc̅as`rV}D-k sOAL,1ӐjgS"N<-'4&`j)iӠ&7>gQTqS?>x6jN@XQNtFXxU8BvrnEUѬeNʒaak@PCA^6l;HVt5lZ*G"^Hi='b-?iMW^>vݧpgZi"vOyx$*Ӧmt[@IT$![7 9" tzֻx㈸ՑF&oun@Z^q/D,҇3ӳnn>/Au}`cL* Iq* _gc#oR3<9 ᔄh)w t gYGp:zD}hGK{ge1ր_Y#AzT1Cv6(/PeQlAAeKO  "K6AQf2C᭳2TE~X寜߶2+C\Ҷ 䢚}6}dzAjHN`B::mNQF^ WWpwz,@%Zc??8t1':?"be*UҦ9j'ğ6[VIn!l_%hS=]# yH +R>xqӼTe$PV.2Ko"}" m|*Ka~6ΖE2'e#ŗ|!_[ߏ܍/'Aa?/6a#:giz'YV9MQ3:O߆^[<_tI_ً7[csVXMۆ^\8JSTmA*zYqĎI|.~qȨWp]%=BM _'^A\(  g ~9Ӵ_#68]^6C H`5ˑ2*6:v5 $#/)8g9UuX~Uem %&O lӨ9~PO4 BA]$ %uװ͟9WLJIQ@)wo͞Pɓsϳ/ϟϟHg+5GXףAsMh!/2#=U<&O@+(^Ȝ ]@iW\~WOO';vOP~گ̓$G:0zǐD:L& (BZqXz|~\zp`t_JNt&/t%sPk5*C!VudiNKʰ^3"{Hl*+H',Lz".Iaz%kx=@IF\lk\/e.VqEWg)DC:.,e0Kμ&Ll/Y;SԤNrYp x-w%PO|$*h]&(Eq -.+{jk͵J9΢Py~ąiɧ^/5{Ip9fEudlGeVFiP?+՟3K$8sݟ#CƬ*+Gݺ>FXCL=MQ$d--=FjQHjiǨ3-pk 0nC#t܊{M/er^+?D5vX5ȥڇF,"ɖxӁ,iA/nh(]`춉^EVÕms8c5X2ӊ,пM%mb gc-L"G)]ޥ/9-ep^0,e4l9mG^!aUwoqkY~:8mGZkZ6(uϭFRtb6al6 ܐl=iim)CG$qmh&P?&D[z/"#vE`D$#=4eG䐪0mСBʥ|?*w9.$/gGؕT&zҟ 2phni  ,U]:~">I 1qC+?jS&O`9Ci!2̙ڪz>AEo&M\&{HIGGNH !pkgzwocu][IOI/!S6m`/<H XFBF:|'uM(@;bGֶmvWh՛f.}ؙb4aXQc6Ii5דE(Zk, ZT{DqP~mB8iEXmC(.wdtԑƝsRWY~ZmØپ7ie)XjEKyP&"rK*t [Ymd ʫ|z`0YjDF2X]f6Ս k0FpK^dOܚK,2Y=\K[ۼ8esG[ZUMBZh+@0L0 9w#qZL aҦj,I*r7hQ/Z8zh8(0c,b__ zpr-'Y.[OׁFLAfc$z_N" )tJ@X۹1&<VXNZ,B˔]#o8LPP5I^zڪvV N)I>rON ף/uS9 v@Fe۞[ %m͡]2Qm3P[$X\XP\s3_&>xU|4F,&"_tJWM ܰ&FBҔ=,yTM0Meau=ٟDLTsyMX|O!UhMM[u¢8-q:(n]LI6؊ [V\2}U50`$: ba+V7rn9-[D fa5p;C< Kf6C m@w(_ LWF-^s+}UʺkUA- m üG2s%> ?|`FRɬ%,cn@k+#+Mؒ`+JW;_WnHWDɂ1϶ R4&?1S0ڶLhQ0EY"v2N. %xvph{rpn~9?;95睳_̣{|U*2DMk=\X|O۴H?ڗm/w'|7}?vw][$yWML׾Ϗ:y;_K#.xKo7ۓ ϟ}WK??g7wkQ|lO;gQ\C B)B SP8n0dr'iL-,lGp1gi[/g욼w~X3N6['I .5\@ (H,'mUNvE_zg/ZӱZ3 "nVk9{ GDP^V'U>B21dh4A0]͠669$T* s+uM rG+q,qwFsa;i)bAln:%6Nj ZHdyeĂ}r2ց@ͥ^j06mhaQhBB ޑ;Ƭ#zD쌌(Ÿ8&^"Zݍ>1 l*.%w-iaÒ;F(1-م&QVJjB[Z] jRku?-„ "_ٸf] BWQ0fQuS ,y74 m$&ӦȁlWQ @3[ gAn'lbky,'@~{n՛v^#!c/%Ve9Xe.ހCX,qgwPV} 9eBK0_xdLX2Ω! Uϋ4d|? F(zGW49BlB!D,G/l&m9typuFI"V Flh Zӟs}}{ G8ITn;or{y~܆1+!zo-<#,1C=GL'xF|PZ#;ىDkm>@f&̹ ;020?۱D3ylw,r~ GKh!Co$b vjiSVr8 ٘9TE9.3uE>w%xF[mA;p@YH=F|:l+,-aX=`i_Igq&^' +MVǂbKvB Ï'?y?J5HMY'2/KB֘A%Id΋%`OzUy +el;Ƣ;3<#D@By \ >%7#2L`pcY:e8MJf#a`ӰE ޅ9G'b)G*_e&͌='B5=|w:;qvDm˘^ٳF@S*#nCxdƵ{GO2萕~ zL'o6}kLA@N gaqM5_)4;a'8aG6`r`G?)ĞkA@"t5wBI)ZR682ՎrhHIjޠw6^Iж)ጌ3yauѥByd3c]!IHyD8.YsMdOn *4{8k/i&Z@]MnDxil!Yx06%Ax2E\$F 8WAX Ђ7'X)\IBu ьKhSW_xapTiU"wD ͿRF!"G e Xc-H5YFn:vYJݧa,DSʉ_]>r9]S]B`o"<l&:>!\Cu.'le[U ed ?=8tjR+pWUٜw b;3!F9B8\DV@'ওX5f91(fgRC,yKiX7pzI ~G83 f$)|1S$\[ΰ).&k ^#1wIBºF*>:wMޮnrUsb$`9y>0ɣaHp=?99Y!0fPL9(rӧE^ )R/ ꘡OYDX+~>D#r|@MԾEя4:(Tc0ҵƜzˎ\nKDDrL8CbS<̡C 6~]A4T! a4Ҕ*/D3u+YѾ:]rJ\l\mEVo*P6K0 V>@cJlo$@ď9i RQwXG(JC Aը%@&(>1@<! =9U. @R=G@7O&24 ڥNIB(ѻz)"$PB"QPuKF" hiB(Zo٘:%wC\IRbOg 0_544[%cU-発ko~BP>2Q/lYZFQe҂l@\ G FL z ^\0ꉏI\'BA> Yxc(Rwq]̕{'̚&d^g{ KذKV=c ~g6(1Eα9]D .y!j1B#ňX'S pDa:Nv-vț?0ros]3A\ ^RS [[F"F( rva9|VMeHn\R.N]3;G li>)/%. p%jn3 I g8-z`ː<(4^IRStc9s+7*LF8.^Z8%@_ 3ZGok@^`ftW=P뭵 @Q]2t\Sg1x`9cʹa򩦡q}>7K=$;$lR ˇ`Rc PxDOP(JJw+Z Yaf*㯜U_s 30?a_|$ГƷw hP2tħ2\K6З3O`@t KavVEub,v6&;@\A-b~`qzQ0dh"mrC8wջ`Ojpx`hx+ M0]+iݨ}OciY^P:pSu.c+ײآ2AdljDb: 8TLũ[+FͲT 5┦Aα\a=]SXI.EH 2˫dN$orF$,gxu5\Yhfl?YԤj} g'mIO1cpQqS&-tE;g'ZZ 8,,XD0p&I'_}~]xzG9oB|y*"JN93)xd[ar+67EҖ|;eǶ#i.)i~ xOUa5;C^'.==9>_39Ɩ~j/sQ6`0 uՎW9wħ9|rfzǯN''}xA6sBA_~d\N qη&@H}b"3Aڅōus~vZ*i#S1gN۩rB$s_}^\/,F]vu!U:P DWӛCw9IB6[d^1G s}JʻmvRKMOOuVFJVMߟu_{YǺ9_6WD), 6WwM}]$o+a 8WkCN9w$ס]l_ɱF!/C.OM=,p,~\?n?رкlիܳ{ m^ND_(H &U"t)=/x⑑SBl\qu{kO.N;=+H;;1c{g=2z"LB$n!bY9C-rsuRsʪ_^F_TE{gvA#p܃Mnwgӿx_p"1_!s*Zv0si.E0fsWܳ'n .of!䶓oCO[o'Í8K^+V,ٗɞyBA5p6Iksٶf)I:[Rgf~c÷A+t.'{_w|@Jgcæ'`8`Q <¼B*q`4DK^EYQA ^ 6RP2E\n/ӷ=G޹>ZɂYlpB&_=~ѭ,., .~m8#Ԃ c.+d:8?{.o6&*>_lnnWm@?DXh hVOwO."B{ζysm͝wQOL0k ֺ13ͭun-[ۼ \{ntPM=u#ȤQi*u= 7oXxY{Ɉn'-/7!j"y*/80OܷGz0P [Xƃů VIo3ٹ\} nz\\7^&#yG-P[կկXrZ - )ەXͿ/c1вnv3`i+ܮb1'cE Inםno4 ^~W%2Wq;wk)'5wUoZ\ǹ:#k~"̗7u؟$"yMhvI3NغwykAXbf&[ԩlUÚ%H*n7A{쮸ۣnz<?}G3<~_n8'IXIaґۛzp }usϝ,bTs\osyІP7{aFzjlDPKam4sݡ9nr=K-rēU>]{pN#_??;B3qZ1ԧiY^ҫ#%[|9e SX[5f5 `l61 4H؀rh)eS.._VCA&L]e xJuI8f|4ՁiBxA/S)J|5YƒNTMSJT|4߅%Zt Zř< _LxVv`BuZռI}y*VsƢi[kպN#bu$LL }fb=w[һ*:+H X82*mQ3bQc<;GOzQ U;s0_Xqn3v<>W#+oh \ M6e>Z=yJ(h=9:bW];Vb% 5yɎU}{"'?}QE@]kԐ2%u<-3pq0B&_  t@ԀL+g 噰J{Vd4?~ ]8]մ~5|Ru?2BL[瑋lQW{za*0o16nFiFvO&(5XulIᩛɊ2oq Xeycv67dӭm$lAOxԴu}›xҰac%x+ Z\4}[#rC^1'~u.d-m*w-NFj6ecŽllQMc6k-m,l~2 NSƊp鹶A|V+o=vg~l΂Of% 6 jj|d_ l{ǾHIWC;nN0tU{p{~76ӲXP#^P3O@&=q1"Y,|fF>mmzSD׆+!R|@5L^8{b(Z@]mxY9ao=ƊhWDm0.+;Q[Z0*$;Hki_F\l5L-5T" 55l Qش2|lyxB `jB%k3˂٤vdӨ4A0u\x6^B:iBFSVY0e"nߓd5qU0E,#JPU C/'/y 课yq_5TruY~=O?q8ec:RR~6 ::1 :ܠxS"^= s@WCMvz_^|g7zZ aEm|D\N'{:!-a FnH7ЈĖQrV!Q/nK"KcS|:ph9(_angb#(,f`t ,iuח2wzX:*eNl Q@LA_xD$nmkx[FW-ͤA<=Hj៫0 vp~G.<$(G''n ]9֦Es@ aK^ېu9oicl oCS)g]/\<.eĄ]Ѫ06OUʸlMT]=ՊMߖF-xKxλuǍw7Z.YS `:>_Yp?,?qX+scyZ,u*#9/pyt[ZwrͲrV TlpgP;34C4Hcii&˖WV5+).Cg _㨼@6rKouo+dž$?wAkĥXr,G _z͸I]Ne^6^^mtO-]d{/.T$\RW:J eK+USj%jIQ뜾e1eHfK([+ b̠Vj.։aa$89ܲ Cr Nw^z_N/qϟToԡXj}|"w)AK:gu㓪畁my81FQ`yty>Bͪ j W0+?[댆hu:*F6f GZbw\8@*!mHnz=aM"bϿybjie;>۶`bEg0HDϤ\ۼFf4=Rx/twAiCC[wʉV羗Jo|6@hZ$:k%^Vy0lq@GRkV?YcFo?yWvN1RT2*hC$NYqNPި۠:DuV#fһ8N?@8%57Xqs>Sr_Ad;*?qe`+* Ş87mD} ]hy&Vߑ:d=DAy9Ʈm%~+E%I|4Jm|%lR̥v>,Y]zef>bT@&b,%y ס]BYNUr}t h죋P)V]f3y#f~*N c̝[.uh9a51݋j;Ƌ OP x푊蹪2'/YN=|Jh6]_y֭=D٩%IY!}*Tm|d}U H(Ub> :Mw%7>]7KE2m5*uPLs=(z+{1՝p-D3a6-L!,<BJ_ռ~"w?~@\-=S"/^1w5g?kݸ{P9+r[(@d~<"|%BǿyScsyk/뿿=/~ |/_>Y=;}ΏqS9?v:`^}޻O8*-_moW .?0(O3nw&jP AܮA,Eq&Cf3GłT3qiVK#_=W| 耖I| fI>\S: 6cH M!$Db՗SB9kA{M(5k'A2vI_vj$\F^+gӸ,js+x[g(jv}]Jqޚ  3ܑ[*! Ɩ$ְEz|d+]煤Z^XUG_Bهf wt"`IgdEg~]-C駫8#".-28ǎEjmfw24R:+V]T"h/PtXkc/W߼۬G-񹣖I-G>E>?? <]֚?XVNXŧI]Vj uD.cOoHYBi! j{v/ϊNb\2*f-qq 瓰hI`5:WvݎN8r[-a!ǯUw%#-p&%_nYTl!K⟵(6 ڥ ),#L΀)\6|PXQ-ͼietl-hY@pQ9l!D\zyO}ÓOFڪzDlt}y^.[VXԩNVtx8uK9]\Jk6 ovUۣeU}[}{T~u F{}-Oy(G&B V+ِ#DEC#o NǂkHPh\mbXH㢸7` /iw\<*XM2Rr9SpA \F@ +%,Cvy928uIio~CO]>ȝKݱ/箵Xgz`{'`eԑ{]-X̓1^}Z7>FIRgsN9sLR' pY eR$jga. hdNB2m V"_`q3Dk38ύC_J2J4`=gZtN[ KZ7RT<:xdW W`>e5Ud/ w"5.Ѡ}}]3:@VSqpÐG+`\VEs܃ނ CH\C69MJk/˜p[l423pR 񇥙L^Ώ;n+6kxTF{'nUҜ `•x6TZV ӜLԒ%$^x4+g(@'-̦^ H}p%VK)syE ܊keQ.'bNU]="tVx軙&ό6Պs4a3 p-wݦEԜX;N[*[7jVJm)Byyj5 LI$'4loAFF"D It7o67?VG]x/(KєY?O>t! fzOWnydw7f{ȭk7'S/ΗzwO.ΞwlQS0cP`$q+[ ue 9SJf2߶ –- AmcG3lgNb-YVTUo56_ZDh6D+*, j/DX1D4X iA ˨o;Qjhk[nD|UaXm<Ńqm6ݒdJ~"d'H mk b Z"r?V3!w% U/_T`R(L 7fvUʫ2`/W;O׹XdJf{{*PTo:"oQU*5qOL>#9B4 z,+2 ټ^z]%?^Ik/dJfUG !<{'}ɹ1=bg~٢^_ ~3i-+UPuaL??Nׄȫآ)rH4v`!KNHR8Vck k xmIV|jG}p^A1߭㟓?/ȷ~^  d)KΥZ4郛޻Ō~r\VZoU#CَuӼlзp6H3l?\F3Rߴl\ӷ0gEHV;OB ۘC5-l4hZ3y>ApI5Mb(\fKڳnL9*z%_UReBߙvZ[vnm}}VAAq>:nO-s{z ծUhքw37بJI*)f2](%A@EnfdW4A]Ó=@Я@Ѡp(Jl :OZQ*cUig+ 'K:|n^/K8N޸'(LQYia/Q0 {uS,EKE#h-(a~I8c4 ͪ׫.l'U@CO$0ҿ9Y ޔ|YЙ&!I b4]ہ*%b0jXT>RMQtt[/Yc;(Qb-9}]ח*ڕe 0DSBsoW] &Ta3Q1)z|o= ^hDr͆J`5}f jhqCLݚD_M!a^H9OUYPY*`TZ:Y̷YtM{ԅN+vZu\nX-bmkcksMs5• &:+/n ;(m6^ YPZ= 6Þ#IT9G\^iX~۫ !yk Y} IwS}S˦sM *C{.qQL[EtfyŖz-Pր s *vo_=HQS˹ȁXO3KޜB8ys:K :3KWƵ]p"9 Aa Z URb:o#zcex #>kLpZ+M"(OP/̀G;5N iN$ij a!,6"^Vat09 4O2Xnvzm LVm"PEWl.BJ"kle!iU$O_.yStXd ST!]Ϧpھkqw}hivi'[,S:QCTlnW31o̕Exh3;nWc]MkNk B8tx_I}6 ڊ'J >IH dnk 11p3g7%Ŗ-sRdGQ\˲,uIX(TAwo2Z7#3\wBTd.V$ `z'aD! $*OR[R MJft01u}Br& Gk{&"%k9'"~- b!qE!ڀr15( U b2Ǎ5*XCI/RO2PY[_Åei1Z/71| ~b(?*SBӃ\Y VAjhQ }S;[;-nNV7)I? 㑇i19je֒+aSܟOIAW  ^Y^UoiѻhȂb 2cٷ:\kSZG0e螓 KZܶUo>UT%xP#,J0!Z, h8]<|0E)4cð1+ia.l#]/2SNCle(9o`U WًKwG:-3#p3 9~'H2"& 4`Tۗa=[j`$DV@bZ(}N Ǵ,^=iysi^_7*KApy`NqmۘaqΣF_=|MC pd/ " *F_i`F)Z(3)Qf:[n"NgiqĹԘf/37 KMDMP1gĥx!_M67wFaUlI ^~困hvONӋI{''4g3z7Y{r}3O.8{3&x~!P9MkAAy2f:'K*m΀ew_0!gF m\zEl4_@9h {[@䩷=vaւOR2`25h & Jܛ$2 X, V\\e UH~icg{GOFmײ3(ovLąɈ&!S$!1+axŇ Qim`/L((xٺ[!jyo8/^.c~Չh2yǟ=Wer7͸Lj/8Xak> h;AW~e0 ZD+ l /7qbbg4~`?K O5-bK(>qG=w;읾<9VmNdvd>ţGLpX03eK"w}AmԂ1rIqƂ]R9K/qrˣIZ!% ,&anBgo+ B;㫴z 2162KXK#=[!Oۀ_Jb”Ytn?l}}p}i@'E8DI6.?Dk%1.n^͢VѻN`g/NVc=ѠQ!=; DcG%)څULYS ?|&JQE]9p %e˖2b:,~m0M< ?탯J%2V<|3لD a0S}&D)rЗuRI٘uk fk7lŌ34G:N ?/^^ĜGc. =N{g'O=h,' r7I8%b^bٺ")m(U<U'Tn9f7돤){M<p= 9kq=vM CqQ7h-%=qIxy*~uE/`&$! CП@~c1O[Qtmȉ6RfjSR|j ` *Bނ~Ig'|3 iqHP.2eM"'B{@mt,"s)8)O1AIv8,I888΢v1srC\؄6V@D ʓh!zpr:F $xyi:/$`ჳ@O1S)6zXuRd>y#7HT {)75U>\-%= /bWbhp 翆[jlyRrFŢ"7iyV xZNB)CXu+Y% vC0*Q PF@4ra=Tt ;=ЁtCHWp1<ռYQ ɡyVp}ID )_0%W)CQ쥢G/FQ`M qr>Ęep&a+n 6gf?ԪfNvEP0Se>Ò o閗sJW@灹'Dy;b<+qXͿo*Zf#;^z_o); Rȕ)BRET[0oN u\ꝟ=_:M;H2g]"rn>6<huz|>-o. FGF.%fvLg;UK f(4^ARSτ凉«UW]B%j_i "'StLMl:/r KMy q{3-o6h*|n7ySa)X7R.& n;Vp5"=UjbdeZ-;9ь&v݁ 2c7ND>ⅮXE|6TQR@)f4z~G8 \QyJx:y" uF=uvX=L5D0Lӱ2ԌAQ&k#P<GM;S䷜%+pDI];^#6㺖l"GqFx() QCs?<V>F _]^Ũae!˰+/-YcBŅs - il*X*Ku7YU:<~dA'np1,F%W<³KgE-P@=i&U[sX4hG OXnPg>wBwQM?̲ LN2aqE"|5!chB8*$C؈lǤLJ1ET,`9_x\^ .P߯{iyMKurKtr?~1(CW=Y gOӠ_=,9@h=02枓e+} W  #"RSo mZz0M1݊뢄2~5h w]GC^PcmccoFz**u5LΜBaCxm%FHaV*^W9A'}/\EP<D5 hJȆf:C]A[(v) ‡+XO,2;/K'A 2CMr(%R/ݢ'arjwB@߮?!:~=aoSP)9@Nf:\LlqgC< |c<[caJy8[! zFT\]xq22ifa^c oW{ĄG'yE3"HClܔ`_L.M'#ٜH.rP_f o_w"5 ]A;őTEK{;{ֳSV2SqaJd2nɓ*XD|H 1Db}(u: |P `-73Ϧ]}~<#}7\,2ЧDZ*!*~Jy'y R̝J3wiXij0gbJ@0cug X(T"0bJ` z{Eb!}# YFE'ayd;?ft|YffYm~ԹeUd5^)Zd @6 L,L(t>i}bzvsdY?@#2k$~u6_?~|^䱠Li=fg97)8_TWwKJC]60P,-g8r w\n&79#OuϣK쨗 o~2%NasK8,4# !p:Uiv 9x5G;A|ܲ.%%eU?',ARFy՛lу5ZB"*TGZF az)eq^dE*oȒXhoka>_F_v|._`m8h T?㉈HHW.i ǿ¤؏JRf6lE mz!¢[ բқ(3#0hRP=COlǛ޿ RXA 05D!ByPz.+]$+zLPU85p CC? ;+r_gk{Oِa#\&<$F 2ɛa'W c9z9:B5WqGjPj{n"{x>DG/yݜ$[^:Sy3Fvݿέ؋0s9K>|7!pj= c~gOwL-e[V+앶D8u{|MIԟV) A[-:n<Hb!/N3jwIt(cfj㌂&j38VDZ>BۄOBeB֚&7s|5u #ZcX=M1%Pًe$QqOPҍ*&A k/SN0_ˋ.>InLLgvJ` LPji;$;pƴj F/7};L0+?)}ktlZ{~~N*h~|N ؇1wqo8M+%9EYr60sMDs 4t`e;u7gTf"f2&}|cun;i p" \8>dJ;<BebC Λs`*Ľx K( e:P87@*ោʿ&lر̈~ԻIE]=x5 Y93?c# Lt5Dg=\eVwjnP3%+VSDbiDb$8NX:{" bzj}%ZIᩘm4!M3bMlM((YL:Dž '#u'̫/Ԡ=xxLE7yP矉؂m@~/QqkM^6M UΠ:l^C^ &gb]p>Yֻ.'4K] I{9?VLЉܶ"sߚ tא86(CLܜ``rŶFi[gٴ3I,:s$gs_lO4OSySֱ芧LX_ނw(kN^N2t$N DtkI6fK&awc gȵb4z!Joxzaac%,9&{ҬeQPch-@s`z2= 1f=G" =- 7I2;! E I4AscƜ"1^U4` ]atI8 !WIZ(% !X V̼0&{W5 OT\LT5/nAnL 4@zC(,xw;p8L/ìITss$s,8?jˢ(GC-x 焵z+I,WZ7Aq4c?RNҺU^U!vCH bIPAY>Bb~"­eMt( e-VӪ}b1.r?-/=7m1cXEDy{[ &ڬ*33s 8jhA7Or %8|jdl>+};ӄ}dVoRq_Zy# v!ڢgcXsi=9P($wQ\O#Vf|!rR&t_ ,zJwXmH&lhd8^=j¤ KSyg}Dҏ9ПnjNL;t*WfY"`B4<ŞaUJFy;oeփ+l>.WҸ^˂;skp"Yŧ lB.dio'J ;#+=|Vn_;֪Uc{:@*=ubȮe轵̾)kb"R[;uux T_0@v\aBjHFv6Ъ}E?`{l EBg]h{^':HQPvN؇wG"ƌ!CS7!\?3z5s$Yep/r;@U\xL5֡""E}kɦ^yhqtsdZC#vE oWewէI7.L;-84|iC9,ȴTD{idEC2В,@NV:)lŽBؚk*"V+EaJ]U<ˑc >0iƞ<#"ӭՍjiN Y3duz gЁ82R!Σ%7~:? >lW&.+K- ?T&A|Yx5T,rhFM<3@cxGsz5ww*~#LIyޜɝ}g{D7uQyUO/sr[awv)sAdVZ|i\ (=h7NoKlAӪ ]_u%_B%UN4$DȼWT t;˸AmI}┹ 7/q߹Cu+u6X.iJ+lcUO-o?eÈYVp=ST۪Um\y10*$"Y=rvoV4r [(^ ;v]DYA[ָmAU sHgxH0aJz)k"1oZxLQɆvߎ;NɆSZWp[iY@c Tqpgut!xyrC,'{rD4X6Q`PcmX9 ޥ%KK~hb#X ^&-I#}_( TJ]-8iՒ,O닋uni8tb:;le`//eg FkPP7BVels3_YO6a@˲+@A\cq.>!g㷽xv kz^|_{]bڙ =hp5I{ 4@iLr^`ԯɞg'Eb}8 MƗiJ=9k!M@l|A{D2#*:"EVCw9{&dpHc9N23):&4f8<^1QCZ)B ܣQ!ck[_t0dYӊJZGW_$eRB 3/uެ"<5rWسN y )SO)5UjxYs*Z*vo+wAϮ>]wKoGgpGcw~Zo]ܽ) =Z0|¢Cr"I^TfC?z? w?6:P$Qb}ڝNܥk1N$fys&Gk康8kjbbr{a mءuKJm^Zmv<խY\8jqӹ^ʣCutG~t[|7Wv/˿pݦ5ŹMeSɅsG~~.~Q3'ӳ!fk+W*֪߮'[?;h^{UݮmOBݽ϶Q˫jmwӧO̞̊ Gt?%V4O{)N,rro RxQzzT(<~բ|83mڭsEHc692WPJIÚ+@nk}9GףR1(۝} xr/sR\89q4-/_ n4QP~=sg74Oyr&_̨9_e)1l$&$%籼W񋌧E^֞3jۛ՝ma窛u8=l^K.*x|\>8S?G>vmoG߳ѫw:,Vݯ=k`"6foKw?PW{k6ͧ++S۫~ΟjۻxӅٯ.Jӳ翻p0Z )^@,PsV|ogw6EOODgx³Oݯ> jM[Oyi[(nAa{0}v] sDBiCc%nZቹr.futŬf [ T YŬ3CpGg.:QƵe `C҇4=gĚGFh^u*/.>}m]zp{YK5^6|90K,;<>ٯV.>÷[ mP|Tmwo rv,<xت>3Zaj"q'mz-_,/ad㟖ZS~^^noB+]W#Tt衭fIDAٚr;y/+D7=G[쮱<ղQGL 燭MOUiŤov*mmoBMo/ńnEʭݽ~qe̝ZG~Tܹt\*^sFdFhtUx@t}DP(psZmӲ6_&Ǩܭ3o#uy7ζοqqv̩sK7ΚMW M댂zKĂK]fW-v,Sh..EWA#j^MZErp[ yT6J~}a;T%FHjoMQTnDEgj#{iPkBOO^=ke|Gb-DBr3=!BZ\`7R^'GHtZ߈t}u |ϐo\16?AɼtSDR | ?y&0$}h#doYځ3_rd[nWD[{ vRZ &c>`=$cnQtL?A~]Mo 5,5篷 P4gQt^ȶ>֩muNeQpp:/t[U]e!H,LPfsD1jWJo|}fG"zk~VBi^.3mV۵gGj\~=.d;%'M!95Ɠ|&ֻ(s.6S^ų-V;Ϟю:W/ _IsQWنp žT\x!b:!OcxPn張gn(ԥ0d'I_k8T WN̥ qYiWC6k0+N觘(/$6N0E6 v7 1l̢\[̺~ʗ ،33Ud8+(6(O0֮S8Z-vflv)Hbx>L} &guUL7WCfJV8*XZߍd0ٲWacə>edW`M(T*YUՈ)q,Y*k|G*ؽ,7±G>Mr\;RxnP?8&S0aQu+i1 FAg0pGgЃ@EP;"DV4'x3M&9[H2z*t%lˉJgx 4DԱ0w%*%im, VO=@e]q}&D0ma;Re@z(d7[+Cq#^?^@GԳ[iZiAB \ t'tKluCl%'.5/^oJx`F*y/X~tG'MY)jݧ՝.BTaxEkuꯐgT ;}eKҋ!Yf' /*Ī"by??"~)*=?f%GFGE)گƢjn6o! [sޡ}Rm@njfܯd$%{3I'L:[B3m/qF,!X"* ;0;,'#ʸ1L`t=0SL *hHX6ݤq<T+پ=eAw ii<*a=V9!V5>մ+YyK|j:MWb]&SXT ޱN:Dej$X1A "(B"Za>C ?ӌ_cCJ.=9@? K` GfQ!l[/jy \XLv3b#4h:eEydω!ˆYM(B~o4׭ HqO՜44Ȑ0fY1IZ {zT?