TOOLKIT.TXT

This file contains four sections of information.  The first
section, titled Specific Additional Information, contains
additional information that relates to specific lines of
text or code in the book.  The second section, titled
General Additional Information, contains general information
relating to subjects discussed in the book.  The third
section, titled Specific Corrections, contains corrections to
specific lines of text or code.  The fourth section, titled
General corrections, contains corrections to general
statements or repetitive code segments.

SPECIFIC ADDITIONAL INFORMATION

Specific additional info
Page 20, if you cannot use the 800 number to call ELSA, you
can use the following direct line number: 1-415-615-7799.

Specific additional info
The following can be added to the Note on page 30:
Any language that can support C calling conventions and can
use a supplied library can be used by ADS.  This is how
Watcom FORTRAN works with ADS.

Specific additional info
One of the disadvantages to AutoLISP listed on page 32
indicates that speed is impeded because AutoLISP is
interpreted.  An AutoLISP compiler has been distributed in
the European market.  This compiler creates code that runs 
faster than regular interpreted AutoLISP, but not as fast 
as ADS applications.

Specific additional info
The following can be added to the Note on page 40:
To support a compiler, start-up code must be written.  This
is the major hurdle to adding more compilers to the list of
those already supported.

Specific additional info
The first disadvantage to real-mode compilers list on page
42, can include the following:
Due to the relatively small amount of memory available to a
real-mode application, considerable time is spent at run-
time context switching from protected-mode to real-mode.
This is the major reason why limited memory affects the
speed of real-mode compilers when used with AutoCAD.

Specific additional info
Page 42 lists the supported protected mode compilers.
Because a number of users have tried to use MetaWare High
C/C++ 2.3 rather than the required 3.0, we would like to
reemphasize that you need at least 3.0.  For those of you
using Watcom C, you will need at least 9.01 to compile ADS
applications for Windows.

Specific additional Info
Page 95 discusses the use of a function table.  The code
description labeled (3)  says that "The functions are
declared.  All the functions in a function table must be of
the same type and have the same type and number of
arguments."  All of this is true.  When you are using a
function table to register functions, you should note that
ADS_REGFUNC imposes the following restriction:
All functions must be of type INT and cannot have arguments.
As noted elsewhere in the book, you can get around the no
argument restriction by using ADS_GETARGS when your function
is called.

Specific additional info
The discussion of ADS_BUILDLIST on page 107 says that the
result buffer list created by ADS_BUILDLIST is exactly like
the one created by ADS_COMMAND.  This is not strictly true.
The call to these functions and their arguments are similar.
The purpose and internal working of the code, however, are
significantly different, so the two functions do not actually
build identical lists.

Specific additional info
Page 107, The last sentence of the page reads " Zeros used
in data type and value pairs in the list do not cause the
list to end prematurely."  The term "data type and value
pair" refers to a result buffer type AND its associated
argument in a pair.  If you do not specify an argument in
addition to the result buffer type, AutoCAD sees this as a
single zero and terminates the list.

Specific additional info
Page 112, The list of limitations of ADS_COMMAND and ADS_CMD
can have the following additional pieces of information:
1. According to developer support, the first item in the
list applies to ADS_COMMAND and ADS_BUILDLIST only.

2. The third item in the list lists the PLOT command as a
command that cannot be called by ADS_COMMAND or ADS_CMD.
PLOT can be called but not with the dialog box interface.

3. The fourth item mentions that scripts invoked by
ADS_COMMAND or ADS_CMD are not run until the ADS function
ends and returns control to AutoLISP.  It is worth noting
that the same restriction applies to AutoLISP itself.  If
you use COMMAND to call a script in a user-defined AutoLISP
function, that COMMAND should be the last function call in
the user-defined function.

4. The final two items of the list can be supplemented by
mentioning that use of ADS_COMMAND or ADS_CMD in these ways
will produce an AutoCAD error message.

Specific additional info
Page 144, The last sentence of the middle paragraph of the
ADS_ALERT description says, "For this reason, use ADS_ALERT
if the message is important enough to warrant pausing the
application until the user clicks on OK."  ADS_ALERT
actually pauses everything, so it would be more accurate to
say "For this reason, use ADS_ALERT if the message is
important enough to warrant pausing ALL applications until
the user clicks on OK."


GENERAL ADDITIONAL INFORMATION

General additional info
You must be very careful when using a real-mode compiler
with any memory manager.  AutoCAD runs in protected-mode
using extended memory.  Real-mode applications run in real-
mode in conventional memory.  The constant context switching
between AutoCAD's protected-mode and the real-mode
application in combination with AutoCAD's memory manager and
any memory manager you may have loaded has the potential for
crashing a perfectly good ADS application.  If you need to
use a memory manager, make sure you configure it so that it
does not conflict with AutoCAD.

If you are experiencing problems with a real-mode ADS
application, you should try running it on a computer with a
stripped-down CONFIG.SYS and AUTOEXEC.BAT.  If the
application runs correctly, you may have a memory manager
conflict.  Check your memory manager's documentation for any
switches that may help it work with AutoCAD.  You may find
that the cost of a protected-mode compiler and linker is
easily offset compared to complications and speed penalties
on a real-mode compiler.

General additional info
From a coding style point of view, you should allocate all
of the memory that a new link in a link list will need
before traversing the list looking for the new link's
eventual insertion location.  The reason for this is that if
you cannot allocate the memory, there is little point in
traversing the list looking for where to place the link.

General additional info
The following code example is included as an additional
warning.  The explanation following the code shows why this
code is dangerous.
    struct resbuf *rb;

    if((rb = ads_newrb(RTSTR)) == NULL)
    {
      return RTERROR;
    }
    ads_relrb(rb);

The reason this is dangerous is that the ADS_NEWRB function
initializes the RBNEXT field to NULL, but in the case of
allocating a resbuf for RTSTR, the function does not
initialize RB->RESVAL.RSTRING to NULL, but instead leaves it
pointing to some random memory location.  With the
subsequent ADS_RELRB call, AutoCAD tries to free memory
pointed to by RB->RESVAL.RSTRING that was never allocated,
which is a sure-fire way to corrupt things.

General additional info
Programmers using ADS, AutoLISP, and selection sets should 
consider the following potential problem when designing their
code:
There is a potential problem with ADS_FREE if you are not 
careful with your algorithm.  AutoLISP users are used to doing something 
similar to (setq ss nil) to free up a selection set.  This sequence 
does not free the selection set if it was created with an ADS 
routine and returned to AutoLISP with an ADS_RETNAME call.  On
the ADS side, the potential for error comes with the sequence
    ads_retname(ss, RTPICKS); 
    ads_ssfree(ss);
Even though the selection set was returned to AutoLISP, the ADS_FREE call
wipes it out and the AutoLISP routine ends up with a selection set
containing no entities.  The only workaround is to take the
selection set returned by the ADS program, and duplicate it
within AutoLISP by doing the following:
    (setq ss (some_ads_routine_that_returns_a_ss))
    (command "._select" ss "")
    (setq ss (ssget "p"))
At this point, the ADS routine can perform the ADS_FREE.


SPECIFIC CORRECTIONS

Specific Correction
In the files DRIVER.C, LOADER.C, and VIEWREN.C the memory
for the character pointer FILENAME must be allocated before
it is used in ADS_GETSTRING.

Specific correction
Page 34, the final advantage listed for using ADS mentions
the AutoCAD Developers Kit.  This should be the Software
Developers Kit.

Specific correction
Page 42, the final disadvantage to real-mode compilers
indicates the DOS extender switch SAVER may need to be
adjusted.  The correct name of the switch is SAVEREAS.  This
correction should also be made to the REALMODE.TXT file
supplied by Autodesk in your /ADS/DOCS directory.

Specific Correction.
Page 51, The syntax for the ADS_INIT function currently
reads:
    INT resbuf ADS_INIT (argc, agrv);
it should read:
    INT ADS_INIT (argv, argc);

Specific correction
Page 52, two lines after the line of C code labeled (1):
    scode = RTRSLT;
should read:
    scode = RSRSLT;

Specific correction
Pages 83-86, all code examples show ADS_POINT and ADS_NAME
in uppercase.  These should be in lower case in the actual
code segments.

Specific correction
Page 85, The ADS_MATRIX function description lists a series
of functions that use transformation matrices.  Included in
that series in ADSNENTSELS which should be listed as
ADS_NENTSELS

Specific correction
Page 86, first line:  ADS_NAME_EQUAL should be ADS_NAME_SET.

Specific correction
Page 90, the code listing for the declaration of a RESBUF
called VALUE should be as follows:
    struct resbuf value;
    value.resval.rreal = 1.0;
    value.restype = RTREAL;
This eliminates the pointer and allows for the allocation of
the memory used by the structure.  Because the RESBUF
structure is declared rather than a RESBUF pointer, the ->
symbol in the book is changed to the . you see in the
listing above.

Specific correction
Page 92, the first code listing on the page uses a RESBUF
pointer.  To use this properly, you must use ADS_NEWRB to
allocate the memory used by the result buffer before
assigning it any values.

Specific correction
Page 117, The line of C code to release the result buffer
reads:
    ads_relrb(resval);
it should be:
    ads_relrb(retval);

Specific correction.
Page 118, the character pointer HOLD should have its memory
allocated before being used in the STRCPY.  In the same code
example, you should note that the code assumes the user will
pass the correct number of arguments.  Before using this
code in your application, you should expand the error
checking to make sure that each result buffer in the list
exists before attempting to read it.  The line args = args-
>rbnext; should be called only after you have confirmed that
args->rbnext exists.

Specific correction
Page 118, the source code for Application B: has an
allocation error.  The line:
     char *hold, new[128];
should be
     char hold[128], new[128];

Specific correction
Page 119, the lines of C code under the label (7) include a
line to call ADS_ALERT.  This ADS_ALERT includes a linefeed
(\n) character.  This is not normally used for ADS_ALERT
calls and should be removed.

Specific correction
Page 120,  The description labeled (8) included the line,
"If the copy works, NEW is returned to AutoLISP; otherwise,
the user is warned, and the function fails."  In the source
code listed on page 119, no warning is given if the copy
does not work - the routine simply returns an error code of
RTERROR.  A warning should be displayed for the user with
ADS_FAIL or ADS_ALERT.

Specific correction
Page 121, the discussion labeled (2) has the line "returned
from CALLED (with ADS_RETLIST)."  The function CALLED uses
ADS_RETSTR function not ADS_RETLIST.

Specific correction
Page 124, the first paragraph indicates that a function's
local variables are freed whenever a function ends.  If you
use the C directive "static" when declaring the function,
the variable value is maintained.

Specific correction
Page 126, in figure 3.2, the sample link in the upper right
of the figure has the previous link address and the next
link address reversed.  The actual links in the figure of
the linked list are correct.

Specific correction
Page 128, in the line of C code labeled (3), there's 
a ( missing just after STRCPY.

Page 128, the section of C code labeled (2) in the line:
    if ((new->resval.rstring = malloc (strlen (value)) == NULL)
The MALLOC() statement doesn't allocate enough memory, since
STRLEN does not include the null terminator in the returned
length.  Additionally, MALLOC needs to be declared as a
character pointer.  The statement should be
    if ((new->resval.rstring = (char *) malloc (strlen(value) +1) == NULL)

Specific correction
Page 128, the line of C code labeled (3):
    strcpy new->resval.rstring, value);
should be
    strcpy(new->resval.rstring, value);

Specific correction
Page 128.  Item 3.  The line "new->rbnext = NULL;" is not
needed since the ads_newrb() command automatically sets
rbnext = NULL.

Specific correction
Page 128, the code segment should include a call to
ADS_RELRB to release the result buffer NEW.

Specific correction
Page 131, the third bulleted item.  For clarity, the first
sentence should be changed to "For the sake of this
demonstration, the result buffers TO BE ADDED are RTREAL
buffers."

Specific correction
Page 132,  in the C code example:
    new = ads_newrb(RTLB)
should be
    new = ads_newrb(RTREAL)

Specific correction
Page 132, the code to make a new head should include the
line:
   head = new;
after the line:
   new->rbnext = head;

Specific correction
Page 134, the WHILE loop in the code sample should read:
    while (ahead->resval.rreal <= x && ahead != NULL)
    {
      behind = ahead;
      ahead = ahead->rbnext;
    }

Specific correction
Page 134, in the C code segment the line:
    while (ahead->resval.rreal <= X)
will cause an infinite loop/lockup to occur if every item in
the list has a value less than or equal to X.  To correct
this, the line should be:
    while (ahead && (ahead->resval.rreal <= X))
or
    while (ahead->resval.rreal <= X && ahead != NULL)

As previously mentioned, for the sake of clarity this code
segment was designed for result buffers of type ADS_REAL
only.  For the condition in the WHILE loop to work
universally, it needs to identify the result buffer type
before making a judgment about the result buffer's value.

Specific correction
Page 141, the final description and code segment of the page
describes a blank entry into ADS_GETSTRING as a NULL
pointer.  This is not true.  It you do not enter a value in
ADS_GETSTRING, the result is a pointer to a "" not NULL.

Specific correction
Page 143, the second to last sentence of the ADS_PRINTF
description says that "The FORMAT can be a text string
and/or scan codes."  Technically, the FORMAT is a single text
string that can contain text and/or scan codes.

Specific correction
page 154, the first item in table 3.4 is ADS_ADSLAST; this
should be ADS_ENTLAST.

Specific correction
Page 160, last line in the paragraph following the second
bullet from the bottom:  ACAD.PDW should be ACAD.PWD.
Because deleting the ACAD.PWD file will require a
reconfiguration, you should keep a backup copy of your
ACAD.CFG and ACAD.PWD files.

Specific correction
Page 176, the code for the function L.  Change
    char *filename;
to
    char filename[128];
to prevent memory allocation errors or use MALLOC to
allocate memory for the character pointer.

Specific correction
Page 180, second paragraph, first sentence.  The reference
to figure 4.2 should be to figure 4.3.  The following
reference to figure 4.3 should be to figure 4.2.

Specific correction
Page 196, first sentence.  The reference to figure 4.3
should be to 4.2.

Specific correction
Page 341, the Database Query section.  The last line on the
page says "ADS_SSGET (interactive ADS_SSGET only)".  It
should say non-interactive ADS_SSGET

Specific correction
Page 344, The character pointer FILENAME should have its
memory allocated before it is used in ADS_GETSTRING.

Specific correction
Page 353, The character pointer FILENAME should have its
memory allocated before it is used in ADS_GETSTRING.

Specific correction
Page 361, under the ADS driver section.
1. The line:
    ads_start_dialog(cpkt->dialog, status);
    should be
    ads_start_dialog(cpkt->dialog, &status);

2. The NEST() function should be declared as type VOID or
left as type INT and be given a return value.  Either method
will compile.  From an error-checking standpoint, you will
probably need to leave the function type INT and add return
values to be checked by the calling function.

3. The fourth and fifth lines from the bottom of the page
read:
       /* associate the accept key with the
          accept_dialog function */
This is included to let you know that, if you want a special
function for the accept key, you need to associate the
accept key with an accept dialog function.  This line of
documentation is not intended to describe the actions that
follow it.  The line following the comment associates the
"test_button" key with the NEST function.

4. The third line from the bottom uses the variable
DIALOG_HDL.  This variable should be DBFIRST.

Specific correction
Page 367, the two-line code example in the middle of the
page:
    (strcpy new_text "Look for change");
should be
    strcpy(new_text, "Look for change");

Specific correction
Page 374-375, The character pointer ITEM should have its
memory allocated before it is used in the line "strcpy(item,
list_items->resval.rstring);".

Specific correction
Page 380, the which_button() function.  The character VALUE
should have its memory allocated before the line
strcpy(value, cpkt->value);".

Specific correction
Page 380, the which_button() function.  The three lines
    'case "one" :
    'case "two" :
    'case "three" :
are invalid C expressions.  The case statements must be of
integral type.  In this case they are of string type.

Specific correction
Page 669, first two lines of code.  The lines:
    ads_relrb (&from);
and
    ads_relrb(&to);
are incorrect, since ADS_RELRB is only for resbufs that
have been dynamically allocated using ADS_NEWRB() or
MALLOC().  In the code sample, FROM and TO were not defined
as pointers, so they do not need to be freed using
ADS_RELRB.  The discussion labeled (9) on page 670 is
incorrect for the same reason in regards to its discussion
about releasing FROM and TO.

Specific correction
Page 703. The line of C code:
    char *pointf;
needs to be changed to
    char pointf[128];
or use MALLOC to allocate the memory for the character
pointer.

Specific correction
Page 705, the character pointers
    char *pointf;
    char *viewf;
    char *imagename;
    char *imagef;

need to be changed to
    char pointf[128];
    char viewf[128];
    char imagename[128];
    char imagef[128];

or the memory must be allocated for the character pointers.

Specific correction
Page 706 and 707, the C code segment contains a memory leak.
The way the code is currently written, it builds a list for
CMD each time the WHILE loop executes, but only frees the
resbufs after exiting the WHILE loop.  The same problem
occurs with the RESULT variable set by ADS_INVOKE.

The following code under the code section labeled (11) is
repeated for each execution of the WHILE loop:
    cmd = ads_buildlist (RTSTR, "C:RENDER", 0);
    if (ads_invoke (cmd, &result) == RTNORM)
    {
      / * save the image */
      ads_relrb(cmd);
      ads_relrb(result);
      result = NULL;
      cmd = ads_buildlist (RTSTR, "C:SAVEIMG", RTSTR,
                           imagename, RTSTR, "TGA", 0);

The following code under the code section labeled (12) on
page 707 is called just once after the WHILE loop.
      ads_relrb(cmd);
      cmd = NULL;
      ads_relrb(result);
      result = NULL;
    }
    fclose(vptr);  /* close view name file */

Specific correction
Page 711, the code sample for SHOWVIEWS().  There is a
memory leak in the code sample.  The way the code is
currently written, it builds a list for CMD each time
the WHILE loops executes, but it only frees the resbufs
after exiting the WHILE loop.  The same problem occurs with
the RESULT variable.  Change the last two lines of code on
page 711 to include the following:

               }
               ads_relrb(cmd);
               cmd = NULL;
               ads_relrb(result);
               result = NULL;
          }

Specific correction
Page 711, the SHOWVIEWS sample.  Change
    char *viewf, *imagename;
to
    char viewf[128], imagename[128];

or use MALLOC to allocate the memory for the character
pointers.


GENERAL CORRECTIONS

General correction
ADS_RELRB ignores NULL pointers.  FREE, on the other hand,
may not.

General correction
Make sure that you allocate the memory used by ADS_GETSTRING
before calling ADS_GETSTRING.

General correction
You need to be wary of memory leaks.  The following
psuedocode sample shows a functional piece of code that can
cause a memory leak:

    Allocate a resbuf;
    attempt a process with the resbuf;
    if process failed
    {
      display error message;
      return RTERROR;
    }
    do other things with the result buffer;
    release result buffer;
    return RTNORM;

In the above sample, the result buffer is not released if
the IF statement is true because the function is terminated
immediately.  An additional line must be added in the IF
statement nest to free the result buffer before the function
is terminated.

