Vous êtes sur la page 1sur 269

lcc-win32

An Integrated Development Environment

User’s Manual

Jacob Navia
Logiciels/Informatique
41 rue Maurice Ravel
93430 Villetaneuse
1991-2001

Lcc-win32 User’s Manual 1


Table of Contents

Table of Contents 2
Organization of the Documentation of lcc-win32 7

Installing lcc-win32 8
Troubleshooting 9
Getting Started 10
Keyboard shortcuts 11

Special Features of lcc-win32 13


The Memory Manager (Garbage collector) 13
Operator Overloading 16
Differences to C++ 21
References 22
Generic Functions 27
Other Syntactic Enhancements 30
An Application of Operator Overloading: The iostream Library 32

Using lcc-win32 from the Command Line 36


Using the Compiler from the Command Line 38
The compiler driver 38
The Compiler 39
lcc-win32 Command Line Options 39
The Intrinsic Functions 41
Size, Storage, and System Specifics 43
Pragma Directives of lcc-win32 43
Runtime Organization 45
Saved Registers, Prolog and Epilog Sequences 45
Registry Use of lcc-win32 46
Predefined Preprocessor Symbols 47
Predefined Compiler Symbols 48
Standard Header Files of the lcc-win32 System 49

The Linker 56
Command Line Options Syntax 56
Command Line Switches 56
Libraries Distributed with lcc-win32 60
Other Libraries Distributed with lcc-win32 : 60

Other command line utilities 62


The Resource Compiler 62
The pedump Utility 63
F2C — The Fortran Compiler 64
The browsegen Utility 66
The buildlib Utility 67
The lcclib Utility 68
The Bind Utility 68
The mergeasm utility 68

WEDIT: THE INTEGRATED DEVELOPMENT ENVIRONMENT 70

Lcc-win32 User’s Manual 2


Command Line Arguments 70
The Main Menu 70
How Wedit Displays the Program Text 75

Projects 78

Configuring Wedit 83
Exporting/Importing Projects 84
Complex Projects 86

The Workspace Options 87


Defining Macros 88

Finding or Browsing Information with Wedit. 89


The Workspace view 89
The ‘Name Completion’ Feature 90
Information About your Symbols (Variables, Functions, etc.) 90
Finding the Usage of a Symbol 91
Displaying the List of Functions in the Current File 92

Editing Text 94
Selecting and Moving Text 94
Searching Text 94
Replacing Text 95
Goto 95
Matching Parentheses, Brackets, etc. 97
Bookmarks 97
Redefining what is a keyword 97

Wedit’s Debugger 99
Configuring the Debugger 100
Using the Debugger: The Basics 101
Switching between the Different Displays 102
Setting/Unsetting Breakpoints 103
Displaying Information about the Program 103
CPU 104
Machine Instructions 106
The Stack Display 106
The Locals Display 107
The Events Display 108
The Memory Window 108
The Watch Window 109
The ‘Auto’ Window 109
Evaluating an Expression 111
Setting Data Breakpoints 111
Calling Up the Debugger if your Program Crashes 111
The debugger configuration tab 111
Debugging Windows Programs 111

The Profiler 113

Configuring the Compiler and the Linker in Wedit 114

Other utilities 117


The Binary Editor 117

Lcc-win32 User’s Manual 3


The Software Metrics Module 120
The Macros 124
Identifying an Executable or an Object File 125
Generating a Table of Character Strings 126
The "DIFF" Utility 129
The GREP Utility (Find in files) 132
Adding a Utility 133
Inserting Special Commentaries 134
Inserting a Comment at the Beginning of a Function 135
The 'TREE' Utility 136
The Object File Cross-Reference Utility 137
Searching Information about the Defined Functions 141
Writing the Prototype of all Functions Defined in the Current File 142
Searching and Displaying a Structure Definition 143
Show Information about the Global Variables 145
Showing the Relationships between Two Modules 145
Showing the Executable or Object File Statistics 146
Automatically Generating the Program's Technical Documentation 147
Printing Your Files 148

Weditres : the resource editor 149


Structure of the generated code. 150
Building the dialog box. 152
A simple example 152
Controlling which files get generated. 154
Configuring the preferences 156
Managing the selection 156
Testing your dialog box. 157
Using the directory listing 157
Setting the tab order. 157
Group order 158
The toolbar 159
The selection 160
Fixing a control in the screen 161
The status bar 161
Managing the symbols 162
The zoom utility 162
Properties of a dialog box 163
Properties of a Push button 167
Properties of an edit field 169
Radio button styles 173
Static text styles 175
Properties of a ComboBox 177
Properties of a List Box 182
Check box Styles 187
Group box styles 189
White Rectangle styles 190
Black rectangle styles 190
Horizontal scroll 191
Vertical scroll styles 191
Spin control styles 191
The tree control 194
The slider control 200
The date calendar control 201
The menu editor 204
The string table editor 205

Lcc-win32 User’s Manual 4


The accelerator table editor 206

CMS 209
Changing the CMS Project Parameters 209
Get: Retrieving a Version from a CMS File 210
Retrieving all Default Versions from a Project 211
Saving a File under CMS 212
Saving All Files 213
Searching for Differences between Two Versions of the Same Module 213
Viewing all Versions of a Given File 214
Visualizing the Log Files 215
Building a Release 215
Inspecting the Stored Releases 217
Retrieving a Release 217

The Application Wizard 218


Class Definition 219
Toolbar Definition 221
Styles 221
Creating a Window 221
Using the Wizard 223

Advanced 225
Compiling a DLL 225
Using the Intrinsics Utility 228
The Dynamic Loader 234
Eiffel Support within lcc-win32 236

Frequently Asked Questions (FAQs) 238

Compiling with the lcc-cd. 243

Accessing COM Objects Using C 244

Appendix 1. The Windows Programming Examples 245


The Standard Library Examples 247

Appendix 2 : The Language Grammar 249

Appendix 3: The bignum Library 262

Appendix 4: Implementation Limits 268

Bibliography 269

Lcc-win32 User’s Manual 5


I used to pass by a large computer system with the feeling that it represented the
summed-up knowledge of human beings. It reassured me to think of all those
programs as a kind of library in which our understanding of the world was
recorded in intricate and exquisite detail.
I managed to hold onto this comforting belief even in the face of 20 years in the
programming business, where I learned from the beginning what a hard time we
programmers have in maintaining our own code, let alone understanding
programs written and modified over years by untold numbers of other
programmers. Programmers come and go; the core group that once understood
the issues has written its code and moved on; new programmers have come, left
their bit of understanding in the code and moved on in turn. Eventually, no one
individual or group knows the full range of the problem behind the program, the
solutions we chose, the ones we rejected and why.

Over time, the only representation of the original knowledge becomes the code
itself, which by now is something we can run but not exactly understand. It has
become a process, something we can operate but no longer rethink deeply. Even
if you have the source code in front of you, there are limits to what a human
reader can absorb from thousands of lines of text designed primarily to function,
not to convey meaning. When knowledge passes into code, it changes state; like
water turned to ice, it becomes a new thing, with new properties. We use it; but in
a human sense we no longer know it.

Ellen Ullman

Salon Magazine, May 13, 19981

1 Ellen Ullman is the author of the book, Close to the Machine: Technophilia and its

Discontents, City Lights Books,

Lcc-win32 User’s Manual 6


Organization of the Documentation of lcc-win32
The documentation is split into several files, all in WinWord format.
•User Manual. This document. It describes all options of the system. The emphasis here
is to show how to use the system, and to provide enough information for getting along.
File name: manual.doc.
•C-Tutorial. This is an introduction to the C language that starts at the very beginning,
and gives you an overview of the language and the lcc-win32 system.
•Lcc-win32. Technical document describing the issues in lcc-win32: how the compiler,
the debugger, the assembler, the optimizations, and the algorithms, etc. work. The
emphasis is in explaining how things are implemented, and giving you enough
information to understand the workings of the compilation system. File name
lccwin32.doc.
•Common Controls. This documents is a supplement to the API documentation, taken
from the SDK documentation. It describes all common controls of the windows API as
SDK release of October 1999. File name: Common Controls.doc
•Shell. This document is a supplement to the API documentation. It documents the shell
API as of October 1999. File name: shelldoc.doc.
•Internet. This document is also a supplement. It documents the Internet API and several
other functions that can be used to build network applications. File name wininet.doc.
•Online help files.
•win32.hlp. Documentation of the windows API.
•Wedit.hlp. Documentation of the IDE and all C library functions.
•mc.hlp. Documentation of the message compiler mc.exe.
•examples.hlp. Documentation for the samples distribution.
•c-faq.doc. The Frequently Asked Questions for the C language.

Lcc-win32 User’s Manual 7


Installing lcc-win32

If you have the auto-installable version, you can happily skip this section. There are no
special instructions and everything is automatic. The system installs in the ‘Programs’
menu item of the ‘Start menu’ of windows.

Depending how did you obtain the software, you can start either with a zip file, or with a
CDROM. In both cases, you should execute in this order:

lccwin32.exe. This installs the compiler and the basic system.


lcc2.exe. This installs the examples and the source code.
lcc3.exe. This installs the sources for the debugger/linker/IDE, etc.
Lccdoc.exe. This installs the documentation.
Fortran.exe. This installs the Fortran compiler.
w32hlp.exe. This installs the windows on-line docs.
lccdb.exe. This installs the database module.

You should establish a directory tree like this:


lcc Root directory
Bin Binaries
include Include headers.
gl Open gl headers
sys System specific headers
Lib Libraries
wizard Wizard templates
buildlib EXP files for the buildlib utility
Src Sources root dir
lccsrc Compiler sources. Optional.
pedump Sources of the pedump utility
examples Samples

In the \lcc\bin directory you should have the executables for (at least):
•Wedit.exe The IDE
•lcc.exe The compiler
•lcclnk.exe The linker
•lcclib.exe The librarian
•buildlib.exe Utility for building import libraries
•Weditres.exe Resource editor
•lrc.exe Resource compiler
•make.exe The program maintenance utility
•dolibs.exe Automatic construction of the libraries.

Lcc-win32 User’s Manual 8


In the \lcc\include directory you should have all the include files distributed with lcc-
win32: windows.h, stdio.h etc.
In the \lcc\lib directory you should have the libraries, and the startup code. The startup
code comes in two varieties:
1.lcccrt0.obj, for normal programs
2.libcrt0.obj, for DLLs
In the lib directory there is a sub-directory ‘wizard’ that contains the templates that the
wizard utility uses for automatically generating Windows programs. The templates have
an extension of .tpl.
The lcc-win32 system supposes this directory structure. You have to establish a directory
tree like this. You can add/delete directories, but at least those mentioned above should
be present. The installation program will automatically do this.
Once this step is finished you are done. Lcc-win32 is ready to run. Start Wedit, and make
a project for the ‘hello’ sample in the \lcc\demo\hello directory. If everything is correct,
you should be able to compile that short program.
Troubleshooting

After the copying of the system files is finished, the lcc setup program will call the
‘dolibs.exe’ utility to build all the import libraries from their ASCII descriptions. This
saves download time, since the megabytes of import libraries are not transmitted but
generated at your machine.
Sometimes for various reasons2, the dolibs.exe utility does not work properly. In this case
you can do the work manually. Do the following:

cd \lcc\buildlib this supposes you installed in \lcc


make start building the libraries
copy *.lib \lcc\lib copy libraries to \lcc\lib directory
del *.lib erase all libs from the buildlib directory

The buildlib utility is called with each ASCII description of the import library, building
the import lib. The newly created libs should be moved to \lcc\lib so that the linker finds
them when it needs them.
The registry keys that lcc-win32 uses are stored under the key
HKEY_CURRENT_USER, i.e.; if you log in under another user ID after installing lcc-
win32, you will be forced to install it again. If you install under the same directory,
everything will work properly.
The lcc-win32 system assumes the software is under a directory called ‘lcc’. Please do
not change this name.

Another possible problem are paths with spaces in them, for instance “Program Files”. I
have tried to do my best to account for this, and the latest versions of the software should
handle those paths without problems, I have installed my own copy of lcc in Program

2 In some systems, there is an old command.com present that gets called instead of the correct win32
command interpreter. In this case, a DOS session is opened and other things fail completely. The
command can fail for lack of disk space, or other reasons.

Lcc-win32 User’s Manual 9


Files, but ther could be still some problems in the utilities like lcclnk or lcclib. If you find
path related problems, re-instal lcc in a directory without spaces in it.

Getting Started

To start using lcc-win32, a simple application will be used as an example. Start the editor
(Wedit), go to the Project menu, and choose Create. You will be prompted for the name
of the new project. Enter a short name, without spaces in it.3

The project definition dialog box appears. You should specify a source directory, where
your project will be built. If that directory does not exist, it will be created. Choose a
Windows application as the type of application, and press the Create button.

You will be prompted if the wizard should write the project skeleton for you. You should
answer: Yes. Wedit minimizes itself, and the wizard definition dialog box appears. You
can select several types of applications, but to get started easily, maintains all of the
default settings, and press Continue until the wizard informs you that the files have been
created. Wedit will restart, and it will make a ‘Makefile’ from the files generated.

When the ‘Makefile’ has been created, press the F9 key to compile your application. This
should go very quickly since the application is very small. Then press Ctrl+F5 to start
your new application. A window will appear with the name of the application in the title
bar.

You can debug your application by using the F5 key — Wedit’s debugger. Press F4 to go
line by line to execute the application. The F8 key is used for stepping into procedure
calls. The F4 key skips procedure calls and always stays at the same level.

You can modify the dialog boxes or other types of resources using the integrated resource
editor. Go to the Resources menu, and choose Open. This will open the resource editor in
which you can add new dialog box definitions, menus, resource strings, or other types of
resources to your application.

To define a dialog box, choose Resources, then New, then dialog box. An empty dialog
box will be created, and the resource editor will automatically bring up the properties of
the dialog box. You can then change the title, style, etc.

To populate your dialog box with controls, just select a control type in the floating
toolbar of Wedit, drag and drop it in the desired position. You can test your dialog box by
using the Test option in the Resources menu at any time. You can change the properties
of any control by double-clicking on the specified control. This also applies to the dialog
box as a whole.

3 This name will be added under the \HKEY_CURRENT_USER\Software\lcc\Wedit. See the


‘Projects’ chapter in this manual for greater detail.

Lcc-win32 User’s Manual 10


By pressing the right mouse button anywhere within the program text, you can always go
to the definition of a symbol, or add special comments to your code. A quicker way to
navigate through your code is to use the F12 key to show the list of defined functions in
the current file. The keys Ctrl+F8 will show you where the symbol under the cursor is
used.

Wedit has many settings for fonts, compiler configuration, links, etc. All of them are in
the Project menu, under Configuration.

If you do not want to create a project, you can load any C source file, and press Compile.
Wedit will create a default project for the Windows application if it finds a WinMain
procedure or Console application if it finds a main() function. In this case, you should
have a file that needs no other source files. You can create a project easily within a few
seconds.
Keyboard shortcuts

Key Meaning
F1 Help for a system function under the cursor
F2 Toggle breakpoint
F4 Debugger, next line, without tracing calls
Ctrl+F4 Close current document
F5 Start the debugger
F7 Set Bookmark
Ctrl+F7 Goto bookmark
F8 Debugger: Trace into
F8 Go to definition
Ctrl+F8 Show all calls to the function under the cursor
F9 Make executable
F11 Find matching brace, bracket, #endif
Ctrl+F11 Recenter cursor in the window
F12 List defined functions in current file
Ctrl+Ins Copy into clipboard
Shift+Ins Paste from keyboard
Esc Complete the word under the cursor
Ctrl+S Save
Ctrl+G Goto line number
Ctrl+Right arrow Goto next word
Alt+Up arrow History of visited functions
Alt+Left arrow Go to the last visited function
Shift+Left arrow Select to the left
Shift+Right arrow Select to the right
Shift+Down arrow Select one line towards the bottom
Shift+Up arrow Select one line to the top

Lcc-win32 User’s Manual 11


Shift+End Select till end of line

Lcc-win32 User’s Manual 12


Special Features of lcc-win32
Lcc-win32 features several enhancements to the normal C compilers. These are
enhancements at:

• The language level. Lcc-win32 implements the C89 standard, and most of the C99
standard from ANSI. In addition, several enhancements such as operator overloading,
references, etc., make the language supported more powerful and simpler to use.

• The intrinsics. These pseudo functions allow you to access any feature of the CPU
you have inside your machine at very high speed. You can, for example, access the
extremely accurate time stamp counter, updated at each clock. You can also access
any of the new MMX instructions or test the overflow flag.4

• The runtime level. Lcc-win32 features an incorporated memory manager (gc). This
feature simplifies the programming, relieving you from memory
allocation/deallocation troubles.

• The libraries provided. Several libraries enhance the runtime: A regular expression
library, an image processing library, an unlimited precision library and several others.
Of course, you have access to all standard libraries of the Windows system and to all
of the Windows API.

• The dynamic loader. This facility allows you to load object files (.objs) as if they
were DLLs. This means you can store them in databases, etc., sparing your user the
core of building DLLs.

This features are described in detail below. It follows a description of the command line
tools, (linker compiler, etc.) and then the user interface (Integrated Development
Environment, IDE).
The Memory Manager (Garbage collector)

This part of the manual covers one of the central features of the system runtime. It
requires some basic understanding of C. If you are a beginner, skip this chapter and
remember: To get more memory, use the function GC_malloc(), and forget the rest. No
free() or other items are required.

4 Although it seem unlikely, there is no portable (ANSI standard) way of testing this flag ! Since the
language does not provide any exception for overflow, testing if overflow occurs is almost impossible
in a standard compiler.

Lcc-win32 User’s Manual 13


Lcc-win32 features the garbage collector developed by Hans J. Boehm and Alan J.
Demers. This fine piece of public software allows you to program in C from a different,
much more relaxed perspective.

The well-known problem with manual memory management is that it is very difficult for
a person to specify without any error when each memory block used will be destroyed
and recycled by the runtime system.

This is a task that is better left to a machine, i.e., a computer. The authors of this software
have solved the memory management problem, eliminating countless debugging hours.

There are, of course, applications where real-time requirements make the usage of the
automatic memory manager impossible. Those applications can still use the default
memory manager (a much slower solution) or devise a memory manager tailored to the
application, as all C programmers do, in one way or another.

For most applications, however, the time required for the memory manager to accomplish
its task will be unnoticeable. The authors’ years of development have fine tuned the
software. The speed of the automatic memory manager exceeds that of the standard
“malloc” implementation by a factor of greater than 10!

The development speed is another important factor. You can concentrate more on what
the program is doing and if its doing it well now without having to focus on each bit of
RAM you are using. It is no longer necessary to develop a memory manager for each
application. A DLL and a link time import library are the only requirements.

The debugging time required by manual collection must also be taken into consideration.
Problems in this area are quite difficult to locate. A memory leak or a mistake like calling
free twice can cause a long search and hours lost in the debugger, if you ever find the
problem at all. There are numerous examples of programs with this type of problem that
are never corrected: it is just too hard to follow. When the symptoms appear, there is a
crash, etc., the real problem can be far removed. Reconstructing the route from the
destroyed data to the error can take an immense amount of time.

Consider too, the realities of the lcc-win32 implementation. The malloc runtime function
furnished with the Windows system is quite possibly the worst implementation available.
When compiled for the standard memory allocator, Wedit takes 80 seconds to load an 8
MB project. This time is reduced to only 5 seconds with the collector.

You should know, however, that the memory manager requires a few simple rules to
operate properly. These rules are common sense, so they are easy to understand and
follow.

Lcc-win32 User’s Manual 14


Preparing your Programs for Use with the Memory Manager
Below are a few simple rules to follow when using the memory manager.
1. Never store pointers to objects allocated with the collector in inaccessible places.
For instance:
• Do not store pointers in the window extra bytes, without keeping a pointer
somewhere in memory to indicate to the collector which object is being used. The
memory manager has no access to pointers inside the system’s data structures. It
will therefore assume that memory can be reclaimed, resulting in problems in
your program.
• Do not store pointers at odd addresses or at addresses that are not a multiple of
four. The compiler and the linker align the memory so that this is the case for all
your data when the program starts. Thereafter, you must follow this rule.
2. Do not store pointers in arrays declared as integers or in DWORDs. The compiler
generates type information and makes special calls to the memory manager when the
object allocated contains no pointers. Basically, it tells the collector to ignore those
memory locations, since they do not contain pointers. If you circumvent this with
casts, the collector will not know that the data are being used and will reclaim them.
3. It is better, though not required, to set all pointers that are no longer is use to ZERO
to avoid retaining too much data unnecessarily. If you do not do this, the data will be
retained until the scope of the pointer is finished. Pointers stored in global variables
remain indefinitely, so that the data they point to will never be reclaimed and the
program will leak. A similar situation holds for pointers stored as local variables in
the main() function
4. You should link with gc.lib, which is the import library of gc.dll. For technical
reasons, it is not possible to link statically with the gc. It must be a DLL. This means
that when you ship your program, it must be shipped with the gc.dll .5
The C Interface to the Collector
This interface is described in greater detail in the on-line documentation. It will not be
repeated here. You can find it if you go to the « index » item in the help menu, and
choose the memory manager link.

Function Description
void *GC_malloc(size_t size) ; Returns to the address of a new
memory block start. The object can
contain pointers to other objects.

5 The memory manager must be informed by the system when the program starts a new thread. The
stack of the new thread must be recorded. This is not possible with a static library. The collector data
structures are protected with semaphores, but the collector must stop all other threads to avoid being
called when a collection is not finished.

Lcc-win32 User’s Manual 15


void * GC_malloc_atomic(size_t size) ; Returns to the address of a new
memory block start, which cannot
contain pointers.
void *GC_realloc(void *oldObject,size_t Resizes the given object.
newSize) ;
void *GC_malloc_ignore_off_page( Large objects (> 100K) should be
size_t) ; allocated using this function.
size_t GC_size(void *object) ; Returns the size in bytes of the given
object.

Operator Overloading
Operator overloading is a powerful feature. It gives you the ability to replace the standard
infix notation with your own, i.e., writing a+b will be understood as a function call to a
function defined by you called ‘+’. This feature has a multitude of applications. Among
these are arrays bound checking and implementation of new numeric types, etc. Its usage
has been utilized extensively in the C++ language, so many people should be familiar
with it.

Usage
Operator overloading will be considered by the compiler as an option only for user
defined types, i.e., structures. Please note that this makes it impossible to redefine the
basic types, such as int or double.

The following typedef is assumed in the examples below:

typedef struct tagComplex {


double x;
double y;
} COMPLEX;

To define a new operator, proceed as follows:

COMPLEX operator +(COMPLEX left, COMPLEX right)


{
COMPLEX result;
result.x = left.x + right.x;
result.y = left.y + right.y;
return result;
}

Note several things here:


• This declaration can happen only at the global level, like all function declarations.

Lcc-win32 User’s Manual 16


• This function returns a NEW object.
• The input arguments to this function are pointers to objects, or as in the example, the
objects themselves passed by value.
• This declaration is equivalent to a function you would have written with a long name
(see how this name is derived below). Each time the compiler finds a match for this
function call within an addition, it will call this function.

Assume then that after this definition is seen by the compiler, you write the following
code:

int example(void)
{
COMPLEX a = {2.0,0.0},b = {3.0,0.0},c;
c = a+b;
}

This instruction will be interpreted as:

c = _op_plus_COMPLEX_COMPLEX(a,b);

The name of the function is derived as follows:


1. It starts with the prefix _op_ .
2. Followed by the name of the operator. The names are documented below.
3. Followed by an underscore to separate types, except for the last type.
4. If any spaces appear in the type, they will be substituted by an underscore. Thus
‘unsigned int’ will become ‘unsigned_int’.

Rules
1. All operators should have at least one argument that is a user defined structure.
2. Type conversions can be realized by defining different operators for different input
arguments. You can write several operators +, each with different arguments.

Here is an example for rule 2.

COMPLEX operator +(const COMPLEX left, const double right)6


{
COMPLEX result;
result.x = left.x + right;
result.y = left.y;
return result;
}

6 In lcc-win32 you can use pointers or references, and the ‘const’ attribute is not required. You can
modify the arguments to a plus operator, but that could cause problems.

Lcc-win32 User’s Manual 17


Then you can write in your code:

COMPLEX c = a + 5.9;

and the compiler will call the right operator for you. Note that the compiler-generated
name for this operator will be _op_plus_COMPLEX_double, which differentiates it from
the preceding example.

Operator Arguments
In this table, arguments that are preceded with const should not be modified by the
operator function. This has not yet been verified in lcc-win32, but you should not rely on
this.

The column titled ‘Pointer args?’ refers to the arguments of the operator redefining
function. Can it use just pointers as argument or must it have at least one argument that is
a structure or a reference to it?
In general, operations that are defined by the C language for pointers need at least one
argument that is NOT of pointer type to avoid ambiguities in the language. When you
write

char *p = “Hello”;
p++;

should the compiler call the redefined operator ++ or just increment the pointer? There is
no way to know, so an operator ++ should never have a pointer as an argument. On the
other side, division of pointers is not defined. If the redefined operator ‘/’ uses pointers as
arguments, no problems can arise. Note that this is much more general than C++, which
prohibits an operator to be redefined when only pointers are used as arguments.

Name Symbol Arguments Pointer Comment


only
args?
plus + const left, Yes Binary addition. Should
const right return a new object with the
result of the operation.
Arguments are const.
unary_plus + const right Yes Monadic plus. This is
normally blank for numeric
arguments, but can be used
for any purpose you wish
with your own structures.
Should return a new object.
plusasgn += left, No Should return its (possibly
const right modified) left argument.
increment ++ right No Post increment. Should

Lcc-win32 User’s Manual 18


return the unmodified value
of its argument. Normally,
as a side effect, the
argument can be modified.
minus - const left, No Binary subtraction. Same
const right constraints as binary +
unary_minus - const right Yes Monadic minus. Should
subtract its argument from
zero, in the numeric cases.
Should return a new object.
Normally it shouldn’t
modify its right argument.
minusasgn -= left, No Should return its possibly
const right modified left argument
decrement -- left No Post decrement. Should
return the unmodified value
of its argument. Normally,
as a side effect, the
argument should be
modified.
multiply * const left, Yes Multiplication. Should
const right return a new object with the
result of the operation.
multasgn *= left, Yes Should return its (possibly
const right modified) left argument.
divide / const left, Yes Division. Should return a
const right new object with the result of
the operation.
divasgn /= left, Yes Should return its (possibly
const right modified) left argument.
index []7 left, No Should return a reference to
right indexing the left argument
with its right argument, that
is always an integer
expression.
indexasgn []= left, No Should be assigned to the
index, left argument at the position
right indicated by indexing the
new value given by right.
leftshift << const left, Yes Should leave its right
const right argument unmodified and
return a (possibly modified)

7 Note that in C++ the operator [ ] can only be redefined at the class level. Since there are no
classes here, this restriction does NOT apply.

Lcc-win32 User’s Manual 19


left argument.
rightshift >> const left, Yes Should leave its right
const right argument unmodified and
return a (possibly modified)
left argument.
lshasgn <<= left, Yes Should return its (possibly
const right modified) left argument.
rshasgn >>= left, Yes Should return its possibly
const right modified left argument.
not ! const right Yes Should return a new object.
Normally it shouldn’t
modify its right argument.
equal == const left, No Should return an integer
const right other than zero if the
comparison succeeds,
otherwise zero. The
arguments shouldn’t be
modified.
lessequal <= const left, No Should return an integer
const right other than zero if the
comparison succeeds,
otherwise zero. The
arguments shouldn’t be
modified.
greaterequal >= const left, No Should return an integer
const right other than zero if the
comparison succeeds,
otherwise zero. The
arguments shouldn’t be
modified.
less < const left, No Should return an integer
const right other than zero if the
comparison succeeds,
otherwise zero. The
arguments shouldn’t be
modified.
greater > const left, No Should return an integer
const right other than zero if the
comparison succeeds,
otherwise zero. The
arguments shouldn’t be
modified.
notequal != const left, No Should return an integer
const right other than zero if the
comparison fails, otherwise

Lcc-win32 User’s Manual 20


zero. The arguments
shouldn’t be modified.
8 () at least one Yes Function call overloading

Differences to C++

In the C++ language, you can redefine the operators && (and) || (or) and , (comma). You
cannot do this in C. The reasons are very simple.
In C (as in C++), logical expressions within conditional contexts are evaluated from left
to right. If, in the context of the AND operator, the first expression returns a FALSE
value, the others will NOT be evaluated. This means that once the truth or falsehood of
an expression has been determined, evaluation of the expression ceases, even if some
parts of the expression haven't yet been examined.
Now, if a user wanted to redefine the operator AND or the operator OR, the compiler
would have to generate a function call to the user-defined function, giving it all the
arguments of BOTH expressions. To make the function call, the compiler would have to
evaluate them both, before passing them to the redefined operator&&.
Consequence: all expressions would be evaluated and expressions that rely on the normal
behavior of C would not work. The same reasoning can be applied to the operator OR. It
evaluates all expressions, but stops at the first that returns TRUE.
A similar problem appears with the Comma operator, which evaluates in sequence all the
expressions separated by the comma(s), and returns as the value of the expression the last
result evaluated. When passing the arguments to the overloaded function, however, there
is no guarantee that the order of evaluation will be from left to right. The C standard does
not specify the order for evaluating function arguments. Therefore, this would not work.9
Another difference with C++ is that here you can redefine the operator []=, i.e., the
assignment to an array is a different operation than the reference of an array member. The
reason is simple: the C language always distinguishes between the operator + and the
operator +=, the operator * is different from the operator *=, etc. There is no reason why
the operator [] should be any different.
This simple fact allows you to do things that are quite impossible for C++ programmers:
You can easily distinguish between the assignment and the reference of an array, i.e., you
can specialize the operation for each usage. In C++ doing this implies creating a “proxy”
object, i.e., a stand-by construct that senses when the program uses it for writing or
reading and acts accordingly. This proxy must be defined, created, etc., and it has to
redefine all operators to be able to function. In addition, this highly complex solution is
not guaranteed to work! The proxies have subtle different behaviors in many situations

8 Not yet implemented.


9 Note that this does not work in C++ either. Lengthy explanations are required to dissuade users from
redefining these operators, the best one is in Scott Meyer’s book “Effective C++”, see “Item 7: Never
overload &&, ||, or ,”. Personally, I do not understand why things should be present in a language only to
then have to write lengthy explanations on why these features are not useful or are risky. A cleaner design
would omit those features.

Lcc-win32 User’s Manual 21


because they are not the object they stand for.You do not need all of these complexities
in your software. You are in control. This is C.10
References11

References are pointers that are always initialized in their declarations to some existing
object, and cannot be re-assigned to point to other objects. They will always be
dereferenced when used, so their usage differs from pointers in their syntax. The formal
description of their usage is:

<type> ‘&’ <identifier> ‘=’ <object of the specified type> ;

Examples:

int a = 7;
int &ra = a;

ra++; // Now a is 8. The integer is incremented, not


the pointer

This is a reference to an integer that is initialized to point to the address of the integer ‘a’.
Note that you should not specify the address-of operator, as you would do with a normal
pointer. It is the compiler that internally takes the address of the resulting object.

Rules for References12


• References cannot be re-assigned. Any re-assignment of a reference is a compilation
error. The only exception is the initialization of a reference when it is declared or
when the declaration includes an explicit external keyword.
• In an external reference, the type of the reference must be explicitly known to the
compiler when the reference is first used, since to dereference an object (and
references are always dereferenced when used) the compiler must know its definition.
• A function that expects a reference cannot receive a pointer. Pointers and references
are not compatible and no automatic conversion between pointers and references is
provided. To convert a reference to a pointer, use the address-of operator
(‘&’).

10 In a (rather lively) discussion in the comp.std.c newsgroup jepler epler pointed that in Python:

“The expression i = x[j] will call the method x.__getitem__(j) and assign the returned value to i.
The expression x[j] = i will call the method x.__setitem__(j, i)
I make the first out as being analogous to operator [], and the second as the proposed operator []=.”
11 This construct is needed by the problem of the operator [ ]. To avoid having the construct
Vector[5] = 6; be forced to be written as *Vector[5] = 5; or add a new operator [ ]= incompatible with
the C++ language, I decided to add the references to lcc-win32. This has ancillary benefits because in
general, references are cleaner than pointers: you can do fewer things with them. Since they always
have to be initialized to a known object, there is less room for error.
12 These rules are the same as in the C++ language.

Lcc-win32 User’s Manual 22


• Tables of references are not possible.
• Pointer arithmetic is not possible with references.
• References of references are not possible.
• The initialization of a reference should always follow the declaration, unless the
declaration is a function argument or a function result.
• Arrays of references are not possible.
• A reference cannot be assigned to a bit-field.
• The address of a reference cannot be taken, since the address-of operator will be
applied to the object to which the reference points. In the example above, the
expression &ra means the address of the object ra points to the integer a. The result
will be the address of a and not the address of the reference.
• Since the address of a reference cannot be taken, there can be no pointers to
references.
• In a function call to a function, which has a reference as argument in its prototype, the
reference and not its value will be passed.
• In a function call to a function with no prototype or with one that does not have a
reference in the given position, the value pointed to by the reference will be passed.
• In a return statement, when the function has a reference as return value, the compiler
automatically takes the address of the resulting object, and returns this reference as
the result of the function.

In C++, passing arguments by reference avoids calling the automatic constructors and
destructors for the object. Since there are no destructors or constructors called
automatically here, the need for references is less pronounced. C is not C++, and there
are no functions being called ‘behind your back’ by the compiler. All implicit function
calls are those redefined explicitly by the program.

Examples:
Given

int fn(int &arg)


{
return arg+8;
}
You cannot use:
fn(6);

for instance. A constant is not automatically converted to a reference. This is consistent


with the C++ behavior.

Using Operator Overloading: An Example

To demonstrate how to use this, a simple implementation of the “<<” syntax of C++ for
output is illustrated.

Lcc-win32 User’s Manual 23


Description

The left shift operator will be redefined with each of the basic types. Start by defining a
structure that will contain the necessary information for output.

typedef struct tagiostream {


FILE *f;
unsigned left:1; // Left-align values
unsigned right:1; // Right-align values; pad on the
left
// with the fill character (default
alignment).
unsigned dec:1; // Format numeric values in decimal
unsigned oct:1; // Format numeric values in base 8
unsigned hex:1; //Format numeric values as base 16
(hexadecimal).
unsigned showpoint:1; // Show decimal point and
trailing zeros
// for floating-point values.
unsigned uppercase:1; //Display uppercase A through F
//for hexadecimal values and E for
// scientific notation.
unsigned showpos:1; // Show plus signs (+) for positive
values.
unsigned scientific:1; // Display floating-point
numbers
// in scientific format.
unsigned unitbuf:1; //Cause flush the stream after each
insertion.
unsigned showbase:1; // Show the output base
unsigned char fill; //Sets or reads the streams fill
character.
unsigned char precision;
unsigned char width;
} iostream;

This structure allows fine control of the displayed output.

Start defining the different types of operator << for the different types of right hand
values. The simplest is the character string.

iostream * operator<<(iostream * f,char *p)


{
int n = fprintf(f->f,"%s",p);
while (n < f->width) {
fputc(f->fill,f->f);
n++;
}
return f;

Lcc-win32 User’s Manual 24


}

You call fprintf with the underlying value, and put as many of the fill chars as needed to
fill the current width. Note that the return value is the structure iostream received in
input, so that several of these operators can be linked together.

The other types are similar: For instance, integers:

iostream * operator <<(iostream *f,int i)


{
unsigned char buf[50];
if (f->dec)
sprintf(buf,"%d",i);
else if (f->oct) {
if (f->showbase)
sprintf(buf,"0%o",i);
else
sprintf(buf,"%o",i);
}
else if (f->hex) {
if (f->showbase)
sprintf(buf,"0x%x",i);
else
sprintf(buf,"%x",i);
}
return f << buf;
}

Fill a buffer containing the different possible representations of an int, and then call the
previously defined operator << for strings, that will handle the width options.

Provide a function that will return a new iostream with an open file pointer as input.
Allocate the new structure with the standard “malloc” function, set the default fields, and
return it.

iostream *new_ios(FILE *f)


{
iostream *result = (iostream
*)malloc(sizeof(iostream));
memset(result,0,sizeof(iostream));
result->f = f;
result->precision = 6;
result->dec = 1;
result->fill = ‘ ‘;
return result;
}

A simple program can be used to test at this point:

Lcc-win32 User’s Manual 25


int main(void)
{
iostream out = new_ios(stdout);
int a = 7;
out << “Hello ” << a << “\n”;
close_ios(out);
}

This will produce the output:

Hello 7

If you want to change the settings (output base say), you must manipulate the iostream
structure directly. A more elegant solution is to define a new structure that will be a place
holder. An appearance of that structure in the output stream would provoke no new
output, but a change to the settings of the underlying iostream structure. Define the new
structure as follows:

typedef enum {Flush,Dec,Oct,Hex} controlsequences;


typedef struct _control {
controlsequences val;
} Control;
Control flush = {Flush};
Control dec = {Dec};
Control oct = {Oct};
Control hex = {Hex};

Define a structure that contains just one field: a member of the enumeration of possible
actions to perform. With this defined, you only have to add a new operator<< to assign
meaning to those structures embedded in the output stream:

iostream * operator<<(iostream *f,Control e)


{
switch (e.val) {
case eflush:
fflush(f->f);
break;
case edec:
f->dec = 1;
f->oct = 0;
f->hex = 0;
break;
case eoct:
f->dec = 0;

F->O
f->hex = 0;

Lcc-win32 User’s Manual 26


break;
case ehex:
f->dec = 0;
f->oct = 0;
f->hex = 1;
break;
}
return f;
}

No output is performed, but the settings of the stream are changed. Use the following
program to test this:

int main(void)
{
iostream out = new_ios(stdout);
int a = 12345;
cout << "Dec: " << a << oct << " Octal " << a <<
" Hex: " << hex << a << nl;
close_ios(out);
}

This will produce the output:

Dec: 12345 Octal 30071 Hex: 3039

See the iostream library documentation for a more detailed description of this feature and
the source code of iostream.c in \lcc\src\iostream.

Another example of operator overloading is in the doubledouble directory, where a new


numeric type (doubledouble) is introduced, which replaces the normal floating point data
type and has extended precision.

Generic Functions

Generic functions allow you to specify different arguments list for an abstract function
type. This allows the programmer more flexibility in specifying the argument list for a
function.

To give an idea of how these functions are used here is an example:

double overloaded sqrt(double);


int overloaded sqrt(int);

This declares two different functions that will get an automatic name furnished by the
compiler. Those functions will be selected at the call site according to their arguments
list: if the argument list is a double, the first function will be called and the type of the

Lcc-win32 User’s Manual 27


resulting expression is a double. If an integer is given, the second function will be
selected and the resulting type is integer.

The exact syntax is:

Short form:

<return type> overloaded identifier ( argument-list )

Example:
double overloaded sqrt(double);

The compiler will supply here automatically a name for this function. The name will be
constructed from the overloaded identifier and the argument list.

Long form:
<return type> overloaded identifier . identifier ( argument-
list )

Example:

double overloaded sqrt.DblSqrt(double);


int overloaded sqrt.IntSqrt(int);

The long form allows the programmer to override the automatic name of the function and
furnish its own. This is important since it allows for easy interfacing of the software that
uses this extension with other software.

This extension doesn’t introduce a new keyword. You can still define

int overloaded = 0;

or

int overloaded(int a);

or even

typedef int *overloaded;


overloaded foo(int a);

and this will compile as you would expect. In the last example the typedef definition is
used, since overloaded functions can’t have an implicit “int” result: they must be given a
full prototype.

If you need (for whatever reason) to force the compiler to choose one of the overloaded
functions, you should use the long notation and just call the function in question:

Lcc-win32 User’s Manual 28


double overloaded sqrt.DblSqrt(double);
int overloaded sqrt.IntSqrt(int);

You can force calling the first function just with:

double s = DblSqrt(4.9);

The DblSqrt function will be visible in the current scope after the “overloaded”
declaration is seen.

Rules for using this extension


• You can add any number of overloaded arguments lists to an identifier, but once
the first call to such a function is generated, it is impossible to add a new
definition.
For instance :

double overloaded sqrt(double);


int overloaded sqrt(int);
int foo(void)
{
double a = sqrt(2.3);
}
double overloaded sqrt(complex) ;
This is an error. All overloaded function definitions must be present when the first call is
generated.
• You must supply the « overloaded » marker at the declaration and at the definition of
the function. For instance, it is an error when you write :
double overloaded sqrt(double) ;
double sqrt(double) // error : redefinition of sqrt.
{

}

Applications of overloaded functions

This extension is very useful for constructors. For instance consider:


typedef struct _Person {
char *Name;
int Age;
} Person;

Person * overloaded newPerson(void)

Lcc-win32 User’s Manual 29


{
return (Person *)malloc(sizeof(Person));
}

Person *newPerson(char *name)


{
Person *result = malloc(sizeof(Person));
result->Name = name;
return result;
}
Person *newPerson(char *Name,int age)
{
Person *result = (Person *)malloc(sizeof(Person));
result->Name = name;
result->Age = age;
return result;
}

etc.

Other Syntactic Enhancements


Declarations anywhere within a code block
You can declare an identifier not only at the beginning of a block, but anywhere within a
compound statement. For instance:

int example(void)
{
int a = 2,b = 3,c = 4,d;
d = a+b;
int e = d+a; // e is now declared as an int.
e += 34;
return e;
}

The scope of the identifier extends to the end of the current block. Note that this is NOT
an extension of the C language, since the new ANSI C standard accepts this as normal
usage.

The ‘for’ Statement Introduces a New Scope


Within a for statement, you can declare local for loop variables. The scope of these
variables is finished when the for statement ends.

#include <stdio.h>
int main(void)
{
for (int i = 0; i< 2;i++) {
printf("outer i is %d\n",i);

Lcc-win32 User’s Manual 30


for (int i = 0;i<2;i++) {
printf("i=%d\n",i);
}
}
return 0;
}

The output of this program is:


outer i is 0
i=0
i=1
outer i is 1
i=0
i=1

Note that the scope of the identifiers declared within a ‘for’ scope ends just when the for
statement ends, and that the ‘for’ statement scope is a new scope. Modify the above
example as follows to demonstrate this:
#include <stdio.h>
int main(void)
{
for (int i = 0; i< 2;i++) { 1
printf("outer i is %d\n",i); 2
int i = 87; 3
for (int i = 0;i<2;i++) { 4
printf("i=%d\n",i); 5
} 6
} 7
return 0; 8
}

At the innermost loop, there are three identifiers called ‘i’.


• The first i is the outer i. Its scope goes from line 1 to 7 — the scope of the for
statement.
• The second i (87) is a local identifier of the compound statement that begins in line 1
and ends in line 7. Compound statements can always declare local variables.
• The third i is declared at the innermost for statement. Its scope starts in line 4 and
goes up to line 6. It belongs to the scope created by the second for statement.
• Note that for each new scope, the identifiers of the same name are shadowed by the
new ones, as you would normally expect in C.

Lcc-win32 User’s Manual 31


Functions with optional arguments
This feature allows you to define some or all of the arguments of a function to have
default values. If the arguments aren’t supplied, the compiler generates the default
values and pass them to the called function.

Example :
int foo(int a,int b = 45,double c = 0.777) ;
The function « foo » needs always the first argument in a call, but if arguments b or c
aren’t supllied they will default to 45 and 0.777 respectively.
There are then three types of call in this example :
foo(1) ; // This is equivalentd to foo(1,45,0.777) ;
foo(1,2) ; // This is equivalent to foo(1,2,0.777) ;
foo(1,3,0.1) ;

An Application of Operator Overloading: The iostream Library


This library allows you to use the << notation for output, as in C++. The current
implementation is just a sketch of what is possible, and allows the basic functionality, but
it is NOT 100% compatible with the very complex iostream library of C++. The reasons
are many, the principal being that C is not C++, and classes and other C++ constructs are
not recognized.13

This will still allow you to compile C++ code with minimal changes.

The iostream library is based on the iostream structure, defined in iostream.h.


Two types of iostreams are defined:
• File based: The stream uses a FILE structure and when you write into it, you actually
write to that file. You should first open a file in the usual way with fopen, or use one
of the predefined standard file names (stdout for instance).
• String based: The stream uses a fixed or a resizable string buffer. When you write to
this stream you append characters to the string buffer. If the string buffer is resizable,
it will automatically be reallocated when full.

Creating a Stream
A stream can be created using two functions:
1. iostream_new_from_file(FILE *); This function will create a file based iostream
using the given file name.
2. iostream_new_from_string(char *,int); This function will create a string based
stream using the given character string buffer and its length.

13 The objective for this first version is just a minimal functionality, and some compatibility with
C++, but not 100% compatibility.

Lcc-win32 User’s Manual 32


Input arguments Meaning
Input string is null Create a resizable stream and allocate the initial buffer to it. This
and length is zero is the most common situation.
Input string is null Create a non-resizable stream of the given length, allocate the
and length is non- initial buffer.
zero
Input string is non- Create a resizable stream using a copy of the given string. The
null and length is zero current location will be at the end of the given string.
Input string is non- Create a non-resizable string based stream, using the given
null and length is buffer. When the buffer is full, the write operations will not
non-zero affect the stream in any way.

Examples:

// the stream is string based and resizable.


// The initial buffer is allocated.
iostream *ios = iostream_new_from_string(NULL,0);

// The stream is string based but not resizable.


iostream *ios = iostream_new_from_string(NULL,4096);
// Create a resizable, string-based stream and use the
// initial contents of the given string.
iostream *ios = iostream_new_from_string(“Results:”,0);
// Create a fixed, string-based stream using the given
buffer.
iostream *ios =
iostream_new_from_string(buffer,sizeof(buffer));

Using iostreams
Below is a very simple example:

#include <iostream.h>
int main(void)
{
iostream *cout = iostream_new_from_file(stdout);
cout << "Hello" ;
cout << "world" << “\n”;
}

This example will produce the well-known words in your screen. Note that “\n” and NOT
‘\n’, is used, since single quotes are not supported. The problem is that in C, single quotes
are just integers, which will provoke the numerical value of the character to be added to
the stream instead of the character itself.

Lcc-win32 User’s Manual 33


Iostream Modifiers
• You can change the width of a field using the iostream_set_width function:
int iostream_set_width(iostream *i,int w);
This function will restore the previous field width value.
• You can change the base used for numerical conversions with:
int iostream_set_base(iostream *,int);
This function will restore the previous base in use. To just query the current base use:
int iostream_get_base(iostream *);
This will restore the current base in use.
You can change the current position with:
int iostream_seek(iostream *ios,unsigned long where,int
how);
The argument for these functions is identical to the fseek function of the standard library.
Note that with string-based streams, the buffer will be extended to have at least the size
requested.
You can obtain the current position of a stream with:
int iostream_tell(iostream *);
You can format an integer by grouping the numbers of three characters using the:
int iostream_set_thousands(iostream *,int);
If the given integer is different from zero, the thousands flag will be activated, if it is
zero, it will be deactivated. Note that this flag applies only to integers, not to floating
point values. The flag can be queried using the function:
int iostream_get_thousands(iostream *);
You can change the precision of the display for floating point data using:
int iostream_set_precision(iostream *,int);
and query the value of the precision with:
int iostream_get_precision(iostream *);
Note that values up to 255 can be stored in this field, but only values up to 15 are useful.
Embedding Modifiers
Some modifiers can be embedded in the stream. For instance:
#include <iostream.h>
int main(void)
{
iostream *cout = iostream_new_from_file(stdout);
cout << "Changing the output base\n";
a = 12345;
cout << "Decimal: " << a << oct << " Octal "
<< a << " Hex: " << hex << a << "\n";
}

This will produce the following output:


Changing the output base
Decimal: 12345 Octal 30071 Hex: 3039

The modifiers are:


• flush Flushes the stream. No effect on string- streams.

Lcc-win32 User’s Manual 34


• dec Sets the integer base to decimal
• oct Sets the integer base to octal
• hex Sets the integer base to hexadecimal.

Lcc-win32 User’s Manual 35


Using lcc-win32 from the Command Line

You can use the entire system without any GUI interface or even another editor, Make
utility, etc. Following is brief description of al ofl the command line switches accepted by
each utility.

If you choose to use the standard settings, however, skip this section for now. You can
perform these steps from the integrated development environment (Wedit).

In order for the utilities mentioned here to function, you must add the directory in which
the executables are saved (normally \lcc\bin) to your PATH environment variable.
Technically, this is just a convenience, but it is recommended.

The following executables should all be in your \lcc\bin directory. An explanation of


their functions follows:

Utility Function
apilist.dll Answers queries on which library exports a given API
bind.exe Binds an object file to prepare it for the dynamic loader
browsegen Builds a file with definition information for a given source file
buildlib Builds import libraries for making DLLs
buildapi Builds the list of all windows APIs in \lcc\lib\apilist.txt
dllwiz Manages the export definitions file for a DLL
dolibs Rebuilds all import libraries. Normally it runs only once when
lcc-win32 is installed, but it can be used at any time.
dynloader.dll The dynamic loader
iedit Icon/cursor/bitmap editor
f2c Fortran to C translator
gc.dll The memory manager DLL
lburg Compiler compiler. Not needed in normal operation. Only needed
if you modify the machine description of the compiler.
lc.exe Compilation driver. Calls the compiler, and if there were no
errors when compiling the source, it calls the linker.
lcc Preprocessor, C Compiler and assembler
lcclib Librarian. Used for maintaining object file libraries.
lcclnk Linker
lrc Resource compiler
make Utility for project maintenance
mc Message compiler
pedump Binary file dumper
rundos Utility to run an executable in a console window

Lcc-win32 User’s Manual 36


Wedit Integrated development environment
weditres Resource editor
wresdll.dll Resource editor DLL
windent.exe Indents (reformats) C programs
wizard Utility for generating an application skeleton

Lcc-win32 User’s Manual 37


Using the Compiler from the Command Line
The compiler can be used from the command line without the IDE. This action assumes
you have the \lcc\bin directory in your PATH environment variable.
c:\lcc\project> type hello.c
#include <stdio.h>
int main(void) {
printf(« hello\n ») ;
return 0 ;
}
c:\lcc\project> lcc hello.c (1)
c:\lcc\project> lcclnk hello.obj (2)
c:\lcc\project> hello.exe (3)
hello
c:\lcc\project>
You must first compile the source file. You call up the compiler (lcc.exe). Next, you
should link the resulting object file with lcclnk, the linker (2). The program can then be
executed by typing its name.
Below you will find the command line options for the compiler and the linker.
To build a Windows executable using some resources, the sequence of commands could
be:
c:\lcc\project> lcc win.c
c:\lcc\project> lrc win.rc
c:\lcc\project> lcclnk –subsystem windows win.obj win.res
c:\lcc\project> win
The only difference is that you should compile your resources using the lrc resource
compiler and add the resulting windows.res to your link command line. Please note that
you should specify ‘subsystem Windows’ in the linker command line to avoid having a
blank window appear whenever you start your program.
The compiler driver

The lc.exe compiler driver has the following format:

lc [ compiler options] files… [linker options]

This means that you give it all the compiler options first, then the files you want to
compile, then the options you want for the linker pass. Things in brackets are optional.
You can just use lc file.c and the driver will call the compiler without any options, as
well as the linker if all compilation steps happen without any error.
Note that you can pass to the driver an ambiguous file specification like

Lcc-win32 User’s Manual 38


lc *.c –o prog.exe

The “-o” option is to name the executable output file, and it is a linker option, that’s why
it is placed after the c files proper.

The driver will assume that rc files should be compiled with the resource compiler lrc,
and asm files will be assembled with lcc.
If more than one source file is given, the driver will write to stderr the name of the file
that is currently being compiled, and will echo the linker command line.
If there are errors during the compilation of any one file, the compilation goes on with
the next file, but the process will stop before the link step. The result code will be the
number of errors in either the compilation or in the linking step.
The Compiler

The technical documentation for the compiler (how it works) is described in the ‘lcc-
win32.doc’ document. Only the recognized command line options are listed below.
lcc-win32 Command Line Options

Option Meaning
-A All warnings will be active.
-ANSI Disallow the language extensions of lcc-win32: operator overloading and
references will not be accepted.
-E Generate an intermediate file with the output of the preprocessor. The
output file name will be deduced from the input file name, i.e., for a
compilation of foo.c you will obtain foo.i.
-E+ Like the -E option, but instead of generating a #line xxx directive, the
preprocessor generates a # xxx directive. Some systems need this option,
specifically some versions of gcc.
-EP Like the -E option, but no #line directives will be generated.
-Fo<file This forces the name of the output file. Normally lcc deduces that name
name> from the name of the input file, i.e., for foo.c, foo.obj, or foo.asm, or foo.i
will be generated.
This option allows you to specify another name. Please, be careful using
it, since no checks are run on the name. You can, in principle, make
careless errors, such as: lcc foo.c –Fogg.c and the output binary object
file will be called gg.c..., which is not recommended.
-g2 Generate the debugging information. Two types of debug information
will be generated: COFF and CodeView (NB09).
-g3 Arrange for function stack tracing. If a trap occurs, the function stack
will be displayed.
-g4 Arrange for function stack and line number tracing.
-g5 Arrange for function stack, line number, and return call stack corruption
tracing.
-D Define the symbol following the ‘D’. Example:

Lcc-win32 User’s Manual 39


-DNODEBUG
The symbol NODEBUG is #defined. Note that there is NO space
between the D and the symbol.
-U Undefine the symbol following the ‘U’.
-M Print in standard output the names of all files that the preprocessor has
opened when processing the given input file. If the Fo option is active,
printing will be done in the file indicated by the Fo option. No object file
is generated.
-M1 Print in standard output each include file recursively, indicating where it
is called from, and when it is closed. This option is used in the IDE in the
“Show includes” option.
-I Add a path to the path included, i.e., to the path the compiler follows to
find the header files. Example:
-Ic:\project\headers
Note that there is NO space between the I and the following path.
-O Optimize the output. This activates the peephole optimizer. Do not use
this option with the -g option above.
-errout= Append the warning/error messages to the indicated file. Example :
errout=Myexe.err
This will append to Myexe.err all warnings and error messages.
-eN Set the maximum error count to N. Example:
-e25
The compiler will stop after 25 errors.
-x Generate browse information in an .xrf file.
-E Generate an intermediate file with the output of the preprocessor. The
output file name will be deduced from the input file name, i.e., for a
compilation of foo.c you will obtain foo.i.
-S Generate an assembly file. The output file name will be deduced from the
input file name, i.e., for a compilation of foo.c you will obtain foo.asm.
-unused Warns about unused assignments and suppresses the dead code. Use with
care
-z Generate a file with the intermediate language of lcc. The name of the
generated file will have a ‘.lil’ extension (lcc’s intermediate language).
- Set the default alignment in structures to one, two, four, etc. If you set it
Zp[1,2,4,8, to one, this actually means no alignment at all.
16]
File.asm All files with a .asm extension are assumed to be files written for lcc’s
assembler. Beware: the syntax of lcc’s assembler is radically different
from all standard assemblers. See the chapter about the assembler for
more information.

Lcc-win32 User’s Manual 40


The Intrinsic Functions
Lcc-win32 offers a series of pseudo-functions that use the call syntax function, but which will
trigger the emission of an inlined assembly macro. These macros do not have the overhead of
the function call instruction and spare the cost of setting up and destroying a procedure frame.
They can be used only if the file « intrinsics.h » is present in the compilation unit.

Name Description
long long Returns a long long integer (64 bits) containing the number of cycles
_rdtsc(void) that the machine has done since it was turned on. Since this counter is
automatically incremented at each cycle, to get a time in seconds you
have to divide by the clock speed of your machine. For example if you
divide the value by 166 x 1e6 you get the number of seconds elapsed
for a 166 MHz machine. This intrinsic value will use up some cycles
for converting the 64 bit value into a floating point number, so there
will be an overhead of at most 1000 cycles: at 200 MHz this should be
5 millionths of a second.
int Returns the byte swapped long integer.
_bswap(long)
double Returns sin(arg), and stores the cosine in the address pointed by cos *.
_fsicncos(arg
,cos *)
double Returns the cosinus of its argument.
_fcos(double)
double Returns the sinus of its argument.
_fsin(double)
double Returns the constant pi in floating point format.
_fldpi(void)
double Returns the logarithm base 2 of e.
_fldl2e(void)
double Returns the logarithm base 10 of e.
_fldlg2(void)
double Returns the natural logarithm (base e) of 2.
_fldln2(void)
int Returns the carry flag as an integer. This value is VERY volatile, since
_carry(void) most calculations set/unset it. You should not assume that the value
returned is the value of the last C instruction performed, since the lcc’s
optimizer could re-arrange the instructions. The best way to do this is
to write only one operation, immediately followed by an assignment
expression. For example you should write:
a = b+c;
instead of
a = b+foo(5)+78;
If you test the carry/overflow flag at the end of a complicated
expression, you cannot know the exact operation that produced the
error. Besides, since many operations change this flag, an actual

Lcc-win32 User’s Manual 41


overflow could be hidden by the operations that follow it.

int Returns a long integer from the given double using the rounding mode
_fistp(arg) that is in effect at the time of the call. Normally this should be
rounding to nearest number, since lcc-win32 never changes this
setting. This allows for very fast rounding. Remember that to satisfy
the rules of ANSI C, lcc-win32 is forced to set the rounding to
truncation, round the figure, and then restore the original mode. This
can be avoided by using this intrinsic function to round floating point
data.
int Returns the value of the overflow flag. The same considerations apply
_overflow(voi as to the carry() function above.
d)
int Rounds the given floating point number to an integer using the current
rint(double) rounding mode. By default, the rounding mode is round to nearest
number. To use this, you should include <math.h>.
int Returns an integer with the index of the first non-zero bit in the given
_bsr(long) integer, starting with the most significant bit.
int Returns an integer with the index of the first non-zero bit in the given
_bsf(long) integer starting with the least significant bit.

Lcc-win32 User’s Manual 42


Lcc-win32 offers special macros for all MMX instructions. Please refer to the associated
documentation.
Size, Storage, and System Specifics
This table shows the sizes and alignment of C data types. Since the size of signed and
unsigned types are the same, they are not shown.

Data Size Alignment Notes


type (bytes)
bool 1 1
char 1 1 Source and execution character sets are
standard ASCII.
short 2 2 Integer is converted into short form by
truncation.
int 4 4 The difference of two pointers is an int.
long 4 4
long 8 4
long
float 4 4 Exponent : 8 bits, mantissa 23.
double 8 4 Exponent : 11 bits, mantissa 52.
pointer 4 4
T[n] n * sizeof T Same as T
(Array)
Enums 4 4 Enums are implemented as ints.
The compiler creates segments for code, data, and uninitialized data. The segments (or
sections, in COFF terminology) are the following:
• The code section stores the executable statements.
• The initialized data section stores all literal constants
• The uninitialized data section (bss) is initialized to zero by the operating system.
The format of the debug information generated is compatible with the NB09 standard as
published by Microsoft and Intel Corporations. Any debugger that understands that
format can be used with the generated code.

Pragma Directives of lcc-win32


Packing directives. These directives tell the compiler how to pack the structure
members.

Lcc-win32 User’s Manual 43


This directive can have two forms:
#pragma pack(n)
where n is 1,2,4,8, or 16. This will align the members of a structure at 1 (i.e., no packing)
at 2, 4, 8, or 16 bytes.
You can also use:
#pragma pack(push,n)
This will save the current value of the packing constant, and set it to n, which should be
an integer as explained above. After some code, this allows you to use:
#pragma pack(pop)
to restore the original value again.
Example:
The most common use is at the beginning of an include file to set the value to a certain
amount, and to restore it at the end of the file.
#pragma pack(push,1)
.....
#pragma pack(pop)
EOF
Include directives. The pragma
#pragma once
will ensure that the current file will be read only once by the compiler. Any further
directives for #including the same file will have no affect.
Optimization directives. This allows you to set the optimization flag on or off at certain
functions.
#pragma optimize(n)
where n will be either zero (no optimizations) or one (optimizations).
Switch generation control. The pragma
#pragma density(push,0.0)
will trigger the compiler to generate a table of all possible switch values between the
lowest and the highest case statements found, making a tradeoff that penalizes space for
speed. This can of course overflow if you have:
switch(i) {
case -10000000:
...
case 10000000:
...

Lcc-win32 User’s Manual 44


}
In this example, the generated table would have 20 million positions, which may not be a
good idea.
On the contrary, in other cases where the numbers are densely packed, this can be an
ideal optimization.
Runtime Organization
A stack frame is an area of storage associated with the activation of a function. A stack
frame that is allocated as a function is entered, and it is deallocated when the function
exits. Automatic (auto) variables are compiler-generated temporaries that are located in
the stack frame. It is organized as follows:

second parameter ESP+8


first parameter ESP+4
caller’s return address ESP+0
saved frame pointer ESP-4
local variables and temporaries ESP-8
ESP -n
saved registers (if any)

Usually, it is the EBP register that points to the stack frame. This register is used to
address all local variables and arguments. When possible, and when the user has
specified the –O (optimization) flag, lcc will not build a full stack frame, but just a
minimal one, consisting only of the saved return address and the registers used by the
procedure.

Saved Registers, Prolog and Epilog Sequences


Lcc-win32 always saves the registers EBX, EBP, ESI and EDI. Under no circumstances
when writing assembly modules should the values stored in these registers be lost.
A prolog is the code executed immediately upon a function entry, i.e., the code that
builds the stack frame for the function and saves the registers that the function will use.
An epilog is the code executed to deallocate the stack frame, and restore the saved values
of the registers.
The prolog sequence of lcc-win32 is:
push %ebp ; save the frame pointer
movl %esp,%ebp ; move the stack pointer to the frame pointer
subl <n>,%esp ; allocate space in the stack for the function’s variables

Lcc-win32 User’s Manual 45


push %esi ; save registers
push %edi
push %ebx
Symmetrically, the epilog sequence looks like this :
pop %ebx ; restore the saved registers
pop %edi
pop %esi
movl %ebp,%esp ; restore the stack
popl %ebp ; restore the old frame pointer
ret ;return to caller. Caller responsible for cleaning the
stack.
Registry Use of lcc-win32
Lcc creates the following key in the registry:
HKEY_CURRENT_USER\SOFTWARE\lcc
This key contains the following subkeys:
1. lcc\General General type of information
2. lcc\Compiler Compiler specific information
3. lcc\Wedit For the IDE
4. lcc\lcclnk For the linker
5. lcc\weditres For the resource editor
6. lcc\db Database extension

Following is a description of all keys used by lcc-win32. The prefix


HKEY_CURRENT_USER\Software\lcc
is assumed in all of them.

Key name Contents and description


SmallEiffel Path to the SmallEiffel compiler
Version Version number, for example “2.7”
compiler\includepath Path to the directory included
lcclnk\libpath Path to the libraries
Wedit Project management
All the keys following this will have the implicit path:
HKEY_CURRENT_USER\Software\lcc\Wedit
Accel Number of user-defined accelerators
Acceln Contents for the nth accelerator
BackgroundColor RGB for the current background color
CommentColor RGB for comment color
CurrentDir Current working directory

Lcc-win32 User’s Manual 46


Predefined Preprocessor Symbols
Lcc-win32 defines the following symbols:14
Symbol Meaning
__STDC__ Defined to 1. This identifies lcc-win32 as an
ANSI C compiler.
__DATE__ Contains the current compilation date in the
format: MMM DD YYY as a character string.
__TIME__ Contains the current time as a character string in
the format: HH:MM:SS Note that this “timer”
does not change, even if the compilation takes a
long time.
__FILE__ Contains the name of the current file without any
path component as a character string.
__func__ This symbol will be expanded by the compiler to
a character string containing the name of the
current function being compiled, or the character
string “<none>”if no function is currently
being defined.15
__LINE__ This symbol will be expanded to an integer
containing the current line number in the source
file. Note that this line number can be changed to
an arbitrary value with the # line directive.
__LCC__ Allows you to conditionally compile source for
the lcc compiler.
__LCCOPTIMLEVEL If optimization is on, i.e., the –O option was
given in the command line or if the #pragma
optimize was parsed, this preprocessor variable
will have the value one. If no optimizations are
active, its value is zero.
__LCCDEBUGLEVEL If the compiler is called with the –g<n> option
(debug level n) the value of LCCDEBUGLEVEL

14 Note that none of this identifiers can be undefined with the #undef macro directive.
15The standard gives the following definition for this:
“The identifier _ _func_ _ shall be implicitly declared by the translator as if, immediately
following the opening brace of each function definition, the declaration static const char
_ _func_ _[]="function-name"; appeared, where function-name is the name of the
lexically-enclosing function.”.
WG14/N843 ANSI standard page 45. Note that the behavior of lcc-win32 is more
lenient: the symbol still has a valid value outside a function.

Lcc-win32 User’s Manual 47


is n. If there is no –g in the compiler’s command
line, then its value is zero.
RC_INVOKED Defined by the resource compiler when active.
WINVER Contains a two-byte number with the major
version number of windows in the high byte, and
the minor version number in the low byte. This
value is determined at compile time. Note that
this predefined symbol CAN be changed with the
#undef directive.
WIN32 Defined to 1. Note that contrary to other
_WIN32 predefined symbols, this symbol can be
undefined with the #undef directive.
__int64 Defined as the long long integer type for
compatibility with the Microsoft compiler.
__cdecl Defined to the empty string for compatibility
__inline reasons.
_cdecl
_huge
Predefined Compiler Symbols

Symbol Meaning
_asm(“ “); In-line assembly instruction(s).
_stdcall Call convention declaring a function that cleans
up the stack before executing the return
statement.
_try Introduces a try block in the Win32 structured
exception handling.
_except Finishes a structured try block.
__declspec Declare special. Its arguments can be:
__declspec(dllimport)
meaning the symbol following this declaration is
imported from a foreign DLL, or:
__declspec(dllexport)
meaning this symbol should be exported from the
DLL being compiled.

Lcc-win32 User’s Manual 48


Standard Header Files of the lcc-win32 System
The compiler comes with a complete set of header files for the standard ANSI headers
and the windows header files. In the table below, the header files have been classified as
either :
• Windows related headers (WIN32)
• Standard in the largest sense, i.e., you will find those headers almost in any C
compiler. (STD)
• lcc-win32 specific files (LCC)

Header Type Description


activeds.h WIN32 Master includes file for the Active Directory component.
adshlp.h WIN32 Active Directory component.
adserr.h WIN32 Active Directory errors definitions.
adsiid.h WIN32 Active Directory GUIDs.
adsnms.h WIN32 Active Directory name scheme.
adssts.h WIN32 Active Directory status definitions.
assert.h STD Defines the assert macro.
bhtypes.h WIN32 Bloodhund types definitions
bignums.h LCC Bignum (arbitrary precision) library.
basetsd.h WIN32 Defines some types for porting from 32 bit to 64 bit windows.
cderr.h WIN32 Defines the common dialog box error codes.
cguid.h WIN32 Common GUIDs definitions.
cchannel.h WIN32 Virtual Channel Client API.
clusapi.h WIN32 Cluster Server API.
colordlg.h WIN32 Common color dialog box definitions.
comcat.h WIN32 COM categories information definitions and interfaces.
commctrl.h WIN32 Common controls definitions. Most are included in windows.h.
commdlg.h WIN32 Common dialog box definitions.
confpriv.h WIN32 Teleconferencing definitions.
conio.h STD Console input/output definitions. Other special purpose
functions like _kbhit() or outb are prototyped here.
cpl.h WIN32 Control panel extensions.
cplext.h WIN32 A few definitions for the property sheets extensions.
ctype.h STD Character classification routines (isdigit() etc.).
Custcntl.h WIN32 Custom control interface definitions for a general interface
between a control and a resource editor.
d3d.h WIN32 Direct3D include file.
d3dcaps.h WIN32 Direct3D capabilities definitions.
d3drm.h WIN32 Direct3D com interfaces.
d3drmobj.h WIN32 Direct3D com interface (continued).

Lcc-win32 User’s Manual 49


d3drmwin.h WIN32 Direct3D win device definitions.
d3dtypes.h WIN32 Direct3D types definitions.
d3dvec.h WIN32 Vector primitives for ddraw
d3dx.h WIN32 Master include file for directx
d3dxcore.h WIN32 D3DX core functionality
d3dxerr.h WIN32 D3DX error codes
d3dxmath.h WIN32 Mathematical functions for d3d
d3dxshapes.h WIN32 Simple shapes for D3DX
d3dxsprite.h WIN32 Sprite handling
dbghelp.h WIN32 Debugging information API.
dde.h WIN32 Dynamic data exchange definitions.
ddeml.h WIN32 More dynamic data exchange definitions (error messages,
codes, etc.).
ddraw.h WIN32 Direct draw interfaces and definitions.
digitalv.h WIN32 MCI Digital Video command set.
dinput.h WIN32 Direct input definitions.
dinputd.h WIN32 Direct input driver header file
direct.h STD Directory handling functions.
dispex.h WIN32 Extended dispatch interface (com stuff).
dls1.h WIN32 Direct music: interfaces and structures for the Instruments
Collection Form (RIFF DLLs).
dls2.h WIN32 Follow up to dls1.h above.
dmdls.h WIN32 DLS Download definitions for DirectMusic APIs
dmerror.h WIN32 Direct Music eror codes
dmusbuff.h WIN32 Direct music buffer definitions
dmusicc.h WIN32 Direct music core API.
dmusicf.h WIN32 Direct music definitions.
dmusici.h WIN32 Direct music interactive.
dlcapi.h WIN32 DLC interfaces and definitions.
dlgs.h WIN32 Definitions for the resource numbers in the common dialog
boxes.
docobj.h WIN32 OLE documents interfaces.
dplay.h WIN32 Direct play interfaces and definitions.
dplobby.h WIN32 Direct play definitions
dsadmin.h WIN32 Interface declaration for directory services.
dsetup.h WIN32 Direct X setup interface and flags (for directx sdk 6).
dsound.h WIN32 Direct sound interfaces and definitions.
dvp.h WIN32 Direct X video port definitions.
dxfile.h WIN32 Direct X file interface.
dynloader.h LCC Dynamic loader interface.
errno.h STD errno definitions.
evntrace.h WIN32 Event trace functions
faxcom.h WIN32 FAX services.

Lcc-win32 User’s Manual 50


f2c.h LCC Fortran compiler definitions. This will be available only if you
have the Fortran compiler.
fcntl.h STD File control definitions for the open() function.
fenv.h STD Manipulation of the floating point environment.
float.h STD Definitions of FLT_MIN/MAX, and other manifest constants.
frame.h WIN32 Bloodhund definitions
gc.h LCC Memory manager (gc) interface.
gdbm.h LCC GNU GDBM database interface.
hlink.h WIN32 Definitions for the hyperlink interface functions.
htmlguid.h WIN32 HTML GUIDs.
httpext.h WIN32 Microsoft HTTP protocol extensions.
httpfilt.h WIN32 Interfaces and definitions for the http filter extensions.
iads.h WIN32 Active directory interfaces and definitions.
icm.h WIN32 Microsoft color manager interface. Associated DLL: icmui.dll.
icmpapi.h WIN32 ICMP protocol. Associated DLL icmp.dll.
ils.h WIN32 Internet Locator API (ILS).
image.h LCC Interface to the dynamic loader.
imagehlp.h WIN32 Definitions for IMAGEHLP.dll: This DLL reads an executable
image (hence its name).
ime.h WIN32 Procedure declarations, constant definitions and macros for the
IME component.
imessage.h WIN32 External definitions for MAPI's IMessage-on-IStorage facility.
imm.h WIN32 Input Method Manager header. In the first versions of lcc-
win32, this file was included in win.h, but now has been
separated. The rationale for doing this is that it is a seldom-
used file. This file and its associated import library imm32.lib
allow you to process the special messages for extended
alphabets, such as Japanese.
ipexport.h WIN32 IP packet description. Defines structures useful for ping and
ARP.
ipifcons.h WIN32 Constants needed by the IP interface definitions.
iphlpapi.h WIN32 Functions to interact with the IP Stack for MIB-II (router).
iprtrmib.h WIN32 IP Router Manager definitions.
iptypes.h WIN32 Types descriptions for iphlpapi.
initguid.h WIN32 Defines the DEFINE_GUID macro.
intrinsics.h LCC Defines the intrinsics of lcc-win32. See also the Intrinsics
chapter of this documentation.
intshcut.h WIN32 Internet shortcut definitions.
io.h WIN32 Input/Output header file: findfirst, and other file related
functions are defined here. Specifically all low level file
functions like read/write/open, etc.
iostream.h LCC Extensions for the overloaded operator << to be used for
output.
isguids.h WIN32 Internet shortcut GUIDs.

Lcc-win32 User’s Manual 51


iso646.h STD Alternative spellings for and (&&) or (||), etc.
limits.h Compiler limits.
lm.h WIN32 LAN Manager definitions.
lmat.h WIN32 Schedule service API.
lmcons.h WIN32 LAN Manager constants.
lmdfs.h WIN32 NetDfs API structures and definitions.
lmerr.h WIN32 LAN Manager error codes.
lm*.h WIN32 Other LAN Manager include files.
locale.h STD Locale conventions.
lzexpand.h WIN32 Definitions for using expand and compress from lz32.exp.
malloc.h STD Memory management.
mapicode.h WIN32 Messaging API definitions.
mapidefs.h WIN32 Messaging API definitions.
mapiform.h WIN32 MAPI forms and forms registries.
mapiguid.h WIN32 Messaging API GUIDs.
mapitags.h WIN32 Messaging API tags.
mapix.h WIN32 Messaging API definitions.
math.h STD Mathematical functions prototypes.
mbctype.h WIN32 Multi byte ctype (classification) definitions.
mbstring.h WIN32 Multi byte string.h.
mcx.h WIN32 Modem usage definitions.
memory.h STD Empty file that just includes <string.h>.
mgmtapi.h WIN32 Windows SNMP management API header
midles.h WIN32 RPC serializing primitives.
mmreg.h WIN32 Multi-media definitions and interfaces.
mmsystem.h WIN32 Multi-media extensions, (MCI) definitions and interfaces. This
file will not be automatically included in <windows.h>.
mmx.h LCC MMX intrinsics definitions.
mprapi.h WIN32 Mpr Admin network definitions and APIs.
mq.h WIN32 Master include file for message queue applications.
mqmail.h WIN32 Master include file for the Message Queue Exchange
Connector or MAPI applications.
mqoai.h WIN32 Master include file for Microsoft Message Queue COM
objects.
msacm.h WIN32 Audio compression manager include file.
msfs.h WIN32 Microsoft Mail Transport definitions.
mshtmhst.h WIN32 Html controls definitions.
mswsock.h WIN32 Microsoft win sockets interface extensions.
msxml.h WIN32 XML definitions for XML 2.0.
multimon.h WIN32 Multi monitor support
nal.h WIN32 Network Abstraction Layer API. Associated DLL: nal.dll.
nb30.h WIN32 Net-Bios 3.0 support.
ndde.h WIN32 Network DDE interfaces and definitions.

Lcc-win32 User’s Manual 52


nspapi.h WIN32 Name Space Provider APIs.
oaidl.h WIN32 COM Interfaces. Mainly concerned with OLE Automation.
objbase.h WIN32 COM base interfaces.
objidl.h WIN32 COM Interfaces : Marshal, malloc, ROT, moniker, data object,
rpc.
ocidl.h WIN32 COM Interfaces (Connection point, class factory, ole control,
property page, persistent memory, frame site, font, picture, ole
in place and others.
odbcinst.h WIN32 ODBC header file.
odbcver.h WIN32 Version of the odbc interface.
ole2.h WIN32 OLE extended interface.
oleacc.h WIN32 Accessibility OLE Interface.
oleauto.h WIN32 OLE automation interfaces.
olectl.h WIN32 OLE Controls interface.
olectlid.h WIN32 Identifiers for the ole controls.
oledlg.h WIN32 OLE dialog boxes.
oleidl.h WIN32 OLE/COM interfaces.
pchannel.h WIN32 Virtual channel protocol header.
pdh.h WIN32 Performance data helper (pdh) DLL functions and definitions.
process.h STD exec and spawn prototypes.
propidl.h WIN32 Property set implementation in COM.
psapi.h WIN32 Process Status helper API.
ras.h WIN32 Remote Access Service definitions and interfaces.
raserror.h WIN32 Remote Access Service error messages and definitions.
rasshost.h WIN32 Defines the interface between third party security DLLs and
the RAS server.
regexp.h LCC Regular expressions package.
regstr.h WIN32 Global registry definitions.
resapi.h WIN32 Windows Cluster resources.
richedit.h WIN32 Rich edit control definitions and interfaces.
rpc.h WIN32 Remote procedure call interfaces and definitions.
rpsasync.h WIN32 RPC: Async features.
rpcbase.h WIN32 Remote procedure call interfaces and definitions.
rpcdce.h WIN32 RPC: DEC RPC runtime APIs.
rpcdcep.h WIN32 Remote procedure call interfaces and definitions.
rpcndr.h WIN32 RPC: Stub data structures and definitions.
rpcnsi.h WIN32 RPC: Name Service Independent APIs.
rpcnsip.h WIN32 RPC : The auto-handle features of the runtime.
rpcnterr.h WIN32 RPC: error messages.
rpcproxy.h WIN32 RPC: the proxy stubs.
rtp.h WIN32 RTP protocol definitions.
secext.h WIN32 Security function prototypes. This should not be included
directly, but through the security.h header.
security.h WIN32 Top level include file for security related information.

Lcc-win32 User’s Manual 53


servprov.h WIN32 Interface server provider definitions.
setjmp.h STD Non-local jumps definitions : setjmp and longjmp.
share.h WIN32 Definitions for sopen().
shellapi.h WIN32 Shell definitions and interfaces.
shlguid.h WIN32 Shell GUIDs.
shfolder.h WIN32 Shell folders definitions.
shlobj.h WIN32 Shell objects.
shlwapi.h WIN32 Shell functions definitions
signal.h STD Definitions for signal().
sql.h WIN32 Definitions for the SQL server.
sqlext.h WIN32 Definitions for the SQL server.
sqlucode.h WIN32 Sql Unicode definitions
sqltypes.h WIN32 Types definitions for the sql server.
sspi.h WIN32 Security support Provider interfaces and definitions.
stdarg.h STD Variable arguments lists definitions.
stdbool.h STD Contains definitions for true and false. Required by the C99
standard.
stddef.h STD Standard definitions.
stdint.h STD Portable type sizes.
stdio.h STD Standard input/output.
stdlib.h STD Standard C library.
string.h STD String runtime library definitions.
svrapi.h WIN32 NetAccess, NetConnection, NetFile, NetServer, NetSession,
NetShare and NetSecurity APIs. Primarily a Windows 95
specific network APIs.
tapi.h WIN32 Telephone API definitions.
tapi3if.h WIN32 Telephone API 3 interfaces (COM).
tcconio.h LCC Clone of the Turbo C console library, featuring functions to
clear the screen, etc.
tchar.h STD Portable char/wide char definitions.
time.h STD Time related definitions.
tlhelp32.h WIN32 Win32 tool help functions and definitions
tnef.h WIN32 MAPI implementation of the Transport Neutral Encapsulation
Format.
tom.h WIN32 Text Object Model header file (COM).
unknwn.h WIN32 Definition of the unknown interface (COM).
urlmon.h WIN32 Url monitor definitions.
vcr.h WIN32 MCI VCR definitions.
vfw.h WIN32 Video for windows definitions.
wchar.h STD Wide char definitions.
wctype.h STD Wide char type definitions.
weditres.h LCC Definitions for the dialog box editor.
wfext.h WIN32 Windows File Manager extensions.
win.h WIN32 Basic Windows definitions. This file contains the files:

Lcc-win32 User’s Manual 54


windef.h winbase.h wingdi.h winuser.h and wincon.h
of other compiler systems. Those files have been assembled
into a single file.
winable.h WIN32 Hooking mechanism to receive system events.
wincrypt.h WIN32 Cryptography API prototypes and definitions.
windows.h WIN32 Windows basic definitions. This file is just a small file that
includes <win.h>.
windowsx.h WIN32 Window message crackers; also controls API.
winerror.h WIN32 Includes windows.h.
wininet.h WIN32 Internet network definitions and interfaces.
winioctl.h WIN32 Ioctl interface description.
winnls.h WIN32 National Language Support component.
winperf.h WIN32 Performance monitor definitions.
winreg.h WIN32 Registry definitions and interfaces.
winsnmp.h WIN32 Windows SNMP implementation.
winsock.h WIN32 Windows sockets interface.
winsock2.h WIN32 Windows sockets interface 2.
winspool.h WIN32 Print spooler definitions.
winsvc.h WIN32 Service Control Manager interfaces. Not included in win.h.
wintrust.h WIN32 Trust interface.
winuser.h WIN32 Includes windows.h.
winver.h WIN32 Version resource description. This file will not be included
when you include windows.h. You should include it manually.
wpapi.h WIN32 Web publisher interfaces.
wpguid.h WIN32 Web publisher GUIDs.
ws2spi.h WIN32 Version 2.2.x of the WinSock SPI specification.
ws2tcpip.h WIN32 Extensions to the tcpip protocol
wtsapi32.h WIN32 Windows Terminal Server API.
wtypes.h WIN32 Includes windows.h.
winfax.h WIN32 Fax API.
winwlx.h WIN32 Windows logon extensions.
wmistr.h WIN32 WMI interface declarations and definitions
xlcall.h WIN32 Excel interface for C.

Lcc-win32 User’s Manual 55


The Linker
The general format of a link command line is as follows:
lcclnk [options] object-files library-files
The linker will default to the following import libraries:
LIBC.LIB A few C functions are in here
KERNEL32.LIB Kernel function calls
COMDLG32.LIB Common dialog boxes library
USER32.LIB Windows 'user' functions
GDI32.LIB GDI functions
ADVAPI32.LIB More Windows functions
COMCTL32.LIB Library for the common controls of Win32
CRTDLL.LIB Library for the 'C' runtime functions
These libraries do not need to be specified in the command line because the linker will
search them anyway.
The name of the object file can be an expandable file specification. For instance: '*.obj'.
If the name of the file begins with an '@', it will be interpreted as a list of object files to
be included in the link. For instance you can say:
lcclnk @list.lst
which will cause lcclnk to open a 'list.lst' file and to read the file names to be used in the
link.

The contents of that file could be:


h:\mywork\src\file1.obj
h:\mywork\lib\mylib.lib
etc.

One line should have only one file name. This option is especially useful if you have too
many files in the command line, which is limited by Win32.

Command Line Options Syntax


Options are introduced with the character '-' or the character '/'.
Example:
-map or /map
are identical options.
Registry keys used
To find the libraries, lcclnk uses the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\lcc\lcclnk\libpath

This is an ASCII_Z key that contains the full path of the libraries directory. If the linker
does not find this key, you will be prompted for it at the command line. If you enter a
correct path, lcclnk will always use it later.
Command Line Switches

-o <filename>

Lcc-win32 User’s Manual 56


Sets the name of the output file to file name. Insert a space between the o and the name of
the file.
Example:
lcclnk -o myexe.exe
If this option is absent, the name of the first file will be used.
-errout <filename>
Write all warnings/error messages to the indicated file name.
-subsystem <subsystem>
Indicate the type of output file. Subsystem can be one of:
1. Console
2. Windows
If you specify console, a console application is created. The standard input, standard
error, and standard output are opened. When the program is started, Windows
automatically creates a console window.
If you specify Windows, a windowed application is created. No console window is
created, and stdin, stdout, and stderr are NOT initialized.
-stack-commit <number>
The default stack reserves 1MB of stack space, and commits 4096 bytes of it. With this
option, you can commit more pages than one (4096 bytes). This means that a slight
improvement in execution speed can be attained with programs that use a lot of stack.
Example:
-stack-commit 27000

-reloc
This option instructs the linker to build a .reloc section. This section is a table of
relocations to apply if the executable cannot be loaded at its preferred load address. This
option is necessary under Win32s.
This option is automatically turned on for DLLs.

-dll
This option indicates to the linker that a .dll should be created instead of an .exe. The
process of building a DLL is very simple:
1. Compile the source(s) files for your DLL as you would compile normal sources.
2. Link the resulting object files using the option -DLL and provide the linker with the
names of the functions exported in a .def file that you include in the link.
3. Produce an import library using the implib utility.
EXAMPLE:
lcc mylib.c
lcclnk -DLL mylib.obj mylib.def
implib mydll.dll
The format of the .def file is as follows:
EXPORTS
Function
AnotherFunction
YetAnotherFunction
You write the EXPORTS keyword, followed by the name of each function of the DLL
you want to export (i.e., to make visible for use in another executable) in a single line.

Lcc-win32 User’s Manual 57


-map <filename>
This indicates the name of the map file. In the map file, you will find the addresses of all
symbols used in the link and the line number information, if available. The format for the
line numbers is simple: Address:line. The address is written in 8 characters prefixed by
the '0x', and the line number is written in 4 characters in decimal form. This option allows
you to find out where in your program a fault occurred by reading the address from the
dialog box that the system displays when a program crashes.

This option is not compatible with the -s option, i.e., if you ask to strip all symbols, no
line number information can be generated.
When creating an executable with the -s option to ship to customers, it is better to do the
link twice: One with the debugging information and a mapfile; the other stripped. First
create the stripped version and then the full one. The reason behind this is that when both
options -s and -map are specified, the linker writes a smaller link file without any line
number information. If you create the full link first, and then the stripped, this smaller
map file will overwrite the good one.
Example:
-map myexe.map

-s
This option indicates that the linker should strip all symbolic and debugging information
from the executable. This means the executable cannot be debugged with a debugger, but
that its size will be considerably smaller. In addition, the linking speed is increased
because the linker has less work to do. Use this option with debugged programs if you
believe this to exist.

-version nn.nn
This option adds the version number to the executable. The numbers are the major
version number and the minor version number. A period character separates them.

Example:
-version 3.8 or -version 99.01

-x
Analyzes the symbols that are declared 'extern', but which are never referenced in any
other object in the link. There are two cases:
1. The symbol is in the .text section (code section).
Even if this symbol is not used in other modules, it can be used in the same module. The
linker cannot determine this (without disassembling the whole object file), but you can
easily check this. Declare the function 'static' and recompile your source. If it is not used,
the compiler will issue a warning.
2. The symbol is in the .data or .bss section.
This is a data item and it is surely not used. Delete it from your source.
errout=<filename>

Lcc-win32 User’s Manual 58


Write all warnings or errors to the file name indicated. Do not include any spaces
between the equals sign and the name of the file.
Example:
errout=link.err
Lcclnk writes the errors to stderr by default. If you want the errors in the standard output
use:
errout=stdout
nounderscores
When creating a DLL for Visual Basic for instance, it is better to export names without
underscores from a DLL. This option will allow this.

Lcc-win32 User’s Manual 59


Libraries Distributed with lcc-win32
These libraries are distributed in the form of ASCII description files « .exp ». These files
will be transformed by the installation program into libraries in lcc-win32 format. This is
a different format than the format used by Microsoft, so the libraries generated are NOT
compatible with Microsoft or other compilers.
To see the contents of each library, look at the corresponding .exp file in the
\lcc\buildlib directory.
aclui.lib activeds.lib Advapi32.lib bdnapi.lib
cap.lib comctl32.lib Comdlg32.lib crtdll.lib
crypt32.lib ctl3d32.lib d3drm.lib dapi.lib
ddraw.lib dflayout.lib Dlcapi.lib dplay.lib
dplayx.lib dsound.lib gdi32.lib glide2x.lib
glu32.lib glut32.lib Hlink.lib iprop.lib
iostream.lib fdlibm.lib Icmp.lib Icmui.lib
imagehlp.lib imm32.lib Imm32.lib iphlpapi.lib
kernel32.lib loadperf.lib Lsapi32.lib lz32.lib
mapi32.lib mpr.lib Mprapi.lib msacm32.lib
mscms.lib msi.lib Mslsp32.lib msvcrt.lib
msvcrtd.lib msvfw32.lib Mswsock.lib nal.lib
netapi32.lib ntdll.lib Ntmsapi.lib odbc32.lib
odbccp32.lib ole32.lib Oleaut32.lib oledlg.lib
olepro32.lib opengl.lib Opengl32.lib pdh.lib
penwin32.lib pkpd32.lib rasapi32.lib rasdlg.lib
rassapi.lib riched20.lib rpcns4.lib rpcrt4.lib
resapi.lib scrnsave.lib segexp.lib mgmtapi.lib
rtm.lib secur32.lib setupapi.lib shell32.lib
shfolder.lib shlwapi.lib snmpapi.lib svrapi.lib
tapi32.lib tcconio.lib url.lib urlmon.lib
user32.lib userenv.lib Version.lib webpost.lib
win32spl.lib wininet.lib Winmm.lib winspool.lib
wintrust.lib wow32.lib ws2_32.lib wsock32.lib
wst.lib winfax.lib vfw32.lib
Other Libraries Distributed with lcc-win32 :

Lcc-win32 User’s Manual 60


The intel jpeg image processing library has been adapted to lcc-win32, and it is
distributed with the CDROM versions. It can be downloaded at no charge from:
http://www.ps.qss.cz/pub/lcc/inteljpg.exe.
The fdlibm mathematical library has been compiled under lcc-win32 and is included in
the normal distribution effective May 2000.
This library is intended to provide a reasonably portable reference quality (below one ulp
for major functions like sin,cos,exp,log) math library. Many of the functions in this
library are redundant with those in crtdll.dll, so it is not needed for each compilation.
There are, however, some functions that do NOT appear in the standard version of
crtdll.dll, for instance lgamma, or others. When in doubt, include this library in the linker
command line.
This library should be used if you intend to use the matherr function. It is NOT possible
to use the matherr mechanism with the standard crtdll.lib.
The following mathematical functions need fdlibm :

asinh acosh atanh


cbrt erf erfc
expm1 finite gamma
Ilogb lgamma log1p
logb scalbn significand

The regular expressions library. This library, developed several years ago by Henry
Spencer at the University of Toronto, implements the functions needed to compile and
execute a regular expression and apply it to a character string. The library is called
regexp.lib, and the include file is regexp.h.
The arbitrary precision library. This library defines the « bignum » data type. Bignums
are numbers of arbitrary precision that can be used instead of integers or floating point
numbers. The documentation for using this library is in Appendix 3. The include file is
« bignums.h » and the library is « bignums.lib ».
The GNU GDBM library is a hash based (key) database package that allows you to
associate arbitrary data with a key. To see the complete documentation for this package,
go to the index in the “Help” tab of wedit, and then click in the GDBM link.
The zlib2 compression library is distributed with the examples/CD-sources distribution.
This library allows you to compress data, so that it uses less space but keeping the same
information (without looses).
The Berkeley DB library is distributed in a separate file with sources (lccdb.exe)

Lcc-win32 User’s Manual 61


Other command line utilities
The Resource Compiler

The resource compiler receives an .rc file as input that is written in a special language for
describing resources. It will produce a binary file as output with the .res extension that
can be used with the other object files by the linker to build an executable.
Usage:
lrc [options] .RC input file
Switches:

Option Meaning
/r Build a .res file. This is assumed, so this option is there just for compatibility
with earlier versions of rc.
/v Verbose output
/m Build a map file. The name of the map file will be the same as the output file
with a .map extension.
/dSYM Define symbol. This is for Lrc's pre-processor.
/ofile Write the output into <file>. No space should be left between the o and the name
of the file.
/fo Same as above.
/l Default language number follows in hexadecimal.
/I Add an include path.
/p Print in the standard output a list of file dependencies of the given input resource
file.

Flags are not case sensitive.


The resource compiler defines the symbol
RC_INVOKED
To allow you conditional compilation of resources and to direct it to avoid much of the
program text.

Lcc-win32 User’s Manual 62


The pedump Utility
This utility has been the workhorse of lcc-win32. Without it, the linker and the debugger
would not exist. To be able to generate something, you must be able to see what you are
generating. See the technical documentation for more information about pedump.
Files types dumped are:
•EXE Executable files
•OBJ Object files
•RES Resource files
•DLL DLLs
•OCX Type libraries+dlls
•LIB Libraries
•TLB/OCA Type libraries
•DBG DLLs debug info

Option Description
/A Includes everything in the output. All sections, all data dumps, etc. The
code sections will be disassembled and if debug information is available,
the line numbers will be annotated in the resulting output.
/D Dumps the code view or gcc debug information. This option supports the
NB09 Standard from Microsoft, and the STABS format from gcc.
/E Dump the resources section.
/EXP If given an import library, pedump will generate a list of the exported
functions in a format suitable for the buildlib utility. See FAQ question 12
for further explanation. If given a DLL, pedump will print a list of the
exported symbols from the DLL, in the same format. If given an object
file, this option will trigger pedump to print a list of all public symbols
defined in the object file, in the same format.
/functionsize Will produce a table of all functions defined in the object or executable file
sorted by their size in bytes. The executable should have a symbol table
(debug information should be present).
/H Includes a hexadecimal dump of the sections in the file.
/HEX Dump contents in hexadecimal form, without any concern for structures in
the file. This allows you to dump any type of file.
/L Includes line number information.
/OUT:file Prints the output into <file> instead of standard output. If the given file
name contains spaces it should be enclosed in quotes.
/REL Shows the relocations.
/R Shows the resources in an executable.
/SUMMARY Shows the sizes for the main parts of the file only.
/S Dumps the symbol table. All the symbols are dumped with all the details.

Lcc-win32 User’s Manual 63


Useful if you are writing a compiler.
/SP Writes all the exported/imported symbols from an object file or
executable. This is a smaller and more readable output than /S.
/T Dumps a type library. This will be determined automatically if you present
to pedump a library that contains an exported function like
DllRegisterServer.
/X Extracts a section to a file. The name of the section immediately follows
the “x”. For instance /x.data will create a data.scn file with the contents of
the data section.
F2C — The Fortran Compiler

SYNOPSIS
f2c [option ... ] file ...
DESCRIPTION
F2c converts Fortran 77 source code in files with names ending in `.f' or `.F' to C source
files in the current directory, with `.c' substituted for the final `.f' or `.F'.
The lcc compiler is invoked if the compilation finished without error and an object file is
generated in the current directory.
If no Fortran files are named, f2c reads Fortran from standard input and writes C on
standard output.
File names that end with `.p' or `.P' are taken to be prototype files, as produced by option
`-P', and are read first.

The following options have the same meaning as in other Fortran compilers.
-C Compiles code to check that subscripts are within declared array limits
-Idir Looks for a non-absolute include file first in the directory of the current input file,
then in directories specified by -I options (one directory per option). Options -I2 and -I4
have precedence, thus a directory named 2 should be specified by -I./2.
-onetrip Compiles DO loops that are performed at least once if reached. (Fortran 77 DO
loops are not performed at all if the upper limit is smaller than the lower limit.)
-U Honors the case of variable and external names. Fortran keywords must be in lower
case.
-u Makes the default type of a variable `undefined' rather than using the default Fortran
rules.
-w Suppresses all warning messages, or if the option is `-w66', just Fortran 66
compatibility warnings.

The following options are peculiar to f2c.


-A Produces ANSI C. Default is old-style C. This option is not very useful with lcc-
win32, but allows you to port the resulting C code to other machines.
-a Makes local variables automatic rather than static unless they appear in a DATA,
EQUIVALENCE, NAMELIST, or SAVE statement.
-C++ Outputs C++ code. This will make the resulting code incompatible with lcc-win32,
and object file generation will not work. Again, this can be useful if you are porting the
code to another machine or you want to link the resulting code with C++.

Lcc-win32 User’s Manual 64


-c Includes original Fortran source as comments.
-cd Does not recognize cdabs, cdcos, cdexp, cdlog, cdsin, and cdsqrt as synonyms for
the double complex intrinsics zabs, zcos, zexp, zlog, zsin, and zsqrt, respectively.
-ddir Writes `.c' files in directory dir instead of the current directory.
-E Declares uninitialized COMMON to be Extern (defined to be overwrite-capable in
f2c.h as extern).
-ec Places uninitialized COMMON blocks in separate files: COMMON /ABC/ appears
in file abc_com.c. Option `-e1c' bundles the separate files into the output file, with
comments that give an unbundling sed(1) script.
-ext Complains about f77(1) extensions. This is useful if you want to remain compatible
with Fortran 66, the standard of more than 30 years ago.
-g Includes original Fortran line numbers in #line lines.
-h Emulates Fortran 66's treatment of Hollerith: tries to align character strings on word
(or, if the option is `-hd', on double word) boundaries.
-i90 Does not recognize the Fortran 90 bit-manipulation intrinsics btest, iand, ibclr, ibits,
ibset, ieor, ior, ishft, and ishftc.
-kr Uses temporary values to enforce Fortran expression evaluation where K&R (first
edition) parenthesization rules allow rearrangement. If the option is `-krd', uses double
precision temporaries even for single-precision operands.
-P Writes a file.P of ANSI (or C++) prototypes for definitions in each input file.f or
file.F. When reading Fortran from standard input, writes prototypes at the beginning of
standard output. Option -Ps implies -P and gives exit status 4; if rerunning f2c may
change prototypes or declarations.
-p Supplies preprocessor definitions to make common-block members look like local
variables.
-R Does not promote REAL functions and operations to DOUBLE PRECISION. Option
`-!R' confirms the default, which imitates f77.
-r Casts REAL arguments of intrinsic functions and values of REAL functions
(including intrinsics) to REAL.
-r8 Promotes REAL to DOUBLE PRECISION, COMPLEX to DOUBLE COMPLEX.
-s Preserves multidimensional subscripts. Suppressed by option `-C' .
-Tdir Puts temporary files in directory dir.
-w8 Suppresses warnings when COMMON or EQUIVALENCE forces odd-word
alignment of doubles.
-Wn Assumes n characters/word (default 4) when initializing numeric variables with
character data.
-z Does not implicitly recognize DOUBLE COMPLEX.
-!bs Does not recognize backslash escapes in character strings.
-!c Inhibits C output, but produces -P output.
-!I Rejects include statements.
-!i8 Disallows INTEGER*8.
-!it Does not infer types of untyped EXTERNAL procedures from use as parameters to
previously defined or prototyped procedures.
-!P Does not attempt to infer ANSI or C++ prototypes from usage.

Options specific to lcc-win32:

Lcc-win32 User’s Manual 65


-removec Instructs f2c to remove the intermediate C file.

The resulting C invokes the support routines of f77; object code should be linked with
lcclnk specifying libf77.lib at the end of the command line. Wedit will automatically add
this library when any of the project files end with .f.

SEE ALSO S. I. Feldman and P. J. Weinberger, `A Portable Fortran 77 Compiler',


UNIX Time Sharing System Programmer's Manual, Tenth Edition, Volume 2, AT&T
Bell Laboratories, 1990. This document is distributed with the source code of f2c. It is a
file for the Laserjet printer. To print it you should open a command shell and issue the
command: print f2c.prt.

FILES
f2c.h This file is used by the generated C code. It should be in the \lcc\include directory.
libf77.lib This file is the runtime of the Fortran system. It should be in the \lcc\lib
directory with all other libraries.
f2c.exe The is the compiler itself. It should be located in the \lcc\bin directory together
with all other executables.

DIAGNOSTICS
The diagnostics produced by f2c are intended to be self-explanatory. lcc-win32 will not
generate any warnings when called from f2c. The resulting C file can be invalid,
however, this provokes an error message from lcc-win32. This happens when you do not
adhere to the prototypes given or you have an error in the calling sequence: you are
calling a subroutine with different numbers of arguments within the same program. The
error issued by lcc-win32 follows the warning of the Fortran compiler.

BUGS
Floating-point constant expressions are simplified in the floating-point arithmetic of the
machine running f2c, so that they are typically accurate to, at most 16 or 17, decimal
places.
Untypable EXTERNAL functions are declared int.
The browsegen Utility

This utility is a modified version of the compiler that will produce a browse file
containing the position in the given source file or its included headers of the symbols
used. The format of the generated browse files is described in the technical
documentation. Use this utility only if you want to build browse information for use in
another software. Normally, this utility is only used by the IDE (Wedit) to answer
queries. A more detailed description of how it works is found in the technical
documentation.

Browsegen accepts the following command line options:

Lcc-win32 User’s Manual 66


• showifdeflines. This will trigger line numbers of inactive lines to be printed in
standard output or in the given output file. This is useful for finding out which lines in a
source file are being compiled or not.
• M1. This will show in the standard output all include files by the given input file.
• Fo<file>. Writes all output in the given file. This is exactly the same as the compiler
option Fo.
• -P –P1 –P2 –P3 –P4. This generates a C source file that contains the public or public
and private interface for the given source file.

Option Description
-P or –P1 Will write all the prototypes for the public (i.e. not static) functions defined
in the module.
-P2 Will write the public prototypes and data definitions for the given module.
-P3 Will write the prototypes for both the public and static functions, and the
public data dependencies.
-P4 Will write the public and static function prototypes, and the public and
static data definitions.

Note that only definitions at the global level will be written. Local or external variables
will never be written.
The buildlib Utility

This utility reads an ASCII description of symbols and produces an import library that
allows you to link your executable with a specific DLL.
It has no command line options and the input arguments are as follows:

buildlib <ASCII description> <output library>

The first argument has to be a text file that contains the list of symbols to be built into the
library; the second argument is the name of the library.

Normally, the extension used in lcc-win32 for this textual description is .exp. See the
directory \lcc\buildlib for numerous examples of these file types.

The format of the text file is as follows:

First line: Name of the DLL this import library should bind to. This is mandatory.
All other lines have a column format with 1 mandatory column and two optional
columns.

The first column should contain the symbol name as emitted by the compiler, i.e., with all
decorations, such as leading underscore, and '@nn' decoration for _stdcall symbols.

The second column is optional. It indicates the name of the symbol as it is exported from
the DLL. This can be different from the decorated form. For example, you may want to

Lcc-win32 User’s Manual 67


export a function without any decorations so that you can your DLL in other
environments. If you omit this column, buildlib will strip decorations from the symbol
names.

The third column is also optional, consisting of a single keyword 'data'. If present, this
means that the exported symbol is not a function, but a data item, i.e., a variable.
The lcclib Utility
The purpose of this utility is to build library files (.lib) from a list of object files. The
general format of the command line is:

lcclib <options> <library file> <object files >

Options:
Option Meaning
/out:libfile.lib Specifies the name of the output library file.
/extract:<object file> Extracts the specified object file from the library.
/remove:<object file> Removes the specified object file from the library.
/verbose Progress report will be printed to standard output.

The Bind Utility


This program inspects a given object file and appends to it a list of imported functions.
This list has the following format:

IMPORTS
CRTDLL.dll
_fprintf fprintf
USER32.dll
_LoadLibrary@4 LoadLibrary
...
$$END$$

In words: The list starts with the keyword ‘IMPORTS’, followed by a DLL list. Each
DLL starts with the name, followed by the imported functions from that DLL in the
object file.

Usage:
The syntax is:
bind <file name>

The argument should be the name of an existing object file.

The mergeasm utility

Lcc-win32 User’s Manual 68


This utility will take an assembler file as generated by the compiler, and will merge it
with the C source file. This needs that you instruct the compiler to generate debug
information with the –g2 option. The usage is very simple :

mergeasm input.asm MergedOutput.asm

This will read the corresponding C input file and merge it with the assemble file
input.asm, producing a merged « MergedOutput. asm » file.

Lcc-win32 User’s Manual 69


Wedit: The Integrated Development Environment

Command Line Arguments


Wedit understands the following command line parameters :

Argument Meaning
/prj : project-name Opens « project-name » at startup. This name should be a
valid project already created in previous sessions. Example :
Wedit /prj :parser
This opens the « parser » project.
/f Opens no projects or windows.
/w Opens no projects or windows and does not show the startup
banner.
executable-name Starts the debugger and debugs the executable named in the
more args command line. Passes all further arguments to the program
that will be started. For instance, if you want to debug foo.exe
with arguments silent and fast, write :
Wedit foo.exe /silent /fast
Note that the .exe extension is mandatory.
The Main Menu
To know the purpose of any menu option in Wedit, open the menu and run the mouse
over each item. A short explanatory text will be shown at the lower right of Wedit’s
window.
Following is a description of all menu entries:

• File: Opens and closes files, renames or saves the current file, opens or closes a
project.

Item Description
New Creates a new text file, a new Wedit window, or a new project.
Open Opens an existing file.
Open binary Opens an existing file and calls the binary editor to edit it.
Insert a file Inserts a text file at the current cursor position.
Save Writes the current document to disk.
Save as Renames the current document and writes it to disk.
Save all Writes to disk all modified files.

Lcc-win32 User’s Manual 70


Reload Discards any changes to the current file and reloads it from disk.
Set read-only Makes any modifications to the current file impossible.
Close Closes the current document.
Print Prints the current file or all loaded files.
Quit Closes Wedit.

• Edit: Text manipulation including moving blocks of text, reformatting the current
document, inserting a file, and other commands.

Undo Undoes the last action.


Cut Erases the current selection saving it in the clipboard.
Paste Copies the contents of the clipboard to the cursor position.
Copy function You choose a function and Wedit copies it to the clipboard.
Copy to file Copies the contents of the clipboard to a file.
Level Shows the bracket level.
Mark block Marks the current block (where the cursor is).
Spaces->Tabs Converts all white space to tabs if possible.
Tabs->Spaces Replaces all tabs with their equivalent in spaces.
Recenter Recenters the cursor in the screen.
Description Æ Edits a standard description of a function.
Function
DescriptionÆ Edits a standard description of a file.
File
Show changes Shows the changes made to the current document.
Reformat Reformats the program, adding indentation.

• Search: Searching or replacing character strings or regular expressions,


identifying a file, searching for a function, GREP.

Find Searches for a character sequence.


Find next Searches for the next occurrence of the previous search.
Find previous Searches backwards.
Replace Replaces one character sequence with another.
Find in files Searches for a character sequence in a set of files.
Goto Top Sets the cursor at the beginning of the file.
Goto end Sets the cursor at the end of the file.
Goto line Prompts for a line number and sets the cursor there.
Goto Previous Sets the cursor at the beginning of the previous function.
function
Goto Next Sets the cursor at the beginning of the next function.
function
Goto Prompts you for a bookmark and sets the cursor there.
Bookmark
Bookmark set Establishes a bookmark at the cursor position.
Bookmark Moves the cursor to a chosen bookmark.

Lcc-win32 User’s Manual 71


goto
Bookmark Moves the cursor to the next bookmark.
goto next
Bookmark Erases a bookmark.
delete
History Shows the list of visited functions for the current session.
Functions list Shows the list of all functions defined in the current file
Structures list Shows the definitions of all structures defined in the current file
Search a Shows the list of all functions defined in all loaded files. It allows for
function regular expressions for searching.
Search Moves the cursor to the definition of the symbol currently under the
definition cursor.
Symbol usage Shows all occurrences of a symbol,i.e. where its used. Comments and
strings aren’t included in the search.
ID Sets a character string containing the file nameand date of last save.
This string will be in the executable and can be searched to know
which files and which version of those source files were used to build
the executable
Identify file Searches the character strings generated by the ID feature.

• Project. Project-related options (reading, opening, creating, modifying, etc.) and the
general configuration wizard.

Configuration All the configuration options for the compiler, editor, debugger, linker,
help files, etc.
Create Starts the creation of a new project.
Open Loads an existing project.
Close Closes the current project.
Erase Erases a project you choose.
Add/Delete Inserts or deletes files from the current project.
files
Import Allows the user to browse for a project file (with the .prj extension),
and loads it into the projects list. This closes the current project (if
any).
Open all files Opens all the files defined in the current project.
Workspace Shows the modules of the current project. You can add/delete
modules, switch from one source file to the next, and many other
options. You turn on those options using the right mouse click.
After this entry All user-defined menu commands, added with the add utility option in
the configuration tab, start at this point.

• Resources. Resource editor.


Open/New Creates or opens a resource file.
Show directory Shows all the types of resources defined and each one of the objects.
Symbols Opens the symbol editing dialog box. With this you can add/change

Lcc-win32 User’s Manual 72


symbols assigned to controls.
Group Opens the group and hierarchy dialog box. Here you can establish the
tab sequence and set the group separators.
New Inserts a new object.
Alignment Aligns the selected objects.
Spacing Opens the spacing dialog box.
Same size Resizes the selected controls to the same size of the dominant control.
Buttons Positions the buttons either at the right or at the bottom.
Zoom Starts the zoom utility.
Config Opens the configuration dialog box of the resource editor.
Output Shows the name of the output files.

• Compiler: Compiler specific options. Make, Makefile generation, link, debug,


execute, etc.
Make Calls the Make utility to build the current executable. If the Make
utility is running, there will be an entry to stop the building process at
this point.
Shows results Shows the results (errors or warnings) of the last compilation, if any.
Link Calls the link editor.
Generate Generates an ASCII text file (Makefile) that specifies the
Makefile dependencies of the project files to the Make utility.
Rebuild all Erases all object files and starts a build.
Debugger Starts a debugging session.
Breakpoints Calls up the breakpoint editing dialog box.
Set breakpoint Sets a breakpoint at the current position.
Execute Runs the executable of the project. The arguments to the program (if
any) are the ones specified in the debugger configuration tab.
Compile Compiles the current file.

• Debug. This menu option appears when the debugger is active, in the place of the
compiler menu, assuming you do not compile when the program is being debugged.

Execute Continues the execution of the program. Breakpoints remain active.


Step in If the current line contains a function call, the debugger will step into
that function, provided there is debug information for it. If there is no
function call, the program is stopped at the next line.
Same level Continues the execution of the program until it reaches the next source
line.
Step out Continues the execution of the program until it leaves the current
function. Breakpoints remain active and can stop the execution of the
program before the end of the function is reached.
Run to cursor Continues the execution of the program until it reaches the line
pointed to by the text cursor. If that line is never reached this is
equivalent to Execute.
Stop Stops program execution and returns to the editor.

Lcc-win32 User’s Manual 73


debugging
CPU Shows the machine register window.
Stack Shows the execution stack.
Memory Allows you to inspect memory locations.
Machine Shows the disassembly window.
instructions
Watchs Shows the watch window.
Evaluate Shows the symbol evaluation dialog box.
symbol
Info Shows information about the program current running, its threads, its
windows, etc.
Restart Stops the current process, terminates it, and restarts the debugger,
stopping at the main or WinMain function.
Break Immediately stops the execution of the program wherever it is.
Breakpoint Sets a breakpoint at the current position of the text cursor.
Edit Shows the breakpoint editing dialog box.
breakpoint
Data Allows you to set a breakpoint that will be triggered when the program
breakpoint accesses a certain memory location or variable.

• Utils: Several help programs such as diff, generating a hypertext file from a
program file, information about variables, structures, etc.

Execute Runs a specified program.


Diff Calls up the diff utility to determine the differences between two files
or two directories
Profiler Calls up the profiling utility to determine where your program uses its
time.
Analysis Analyzes the project or a file. The detailed menu options are described
below.
Apply patch Applies a patch file. This option is not currently functioning well. The
patch should be generated with the diff option ‘generate patch’.
Database This will appear if Berkeley DB of Sleepycat Software is installed
wizard
Show #ifdefs Redraws the current file showing inactive lines in gray.
Executable Shows the size of each part of the executable: code, data, etc. The
stats DLLs used are also shown.
Function size Determines all sizes of each function in the executable of the project
stats file, sorts it by size, and displays the result in a normal editor window.

• Analysis. These commands allow you to browse or get other information about a
specific file or about the project as a whole.

Import foreign Allows the user to read a dll import library in the Microsoft format,
library and transform it into a library in the lcc format.

Lcc-win32 User’s Manual 74


Show Shows all the include files in the current open file. The display is in
#includes the output window.
ObjXref Shows a cross-reference of all object files created by the current
project, showing which functions are defined, but not called from
other files, for instance, or a graphical plot of the object files
relationships: which files call which.
Function tree Prompts for a function in the current file and shows which functions
are called by that function.
Generate HLP Generates a help file automatically with the definitions of the
functions in your program.
Strings Allows you to automatically replace the character strings in a source
file by a reference to either a table or a resource.
File metrics Shows the software metrics for the current file.
Function Shows the software metrics for the specified function.
metrics
Write Writes in a specified file the prototypes for the functions in the current
prototypes file.
Browse fn defs Opens a dialog box showing you all defined functions in the files
currently opened.
Show globals Shows the global variables of the current file.
Slice by local Shows the lines that concern a specific identifier, i.e., a program slice.
File relations Shows the relationship between two given files.
Audit Writes a document with all metrics of all loaded functions.

• Versions: Versioning system. Get, put, seeing revisions, maintain CMS files and
in general all versioning options.
• Window: All loaded files are listed here.

Wedit has a status window at the bottom. Here, you can see the output of different things:
GREP, make, the debugger, the locals display, etc. This window can be shown using the
button at the lower left of Wedit, or hidden, using the same button. At the bottom right,
you will find the current function for where the cursor is located, if any, and the current
line and column number.

The list in the output window is a ‘dockable’ window. You can detach it from the main
Wedit window, and so that it becomes an independent floating window that you can place
anywhere in the desktop.

To force this window into its home position, just double-click in the window’s title bar.

How Wedit Displays the Program Text

Lcc-win32 User’s Manual 75


You can toggle the
open files toolbar
on/off with the
corresponding
option in the
Configuration
property sheet. It is
an independent
window that can be
placed anywhere in
the desktop.
Wedit will remember
its last position and
re-open it when
restarting.

C language keywords are displayed in blue, commentaries in light green, text in black.
You can alter these colors as desired using the corresponding option in the Configuration
property sheet. Lines that are bigger than the display window are finished with a white
square. The name of the current function, the line number, and the current column are
displayed at the lower right corner of Wedit’s window. If the file has been modified, an
asterisk will be added after the column number.

There is no horizontal scrollbar. Click near the vertical scrollbar and the screen will
move to the left, click at the opposite side and the screen will move right.16

You can make Wedit show you the braces level by choosing the ‘Level’ option in the
‘Edit’ menu. A column with the level of each line appears at the left. To make the ‘level’
disappear just choose the same option again.17

16 An horizontal scrollbar takes at least one line of text away from the display. No matter how big
your screen is, there will be always a shortage of space. A 'virtual' scrollbar as implemented in Wedit
has the same functionality but takes zero lines of text to show!
17 This is useful to see where your are missing a brace.

Lcc-win32 User’s Manual 76


You can save disk space by using the ‘Spaces to tabs’ option in the ‘Edit’ menu. This
function will replace all leading spaces with tabs, so your file uses less disk space and
loads faster.

If you have made changes and want to discard them, the fastest thing to do is to choose
the ‘Reload’ option in the ‘File’ menu. This will reload the file from disk, disregarding
all changes.

If you want to see what changes you have made to a file, use the ‘Show changes’ option
in the ‘Edit’ menu.18

To display two files side by side, use the ‘Disposition’ option in the ‘Window’ menu.
You can position the files side by side vertically or horizontally.

The button at the lower left corner is used to show/hide the output window. This window
can be detached and moved freely around by clicking in the bands of free space between
the output window and the borders. In addition, its height can be arranged by moving the
slider in the middle. To do this, press and hold your mouse button for more than one-half
second when the mouse is over the slider. The slider window will then be ready for
resizing. It will show a horizontal bar that can be used to adjust the height of the output
window.

Pressing the right mouse button above the area of the output window will bring up a
contextual menu. With this, you can save the actual contents in the output window to a
file.

18 This option just saves the current file in a temporary file, and invokes the 'diff' utility.

Lcc-win32 User’s Manual 77


Projects
A project is a set of source files that contains the code for an executable or a library. This
set of files can include header files and many other associated documents such as
documentation, etc. For Wedit, however, you should only indicate the C source files, RC
resource files (or their binary equivalent, the .res files) and no other files.
Creating a Project
This option allows you to define the set of files that will be loaded together and
considered as a work unit. For this you have to define:
• The name of the project
• The directory where the source files will be found

The object files and the executable are placed by default in a directory named 'lcc' under
the sources directory. For instance. if you use the directory c:\myproject for the sources,
the output of the compiler will be placed in a directory named 'c:\myproject\lcc'. This
method is not obligatory in this version, but it was in earlier versions of Wedit. Still, it is
better (as always) to use the defaults.19

Avoid placing two completely unrelated projects in the same directory. The makefiles
would be erased and several object files could be lost. For example, if you have a file
called main.c in two projects, the object files of both projects would be the same and the
linker would be confused.
Four types of projects are supported:
1. Windows executable. This means that your program will start at the ‘WinMain’
function, that it will not use the standard input or standard output functions and that it
will not use the ‘console’ window.20
2. Console application. This means that your program uses ‘printf’ and assumes, for
example, that stdin and stdout are initialized and it will appear in a text mode window.21
3.Static library. This means that you want to create a library containing a set of object
files. This library is linked statically, i.e., each executable will contain its own copy of the
routines in the library.
4.Dynamic link library. This means that you will create an executable that is
dynamically attached to another process when the other executable starts.

19The current directory can be determined easily: just go to the configuration menu option. In the
‘General’ tab, you will find what the current directory is.
20Of course windows program can open an own console if they wish to. This refers to what is present
by default at the program startup.
21 Again, console programs can use any window API. The system opens a console for them by default
at the program startup, that’s all.

Lcc-win32 User’s Manual 78


Creating Several Projects under the Same Directory
From the same source set, you can create different projects that use some of the files in
the sources directory. For instance under the project \myprojects\accounting,
you could create several projects that use some of the same sources under that directory
for setting up different executables, a DLL, a library, etc. You can do this if you change
the item ‘Project directory’ in the definition of the project. Since the object files are
stored in different places, there is no risk of mixing them up.

Defining the Files to be used by the Project


When you accept by pressing the 'Create' button, the system will ask you if you want to
use the wizard to generate the code for the skeleton of a new application. If you answer
yes, the code generation wizard starts. If you answer no, the following dialog box
appears:

Lcc-win32 User’s Manual 79


You reach this dialog box
either by choosing ‘Create’
in the project options, or by
choosing ‘Add/Delete files’.
This is the standard dialog
box for project file
maintenance.
To add a file, choose a file
from the list box at the
upper left or type its name
in the corresponding entry
field, then click on the ‘Add’
button.
To remove a file, select it
first in the list box at the
bottom, then click on the
‘Remove’ button.

Here you should enter the names of all files that will create this project. You can enter
them quickly if you click on the ‘Add all’ button.

If your project uses special libraries, add them to the project files here. For instance, if
you want to use the Windows sockets primitives for network programming add
ws2_32.lib. You can enter the library without a path. If no library is found in the current
directory with the name you typed, Wedit will search in the system \lcc\lib directory, and
determine the path for you.

If you are building a Windows executable, you should add your resources, either by
adding a .rc file or a binary .res file. Use the combination box with ‘List files of type’
header to choose the different files that you want to add to the project.
When you have chosen all the files, click the ‘Validate’ button and the following dialog
box will appear.

Lcc-win32 User’s Manual 80


You can reach
this dialog box
either when
you create a
new project or
by using the
‘Configuration’
option from the
‘Project-
Configuration’
menu bar.

This dialog box lets you change/add/modify the settings for the compiler, choose the
level of debugging support, etc. This will be explained in full in the corresponding
chapter. This is the same dialog box that you reach from the ‘Configuration’ tab in the
‘Options’ main menu. It is just displayed differently.

This is the first of a series of three dialog boxes that the system presents to you in the
event that you want to modify some of the settings at the start of a project. Choosing the
‘Next’ button allows you to continue.

This is a good place for adding the #defines that your project may need or a special
library that is not included in the default libraries. By default, the compiler will start the
project with a debug setting (debug information turned on, optimizations off), but you
can also change this here.

The next two dialog boxes (shown later in the ‘Compiler’ chapter) concern the linker and
the debugger settings. Once finished with the settings, Wedit will generate a Makefile for
your application using the available information.

The project is then ready. You can compile and execute your application. You should
wait, however, until Wedit finishes generating the Makefile for your application. This

Lcc-win32 User’s Manual 81


can take a few seconds, since Wedit calls up the compiler to determine which files are
used for each of the files you added to the project.22

The structure of the Makefile that is generated is described in the technical


documentation.

Opening an Existing Project

This option allows you to change the current project. All open files will be closed and the
current project will be saved. The windows with the files of the new project will be
opened as you left them the last time you worked in them.

To open an existing project, click in a project and Wedit will open it. When Wedit opens
a project, it will hide the main window to accelerate the file loading time without any
unnecessary repainting. You may be concerned that Wedit has crashed/disappeared if it
takes a long time to open. This is not the case.

You can open several projects by checking the button at the bottom of the dialog box. If
that button is checked, Wedit will open a new window with the new project instead of
closing the current project and opening a new one.

Opening a project file

When you have a project file and you want to add the project to the list of your projects
you can use the « File Æ open » menu option to open the project file and automatically
read-in the project description.

22 It could be argued that calling the compiler for this is an overkill, and just scanning for #include
statements would suffice. The problem is that #ifdef ... #endif statements, that need to be processed in
order to know which files are actually used by a source module.

Lcc-win32 User’s Manual 82


Configuring Wedit

Here you can customize several options, such as the what an editor will do at a new line
(indentation or not), which font to use, whether or not a backup copy should be made, the
language definition, etc.

This tab allows you to change:


1. Whether the editor will make a backup of the old version when saving a file. This
backup file contains the text of the file as it was before saving and has the same name
as the saved file, with a different extension (xxx).
2. Whether the editor shows the floating toolbar. This toolbar will show the names of all
loaded files so that you can quickly change from one file to the next. This is useful
when you have a large number of files loaded.
3. Whether the editor saves the changes to its configuration when quitting. This can be
turned off if you have modified parameters you do not want to keep for future
sessions.
4. Whether the editor will indent automatically when you press the carriage return.
5. Whether the editor will check for syntax errors like mismatched parentheses or
brackets when saving a file.
6. Whether the size of the fonts in the output window should be small or normal.

Lcc-win32 User’s Manual 83


7. Whether the editor will save all modified files before starting a build.
8. Vertical scroll options. You can use three modes of downward/upward scrolling when
you use the up/down arrow in your keyboard. You can have the normal scroll, i.e., one
line at a time, or ‘smooth’ scrolling, where Wedit moves scrolls a smaller fraction of a
line each time, and ‘very smooth’, where Wedit scrolls through the text slowly.
9. The tab size: You enter a number between 1 and 8 here.
10.Auto save. If enabled, the editor will save the modified files regularly every 3
minutes. The saved files are in \lcc\autosave.

The current directory. Use


the edit field at the bottom
of the tab to change it.

Change the location where Wedit will look for the


compiler if you moved it to another location or you
want to use another version of the compiler; a
version that you compiled yourself for instance.
Exporting/Importing Projects

Each project is stored in the registry under the key:

HKEY_CURRENT_USER\Software\lcc\Wedit\<project name>

You can ask Wedit to write all the values of all the keys of a given project with the
‘Export’ option in the ‘Project’ menu. The values will be written into a file called
<project name>.prj, in the project’s sources directory. This file will be used by the
corresponding ‘Import project’ option to read all the values into the registry.

If you are moving a project from one place to another on your disk or to a different
machine in another context, you can edit the paths in this file so that they correspond to
the configuration you changed. For instance, if you move a project from drive
D:\projects\work to drive K:\shared\lcc, you should edit the paths in the generated text
file to reflect this new configuration.
The keys used by Wedit are:

Key name Meaning


PrjFiles Number of files that contribute to the project, regardless of whether
they are open in the editor or not.
File1 … FileN The names of the project files. If they do NOT have any path
information, the value of the key “SourcesDir” is implicitly assumed.
UserCount Number of people working in this project.
User1 … Names of each user.
UserN
CMS directory Directory where the versioning system stores its data.

Lcc-win32 User’s Manual 84


Put options Versioning system data.
GetOptions Versioning system data.
FileOptions Versioning system data.
LockOptions Versioning system data.
UserOptions Versioning system data.
ProjectFlags Versioning system data.
Frame Coordinates of the main window.
StatusBar Coordinates of the status bar.
Name Project name.
CurrentFile Last file open in this project.
OpenFiles Number of open files.
OpenFile1… Paths of all the open files, followed by the coordinates of each window
OpenFileN in pixels.
ProjectPath The working directory last time the project was closed.
SourcesDir Directory in which the sources are saved.
Defines The #defines to be added to the compiler command line with –Dxxx.
Includes The additional include paths for this project to be added to the
compiler’s command line with –Ixxx.
Libraries The additional libraries to be added to the linker’s command line.
LinkerArgs Additional arguments to be passed to the linker.
MakeName Path of the Make utility. Usually \lcc\bin\make.exe.
MakeArgs Arguments to be passed to the Make utility. Usually empty.
MakeDir Directory where the object files are stored, together with the Makefile
that was generated.
Exe Name of the resulting executable for this project.
DebuggerArgu Arguments to be passed to the program when started. This is used by
ments the ‘Execute’ command and by the debugger.
DbgExeName Executable to be started by the debugger. This is different from the
executable name only in the case of a DLL.
DbgDir Directory where the debugger should start the program.
CompilerFlags Flags describing the compilation options.
FortranFlags Fortran compiler flags.
EiffelFlags Eiffel compiler flags.
NumberOfBre How many breakpoints are defined in this project.
akpoints
Breakpoint1 Breakpoint description.

BreakpointN

Lcc-win32 User’s Manual 85


The project description files are just text files with the .prj extension, which are saved in
the project’s source directory when the project is exported. Wedit will translate some of
the paths stored here to be relative to the project directory when importing, and will
ignore some keys, for example, MakeName, if the contents are different from the
configuration of the machine retrieving the project. For instance, if you export a project
in a machine that has lcc installed in c:\lcc to a machine that has lcc in
k:\shared\compilers\lcc, the Make utility that will be called up is k:\shared … and not the
one in the exported project.
Complex Projects
There are some situations when you need to process a file with another tool, not the
compiler, to obtain a C source file. For instance, the compiler sources themselves require
the ‘lburg. exe’ utility, which will build a C file from a machine description file. This
machine description file is stored in win32.md.
To describe this project to the IDE, add win32.md to the project files. Wedit will notice
that it cannot determine how this file will be processed, since it does not end with the
standard extensions .c, .asm, .obj. It will open up a dialog box asking for more
information. In that dialog box, enter the command line that should be executed when this
file changes. In this case, enter :
lburg win32.md win32.c
You also need to specify the output of this command. The output in this case is a file
called « win32.c », which you add to the project files.
In a much simpler way, you can specify .asm files that will be processed by the compiler,
assuming lcc assembler syntax. If you want your assembler files processed by another
assembler, such as NASM, right click on the open file and add a ‘file processor’ for that
specific file. If, for example, you have your assembler functions in a file called
asmcalls.asm, you open asmcalls.asm, add it to the project, then right click somewhere in
the text of that file. Then add « nasm.exe » as a file processor or \utilities\bin\nasm.exe «
if the tool is not in the path.

Lcc-win32 User’s Manual 86


The Workspace Options

These options allow you to modify the fonts and the colors used by the editor.

You can reach this tab


from the ‘Configuration’
option of the menu, and
then ‘Workspace’.

• Colors: To change the colors, first select the type


of text you want: normal text, commentaries or
keywords, then press the ‘Change colors’ buttons.
You can choose a color and Wedit will use it to the
type of text you selected.
• If you get lost and would like to return to the
default colors, you should use the ‘Reset colors’
button.
• Fonts: Press this button and choose a font and font
size. Wedit is capable of displaying proportional
fonts, but in general, programs do not look good
when displayed in these font types. Use non-
proportional fonts such as Courier.

Lcc-win32 User’s Manual 87


From the ‘Fonts’ button, you can change the font and the size of the font used by Wedit.
Proportional fonts are not recommended. They are supported, but not well tested because
programs do not look good with these fonts.
Defining Macros

The purpose of this tab is to allow you to define simple macros using the keys Ctrl+’A-
Z’, which will insert the desired text at the current position.
You must supply Wedit with the following information:
1. The letter (a-z) that will be used for the macros. This is entered in the small square at
the top.
2. The replacement text you want introduced at the current position when this macro is
used.
3. When you have entered the information in both fields, press the ‘Add’ button to enter
the new macro into the list of defined macros.
For example, if you want the macro Ctrl+i to represent
i = MyCurrentStructureWithLongName[MyCurrentIndex]
you would enter ‘i’ in the box, and the contents in the edit field below, then press the add
button. This creates the macro.

Lcc-win32 User’s Manual 88


Finding or Browsing Information with Wedit.

Wedit constructs implicit links between symbols in your source files as you edit them. It
records where functions are defined, where structures are used, and other 'important
places'. It can show you the definition of symbols by pressing F8 .
Information can be displayed in several forms, according to their type: variables,
structures, functions, globals, locals, etc.
Press and hold down the right mouse button to recall the definition of any symbol under
the mouse pointer. A contextual menu appears, showing you the different options
available. The different options are:
• Definition. Wedit will show you where this symbol is defined.
• Usage. Wedit will show you where this symbol is used in the current file. Comments
and character strings are ignored.
• Documentation. Wedit will call up the Windows help with the given symbol. You
should use this with symbols that are documented in the windows API.

If you click with the right mouse button where no symbols are defined, Wedit will show
you the following options:
• Globals. This will show all global variables in the given file.
• Functions. This will display the list of all functions defined in the current file.

In addition to these options, the following options are always available, regardless of
where you clicked:
• Metrics. This will show you the software metric measurements for either a symbol or
the whole file.
• Edit description. This will prompt you with the standard function description dialog
box.
• Properties. This will show you the exact path of the current file.

If you right click on include statement, Wedit will automatically open the included file. If
you right click on an ifdef, a new item will appear prompting you to bring the cursor to
the matching endif. The same occurs if you right click on an opening or closing brace.

If you right click on a function definition, Wedit will prompt you to show the local
variables of the function. This allows you to see slices of the function’s code by variable.

The Workspace view

This button allows you to see the contents of a project.

If you click on the name of the function with the right mouse button, a menu appears in
which you can to see some information about that function. If you double-click on a
function name, the cursor will be positioned at the beginning of that function's definition.

Lcc-win32 User’s Manual 89


The ‘Name Completion’ Feature
When you type the start of an identifier and press the Escape key, Wedit will try to
find the closest match to the incomplete identifier. If only one match is found, it will be
inserted without further questions. If multiple matches are found, you will be presented
with a contextual menu with those identifiers or with a dialog box if the number of
identifiers found is too great to be presented in a menu.
If you press Escape after having written an identifier followed by a point or a
sequence of ‘->’ characters, Wedit will try to find the fields of the structure you are
writing.
Wedit tracks the include files to search for identifiers. Comments will be ignored, but
conditional definitions will not be executed because for this, the preprocessor would have
to run.
Information About your Symbols (Variables, Functions, etc.)
Finding the definition of a structure
The difference between Wedit and other editors is that it can show you the information
you need more quickly than simply using GREP. To do this, press F8. This will instruct
Wedit to search for the definition of the symbol that is currently under the cursor.
If the symbol corresponds to a function whose definition is in a currently loaded file, the
cursor will be moved to that file and positioned at the beginning of the function
definition.
If the symbol is a global or a local variable of the current function, its definition will be
displayed in a new small window. If the symbol or variable is a structure, its definition
will be included in the new window.
If the symbol corresponds to a typedef, only its definition will be shown.
Following is a sample display after F8 is pressed while the cursor is below the word rule:

The ‘Options’ menu allows you to open the file from the definition and puts the cursor at
the beginning of the definition. You can also print the contents of the structure.

Lcc-win32 User’s Manual 90


Finding the Usage of a Symbol
Press the accelerator keys, Ctrl+F8, to go to this option. It will use the symbol under the
cursor to show all lines in all loaded files where the given symbol is used. This is similar
to the GREP utility, but it ignores commentaries and character strings.
Finding the Definition of a Function
To us this option, place the cursor on the name of the function and press F8. This will
take you to the function definition if that function is loaded into the editor. As with other
options like this, it is very useful to load all source files of a project in the editor.

The ‘Files’ combo box shows you which files use the symbol, the ‘Functions’ combo box
shows you which functions use it. You can change the context displayed by clicking in a
line from the main list box.
Searching for a Function
This option is complementary to the preceding one. It is useful when you are uncertain of
the function name you are searching. To search using regular expressions, select the
"Function" option from the "Search" menu.
The following dialog box appears:

Lcc-win32 User’s Manual 91


You can reach this
dialog box by
using the ‘Search
a function’ option
from the ‘Search’
menu bar.

The list of all functions defined in all loaded files appears at the left, sorted by name. If
you double-click on a function name, the dialog box will close and the cursor will be
placed where the function is defined. The prototype of the selected function is shown at
the lower right.
If you double-click on the list of files in the center-right, Wedit will open a new list with
all of the functions defined in that file.
You can indicate a filter in the entry field at the center. This filter can be a regular
expression. After the filter is applied, if any functions are found, they will be shown
within the list of selected functions. For instance, to find all functions that begin with a
capital 'C', the regular expression will be "^C.+"
The ‘Include *.c’ button at the upper right instructs the search engine to look for all files
in the current directory (that end with .c) and not only in the loaded files.

Displaying the List of Functions in the Current File

This dialog box does not use the information in the file. If you have just written a new
function and you have not yet saved the file, this dialog box will also accurately show
you the new function.

Lcc-win32 User’s Manual 92


You can reach this dialog box
either by using the
F12
function key, or by selecting the
‘Function list’ option in the ‘Search’
menu bar.

To go to the function definition, select the desired line from the list.
The small entry field at the right allows you to enter the function name if you know it.
You can sort the functions by occurrence in the input file or by name.
Since the #ifdef / #endif are not taken into account, the same function can appear several
times. In addition to this problem, the assumption here is that there are no fatal syntax
errors in the text of the file being scanned. Most syntax errors will not affect this option,
except unbalanced brackets, unfinished commentaries, or similar syntax errors.

Lcc-win32 User’s Manual 93


Editing Text
Selecting and Moving Text
To select a piece of text, use the Shift key with the arrow keys. The options are listed in
the main menu. For instance, to select a line, press Shift+down arrow.
Once selected, the text can be copied to the clipboard with Ctrl+Ins. The clipboard is
exported immediately when the selection is copied and is available via the clipboard to
other applications in the system.
To move a whole function, use the Copy function option from the Edit menu. This will
copy the selected function to the clipboard. You can then delete it and place it somewhere
else.
To insert text from the clipboard, use the Shift+Ins keys. To insert a file at the cursor's
position, use the Insert file option from the File menu.
Searching Text
This option allows you to search for a text string or for a regular expression in the current
file or in all opened files.

The different options indicate:


• Scope: Can be the current window or all opened windows.
• Type of Match: The character string can be used literally or as a regular
expression.
• Symbols only: The text is a symbol and only matches that are delimited by non-
symbol characters will be reported.23
• Match case: Whether case is important when searching.
• Direction: You can search forward (towards the end of the file) or backward
(towards the beginning of the file) or make the search wrap at the end of the file and start
at the beginning.

23What a symbol is depends on the programming language. To avoid overloading the language definition
with heavy syntax, only letters, digits, and the underscore are used as symbols. This will fit most languages
except Common Lisp, where you can define symbols containing almost any combination of characters.

Lcc-win32 User’s Manual 94


Replacing Text
This dialog box can also be used to specify the replacement of a variable or any character
string. The search can be global (i.e., all loaded files) or only within the current file.
You can reach this dialog box by
using the ‘Replace’ option in the
‘Search’ menu bar
Alt+s, then r.

The user interface is simple: Type in the text and the replacement text, then press the
Replace button. The search expression can be a regular expression. If this is the case, do
not forget to select the corresponding option in the Match group box.
Possible options are:
• Use of a confirmation dialog box or if Wedit should replace all matches globally
without confirmation of each occurrence.

• Identifier search: Implies that to be a valid match, non-identifier characters


should enclose the text. This allows you to replace all occurrences of the variable 'j' in 'z'
without replacing all j's in z's!
• The Scope field: Specifies that the files will be included in the search. Either the
current file or all loaded files can be used by the search.
• Case: Specifies if the search should be case sensitive.
• Direction: You can search towards the end of the file, towards the beginning of
the file. If you choose a global search, it searches forward only.

Goto
The Goto option from the search menu leads to the following dialog box:

Lcc-win32 User’s Manual 95


You can reach this dialog box
by using the ‘Goto’ option in
the ‘Search’ menu bar.

This option allows you to move the cursor within the current file. Top and End place the
cursor at the beginning or at the end of the file, respectively. Line is used to move the
cursor to a specific line. You can skip the subsequent dialog box if you enter a line
number in the corresponding entry field at the lower right corner of the ‘Goto’ dialog
box.
You can reach this dialog box by selecting the
‘Goto’ option in the ‘Search’ menu bar. A dialog
box will show you several options, you choose
‘Goto line’. Or you can press the keys Ctrl+F12
and you arrive directly.
Ctrl+F12

The editor remembers the lines entered during an editing session.


The Function option allows you to place the cursor at the beginning of a function
definition. The editor will show you a list of the functions defined in the current file.

Lcc-win32 User’s Manual 96


Matching Parentheses, Brackets, etc.
This function allows you to match braces, brackets and parentheses or a #ifdef / #endif
construct. To use it, place the cursor just before the letter in question and press F11. The
cursor will be moved to the corresponding element. If you press F11 again, the cursor
will return to the original position. This works in either direction. This functionality will
be called each time you save a file, to check that parentheses and brackets match.
Bookmarks
You can set bookmarks at any line within a file to establish a point where you can return
to. To set a bookmark, press F7 on the desired line. To return to a bookmark, press
Ctrl+F7. The editor will list the bookmarks established thus far.

You can reach this


dialog box by
pressing the
CTRL+F7 keys or
by using the ‘Goto’
dialog box in the
‘Search’ menu bar.

Choose a line and the cursor will be placed there.


The same dialog box is used for deleting a bookmark. Select a line and the bookmark will
be deleted.
You can scroll through the bookmarks using the Ctrl+F7 keys.
Redefining what is a keyword
You can add or delete keywords from the default keyword list. It can be useful to see
your own types in the keyword’s colors. To do this, choose the Keywords tab in the
configuration property sheet.

Lcc-win32 User’s Manual 97


You can reach this
dialog box by using
the ‘Configuration’
option in the
‘Project-
Configuration’ menu
bar.

You can add or delete keywords. To add a keyword, type it in the entry field and press
the 'Add' button. To erase a keyword, select it from the list first, and then press the
'Delete' button.

Lcc-win32 User’s Manual 98


Wedit’s Debugger

The debugger allows you to follow the program execution and to examine values at
runtime. There are two ways to start it.
•Press the F5 function key. If you have built a project, the executable will be started
automatically, or
•Use the File->Open menu option, and enter the name of an executable that you want to
debug. From the command line, you can specify to Wedit the name of the program to
debug. If the file given has a .exe extension, Wedit will assume you want to debug it and
will start.
If it is not a .exe file, the following dialog box appears:

You reach this dialog box when you open an executable using the ‘File’ and then ‘Open’ menu option.

You can enter optional command line parameters here or cancel the whole operation.
The executable started should contain the debug information. If it does not, you should
recompile it with the debug information turned on. This is specified in two place: The
compiler tab of the configuration property sheet and in the linker tab. The first one
specifies that the object files should be generated with debug information; the second
specifies to the linker that the debug information should be included in the executable.
If functioning properly, the program to be debugged is started and execution stops at the
‘main’ or WinMain function.

Wedit is a multi-language debugger, however, it supports C best. For Eiffel language


support, choose the appropriate button in the dialog box.

Lcc-win32 User’s Manual 99


You can use the command line to start debugging a program with Wedit. If you want to
debug the program « foo.exe », with the startup arguments « arg1 » and « arg2 », the
command line would be:

d:\lcc\projects> Wedit foo.exe arg1 arg2

Please note that you must write the extension: foo.exe. Writing only « foo » will not
work.
Configuring the Debugger

You can configure the debugger with the following tab in the ‘Configuration’ wizard.

You should verify that the start directory is correct.

When building a DLL project, enter the name of the executable that will call up the DLL.
This executable should have debug information and be linked with the DLL to debug
statically. If the executable runs a LoadLibrary, instead of being linked with the DLL
statically, Wedit’s debugger will not be able to restore the breakpoints you set, since the
debugger cannot know in advance which DLLs are going to be loaded at which address.

Lcc-win32 User’s Manual 100


Using the Debugger: The Basics

There are several options for controlling the program execution of the program you
would like to debug:
• Same level (F4). This means that the debugger will run the program until it reaches
the next source line. If the current line contains a function call, it will be skipped. You
remain on the same level. If you reach the end of the function, the line where the function
call was implemented will be displayed. This is not possible in all cases — specifically if
your function is a Windows callback, it was called up by the operating system. You
cannot step through system code, so the debugger will stop when control reaches one of
the source lines of your program again.
• Step in (F8). This means that the debugger will run the program until it reaches the
next source line. If there is a function call in the current line, the debugger will try to see
if it has debug information for the function in question. If yes, execution will stop at the
first line of that function. If that function does not have any debug information, the
debugger will arrange to skip that call. In cases where the function calls one of the
procedures of your program indirectly, the debugger will stop when control reaches the
next source line of your program. A SendMessage call is one example of this. This
function will call the callback procedure for the window that can be in your program. In
this case, the debugger will stop at the beginning of the callback procedure.
• Step out (F9). This means that the debugger will run the program until it exits the
current function and place a stop at the calling function. The same rules apply as in the
return from a procedure explained in Same level above.
• Run to cursor (F7). The debugger will put a temporary stop at the indicated line and
pass control to the program being debugged. If control reaches the indicated line, the
debugger will stop. If not, the program will continue normal execution. Be careful to
ensure that control MUST reach the line you indicate with F7.
• Set a breakpoint (F2). This will set a breakpoint at the indicated line.
• Unset a breakpoint (F2). If the line that is under the cursor contained a breakpoint,
that breakpoint will be deleted.
• Break. This makes the debugger stops the program under debug, no matter where it is.
• Stop debugging. This stops the execution of the program under debug, and closes the
debugger.
• Set next statement. This can be reached through the right mouse button menu. Using
this feature, you can skip several lines of code in the current function, or return
backwards to retrace the execution. Note that you can make the program fail if you set
the next statement where it would use variables that were initialized in a piece of code
that you just skipped. The debugger cannot undo what the program has done, when you
reset the current line to some line before the current one. If the program opened, closed,
or deleted files, for instance, the debugger does not undo those actions.
• Set next instruction. When the ‘Machine instructions’ window is open, you can move
the program counter explicitly to a new location by pressing the right mouse button
anywhere on that window. A contextual menu will appear, prompting you to change the
program counter to the selected line in the ‘Machine instructions’ window. To do this,
choose this menu item and the program counter will be set to that location.

Lcc-win32 User’s Manual 101


Debugger Description
menu
Execute Continues the execution of the program.
Step in If the line contains a function call, the debugger steps into the
called function if debug information for that function is
available.
Same level Stops ignoring function calls.
Step out Stops when the current function is finished.
Run to cursor Stops when execution arrives at the line where the text cursor
is placed. If this line is never reached, this is equivalent to
Execute.
Stop debugging Stops the debugger and returns to the editor.
CPU Activates the register display.
Stack Shows the call stack.
Memory Allows you to inspect memory contents.
Machine Activates the assembly display.
instructions
Watchs Activates the watch window.
Evaluate symbol Lets you evaluate a symbol or a simple expression.
Info Shows several information displays about the program being
debugged.
Restart Stops the program being debugged, and restarts it from the
beginning.
Break Interrupts the execution of the program immediately.
Breakpoint Sets a breakpoint at the line where the text cursor is.
Edit breakpoints Shows the breakpoints dialog box.
Data Shows the data breakpoints dialog box.
breakpoints

Switching between the Different Displays


The display at the bottom of Wedit changes when you start the debugger. The see
following buttons will appear:
• auto. Wedit tries to determine the variables that the program is working with, and
it will display them automatically in this window.
• locals. Wedit displays the local variables of the current function.

Lcc-win32 User’s Manual 102


• stack. The call-stack is displayed.
• events. Events are reported, such as DLL loading, etc.
• search. As in the editor, this is the search window.

Setting/Unsetting Breakpoints
To set/unset a breakpoint, press F2. This will toggle a breakpoint at the line where the
cursor is located. If you are in the debugger, a breakpoint symbol is shown at the left
side of the affected line.
You can also edit the current breakpoint list using the ‘Edit breakpoints’ dialog box,
which can be called up from the debugger menu.
In this dialog box, there is a list of all functions defined in the running program at the left
side. To set a breakpoint in any of these functions, double-click on the large list box at
the left side of the dialog box. Note that this enables you to set a breakpoint at any
function, even those library functions where there is no source file associated with them.
For instance, to set a breakpoint in the library function ‘printf’, double-click on its name.
This is the only way to specify a breakpoint in these functions. F2 will not work here
because there is no source file associated with that function.
You can specify a source file and a line in the “New breakpoint” edit field. This is
enabled only when the debugger is active.
To specify a breakpoint that will be skipped <n> times before it stops the program under
debug, double-click on the breakpoint you want to modify. Then enter the number of
times to skip in the dialog box that pops up. This feature is active only when the
debugger is running, and the settings will not be saved between debugging sessions.

Displaying Information about the Program


This can be reached using the ‘Info’ menu item of the debugger menu. It appears in the
form of a tab control, displaying information about the executable, its size, etc., as well as
the threads that the program has created, the loaded DLLs, and the windows that belong
to the executable that is running. This can be useful for pinpointing where a problem
occurs.
Note that in the threads display, you can choose among different running threads and
start/stop it by double-clicking in the display line.

Lcc-win32 User’s Manual 103


CPU
This menu option in the debugger menu will open/close the machine state property sheet.
This allows you to see the contents of the machine registers. You cannot currently modify
the register contents. This option should be available in the future.

The first set of registers shown is the integer register set:

• Six integer registers


(eax, ebx ecx, edx, esi
and edi)
• Flags. Since the
debugger sets the
machine in single
stepping, that flag is
always on.
• Three system registers:
the program counter
(eip), the stack pointer
esp, and the frame
pointer ebp.
• Display of the stack
frame, at right.
You can change the base
for displaying numbers
with the radio buttons

Lcc-win32 User’s Manual 104


‘Hex’ or ‘Decimal’.

The second set of machine registers are the FPU registers and their associated flags.

The 8 FPU registers are


shown at the left.
At the upper right, the tag
word is displayed. The top
of stack (TOS) is shown in
a read only entry field.
Status flags of the FPU
(C0-C3) and the other
flags are shown in the two
columns of checkboxes
below.

The third set of registers is the mmx registers. Use this set only if you use the MMX
intrinsics and your machine is an MMX machine.

Using the ‘Units’ button at


the right, you can change
the display from 8 bits, to
16 or 32 bits since each
mmx register can have 8
characters as 8 bits
quantities, or 4 16-bits
words, or two 32-bits
double words.
Using the ‘Base’ radio
buttons, you can display
the data either in binary,
decimal or hexadecimal
form.

Lcc-win32 User’s Manual 105


Machine Instructions

This menu option opens or closes the ‘Code’ display. This will display the assembly codes for
the function currently being executed.
If you click in this window with the right mouse button, a contextual menu will appear that
allows you to mix C code with assembly instructions (the ‘Source annotation’ menu option) or
display the code bytes, i.e., the exact instructions without decoding by the disassembler. When
this window is open, you can reset the program counter to any desired location within this
window. Choose the ‘Set next instruction’ menu item from the contextual menu. This menu
appears when you click anywhere in this window with the right mouse button.

The name of the currently


active function is shown in the
title, its corresponding file, and
the machine address where
execution has stopped.
Next there is a three-column
display with the machine codes
to the left, followed by the
assembler mnemonics in lcc
assembler syntax.
The C source lines are mixed
with the assembly display. The
line numbers are in square
brackets to the left.

If you are interested in the exact code bytes that are stored and not just their mnemonics, you
can view the hexadecimal numbers shown at the left of the assembler mnemonics.
When the ‘Code’ window is open, the debugger will single step through each assembler
instruction instead of single stepping through each line of the source program.

The Stack Display


The stack window displays the stack of procedures that are active at a given execution point.
It can be activated at any time by clicking in the stack button at the bottom of the editor.

Lcc-win32 User’s Manual 106


The ‘_MainWndProc@16’ is
the active procedure. Note that
symbols are displayed with
their decorations as they appear
in the executable.
The name of the function
appears, followed by the
source file and line number.
The next lines show the
argument stack for the
procedure with the type of each
argument and their values.
When the information is not
available (i.e., a system DLL),
only the machine address
where the call up was
implemented is shown.

Note that ‘MainWndProc’ is a callback procedure. You can determine this because
USER32.dll and ntdll.dl appear as active in the stack. Note that the user function
‘InitializeApp’ is also active. This is the normal case for processing a WM_CREATE
message. When you call up CreateWindow, this function sends a WM_CREATE message to
the window procedure before returning to the caller.
You can view the code of any active stack procedure by clicking on the corresponding line.
Note that you should click on a function name and not in the parameters. When you click on a
function name, the debugger will bring that part of the source code into view.
The Locals Display

This window will show you the local variables of the function currently being executed.

The symbols marked with a ‘+’ are structures, unions or tables, i.e., aggregates.

Lcc-win32 User’s Manual 107


The Events Display

The ‘Events’ window shows you the threads that the program has started, the DLLs that
were loaded/unloaded on the program’s behalf, etc.
The debugger will show the output of the ‘OutputDebugString’ Win32 function in this
window.

If your message uses the Win32 API function ‘OutputDebugString’, all debug strings will
be displayed in this window. Note that this does not trigger a breakpoint.

Here, the exact sequence of actions when a trap occurs will be displayed, if there is a
problem with the debugger.
A DLL is loaded. The
debugger displays its name,
the file handle for the
executable, the base of the
DLL code, the offset to the
debug information (if any),
the pointer to the DLL
name, and whether or not it
is a Unicode DLL.
The OutputDebugString
event is received. The
debugger is currently unable
to understand the
undocumented formats that
are used by Microsoft’s
DLLs. Further investigation
of this may produce a more
interesting display here.
Normally a character string
should be at the address
pointed to by
lpDebugStringData, but this
is not the case for system
DLLs.

The Memory Window

The memory window allows you to explore the contents of memory at a specified address
or variable name.

Lcc-win32 User’s Manual 108


A contextual menu opens with the right mouse button that allows you to modify the
display format. You can use bytes, shorts, or longs as units.
If you enter a symbol name, that symbol should be either global or in the active scope.

The Watch Window

This window allows you to open a secondary watch window where the contents of a
variable can be displayed permanently. The debugger will evaluate the contents of the
field at each stop.
A box opens asking you which variable you want to watch. Enter the name of a watch
and press return.
To erase a variable from the watch list, press the ‘delete’ key. To add a variable, press the
‘insert’ key. Remember to first click in the watch window so that it receives the focus. As
of this release, only simple types are supported, i.e., if you have a structure with an
integer field, type struct->field into the watch window input.
The watch window looks like many other windows in the debugger:

Each field of the ‘msg’ structure is displayed.


Each time the debugger stops, it will update this window with the current values. This
allows you to follow the evolution of the values during program execution.

The ‘Auto’ Window

This window tries to display the values that may be of interest from each line of the
source code that is currently being executed.
For instance, for the following source lines:

Lcc-win32 User’s Manual 109


Here
execution is
suspended in
the
‘TranslateMes
sage’ source
line (shown in
yellow).
There is a
breakpoint
three lines
earlier.

At this stop in execution, the variable window will display the following:

• The value of ghwndMain


is shown
• The value of ghAccel is
shown
• The structure tagMsg has
the address 0x16065c.
Aggregate values are not
shown and are only
displayed as {...}
• The function results are
indicated by ‘returns’ and
a symbol followed by a ().

The preceding line and the current lines are scanned for identifiers, and the values of all
such identifiers are displayed. In addition, the return values of all functions called are
shown. This is very simple: Wedit’s debugger scans the current line and the preceding
line, eliminates comments and character strings from them, and scans all identifiers that it
can find. The debugger and the results shown evaluate this list. In addition, each time a
function call is found, its results will be stored and displayed in the ‘Auto’ window.

Lcc-win32 User’s Manual 110


Evaluating an Expression
You can reach this option through the ‘Evaluate symbol’ option of the debugger menu.
This option leads to a dialog box that prompts you for an expression to evaluate and
displays the results in a list box, below the input combo box.
It is simple to use: Type the expression to evaluate in the combo box line and the result is
displayed below. In principle, all symbols in your program should be available for
display. In practice, there could be some problems. See below for further information.

Setting Data Breakpoints


Wedit can stop the program when an address is accessed, either in read or in read/write
mode . To enable these special breakpoints, you should choose the ‘Data breakpoints’
option in the debugger menu.
You have up to four data breakpoints (there are only 4 debug registers in the x86
architecture). Enter an address expression or the name of a variable, the size of the
variable (only 1,2,or 4 are possible), and the access type. Whether the breakpoint should
fire when the variable is accessed (read access) or when the variable is written to
(read/write access).
When the breakpoint fires, Wedit will stop the program and display the closest location
to the breakpoint in the program. Note that data breakpoints fire after the instruction is
executed. If the access is in read/write, Wedit will display the old and the new variable
values.
Calling Up the Debugger if your Program Crashes
If you have set the debug level higher than 2, the compiler will present a dialog box with
the option of calling up the debugger if a program crash occurs. You just press the
‘Cancel’ button, and Wedit will be called up with the context of the crash. You can
browse the variables in the procedure that crashed, and (if possible) you can restart the
program at a different line in the same function.
The debugger configuration tab
You can set several parameter in the debugger configuration tab of Wedit. You can :
• Set the number base (10 or 16) to display integers either in hexadecimal or in
decimal notation.
• Set the name and the arguments to be passed to the program that you will
debug. Note that this command line will be executed when you just execute the
program with Ctrl+F5.
• Set the initial directory where the program will be started.

Debugging Windows Programs

Lcc-win32 User’s Manual 111


It is important when you debug windowed programs that the debugger not interfere with
the window of the program being debugged. Any interference of the debugger with your
program’s window will trigger a message to your program, which could cause procedures
to be called up that will change the execution of the program. For instance, if you try to
debug the procedure that is called up when a WM_PAINT message is received, the fact
that the debugger will pop up and hide a portion of your program’s window, will trigger
the function you want to debug to be called up again. If you have a breakpoint in it, there
is no way to escape an endless cascade of the same message. This can be stopped either
by erasing the breakpoint or by moving the window so that the debugger’s window does
not touch the window of your program.

Lcc-win32 User’s Manual 112


The Profiler

The profiler is a utility that allows you to see where your program is spending its time. It
operates by starting a special debugging session in which the debugger interrupts the
running program approx. 1,000 times per second. When the debugger stops the program,
it checks what the program is currently executing and records each source line/function
that corresponds to the current program counter (EIP).
When the program finishes running, the debugger assembles the information it has
gathered into a report in which each function that was interrupted is shown with the
number of hits it had.
The logic behind this method is that the longer a function executes the higher the
probability that the debugger will interrupt its execution. Since this is a statistical
approach, the longer the program runs, the more accurate the information of the profiler
will be. Short runs can introduce errors because the chance factor is higher. Longer runs
provide a more reliable report.
When measuring a program’s execution, you should run several profile sessions before
using the data.
To start a profiler session, you should compile the program with the debug information
ON of course. Use only the lowest debug level (g2). Other debug levels will introduce a
skew in the data, since they affect the program’s runtime behavior. For instance, if you
set the debug level to g3, at each procedure call, the program will record the name of the
procedure in the stack, making procedure calls more costly, skewing the data seen by the
profiler.
The profiler report will be loaded automatically into the editor. You can save it or rename
it as you would do with any other text file.
During the profiler session, the debugger’s main window will appear. Do not use it
because the profiler session could be stopped or slowed down, rendering the data useless.

Lcc-win32 User’s Manual 113


Configuring the Compiler and the Linker in Wedit

The compiler can be configured using the following tab:

In the first line, under ‘Preprocessor’, enter the symbols you want to define for all
compilation units. Wedit will append a –D to each definition that should be separated by
commas or spaces and pass these options on to the compiler.
For code generation, you can:
• Generate the assembler listing of each source.
• Turn optimizations on or off.
• Generate the browsing information always when compiling. This is not very
productive, since Wedit will generate this information on an ‘as needed’ basis. Setting
this option will slow your compilation, but may speed up later searches.
• Use Pentium Pro instructions or not. Note that if you check this button, the compiler
will generate a program that will not run in a machine that does not have these
instructions, for example, an old 486.

Lcc-win32 User’s Manual 114


• Set the structure alignment space. This is the space that the compiler leaves free
between members of a structure to speed up their access.
The options are self-explanatory for the debug support. Note that the options for runtime
stack trace support will not work with DLLs.
The file for error messages and warnings will be used internally by Wedit. This is
displayed here for informational purposes and can be changed, but it is not
recommended. If you want to save the messages of a compilation, you can copy this file
to another site.
The warning level options are self-explanatory. The ‘Misc’ entry, with the option to
generate the intermediate file is only intended for studying the compiler itself. It will
produce a .lil (Lcc Intermediate Language) file for each compilation unit .

The linker can be configured with the following tab:

You can change the name of the output file, for instance, to place your binaries in
different directory, instead of the default directory.
In the additional libraries tab, enter any libraries that are not included by the linker as a
default.
You can instruct lcclnk to generate a map file with the addresses of all symbols used by
your program by checking the corresponding box. If you are building the executable to

Lcc-win32 User’s Manual 115


be shipped and are concerned about its size, you can instruct the linker to strip all debug
information from the executable.
Some DLLs that are going to be used by language processors other than C do not support
the preceding underscore in the export table. The corresponding option allows you to set
this feature for use, for instance, by Visual Basic. Remember that if you load this type of
library dynamically, use a name without underscores!

For simplicity’s sake, not all the linker options are displayed in this tab. You can read the
lcclnk command options for the command line at the beginning of this document and add
any option you consider useful in the corresponding edit field at the bottom of this tab.

Lcc-win32 User’s Manual 116


Other utilities
The Binary Editor

This sub-system allows you to visualize a file in binary mode. The bytes in the file are
displayed without taking into account any line records.
You reach this utility from the File -> open binary menu option.

The display is organized in three main blocks:


• The offset of the data within the file in the left column
• The 16 bytes that follow that offset displayed according to the settings of the
'Style' button
• Their character representation (if any)

The Menu Options of the Binary Editor


Style
This option allows you to change the representation of the data in the column at the
center of the display.

Lcc-win32 User’s Manual 117


You reach this dialog box by using the ‘Style’ option
in the binary editor ‘File’ menu.
The representation formats available are:
• Characters shown in hex
• Integer 8 bits shown in decimal
• Integer 16 bits, unsigned or signed
• Integer 32 bits, unsigned or signed
• Bit inverted. The bits 0-31 become bits 31-0
• Float simple precision (32 bits)
• Float double precision (64 bits)

You can choose any of the representations above.


Search
This option allows you to search either an integer or an ASCII character string.
You reach this dialog
box by choosing
‘Search’ in the ‘Edit’
menu bar of the binary
editor window.

It is possible to specify the following data types:


• Integers (8, 16, or 32 bits)
• Character strings
• ASCII
To add to the search byte sequence, enter your data in one of the fields and press the ‘Add’
button.
For instance, if you want to search for the binary integer 47234 followed by the ASCII
sequence « foo » you would enter the number 47234 in the 32 bits field, press the ‘Add’
button, and then write « foo » in the ‘ASCII’ entry field followed by ‘Add’ again. In this
way, you can easily specify very complex search sequences.
The sequence of bytes that will be searched for is shown at the top in the read only entry field
‘Bytes to search’.

Lcc-win32 User’s Manual 118


Goto
This option will move the current point to the specified position. You can move the cursor
using the arrow keys or the page up / page down keys. Within the small ’goto’ dialog box,
you can enter the file offset either in decimal or hexadecimal form.
Structures
This option allows you to apply a data structure to the bytes at the current offset. Data
structure means, in this context, a series of field descriptions composed from the
elementary types and possibly a length. The building of that structure is done with a
screen having the following sections:

• A column at the left indicating the offset of each field relative to the beginning of
the structure.
• A 'Type' column that indicates the length and the representation used for this
field.
• The data for this field. Note that only the first few characters are shown.
• You can display the data either in decimal or hexadecimal form.
To add a field to the structure proceed as follows:
1. Choose the 'Add' menu option. This will open the following dialog box.

Lcc-win32 User’s Manual 119


2. Define the base type of the new field by clicking in the available primitive type list on
the left.
3. Define its length if it is different than one.
4. Give it a name if you choose to.
The primitive types that are available are:
• Characters
• Integer 8 bits
• Integer 16 bits, signed or unsigned
• Integer 32 bits, signed or unsigned
• Float simple precision (32 bits)
• Float double precision (64 bits)
• ASCIIZ: Character string finished by a zero
• ASCII Pascal. Character string with a length byte at the beginning.
• Swapped short: Short integer coming from a machine with inverted byte order.
• Swapped long. 32 bit integer coming from another machine.
• Bit inverted. The bits 0-31 become bits 31-0.
To erase a field from the structure definition:
1. Select a field by clicking on the list.
2.Choose the 'Erase' menu option.
The Software Metrics Module
In this context, software metrics means a set of measurements made of the source code of
your program to determine certain metrics or ratios. This is a domain with a long story of
continuous refinement of the definitions and metrics involved that would be impossible
to describe in the context of a software manual. It is this author’s personal opinion,
however, that this field has lacked the raw data from numerous measurements by many
people. With this idea in mind, Wedit tries to provide you with a set of tools to measure
your code and deduce your own conclusions. The emphasis is on providing raw data and
displaying it without any interpretation; the objective being that you interpret the
measurements as you like. Important here are not the actual numbers displayed, but the
experience you accumulate by investigating your own code and seeing how those
numbers correlate to your experience with the software that you write or maintain.

Lcc-win32 User’s Manual 120


After reviewing the enormous amount of papers published within this field, the author
abstracted the following information, which seems to be widely recognized as
meaningful measurements.
• The number of lines of a program/module
• The number of unique operands
• The total number of operands used
• The number of unique operators
• The total number of operators
• The number of flow control statements
• The volume of commentaries
For the C language, Wedit considers the expression "++" or "+=" as an operator.
Constants and variables are considered as operands (the objects that operators
manipulate). A construct such as 'while' or 'for' is considered to be a control flow
directive.
Analysis of a Whole File
This option provides a global view of the functions in a file, displaying the results in a
graphical form. You can call up this option by clicking somewhere in an open file with
the right mouse button. In the contextual menu that opens, choose the ‘metrics’ menu
option.

A line whose length is proportional to its length or volume, depending on the settings of
the ‘Data’ menu selection represents each function in the file. To see to which function

Lcc-win32 User’s Manual 121


each line corresponds to, click on the line you are interested in. In the dialog box (at the
bottom of the graphic), this will display the exact value of the line and the name of the
function to which it corresponds. If you select it in the dialog box, all the data
corresponding to the data will be shown.

The result is displayed in the following dialog box:

There are four main groups of collected data:


• The group to the left shows the raw data.
• The 'Style' group shows the percentage of comments, etc.
• The 'metrics' groups show the values calculated according to the formulae
below.
• The 'Identifiers' list appears as information only.
The formulae used are:

LENGTH: Total number of operators + total number of operands


VOLUME: Length * (log(number of unique operands)/log(2) )
LEVEL: (2 / unique operands) * (unique operands / total number of operands)
DENSITY: VOLUME / LEVEL
These formulae correspond to Halstead’s work.

Lcc-win32 User’s Manual 122


How Wedit Collects the Data
It is not necessary in this forum to discuss at length what a line of code is. Defining the
nature of an instruction, is slightly more complicated. For the C language, Wedit uses the
number of statement separators (the semi-colon) as a guide. The other definitions are
straightforward: All operators are counted for the number of possible operators, including
the preprocessor commands. The rationale behind this is that they count for the
comprehension of the text. Parentheses are counted each as an operator.
Numbers are considered operands, as well as static character constants or strings. The
flow-control operations such as, 'for case while', etc. are counted, and they are important
for the McCabe complexity measurement.
The 'style' group gives the percentage of comments, the number of 'goto' instructions
used, and the maximum depth of blocks in the analyzed code.

Analysis of a Function's Identifiers


If the number of lines of a function is important, it can be difficult to see the evolution of
a variable usage. This utility builds 'cuts' through the program text, showing you a
reduced number of lines: those that contain the identifier that you want to investigate.

This option allows you to visualize only the lines of the function that contain the given
identifier. It is designed to show more clearly the evolution of the contents of a variable
and to easily identify if there is a problem. If the first line does not contain an assignment

Lcc-win32 User’s Manual 123


statement, for instance, it is likely that an uninitialized variable problem exists. The
variables are classified in three groups:
• Local variables (left column)
• Arguments (center)
• External symbols (right)

An external symbol in this context means all the identifiers that are not defined as locals
or arguments. This includes the #define statements that the function uses and the names
of all typedefs used. This does not correspond to a strict C external definition, but rather
to the importation of names and to the dependencies created by this importation.
It is simple to use: click on the symbol that you want to investigate and all affected lines
will be shown at the top of the three lists.
At the lower left you will find the function's prototype.

The Macros
The key combinations Ctrl+Shift+A to Ctrl+Shift+Z are reserved for 26 different macros.
Macros are simply long phrases that you can define to be inserted at the cursor's position
when you press the specified key combination. For instance, you can define a macro
Ctrl+Shift+I for the 'if' construct of the C language:
if ( ) {
}
else {
}
To enter/modify a macro, use the 'Macros' option from the 'Edit' menu. This option will
display the following dialog box:

Lcc-win32 User’s Manual 124


You can reach this
dialog box by
selecting the
‘Macros’ tab in the
configuration
property sheet of lcc-
win32.

In the left column, the key that corresponds to the macro name is visible. The
replacement text is shown at the center. The 'Add' button adds a new definition, the
'Erase’ button deletes a definition.
Identifying an Executable or an Object File

This option allows you to insert a static character string within the C source file of type:
''$keyword:value$''. Since the static character strings are included in the executable, this will
allow the 'Identify file' utility of the 'Find' menu to search for all of these types of character
strings within the executable to identify the name and the date of each module that was used
to build the final product. The editor recognizes the static character string and updates the
date automatically each time a module is saved.
You reach this dialog box by choosing the ‘ID’
option in the ‘Search’ menu bar.

Lcc-win32 User’s Manual 125


Normally you would leave the entry field empty. You can, however, use it to add additional
information to the file. Take into consideration space restrictions, since these character strings
use space within your executable image.
To inspect an executable, use the 'Identify file' option of the 'Search' menu. This option will
display the following dialog box:

An executable can contain many of these character strings, each one from a different module
of the system. This allows you to see each of the sources that were used to build the final
product. This can provide significant assistance in rebuilding the state of the sources to find a
problem at a client's site.
Generating a Table of Character Strings

Wedit allows you to automatically generate string tables, either in the .rc format, or in a
plain table format. All of your current C source files will be scanned for character strings.

The basic idea is to replace all occurrences of


ShowError("File not found");
by
ShowError(GetRcString(354));
or
ShowError(StringTable[354]);

This
1. Simplifies the translation of your software into another language
2. Separates programming from the writing of error messages

Lcc-win32 User’s Manual 126


3. Reduces the total size of the program in memory because the character strings use
memory only when they are used and total memory size of your executable
diminishes.

You can reach this dialog box by choosing the ‘Strings’ item in the ‘Utils’ menu bar.

This dialog box allows you to view and control the generation process.
'Renum' option
This option allows you to renumber the integers used for identifying each string. If you
want to include the strings in another table, this option is essential.
The following dialog box is displayed:

Here you can change either the starting number or the increment to be added to each
string. If you want to have one numeric identifier for a string altering the sequence, go to
the 'Edit' option below.
'Edit' option

Lcc-win32 User’s Manual 127


This option is active only when a character string is selected. It will change the
configuration for a particular character string. You can change the number or the
symbolic name you will use for the string that is selected.

Exclude:
If you do not want to include a character string and leave it this way in the source, select
the string and press the exclude button.

You have two options for generating the string table. The first is to generate it in the
STRINGTABLE rc format; the second is to generate it in a normal character string table.
The generation of a string table in the .rc format leads to the following dialog box:
You reach this dialog box when you click the
‘rc’ button in the ‘Strings’ dialog box. You
reach the ‘Strings’ dialog box by selecting the
‘Strings’ menu item in the ‘Utils’ menu bar.

You should enter:


• The name of the output file
• The name of the function that will return a character string at runtime
• If you want to have the symbolic names (#defines) or the numbers in your source
file
The resulting file looks like this:
STRINGTABLE
BEGIN
STR_0000,"Aucun"
STR_0001,"Champ <libellé> est obligatoire"
STR_0002,"Champ <nom> est obligatoire"
STR_0003,"*"
...
STR_0034," "

Lcc-win32 User’s Manual 128


STR_0035,"%7d "
STR_0036," -- "
END
In the source file, instead of (for example):
sprintf(msg,"%s exists already",tamponalloc);
We have
sprintf(msg,GetStringFromRc(STR_0008),tamponalloc);
/* %s exists already */
The generation of a table is functionally equivalent.

You enter:
1.The name of the output file. If this file exists already and it is a table string file that was
previously generated by Wedit, the new definitions will be appended to the end of the
file. Automatic renumeration will occur to avoid destroying the definitions of previously
existing strings.
2.The ‘Name of the table’ entry field is the variable name that will be used in your
program text to access this table. You should use names that avoid conflicts with any
other identifier in your program.
Alternatively, you can name a function that will return the character string given an
index. This option is active if you choose the ‘Function’ radio button at the left. If not a
straight index will be used.
The "DIFF" Utility
This utility will find the differences between two text files or between all files of two different
directories.
You can reach this
dialog box by
using the ‘Diff’
option from the
‘Utils’ menu
Alt+u, then
d.

Lcc-win32 User’s Manual 129


The entry fields should contain the names of the files to compare. The options are self-
explanatory. Only the 'C' syntax option needs further explanation. This option will preprocess
both files, ignoring comments and all white space, and report any differences in the program
text. The result will be organized by function changed. This allows you to quickly determine
which functions were changed between two files.
If both names are directory names, DIFF will search all files that match the specifications in
both directories and present a summary of this form:
If you want to use the ‘merge’ utility, you should check the corresponding check box, and fill
in the name of the output file, since the merge will create one.
If you press 'Detail' button, DIFF will compare each of the common files in both directories.
The 'Ignore' button allows you to exclude from the list of common files the selected file.
The differences between two files are presented this way:
You
reach this
dialog
box when
you make
a DIFF
between
two
directorie
s or
several
files at
once.

Lcc-win32 User’s Manual 130


You can go to the next/previous difference using the push buttons at the bottom of the
display.
This dialog box is not modal and can be left open during the modifications that you make
to a file.

If the option 'C syntax' is selected, Wedit will show the differences in this dialog box:

Lcc-win32 User’s Manual 131


At the upper left, there is a list of all modified functions; at the lower left, a list of all global
modifications, i.e., all modifications that are not within a local scope. By selecting a line from
one of these list boxes, you will see the difference shown in the two multi-line entry fields at
the right.

The GREP Utility (Find in files)


GREP stands for "Global Regular Expression Print". This utility searches for a character
string or a regular expression in a set of files. It was first developed under the UNIX
operating system and then converted for most of the operating systems in existence. This
version of GREP differs from the other command line GREPs in the use of the windowed
user interface to facilitate the access to the retrieved information.

Lcc-win32 User’s Manual 132


You reach this dialog box by
selecting ‘GREP’ in the ‘Search’
menu bar.
The expression entered can be understood either as a regular expression or as a literal
character string. To use the regular expression feature, check the corresponding button at
the right.
The name of the file(s) to search can be a generic expression, such as "*.c". This
expression should be understood by the underlying operating system. Neither DOS nor
OS2 accept true regular expressions as ambiguous file names.
The directory in which the search will be performed can be different from the current
working directory.
If the 'Ignore case' button is selected, each line read will be translated into upper case, as
well as the search expression.
‘Multiple’ means that you can enter several expressions separated by blanks. All the
expressions you enter must be in a given line for that line to be considered a match.

Adding a Utility
A utility is a program launched by the editor using a menu item from the 'Utilities' tab in
the configuration of Wedit. It should be a program that you use frequently. The
'nickname' you choose for it will be added to the 'Options' menu.

Lcc-win32 User’s Manual 133


The dialog box asks you for the following information:
• The name of the executable to start. Here you should enter the name of the
executable or a keyword enclosed in dollar signs.
• The arguments you want to pass to the program
• The directory in which the program should start
• The nickname you want to associate with the program. This name will be added
to the options menu.
You can enter the following keywords, instead of a 'hardwired' argument:
• $EXE$ This will be replaced by the executable that is associated to the current project.
• $FILE$ This will be replaced by the name of the current file.
• $CURSOR$ The symbol under the cursor.
• $ASK$ The editor will ask the argument of a program and replace the keyword with the
text you enter.
Inserting Special Commentaries
Commentaries are important. Wedit helps you standardize two kinds of commentaries:
Those that precede a function definition, which help to clarify what the function does, and

Lcc-win32 User’s Manual 134


those commentaries at the beginning of a module, which describe the contents of the whole
module.

You reach this dialog box either by using the ‘Description’ sub-menu in the ‘Edit’ menu bar, choosing the ‘’File’
option, or using the contextual menu that opens when you click with the right mouse button somewhere within an
open source file.

The different fields should contain the following information:


• "Name": The name of the file. This field is filled in automatically by Wedit.
• "Identification": This should be filled in with the user. No control whatever is done on
the data entered here.
• "Description": Idem.

Inserting a Comment at the Beginning of a Function


To use this function, place the cursor at the beginning of a function and choose the Edit-
>Description->Function option from the menu. This will produce the display of the
following dialog box:

Lcc-win32 User’s Manual 135


You can reach this dialog box by using the ‘Function’ sub-menu of the ‘Description’ option in the ‘Edit’ menu bar. Or you can go
to the ‘Edit’ menu bar, choose ‘Description’, then ‘Function’.
If you fill in the fields and Wedit cannot verify the information you type, the prototype of the
function is displayed at the bottom. Do not modify the first two fields: They are maintained
automatically by the editor.
The ‘Purpose’ field is for a general description of the function algorithm and any general
notes that are necessary for understanding how the function works.
The ‘Inputs’ field is for commenting on the argument that the function receives and any
global variables it uses.
The ‘Output’ field is for documenting the return result and any modifications the function
makes to its global environment.
The ‘Error handling’ field is for documenting what happens in the event of an error, including
what error checks are run, etc.
These special comments would not be useful if they could not be modified. The editor
recognizes these types of comments and will parse its contents and display them if you choose
this option again and there is already a special comment similar to this.
The 'TREE' Utility
This option graphically displays the calling tree of a function. It can be reached through
the ‘Utils’ -> analysis -> Tree menu options. You will be prompted for a function name.
That function will be considered the root of the hierarchy.
Here is an example of the graphics displayed.

Lcc-win32 User’s Manual 136


The small menu at the left allows you to print the tree or to show information about it,
such as depth, number of branches, etc.
The Object File Cross-Reference Utility
This utility allows you to search for symbols or view the dependencies between two
modules by using the object files themselves as a source of information. This utility is
based on a similar utility that Borland included in their TURBOC compiler environment
for Windows 3.1.

One of the main points is showing you which functions in your code aren’t used
anywhere. This can be viewed easily with the “Unreferenced publics” list, described
below.
The first step when using this utility is to choose the object files that you want to include
in the cross-reference.

Lcc-win32 User’s Manual 137


You reach this point by using
the ‘Analysis’ option in the
main menu, and then
choosing Cross-reference
object files: ‘obj’.
To add a file, select it in the
list, then press ‘Add’. To
eliminate a file, select it in
the list below, then select
‘Eliminate’.
To quickly select all files,
select the first file, then
simultaneously press the Shift
+ down arrow keys.
The directory in which the
files are located is shown at
the bottom left corner of the
dialog box.

You can change the directory using its corresponding button at the bottom, eliminate
object files with the “Ignore” button in the middle. When you are finished, press the ‘OK’
button. The following dialog box will appear. This may take some time, because all of
the actions are implemented after you press ‘OK’.

Lcc-win32 User’s Manual 138


The main point of interest in this dialog box is the left column. It will indicate to you
which symbols are exported from a module and not used anywhere else in the program.
Either these symbols are used in the same module and should be declared static rather
than public, or they are not referenced anywhere and are dead codes that can be
eliminated. The latter is the more likely. Of course, as in the example above, the ‘main’
function is an exception!!
You can choose a module to display using the combo box at the upper left corner. It is
possible to find a symbol (press the ‘Find’ button) or display the results in a graphical
display. Press the PLOT button.
The plot arranges the object files in a circle, and will indicate the relationships between
any two points in the circle with colored lines. Those lines show you what is
imported/exported between two modules.
By clicking on a line, you will see what symbols are exported/imported from the two
modules. This is similar to the ‘relationships’ utility, but different in that there is no
symbolic processing. When two modules share between them a macro definition, for
instance, this will not appear here.
Here is an example of the PLOT output.

Lcc-win32 User’s Manual 139


This plot shows six object files. The color codes are shown at the upper left corner. By
clicking in the file name ‘exedump.c’, the display changes and two green lines originate
at ‘exedump.c’ going to the other modules where there is a relationship. By clicking in
those lines, you can display in full all of the symbols that tie those modules together at
the object file level.

Lcc-win32 User’s Manual 140


Searching Information about the Defined Functions
The editor can search for the following types of information: Function prototypes and
function relationships, i.e., what calls what and where.

Lcc-win32 User’s Manual 141


You can
reach this
dialog box by
selecting the
Browse
functions
item in the
‘Analysis’ list
box.

The
‘Analysis’ list
box can be
reached
from the
main menu
by selecting
‘Utils’ then
‘Analysis’.

All information shown is based on the currently selected function, which is highlighted in
the function listbox at the upper left. Each time the selection of that listbox changes, the
information in the other parts of the dialog box will be updated accordingly.
For each function, the following will be displayed:
• Its prototype at the bottom and any commentary that immediately precedes the
function definition
• All functions that call up the selected function in the list box at the right
• The name of the file and line number where the function is defined
• All functions that are called up by the selected function in the list box at the
middle of the dialog box
Double-clicking in one of the list boxes will call up a dialog box showing the exact place
where the call is done and its context.
Writing the Prototype of all Functions Defined in the Current File
The 'Prototypes’ option is used to produce a file of prototypes that will describe all
functions defined in the current file. It is better if this is handled automatically so that a
function prototype is not forgotten and older software is converted to the ANSI form.

Lcc-win32 User’s Manual 142


You can reach this dialog box by
using the ‘Analysis’ option from
the ‘Utils’ menu, then choosing
the ‘Generate the function
prototypes’ item in the list box.
Click on ‘Utils’ then ‘Analysis’. A
list box full of option appears.
Choose the ‘Generate function
prototypes’ option by double-
clicking on the line.

Output file You should enter the name of the output file here. If that file name is in
name use already, you will be prompted before the editor replaces it.
Options The button 'Load into the editor' will display the result after build. For
more information see the browsegen documentation

The structure of the generated file is the following:


• A commentary with the name of the source file and the date of generation
• A preprocessor instruction to avoid including this file twice
• The prototypes for each function defined in the source file
• An #endif at the end of the file
For example if the source file is called FOO.C and the name used for the generated .H
file is FOO.H, the generated file will have the following form:

/* Prototypes for C:\TST\FIC.C. Generated 1994.06.19.6.6.26


*/
#ifndef TFIC_H_ID
#define TFIC_H_ID
int FindLineFromPoint (int ycoord );
HRGN BuildRegionUp (HPS hPS ,int lin ,int col );
...
#endif
Searching and Displaying a Structure Definition
The editor will display the definition of any structure defined within the current file or
any file #included in the current file. To use this option:
• Place the cursor under the name of the structure you want to display
• Press F8.
The editor will open a secondary window containing the definition of the structure.
Similarly, if the cursor points to a symbol of a type structure, F8 will display the
definition of the symbol AND the definition of the structure. The newly opened window
can be reached with Ctrl+Esc.
Alternatively, you can point the cursor arrow at the name you want to search and choose
the option to go to the definition from the contextual menu that appears.

Lcc-win32 User’s Manual 143


Showing the Definition of all Defined Structures
This option is part of the ‘Analysis’ menu item in the ‘Utils’ menu bar. It allows you to
browse the definitions of all defined structures in all loaded files. The editor assumes that
the definitions of structures are common to all loaded files.
Before parsing the current file, the editor asks which include directive should be
followed. As you know, in C there are global includes (enclosed in angle brackets) and
the local includes, enclosed within quotes. Choose only the local includes if you want to
focus your search on the structures defined by you, without taking into consideration the
system structures, which can be numerous and may not relevant to your search.

The information is presented as follows:

The information displayed depends on the selection in the list box to the left.
The 'Print' button will generate a memory file in the editor with the definitions of all the
structures in alphabetic order. You can print it using the normal printing procedure of
Wedit. The name of the buffer is '_struct_.c'.

Lcc-win32 User’s Manual 144


The 'Small window' button will open a secondary window with the structure definition.
Show Information about the Global Variables
This option allows you to browse the definitions of all the global variables defined in a
given module. A global variable for the parser of the editor is any symbol that is defined
or used at the global scope (bracket level 0) and is not enclosed within parentheses.24
The usage is very similar to all other list-displaying operations. Select one item from the
list with the mouse, and the associated information will be updated accordingly.

Showing the Relationships between Two Modules


This option is designed to answer questions such as 'Which functions/Variables are used
by module X and defined in module Y?’
First, choose the two modules by clicking on their names in the dialog box that presents
you a list of names.

Their relationships are described with the following display:

24This is not always true. It is normal for some include files to begin with the following instruction:
extern "C" {
This means that all definitions later wouldn't be used at all if we followed strictly the 'brackets level
zero' directive.

Lcc-win32 User’s Manual 145


It is important to keep in mind that the search is made at a symbolic level, i.e., if two
modules share a preprocessor macro, it will be listed.

Showing the Executable or Object File Statistics


In the 'Utils' menu, you will find the option 'Executable statistics'. This option calls up the
'pedump' utility and shows the results in the output window. Normally, the file displayed
will be the executable of the current project. If there is no project defined, this option will
prompt you for an executable file name.
To display statistics for an object file, use the 'File' and 'Open' options, then open an
object file. Wedit will call pedump for the corresponding file. The other extensions
recognized are 'OCX' for special VBASIC executables, and 'LIB' for library files. In the
latter case, Wedit will display the symbols exported from the library.
The output of this utility for an object file is:

Summary of "COMMON.OBJ": 96549 bytes


Time stamp: Mon Feb 08 00:01:20 1999

Section Name Size


01 .text 13188
02 .data 13676
03 .bss 138
04 .debug$S 12044
05 .debug$T 7465

Lcc-win32 User’s Manual 146


The code section is traditionally called 'Text', even if its contents are not anything that
remotely resembles normal text. The uninitialized data section is also called 'bss' for the
same obscure historical reasons. The 'debug$S' and 'debug$T' sections are the debug
symbols and debug types information.
Automatically Generating the Program's Technical Documentation
This utility proceeds in several steps. The first is to decide which files should be included
in the technical documentation. Use only .C files.
You can
reach this
dialog box by
selecting the
‘Generate
HLP item’ in
the ‘Utils’
menu bar.

The 'Title' entry field should contain the title that will appear in the help file being
generated.
The 'Help file name' field should contain a file name with the .HLP extension. The result
from compiling an intermediate RTF file (for Windows) or IPF file (for OS2) generated
by Wedit will be stored here.
To add a file to the list, click on the 'Add' button; to delete a file from the list, use the
'Remove' button.
The Output File
The generated file has two main levels:
• A file level, where the index will show all the C sources included during the
compilation. If the file, as is often the case, begins with a commentary, this comment will
be included here. At this level, you will find all of this file’s global variables, as well as

Lcc-win32 User’s Manual 147


all variables declared as 'extern'. In general, all symbol definitions (excluding
preprocessor symbols) appearing at global level will be here.
• A function level, where each function defined in the file is listed, with any
comment that immediately precedes the function. This includes, of course, the special
editor maintained commentaries.
• A 'data structures' level, where all structures defined in the source files and their
associated include files are listed. Wedit assumes that the files are related and does not
list two structures that have the same name.
Printing Your Files
You can reach this dialog box by selecting the ‘Print’ option in the ‘File’ menu bar.
This dialog box is used to print one or all loaded files. You can change the font or print a
function, generate RTF output, add line numbers, etc.

You can print a given function by choosing the corresponding push button.
You can send the printed file to the printer or you can generate an RTF file that can be
used later in a text-processing program.
The ‘Configure’ button allows you to set the printer options.
The first time you use this feature, it is worthwhile to spend some time choosing the right
font for your printouts, according to your printer and the fonts available.

Lcc-win32 User’s Manual 148


Weditres : the resource editor

Weditres is a utility for :


• Designing your dialog boxes under Windows
• Generate the ‘C’ code that is necessary for them to run.

This two operations can be separated. You can use the resource editor for just drawing
your resources, and you will take care of the programming sied, writing of the callback
functions, etc. This is a possibility for instance, when you have already a mass of code
that uses this approach, and you do not feel like modifying it to fit into the resource editor
schema of things.
The different steps involved in the construction of a dialog box.
To use a dialog box you have to:
• Draw it. Weditres helps you by giving you a drag and drop interface. You just place
the objects in their respective positions.
• Generate the different files that containg information about it (Save it)
• Compile and link the generated sources with your program.
• Test it.

This manual will explain you this operations in detail. To give you an overview of the
process, here we summarize all those steps.
• Step 1. Drawing the dialog box. You drop the controls from the toolbar in the place they
will occupy in the dialog box. This operation is explained in detail in the first chapter.
• Step 2. Saving it. Weditres saves the information in a special type of files with the
extension .wed. This file contains the information Weditres needs that is not contained in
a normal windows ressource file. The windows information is saved in two files : the
.dlg, and the .res. Those files contain information that allows Windows to display your
dialog box at runtime. In addition to those, Weditres generates a .c and a .h source files.
Those are linked with your program, and implement all the user interface characteristics
at runtime, that you defined when drawing the dialog box.
• Step 3. You compile and link the generated sources with the callback procedures for your
dialog box.
• Step 4. You test...

Example :
You make the dialog called IDD_MYDLG, in the project called ‘myprj’. If you do not
change the default file names, you will obtain the following files :
1. myprj.dlg. This file contains the ascii description of the resources used, to be
compiled using lcc-win32 resource compiler ‘lrc’.
2. myprj.res This file contains the binary description of the resources. This file can be
directly used by the linker to add your resources into the executable. This saves you
the compilation step.

Lcc-win32 User’s Manual 149


3. myprj.h. This file contains the symbolic definitions of the symbols you used in the
dialog, so that you can use them in your C programs.

The .rc files.


You can have many dialog boxes and other resources in your program. Since weditres
only edits the dialog boxes, it is important, when you needed it, to organize things into
an .rc file, that will contain all other resource files, and the descriptions of all resources
not handled by weditres.
This file, for the above example would contain just the following lines :
#include <windows.h>
#include myprj.h
#include myprj.dlg

The first line is mandatory. All the ASCII descriptions of resources use the symbolic
names defined in windows.h, instead of the raw numerical values.
The second one instructs the resource compiler to include the definitions you made when
designing the dialog box. You gave a symbolic name to each element you want to access
in your dialog box, so this file, that contains all of them, should be included too.
The third line, instructs the resource compiler to read the dialog definitions from the
indicated file.
You can separate all your dialogs, and store each one of them in a spearate dialog box file
and header if you wish. In that fashion, each editing project remains of reasonable size.
Or you can throw all your dialogs into one big file, so you avoid cluttering your directory
with too many files. This is a matter of taste left to you.
Structure of the generated code.
Weditres generates a dialog box procedure in a c file. this procedure contains the actions
to take when each of the windows messages that you have decided to handle arrives at
your dialog.
The structure of this procedure is verey simple : it is just a big ‘switch’ statement,
containing a case for each of the messages that interested you.
BOOL DialogDlgProc(HWND hwnd,UINT msg,UINT wParam,UINT lParam)
{
switch (msg) {
case WM_INITDIALOG :

. some code here to treat this message


.
return (TRUE) ;
case WM_COMMAND :

. some code here to treat this message


.
etc.
}
return(HandleDefaultMessages(hwnd,msg,wParam,lParam)) ;
}

Lcc-win32 User’s Manual 150


The unhandled messages go to the default dialog box procedure of weditres. This
procedure is described later, and treats all messages and takes default actions for some.
Its code is located in weditreslib.lib, that you should include in your project link libraries.
The source code is available too, so you can modify it as you wish.
Normally, you are interested in taking some action when a message arrives, and this can’t
be generated by weditres. It is your task. Here we meet the ‘callback’ functions.
Each of those callback functions will be called by the dialog procedure when a message
for which you showed interest arrives. Those callback functions receive different
parameters, that allow them to access to the other controls of the dialog, or to take any
other action.
The last piece that is missing from this puzzle, is how do you start all this happening.
This is very easy. You use the DialogBox, or the DialogBoxParams function, to associate
a resource with a procedure that will handle the messages.
This is done using the DialogBox windows primitive :
The DialogBox function creates a modal dialog box from a dialog box template resource.
DialogBox does not return control until the specified callback function terminates the
modal dialog box by calling the EndDialog function. Its prototype looks like this :
int DialogBox(HANDLE hInstance,LPCTSTR lpTemplate,HWND hWndParent,
DLGPROC lpDialogFunc ) ;
hInstance Identifies an instance of the module whose executable file contains the dialog
box template.
lpTemplate Identifies the dialog box template. This parameter is either the pointer to a
null-terminated character string that specifies the name of the dialog box template or an
integer value that specifies the resource identifier of the dialog box template. If the
parameter specifies a resource identifier, its high-order word must be zero and its low-
order word must contain the identifier. You can use the MAKEINTRESOURCE macro
to create this value.
Normally, all your resources are defined using a symbolic name, i.e. a #define that
amounts to an integer. Weditres does not support named dialog boxes very well, and in
any case, that is really wasteful of space in your executable.
hWndParent Identifies the window that owns the dialog box. Normally, this is the main
window of your application, but of course you can use any other window.
lpDialogFunc Points to the dialog box procedure. For more information about the dialog
box procedure, see the DialogProc callback function.
Return Value If the function succeeds, the return value is the nResult parameter in the
call to the EndDialog function used to terminate the dialog box.If the function fails, the
return value is -1.
In the normal case you would just call then :
DialogBox(hInst,MAKEINTRESOURCE(IDD_MYDLG),hwndMain,MyDlgFunc) ;
The system loads the indicated resource dialog from the executable, and starts sending it
messages. The first message, that its sent is WM_INITDLG, followed by a WM_SIZE.
This messages are received when the dialog box is not yet visible in the screen. Here you
can initialize things.
The function ‘MyDlgFunc’ is generated by weditres, and it starts receiving those
messages. When a message that you marked as interesting arrives, the procedure that you

Lcc-win32 User’s Manual 151


indicated in the ‘Callbacks’ field of the control/dialog will receive control, and you can
treat the message as you wish.
Building the dialog box.
The principle of operation for building the dialogs is simple : You have a toolbar with all
the controls supported by weditres. You pick up one type of control (a button, a group
box, etc) and you drop it at the position you want, within the surface of the dialog box.
You access to the parameters of the selected control by typing Ctrl+Y, or just double
clicking in the surface of the control. Personally, typing Ctrl+Y is better, because a
double click could slightly move the control from its position.
There is a different dialog box for each type of control. In those dialog boxes you define
the identity (symbolic #define) and numerical value that you want for each control. This
is not necessary for all controls, only for those you want to access from your program. Of
course you could write
GetDlgItem(hwnd,476) ;
but it is much clearer if you write
GetDlgItem(hwnd,IDVALIDATE_BUTTON) ;

In the parameters dialog boxes you determine in general the following things :
1. The identity of the control, as shown above.You can change the symbolic name given
by default, or its numeric value. To use an already existing identifier you open the
identity combo box, and select an item from the list of available identifiers. Do not type
an old name directly, because of a small bug I haven’t foudnd the time to correct. Only
type a name in there when its a new name, not used before.
2. The static style of the control, i.e. the different options that windows gives for
modifying the appearence of the control, or some other properties.
3. The dynamic style. This is implemented by C code generated by weditres, that allows
you to change some characteristics of the dynamic behaviour or appearence that waren’t
provided by the windows system.
4. The messages and actions you want to be aware of. Weditres will intercept the
messages you indicate, and generate code that will code the function you specify. That
function is usually indicated in a ‘Callbacks’ edit field, in each dialog box. You can type
any name you want, but it is better to prefix it with the name of the dialog box, so that
there isn’t any name conflict between the functions that make similar actions in different
dialog boxes.

A simple example
You go into the ‘File’ option of the menu, choose new, enter ‘example’ as the name of
the project, and then OK.
Weditres will startup a dialog box, and give you a complicated dialog box with several
dozens of parameters. You ignore all of them except the ‘Callbacks’ field, and enter there
the prefix for all the functions in this new dialog box : DlgExample.
Then, press the ‘ok’ button and the dialog box will disappear, leaving you an empty
dialog box. Drag one button from the toolbar to the dialog box.
The ‘Button’ icon is labelled ‘ok’, so it is fairly easy to recognize it. If you leave the
mouse a small time over each button, an explicative text appears, telling you what control
is described by the icon.

Lcc-win32 User’s Manual 152


Put the button somewhere in the dialog box, then double click on it. You will see a
slightly less complicated dialog box open, and you will ignore all parameters, BUT the
‘Callbacks’ edit field. You will type in there : DlgExampleButtonAction.
Save your work. With an editor, open the file example.c, generated by weditres. You will
see following code :
/* Wedit Res Info */
#include <windows.h>
#include « example.h »

BOOL APIENTRY DlgExample(HWND hwnd,UINT msg,


WPARAM wParam,LPARAM lParam) /* Standard
paramaters of a callback function */
{
static WEDITDLGPARAMS WeditDlgParams ;
switch(msg) {
case WM_INITDIALOG : (1)
SetWindowLong(hwnd,DWL_USER,(DWORD)&WeditDlgParams) ;
DlgExampleInit(hwnd,wParam,lParam) ; (2)
/* store the input arguments if any */
SetProp(hwnd, »InputArgument »,(HANDLE)lParam) ;
break ;
case WM_COMMAND : (3)
switch (LOWORD(wParam)) {
case 101 :
DlgExampleButtonActionSelected(hwnd) ; (4)
break ;
}
break ;
}
return(HandleDefaultMessages(hwnd,msg,wParam,lParam)) ;
}
1. This message, is the first one that this procedure receives. Weditres does here some
initializations, needed later for its internal workings. We ignore this.
2. The procedure ‘DlgExampleInit’, is called by the code generated by weditres. This
procedure should initialize what needs to be initialized in this dialog box. This procedure
should be written by YOU, since you are the one that knows what this dialog box will do,
and what things need to be stored where.
3. The message WM_COMMAND is one of the most popular window messages. Most
of the messages sent by the controls when an event occurs reach this part of the code.

Lcc-win32 User’s Manual 153


4. DlgExampleButtonAction is again an example of a callback. This is a procedure that
should be written by you, and should do whatever you think is necessary when the
‘action’ button is pushed.
The .dlg file
DLG_0100 DIALOG 6, 18, 180, 180 (1)
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
(2)
CAPTION « Dialog Title » (3)
FONT 8, « Helv » (4)
BEGIN
PUSHBUTTON « Push », 101, 52, 65, 40, 14 (5)
END
1. The dialog has the name DLG_0100 since we didn’t change the default name. You
should put more meaningful names here. The coordinates in dialog box units follow.
2. The style of the dialog is the default style : visible, caption, system menu, and modal
frame. This are the static styles.
3. The text of the caption follows.
4. The font name and point size follow.
5. We have only one control : a push button, with its default text. Again, the coordinates
of the control follow in dialog box units.
A simple .rc file for our example
We can write a simple .rc file to be used with the resource compiler. Here it is :
#include <windows.h>
#include « example.h »
#include « example.dlg »
You can then compile this with the symple command line directive :
lrc example.rc
This is not necessary, since weditres generated too an example.res resource file that can
be directly used by the linker.
Controlling which files get generated.
To control which files will be generated, and where they will be written, you should use
the ‘Files’ menu item in the ‘Files config’ contextual menu. This menu can be shown at
any time if you press the right mouse button somewhere in the surface of the weditres
edit window.

The dialog box that appears allows you to individually select/deselect which files will be
generated, and to change the paths where they will be generated. It is not a bad idea to
look at this place if you have any problems with paths, or similar.

Lcc-win32 User’s Manual 154


The options are the following:
1. The framework file. This is a C source file that is generated by the resource editor
that contains a dialog box procedure for each dialog box defined. Only if this option
is active you will see in all properties dialog boxes the corresponding dynamic
options.
2. The header file. This file should be always generated since it contains all the
definitions of the integer constants in your resources.
3. The binary resource file. This is a file that can be passed directly to the linker.
4. The .rc ascii definitions file. This file will be generated if you started the resource
editor with a .rc file. It contains the definitions of all the resources.
5. The .dlg file. This is an ascii file that contains the resources definitions for your
dialog boxes only.
6. The .wed file contains the definitions of the dynamic properties of the dialog boxes or
resource that you have designed.

Lcc-win32 User’s Manual 155


7. User callbacks file. The name of the file where you stored the procedures that are
going to be called from the dialog box procedures. This is optional.
8. Additional include files. Files that will be included too in your resource files. You can
leave this field empty.
9. Dictionary. This is not implemented fully yet.
10. Include files for bitmaps etc. The resource editor will start the resource compiler
telling it to include these directories in the search.

Configuring the preferences


You can set the margins, and other things using the ‘Config’ menu item in the
‘Resources’ menu of Wedit.

The grid is the minimung spacing between each movement. The spacing is the amount of
space left by the editor by default between controls. The margins, are just that : margins
that delimit the controls from the borders of the window.
‘Sticky group boxes’ means that the controls that are enclosed by a group box are moved
with the group box when you move it. If you deselect this feature, to move all items in a
group box you have to select all of them.
You can include additional text in the header file that the resource editor generates. This
text can be entered here.
Managing the selection
There is always a selected item. It is highlited with eight small red squares. You can
change its hsape by taking one of the squares with the mouse, or, if you prefer using the
Ctrl+Arrow keys : Ctrl+left arrow is equivalent to taking the square in the left border of
the control and moving it leftwards.

Lcc-win32 User’s Manual 156


To select several items, you click in the controls you want to select and maintain the Shift
key pressed.
When several items are selected, you can align them using the dominant control as the
guide. The dominant control has all its squares full, in contrast to the others, that have
empty squares around them.
To align controls, use the fixed toolbar at the top of weditres. This toolbar contains
bitmaps for aligning several controls in all possible positions.
You can use the clipboard to cut and paste dialog items from one dialog box to the other.
The clipboard works as always with the currently selected items.
Testing your dialog box.

To start the control, just press the ‘test’ button, or press Ctrl+T. This will make weditres
create a copy of the control, and load that copy as windows would do. You can see the
appearence of the control in action, press buttons, select list box items, etc. Pressing the
OK button, or the Cancel button will stop the test. If the dialog box has a close menu,
pressing that button will stop the test too.
If you have painted yourself in a corner, by drawing a dialog box without all those
buttons, you can always get out by pressing Ctrl+T again, what will stop the test.
Using the directory listing
When you press the ‘dir’ button, you will see a list of all the dialog boxes that are
contained in the current project in a separate window. Using the right mouse button, you
can sort the items in several ways : by ID, or by title or others.
Setting the tab order.
The tab key can be used to switch the focus from one element of the list box to the
following one in the Group order that you choose at design time. Normally, this order is
the sequence that you used when dropping the controls in the dialog surface one after the
other. You can change this order by using the ‘Group’ item in the ‘Options’ menu bar.
This order is important for the ergonomy of your dialog box, specially for people that do
not like to leave the hands from the keyboard, and prefer just using the tab key to go to
the next entry field for instance, instead of using lengthy mouse move operations.
The ‘Group’ dialog box will show you the list of controls that you have already dropped
in your dialog box. You select one item, and then you can easily move it around to put it
first or after another control. Here you can set/unset whether the control will be a tab stop
or not. If you unset the tabs, the tab key will never go into that control. This is
recommended for controls that do not accept any user input, like static text fields or
group boxes.
And this is all there is to it Of course, there are hundreds of details that will be explained
later,if I arrive at bringing myself to writing all the documentation... But the essential of
weditres is this.

Lcc-win32 User’s Manual 157


Group order

The group and the tab order are essential for a good user interface. The tab order is the
sequence that the focus of the controls in the dialog will follow when the user presses the
TAB key. Normally, the TAB key should go from one control to its immediate neighbor,
without jumping around.
The dialog editor will establish this sequence as just the order that you used to drop the
controls in the dialog. It often happens, however, that you drop a control, and then you
realize that you forgot one, and drop another control in a wholly unrelated place. This
doesn’t affect your dialog box visually, but it does affect the user interface. Pressing the
TAB key will make the focus jump around within the controls of your dialog box.
Besides, it is important, that static controls like group boxes or text fields aren’t available
with the TAB key. If they acquire the focus, they do not show it, so the user doesn’t
know where the focus is.
You can change the tab order by moving the controls around within this dialog box. To
move a control you select it first, by clicking in the middle of a row.
When a control is selected, you will see that the form of the mouse changes to an
horizontal bar when moving within the list of controls. This means that you can drop the
control in that position, and change its order.
The controls that are reachable with the TAB key have a small tab symbol at the left of
them.
You should remove that tab stop from Group boxes, static text fields, and other static
controls. You should add it to all controls that receive user input like buttons, edit fields,
list boxes, etc.

Lcc-win32 User’s Manual 158


You can set/unset this property with the corresponding buttons at the right side of the
controls list.
You can set the ‘GROUP’ property to any control, that will become a group separator for
a number of controls that are logically related.
The toolbar
The floating toolbar of the editor allows you to choose a control and to drop it into the
dialog box.

The different buttons are :

This cancels the selection.

This represents a static text control.

This represents an edit control, both single line (default) or a multiline edit control.

This represents a group box.

This represents a push button.

This represents a check box.

This represents a radio button.

This represents a combo box.

This represents a list box.

This two buttons represent a scroll control, either horizontal or vertical.

This two buttons represent a static rectangle, either empty or filled.

Lcc-win32 User’s Manual 159


This represents an icon control.

This represents a month calendar control.

This represents a list view control. If you use this, please do not forget to call
InitCommonControls in your code. This applies to all other controls after this one.

This represents a tab control.

This represents a tree view control.

This represent a progress control.

This represents a spin button.

This represents a slider control.

This represents an AVI displaying control. This is not operational in this version of
weditres.

The two comboboxes allow you to edit the symbolic name of the currently selected
control at the left, and to edit the control’s text at the right, if applicable.

The selection

The selected control will be shown with full red handles around it. By holding the Shift
key down and clicking in other controls, you can select several of them :

Lcc-win32 User’s Manual 160


Here we have four controls selected. The dominant control has the full red handles. The
others are the controls that will be resized or aligned using the dominant control as the
guide, and are shown with hollow red handles. For instance, if you select several controls

and then press the align left button in the fixed toolbar of the editor, the controls will
be aligned using the left side of the dominant control. If you choose the ‘same width’
button in the fixed toolbar, the dominant control’s width will be used to resize all
other controls in the selection.
The multiple selection doesn’t apply to the dialog box itself of course, since there is no
meaningful alignment that can be used with the dialog box itself.
The selection is important when copying controls from one dialog box to the other, since
the normal operations like cut, paste, and copy apply to the selected controls. This allows
you to easily transport controls from one dialog to another.
The arrow keys apply to the selection too : you can move the group of selected controls
using the arrows, what is more precise than using the mouse.
When there is only one control selected, you can resize the selected control using the
Ctrl+arrow keys. The combination Ctrl+left arrow, for instance, will maintain fixed the
right side of the control, and resize it towards the left. The right arrow with the control
key does the same but to the right, the up arrow resizes it towards the top of the screen,
and the down arrow towards the bottom of the screen.
Fixing a control in the screen
Using the tool, you can fix a control, or one side of a control to the screen. This
allows you to move it horizontally or vertically without fear of disturbing the overall
position, or to fix it in one place within the dialog box, so that you do not move
accidentally later.
When you click in the tool, the mouse changes its shape, signifying that you can fix the
selected control. This will not work when you have the entire dialog box selected, since
fixing a dialog box is not very sinful.
You should click in one of the red handles of the selected control. The color of the handle
will change, telling you that side of the control is now fixed. For instance :

will change to : , meaning the right side of the control is now


fixed. This means that the control will move along the vertical axis only. This allows you
to move this control easily with the mouse without fear that you move it to the left or
right.
To exit from the ‘fixing’ mode, just click anywhere far away from the selected control in
the screen.
To unfix a fixed control you just select the fixing tool again, and click in a blue handle.
This acts as a toggle, unfixing the control.
The status bar

The status bar is divided into five fields. They show in dialog coordinates :
1. The upper left corner of the selected control(s).

Lcc-win32 User’s Manual 161


2. The lower right corner of the selected control(s).
3. The width (dx).
4. The height (dy).
5. The id of the control.

You can use the status bar to fine tune the position. By double clicking in the
corresponding field of the status bar you can enter the positions numerically. When you
double click in the ‘dx’ field of the status bar, you can change the width of the selected
control and enter a numerical value directly.
Managing the symbols

The purpose of this dialog is to allow you to add a new symbol, to erase a definition you
no longuer need, or to change either the name or the value of a symbol.
To add a new symbol type its name in the first entry field, then the value it should have in
the second, and press the Add button.
To erase a symbol select one in the list and press the Erase button.
To change a symbol change either its name or value, and then press the Change button.
The changes you do will be effective only after you press the validate button.
Easy isn’t it ? No big science here.
The zoom utility
This allows you to see in more detail your dialog box. Just choose ‘zoom’ in the
resources menu of Wedit, then click in the surface of the small window that appears.
Then, without releasing the mouse button , move the mouse pointer around. You will see
the magnified contents of the rectangle that the mouse draws in the zoom window

Lcc-win32 User’s Manual 162


Properties of a dialog box
Applications use dialog boxes to prompt for additional information for commands that
require user input. Using a dialog box is the only recommended way for an application to
retrieve the input.
Normally the dialog box is created, used, and destroyed. When the dialog box is visible,
the main window of the program is inactive. This type of dialog boxes is called modal
dialogs.
Many applications also use dialog boxes to display information or options while the user
works in another window. For example, word processing applications often use a dialog
box with a text-search command. While the application searches for the text, the dialog
box remains on the screen. The user can then return to the dialog box and search for the
same word again ; or the user can change the entry in the dialog box and search for a new
word. Applications that use dialog boxes in this way typically create one when the user
chooses a command and continue to display it for as long as the application runs or until
the user explicitly closes the dialog box. This are the modeless dialog boxes.

Modal dialog boxes are simpler to manage than modeless dialog boxes because they are
created, perform their task, and are destroyed by calling a single function.

Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.

Lcc-win32 User’s Manual 163


Title
This text will be shown in the title bar of the dialog. You can enter any text here.
Identity
The #define under which this dialog box will be used in your application. This is the
define you use when you call the DialogBox function. The numerical value is shown too,
below. In the ‘Specific class’ entry, you can enter a specific class that you want to use for
this dialog. This is normally left blank. In case you want to use another window class
than the usual one, please be sure that your class is registered before invoking the dialog.
Font
Name and size of the font used for this dialog.
Optional Gadgets
Button Style Effect
Title WS_CAPTION Shows a dialog box title
Min button WS_MINIMIZE Minimize control in titlebar
Max button WS_MAXIMIZE Maximize button in titlebar
System menu WS_SYSMENU System menu
Vertical/horizontal WS_HSCROLL/WS_VSCRO Scroll bars. Normally never
scroll LL used

Lcc-win32 User’s Manual 164


Standard buttons
This allows you to add the standard button ‘OK’, ‘Cancel’, and ‘Help’ to the dialog box
automatically.
Just press the ones you want to be added.
Styles
Button Style Effect
Tool window WS_EX_TOOLWINDOW A tool window has a title bar that is shorter than a
normal title bar, and the window title is drawn using a
smaller font. A tool window does not appear in the
task bar or in the window that appears when the user
presses ALT+TAB.
Accept files WS_EX_ACCEPTFILES Specifies that a window created with this style
accepts drag-and-drop files.
Clip siblings WS_CLIPSIBLINGS Clips child windows relative to each other ; that is,
when a particular child window receives a paint
message, the WS_CLIPSIBLINGS style clips all
other overlapped child windows out of the region of
the child window to be updated. (If
WS_CLIPSIBLINGS is not given and child
windows overlap, when you draw within the client
area of a child window, it is possible to draw within
the client area of a neighboring child window.) For
use with the WS_CHILD style only.
Transparent WS_EX_TRANSPARENT Specifies that a window created with this style is to
be transparent. That is, any windows that are
beneath the window are not obscured by the
window. A window created with this style receives
WM_PAINT messages only after all sibling
windows beneath it have been updated.
Center mouse DS_CENTERMOUSE Centers the mouse cursor in the dialog box.
Set foreground DS_SETFOREGROUND This style brings the dialog box to the foreground.
Internally, Windows calls the
SetForegroundWindow function for the dialog
box.
Control DS_CONTROL Creates a dialog box that works well as a child
window of another dialog box, much like a page in
a property sheet. This style allows the user to tab
among the control windows of a child dialog box,
use its accelerator keys, and so on.
Absolute DS_ABSALIGN Indicates that the coordinates of the dialog box are
alignment screen coordinates ; otherwise, Windows assumes
they are client coordinates.
No idle msg. DS_NOIDLEMSG Suppresses WM_ENTERIDLE messages that

Lcc-win32 User’s Manual 165


Windows would otherwise send to the owner of the
dialog box while the dialog box is displayed.
System modal DS_SYSMODAL Creates a system-modal dialog box. This style
causes the dialog box to have the
WS_EX_TOPMOST style, but otherwise has no
effect on the dialog box or the behavior of other
windows in the system when the dialog box is
displayed.
Popup WS_POPUP Creates a dialog that has the WS_POPUP bit on.
Normally this is the default.
Child WS_CHILD Creates a dialog that has the WS_CHILD window
style. Normally this is not desired. The dialog box
can’t leave the boundaries of its mother window.
No fail create DS_NOFAILCREATE Creates the dialog box even if errors occur ¾ for
example, if a child window cannot be created or if
the system cannot create a special data segment for
an edit control.
Clip children WS_CLIPCHILDREN Avoids drawing in child windows
Local edit DS_LOCALEDIT Applies to 16-bit applications only. This style
directs edit controls in the dialog box to allocate
memory from the application’s data segment.
Otherwise, edit controls allocate storage from a
global memory object. Somehow this button has
resisted the port from 16 bit weditres...
3D look DS_3DLOOK This style is required only by Win32-based
applications compiled for versions of Windows
earlier than Windows 95 or Windows NT 4.0. The
system automatically applies the three-dimensional
look to dialog boxes created by applications
compiled for current versions of Windows.
Center DS_CENTER Centers the dialog box in the working area ; that is,
the area not obscured by the tray.
Visible WS_VISIBLE Show the dialog when it starts
Context help DS_CONTEXTHELP Includes a question mark in the title bar of the
dialog box. When the user clicks the question mark,
the cursor changes to a question mark with a
pointer. If the user then clicks a control in the
dialog box, the control receives a WM_HELP
message. The control should pass the message to
the dialog procedure, which should call the
WinHelp function using the HELP_WM_HELP
command. The Help application displays a pop-up
window that typically contains help for the

Lcc-win32 User’s Manual 166


control.Note that DS_CONTEXTHELP is just a
placeholder. When the dialog box is created, the
system checks for DS_CONTEXTHELP and, if it
is there, adds WS_EX_CONTEXTHELP to the
extended style of the dialog box.
WS_EX_CONTEXTHELP cannot be used with the
WS_MAXIMIZEBOX or WS_MINIMIZEBOX
styles.
Disabled WS_DISABLED Creates a window that is disabled at startup.

Messages
Message Effect
Init Calls the specified callback function when the message WM_INITDLG is
received.
The name of the callback is
DlgXXXInit(HWND hwnd, WPARAM wParam, LPARAM lParam)
Normally, you should handle this message, since it allows you to initialize
things in the dialog box before is displayed.
Cancel Calls the specified callback function when the user presses the ‘Cancel’ button.
The name of the callback is :
DlgXXXCancel
Close Calls the specified callback when the dialog receives the WM_CLOSE
message. Its name is : DlgXXXClose.
All Instead of calling the default message handling function, it calls a callback :
DlgXXXDefault(HWND hwnd,UINT msg,WPARAM wParam,LPARAM
lParam) ;
This is an escape hatch so that you can always treat a message the framework
doesn’t consider.
Validation Calls DlgXXXValidate(HWND hwnd) when the user presses theOK button.

Properties of a Push button


The properties are described in the following dialog box :

Lcc-win32 User’s Manual 167


The fields are:

Button Style Effect


Standard BS_PUSHBUTTON Creates a normal push button
Default BS_DEFPUSHBUTTON Creates a default push button
Owner draw BS_OWNERDRAW Creates an owner draw pushbutton
Transparent WS_EX_TRANSPARENT Transparent button
Bitmap Not implemented
Windows Not implemented
bitmap
Visible WS_VISIBLE Button is shown at startup
Disabled WS_DISABLED Disabled at startup
Vert center Centers the text vertically rather than
of text horizontally
Client edge WS_EX_CLIENTEDGE Client edge
Flat BS_FLAT A flat button
Multi line BS_MULTILINE Text will contain several lines
Group WS_GROUP Button introduces a group of controls
Tab stop WS_TABSTOP Button can be reached with the tab key
Static edge WS_EX_STATICEDGE Button with a style that signifies that it doesn’t
accept user input. A strange style for a button…

Lcc-win32 User’s Manual 168


Properties of an edit field
An edit field is selected and receives the input focus when a user clicks the mouse inside
it or presses the TAB key. After it is selected, the edit control displays its text (if any) and
a flashing caret that indicates the insertion point. The user can then enter text, move the
insertion point, or select text to be moved or deleted by using the keyboard or the mouse.

Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.
You should establish here the general appearance of the edit field, and the prefix that will
be used by weditres when generating the callbacks you want for this control. You can
change the font, if you wish, the number of accepted characters, and set the initial
contents of the edit field, if any.
Identity
The #define under which this edit field will be used in your application. This is the define
you use when you call the GetDlgItem function for instance. The numerical value is
shown too, below.
Text alignment
Text can be aligned from the left, centered, and from the right. Normally, use left
alignment, other styles will provoke strange things when typing.

Lcc-win32 User’s Manual 169


Styles
Button Style Effect
Visible WS_VISIBLE The edit filed is visible when the dialog box is displayed
Disabled WS_DISABLED The edit field is disabled (grayed) when the dialog box is
displayed. You can change the text in it with
SetDlgItemText, but the edit field doesn’t respond to user
input.
Client edge WS_EX_CLIENTEDGE Specifies that a window has a 3D look—that is, a border
with a sunken edge
Group WS_GROUP Specifies the first control of a group of controls in which
the user can move from one control to the next with the
arrow keys. All controls defined with the WS_GROUP
style after the first control belong to the same group. The
next control with the WS_GROUP style ends the style
group and starts the next group (that is, one group ends
where the next begins).
Tab stop WS_TABSTOP Specifies a control that can receive the keyboard focus
when the user presses the TAB key. Pressing the TAB key
changes the keyboard focus to the next control with the
WS_TABSTOP style.
Static edge WS_EX_STATICEDGE Creates a window with a three-dimensional border style
intended to be used for items that do not accept user input.
Transparen WS_EX_TRANSPAREN Specifies that a window created with this style is to be
T
t transparent. That is, any windows that are beneath the
window are not obscured by the window. A window
created with this style receives WM_PAINT messages
only after all sibling windows beneath it have been
updated.
Accept WS_EX_ACCEPTFILES Specifies that a window created with this style accepts
files drag-and-drop files.
Number ES_NUMBER The edit field will only accept a positive number. A
wrong character provokes a beep.
Read only ES_READONLY Prevents the user from typing or editing text in the edit
control.
Vertical WS_VSCROLL Vertical scrollbar. This is only allowed in multi line edit
scroll fields
Horizontal WS_HSCROLL Horizontal scrollbar. This is only allowed in multiline
scroll edit fields.
Border WS_BORDER The edit field has a black border line around it.
Uppercase ES_UPPERCASE Converts the characters to uppercase as they are typed
in.
Lowercase ES_LOWERCASE Converts the characters to lowercase as they are typed
in.

Lcc-win32 User’s Manual 170


Password ES_PASSWORD Doesn’t display the characters typed in.
Visible ES_NOHIDESEL Negates the default behavior for an edit control. The
selection default behavior hides the selection when the control
loses the input focus and inverts the selection when the
control receives the input focus. If you specify
ES_NOHIDESEL, the selected text is inverted, even if
the control does not have the focus.
Horizontal WS_HSCROLL Has a horizontal scroll
scroll
Want Car. ES_WANTRETURN Specifies that a carriage return be inserted when the user
return presses the ENTER key while entering text into a multiline
edit control in a dialog box. If you do not specify this
style, pressing the ENTER key has the same effect as
pressing the dialog box’s default push button. This style
has no effect on a single-line edit control.
Auto hor. Automatically scrolls text to the right by 10 characters
scroll when the user types a character at the end of the line.
When the user presses the ENTER key, the control scrolls
all text back to position zero.
Translate ES_OEMCHARSET Converts text entered in the edit control. The text is
PC char converted from the Windows character set to the OEM
set. character set and then back to the Windows set. This
ensures proper character conversion when the
application calls the CharToOem function to convert a
Windows string in the edit control to OEM characters.
This style is most useful for edit controls that contain
filenames.
Multi-line ES_MULTILINE Designates a multiline edit control. The default is single-
line edit control.
When the multiline edit control is in a dialog box, the
default response to pressing the ENTER key is to activate the
default button. To use the ENTER key as a carriage return,
use the ES_WANTRETURN style.
When the multiline edit control is not in a dialog box and
the ES_AUTOVSCROLL style is specified, the edit
control shows as many lines as possible and scrolls
vertically when the user presses the ENTER key. If you do
not specify ES_AUTOVSCROLL, the edit control shows
as many lines as possible and beeps if the user presses the
ENTER key when no more lines can be displayed.
If you specify the ES_AUTOHSCROLL style, the
multiline edit control automatically scrolls horizontally
when the caret goes past the right edge of the control. To
start a new line, the user must press the ENTER key. If you

Lcc-win32 User’s Manual 171


do not specify ES_AUTOHSCROLL, the control
automatically wraps words to the beginning of the next
line when necessary. A new line is also started if the user
presses the ENTER key. The window size determines the
position of the word wrap. If the window size changes, the
word wrapping position changes and the text is
redisplayed.
Multiline edit controls can have scroll bars. An edit
control with scroll bars processes its own scroll bar
messages. Note that edit controls without scroll bars
scroll as described in the previous paragraphs and
process any scroll messages sent by the parent window.

Messages
Message Effect
Set focus When the dialog box receives the EN_SETFOCUS message, the callback :
DlgBoxXXXSetFocus(HWND hwnd, WPARAM wParam,LPARAM
lParam) ;
will be called.
Kill focus When the dialog box receives the EN_KILLFOCUS message the callback :
DlgBoxXXXEditFieldYYYKillFocus(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
will be called. Normally at this point you would check the contents of the
dialog box for validity. It is sometimes better to do it immediately, without
waiting for the user closing the dialog box.
Text has When the dialog box receives the EN_CHANGE message from the control,
changed the callback :
DlgBoxXXXEditFieldYYYChanged(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
will be called. This allows you to follow the input character by character if
you want it to.
Space If the user has typed so much text that the edit field has no space for holding it,
Overflow the message EN_ERRSPACE will be received. At this point, if you want it,
the callback :
DlgBoxXXXEditFieldYYYErrSpace(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
will be called. This allows you to react to that situation. It must be noted that
this was very frequent under windows 3.1, but it is virtually impossible that
this happens now.
Horz Scroll If the user has clicked in the horizontal scroll, the dialog box will receive the
EN_HSCROLL notification message from the control. You can react to this
event. In this case the callback :
DlgBoxXXXEditFieldYYYHorzScroll(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;

Lcc-win32 User’s Manual 172


will be called.
Vert Scroll If the user has clicked in the horizontal scroll, the dialog box will receive the
EN_VSCROLL notification message from the control. You can react to this
event. In this case the callback :
DlgBoxXXXEditFieldYYYVertScroll(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
will be called.
Max text This allows you to get called when the user types more text than the limit for
overflow the control. You can set this limit in the ‘Max. accepted chars’ field at the
right of the properties dialog box. The callback has the form :
DlgBoxXXXEditFieldYYYTextOverflow(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
will be called.
Init You can get called at the initialization of the dialog box, to initialize things for
this specific control. Normally this is not used. The callback has the form :
DlgBoxXXXEditFieldYYYInit(HWND hwnd, WPARAM wParam,LPARAM
lParam) ;

Validate You can establish a callback specific for this control when the user presses the
OK button. Normally this is not used, and you process all controls in the
Validate message for the whole dialog box.
DlgBoxXXXEditFieldYYYValidate(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
Note that the HWND parameter there is the hwnd of the edit field.

Radio button styles


A radio button consists of a round button and application-defined text, an icon, or a
bitmap that indicates a choice the user can make by selecting the button. An application
uses radio buttons in a group box to permit the user to choose from a set of related, but
mutually exclusive options. For example, the application might present a group of radio
buttons from which the user can select a format preference for text selected in the client
area. The user could select a left-aligned, right-aligned, or centered format by selecting
the corresponding radio button. Normally, the user can select only one option at a time
from a set of radio buttons.

Lcc-win32 User’s Manual 173


Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.
You should specify the prefix to be used for this control, and the font to be used.
Text
This text will be shown in the radio button. You can enter any text here.
Identity
The #define under which this radio button will be used in your application. The
numerical value is shown too, below.
Font
Name and size of the font used for this radio button.
Messages
Only two messages need to be handled: Th ‘Init’ message, if you want a specific callback
to be called at the initialization of the dialog box, and the ‘Click’ message, when the
radio button has been activated. This message is not received when the radio button is
deactivated, only when the transition is to the ‘on’ state. The callback is of the form:
DlgBoxXXXRadioBtnCliked(HWND hwnd, WPARAM wParam, LPARAM
lParam) ;
Styles
Button text Style Effect
Auto BS_AUTORADIOBUTTON Creates a button that is the same as a radio button,
except that when the user selects it, Windows
automatically sets the button’s check state to
checked and automatically sets the check state for

Lcc-win32 User’s Manual 174


all other buttons in the same group to unchecked.
left text BS_LEFTTEXT Places text on the left side of the radio button or
check box when combined with a radio button or
check box style.
Flat BS_FLAT The 3D appearence of the button is more flattened
than a normal push button, but very similar. For an
example see the radio buttons Init or Click in the
dialog box at the beginning of this chapter.
Visible WS_VISIBLE The radio button is visible at startup.
Disabled WS_DISABLED The radio button is disabled at startup.
Multi line BS_MULTILINE The text of the radio button can be wrapped into
several lines of text.
Client edge WS_EX_CLIENTEDGE Specifies that a window has a 3D look—that is, a
border with a sunken edge
Static edge WS_EX_STATICEDGE Creates a window with a three-dimensional border
style intended to be used for items that do not accept
user input.
Push like The look of the radio button is very similar to a
push button. It remains sunken when selected.
Tab stop WS_TABSTOP The Tab key can be used to move into the control
Help ID The button can answer the WM_HELP message.
Not supported in this version.
Transparent WS_EX_TRANSPARENT The button is transparent. Not really a good idea but
who knows ? Maybe you find a use for it.
Notify BS_NOTIFY Enables a button to send BN_DBLCLK,
BN_KILLFOCUS, and BN_SETFOCUS
notification messages to its parent window. Note
that buttons send the BN_CLICKED notification
message regardless of whether it has this style. Note
that weditres doesn’t handle this messages, so you
should process them yourself within your default
dialog box procedure.
Bitmap The radio button holds a bitmap. Not supported in
this version.
Icon The radio button holds an icon.. Not suypported yet.
Group WS_GROUP The radio button is a group separator. Not a good
idea for a radio button that should be a member of a
group of radio buttons.

Static text styles

A text static control displays text in a rectangle in one of five styles: left-aligned without
word-wrap, left aligned with word-wrap, centered, right-aligned, or « simple. »

Lcc-win32 User’s Manual 175


Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.
Text
This text will be shown in the text field. You can enter any text here.
Identity
The #define under which this control will be used in your application. The numerical
value is shown too, below.
Font
Name and size of the font used for this control.
Styles
Button text Style Effect
Left SS_LEFT Text left aligned
Center SS_CENTER Text centered
Right SS_RIGHT Text right aligned
Simple SS_SIMPLE Specifies a simple rectangle and displays a single line
of left-aligned text in the rectangle. The text line
cannot be shortened or altered in any way. The
control’s parent window or dialog box must not
process the WM_CTLCOLORSTATIC message.
One line SS_LEFTNOWORDW Specifies a simple rectangle and left-aligns the given
RAP
text in the rectangle. Tabs are expanded but words are
not wrapped. Text that extends past the end of a line is
clipped.
User item Obsolete Not longuer supported under windows 32.
Visible WS_VISIBLE Text is visible at startup.
Disabled WS_DISABLED Disabled at startup
No prefix SS_NOPREFIX Prevents interpretation of any ampersand (&)

Lcc-win32 User’s Manual 176


characters in the control’s text as accelerator prefix
characters. These are displayed with the ampersand
removed and the next character in the string
underlined. This static control style may be included
with any of the defined static controls.
Border WS_BORDER The text field has a visible border.
Client edge WS_EX_CLIENTEDGE Specifies that a window has a 3D look—that is, a
border with a sunken edge
Group WS_GROUP The text field signals a group of controls.
Tab stop WS_TABSTOP The text field can be reached with the tab key.
Normally this is not really good for a static control.
Sunken SS_SUNKEN The text has a sunken appearence
Help ID Not yet supported by weditres
Static edge WS_EX_STATICEDGE Static edge around the text

When you press the color button, at the bottom right of the text styles dialog box, the
standard dialog box for choosing a color will appear.
Weditres will generate code to handle the WM_CTLCOLORSTATIC message that will
be received by the dialog box procedure. This code will set the color of the static text to
the color you choose in the colors dialog box.
Properties of a ComboBox
A combo box consists of a list and a selection field. The list presents the options a user
can select and the selection field displays the current selection. Except in drop-down list
boxes, the selection field is an edit control and can be used to enter text not in the list.

Lcc-win32 User’s Manual 177


Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.
Text
This text will be shown in the text field. You can enter any text here.
Identity
The #define under which this combo box will be used in your application. The numerical
value is shown too, below.
Font
Name and size of the font used for this combo box.
Styles
Button label Style Effect
List always CBS_SIMPLE Displays the list box at all times. The current
visible selection in the list box is displayed in the edit
control.
List+entry field CBS_DROPDOWN The user can select an item from the list or
enter a new item in an antry field.
List only CBS_DROPDOWNLIST The user can only select an item from the list.
Visible WS_VISIBLE The control is visible at startup
Inactive WS_DISABLED The control is disabled at startup

Lcc-win32 User’s Manual 178


Group WS_GROUP The control starts a new group of controls
Tab stop WS_TABSTOP The control can be reached with the Tab key.
Sort CBS_SORT Automatically sorts the strings in the list.
Optional scroll CBS_DISABLENOSCROLL Shows a disabled vertical scroll bar in the list
bar box when the box does not contain enough
items to scroll. Without this style, the scroll
bar is hidden when the list box does not
contain enough items.
Vertical scrollbar WS_VSCROLL List has a vertical scrollbar.
Exact height CBS_NOINTEGRALHEIGHT Specifies that the size of the combo box is
exactly the size specified by the application
when it created the combo box. Normally,
Windows sizes a combo box so that it does not
display partial items.
Local memory CBS_HASSTRINGS Specifies that an owner-drawn combo box
contains items consisting of strings. The
combo box maintains the memory and address
for the strings, so the application can use the
CB_GETLBTEXT message to retrieve the text
for a particular item.
DOS character CBS_OEMCONVERT Converts text entered in the combo box edit
conversion. control. The text is converted from the
Windows character set to the DOS character
set and then back to the Windows set. This
ensures proper character conversion when the
application calls the CharToOem function to
convert a Windows string in the combo box to
DOS characters. This style is most useful for
combo boxes that contain filenames and
applies only to combo boxes created with the
CBS_SIMPLE or CBS_DROPDOWN style.
Owner draw CBS_OWNERDRAWFIXED Specifies that the owner of the list box is
fixed responsible for drawing its contents and that
the items in the list box are all the same height.
The owner window receives a
WM_MEASUREITEM message when the
combo box is created and a
WM_DRAWITEM message when a visual
aspect of the combo box has changed.
Owner draw CBS_OWNERDRAWVARIABLE Specifies that the owner of the list box is
variable responsible for drawing its contents and that
the items in the list box are variable in height.
The owner window receives a
WM_MEASUREITEM message for each item
in the combo box when you create the combo

Lcc-win32 User’s Manual 179


box ; the owner window receives a
WM_DRAWITEM message when a visual
aspect of the combo box has changed.
Automatic horz. CBS_AUTOHSCROLL Automatically scrolls the text in an edit control
scroll. to the right when the user types a character at
the end of the line. If this style is not set, only
text that fits within the rectangular boundary is
allowed
Client edge WS_EX_CLIENTEDGE Specifies that a window has a 3D look—that
is, a border with a sunken edge
Static edge WS_EX_STATICEDGE Static edge around the text
Accept files WS_EX_ACCEPTFILES Specifies that a window created with this style
accepts drag-and-drop files.
Right to left WS_EX_RIGHT Gives a window generic right-aligned
properties. This depends on the window class.
Help ID Not supported yet
Transparent WS_EX_TRANSPARENT Not very useful for a combo box
Left scrollbar Displays the vertical scrollbar at the left
Modal frame WS_EX_DLGMODALFRAME Encloses the combo in a modal frame
Notify

Messages
Button Windows Description
message
Init WM_INITDLG You can get called at the initialization of the dialog box, to
initialize things for this specific control. Normally this is
not used. The callback has the form :
DlgXXXComboYYYInit(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;

Hiding list CBN_CLOSEUP This message is sent when the list box of a combo box has
been closed.If you want to be notified when this message
arrives, weditres will generate a callback of the form :
DlgXXXComboYYYHideList(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Double CBN_DBLCLK This message is sent when the user double-clicks a string in
click the list box of a combo box. If you want to take a special
action here, weditres will generate a callback of the form :
DlgXXXComboYYYDoubleClick(HWND
hwnd,WPARAM wParam,LPARAM lParam) ;
Show list CBN_DROPDOWN This message is sent when the list box of a combo box is
about to be made visible.If you want to take a special
action, weditres will generate a callback of the form :

Lcc-win32 User’s Manual 180


DlgXXXComboYYYShowList(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Text CBN_EDITUPDATE
This message is sent when the edit control portion of a
update combo box is about to display altered text. This
notification message is sent after the control has formatted
the text, but before it displays the text. The generated
callback has the form :
DlgXXXComboYYYTextUpdate(HWND
hwnd,WPARAM wParam,LPARAM lParam) ;
Text has CBN_EDITCHANGE
This message is sent after the user has taken an action that
changed may have altered the text in the edit control portion of a
combo box. Unlike the CBN_EDITUPDATE notification
message, this notification message is sent after Windows
updates the screen. The callback has the form :
DlgXXXComboYYYTextChange(HWND
hwnd,WPARAM wParam,LPARAM lParam) ;
Selection CBN_SELENDCANCEL
This message is sent when the user selects an item, but
cancel then selects another control or closes the dialog box. It
indicates the user’s initial selection is to be ignored. The
callback has the form :
DlgXXXComboYYYSelCancel(HWND
hwnd,WPARAM wParam,LPARAM lParam) ;
No more CBN_ERRSPACE
This message is sent when a combo box cannot allocate
memory enough memory to meet a specific request. The generated
callback has the form :
DlgXXXComboYYYErrSpace(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Get focus CBN_SETFOCUS
This message is sent when a combo box receives the
keyboard focus. The generated callback has the form :
DlgXXXComboYYYSetFocus(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Kill focus CBN_KILLFOCUS
This message is sent when a combo box looses the
keyboard focus. The generated callback has the form :
DlgXXXComboYYYKillFocus(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Sel CBN_SELCHANGE
This message is sent when the selection in the list box of a
changed combo box is about to be changed as a result of the user
either clicking in the list box or changing the selection by
using the arrow keys. The callback generated has the
form :
DlgXXXComboYYYSelChange(HWND

Lcc-win32 User’s Manual 181


hwnd,WPARAM wParam,LPARAM lParam) ;
Sel CBN_SELENDOK
This message is sent when the user selects a list item, or
validate selects an item and then closes the list. It indicates that the
user’s selection is to be processed. The callback has the
form :
DlgXXXComboYYYSelValidate(HWND
hwnd,WPARAM wParam,LPARAM lParam) ;

Properties of a List Box


List box items can be represented by text strings, bitmaps, or both. If the list box is not
large enough to display all the list box items at once, the list box can provide a scroll bar.
The user maneuvers through the list box items, scrolling the list when necessary, and
selects or removes the selection from items. Selecting a list box item changes its visual
appearance, usually by changing the text and background colors to the colors specified by
the operating system metrics for selected items. When the user selects an item or removes
the selection from an item, Windows sends a notification message to the parent window
of the list box.

Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.

Lcc-win32 User’s Manual 182


Identity
The #define under which this list box will be used in your application. This is the define
you use when you access the control from your program. The numerical value is shown
too, below.
Font
Name and size of the font used for this list box.
Styles
Button Style Effect
Standard LBS_STADARD Sorts strings in the list box alphabetically. The parent
window receives an input message whenever the user
clicks or double-clicks a string. The list box has borders
on all sides.
Border WS_BORDER Has a border around it.
Sort LBS_SORT Sorts strings in the list box alphabetically.
Notify LBS_NOTIFY Notifies the parent window with an input message
whenever the user clicks or double-clicks a string in the
list box.
Vert. Scroll WS_VSCROLL Has a vertical scroll (default)
Horz scroll WS_HSCROLL Has a horizontal scroll
Use tab tops LBS_USETABSTOPS Enables a list box to recognize and expand tab characters
when drawing its strings. The default tab positions are 32
dialog box units. A dialog box unit is a horizontal or
vertical distance. One horizontal dialog box unit is equal
to 0.25 of the current dialog box base-width unit.
Windows calculates these units based on the height and
width of the current system font. The GetDialogBaseUnits
function returns the current dialog box base units in
pixels.
No redraw LBS_NOREDRAW Specifies that the list box’s appearance is not updated
when changes are made. You can change this style by
sending a WM_SETREDRAW message at any time.
Disable no LBS_DISABLENOSCRO Shows a disabled vertical scroll bar for the list box when
LL
scroll the box does not contain enough items to scroll. If you do
not specify this style, the scroll bar is hidden when the list
box does not contain enough items.
No integral LBS_NOINTEGRALHEIG Specifies that the size of the list box is exactly the size
HT
height specified by the application when it created the list box.
Normally, Windows sizes a list box so that the list box
does not display partial items.
Want keyb. LBS_WANTKEYBOARDI Specifies that the owner of the list box receives
NPUT
input WM_VKEYTOITEM messages whenever the user
presses a key and the list box has the input focus. This
enables an application to perform special processing on
the keyboard input.

Lcc-win32 User’s Manual 183


Owner draw LBS_OWNERDRAWFIX Specifies that the owner of the list box is responsible for
ED
fixed drawing its contents and that the items in the list box are
the same height. The owner window receives a
WM_MEASUREITEM message when the list box is
created and a WM_DRAWITEM message when a visual
aspect of the list box has changed.
Owner draw LBS_OWNERDRAWVAR Specifies that the owner of the list box is responsible for
IABLE
variable drawing its contents and that the items in the list box are
variable in height. The owner window receives a
WM_MEASUREITEM message for each item in the
combo box when the combo box is created and a
WM_DRAWITEM message when a visual aspect of the
combo box has changed.
Has strings LBS_HASSTRINGS Specifies that a list box contains items consisting of
strings. The list box maintains the memory and addresses
for the strings so that the application can use the
LB_GETTEXT message to retrieve the text for a
particular item. By default, all list boxes except owner-
drawn list boxes have this style. You can create an owner-
drawn list box either with or without this style.
Multi LBS_MULTICOLUMN Specifies a multicolumn list box that is scrolled
column horizontally. The LB_SETCOLUMNWIDTH message
sets the width of the columns.
Multiple LBS_MULTISEL Turns string selection on or off each time the user clicks
selection or double-clicks a string in the list box. The user can
select any number of strings.
Extended LBS_EXTSEL Allows multiple items to be selected by using the SHIFT
selection key and the mouse or special key combinations.
Help ID Not supported in this version
Visible WS_VISIBLE The list box is visible at startup
Disabled WS_DISABLED The list box is disabled at startup.
Group WS_GROUP The list box is the start of a new group of controls.
Tab stops WS_TABSTOP The list box can be reached with the tab key.
Static edge WS_EX_STATICEDGE Static edge around the control.
Transparent WS_EX_TRANSPAREN Transparent list box...
T
Client edge WS_EX_CLIENTEDGE Client edge around client area.
Modal List box has a modal frame around it. Not recommended.
frame
Drag list List box accepts dragging of items.
box
No LBS_NOSEL The list box doesn’t allow any selection.
selection

Lcc-win32 User’s Manual 184


Messages
Button Message Description
Init WM_INITDLG You can get called at the initialization of the dialog box,
to initialize things for this specific control. Normally this
is not used. The callback has the form :
DlgXXXListYYYInit(HWND hwnd, WPARAM
wParam,LPARAM lParam) ;
Get focus LBN_SETFOCUS
This message is sent when the list box receives the
keyboard focus. The generated callback has the form :
DlgXXXListYYYSetFocus(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Double LBN_DBLCLK
This message is sent when the user has clicked in an
click item of the list box. The generated callback has the
form :
DlgXXXListYYYDoubleClick(HWND
hwnd,WPARAM wParam,LPARAM lParam) ;
Selection LBN_SELCHANGE
This message is sent when the selection in the list box
changed changes. The generated callback has the form :
DlgXXXListYYYSelChange(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Selection LBN_SELCANCEL
This message is sent when the user has cancelled the
cancel selection in the list box. The generated callback has the
form :
DlgXXXListYYYSetCancel(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Space LBN_ERRSPACE
This message is sent when the list box runs out of
overflow memory. The generated callback has the form :
DlgXXXListYYYErrSpace(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;
Kill focus LBN_KILLFOCUS
The message is sent when the list box looses the focus.
The generated callback has the form :
DlgXXXListYYYKillFocus(HWND hwnd,WPARAM
wParam,LPARAM lParam) ;

Drag list box messages


Drag list boxes use the following structure.
Typedef struct {
UINT uNotification ;
HWND hWnd ;
POINT ptCursor ;
} DRAGLISTINFO, *LPDRAGLISTINFO ;

Lcc-win32 User’s Manual 185


Members
uNotification Notification code that specifies the type of drag event. This member can be
one of the following values :
Value Meaning
DL_BEGINDRAG The user has clicked the left mouse button on a list item.
DL_CANCELDRAG The user has canceled the drag operation by clicking the
right mouse button or pressing the ESC key.
DL_DRAGGING The user has moved the mouse while dragging an item.
DL_DROPPED The user has released the left mouse button, completing a
drag operation.
hWnd Handle to drag list box.
ptCursor POINT structure that contains the current x- and y-coordinates of the mouse
cursor
Here is a description of the callbacks generated by weditres for a list box drag operation.
Button Message Description
Begin drag DL_BEGINDRAG This message notifies the parent window of a drag list
box that the user has clicked the left mouse button on a
list item. The callback for this message is :
long DlgXXXListYYYBeginDrag(HWND hwnd,
DRAGLISTINFO * dlInfo) ;
You should return either one (go on and start dragging) or
zero (cancel the whole operation).
Cancel DL_CANCELDRAG This message arrives if the user has canceled the drag
Drag operation. The callback has the form :
long DlgXXXListYYYCancelDrag(HWND
hwnd,DRAGLISTINFO * dlInfo) ;
The return value is ignored.
Dragging DL_DRAGGING This message arrives continuosly as the user proceeds
with the drag operation. The callback has the form :
long DlgXXXListYYYDragging(HWND
hwnd,DRAGLISTINFO *dlInfo) ;
The return value determines the type of mouse cursor
that the drag list should set ; it can be the
DL_STOPCURSOR, DL_COPYCURSOR, or
DL_MOVECURSOR value. If any other value is
returned, the cursor does not change.
End Drag DL_DROPPED This message arrives when the user ends the drag
operation. The callback has the form :
long DlgXXXListYYYEndDrag(HWND
hwnd,DRAGLISTINFO *dlInfo) ;

Lcc-win32 User’s Manual 186


Normally you should set a callback to all the messages sent. It would be a bad
programming practice to leave the problem of whether the user can start a drag operation
for instance, to the default dialog box procedure that always returns zero. This would
mean that the user could never start a drag operation...
Check box Styles
A check box consists of a square box and application-defined text , an icon, or a bitmap
that indicates a choice the user can make by selecting the button. Applications display
check boxes in a group box to permit the user to choose from a set of related, but
independent options.

Note that if you are editing a .res file, and you haven’t defined a project for weditres,
only a portion of this dialog will be visible.
You should specify the prefix to be used for this control, and the font to be used.
Text
This text will be shown in the check box. You can enter any text here up to 255 chars.
Identity
The #define under which this check box will be used in your application. This is the
define you use when you call the IsDlgButtonChecked function for instance. The
numerical value is shown too, below.
Font
Name and size of the font used for this check box.

Lcc-win32 User’s Manual 187


Initial state
If you check this check box, weditres will generate a call to the windows API
CheckDlgButton, to check the check button when initializing the dialog box.
Messages
The ‘Click’ message is received when the check box has been activated. This message is
not received when the check box is deactivated, only when the transition is to the ‘on’
state. The callback is of the form:
DlgBoxXXXCheckBoxCliked(HWND hwnd, WPARAM wParam, LPARAM
lParam) ;
Styles
Button text Style Effect
Automatic BS_AUTOCHECKBOX Creates a button that is the same as a check box,
except that the check state automatically toggles
between checked and unchecked each time the user
selects the check box.
Three state BS_AUTO3STATE Creates a button that is the same as a three-state
check box, except that the box changes its state
when the user selects it. The state cycles through
checked, grayed, and unchecked.
Left text BS_LEFT Places text on the left side of the check box
Visible WS_VISIBLE The check box is visible at startup.
Disabled WS_DISABLED The check box is disabled at startup.
Multi line BS_MULTILINE The text of the check box can be wrapped into
several lines of text.
Client edge WS_EX_CLIENTEDGE Specifies that a window has a 3D look—that is, a
border with a sunken edge
Static edge WS_EX_STATICEDGE Creates a window with a three-dimensional border
style intended to be used for items that do not accept
user input.
Push like The look of the check box is very similar to a push
button. It remains sunken when selected.
Tab stop WS_TABSTOP The Tab key can be used to move into the control
Help ID . Not supported in this version.
Transparent WS_EX_TRANSPARENT The button is transparent. Not really a good idea for
an item that should receive user input...
Notify BS_NOTIFY Enables a button to send BN_DBLCLK,
BN_KILLFOCUS, and BN_SETFOCUS
notification messages to its parent window. Note
that buttons send the BN_CLICKED notification
message regardless of whether it has this style. Note
that weditres doesn’t handle this messages, so you
should process them yourself within your default
dialog box procedure.
Group WS_GROUP The check box is a group separator.

Lcc-win32 User’s Manual 188


Group box styles
A group box is a rectangle that surrounds a set of controls, such as check boxes or radio
buttons, with application-defined text (label) in its upper left corner. The sole purpose of
a group box is to organize controls related by a common purpose (usually indicated by
the label).

The styles of a group box are described in detail in the documentation of any of the other
controls.
There are no callbacks, since the group box sends no messages, and receives no input.
You will notice that group boxes carry the elements that they contain in the editor, when
you move them. Modifying the ‘sticky group boxes’ check box in the configuration of the
editor can change this behavior.

Lcc-win32 User’s Manual 189


White Rectangle styles

This control, like the group box above, is just for grouping purposes. It receives
no input and sends no messages.
Black rectangle styles

This control, like the group box above, is just for grouping purposes. It receives no input
and sends no messages.

Lcc-win32 User’s Manual 190


Horizontal scroll

Vertical scroll styles

These controls are seldom used by themselves in dialog boxes. They can send
only one message: WM_HSCROLL or WM_VSCROLL.
Since there is only one message, no suffix will be added to the name of the
control procedure as specified in the ‘Callbacks’ edit field. The procedure would
be then :
void DlgXXXScrollYYY(HWND hwnd,UINT message,WPARAM
wParam,LPARAM lParam) ;
The message argumet can be either WM_VSCROLL or WM_HSCROLL. This
way you can use a single callback procedure for both messages.
Spin control styles
To the user, a spin control and its buddy window often look like a single control. You can
specify that an up-down control automatically position itself next to its buddy window
and that it automatically set the caption of the buddy window to its current position. For
example, you can use a spin control with an edit control to prompt the user for numeric
input.

Lcc-win32 User’s Manual 191


Spin controls are called up and down controls in the documentation from Microsoft. Thy
existed before under windows 31 under the name of spin controls, and I didn’t feel like
changing their name just because Microsoft decided a new name. Many of us
implemented those under windows 3.1. This explains the UDS prefix for the spin control
styles: Up Down Style.
Here is an example configuration:

The spin control is at the left of the entry field. Pressing the arrows you can
increment/decrement the edit field contents.
The Identity and Value fields have the same meaning than in the other controls.
Styles

Static styles
Input field Window style Purpose
Visible WS_VISIBLE Makes the control visible at startup
Disabled WS_DISABLED Disables the control at startup
Group WS_GROUP Marks the start of a group of controls
Tab stop WS_TABSTOP Makes this control reachable with the TAB key.
Static edge WS_EX_STATICEDGE Has a static edge around it
Client edge WS_EX_CLIENTEDGE Has an edge around the client area
Help ID Not implemented in this version

Lcc-win32 User’s Manual 192


Select buddy UDS_AUTOBUDDY Automatically selects the previous window in the Z
window order as the spin control’s buddy window. Please be
automatically sure that the window selected is a good one. For
instance, if the Z order indicates a Group box, the
spin control will attach itself to a group box, not a
very useful thing... Use the <Group> menu option of
weditres to select the right control.
No thousands UDS_NOTHOUSANDS Does not insert a thousands separator between every
three decimal digits.
Set buddy integer UDS_SETBUDDYINT Causes the spin control to set the text of the buddy
window (using the WM_SETTEXT message) when the
position changes. The text consists of the position
formatted as a decimal or hexadecimal string.
Wrap beyond UDS_WRAP Causes the position to « wrap » if it is incremented or
selected rage decremented beyond the ending or beginning of the
range.
Use keyboard UDS_ARROWKEYS Causes the up-down control to increment and
arrow keys decrement the position when the UP ARROW and DOWN
ARROW keys are pressed.
Unattached UDS_ALIGNNONE No alignment to the buddy window
Left aligned UDS_ALIGNLEFT Positions the spin control next to the left edge of the
buddy window. The buddy window is moved to the
right and its width decreased to accommodate the
width of the spin control.
Right aligned UDS_ALIGNRIGHT Positions the spin control next to the right edge of the
buddy window. The width of the buddy window is
decreased to accommodate the width of the spin
control.

Messages
Input field Window Purpose
message
Value will change UDN_DELTAPOS The operating system sends the UDN_DELTAPOS
notification message to the parent window of an spin
control when the position of the control is about to
change. This happens when the user requests a
change in the value by pressing the control’s up or
down arrow. The UDN_DELTAPOS message is sent before
the WM_VSCROLL or WM_HSCROLL message that actually
changes the control’s position. This lets you examine,
allow, modify, or disallow the change. return TRUE
in your callback in response to this message to
prevent the change in the control’s position. Return
FALSE to allow the change
The callback will be of the form :

Lcc-win32 User’s Manual 193


int DlgXSpinYDeltaPos(HWND hwnd,PNMHDR
pnmhdr) ;
Value has WM_HSCROLL or This notifies you of the new value. The generated
WM_VSCROLL
changed callback has the form :
int DlgXXSpinYY(HWND hwnd,UINT
msg,WPARAM wParam,LPARAM lParam) ;
Since the message received is passed to the callback,
you can diffrentiate between horizontal and vertical
spin controls.
Range UDM_SETRANGE Sets the upper and lower range for the spin control.

The tree control

Here we have a dialog with a big tree control in it. This is a very complex control, that can
do a lot of things but needs a lot of effort to get it right. Weditres can help you a bit by
generating some of the code that needs to be written.
The properties box of the tree control matches this element’s complexity. Here it is:

Lcc-win32 User’s Manual 194


Styles
Besides the normal window styles like visible, client edge, etc etc, a tree control can have the
following styles of its own :
Description Style Purpose
Has lines to join TVS_HASLINES Enhances the representation of the hierarchy by
items drawing lines that link child items to their
parent item. This style does not link items at the
root of the hierarchy.
Has lines at root TVS_LINESATROOT When combined with the TVS_HASLINES
position style, this forces the tree control to draw lines at
the root of the hierarchy.
Buttons to TVS_HASBUTTONS The user can expand or collapse a parent item’s
indicate item state list of child items by double_clicking the parent
item. A tree view control that has this style adds
a button to the left of each parent item. The user
can click the bitton once instead of double
clicking the parent item to expand or collapse
the child. Again, this styme does not add
buttons at the root. You should specify the style
TVS_LINESATROOT to get buttons at the root

Lcc-win32 User’s Manual 195


of the hierarchy.
Edit labels TVS_EDITLABELS This style makes it possible for the user to edit
the labels of tree view items.
Show always the TVS_SHOWSELALWAYS This style forces a selected item to remain
selected item selected when the control loses focus.
Disable drag and TVS_DISABLEDRAGANDRO This style disables the drag and drop feature.
P
drop

Messages :
Description Message Purpose
Begin drag TVN_BEGINDRAG Notifies the program that the user has begun a drag
operation with the left mouse. The callback function will
be of the form :
xxxBeginDrag(HWND,NM_TREEVIEW *) ;
Begin right TVN_BEINRDRAG The user has begun a drag operation with the right mouse
button drag button. The callback will be of the form :
xxxBeginRDrag(HWND,NM_TREEVIEW *) ;
Begin label TVN_BEGINLABELEDIT The user has begun to edit a tree label. The callback will
editing be of the form :
xxxBeginLabelEdit(HWND,TV_DISPINFO *) ;
End label TVN_ENDLABELEDIT The user has ended the editing of a label in an item. The
editing callback will be of the form :
xxxEndLabelEdit(HWND,TV_DISPINFO *) ;
Needs TVN_GETDISPINFO Requests information that the tree view control requires
display to display an item. The callback has the form :
information xxxGetDispInfo(HWND,TV_DISPINFO *) ;
Set display TVN_SETDISPINFO Informs the parent window that it should set the display
information information it has about an item. The callback has the
form :
xxxSetDispInfo(HWND,TV_DISPINFO *) ;
Selection has TVN_SELCHANGED Informs the parent window that the selection has changed
changed from one item to another. The callback has the form :
xxxSelChanged(HWND,NM_TREEVIEW *) ;
Selection is TVN_SELCHANGING Informs the parent window that the selection is about to
changing change. The callback as the form :
xxxSelChanging(HWND,NM_TREEVIEW *) ;
Item is TVN_ITEMEXPANDING Informs the parent window that an item is going to
expanding expand or collapse. The callback has the form :
xxxItemExpanding(HWND,NM_TREEVIEW *) ;
Item has TVN_ITEMEXPANDED Informs the parent window that an item has been
been expanded. The callback has the form :
expanded xxxItemExpanded(HWND,NM_TREEVIEW *) ;
Key has TVN_KEYDOWN A keyboard event. The callback has the form :
been pressed xxxKeyDown(HWND,TV_KEYDOWN *) ;

Lcc-win32 User’s Manual 196


Return WM_NOTIFY The return key has been pressed. The callback has the
form :
xxxReturnPressed(HWND,NMHDR *) ;

The parameter ‘hwnd’ in all messages above is the handle of the dialog window. You can get
the handle of the tree control by using the GetDlgItem primitive.
The structures used are the following:
1) NM_TREEVIEW

Contains information about a tree view notification message.


typedef struct _NM_TREEVIEW {
NMHDR hdr ;
UINT action ;
TV_ITEM itemOld ;
TV_ITEM itemNew ;
POINT ptDrag ;
} NM_TREEVIEW ;
typedef NM_TREEVIEW *LPNM_TREEVIEW ;
Members description :
NMHDR hdr
Specifies an NMHDR structure. The code member of the NMHDR structure can one of
the following notification codes that identify the message being sent :
TVN_BEGINDRAG, TVN_BEGINRDRAG, TVN_DELETEITEM, TVN_ITEMEXPANDED,
TVN_ITEMEXPANDING, TVN_SELCHANGED, TVN_SELCHANGING.

UINT action
Specifies a notification-specific action flag.

TV_ITEM itemOld
Specifies a TV_ITEM structure that contains information about the old item state. This
member is zero for notification messages that do not use it.

TV_ITEM itemNew
Specifies a TV_ITEM structure that contains information about the new item state.
This member is zero for notification messages that do not use it.

POINT ptDrag
Specifies a POINT structure that contains the client coordinates of the mouse at the
time the event occurred that caused the notification message to be sent.

2) TV_ITEM
The TV_ITEM structure specifies or receives attributes of a tree-view item.
typedef struct _NM_TREEVIEW {
NMHDR hdr ;
UINT action ;
TV_ITEM itemOld ;
TV_ITEM itemNew ;
POINT ptDrag ;
} NM_TREEVIEW ;

Lcc-win32 User’s Manual 197


Members description :
NMHDR hdr
Specifies an NMHDR structure. The code member of the NMHDR structure can one of
the following notification codes that identify the message being sent :
TVN_BEGINDRAG, TVN_BEGINRDRAG, TVN_DELETEITEM, TVN_ITEMEXPANDED,
TVN_ITEMEXPANDING, TVN_SELCHANGED, TVN_SELCHANGING.

UINT action
Specifies a notification-specific action flag.

TV_ITEM itemOld
Specifies a TV_ITEM structure that contains information about the old item state. This
member is zero for notification messages that do not use it.
itemNew
Specifies a TV_ITEM structure that contains information about the new item state.
This member is zero for notification messages that do not use it.
ptDrag
Specifies a POINT structure that contains the client coordinates of the mouse at the
time the event occurred that caused the notification message to be sent.

3) NMHDR
typedef struct tagNMHDR {
HWND hwndFrom ;
UINT idFrom ;
UINT code ;
} NMHDR ;
Members description :
hwndFrom
Handle to control sending message. In the above examples is the handle of the tree
control.
idFrom
Identifier of control sending message. In the case above, this would be the id of the
tree control.
code
Specifies the notification code.

4) TV_DISPINFO :
typedef struct _TV_DISPINFO { tvdi
NMHDR hdr ;
TV_ITEM item ;
} TV_DISPINFO ;
Handling the Begin/End drag.
Here is an example of a callback function that handles the begin drag message, adapted
from the documentation of MSDN.
// MyTreeViewBeginDrag - begins dragging an item in a tree view control.
// hwndTV - handle to the image list.
// lpnmtv - address of information about the item being dragged.

Lcc-win32 User’s Manual 198


void MyTreeViewBeginDrag(HWND hwndTV, LPNMTREEVIEW lpnmtv)
{
HIMAGELIST himl ; // handle to image list
RECT rcItem ; // bounding rectangle of item
DWORD dwLevel ; // heading level of item
DWORD dwIndent ; // amount that child items are
indented

// Tell the tree view control to create an image to use for dragging.
himl = TreeView_CreateDragImage(hwndTV, lpnmtv-
>itemNew.hItem) ;
// Get the bounding rectangle of the item being dragged.
TreeView_GetItemRect(hwndTV, lpnmtv->itemNew.hItem,
&rcItem, TRUE) ;
// Get the heading level and the amount that the child items are indented.
dwLevel = lpnmtv->itemNew.lParam ;
dwIndent = (DWORD) SendMessage(hwndTV, TVM_GETINDENT,
0, 0) ;
// Start the drag operation. This is not a function call, it is just a macro,
defined in win.h
ImageList_BeginDrag(himl, 0, 0, 0) ;
// Hide the mouse cursor, and direct mouse input to the parent window.
ShowCursor(FALSE) ;
// Now capture the mouse to follow the drag operation.
SetCapture(GetParent(hwndTV)) ;
// Sets a global variable to notify the functions that are going to be called
later when dragging is active.
g_fDragging = TRUE ;
return ;
}

OK, that is the start. What about later ?


You have surely remarked that we have captured the mouse in that function above. To
follow the item in its long journey we just follow the WM_MOUSEMOVE messages. To
handle those messages you should check the ‘All’ check box in the properties dialog of
the dialog box that contains the tree control, and handle the mouse move message like
this :
// Dlg_MouseMove - drags an item in a tree view control,
// highlighting the item that is the target.
// hwndParent - handle to the parent window.
// hwndTV - handle to the tree view control.
// xCur and yCur - x- and y-coordinates of the mouse cursor.
void Dlg_MouseMove(HWND hwndParent, HWND hwndTV, LONG xCur,
LONG yCur)
{
HTREEITEM htiTarget ; // handle to target item
TVHITTESTINFO tvht ; // hit test information
if (g_fDragging) { // the global flag that we have set above.
// Drag the item to the current position of the mouse cursor.
ImageList_DragMove(xCur, yCur) ;
// Find out if the cursor is on the item. If it is, highlight

Lcc-win32 User’s Manual 199


// the item as a drop target.
tvht.pt.x = xCur ;
tvht.pt.y = yCur ;
if ((htiTarget = TreeView_HitTest(hwndTV, &tvht)) != NULL) {
TreeView_SelectDropTarget(hwndTV, htiTarget) ;
}
}
return ;
}
When the control arrives finally at the destination we do :
// Main_OnLButtonUp - stops dragging a tree view item, releases the
// mouse capture, and shows the mouse cursor. This is called when the
// dialog procedure receives the WM_LBUTTONUP message
// Global variable
// g_fDragging - indicates whether a drag operation is underway.
void DlgOnLButtonUp(void)
{
if (g_fDragging) {
ImageList_EndDrag() ;
ReleaseCapture() ;
ShowCursor(TRUE) ;
g_fDragging = FALSE ;
}
return ;
}
The slider control
This control allows you to input analog values in an easy to understand fashion. Here is a
screen shot of different sliders with different attributes.
:

Lcc-win32 User’s Manual 200


Sliders can be drawn in vertical or horizontal position, with rounded or not pointers, with
ticks above or below, etc.

To control the different options you use the following properties dialog box :

The slider interfaces with the dialog box that contains it only with the WM_HSCROLL
or the WM_VSCROLL message. Weditres will add code to handle those messages and
call your callback procedure when the slider wants to say to you something.

You can add a range of values, and Weditres will generate code to set that range of
values at run time during the initialization of the dialog box.
The other styles shown are the usual ones already explained in all the other controls
(visible, tab stop, etc). They will not be repeated here.
The date calendar control
This control allows the user to choose a date. Here is an example.

Lcc-win32 User’s Manual 201


The styles that you can choose for this control are displayed in the following dialog box:

Description Style Purpose


Allow dynamic MCS_DAYSTATE The month calendar will send
query of days to MCN_GETDAYSTATE notifications to
display in bold request information about which days should be
displayed in bold. For more information about
supporting this style, see Processing the
MCN_GETDAYSTATE Notification Message
Multiple day MCS_MULTISELECT The month calendar will allow the user to select
selection a range of dates within the control. By default,
the maximum range is one week. You can
change the maximum range that can be selected
by using the MCM_SETMAXSELCOUNT

Lcc-win32 User’s Manual 202


message.
Do not display MCS_NOTODAY The month calendar control will not display the
the “today” line "today" date at the bottom of the control.
Do not display a MCS_NOTODAYCIRCL The month calendar control will not circle the
circle around the E "today" date.
selected day
Display the MCS_WEEKNUMBERS The month calendar control will display week
number of the numbers (1-52) to the left of each row of days.
week in the year Week 1 is defined as the first week that
contains at least four days.

Processing the MCN_GETDAYSTATE Notification Message


Month calendar controls send the MCN_GETDAYSTATE notification message to
request information about how the days within the visible months should be displayed.
The following application-defined function, DoNotify, processes
MCN_GETDAYSTATE by filling an array of MONTHDAYSTATE values to highlight
the 15th day of each month.
DoNotify extracts the number of MONTHDAYSTATE values needed from the
cDayState member of the NMDAYSTATE structure that lParam points to. It then loops
to set the 15th bit in each element of the array, using the application-defined BOLDDAY
macro.
BOOL WINAPI DoNotify(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam)
{
#define BOLDDAY(ds,iDay) if(iDay>0 && iDay<32)\
(ds)|=(0x00000001<<(iDay-1))

#define lpnmDS ((NMDAYSTATE *)lParam)


#define MAX_MONTHS 12

MONTHDAYSTATE mds[MAX_MONTHS];
INT i, iMax;
LPNMHDR hdr = (LPNMHDR)lParam;

switch(hdr->code){
case MCN_GETDAYSTATE:
iMax=lpnmDS->cDayState;

for(i=0;i<iMax;i++){
mds[i] = (MONTHDAYSTATE)0;
BOLDDAY(mds[i],15);
}
lpnmDS->prgDayState = mds;
break;
}
return FALSE;
}

Lcc-win32 User’s Manual 203


Preparing the MONTHDAYSTATE Array
Both the MCM_SETDAYSTATE message and MCN_GETDAYSTATE notification
message require an array of MONTHDAYSTATE values to determine how dates will be
displayed. Each month that the control displays must have a corresponding element
within the array.
To support these messages, your application must properly prepare the array. The
following is a simple macro that sets a bit in a MONTHDAYSTATE value for a given
day within that month.
#define BOLDDAY(ds,iDay) if(iDay>0 && iDay<32)\
(ds)|=(0x00000001<<(iDay-1))
Using this macro, an application could simply loop through an array of important dates,
setting bits within the corresponding array elements. This approach is not the most
efficient, of course, but works well for many purposes. As long as your application sets
MONTHDAYSTATE bits appropriately, it does not matter how those bits were set.

Processing this message within the framework.


The framework will not generate code for this message. You should setup a procedure
that catches all messages for your window, and within that procedure, treat the answer to
this message as indicated above. To setup such a procedure open the properties of the
dialog box as a whole, and then check the “ALL” button in the messages you want to
handle. This way, you will become all messages. Within that procedure you should
handle the WM_NOTIFY message, where this notifications arrive.

The menu editor


The menu editor shows you the menu in the form of a tree. Each top level pop-up
corresponds to the top level items of the menu being edited.

To add a menu item just type insert (the ‘ins’ key), selecting before the menu item above
the one you will introduce.

You do the same for introducing a new menu item in a pop-up.

You can test your menu to see it in ‘action’ by choosing ‘test’ in the ‘File’ option of the
main menu of the menu editor.

Besides the tree with the items, you will se the following dialog box floating around.
Here you enter the name of the menu, its associated symbol (#define), and its value.

In the ‘Options’ group you can change the appearance of the menu item, either for a
normal menu item, or for a popup menu. Do not forget to press ‘Apply’ when you are
done with changes.

Lcc-win32 User’s Manual 204


Kommentar [jn1]:

The string table editor


This utility allows you to edit the string tables contained in your resource file. String
tables are a resource kind for storing character strings in the resource section of the
executable instead of using string literal in the program text itself.
The original motivation for this was the ever-growing need under windows 3.0 to have
more memory with the space severely limited to 64K for the stack, all character strings,
and all static data. This lead to trying to make more space in the data segment by putting
the strings somewhere else, and loading /unloading them as needed. Kommentar [jn2]:
But there are many other beneficial side effects, so the usage of string tables has stayed
with us even in windows 98. One of the good side effects is the separation from message
text from the code itself, so that if you need to translate the program into another
language you do not need to edit the source files, but just the resource file, what is far
easier for the person who is doing the translation, since he/she doesn’t have to be a
programmer AND a foreign language expert, a rare combination.

Lcc-win32 User’s Manual 205


The string editor presents a simple interface. You double click in a string to edit one, or
you can add/delete strings, as you may esteem necessary.
The ‘Save’ button doesn’t save the modified resources to the disk immediately, but just
writes it to the resource file in memory. It will get written to disk when you exit weditres.

The accelerator table editor


An accelerator table is an association from keyboard keys combinations with a command
item. This can be a menu command item, but this is not necessarily the case. When the
user presses the defined keyboard keys combination (Ctrl+Shift+N, for example), the
window procedure associated with the accelerator table will receive a WM_COMMAND
message, containing the numerical value that you associated with this keyboard
combination.

Fo instance, when you want that Ctrl+Shift+N do something special in your application,
you define an accelerator key like

1) In your header file:

#define MENU_STOPCALCULATING 3000

Lcc-win32 User’s Manual 206


2) In your resource file:

"^N" MENU_STOPCALCULATING SHIFT CONTROL

3) In your window procedure:

switch(message) {
...
case WM_COMMAND:
switch(LOWORD(wParam)) {
case MENU_STOPCALCULATING:
if (CalculationsStarted()) {
StopCals();
}
break;
}
}

You can have a menu item somewhere, with an item 'Stop calculations" but this is not
mandatory. You receive from windows this message when you do not forget to add the
TranslateMessage step in that famous MainLoop of your window procedure.

You can edit this table graphically from Weditres. To call the corresponding editor you
should either use the menu item in the 'Objects' bar, or use the directory tree. There, (if
there is already a resource table defined in the application), you will find your table. Just
double click in its name and the accelerator editor will be called automatically.

The editor for this resource type is very simple. It will show you at startup a list of all
defined items. You can perform the usual actions (Add, Modify, and Delete), with three
buttons at the lower right.

If there is no accelerator table defined, the editor will automatically start the 'Add' action,
supposing you are not very interested in contemplating an empty list. The Add/Change
dialog box edits a single line of the accelerator table.

Instead of showing here yet another screen shot, I think it is better to spend more time
explaining the concepts behind this.

Each entry in the table consists of:


• A numerical value. This is the result of pressing the combination of keys.
• An associated numerical identifier.
• A set of flags that determine how the numerical value is interpreted.

You can define either plain Ascii keys combinations, or you can set the 'Virtual Key' flag,
that indicates to Windows that the value is to be interpreted as a value for a virtual key,
i.e. a key like VK_F1, VK_BACK, etc. All those values are defined in <windows.h>, and

Lcc-win32 User’s Manual 207


they give the programmer a view of the keyboard that is independent from the type of
keyboard that is used.

It is important to be clear that the ASCII/VIRTUAL KEY flags are alternatives (hence
the radio buttons in the editor). You can only use one of those.

You can add flags specifying:


CONTROL: That flag means that the CONTROL key has to be pressed for the keys
combination to be valid.
SHIFT: Ditto but with the key Shift.
ALT: The same for the Alt key.
NOINVERT: This means that the menu item associated with the same identifier should
not be highlighted if it exists at all.

These flags are not alternatives, they can all be set for the same key combination. They
can be set/unset using the checkboxes in the dialog box that edits each line of the table.

The accelerator resource is named following the same conventions as the naming of all
other resource types: either with a character string or an identifier. You load the resource
using the LoadAccelerators window function that searches for the specified
accelerator table.

Lcc-win32 User’s Manual 208


CMS
CMS is a sub-system of Wedit for saving all modifications made to a module over a long
period of time (months or even years). Saving a full file copy after each modification
would lead to an enormous waste of space and to a management problem for all the files
created. CMS avoids this problem by saving the last version stored and then the
difference from the last version to the preceding one and so on, to the first version stored
in the system. This is achieved with an editing script that indicates to the editor, which
lines to add and which lines to remove from each version. CMS saves only the lines that
changed. Thus, for example, instead of storing two files of 50K each time you change a
line and save, it will store 50K + some bytes for each line modified. The gains are
considerable.
The basic operations of CMS are:
• SAVE (also known as 'PUT')
• GET
When saving, CMS compares the new version with the last version stored in the system
and deduces the editing script. When getting an older version, Wedit begins with the last
version, and with the help of the stored edit scripts, will reconstruct the preceding
versions until the version that has been asked for. For instance, if the last version is 1.8
and you ask for 1.5, Wedit will retrieve 1.7, and from there 1.6, and then 1.5.
Only the basic features have been discussed here. There are numerous support functions
to help you manage the differences, to visualize them, etc.
Each version is numbered consecutively beginning with the 1.1, the first one. The second
is the 1.2, the third 1.3, etc.
Each CMS file has an access list, initially empty, meaning that anyone is authorized to
use the file. To reduce the number of people who should have access to a given source
file, add the names of the authorized people to the access list.
Each project is considered the work of many people. The manager of the project should
enter the names of the people working in it.

Changing the CMS Project Parameters


A CMS project contains two primary elements:
• A list of files you are working with
• A list of people who are members of your team

Using the ‘Versions’ tab from the ‘Options’ menu (‘Configuration’), you can change
these parameters.

Lcc-win32 User’s Manual 209


You can reach this
dialog box by
selecting the
‘Versions’ tab in the
‘Configuration’ menu
item.
The ‘Configuration’
option is in the
‘Project-
Configuration’ menu
bar.

The options for 'get' and 'put' are very similar. You should specify if you always want
CMS to lock the file after a get or a put operation, if you want to see the progress display,
and if you want CMS to erase the original version of a file after it is stored under CMS.
The other options concern setting the CMS files with a read only attribute
(recommended) and if the user's name is case sensitive (not recommended).
Get: Retrieving a Version from a CMS File
This operation consists of reading a version in the corresponding CMS file. This can
produce access conflicts in a multi-user environment because the file can be locked. CMS
forbids two people from working with the same source at the same time.

After asking for a CMS file, the 'Get' option displays the following dialog box:

Lcc-win32 User’s Manual 210


To get the version you want, select it from those displayed. To obtain more information
about the displayed version, press the 'Details' button. When you select a version, a
confirmation dialog box appears:

You can change the destination directory by editing the corresponding entry field.

Retrieving all Default Versions from a Project


This option will automatically build all versions from a CMS directory.

Lcc-win32 User’s Manual 211


To delete a file from the list, select it and then press 'Erase.

Saving a File under CMS

This operation takes an existing file as input and stores it under the same name in the CMS
file in the CMS directory. If the file does not belong to the project file list, it will be added.
You reach this
dialog box by
using the ‘Put’
option in the
‘Versions’
menu bar.

Lcc-win32 User’s Manual 212


The different options allow you to keep the source file, instead of relying on the CMS
system (recommended) to lock the file so that only you can access it. It also allows you to
avoid the messages CMS shows when working.

Saving All Files


It is tedious to maintain a mental list of all modified files to be stored in the CMS project. To
avoid this problem, the 'Save all' option will search all files belonging to the project and store
them automatically if they differ from the last version stored in CMS.
After scanning all project files for changes, this option will present the following dialog box:
You can reach this
dialog box by choosing
the ‘Put all’ option in the
‘Versions’ menu bar.

The files shown are the files that have been changed.

Searching for Differences between Two Versions of the Same


Module
The 'Differences' option from the CMS menu is very similar to the 'Diff' option in the
utilities menu. It starts by asking you to select two versions of the module. If you select only
one, CMS will assume that the other version is the file of the same name that should be in
the current directory.

Lcc-win32 User’s Manual 213


Viewing all Versions of a Given File
This option is designed to give you an overview of the revisions stored in a CMS file.
The information is displayed in the following dialog box:

Displayed are the default version, the symbolic name of the revisions (if any) and the
lock status. If you select the 'Details' button, the following display appears:

Lcc-win32 User’s Manual 214


By using the buttons at the right, you can move to the next or the previous revision.

Visualizing the Log Files


Each time a put operation is run, you have a special field to describe the modifications made
to the source code. This information can be displayed for all versions in the following dialog
box:

To visualize the different entries, select a line of the list box at the left.
Building a Release
A release is understood in this context as a coherent set of files and versions at a given
moment in the development of a software system. A client receives a version of the
executable, for instance, and a release captures all versions and all files that have been used
to build that executable.

Lcc-win32 User’s Manual 215


CMS proposes the list of the files that have been entered as belonging to the current project,
each using its default version.
It is important to remember that nothing is saved. CMS registers only the set of files and
versions and nothing more. To ensure that everything is correct, you should use the 'Save all'
option from the CMS menu.

You can modify the version used by CMS or exclude a given file from the release.

Lcc-win32 User’s Manual 216


Inspecting the Stored Releases
You can visualize the releases defined in the system by choosing the 'See distribution'
option from the CMS Menu. The information is presented as follows:

To see the contents of each distribution, click under its name in the list box to the left.
The contents of the other controls will be updated accordingly.

Retrieving a Release
Use the 'Get release' option from the 'CMS' menu. First you are prompted to choose a
revision with a list box very similar to the 'See distribution' described above. When you
have selected a release, the following dialog box appears:

You can change the destination directory here.

Lcc-win32 User’s Manual 217


The Application Wizard

The purpose of this utility is to generate a skeleton of your Windows application. The
problem with Windows programming is that, a large amount of code must be written just
to display a window. This frustrates novice Windows programmers and skilled
professionals alike. Normally, a ‘generic’ skeleton is used, which is modified with a text
editor. This is cumbersome and error prone. It is better to generate a customized skeleton
using a set of templates with a utility that is designed precisely for this operation.

Triggering the application wizard is very simple: Type its name or answer ‘yes’ when
Wedit asks you, when creating a new project.

In the first page of the wizard, you should fill in the following fields:

Name Purpose
Name of the project Wedit fills this in when the wizard is called from Wedit. This
will be used to derive the name of the window classes and the
file names.
Single window This is an application that displays only one main window.
Multiple window This is an application that uses the MDI standard. A standard
MDI menu will be generated and the code for resizing the
main window will be slightly modified when a status bar is
active.
Dialog based This is not implemented in this version.
Dll This is a DLL application. The wizard will generate a LibMain
only. No window will be created or other visual controls.
Status bar at the The application (either MDI or SDI) will have a status bar
bottom where you can display messages or other information to the
user. The wizard will generate code to show in the status bar
an explicative text of each menu option as the user moves the
mouse among different menu items.
Toolbar The application has a toolbar, which can be floating or fixed to
the main application window
TCPIP The wizard will generate code at the entry of the program
(after the main window is created) to call the WSAStartup API
to setup the network, and will generate a call to WSACleanup
before the program exists. If you use this option, it is
imperative to add ws2_32.lib to the libraries used by your
project, since lcclnk does not include that library by default.
About dialog box The wizard will generate code for a callback for a standard
‘About’ dialog box, will modify the OnCommand function to
accept the IDM_ABOUT command, and before generating the
code, the wizard will call the resource editor to allow you to

Lcc-win32 User’s Manual 218


edit the aspect of the dialog box. You should design a dialog
box that at least has a Close button and/or a button with the
IDOK id (1).
Path for the template Normally, the wizard will look for its templates in the
directory \lcc\lib\wizard directory. If you want to customize the
templates, copy them to another directory and then enter the
path here. It is impossible to know in advance all possible
needs of the users of lcc-win32. This provides an escape hatch
so that you can add functionality that was not foreseen at
design time.
Output directory The directory to which the output files will be written.
WinMain file The main C source file for the generated code. It defaults to
<ProjectName.c>.
Resources file The resource file. It defaults to <ProjectName.rc>.
Header file The file containing the definitions for the symbols that will be
needed in the application. It defaults to <ProjectNamewiz.h>.

Class Definition

To be able to open a window, a window of a specific class has to be registered with the
system. The purpose of the first page of the wizard is to let you define exactly the
window class. If this looks too complicated to you, press the continue button and leave
the default values. In most cases, the default values are appropriate to your needs.

Input field Purpose


Class name The name of the main window class. This can be any name. It
will default to <ProjectNameWndClass>.
Byte align client area Aligns the Window's client area on a byte boundary (in the x
direction) to enhance performance during drawing operations.
This style affects the width of the window and its horizontal
placement on the display.
Global class An application global class is a window class registered by a
dynamic-link library (DLL) and available to all applications
in the system. For example, your DLL can call the
RegisterClassEx function to register a window class that
defines a custom control as an application global class so that
all applications can create instances of the custom control.
In Windows, all window classes are process specific. An
application can create a global class by creating the window
class in a DLL and listing the name of the DLL in the registry
under the appropriate keys.
When a process starts, the system loads the specified DLL in
the context of the newly started process before calling the
main function in that process. The DLL must register the
class during its initialization procedure and must specify the
CS_GLOBALCLASS style. After a class has been registered,

Lcc-win32 User’s Manual 219


any application can use it to create any number of windows
belonging to that class.
Windows does not automatically destroy a class when the DLL
that registered it is unloaded. For this reason, the Windows exit
procedure of the DLL should call the UnregisterClass
function to remove the class.
Byte align window Aligns the window on a byte boundary (in the x direction) to
area enhance performance during operations that involve moving
or sizing the window. This style affects the width of the
window and its horizontal placement on the display.
Class DC Allocates one device context to be shared by all windows in
the class.
Window DC Allocates a unique device context for each window in the
class.
Redraw when resized Specifies that the entire window is to be redrawn if a
movement or size adjustment changes the width or height of
the client area.
Save bits Saves, as a bitmap, the portion of the screen image obscured
by a window. Windows uses the saved bitmap to re-create the
screen image when the window is removed. Windows
displays the bitmap at its original location and does not send
WM_PAINT messages to windows obscured by the window
if other screen actions have not invalidated the stored image.
Use this style for small windows that are displayed briefly
and then removed before other screen activity takes place (for
example, menus or dialog boxes). This style increases the
time required to display the window, because the operating
system must first allocate memory to store the bitmap.
Accept double-clicks Instructs Windows to send a double-click message to the
window procedure when the user double-clicks the mouse
while the cursor is within a window belonging to the class.
No ‘close’ in system Disables the Close command on the System menu.
menu
Callback function. The name of the function that will handle the messages sent
to the windows of this class. Defaults to <MainWndProc>.
Extra bytes for the Number of bytes to allocate in the class structure to store
class class specific user data.
Extra bytes for the Number of bytes to allocate in the window structure to store
window window specific data.
Icon Name of the icon. Using the ‘browse’ button you can enter an
icon file name here.
Cursor Cursor to be used with this class. Using the browse button

Lcc-win32 User’s Manual 220


allows you to input a file name here.
Background color Background color of the window.

Toolbar Definition

You should click on the button you want to have in your toolbar. If you do not choose at
least a single button, the toolbar will not be generated.

Styles

Input field Description


Floating Creates a toolbar detached from the main window.
Position at the top The toolbar is attached to the top of the client area of the main
window.
Position at the bottom The toolbar is attached to the bottom of the client area of the
main window. This cannot be used with the status bar style.
Multi line The toolbar can have several lines.
Has ToolTips The toolbar will show explicative strings when the mouse
passes above any of its buttons.
Allow customization The user can add/delete toolbar buttons from the toolbar. The
system provides a standard dialog box for this.
Large icons The bitmaps in the toolbar are large.
Small icons The bitmaps in the toolbar are small.
Save tool bar position The position of the toolbar will be saved in the applications
at application exit registry key.
Add custom button This has not yet been implemented.

Creating a Window
The wizard generates a procedure for creating the main application window. If this looks
too complicated, do not alter these parameters; simply press the Continue button. In most
cases, these default parameters will be what you want.
The documentation for each of the fields is included below.
The window class should be defined in the preceding panel. It is displayed here for
information purposes only.

Input field Purpose


Registry key Here you should enter the registry key that the application will
use for storing application specific data. Currently, the wizard
will use and create code to handle this field only if the main
window or the toolbar position should be saved.
Window Title Here you should enter the text to be shown in the frame of the
window.

Lcc-win32 User’s Manual 221


Border Determines whether the window should have a border. It
corresponds to the WS_BORDER window style.
Caption Determines whether the window should have a caption.
Corresponds to the WS_CAPTION window style. Implies
WS_BORDER.
Child Determines whether the window is a child window. Corresponds
to the WS_CHILD window style. This style cannot be used with
the WS_POPUP window style.
Clip children Excludes the area occupied by child windows when drawing
occurs within the parent window. This style is used when creating
the parent window. It is on by default. Corresponds to the
WS_CLIPCHILDREN window style.
Clip siblings Clips child windows relative to each other; that is, when a
particular child window receives a WM_PAINT message, the
WS_CLIPSIBLINGS style clips all other overlapping child
windows out of the region of the child window to be updated. If
WS_CLIPSIBLINGS is not specified and child windows overlap,
it is possible, when drawing within the client area of a child
window, to draw within the client area of a neighboring child
window. Corresponds to the WS_CLIPSIBLINGS window style.
Disabled Determines whether the window should be disabled at startup.
Normally you should not use this option, since a disabled window
will receive no input.
Dialog Frame Creates a window that has a border of a style typically used with
dialog boxes. A window with this style cannot have a title bar.
H Scroll Determines whether the window should have a horizontal scroll
bar. It should not be used if you have used the status bar feature,
since the scroll bar will overlay the status bar.
V scroll Determines whether the window should have a vertical scroll bar.
This option should not be used with a status bar.
Maximize Determines whether the window should have a maximize box.
Note that this is not the WS_MAXIMIZE style, but the
WS_MAXIMIZEBOX.
Minimize Determines whether the window should have a minimize box.
Note that this is not the WS_MINIMIZE style but the
WS_MINIMIZEBOX.
Popup Determines whether to create a popup window. Note that this
cannot be used with the WS_CHILD style.
Sizable Determines whether the window can be resized.
Sys menu Determines whether the window should have a system menu.
Visible Determines whether the window should be visible at startup.
Normally this should be on.
Static edge Determines whether the window should have a static edge.
Normally, this style is not used with main windows. Corresponds
to the WS_EX_STATICEDGE style.

Lcc-win32 User’s Manual 222


Window edge Determines whether the window should have an edge around it.
Client edge Determines whether the window should have an edge around its
client area.
Left scrollbar Determines whether the vertical scrollbar should be at the left.
Normally not used.
Transparent Determines whether the window should let you see the windows
underneath it.
Accept files Determines whether the window should handle the
WM_ACCEPTFILES message.
Tool window Window with a smaller caption. Normally not used with main
windows.
Topmost Determines whether the window should be always visible.
Save window Determines whether the window position in screen coordinates
position in registry should be saved in the registry and restored when the application
restarts.

Using the Wizard


Once the code has been generated, it must then be modified. Following is a short series of
technical tips to allow you to start off quickly.

Action What to do
Adding a new • Modify the .rc file and add the menu item you want. The item
menu item should have a line of text and a numeric identifier. See the other
menu items for ideas on how this is done.
• This new numeric identifier should be #defined in the global
application header file, that is #included in the .rc file.
• Modify the MainWndProc_OnCommand function, adding a
new case in its switch statement. This new case should be the
same numerical identifier you entered in the header file for this
menu item.
Adding a dialog • Design the dialog box with Weditres. Normally, you will have
box several dialog boxes in your application. Therefore, it is best to
do is to start a new project and modify the .rc file with an
#include statement of the .dlg files generated by Weditres.
Assume that you name your dialog box set mydialogs. Weditres
will generate a mydialogs.dlg file. You should then add the line
#include « mydialogs.dlg » to the .rc file. This will allow you to
add several dialogs later always using the same names.
• After the design of the dialog box is finished, you have to call it
up using the DialogBox windows primitive.
• The DialogBox primitive needs a callback function that will be
called up to handle the events in the dialog box. You have the
choice of having Weditres generate that procedure for you, or
writing your own. If you let Weditres do it; it will generate a file

Lcc-win32 User’s Manual 223


called mydialogs.c containing all procedures for your dialog
boxes. Include this file in the project of Wedit.
• Normally, a dialog box is called after the user has clicked on a
menu item.
Adding code to • To handle the messages that Windows sends you, you should go
handle windows to the MainWndProc procedure and add cases to handle the
events messages. For instance, if you are interested in the keys the user
is typing at the keyboard, you can handle the message
WM_CHAR. To do this, add a case WM_CHAR to the big
message switch of the Windows procedure.
Updating the • The status bar can be updated using the function
status bar UpdateStatusBar, which is automatically generated by the
wizard. Normally, something similar to
« UpdateStatusBar(« New text »,0,0) ; » would be written. This
means that the first field of the status bar (field zero) will be
changed, and that there are no special flags to be given.
Adding a new • You should repeat the code in the InitApplication function to
window class add a new window class. You need a new window procedure
too, to handle the messages to this new window, after you create
it. You can use the skeleton in the MainWndProc procedure as a
model.
Adding an icon • Add the statement myicon ICON myiconfile.ico to the .rc file.

Lcc-win32 User’s Manual 224


Advanced
Compiling a DLL
A DLL is a Dynamic Link Library. This acronym means that the library is loaded when
the program starts by the loader, and not linked statically with the program code like with
a normal library.

To build such a library:


1) Define your project as a DLL project. If you are using lcclnk directly in the
command line, you should add the –DLL option to the linker.
This is done in the project definition panel by checking the corresponding radio button.
2) In your code, mark the functions of the DLL you want to export as such.
An “exported” function is a function that is visible outside the DLL, and can be called
from other places in the program. There are two ways of doing this.

The first is by declaring it explicitly in the program text:


int __declspec(dllexport) MyFunction(int f) { … }

This instructs the compiler to add a special instruction for the linker to add this name (in
this case MyFunction ) to the export table of the DLL.

The second method is to build a definition file (.def) where you write the list of exported
functions from the DLL. This is just an ASCII text file whose extension must be .def,
with the list of the exported functions of the DLL. An example of such a file is:

EXPORTS
MyFunction

The first line must be the keyword EXPORTS, followed by the names of the exported
functions, one in each line.
The formal syntax is:

IDENTIFIER [DATA]

IDENTIFIER is a placeholder for the name of the exported symbol. It can be followed by
the keyword DATA, which means that the exported symbol is not a function, but a data
item. This is important to specify, since the entries generated in the import library are not
the same.
3) You should build an import library.
This is done automatically by lcclnk. If you want to do it manually, you should
issue the following command:

buildlib mydll.exp mydll.lib

Lcc-win32 User’s Manual 225


The ‘buildlib’ utility takes an ASCII description of the DLL exported entries in a
similar format as the .def described above, and will output a library that can be
used with the linker to build the finished product.25
4) You should declare the imported symbols in the executable that uses the DLL.
This means, add an “extern” declaration in your code or header file.
5) You should link your executable with the import library.

You are then finished.

To debug your DLL with Wedit’s debugger, change the name of the executable to start in
the project configuration tab ‘Debugger’ and write the name of the executable that uses
your DLL. Then, follow the executable until a DLL function call appears. Next, press F8
to enter the function in the DLL. Remember that both the executable and the DLL should
have been compiled with debug information turned on!

DLLs should have a DllMain or LibMain entry point function, that is called up by the
system when the DLL is loaded or unloaded, and allows you to initialize/cleanup
elements. This function MUST be declared as follows:

#include <windows.h>
/*----------------------------------------------------------
------------
Procedure: LibMain
Purpose: DLL entry point called up when a DLL is loaded or
unloaded by a process, and when new threads are
created or destroyed.
Input: hDllInst: Instance handle of the DLL
fdwReason: event: attach/detach
lpvReserved: not used
Output: The return value is used only when the fdwReason is

25 The format of the .exp file is as follows :

The first line should contain the name of the DLL you are using, i.e., Mydll.dll or whatever. Since it is a
file name, case is NOT significant. No path information should be included. Just the name of the DLL.
The following lines should contain three columns, separated by tabs or spaces.
The first one is the name of the symbol as published by the compiler, i.e., if your symbol is MyFunction,
the column should contain _MyFunction. In the case of a _stdcall function it would be
_MyFunction@12 .
The second one should contain the name of the symbol as exported from the DLL. Normally this should
be the same as the column 1, but sometimes you want to export the functions without the leading
underscore, for instance for using them with another language processor like Visual Basic.
The third column is optional. If present it should contain the column DATA, meaning that this is an
exported DATA symbol.
The .exp file is generated automatically by lcclnk.

Lcc-win32 User’s Manual 226


DLL_PROCESS_ATTACH. True means that the DLL has
successfully loaded. False means that the DLL is unable
to initialize and should be unloaded immediately.
Errors:
------------------------------------------------------------
----------*/
BOOL WINAPI LibMain(HINSTANCE hDLL,DWORD Reason,LPVOID
Reserved)
{
switch (Reason) // Code indicating the reason for this function being
called up.
{
case DLL_PROCESS_ATTACH:
// The DLL is being loaded for the first time by a given process.
// Perform per-process initialization here. If the initialization
// is successful, return TRUE; if unsuccessful, return FALSE.
break;
case DLL_PROCESS_DETACH:
// The DLL is being unloaded by a given process. Do any
// pre-process clean up here, such as undoing what was done in
// DLL_PROCESS_ATTACH. The return value is ignored.
break;
case DLL_THREAD_ATTACH:
// A thread is being created in a process that has already loaded
// this DLL. Perform any per-thread initialization here. The
// return value is ignored.
break;
case DLL_THREAD_DETACH:
// A thread is exiting cleanly in a process that has already
// loaded this DLL. Perform any per-thread clean up here. The
// return value is ignored.
break;
}
return TRUE;
}
The Definitions File (.def)
This file is needed to define the exports of a DLL or mark the data sections of an
executable as shared, i.e., usable by other programs.

The different directives in this file are:


• EXPORTS. This is followed by the exports list. The exports list should have an
entrgy in each line, for instance: MyFunction or _MyFunction=Function, to change
the name of the exported symbol.
• SECTION. This should be followed by one single line containing DATA SHARED,
if you want to make the data sections (.data AND .bss) shared.
• STACKSIZE. This is ignored and is here for compatibility with older versions of the
.def files.

Lcc-win32 User’s Manual 227


• DESCRIPTION. This is ignored and is here for compatibility with older versions of
the .def files.
An example of this is the following file:

Library Mydll
EXPORTS
Myfunction
_MyOtherFunction=Other
SECTION
DATA SHARED

The first line must contain the name of the DLL or file that you are building, but this is
not required. The Exports section contains two exports: A function called “MyFunction”,
and a function called “Other”, which is associated to the “MyOtherFunction” procedure,
and which will not be visible with that name, since its exported name will be “Other”.
The SECTION part defines the data sections (.data and .bss sections) as shared, i.e.,
accessible by other programs.

Using the Intrinsics Utility


Lcc-win32 understands special macro definitions called ‘intrinsics’. These constructs will
be seen as normal function calls by the front end of the compiler, but will be inline
expanded by the back-end. You can add your own intrinsic macros to the system,
allowing you to use the power and speed of assembly language within the context of a
more powerful and safer high level language.

Inlining the strlen Function


Assume that the strlen function of the C library is too slow for your needs. Instead of
generating:
pushl Arg
call _strlen
addl $4,%esp

you would like to generate inline the following code:


; Inlined strlen. The input argument is in ECX and points to
the
; character string
orl $-1,%eax
loop:
inc %eax
cmpb $0,(%ecx,%eax)
jnz loop

This function should then be inlined by the compiler. The C interface would be:
_strlen(str);

The prototype must be:

Lcc-win32 User’s Manual 228


extern _stdcall _strlen(char *);

The compiler recognizes intrinsic macros because they have an underscore as the first
character of their names, they are declared _stdcall, and they appear in the intrinsics
table. Functions that begin with an underscore are few, thereby avoiding the need to look
up the intrinsics table for each function call, which would slow down compilation speed.
Take the file intrin.c in the sources of lcc-win32 and modify the intrinsics table. Its
declaration is in the middle of the file and looks like this:

static INTRINSICS intrinsicTable[] = {


{"_fsincos",2, 0, fsincos, NULL },
{"_bswap", 1, 0, bswap, bswapArgs
},
many declarations omitted…
{"_reduceLtb",3, 0, redCmpLtb,
paddArgs },
{"_mmxDotProduct",3,0, mmxDotProd,
paddArgs },
{"_emms",0, 0, emms, NULL
},
{NULL, 0, 0, 0, 0 }
};

Before the last line, add the following line:


{"_strlen",1, 0, strlenGen, strlenArgs
},
telling the system that you want an intrinsic called “_strlen”, which takes one argument,
whose code will be generated by the function strlenGen(), and the arguments assigned to
their respective registers in the function strlenArgs(). These functions should assign the
registers in which you want the arguments to the inline macro and generate the code for
the body of the macro. Basically, this macros are seen as special calls by the compiler,
which — instead of generating a push instruction — will call your <arguments> function,
which should set the right fields in each node passed to it, to make the code generator
later generate a move to the registers specified.

Note that all intrinsics should start with an underscore to avoid conflicting with user
space names.

When a call to this function is detected by the compiler, you will first be called when
“pushing” the arguments. Here is the function strlenArgs() then:

static Symbol strlenArgs(Node p)


{
Symbol r=NULL;

Lcc-win32 User’s Manual 229


//The global ArgumentsIndex is zero before each call.
The compiler
//takes care of that.
switch (ArgumentsIndex) {
case 0: // First argument pushed, from right to left!
if (p->x.nestedCall == 0) {
Symbol w;
r = SetRegister(p,intreg[ECX]);
}
break;
}
// We have seen another argument.
ArgumentsIndex++;
// Assign the register to this expression.
if (p->x.nestedCall == 0 && r)
p->syms[2] = r;
// Should never be more than one argument
if (ArgumentsIndex == 1)
ArgumentsIndex = 0;
return r;
}

You see that in several places, there is a test:


if (p->x.nestedCall == 0)
This means that there should be check for a nested call sequence within the arguments,
i.e., the following C expression:
strlen( SomeFunction() );
In the case of strlen, this does not change anything important, the result of the function
will be in EAX anyway. But suppose that you defined a macro with two arguments, for
example, some special form of addition sadd(a,b).
In this case, you would assign the second argument (from left to right) to ECX, and the
first to EAX. Consider then the case of:
sadd( SomeFunction(),5);
If you would assign 5 to ECX, then the call SomeFunction(), would destroy the contents
of ECX during the call! This means that when the compiler detects a call within argument
passing, all arguments WILL BE in the stack, and your code generating function should
take care of placing them into the right registers before proceeding. In the case of strlen,
this could seldom occur, but its important to see how this would work in general.
Note too that the argument function should increase the global argument counter for each
argument, and reset it to zero when its done. Again, this is not necessary for strlen, but
for macros that use more arguments, this should be done each time.
The SetRegister function assigns a register. Following is its short body:
Symbol SetRegister(Node p,Symbol r)
{
Symbol w;
w = p->kids[0]->syms[2];
if (w->x.regnode == NULL || w->x.regnode->vbl == NULL)
p->kids[0]->syms[2] = r;

Lcc-win32 User’s Manual 230


return r;
}

This function tests that in the given node, the left child is not already assigned to a
register. It will assign the register only if this is not the case.

You then go to the center of the routine: Generating code for the strlen utility.

static Symbol strlenGen(Node p)


{
static int labelCount;
First, check if you should pop your arguments. If yes, pop them into the right registers.
if (p->x.nestedCall) {
print("\tpopl\t%%ecx\n");
}
Then generate the code for the strlen routine. Note that the % sign is used by the
assembler to mark a register, but your print() function also uses it to mark (as printf) the
beginning of an argument. You must double them to circumvent this collision.

1) Set the counter to minus one.


print("\torl\t$-1,%%eax\n");
2) Generate the label for this instance. All labels must be unique. The easiest way to
ensure that a new label is generated is to number them consecutively using a counter. To
avoid colliding with other labels, use a unique prefix too.
print("_$strlen%d:\n",labelCount);
3) Then generate the code for the body of the loop searching for the character zero.
print("\tinc\t%%eax\n");
4) Note the dollar before the immediate constant.
print("\tcmpb\t$0,(%%ecx,%%eax)\n");
5) Generate the jump, incrementing your loop counter afterwards.
print("\tjnz\t_$strlen%d\n",labelCount++);
You are done; the result is in eax, which is correct. Finish your function. Note that no
pops are needed, since the ones completed at the beginning (possibly) are only to
compensate for the pushes that the compiler generated.
}

Compile the compiler and obtain a new compiler that will recognize the macro just
created.

In general, you can use ECX, EDX, and EAX as desired. The contents of EBX, ESI, EBP
and EDI should always be saved. If you destroy them “unpredictable results” will surely
occur.

Next, write a test function for your new compiler:

#include <stdio.h>
#ifdef MACRO
int _stdcall _strlen(char *);

Lcc-win32 User’s Manual 231


#define strlen _strlen
#else
int strlen(char *);
#endif
int main(int argc, char *argv[])
{
if (argc > 1)
printf("Length of \"%s\" is %d\n", argv[1],
strlen(argv[1]));
return 0;
}

In the C source, we use the conditional MACRO to signify if we should use our macro, or
just generate a call to the normal strlen procedure. We compile this with our new
compiler, and add the –S parameter to see what is being generated.

lcc –S –DMACRO tstrlen.c

The assembly is then:

_main:
pushl %ebp
movl %esp,%ebp
pushl %edi
.line 9
.line 10
cmpl $1,8(%ebp)
jle _$2
.line 11
movl 12(%ebp),%edi
; Your argument gets assigned to ECX, as your strlenArgs
function
; defined
movl 4(%edi),%ecx
; This is the beginning of your macro body
orl $-1,%eax
; This is your generated label
_$strlen0:
inc %eax
cmpb $0,(%ecx,%eax)
jnz _$strlen0
; Your macro ends here, leaving its results in EAX
pushl %eax
movl 12(%ebp),%edi
pushl 4(%edi)
pushl $_$4
call _printf
addl $12,%esp
_$2:
.line 12
xor %eax,%eax
.line 13

Lcc-win32 User’s Manual 232


popl %edi
popl %ebp
ret
You can see that there is absolutely no call overhead. The arguments are assigned to the
right registers in your function strlenArgs, and the body is expanded inline by strlenGen.

Then, link your executable:


D:\lcc\src74\test>lcclnk tstrlen.obj
D:\lcc\src74\test>tstrlen abcde
The length of "abcde" is 5
D:\lcc\src74\test>

Here is the strlenGen() function again for clarity.

static void strlenGen(Node p)


{
static int labelCount;
if (p->x.nestedCall) {
print("\tpopl\t%%ecx\n");
}
print("\torl\t$-1,%%eax\n");
print("_$strlen%d:\n",labelCount);
print("\tinc\t%%eax\n");
print("\tcmpb\t$0,(%%ecx,%%eax)\n");
print("\tjnz\t_$strlen%d\n",labelCount++);
}
Another Example: Inlining the strchr Function
To demonstrate a function with two arguments, inline the strchr function. This
function should return a pointer to the first occurrence of the given character in a
string, or NULL, if the character does not appear in the string. The implementation
could be like this:
_strchr:
movb (%eax),%dl // read a character
cmpb %cl,%dl // compare it to searched for char
je _strchrexit // exit if found with pointer to char as result
incl %eax // move pointer to next char
orb %dl,%dl // test for end of string
jne strchr // if not zero continue loop
xorl %eax,%eax // Not found. Zero result
strchrexit :

Scan the characters looking for either zero (end of the string) or the given char. The
pointer to the string will be in EAX, and the character to be searched for will be in
ECX. Use EDX as a scratch register. Next, write the strchr function for assigning the
arguments. It is:
static Symbol strchrArgs(Node p)
{

Lcc-win32 User’s Manual 233


Symbol r=NULL;
switch (ArgumentsIndex) {
case 0: // First argument (from right to left) char to be searched. Put it in ECX
if (p->x.nestedCall == 0) {
r = SetRegister(p,intreg[ECX]);
}
break;
case 1: // Second argument: pointer to the string. Put it in EAX
if (p->x.nestedCall == 0) {
r = SetRegister(p,intreg[EAX]);
}
break;
}
ArgumentsIndex++;
if (p->x.nestedCall == 0)
p->syms[2] = r;
if (ArgumentsIndex == 2)
ArgumentsIndex = 0;
return r;
}
Next, write the generating function. Note that two labels are needed. The function is:

static void strchrGen(Node p)


{
static int labelCount;
if (p->x.nestedCall) {
print("\tpopl\t%%ecx\n");
}
print("_$strchr%d:\n",labelCount);
print("\tmovb\t(%%eax),%%dl\n");
print("\tcmpb\t%%cl,%%dl\n");
print("\tje\t_$strchr%d\n",labelCount+1);
print("\tinc\t%%eax\n");
print("\torb\t%%dl,%%dl\n");
print("\tjne\t_$strchr%d\n",labelCount);
print("\txorl\t%%eax,%%eax\n");
print("_$strchr%d:\n",labelCount+1);
labelCount += 2;
}
The Dynamic Loader
This utility allows you to load an object file from disk and link it to a running executable.
This facility consists of the following parts:
• The dynloader.dll file, which should be in your PATH variable
• The bind utility

The dynloader.dll exports three functions that are of interest here:

1. LoadObjectFile

Lcc-win32 User’s Manual 234


2. GetProcedureAddress
3. UnloadObjectFile

The interface is very similar to that of LoadLibrary, since the functionality is quite
similar.

The dynamic loader operates by opening the given object, allocating space in RAM for
the data and the code stored in there, copying the contents of the data and code sections,
then fixing up everything.

To resolve external references, the loader relies first on the symbol table of the running
executable. If that symbol table exists, it will be used to resolve external references from
the object file.

If the symbol table is absent in the running executable, or a symbol is found that does not
match any executable symbols, the dynamic loader will rely on the imports table
generated by the bind utility. This table contains the DLLs used by the object file, and all
the imported functions that are needed.

The bind utility will construct this table from the “apilist.txt” file, which is present in the
lcc-win32 distribution in the “lib” directory. This file contains a list of all known DLLs
and their exported functions. Using this list, the bind utility appends a list of needed
DLLs to the object file, that will be used by the dynloader.dll library.

Note that if you wish to add a DLL of your own to the list, you can do so by modifying
apilist.txt.

Lcc-win32 User’s Manual 235


Loading an Object File
An object file is loaded using the LoadObjectFile function. The result can be either
NULL, meaning the object file could not be found, or a pointer to an OBJECT_FILE
structure, containing information about the loaded object. Please note that the
members of the structure will probably change in future releases, so it is not a very
good idea to use them in your code. You can still look at them and they are provided
for debugging purposes.
Getting a Function Pointer
This is accomplished with the GetProcedureAddress function. The pointer returned (that
can be NULL if the name is not found) should be cast to match the function prototype.
Note that the name of the procedure to be found should match the name as exported from
the object file, i.e., you should add the leading underscore and the _stdcall decoration if
any. For instance for the function
void hello(void)
you should pass _hello to the loader. For a _stdcall function, you should add ‘@’ and
the size of the function stack.
Unloading the Object File
This is accomplished using the UnloadObjectFile function. All memory used by the
object file and its descriptors is reclaimed. You should ensure that no further uses of
the object file occur.

A Complete Example
#include <dynloader.h>
int main(void)
{
OBJECT_FILE *obj = LoadObjectFile("hello.obj");
void (*fn)(void);

fn = GetProcedureAddress(obj,"_hello");
(*fn)();
UnloadObjectFile(obj);
return 0;
}

Eiffel Support within lcc-win32

Eiffel support is still in a very early stage within the lcc-win32 system. Still, there are
many things that are working.

Lcc-win32 User’s Manual 236


Wedit uses as its Eiffel compiler, the implementation of Dominique Colnet and Olivier
Zendra, the “SmallEiffel” compiler. It is free of charge and can be downloaded from:
http://smalleiffel.loria.fr.

To build an Eiffel project, you should add to your new project files with a .e extension.
This will tell Wedit that the compiler is ‘compile’, the name of the SmallEiffel compiler.

The configuration is set up under the following tab:

You should enter the name of the root class, and the name of the creation procedure for
that root class on which defaults to ‘make’. The name of each compiler option is the same
as the one used by the Eiffel compiler. Please look at the documentation that comes with
the compiler for more information.

The debugger works with the generated executable, and the commands are the same as
for the C language: F2 to set a breakpoint, F4 to skip calls and advance to the next line,
and F8 to follow calls.

Lcc-win32 User’s Manual 237


Frequently Asked Questions (FAQs)
1) I get an "undefined reference to "_foo@12". What do I do ?
This means that the linker is missing the definitions of a library or that you have
forgotten to add a source file in the list of sources. You should add the library where the
definition of foo is (ignore the leading underscore, and anything after the '@').
2) How do I add a library to the project?
Go to the main menu in the 'options' menu bar. There choose 'Configuration'. The
Configuration tab opens. In this tab, choose the 'Linker' tab. There you will find an entry
field with 'Additional Libraries'. Write in the name of your library. For lcc libraries, you
do not need to indicate the path. For other libraries you should indicate it.
3) I still get an undefined to _xxx even if I do include the library.
This can happen when you use a _stdcall function, but forget to include the
corresponding header file. For instance, if you call CreateWindow without include
<windows.h> you will get an undefined reference. Please include the corresponding
header file.
4) How do I call an external program from the IDE?
In the 'Options' menu there is an option 'Add utility'. Use this.
5) How can I determine in which library the function 'xxx' is located?
Go to the 'Search' menu bar and start GREP. Type the name of the function as the
pattern to search, and give the \lcc\include\*.exp file pattern. This will find which .exp
has this function defined in it (if at all). Then add that library to the link command line.
6) How do I generate an import library for my DLL?
Build a text file containing:

MYDLL.dll
_foo@12 foo
_linelength linelength data
_alternatefoo@12 foo
This file should contain the name of the DLL in the first line, then a series of exports.
In the first column you should write the name of the function, as decorated by the
compiler: A leading underscore, and a '@nn' for all _stdcall functions. The number
following the @ means the number of arguments * 4. In the second column, you should
write the name as it was exported from the DLL. This is optional. If absent, the buildlib
utility will use the name of the function minus the decorations. The third column
(optional) is only necessary if you want to export a data item and not a function.

Lcc-win32 User’s Manual 238


You can build aliases (alternatefoo and foo are different names for the same DLL
entry point).
7) Why is my executable so big?
Do not forget to instruct the linker to eliminate the debug information.
8) How do I pass command line parameters to my program when I use the
debugger?
Use the ‘Debugger’ tab in the ‘Configuration’ options.
9) How do I start the debugger with a given executable without building a project?
At the command line enter:
Wedit myprogram.exe <optional arguments>
or use the ‘File->Open menu’ option, and enter the name of the executable you want to
debug.
10) Why does my program crash when I change the 'Optimize' option?
This can be a problem in the compiler, but before blaming the compiler, remember the
following:
•When optimizing, the compiler does not initialize local variables to known 'bad' values,
as it does when compiling in a normal setting with debugging info. If you use an
uninitialized variable then, in a normal compilation the program will crash.
•Tighter memory layout and register usage when optimizing can produce different
behavior when uninitialized variables are used.
•The ASSERT macro can contain code with side effects. If those side effects are not
being compiled because the ASSERT macro is not active in an optimized version, those
side effects are not there in the optimized build, which can provoke different program
behavior.
11) How do I obtain a stack trace when my program crashes?
Compile all modules with the -g4 option or set the corresponding option in Wedit.
12) How do I use an MSVC import library with lcc?
Do the following:
1. Use the pedump utility to build an ASCII .exp file from the library.
2.Use the buildlib utility to build a library from the generated exp file.
Example:
d:\lcc\test> pedump /EXP qprowinm.lib >qprowinm.exp
d:\lcc\test> buildlib qprowinm.exp qprowinl.lib

Lcc-win32 User’s Manual 239


The first line instructs pedump to generate a file suitable for the buildlib utility. In the
first line, the generated file should contain the name of the DLL to which this import
library is referring. If that name does not appear, it is highly probable that this is NOT an
import library, but a normal library that should work without any problems with lcc.
The second line instructs the buildlib utility to use the generated qprowinm.exp to build
an import library using the lcc format. If the name of the DLL was not found, this step
will fail.
13) How do I list the exported symbols from an object file/executable file/DLL?
Use pedump with the following arguments:
pedump /exp <filename>
14) What is the difference between lcc 4.1 and lcc-win32?
Lcc 4.1 is a continuation by Dave Hanson and Chris Fraser of their work with the
original LCC compiler. Lcc-win32 is derived from lcc 3.6 and has diverged considerably
since. The purposes of the two systems are quite different. Lcc 4.1 needs MSVC to run
and is not very well adapted to the Windows environment. It is conceived as an
environment to learn how a cross compiler works and can generate code for a wide
spectrum of machines. Lcc-win32 is a stand alone compiler system, requiring nothing
else. It is limited, however, to the Windows/x86 environment and is not a cross compiler.
15) The wizard stops with 'Code generation fails' in my Windows 95 system. What
should I do?
In some older Windows 95 systems, the wizard fails mysteriously. I have spent a lot of
time tracking this and never was able to determine why. When I call the PropertySheet
primitive, in some systems the answer will be minus one, and nothing will be shown.
This problem disappears with a newer version of the system. I am sorry about this, but
there is nothing that can be done. You must acquire the latest service release and upgrade
your system.
16) How do I build a DLL?
There are several ways of doing this.
• You can use the integrated development environment, specifying explicitly the ‘DLL’
option. This is the easiest.
• You can call up the ‘wizard’ and generate the DLL skeleton of your DLL with it. You
specify to the wizard in its dialog boxes where on your disk you want the code to be
written.
• You can link your program using the –DLL option, without forgetting to specify the
.def if necessary. This assumes you work from the command line.
14) What does it mean “compiler error in kids” ?

Lcc-win32 User’s Manual 240


This means that the compiler has found a combination of operations that it does not know
how to generate. This error can occasionally appear when you are using the long long
integers. This data type has been introduced relatively recently, and there may be some
combinations of operations that are still not possible. In the event that you get this
message, please send me a bug report.

15) How can I use the debugger of lcc with Microsoft’s compiler?
You should compile with the debug information set to the standard NB09 and avoid the
program database. This can be accomplished with the following command line to the
Microsoft compiler ‘cl’:
cl /Z7 foo.c /link /pdb:none
16) When I start my program, a ‘DOS box’ (console) appears. How can I get rid of
it?
You have not defined your program as a Windows (GUI) program. To do this, go to the
‘Linker configuration’ tab, and check the ‘Windows program’ radio button. This will add
the option ‘Subsystem Windows’ to the linker command line.
When Windows starts a program, it looks at its header for the ‘Windows’ bit. If the
program is not marked as a GUI program, it will open a console window before starting
it. The linker defaults to a ‘console’ application, and not to a Windows application.
17) The linker indicates that _LibMain@12 is not defined when I try to link my
DLL. What does this mean and how do I get rid of it?
This means you did not define the entry point of your DLL. Generate a DLL skeleton
with the wizard. Or write the following function:
BOOL WINAPI __declspec(dllexport) LibMain(HINSTANCE hDLLInst,DWORD fdwReason,LPVOID
lpvReserved)
{
return 1;
}

18) How do I print a message to be shown in the debugger?


With the OutputDebugString() function. If the application has no debugger, the system
debugger displays the string. If the application has no debugger and the system debugger
is not active, OutputDebugString does nothing.
19) How do I debug a DLL?
The debugger cannot start a DLL like a normal executable. You have to define an
executable that will be started by the debugger. This executable should be linked with the
import library of your DLL, and should contain debug information. When this is done,
Wedit will trace calls into the DLL in exactly the same manner as it will trace calls into
any other function. This will work too if the DLL is loaded with LoadLibrary, instead of
being linked in the executable. The drawback of the LoadLibrary method is that
breakpoints cannot be re-established, since Wedit has no way to know which DLLs the
program will dynamically load.

Lcc-win32 User’s Manual 241


20) My dialog box does not show up in the screen!
This can happen if you have a control defined in ComCtl32.dll, and you did not call
InitCommonControlsEx. When you use one of the controls in that DLL, you have
to call that function before you make the call to DialogBox. If you fail to do that,
Windows will not find the class of the list view, slider, etc., and it will refuse to load the
entire dialog box. A sample code for how to do that is:
INITCOMMONCONTROLSEX icex;
memset(&icex,0,sizeof(icex));
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_DATE_CLASSES; // The month calendar control will be
added.
InitCommonControlsEx(&icex);

21) How do I send a bug report?


The purpose of a bug report is to allow the lcc developers to reproduce the bug so that
they can understand it and then correct it. In this context, it is of paramount importance
that the error report states clearly the symptoms of the error and the code that produces
this error. If you write things such as: ‘It does not work’ or ‘It writes an error message’,
there will be NO WAY to help you, since we will NOT be able to reproduce the error or
find out what is really not working !
You should specify what the actions were that produced a crash, if you were working
within the IDE. Then you should specify the symptoms you see (error message, etc.). If
the error is produced by a sequence of C code, try to find out what the smallest piece of
code is that reproduces the bug. It is impossible to find out what is not working if we
receive a bunch of C files with the comment: This does not work.
Send your bug reports to:
Jacob@jacob.remcomp.fr

Lcc-win32 User’s Manual 242


Compiling with the lcc-cd.
If you bought the source code CD, remember: If something fails, please do not panic and
fix it.

For instance:

• When I use 'make' on the \lcc\src\lccsrc the lcclnk.exe fails. It says, 'Fatal: Command
arguments too long' — What have I forgotten to do?

Answer:
There are many make utilities. That prompt does not appear in the make from the lcc CD,
and the user has forgotten that another Make utility with a smaller command line limit
apparently is being used. Maybe a DOS Make utility.

These type of bugs are difficult to prevent, and in general, I cannot prevent a problem
from surfacing somewhere. To be sure that the lcc Make utility is being used, type:

\lcc\bin\make

instead of typing just

make

This will pick up any Make utility in the PATH.

There are other problems that can arise, the possibilities are infinite. Obviously, if a file is
missing, contact me immediately and it will be shipped to you.

Lcc-win32 User’s Manual 243


Accessing COM Objects Using C
Any COM interface method can be called from a C program. There are two things to
remember when calling an interface method from C:
* The first parameter of the method always refers to the object that has been created
and that invokes the method (the ‘this’ argument).
* Each method in the interface is referenced through a pointer to the object's vtable.

The following example creates a surface associated with a DirectDraw object by calling
the IDirectDraw2::CreateSurface method with the C programming language:

ret = lpDD->lpVtbl->CreateSurface (lpDD, &ddsd, &lpDDS, NULL);

The lpDD parameter references the DirectDraw object associated with the new surface.
Incidentally, this method fills a surface-description structure (&ddsd) and returns a
pointer to the new surface (&lpDDS).
To call the IDirectDraw2::CreateSurface method, first dereference the
DirectDraw object's vtable, and then dereference the method from the vtable. The first
parameter supplied in the method is a reference to the DirectDraw object that has been
created and which invokes the method.
To illustrate the difference between calling a COM object method in C and C++, the
same method in C++ is shown below (C++ implicitly dereferences the lpVtbl parameter
and passes the ‘this’ pointer):

ret = lpDD->CreateSurface(&ddsd, &lpDDS, NULL)


Interface Method Names and Syntax
All COM interface methods described in the Microsoft documentation are shown using
C++ class names. This naming convention is used for consistency and to differentiate
between methods used for different DirectX objects that use the same name, such as
QueryInterface, AddRef, and Release. This does not imply that you can use these
methods only with C++.
In addition, the syntax provided for the methods uses C++ conventions for consistency. It
does not include the ‘this’ pointer to the interface. When programming in C, the pointer
to the interface must be included in each method. The following example shows the C++
syntax for the IDirectDraw2::GetCaps method:

HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps );


The same example using C syntax looks like this:
HRESULT GetCaps(LPDIRECTDRAW lpDD, LPDDCAPS lpDDDriverCaps, LPDDCAPS
lpDDHELCaps );

The lpDD parameter is a pointer to the DirectDraw structure that represents the
DirectDraw object.

Lcc-win32 User’s Manual 244


Appendix 1. The Windows Programming Examples
In the directory \lcc\examples26, you will find many examples of Windows programming,
adapted to lcc-win32 from the Microsoft Software Development Kit, and from other
sources.27

Name Purpose
Aclapi Security API functions.
bzip2 Compression library.
Roids Arcade game.
Hello Hello world under Windows.
Htmldlg Calling a Java application that displays a dialog box from C.
Dll Simple DLL.
Intrinsic The intrinsics functions of lcc-win32.
Mandel Mandelbrot drawing.
Exetype Utility showing the type of executable of the given file: Windows or
console.
Service A sample service (Windows NT only).
Tasklist Shows the list of running processes.
Stdlib Many examples illustrating different functions of the standard library
of the C language.
Guidgen Utility to generate a Globally Unique Identifier (GUID). Located in
\lcc\src\utilities\guidgen.
Halftone The Halftone sample allows you to load and display bitmaps while
allowing you to dynamically changing the color filters that are
applied.
Errdecode Utility to show a clear text error description from the HRESULT or
WIN32 error codes. Located in \lcc\src\utilities\errdecode.
Uudecode Utility to transform binary files into a transportable ASCII
representation and back.
Gdidemo GDI window functions.
htmldlg A dialog that displays an html text.
Iconpro Icon management.
Wincapture Mouse capture.
Cpuid Displays information about the type of CPU that is running in your
machine.
Console Console (text mode) functions for managing the cursor, reading from
the screen buffer, setting the video modes, etc.
Perfmon Performance monitoring.

26 This is distributed in the CDROM and e-mail versions only.


27You can subscribe to the Microsoft documentation MSDN. Look at
http://msdn.microsoft.com for details.

Lcc-win32 User’s Manual 245


Winbase: basic windows services
fcopy Copies a file into another using the file mapping APIs.
monkey Registry monitor and other registry APIs.
tty Demonstrates the serial communications primitives of win32, and the
handling of the serial port.
filer This is a complete clone of the file manager in Windows 3.1, using
all file handling primitives, user interface gadgets, etc. of Windows
32.
Network Network examples sub-directory
Network\ping The famous ‘ping’ utility.
Network\wsoc Win-sockets example.
k
Network\overl Overlapped I/O and TCP.
ap
Network\ftp Ftp client with all basic functionality running.
Directx Direct-X examples sub-directory
Directx\quat Quaternions.
Directx\misc Utility functions.
Directx\lib Utility lib.
Directx\faces Graphic example.
Directx\egg Rotating egg in 3D.
Directx\mosqu Another 3D example.
ito
Directx\tunnel Ditto.
Winui Win user interface sub-directory
Winui\menu Menu handling.
winui\mdi Multiple Document Interface (MDI) application. Noteworthy is that
there is a sample of a configuration key using the security primitives.
Different configuration settings are stored according to whether the
user is an administrator or not.
Winui\fileopen Opening a file. It shows the use of the file open common dialog box
and a hook procedure for GetOpenFileName.
Winui\rtfedit RTF editor.
Winui\commo Common dialog box examples. This is an interactive program that
ndialog asks you for the parameters to pass to each common dialog function,
showing you the modifications the parameters make.
Winui\clipboar Clipboard management.
d
Winui \ rebar New rebar control.
Winui \ Provides several active desktops.
switcher
Winui\appbar Provides an application bar like the Windows desktop bar.
Fiber Fiber management (Windows NT only).

Lcc-win32 User’s Manual 246


All the examples come with a corresponding Makefile, so building them is just a matter of
changing to the specific directory, and then typing
‘make’
at the command line prompt.
Most makefiles come with an option , ‘clean’, which will delete all the objects and
executables.
Some of them, particularly those that use the Direct X interface, may not run in all
machines because either Direct X is not installed, or the screen driver does not support a
specific direct x call.
The examples provide a library of common code that you can use in your applications,
sparing you hours of work. I use them still, after many years, just by cutting/pasting from
that code into a new application. This is a simple, but effective way of code re-use.
The Standard Library Examples
For those users who are beginning with the C language, start with the examples in the
‘stdlib’ directory . They are very simple code snippets, but provide you with an idea of how
the language works, and with some useful programs, for instance, the utility ‘paste’, which
mimics the same utility of UNIX, or a utility to convert C source into html source. They
are:

abs.c Absolute value.


asctime.c Printing a time value.
asin.c Asin function (trig).
assert.c Assert macro.
atexit.c Defining a function to be executed at program’s exit.
atof.c Converting a character string into double.
c2html.c Convert C into html. Contributed by David Hoffman.
ceil.c Ceil function.
clock.c Measuring elapsed time with clock().
copysign.c Copysign: extending the sign of a double.
cos.c Trig.
cpuid.c Using the cpuid intrinsic.
ctime.c Printing a time value.
difftime.c Finding out the difference between two time values.
fabs.c Float absolute value.

Lcc-win32 User’s Manual 247


fflush.c Flushing a file.
fgetc.c Get a char from a file.
fpreset.c Floating point reset function.
hypot.c Trig.
ldexp.c The exponent a mantissa values of a number.
log.c Logarithm.
modf.c Floating point modulus.
paste.c A ‘paste ‘ utility.
pow.c Floating point power function.
remove.c Erasing a file.
rint.c Round to integer.
sqrt.c Square root.
strdate.c Date to string.
strip.c Strips the debug information from an executable.
strlen.c Length of a string.
strncat.c Adding a fixed number of chars to a string.
strpbrk.c Finding a character in a string.
strrchr.c Ditto, but the last char.
Tab2spc.c Convert the tabs to spaces. Contributed by David Hoffman.
Tmpfile.c Creating temporary files.
Tmpnam.c Creating a temporary file name.
Valist.c Functions with variable number of arguments.

Lcc-win32 User’s Manual 248


Appendix 2 : The Language Grammar

A.1 Lexical Grammar

A.1.1 Lexical Elements


token:
keyword
identifier
constant
string-literal
punctuator
Tokens are either keywords, identifiers, constants, strings or other punctuation
symbols. They are the basic elements of the language.
preprocessing-token:
header-name
identifier
pp-number
character-constant
string-literal
punctuator
A pre-processing token is the result of a pre-processor action. It can be either a
header name to <include>, identifiers, etc.
A.1.2 Keywords28

keyword: one of

auto break case char


Const continue default do
Double else enum extern
Float for goto if
Inline int long register
(restrict) return short signed
Sizeof static struct switch
Typedef union unsigned void
Volatile while _Bool (_Complex)
(_Imaginary) operator29

A.1.3 Identifiers

28 Keywords in parentheses are NOT implemented in lcc-win32


29The operator identifier is not a keyword strictu sensu, since its meaning depends on the context
where it is defined. See operator overloading.

Lcc-win32 User’s Manual 249


identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit
An identifier must start with a non-digit character, followed by either identifiers
or digits. The maximum identifier length is 255 characters in lcc-win32.

identifier-nondigit:
nondigit
universal-character-name
nondigit: one of
_a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
All characters from 127 to 25430
digit: one of
0 1 2 3 4 5 6 7 8 9
A.1.4 Universal character names
universal-character-name:
\u hex-quad
\U hex-quad hex-quad
hex-quad:
hexadecimal-digit hexadecimal-digit
hexadecimal-digit hexadecimal-digit
A.1.5 Constants
constant:
integer-constant
floating-constant
enumeration-constant
character-constant
Constants are either integers, floats, enums or character constants.
integer-constant:
decimal-constant integer-suffix opt
octal-constant integer-suffix opt
hexadecimal-constant integer-suffix (optional)
decimal-constant:
nonzero-digit
decimal-constant digit
octal-constant:
0 octal-constant octal-digit
hexadecimal-constant:
hexadecimal-prefix hexadecimal-digit
hexadecimal-constant hexadecimal-digit

30 Note that this is not strictly specified by the standard of the language and the programs accepted
by lcc-win32 may not compile in other processors.

Lcc-win32 User’s Manual 250


hexadecimal-prefix: one of
0x 0X
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
octal-digit: one of
0 1 2 3 4 5 6 7
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
integer-suffix:
unsigned-suffix long-suffix opt
unsigned-suffix long-long-suffix
long-suffix unsigned-suffix opt
long-long-suffix unsigned-suffix opt
unsigned-suffix: one of
u U
long-suffix: one of
l L
long-long-suffix: one of
ll LL
floating-constant:
decimal-floating-constant
hexadecimal-floating-constant31
decimal-floating-constant:
fractional-constant exponent-part opt floating-suffix opt
digit-sequence exponent-part floating-suffix opt
hexadecimal-floating-constant:32
hexadecimal-prefix hexadecimal-fractional-constant
binary-exponent-part floating-suffix opt
hexadecimal-prefix hexadecimal-digit-sequence
binary-exponent-part floating-suffix opt
fractional-constant:
digit-sequence opt . digit-sequence
digit-sequence .
exponent-part:
e sign opt digit-sequence
E sign opt digit-sequence
sign: one of
+-
digit-sequence:
digit
digit-sequence digit
hexadecimal-fractional-constant:
hexadecimal-digit-sequence opt .

31 This is not done yet.


32 This is not implemented in lcc-win32

Lcc-win32 User’s Manual 251


hexadecimal-digit-sequence
hexadecimal-digit-sequence .
binary-exponent-part:
p sign opt digit-sequence
P sign opt digit-sequence
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence hexadecimal-digit
floating-suffix: one of
f l F L
enumeration-constant:
identifier
character-constant:
’c-char-sequence’
L’c-char-sequence’
c-char-sequence:
c-char
c-char-sequence c-char
c-char:
any member of the source character set except
the single-quote ’, backslash \, or new-line character
escape-sequence
escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence
universal-character-name
simple-escape-sequence: one of
\’ \" \? \\ \a \b \f \n \r \t \v
octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
hexadecimal-escape-sequence:
\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit
A.1.6 String literals
string-literal:
"s-char-sequence opt " Characters encoded in 1 byte
L"s-char-sequence opt " Characters encoded in 2 bytes
s-char-sequence:
s-char
s-char-sequence s-char
s-char:

Lcc-win32 User’s Manual 252


any member of the source character set except the double-quote ", backslash \, or
new-line character
escape-sequence

A.1.7 Punctuators
punctuator: one of
[](){}.-> ++ -- & * + - ˜ ! /%<<>><><=>===!=ˆ|&&||
?:;... = *= /= %= += -= <<= >>= &= ˆ= |= ,###
<: :> <% %> %: %:%:

A.1.8 Header Names


header-name:
<h-char-sequence> System includes, normally in \lcc\include
"q-char-sequence" User includes, normally in current
directory
h-char-sequence:
h-char
h-char-sequence h-char
h-char:
any member of the source character set except
the new-line character and > Note that lcc-win32 will translate ‘/’ into
‘\’
q-char-sequence:
q-char
q-char-sequence q-char
q-char:
any member of the source character set except the new-line character and "
A.1.9 Preprocessing Numbers
pp-number:
digit
. digit
pp-number digit
pp-number identifier-nondigit
pp-number e sign
pp-number E sign
pp-number p sign
pp-number P sign
pp-number .
A.2 Phrase Structure Grammar

A.2.1 Expressions
primary-expression:
identifier
constant

Lcc-win32 User’s Manual 253


string-literal
( expression )
postfix-expression:
primary-expression
postfix-expression [ expression ]
(indexing)
postfix-expression ( argument-expression-list opt )
(function call)
postfix-expression . identifier
(Structure dereferencing)
postfix-expression -> identifier
(Structure pointer dereferencing)
postfix-expression ++
(Increment by one returning the old
value)
postfix-expression –
(Decrement by one returning the old
value)
( type-name ){initializer-list }33
( type-name ){initializer-list ,}
argument-expression-list:
assignment-expression
argument-expression-list , assignment-expression
unary-expression:
postfix-expression
++ unary-expression
(Increment by one returning the new
value)
-- unary-expression
(Decrement by one returning the new
value)
unary-operator cast-expression
sizeof unary-expression
Returns size of object in bytes
sizeof ( type-name )
unary-operator: one of
&*+-˜!
cast-expression:
unary-expression
( type-name ) cast-expression
multiplicative-expression:
cast-expression
multiplicative-expression * cast-expression

33 The implementation of these two features has started, but will not be ready until July/August 2000.

Lcc-win32 User’s Manual 254


multiplicative-expression / cast-expression
multiplicative-expression % cast-expression Mod operator: 5%3=2
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
shift-expression:
additive-expression
shift-expression << additive-expression Left shift
shift-expression >> additive-expression Right shift
relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression
equality-expression:
relational-expression
equality-expression ==relational-expression
equality-expression != relational-expression
AND-expression:
equality-expression
AND-expression & equality-expression
exclusive-OR-expression:
AND-expression
exclusive-OR-expression ˆ AND-expression
inclusive-OR-expression:
exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression
logical-AND-expression:
inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression
logical-OR-expression:
logical-AND-expression
logical-OR-expression || logical-AND-expression
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
assignment-operator: one of
= *= /= %= += -= <<= >>= &= ˆ= |=
expression:
assignment-expression

Lcc-win32 User’s Manual 255


expression , assignment-expression
constant-expression:
conditional-expression

A.2.2 Declarations
The purpose of declarations is to define the type of an object to the compiler.

declaration:
declaration-specifiers init-declarator-list opt ;
declaration-specifiers:
storage-class-specifier declaration-specifiers opt
type-specifier declaration-specifiers opt
type-qualifier declaration-specifiers opt
function-specifier declaration-specifiers opt
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
storage-class-specifier:
typedef No storage, just a compile time definition.
extern Storage is defined in another module.
static Storage is allocated in this module, but
not visible outside.
auto Stack storage in current frame.
register Integer variable may be stored in a machine
register.
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
_Imaginary
struct-or-union-specifier
enum-specifier
typedef-name

Lcc-win32 User’s Manual 256


struct-or-union-specifier:
struct-or-union identifier opt { struct-declaration-list }
struct-or-union identifier
struct-or-union:
struct Each field is consecutive storage.
union All fields occupy the same space as the largest
one.
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
specifier-qualifier-list:
type-specifier specifier-qualifier-list opt
type-qualifier specifier-qualifier-list opt
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
struct-declarator:
declarator
declarator opt : constant-expression
enum-specifier:
enum identifier opt { enumerator-list }
enum identifier opt { enumerator-list ,}
enum identifier
enumerator-list:
enumerator
enumerator-list , enumerator
enumerator:
enumeration-constant
enumeration-constant = constant-expression
type-qualifier:
const
restrict
volatile
function-specifier:
inline
_stdcall 34

_ _declspec(dllexport)
overloaded35
declarator:

34This specifiers are specific to the Windows system, and are not supported by other compilers in other
systems. Within the Windows system they are fairly common.
35 See the documentation for the overloaded keyword .

Lcc-win32 User’s Manual 257


pointer opt direct-declarator
reference opt direct-declarator36
direct-declarator:
identifier
( declarator )
direct-declarator [ assignment-expression opt ]
direct-declarator [*]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list opt )
identifier . identifier
pointer:
* type-qualifier-list opt
* type-qualifier-list opt pointer
reference:
type-qualifier-list & lcc-win32 extension.
type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier
parameter-type-list:
parameter-list
parameter-list , ...
parameter-list:
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration:
declaration-specifiers declarator
declaration-specifiers abstract-declarator opt
identifier-list:
identifier
identifier-list , identifier
type-name:
specifier-qualifier-list abstract-declarator opt
abstract-declarator:
pointer
pointer opt direct-abstract-declarator
direct-abstract-declarator:
( abstract-declarator )
direct-abstract-declarator opt [ assignment-expression opt ]
direct-abstract-declarator [*]
direct-abstract-declarator opt ( parameter-type-list opt )
typedef-name:
identifier
initializer:

36 References, even if widely used in the C++ language are not strictly part of the C grammar.

Lcc-win32 User’s Manual 258


assignment-expression
{ initializer-list }
{ initializer-list ,}
initializer-list:
designation opt initializer
initializer-list , designation opt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
A.2.3 Statements
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
compound-statement:
{ block-item-list opt }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
statement
expression-statement:
expression opt ;
selection-statement:
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
iteration-statement:
while ( expression ) statement
do statement while ( expression );
for ( expression opt ; expression opt ; expression opt ) statement
for ( declaration expression opt ; expression opt ) statement

Lcc-win32 User’s Manual 259


jump-statement:
goto identifier ;
continue ;
break ;
return expression opt ;
A.2.4 External Definitions
translation-unit:
external-declaration
translation-unit external-declaration
external-declaration:
function-definition
declaration
function-definition:
declaration-specifiers declarator declaration-list opt compound-statement
operator operator-name declaration-list compound-statement37
declaration-specifiers overloaded declarator declaration-list compound
statement
declaration-list:
declaration
declaration-list declaration
operator-name:
+ - * / << += -= *= /= & | ^ >> < <= >= > ~ !
A.3 Preprocessing Directives
preprocessing-file:
group opt
group:
group-part
group group-part
group-part:
pp-tokens opt new-line
if-section
control-line
if-section:
if-group elif-groups opt else-group opt endif-line
if-group:
#if constant-expression new-line group opt
# ifdef identifier new-line group opt
# ifndef identifier new-line group opt
elif-groups:
elif-group
elif-groups elif-group
elif-group:

37 Note that this is specific to lcc-win32, even if this type of operator redefinition is widely used in C++,
it is not a part of the C language.

Lcc-win32 User’s Manual 260


# elif constant-expression new-line group opt
else-group:
# else new-line group opt
(6.10.1) endif-line:
# endif new-line
control-line:
# include pp-tokens new-line
# define identifier replacement-list new-line
# define identifier lparen identifier-list opt )
replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... )
replacement-list new-line
# undef identifier new-line
# line pp-tokens new-line
# error pp-tokens opt new-line
# pragma pp-tokens opt new-line
# new-line
lparen:
the left-parenthesis character without preceding white space38
replacement-list:
pp-tokens opt
pp-tokens:
preprocessing-token
pp-tokens preprocessing-token
new-line:
the new-line character

38 Note that here is one of the few places where white space is significant in the language.

Lcc-win32 User’s Manual 261


Appendix 3: The bignum Library
This library is an adaptation of the “miracl” bignum library published by Mike
Scott in 1989. Since then, Mike has developed his library further. The latest
version can be downloaded from his web site

ftp.compapp.dcu.ie/pub/crypto/miracl.zip

I had worked a lot in the 1989 version, rewriting the essential parts of it in pure
assembly. It runs quite fast now, and I am convinced it is a very useful package.

The interface this library presents is described in “bignums.h”. Basically, most


operators (addition, subtraction, etc.) are overloaded there, so that you can use
the library using a practical infix notation (you write c = a + b instead of
quadsum(a,b,c) to make an addition).

Practical considerations:

Note that the bignum library is designed to work with the garbage collector. Most
operators that need to, for instance “+”, “-“ etc., return a new bignum, that will be
garbage collected automatically if it is no longer needed. This can be costly, and
if you prefer trading speed for notational convenience, you can use the normal C
interface and instead of writing:

c = (a + b)/(a – b);//creates temporary objects for a+b


and a-b

you write:

c = newBignum(0); //allocate result


quadsum(a,b,tmp); // tmp = a + b
quadsub(a,b,c); // c = a - b
quaddiv(tmp,c,c); // c = tmp/c = (a+b)/(a-b)

In this latter case, you create only a single temporary that can later be reused. In
the former case, you create two. This is absolutely unnoticeable in MOST cases.
The convenience of the infix notation largely compensates the occasional stops
to collect unneeded structures. Of course, you can trade execution speed for
development speed.

Note that the public interface of the bignum library is an opaque data structure:
typedef struct _mp {
void *mp;
} pBignum;

Lcc-win32 User’s Manual 262


This allows for changes in the bignum representation to be made transparently to your
code. You could plug in a completely different bignum library, or get the latest version of
Mike Scott and plug it in, without any changes to the bignum client code. Note that this is
just a glorified pointer. Before using it, you must initialize it to a new bignum, either as a
result of an operation or as the result of newBignum().

The library is presented as a DLL. When loaded, the DLL will automatically initialize the
bignum system to a precision of 300 bits. You can change this using the BignumPrecision()
API.
Example:
This example prints the powers of two from 127 to zero.

#include <bignums.h>

int main(void)
{
pBignum a,b,c;
char buffer[4096];

c = newBignum(2);
for (int i = 127;i> 0;i--) {
b = newBignum(i);
a = quadpow(c,b);
quadformat(a,buffer);
printf("[%3d] %s\n",i,buffer);
}
return 0;
}
Output:
[127] 170141183460469231731687303715884105728
[126] 85070591730234615865843651857942052864
[125] 42535295865117307932921825928971026432
[124] 21267647932558653966460912964485513216
[123] 10633823966279326983230456482242756608
[122] 5316911983139663491615228241121378304
[121] 2658455991569831745807614120560689152
[120] 1329227995784915872903807060280344576
[119] 664613997892457936451903530140172288

Bignum implementation

Bignums are stored in two ways:


• As a large integer: The first word (32 bits) contains the length and the sign, followed
by the data, 30 bits for each 32 bit word.
• As a ratio of two integers, represented as a continued fraction. This allows for a
floating point (or maybe floating slash) representation.

Lcc-win32 User’s Manual 263


In both cases, the library returns a pointer to these opaque data. No direct
access is provided, so the underlying library or DLL can be changed as needed,
without affecting user code, as long as the interface of the dll is the same.

Interface overview

Function Description
Initialization
int BignumPrecision(int); Sets the precision to a given value. Each
big number is represented as a vector of
integers. For each integer, the precision
increases of 30 bits. The argument is the
number of integers to reserve for each big
number. For instance, if you request a
precision of 30, 30 integers of 30 bits
precision will be used, i.e. 900 bits per big
number.
Creation
pBignum newBignum(void) Returns a new big number initialized to
zero
pBignum newBignum(int); Returns a new bignum initialized to the
given integer.
pBignum newBignum(double); Returns a new big number initialized to the
given double precision number.
pBignum newBignum(long long); Returns a new big number initialized to the
given long long integer.
pBignum newBignum(char *); Returns a new big number initialized to the
converted value of the given string.
Conversions
pBignum atoquad(char *); Converts the given string to a newly allocated
big number.
pBignum longToquad(long); Converts the given 32 bit integer,double
pBignum doubleToquad(double);
precision, or long long number to a newly
pBignum longlongToquad(long
long); allocated big number.
void long2quad(long,pBignum); Converts the given 32 bit integer or double
void
double2quad(double,pBignum);
precision number into a big number. Sotrage
is not allocated, the result is stored in the given
bignum, that must have been previously
allocated.
double quad2double(pBignum); Returns a double precision or a long long
long long quadToll(pBignum);
number from a big number.
Formatting
void quadexpformat(pBignum x, Formats a given big number “x” as text in the
unsigned char *outbuf, int
width, int decimals); buffer pointed to by “outbuf”, with the given

Lcc-win32 User’s Manual 264


width and decimals.
void quadtoa(pBignum,unsignedFormats a given big number as text in the
char *outbuf);
given output buffer.
Comparisons
int operator<(pBignum a,pBignum (a<b)?1:0
b);
int operator<(pBignum,long);
int operator<(pBignum,double);
int operator<(long,pBignum);
int operator<(double,pBignum);
int operator<=(pBignum,pBignum); (a<=b)?1:0
int operator<=(pBignum,long);
int operator<=(pBignum,double);
int operator<=(long,pBignum);
int operator<=(double,pBignum);
int operator==(pBignum,pBignum); (a==b)?1:0;
int operator==(pBignum,long);
int operator==(pBignum,double);
int operator==(long,pBignum);
int operator==(double,pBignum);
int operator>=(pBignum,pBignum); (a>=b)?1:0;
int operator>=(pBignum,long);
int operator>=(pBignum,double);
int operator>=(long,pBignum);
int operator>=(double,pBignum);
int operator>(pBignum,pBignum); (a>b)?1:0;
int operator>(pBignum,long);
int operator>(pBignum,double);
int operator>(long,pBignum);
int operator>(double,pBignum);
int operator!=(pBignum,pBignum); (a!=b)?1:0;
int operator!=(pBignum,long);
int operator!=(pBignum,double);
int operator!=(long,pBignum);
int operator!=(double,pBignum);
int quadcmp(pBignum a,pBignum b)Returns –1 if a < b, 0 if a == b, and 1 if a > b
Addition
operator+(pBignum,pBignum); Returns newly allocated big number with the
pBignum operator+(pBignum,long);
… other conversions result of the addition.
operator+=(pBignum,pBignum); Returns the addition of the first operand and
the second. No new storage, the result is stored
in the first operator.
Sustraction
operator-(pBignum,pBignum); Returns newly allocated big number with the
result of the sustraction.
operator-=(pBignum,pBignum); Returns a pointer to the first argument. The
substraction is stored in the first argument, no
new storage is used.
Multiplication
operator *(pBignum,pBignum); Returns newly allocated big number with the
result of the multiplication.
operator *=(pBignum,pBignum); Stores the multiplication result in its first

Lcc-win32 User’s Manual 265


argument. Returns first argument.
Division
operator /(pBignum,pBignum); Returns newly allocated big number with the
result of the division.
operator /=(pBignum,pBignum); Stores the division result in its first
argument. Returns first argument..
Math functions
pBignum quadisqrt(pBignum); Returns a newly allocated big number with
the integer square root of its argument.
pBignum quadsqrt(pBignum); Returns a newly allocated big number with the
square root of its argument.
pBignum logb2(pBignum); Returns a newly allocated big number with the
log base 2 of its argument.
pBignum quadln(pBignum); Returns the natural logarithm of its arguments
in a newly allocated big number.
pBignum quadpow(pBignum,pBignum) Returns a newly allocated big number with the
result of elevating the first argument to the
second argument power, i.e.
result = first Second
pBignum quadexp(pBignum) Returns newly allocated big number containing
e raised to the first argument.
pBignum quadrand(pBignum) Returns a random number between 0 and the
given big number
pBignum quadpgcd(pBignum x, Returns the gcd of the two big numbers
pBignum y);
pBignum quadround(pBignum x,int Rounds the given number to n places. Returns
n);
a new number, the input is not modified.
pBignum quadratio(int numerator, Returns a new big number built as a ratio from
int denominator);
the given integers.
int quadintegerp(pBignum x); Returns 1 if the given big number is
represented as an exact integer, or 0 if it is
represented as a ratio.
Trig
Note: All arguments must be in radians.
pBignum quadsin(pBignum); Sinus
pBignum quadcos(pBignum); Cosinus
pBignum quadacos(pBignum); Arc cosinus
pBignum quadasin(pBignum); Arc sinus
pBignum quadtan(pBignum); Tangent
pBignum quadatan(pBignum); Arc tangent
pBignum quadtanh(pBignum); Hyperbolic tangent
pBignum quadatanh(pBignum); Hyperbolic arc tangent
pBignum quadsinh(pBignum); Hyperbolic sinus
pBignum quadasinh(pBignum); Hyperbolic arc sinus
pBignum quadcosh(pBignum); Hyperbolic cosinus

Lcc-win32 User’s Manual 266


pBignum quadacosh(pBignum); Hyperbolic arc cosinus

Lcc-win32 User’s Manual 267


Appendix 4: Implementation Limits

Limit Effect
More than 4095 characters in a string literal Warning message
More than 127 levels of nested statements Warning message
More than 1023 cases in a switch statement Warning message
More than 511 identifiers declared in a block Warning message
More than 65535 bytes in an object Warning message
More than 2147483647 bytes in an array Error
More than 1023 fields in a struct/union Warning message
More than 1023 enumeration members Warning message
More than 127 arguments to a function Warning message
More than 4095 external identifiers Warning message
More than 64 #if nesting levels Error
More than 128 evaluation levels in #if directive Error
More than 15 #include nesting levels Error
More than 256 arguments to a macro Error

Lcc-win32 User’s Manual 268


Bibliography

The following books may be of interest for learning how to program under
Windows:
Programming Windows, Petzold (and Yao), MS Press
Charles Petzold wrote the original Windows programming 'bible' - "Programming
Windows" back in the mid eighties. Everyone who started Windows programming in
those days had (or needed) a copy of this book. Now updated for Win32, Petzold
starts the basic paradigms of Windows programming, Windows and message queues.
He goes on to cover many advanced topics. The book uses C and assumes a prior
knowledge of this language. I have tried to get all of the examples of this book to
work. If you find any problems please report them to me!
Windows 95 System Programming Secrets by Matt Pietrek
A good book to investigate. All low level details of the Win32 API. It complements
the explanations in the lcc-win32 technical reference very well.

These magazines are good references and can be useful for your work:

Microsoft Systems Journal


A monthly magazine containing the most up-to-date official view of Windows
development. Contrary to what anyone would expect, sometimes you can find highly
critical articles about Microsoft products!

Windows DOS Developer’s Journal


This is a must for Windows developers. Highly technical contents, very good book
reviews.

Dr. Dobb’s Journal


Another regular magazine. For those who want to know what is happening beyond
the Windows horizon. There are articles about Windows, but they are not the only
content of this magazine.

Lcc-win32 User’s Manual 269

Vous aimerez peut-être aussi