(C) 1993 BASIC d.o.o Ljubljana, Jure Spiler, Jesenkova 5, 61000 Ljubljana, Slovenia tel: +386 1 314 069 fax: +386 1 318 211 CompuServe: [70541,1765] e-mail: Jure Spiler, director jure.spiler@public1.noprmd.mail.si Joze Marincek joze.marincek@uni-lj.si Lisp2C AutoLISP to C (ADS) treanslator user's guide version 1.9 (22-June-1993) Table of Contents Table of Contents 2 1. INTRODUCTION 3 2. INSTALLATION 4 2.1.DOS - WATCOM 4 2.2.DOS - METAWARE 4 2.3.WINDOWS - WATCOM 4 2.4.WINDOWS - METAWARE 5 2.5. DOS Example (Watcom) 5 3. THE USAGE 6 3.1. COMMAND LINE INPUT 6 3.2. INTERACTIVE INPUT 7 3.3. PROJECT FILE 8 3.4. SWITCHES 8 3.5. COMPILING THE CODE (WATCOM) 9 3.6. LINKING (WATCOM) 10 3.7. BINDING (WATCOM) 10 4. SUPPORTED FUNCTIONS 11 5. DIFFERENCES AND LIMITATIONS 12 5.1. EXPRESSIONS OUTSIDE THE FUNCTIONS 12 5.2 NUMBER OF ARGUMENTS 12 5.3. PASSING SYMBOLS, SUBROUTINES ETC. 12 5.4. PASSING LISTS OF INTEGERS ETC. 12 5.5. BUILD-IN PRIMITIVES 12 5.6. GLOBAL SYMBOLS 12 5.7. A SYMBOL TABLE 13 5.8. NENTSEL, NENTSELP 13 5.9. ATOMS-FAMILY 13 5.10. COMMAND 13 5.12. SPEED 13 6. FEATURES 14 6.1. A GARBAGE COLLECTOR 14 6.2. S::L2CSTARTUP FUNCTION 14 6.3. AUTOMATIC S::L2CSTARTUP GENERATION 14 6.4. SCOPING 14 6.5. MEM FUNCTION 14 6.6. DEBUGGER 14 7. A PROGRAMMER'S VIEW 15 7.1. SymExp 15 7.2. A FUNCTION CALL MECHANISM 15 7.3. NAMING CONVENTIONS 16 APPENDIX 17 A. EXAMPLE: DLINE.LSP 17 1. INTRODUCTION Lisp2Cads translates an AutoLISP source file(s) into C source files that can be further compiled using the Watcom or Metaware C compiler. Why would anyone bother to compile the existing .LISP code? First, this completely protects your algorithms. If you use ordinary AutoLISP, you have to provide source that can be read by AutoCAD. But then it can also be read by a human. Therefore all of your know- how is exposed to everyone interested. Second, an ADS environment is gaining more and more acceptance. Lisp2C is a great way to preserve all your investments into Lisp (trainig, coding) and slowly moving to the ADS. And finally, Lisp2C also includes a debugging tool that is easy to use yet powerful. Requirements are: * AutoCAD R12 (Dos, Windows) * Watcom C/386 9.0 (9.01d required for Windows), or * Metaware C/C++ 3.1 and PharLap DOS Extender/Linker You need DOS4GW.EXE to run L2C.EXE! Lisp2Cads consists of: 1. QSTART.TXT How to quick - start LISP2C LISP2C.DOC This file (Word for Windows) LISP2C.TXT This file (ASCII) 2. L2C.EXE Lisp to C compiler 3. L2C.H Header file, included into source 4. L2C.LIB Libs: (Watcom -DOS) WINL2C.LIB (Watcom - Windows) MWL2C.LIB (Metaware - DOS) MWWINL2C.LIB (Metaware - Windows) 5. DEMO.LSP Sample Lisp program 6. DLINE.LSP Sample LISP from ACAD12 STARTUP.LSP Direct statements from DLINE DLINE.L2C Project file to compile DLINE.LSP Other example files may appear in distribution. 2. INSTALLATION 2.1.DOS - WATCOM Install your Watcom C/386 9.0 or later compiler and compile at least one sample file (eg TOWER.C) from \ACAD\ADS, to ensure that the compiler is set up properly. Place the files L2C.EXE (Lips2C translator) and DOS4GW.EXE (Watcom DOS extender) into directory pointed by a system variable PATH. We suggest C:\DOS or C:\ACAD directory. Place L2C.LIB and L2C.H files into \ACAD\ADS directory. Point to this directory with L2C variable: SET L2C=C:\ACAD\ADS Change INCLUDE variable to include \ACAD\ADS directory: SET INCLUDE=C:\WATCOM\H;C:\ACAD\ADS 2.2.DOS - METAWARE Install your Metaware HighC/C++ 3.1 compiler and compile at least one sample file (eg TOWER.C) from \ACAD\ADS, to ensure that the compiler is set up properly. Place the files L2C.EXE (Lips2C translator) and DOS4GW.EXE (Watcom DOS extender) into directory pointed by a system variable PATH. We suggest C:\DOS or C:\ACAD directory. Place MWL2C.LIB and L2C.H files into \ACAD\ADS directory. Point to this directory with L2C variable: SET L2C=C:\ACAD\ADS Change IPATH variable to include \ACAD\ADS directory: SET IPATH=C:\HIGHC\H;C:\ACAD\ADS Note that paths must be set before Lisp file is converted into C source. L2C uses the values of these variables to produce .BAT and .MW files. If those values are not set or set properly, .BAT and .MW files may not compile the C files. This does not, however, corrupt produced C code in any way. 2.3.WINDOWS - WATCOM Install your Watcom C/386 9.01d or later compiler and compile at least one sample file (eg TOWER.C) from \ACADWIN\ADS, to ensure that the compiler is set up properly. Place the files L2C.EXE (Lips2C translator) and DOS4GW.EXE (Watcom DOS extender) into directory pointed by a system variable PATH. We suggest C:\DOS or C:\ACADWIN directory. Place L2CWIN.LIB and L2C.H files into \ACADWIN\ADS directory. Point to this directory with L2C variable: SET L2C=C:\ACADWIN\ADS Change INCLUDE variable to include \ACADWIN\ADS: SET INCLUDE=C:\WATCOM\H;C:\ACADWIN\ADS Copy the file ADS.ICO from ADS\WIN directory to your working directory. 2.4.WINDOWS - METAWARE Install your Metaware HighC/C++ 3.1 compiler and compile at least one sample file (eg TOWER.C) from \ACADWIN\ADS, to ensure that the compiler is set up properly. Tip: Read README.ADS from ACADWin. Use -NOSTUB switch with PharLap linker 5.0 or later. Earlier versions of PharLap do not need this switch. Place the files L2C.EXE (Lips2C translator) and DOS4GW.EXE (Watcom DOS extender) into directory pointed by a system variable PATH. We suggest C:\DOS or C:\ACAD directory. Place MWL2CWIN.LIB and L2C.H files into \ACADWIN\ADS directory. Point to this directory with L2C variable: SET L2C=C:\ACADWIN\ADS Change IPATH variable to include \ACADWIN\ADS directory: SET IPATH=C:\HIGHC\H;C:\ACADWIN\ADS Note that paths must be set before Lisp file is converted into C source. L2C uses the values of these variables to produce .BAT and .MW files. If those values are not set or set properly, .BAT and .MW files may not compile the C files. This does not, however, corrupt produced C code in any way. Copy the file ADS.ICO from \ACADWIN\ADS\WIN directory to your working directory. Again, this only affects the compilation with produced .BAT and other files. 2.5. DOS Example (Watcom) Place the rest of the files into your working directory. These files are included only as a demonstration and can be deleted altogether. Example: Let us assume that you have correctly set up the Watcom C/386 9.0 to the C:\WATCOM directory. Thus, when you type SET, you might see something like PATH=...C:\ACAD;C:\WATCOM\BIN;C:\WATCOM\BINB ;C:\WATCOM\LIB386\DOS;... WATCOM=C:\WATCOM\. INCLUDE=C:\WATCOM\H In order to use ADS, your C:\ACAD\ADS directory should contain at least the following files: WCADS90.LIB ADSLIB.H ADSDLG.H ADS.H ADSCODES.H If those files are missing, you can copy them from our distribution. Now you can copy L2C.EXE to C:\ACAD directory (listed in path), and L2C.H, L2C.LIB into C:\ACAD\ADS directory. Also, you should change the INCLUDE variable so that Watcom C/386 will search for header (.h) files also in C:\ACAD\ADS directory: SET INCLUDE=C:\WATCOM\H;C:\ACAD\ADS And finally, you should set the L2C system variable to C:\ACAD\ADS: SET L2C=C:\ACAD\ADS 3. THE USAGE 3.1. COMMAND LINE INPUT The syntax is: L2C [options] file [file...] where options are d includes debugging information oname sets the output file name to 'name', instead to the name of 1st input file name c compiler (cWAT = Watcom, cMW = Metaware) e compiles every function separately y "yes" to all questions (except for the registration) n "no" to all questions (except for the registration) t target (currently Dos or WIndows) ? displays simple help The option must be preceded with either / or - character. If an invalid option is specified, program terminates with a message. File is the name of AutoLISP source file. L2C produces file.C file (if more than one file is specified, the first name is taken, unless /oname option is used). In addition, one file is produced for each (defun...) and (lambda...) These additional files have the name of the main file file padded with underscores ("_") to the length of total 8 (eight) characters, and then up to the last three characters are replaced with a number, starting from 0. If two different applications are compiled on the same directory, then the corresponding main file names must differ in first five characters, or the files of one application will tackle with the files from the other application. The order of files and options is insignificant. They can also be mixed. Example: to compile DLINE.LSP, one could use the following command: L2C ai_utils startup /odline dline /d which would compile AI_UTILS.LSP, STARTUP.LSP, and DLINE.LSP into DLINE.C and DLINE__0.C, ..., DLINE_64.C, DLINE.BAT, DLINE.MAK, and DLINE.LNK. For Windows, also DLINE.RC and DLINE.DEF would be generated. 3.2. INTERACTIVE INPUT Alternatively, one can invoke L2C without parameters: L2C Input file name (.lsp): The user then enters one file name per line. The input is terminated with a blank line. Then the question appears: Include debugging information (/No/?): The answer "Yes" is equivalent to specifying the /d switch. The answer "No" is equivalent to omiting that switch. Next, the target environment and compiler are specified: Target (/Windows/?): Compiler (/Metaware/?) Currently supported are DOS and Windows 3.1 operating systems. The code produced is the same in both cases. However, the support files (.BAT, .MAK, .LNK, and optionally .RC and .DEF) files are different for those two environments. Those two questions correspond to /t and /c switches. Next, the way how produced source code will be compiled, is choosen: Arrange for separate compilation of each file (Yes//?): This question corresponds to the /e switch. The answer "Yes" is equivalent to specifying that switch, and the answer "No" is equivalent to omitting it. Next, an answer to all questions can be specified: Answer to all questions (Yes/No//?): This question corresponds to /y and /n switches. The answer "Yes" is equivalent to specifying the /y switch, the answer "No" is equivalent to specifying the /n switch, and the answer "Ask" is equivalent to omitting both two switches. Next, the code commenting can be disabled: Comment the produced code (/No/?): This question corresponds to /b switch. The answer "Yes" is equivalent to specifying that switch and the answer "No" is equivalent to omiting it. Finally, user can specify the output file name: Output file name (5 chrs significant) <>: This question corresponds to an /o switch. In angle brackets, the name of the first file appears as a default output file name. If the default file name is longer than 5 characters, then only the first five characters are in the upper case, and the rest are in the lower case letters. One should be aware, that Lisp2Cads will use only the first 5 characters for all files but the main .C file, the .BAT file, and the .LNK file. Example: to compile DLINE.LSP, one could use the following command: L2C Input file name (.LSP): AI_UTILS Input file name (.LSP): STARTUP Input file name (.LSP): DLINE Input file name (.LSP): Include debugging information (/No/?): Yes Target (/Windows/?): Dos. Compiler (/Metaware/?): Watcom Output file name (5 char..) : DLINE which would compile AI_UTILS.LSP, STARTUP.LSP, and DLINE.LSP into DLINE.C and DLINE__0.C, ..., DLINE_64.C, DLINE.BAT, and DLINE.LNK. 3.3. PROJECT FILE The third option is to invoke the compiler with the name of the project file, preceded with an @ character. Project file is an ASCII file. Each line is either a comment (starts with an * (asterisk) or ; (semicolon) in the 1st column), a file name, or an option. The syntax for options is the same as in the command line case. A sample project file (with no comments) might look like: ai_utils startup dline /odline /d /tWIN /cWAT /n The default extension for a project file is .L2C. You can specify a full project file name, if necessary. Example: to compile DLINE.LSP, one could use the following command: L2C @DLINE which would compile AI_UTILS.LSP, STARTUP.LSP, and DLINE.LSP into DLINE.C and DLINE__0.C, ..., DLINE_64.C, DLINE.BAT, DLINE.MAK, and DLINE.LNK. 3.4. SWITCHES /D - Debugging When this switch is used, a code is added to every function that prints out the function name and its arguments, and simple debugger is enabled Also, batch and link files are set to include the debugging information. You will find more information about debugger in Section 6.3. /Oname - Output filename You can specify the output file name. If none is specified, the first file name is taken. /C - Compiler Currently supported are Watcom C/386 compiler (/CWAT) and MetaWare High C/C++ compiler (/CMW). By default, compiler assumes Watcom C/386. If you use MetaWare C/C++, then use /CMW switch. /E - Separate compiling By default, all the functions are included to the main file during compile time. In this way, the C compiler has only to be loaded once, and the compilation process is significantly faster. Using /E switch, you force the L2C to produce several source files; one main source and one source file for every LISP function. They are compiled separately and then linked together. This way, you can edit functions without recompiling all the source code over and over again. Note that this is not simply the question of the batch and link files produced by L2C. The headers of C source files are also different. /Y - YES to all questions /N - NO to all questions Specifies that answers to all the questions are Yes or No, respectively. If you specify both switches, the last is used. These two switches do not apply to the question on registration. /T - target system (DOS or Windows) The target is the system under which the compiled application will be running. Currently two target systems are supported: MS-DOS and MS-Windows. To choose MS-DOS as a targeting environment, use /TDOS switch. To use MS-Window as a targeting system, use /TWIN switch. The former is default. The code generated is the same for all the targets. The difference is in the files that Lisp2C produces to compile the application. /B - brief code generator Normally, Lisp2C inserts corresponding parts of Lisp code as a comment to the prodused C code. This is intended to ease the code modification process. However, the size of produced .C files is expanded significantly. If you don't intend to modify the code or you don't have enough disk space, specify /b switch to surpress the insertion if the comments. /? - Help This switch displays a simple remainder of the switches and stops the compiler execution. 3.5. COMPILING THE CODE (WATCOM) The C source file must be translated with Watcom C/386 compiler. The object (.OBJ) file produced by Watcom C/386 compiler must be further linked together with WCADS90.LIB and L2C.LIB libraries under DOS, or with WINADS.OBJ, WINADS.LIB and WINL2C.LIB libraries under Windows. To simplify the job, Lisp2C translator, automatically produces several files, a batch file named name.BAT, make file name.MAK, a link file name.LNK, and possibly simple resource file name.RC and a simple definition file name.DEF. Batch file invokes the make utility to compile and link all files into an .EXP file under DOS, or .EXE file under Windows. The file file.LNK uses the system variable L2C to locate the libraries. If the user hasn't preset the variable, file.BAT sets it to point to a \ACAD\ADS directory (on the current drive). If a single file is to be compiled, the command wcc386p /mf /3s /fpi87 can be used for a DOS target. The meanings of the options are /mf generate the code for the flat memory model, /3s pass the arguments on the stack, /fpi87 generate in-line calls to a math coprocessor. Similar command for Windows environment would be wcc386p /mf /3s /fpi87 /s /j /opmaxet /dWIN /dWATWIN /zW where /mf generate the code for the flat memory model, /3s pass the arguments on the stack, /fpi87 generate in-line calls to a math coprocessor, /s remove stack overflow checks, /j change char default from unsigned to signed, /opmaxet controls several optimization parameters, /dWIN defines WIN symbol (as with #define), /dWATWIN defines WATWIN symbol, and /zW uses Microsoft Windows entry/exit code. Note that, during the compilation, a compiler might issue several warning messages. They refer to undefined macro symbols (used in other systems), unreachable statements, and unreferenced variables. This is perfectly OK, as long as no error is produced. 3.6. LINKING (WATCOM) To link the compiled files together, it is best to use the generated linker file, as all the file names must be listed. A command wlink @file.lnk should do the trick. However, do not forget the "@" symbol or the file extension! The resulting file.EXP file is ready to be XLOADed. 3.7. BINDING (WATCOM) When compiling for Windows environment, the linker produces .REX file. This file has to be further binded with resource and definition files, file..RC and file.DEF, respectively. This can be achieved with the command wbind file -R file.rc file.exe Make sure that the ADS.ICO file is placed in the current directory, You can find that file in \acadwin\ads directory. Example. To compile DEMO.LSP the command L2C DEMO produces the following C source and some support files: DEMO.C contains the main loop DEMO__0.C code for (defun qsort ...) DEMO__1.C code for (defun c:stat ...) DEMO__2.C code for (defun c:gc ...) DEMO__3.C code for (defun c:interpreter ...) DEMO__4.C code for (defun S::STARTUP ...) DEMO.BAT batch files that starts make utility, DEMO.MAK make file, DEMO.LNK link file used by DEMO.MAK. DEMO.RC is produced under Windows only, a resource file. DEMO.DEF is produces under Windows only, a definition file. Then the command DEMO produces (among others) ADS module, DEMO.EXP file , which can be later loaded into AutoCAD with the command (xload "demo"). Under Windows, DEMO.EXE is produced, which can be XLOADed into AUTOCAD for WIndows. 4. SUPPORTED FUNCTIONS Lisp2Cads *DEMO* supports AutoLISP R12 functions, except AME and ASE support. Here is the brief list of supported functions: (* *error* + - / /= 1+ 1- < <= = > >= abs alloc and append apply ascii assoc atan atof atoi atom atoms-family(*) boole boundp caaaar caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar caddar cadddr caddr cadr car cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr cddr cdr chr cond cons cos defun eq equal eval exit exp expand expt fix float foreach gc gcd getenv if itoa lambda last length list listp load log logand logior lsh mapcar max mem member min minusp not nth null numberp open or prin1 princ print progn quit quote read read-char read-line rem repeat reverse set setq sin sqrt strcase strcat strlen subst substr terpri trace type untrace ver vmon while write-char write-line zerop ~ acad_colordlg acad_helpdlg acad_strsort ads alert angle angtof angtos command cvunit distance distof entdel entget entlast entmake entmod entnext entsel entupd findfile getangle getcorner getdist getfiled getint getkword getorient getpoint getreal getstring getvar graphscr grclear grdraw grread grtext grvecs handent initget inters menucmd nentsel nentselp osnap polar prompt redraw regapp rtos setvar ssadd ssdel ssget sslength ssmemb ssname tablet tblnext tblsearch textbox textscr trans vports wcmatch xdroom xdsize xload xunload load_dialog unload_dialog new_dialog new_dialog start_dialog done_dialog term_dialog action_tile mode_tile get_attr get_tile set_tile start_list add_list end_list dimx_tile dimy_tile start_image vector_image fill_image slide_image end_image client_data_tile) 5. DIFFERENCES AND LIMITATIONS 5.1. EXPRESSIONS OUTSIDE THE FUNCTIONS Only Lisp expressions inside Lisp functions are compiled. Other expressions are merely skipped (and a warning message is generated). They can be collected automatically into S::L2CSTARTUP function (into the file ?????__S.LSP). 5.2 NUMBER OF ARGUMENTS User functions in Lisp2Cads can only have up to 32 arguments if they are ever to be evaluated using EVAL, APPLY or MAPCAR function. 5.3. PASSING SYMBOLS, SUBROUTINES ETC. Currently, there is no (regular) way to exchange SYMbols, SUBRoutines, EXSUBRoutines and some other exotic data types between an ADS application and an AutoLISP environment. Functions that expect symbols as their arguments (as when calling parameters by reference) should be rewritten in a way that they would accept strings as arguments and then READ out the symbol. This only applies to a function that is called from AutoLISP. Function called directly from another L2C function can pass symbols without any limitations. 5.4. PASSING LISTS OF INTEGERS ETC. The transfer of the objects between AutoLISP and an ADS application is not an exact one. For example, if the function FOO is invoked with a list of two integers as the only argument: Command: (FOO '(1 2)), then an ADS application will receive this as a 2D point, with integers already converted into reals. As most of the functions that expect real value they work well if given an integer argument, while the opposite might not be true, Lisp2Cads application will transform any whole element of 2D or 3D point passed from AutoLISP to integer. Therefore an unexpected results may occur every now and then. Example: AutoLisp value is seen by Lisp2C as AutoLISP Lisp2C (1 2 3) (1 2 3) (1.0 2.0 3.0) (1 2 3) (1.1 2.2 3.3) (1.1 2.2. 3.3) (1 2.2 3.3) (1 2.2 3.3) (1 2.0 3.3) (1 2 3.3) 5.5. BUILD-IN PRIMITIVES Build-in primitives are considered as a keywords in L2C. You should not use them as an ordinary symbols, or the results will be unpredictable. The only exception is the TYPE function, that returns 'SUBR type on *every* build-in primitive, except on ACAD_COLOR. Unfortunately, you cannot check whether an external function has to be loaded by matching its type against EXSUBR type symbol. 5.6. GLOBAL SYMBOLS When a global symbol is set, also its value in AutoLISP is updated, unless a value contains a non-re presentable datum (such as a symbol or a function). However, once a Lisp2C cannot pass a symbol value to an AutoLISP, it doesn't check that symbol's value in AutoLISP until a Lisp2C application assigns this symbol to a value such that it can be passed to an AutoLISP. (This is necessary as otherwise global symbols would either be number, strings or lists of numbers or strings, or they would evaluate to NIL.) This also gives rise to a simple trick that prevents Lisp2C from constantly updating value of a global symbol in AutoLISP. Assume, for example, that a global variable X must hold an integer value and that we don't want to pass this value to AutoLISP every time X is referenced (this passing mechanism can also be time-consuming). Therefore one would set X to a (dotted) pair (X . ) instead simply to a number. In this way Lisp2C will quickly determine it cannot pass a symbol's value to AutoLISP (as already it cannot pass the very first element of a list) and will in turn refuse to pass to or import from AutoLISP the value of X as long as X is stored in this format. And, as usually, the value of X can be obtained using CADR function. Anyway, it is generally much better practise to avoid using global variables as much as possible. 5.7. A SYMBOL TABLE A symbol table is used to store names (and values) of the symbols. Currently, symbol table has 631 entries. The hashing algorithm guarantees that at least half of the table will be used before Lisp2C will complain. 5.8. NENTSEL, NENTSELP Functions NENTSEL and NENTSELP will return a three-element list when the argument is a simple entity, with the third element being an identity matrix. 5.9. ATOMS-FAMILY It was virtually impossible to reproduce the bug in AutoLISP's (atoms-family ...) function. Therefore (atoms-family ...) returns only the list of the symbols (as a list of symbols or as a list of strings) without "nil's being inserted here and there. Sorry. 5.10. COMMAND In AutoLISP, (command) evaluates its arguments on-fly. To maintain compatibility, Lisp2C compiles the command (command arg1 arg2 ... argn) into (command arg1) (command arg2) ... (command argn) 5.12. SPEED Normally, the program runs faster when compiled with Lisp2C. But the global variables slow down the execution speed significantly. Avoid the usage of global variables wherever possible. Not to mention that global variables as a rule reflect a poor programming style. 6. FEATURES 6.1. A GARBAGE COLLECTOR The garbage collector not only reclaims a node space, but also releases unused selection sets and closes all unused files. When unloading the application, garbage collection is invoked automatically. 6.2. S::L2CSTARTUP FUNCTION This function, if present, is invoked automatically during XLOAD. It can already use all functions compiled with Lisp2Cads. 6.3. AUTOMATIC S::L2CSTARTUP GENERATION When the first statement that is not a function is read, you can select whether this and all subsequent statements should be collected into S::L2CSTARTUP function. You have to be careful, though, not to include (load ...) statements. It is generally better idea to compile the file than to (load) it. You are prompted for each statement whether to include it into S::L2CSTARTUP or not (as long as /N or /Y switches are not used). You can check the ?????__S.LSP function and edit it to meet your needs. Then you should rename it and recompile the program, adding this function to the file list (e.g. in project file), and, during second iteration, you should not generate this file again. Note: if you already have S::L2CSTARTUP on the disk and L2C generates its own one, the latter will be executed (for it is compiled later). 6.4. SCOPING Lisp2Cads supports entirely the scoping mechanism from AutoLISP interpreter. 6.5. MEM FUNCTION Function (MEM) now accepts a single optional argument. If present and not nil, MEM scans the symbol table and prints out the values of all the symbols. Note that symbol can have more then a single value, one in each instance of a function. 6.6. DEBUGGER The /d switch enables a L2C debugger. This has the following features: * the program execution can be monitored step by step, * intermediate results are printed out (optionally), * at the break point, any Lisp expression can be entered, so the symbols can be viewed and even set. When the break point is reached, the following message appears: Function , depth . Command . Here, is the Lisp name of the function that is being executed. is a depth, or level of the command that will be executed first. In the following example, the depth of every function is indicated with the corresponding number: (defun depth () (setq1 a (1+2 (*3 (sin4 x) (cos4 (read5 y))))) ) The is the command that will be executed next ("User function", if user function will be called). Then, the following commands are available: Over/Return/Go/Verbose/lisp expr <1>: * Over will step the execution at the first command having the same or smaller depth as the current command, in the scope of the current function. If a user function is called, another command in that function may have the same depth, but the execution will not be broken. If no other command inside this function has this or smaller depth, the execution will break at the end of the function. * Go will break the execution of the program only when returning to an AutoLisp * Return will break the execution of the program only at the end of the function. * environment. However, the next time some L2C-compiled function is invoked, the debugger is here again. * Verbose turns on the printing of the commands results. * Silent turns off the printing of the commands results. * lisp expr is any Lisp expression. This string is processed by (read...) and (eval..) pair. * <1> is the number of steps that are to be executed before the program execution is broken again. One (1) means single step, and greater numbers skip several steps. This has to be a non-negative integer. To effectively use a debugger, one has to have a printed LISP program (or function) being debugged. There is no line information (currently). 7. A PROGRAMMER'S VIEW 7.1. SymExp The SymExp .is a basic type in Lisp2C. It is similar in part to a resbuf structure in ADS, but more powerful. In short, it is designed to represent any Lisp data structure. The structure of SymExp can be found in L2C.H file. However, to preserve compatibility with the subsequent releases, you should not access parts of the structure directly, but rather through several procedures, provided for this purpose. These procedures include: SymExp MakeNumber (long); SymExp MakeReal (ads_real); SymExp MakeString (char *); SymExp MakeSymbol (char *); SymExp MakeFunction (SymExp (*f)()); SymExp MakeFile (FILE *); SymExp MakeEName (ads_name); SymExp MakePickSet (ads_name); SymExp MakePoint (ads_point); SymExp MakeMatrix (ads_matrix); 7.2. A FUNCTION CALL MECHANISM A call to a user written function (myfunc arg1 arg2 ... argn) is translated as follows. 1. The symbol myfunc is fetched from the symbol list table. 2. If the symbol is a function, then the function is called. 3. If the symbol is a list, it is evaluated. 4. In any other case, myfunc is invoked (via ads_invoke). There are n+1 arguments passed to a function. The last argument is always a EndArgList symbol. This convention is used to allow the functions having variable number of arguments. In AutoLisp one cannot write such a function. However, in C, this is no problem. Via va_start, va_arg, and va_end macros, one fetches one SymExp after anoter, until there is a EndArgList argument. Example: the following function will act as a (print ...), but accepting as many arguments as supplied. SymExp myfunc (SymExp S,...) { va_list args; SymExp arg; if (S == EndArgList) // no arguments return (NULL); LSP_Print (S, EndArgList); // 1st argument va_start (args, S); while ((arg = va_arg (args, SymExp)) != EndArgList) LSP_Print (S, EndArgList); va_end (args); } // myfunc Note that you have to modify either L2C.H file (highly unrecommended), or an aplicattionīs header file, and accordingly either modify one of the source files, or the make file, to compile this function and link it to the application. Further releases of Lisp2C will include additional mechanisms to assist you in creating your own libraries. 7.3. NAMING CONVENTIONS Wherever possible, LISP symbol names are kept in C source files. To avoid name collision, they are being capitalised (first letter in uppercase and the rest in lowercase letters). In addition, all build-in functions have a prefix LSP_ or ADS_, and might have more letters in uppercase. Special characters (everything other than a letter, digit, or underscore) cannot be handled by C. This characters are replaced with a three-letter code (e.g., a colon (:) is replaced with COL). This guarantees that two different names in LISP will translate into two different names in C, and additionally, no LISP name can match the name of functions in Lisp2C library, as all functions in this library have more than one capital letter, and none contains any three-letter sequence mentioned above. APPENDIX A. EXAMPLE: DLINE.LSP As an example, we shall examine closer the translation of DLINE.LSP file (located in your AutoCAD SUPPORT directory) for AUTOCAD/386. The following steps should be followed: A number of files will be produced during the compilation, so it is best to do all the compilation in a separate directory. Make sure you can run L2C.EXE program (either place a copy of it in the working directory, or place it into a directory listed in PATH). Make sure that Watcom compiler will be able to locate L2C.H header file (Watcom compiler can locate any header file in current directory or in the directory pointed to by a system INCLUDE variable) and make sure that L2C system variable is pointing to a directory containing both WCADS90 and L2C library files. In general, read section 2 again. Once you have a working directory, copy the file DLINE.LSP from \ACAD\SUPPORT directory (you might have a different name, and perhaps a drive letter is necessary as well). As stated in section 5.1., lisp expressions that are not inside a function are ignored. As those expressions are usually evaluated during load time, it is important to understand what they are doing. In our case, the expression at the line 204 loads the file containing the support functions. Therefore, we must copy the file AI_UTILS.LSP form \ACAD\SUPPORT directory as well. Look further. At the lines 2121-2124 four global variables are set that enables DLINE command to retain several parameters between two successive calls. The obvious solution would be to copy those four expressions into another file, say DL.LSP, and load that file *before* calling DLINE command. Unfortunately this won't work. The reason is that both dl:snp and dl:brk are set to T, and T is a symbol. According to 5.5 and 5.7., one cannot pass a symbol from AutoLisp to Lisp2Cads. The correct solution is to copy these expressions into a file, say STARTUP.LSP, and enclose them into a function S::L2CSTARTUP . In this way those variables will be set during xload. Your STARTUP.LSP file should now look something like this: (defun S::L2CSTARTUP () (if (null dl:ecp) (setq dl:ecp 4)) ; default to auto endcaps (if (null dl:snp) (setq dl:snp T)) ; default to snapping ON (if (null dl:brk) (setq dl:brk T)) ; default to breaking ON (if (null dl:osd) (setq dl:osd 0)) ; default to center align ) and in your working directory you should have the following files: DLINE.LSP AI_UTILS.LSP STARTUP.LSP We could now compile those files with a single command: L2C DLINE AI_UTILS STARTUP The order of the parameters is not important. However, we would place DLINE.LSP file the first, to get DLINE??? file names But there is an easier way. Using a project file (supplied with a distribution), one only has to say: L2C @L2C During the compilation, L2C encounters the statements that are not inside any functions. After the first statement, (LOAD ...) function is read, L2C asks Create DLINE__S.LSP with S::L2CSTARTUP? (/No) As we already have our own S::L2CSTARTUP function, we answer "No". L2C produces files: DLINE.C main loop DLINE__0.C 1st function DLINE__65.C last function DLINE.BAT this one compiles everything DLINE.LNK We can now compile and link the application using the command DLINE Watcom C/386 9.0 complains every time for a symbols that are not defined. This is perfectly all right as long as there are 5 warnings per file. Anything more is suspicious and should be reported immediately. If everything went OK (and it should), you are ready to xload the application. Start AutoCAD and at the Command: prompt type: (xload "dline") Ljubljana, 22th June 1993 STARTUP.LSP is also supplied with Lisp2Cads, in case you don't fill like typing. Lisp2C 1.9 25.06.93 (C) BASIC d.o.o. 2