Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Malformed list on input

19 REPLIES 19
SOLVED
Reply
Message 1 of 20
cncah
21393 Views, 19 Replies

Malformed list on input

I'm having an error thrown on me in the first line of a new program I'm trying to write. I've read that you want to localize your variables in parentheses after the c:name. But when I put the values in there it flags an error on me saying malformed list on input. Here is what it looks like:

 

(defun c:f2scfrt ( / *error* osm ipt1 ipt2 midX midY angent lftwall)

 

I've tried lowercase, uppercase doesn't seem to matter. If I take out all that and just leave ( / ). Then the program loads and I can start trying to debug the program. I'm new to autolisp and am trying to learn the best I can. I'm currently trying to use the tutorial on error handling from Lee Mac's website. Very nice website, trying to learn the best I can from examples he uses. Is there a good book that someone could suggest that would be pretty much like: AutoLISP For Dummies? I've tried looking at the autodesk reference guide, but it is pretty vague and doesn't go into any detail on the individual subjects. I'm picking up some good basics from AfraLISP and the JeffreyPSanders websites as well. I'm just basically needing to know if I can leave the defun line in my program ( / ) or if I need to figure out a way to add my setq values in there to localize them. Any help is appreciated. Thanks.

19 REPLIES 19
Message 2 of 20
hmsilva
in reply to: cncah

The "malformed list on input" usually means unbalanced brakets, therefore nothing to do with localize variables.


Post your code, will be easier to assist.

 

Al the sites mentioned by you, are very good places to learn, but don't forget the AutoLISP Reference, the AutoLISP Devoloper's Guide and the AutoLISP Tutorial from the Help files.

 

Henrique

EESignature

Message 3 of 20
Lee_Mac
in reply to: cncah

Firstly, thank you for your compliments for my site - I hope my tutorials are clear & somewhat comprehensible Smiley Happy

 

As Henrique points out, the 'malformed list on input' error indicates unbalanced parentheses - specifically, you have too few closing parentheses for the number of open parentheses. I have written an overview explaining the possible meaning of some of the most common error messages which you may find here for your reference.

 

To help you to find the imbalance, if you are using the Visual LISP IDE* (and if not, I would strongly suggest that you do use it!) note that you can double-click before an open parenthesis or after a closing parenthesis in order to highlight all code enclosed by that expression:

 

vlidematchparens.gif

 

 

*If you are new to the Visual LISP IDE, here are some tutorials to get you started:

 

The Visual LISP Editor - Part 1

The Visual LISP Editor - Part 2

An Introduction to the Visual LISP IDE

Retrieving Information About a Function

A Shortcut to Localising Variables

Debugging Code with the Visual LISP IDE

Message 4 of 20
stevor
in reply to: cncah

Yah, me too. In addition to the parens, you also can have unbalanced " marks, that can cause several error. And 2 single ' marks do not make a ". Sometimes doing a setwise search thru the " characters is required. For the parens, there are free text editors that will illuminate the matching paren of a selected paren. Notepad2.exe is one of them.
S
Message 5 of 20
cncah
in reply to: Lee_Mac

Here is a simple program (well simple for others I guess) that I'm trying to write just to get some basics down. It's for importing toolpath geometry from other dwg files. What I'm wanting to do, is insert commonly used blocks from other parts so that programming the 1000's of parts for our cnc router will go a little faster. I'm currently having to navigate through the insert block window, and ever since I found out about AutoLISP, I want to try and automate or cut out the repetition as much as humanly possible. Our company puts out thousands upon thousands of different parts, just for the router, that have to be programmed by myself, and then if there is a revision made, I'm reprogramming those parts all over again. So the more automated I can get, the happier I'll be. What I'm trying to do with this program is just have the user enter yes or no if they want to insert a certain block into the drawing. Thanks for the tip about double clicking after a parentheses and seeing where the expression starts and stops. I have been using vlide from a dummy drawing to go into the editor and write and de-bug the lisp programs. The parentheses checking is very helpful. So far I've gotten the program to run to the end it seems, but instead of finishing gracefully it gives me this error at the end:

 

;error: AutoCAD variable setting rejected: "Osmode" nil

 

I tried using the error handling tutorial from Lee Mac's website so that if someone else at the company was trying to use the software and my program, they wouldn't lose their osnap settings if they hit esc. I guess I still don't have some things quite right in here. I appreciate the reference guides everyone suggested. I'll be sure to check those out ASAP. Thanks for all the help. It's greatly appreciated.

 

P.S. How do I place a prompt comment in the program, so that when I have this tweaked out and in the StartUp-Suite, I open up a drawing, and it displays <Type "cmb" To Start Block Insert Program> ?

Message 6 of 20
Lee_Mac
in reply to: cncah

A few things I notice immediately:

 

You store the value of the osmode system variable using the variable 'oldosm', but in the *error* function, you use a variable 'osm':

 

(defun *error* ( msg )
    (if osm (setvar 'osmode osm))
    ...
)
...
(setq oldosm (getvar "Osmode"))

 

You have an extra closing parenthesis which ends the function definition (defun) immediately after storing & setting the system variable values:

 

    ) ;End of storing old user settings

 

 

Message 7 of 20
Lee_Mac
in reply to: cncah

This should get you going in the right direction:

 

(defun c:cmb ( / *error* cmd ins osm )

    ;; Define local error handler to reset CMDECHO & OSMODE
    (defun *error* ( msg )
        (if cmd (setvar 'cmdecho cmd))
        (if osm (setvar 'osmode  osm))
        (if (not (member msg '("Function cancelled" "quit / exit abort")))
            (princ (strcat "\nError: " msg))
        )
        (princ)
    )
    
    ;; Store current values of OSMODE & CMDECHO system variables
    (setq osm (getvar 'osmode)
          cmd (getvar 'cmdecho)
    ) ;; end setq
    
    ;; Set the sys vars to their required values
    (setvar 'osmode  3)
    (setvar 'cmdecho 0)

    ;; Initialise keyword options
    (initget "Yes No")
    ;; Prompt user
    (if (= "Yes" (getkword "\nInsert Pkt_Radius_0.3583RH? [Yes/No] <No>: "))
        ;; Prompt user for insertion point
        (if (setq ins (getpoint "\nPick insertion point: "))
            (command
                "_.-insert"
;| *=explode |; "*PktRadius3583RH" ;; Program assumes this block exists
                "_S" 1.0 ;; Block Scale = 1
                "_R" 0.0 ;; Block Rotation = 0
                "_non" ;; Ignore Object Snap for the next input
                ins
            ) ;; end command
        ) ;; end if
    ) ;; end if

    ;; Initialise keyword options
    (initget "Yes No")
    ;; Prompt user
    (if (= "Yes" (getkword "\nInsert Pkt_Radius_0.3583LH? [Yes/No] <No>: "))
        (if (setq ins (getpoint "\nPick insertion point: "))
            (command
                "_.-insert"
;| *=explode |; "*PktRadius3583LH" ;; Program assumes this block exists
                "_S" 1.0 ;; Block Scale = 1
                "_R" 0.0 ;; Block Rotation = 0
                "_non" ;; Ignore Object Snap for the next input
                ins
            ) ;; end command
        ) ;; end if
    ) ;; end if

    ;; Reset sys vars
    (setvar 'cmdecho cmd)
    (setvar 'osmode  osm)
    (princ "\nEnd of program.")
    (princ) ;; Supress the return of the last evaluated expression
) ;; end defun
(princ "\n<Type \"cmb\" To Start Block Insert Program>") ;; Loading expression
(princ) ;; Supress the return of the last evaluated expression on load

 

Note that for the sake of simplicity for your understanding, the above program does not test whether the blocks exist.

 

Lee

Message 8 of 20
hmsilva
in reply to: Lee_Mac

Lee Mac wrote:

"...for the sake of simplicity for your understanding..."

 

Nicely explained, Lee! Smiley Happy <Kudos>

 

Cheers

Henrique

EESignature

Message 9 of 20
cncah
in reply to: Lee_Mac

Lee,

 

      Thank you very much for the fix to the program, I had noticed I had changed the osm variable in the program after I had uploaded it to the site, that's my bad. I appreciate you showing me how to use the if function properly. I didn't have the program structured correctly at all by the looks of it. I had seen the trick of using the * in front of the filename to explode it upon insertion before in my research, and have tried it many times, but can never get it to work. Doesn't seem to matter if I describe the full path to the file, or if I move the files to the active document and just call out the filename without inputting the path info. Also, thanks for the tip of using _non to tell it to ignore the snap settings for insertion. I think that may be causing myself an issue on another program I've been trying to mess with that's a bit more compilicated. I had to move the scale factor and the input for the rotation angle to individual inputs after the _S and _R commands. Was making the program throw an error saying invalid input having it like this in the program "_S" 1.0. This is what I ended up with and it runs great:

 

(defun c:cmb ( / *error* cmd ins osm )

    ;; Define local error handler to reset CMDECHO & OSMODE
    (defun *error* ( msg )
        (if cmd (setvar 'cmdecho cmd))
        (if osm (setvar 'osmode  osm))
        (if (not (member msg '("Function cancelled" "quit / exit abort")))
            (princ (strcat "\nError: " msg))
        )
        (princ)
    )
   
    ;; Store current values of OSMODE & CMDECHO system variables
    (setq osm (getvar 'osmode)
          cmd (getvar 'cmdecho)
    ) ;; end setq
   
    ;; Set the sys vars to their required values
    (setvar 'osmode  3)
    (setvar 'cmdecho 0)

 

;Start Of Block Insertion Program---------------------------------------------------

 

;Pkt_Radius_0.3583RH----------------------------------------------------------------

 

    (initget "Yes No")
    (if (= "Yes" (getkword "\nInsert Pkt_Radius_0.3583RH? [Yes/No] <No>: "))
        (if (setq ins (getpoint "\nPick insertion point: "))
          (progn
            (command
                "_.-insert"
                "PktRadius3583RH"
                "_S"
                "1.0" ;; Block Scale = 1
                 "_R"
                "0.0" ;; Block Rotation = 0
                "_non" ;;Ignore osnaps for block insertion
                ins
                ) ;; end command
            (command "_explode"
                             "last") ;;Explode last inserted block
     )
        ) ;; end if
    ) ;; end if

 

;Pkt_Radius_0.3583LH----------------------------------------------------------------
 
    (initget "Yes No")
    (if (= "Yes" (getkword "\nInsert Pkt_Radius_0.3583LH? [Yes/No] <No>: "))
        (if (setq ins (getpoint "\nPick insertion point: "))
          (progn
            (command
                "_.-insert"
                "PktRadius3583LH"
                "_S"
                "1.0" ;; Block Scale = 1
                "_R"
                "0.0" ;; Block Rotation = 0
                "_non" ;;Turn osnaps off for block insertion
                ins
                ) ;; end command
          (command "_explode"
                           "last") ;;Explode last inserted block
     )
        ) ;; end if
    ) ;; end if

 

;End Of Block Insertion-------------------------------------------------------------

 

    ;; Reset sys vars
    (setvar 'cmdecho cmd)
    (setvar 'osmode  osm)
    (princ "\nEnd of program.")
    (princ) ;; Supress the return of the last evaluated expression
) ;; end defun
(princ "\n<Type \"cmb\" To Start Block Insert Program...>") ;; Loading expression
(princ) ;; Suppress the return of the last evaluated expression on load

 

 

I appreciate the help with the training and getting me out of the rut I was in. As always Lee you have helped me out tremendously and I thank you. I'm going to start adding all the other blocks that I need to this program and will refer to it as my template when writing new programs. Thank You Very Much!!!

Message 10 of 20
Lee_Mac
in reply to: hmsilva

Thank you Henrique!

 

The program could be enhanced further, but I didn't want to deviate too far from the original code so as not to overwhelm the OP. Smiley Happy

 

Lee

Message 11 of 20
Lee_Mac
in reply to: cncah


@cncah wrote:
Thank you very much for the fix to the program

 You're welcome! Smiley Happy


@cncah wrote:

I had seen the trick of using the * in front of the filename to explode it upon insertion before in my research, and have tried it many times, but can never get it to work. Doesn't seem to matter if I describe the full path to the file, or if I move the files to the active document and just call out the filename without inputting the path info.


The use of the asterisk only works when supplying only the block name to the -INSERT command (i.e. when the block is either already defined in the drawing, or the drawing file for the block resides in an AutoCAD Support File Search Path).


@cncah wrote:

This is what I ended up with and it runs great:

 

(defun c:cmb ( / *error* cmd ins osm )

    ...

)


Excellent - I'm glad you were able to get the program working as required.

 

A couple of minor suggestions:

 

1) You could combine the two command expressions into one, removing the need for progn:

 

          (progn
            (command
                "_.-insert"
                "PktRadius3583RH"
                "_S"
                "1.0" ;; Block Scale = 1
                 "_R"
                "0.0" ;; Block Rotation = 0
                "_non" ;;Ignore osnaps for block insertion
                ins
                ) ;; end command
            (command "_explode"
                             "last") ;;Explode last inserted block

  becomes:

 

(command
    "_.-insert"
    "PktRadius3583RH"
    "_S" "1.0"
    "_R" "0.0"
    "_non" ins
    "_.explode"
    "_last"
)

 

2) Instead of separately prompting the user for an insertion point, you could take advantage of the ghosting effect afforded by the -INSERT command, i.e. this:

 

    (initget "Yes No")
    (if (= "Yes" (getkword "\nInsert Pkt_Radius_0.3583RH? [Yes/No] <No>: "))
        (if (setq ins (getpoint "\nPick insertion point: "))
          (progn
            (command
                "_.-insert"
                "PktRadius3583RH"
                "_S"
                "1.0" ;; Block Scale = 1
                 "_R"
                "0.0" ;; Block Rotation = 0
                "_non" ;;Ignore osnaps for block insertion
                ins
                ) ;; end command
            (command "_explode"
                             "last") ;;Explode last inserted block
     )
        ) ;; end if
    ) ;; end if

 

Becomes:

 

(initget "Yes No")
(if (= "Yes" (getkword "\nInsert Pkt_Radius_0.3583RH? [Yes/No] <No>: "))
    (if (vl-cmdf "_.-insert" "PktRadius3583RH" "_S" "1" "_R" "0" "\\")
        (command "_.explode" "_last")
    )
) 

@cncah wrote:

I appreciate the help with the training and getting me out of the rut I was in. As always Lee you have helped me out tremendously and I thank you. I'm going to start adding all the other blocks that I need to this program and will refer to it as my template when writing new programs. Thank You Very Much!!!


Thank you for your gratitude for my time & assistance - you are most welcome.

 

Message 12 of 20
cncah
in reply to: Lee_Mac

Ok Lee, I've got a new one for you. A lot of the blocks I need to insert are the same size and dimensions, the only difference is the thickness assigned to that particular entity. But, for the router software, the layer name has to have that thickness at the end of the layer name. Example being, several of the blocks are named Pkt_Radius_0.0000. The thickness is the difference in each instance. Some of the blocks I insert on a regular basis are Pkt_Radius_0.3583, Pkt_Radius_0.4110, Pkt_Radius_0.5410. I tried to modify the program to insert a block that has no thickness, and the layer name is Pkt_Radius_. Then I would prompt the user to input the thickness desired as a negative number. (It has to be a negative number.) Then when I do a _.chprop command the setq variable I assigned to the thickness gets put into that command to change the thickness. But after that I would like to convert that number to a positive number, and add it to the end of the layer name. So that Pkt_Radius_ would become Pkt_Radius_0.3583. I used abs to convert the negative to a positive number and setq that to a new variable name, then when I try using append or cons to add the two variables together to get a new layer name, it keeps throwing an error on me. Some research I did showed having to get the layer table, and converting the entity to a vla-object and all that to get the layer name for that entity I'm modifying. But it seems to me like I wouldn't have to go through all that if I know what the previous layer name was already. I appreciate any help. This is the code I have most recently, and it still doesn't work:

 

 

(setq en1 (entlast)) ;;Sets the last inserted entity as the one being changed

(setq thk (getreal "\nEnter Thickness For Inserted Block \ Example -0.7500: "))

(setq thk1 (abs thk)) ;;Changes the negative thickness number to a positive and sets it a new variable

(setq oldlayername '(Pkt_Radius_)) ;;Assigns the inserted block's layer name to a variable

(setq newlayername (strcat (oldlayername thk1))) ;;I've tried using append and cons here as well. Just can't get it structured correctly I guess.

 

(command "_chprop"

                     en1

                     "" ;;Selects the inserted entity for properties change

                     "Thickness"

                     thk ;;Inputs the thickness value | THIS SHOULD ALWAYS BE A NEGATIVE NUMBER!|

                     ""

                     ) ;;End thickness change to new entity

            (command "_Rename"

                              "Layer"

                             oldlayername

                             ""

                             newlayername

                             ""

                              ) ;;End of layer rename

             ) ;; End of function commands

        ) ;; end if

    ) ;; end if

 

I also have a trim option I would like to use after each block insert, I tried writing it as a separate program and just calling it from the main program like this:

                                                     (command "_optrim"

                                                      )

 

But it throws an error on me when trying to do that. I'd like to keep the program length down if possible. I've seen examples of people running one program inside another but they always just show that one little section of it. I don't know what it is supposed to look like for my particular program where if someone chooses to insert a block afterwards it would prompt the user if they need to trim the entity. Thanks in advance. I'll include my latest version of the program from earlier as well.

Message 13 of 20
Kent1Cooper
in reply to: cncah


@cncah wrote:

...

(setq oldlayername '(Pkt_Radius_)) ;;Assigns the inserted block's layer name to a variable

(setq newlayername (strcat (oldlayername thk1))) ....

...

Layer names are text strings, and that's what (strcat) will want to work with.  Try changing the first line above to:

 

(setq oldlayername "Pkt_Radius_")

Kent Cooper, AIA
Message 14 of 20
cncah
in reply to: Kent1Cooper

Ok, I got it to set the Pkt_Radius_ to the oldlayername value. But I still can't get the Pkt_Radius_ and a real number(0.3583) to add together. I got it to add together at one point, but it left a space in between the 2 values:

 

Pkt_Radius_ 0.3583

 

I appreciate some help with this as I'm starting a new batch of parts I have to program and I'd like to start using this lisp at full capacity soon. Thank You.

I guess, I just need to know how to add a set of text to a real number so I can set that to a new value and use that to rename the layer.

 

 

Message 15 of 20
Kent1Cooper
in reply to: cncah


@cncah wrote:

Ok, I got it to set the Pkt_Radius_ to the oldlayername value. But I still can't get the Pkt_Radius_ and a real number(0.3583) to add together. ....

I guess, I just need to know how to add a set of text to a real number so I can set that to a new value and use that to rename the layer.


I hadn't looked closely enough to notice that what you were tacking on was a number.  In that case:

  (setq newlayername (strcat (oldlayername (rtos thk1 2 4))))

 

The 2 is for decimal mode.  The 4 is the number of decimal places, which will flesh it out with trailing zeros when appropriate, as in some of your examples.

Kent Cooper, AIA
Message 16 of 20
cncah
in reply to: Kent1Cooper

I had already tried the rtos conversion, but then it gives an error on the Pkt_Radius_ portion saying:

 

bad function: Pkt_Radius_

 

That was using this code:

 

(setq thk (getreal "\nEnter Thickness For Inserted Block \ Example -0.7500: "))    ;;I type in=     -0.3583 and press enter
     (setq thk1 (abs thk)) ;;Changes the negative thickness number to a positive
     (setq oldlayername '(Pkt_Radius_))
     (setq newlayername (strcat (oldlayername (rtos thk1 2 4))))

 

Then when using this code I get:

 

bad function: "Pkt_Radius_"

 

(setq thk (getreal "\nEnter Thickness For Inserted Block \ Example -0.7500: "))    ;;I type in=     -0.3583 and press enter
     (setq thk1 (abs thk)) ;;Changes the negative thickness number to a positive
     (setq oldlayername "Pkt_Radius_")
     (setq newlayername (strcat (oldlayername (rtos thk1 2 4))))

 

I'll keep playing with it to see if I can get any different outcomes. I gratefully appreciate any help.

Message 17 of 20
Kent1Cooper
in reply to: cncah

I didn't notice the extra left parenthesis you had in there, preceding the oldlayername variable name [and corresponding extra right parenthesis at the end].  Try this:

 

(setq newlayername (strcat oldlayername (rtos thk1 2 4)));; no ( before oldlayername

Kent Cooper, AIA
Message 18 of 20
cncah
in reply to: Kent1Cooper

That fixed the layername setq. Although when I check the value in vlide, it shows up in quotation marks.

 

"Pkt_Radius_0.3583"

 

So when I go to rename the layer it throws me an error saying:  Invalid layer name

 

I've tried doing it through _chprop, and -rename, and _change commands. All of them seem to not like the new layer name I'm trying to change in there. This is what I'm running right now:

 

(setq en1 (entlast)) ;;Sets the last inserted entity as the one being changed

(setq thk (getreal "\nEnter Thickness For Inserted Block \ Example -0.7500: "))

(setq thk1 (abs thk)) ;;Changes the negative thickness number to a positive

(setq oldlayername "Pkt_Radius_")

(setq newlayername (strcat oldlayername (rtos thk1 2 4)))

 

     (command "_chprop"

                       en1

                       "" ;;Selects the inserted entity for properties change

                       "Thickness"

                       thk ;;Inputs the thickness value | THIS SHOULD ALWAYS BE A NEGATIVE NUMBER!|  

                       ""

                        ) ;;End of thickness change to new entity

 

     (command "-Rename"  

                       "Layer"

                        oldlayername

                        "" ;;Inputs what the old layer name was

                        newlayername

                        "" ;;Inputs what the new layer name will be

                         ) ;;End of layer rename

 

I've tried changing the layer name change command a few different ways, this method seems to get me the closest. When I manually change the layer name at the command line the only method that works is the -rename command. Both the _chprop and _change commands flag the error: invalid layer name. I appreciate all the help Kent, it's been very beneficial.

Message 19 of 20
Kent1Cooper
in reply to: cncah


@cncah wrote:
....Although when I check the value in vlide, it shows up in quotation marks.

 

"Pkt_Radius_0.3583"


....

     (command "-Rename"  

                       "Layer"

                        oldlayername

                        "" ;;Inputs what the old layer name was

                        newlayername

                        "" ;;Inputs what the new layer name will be

                         ) ;;End of layer rename

 

....


Yes, Layer names are text strings, and those always display with double-quotes at the ends.

 

The Layer names, both old and new, will be "registered" by the end of their text strings, and don't need an additional Enter for that.  Try removing the orange lines, which I believe you do not need.

Kent Cooper, AIA
Message 20 of 20
cncah
in reply to: Kent1Cooper

That did it Kent. You are the man! Thank you so very much!Smiley LOL

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost