From: timmy
Subject: newbie can't understand lists
Date: 
Message-ID: <mwsl5.110016$Yr4.1875305@news1.rdc1.tn.home.com>
ok i'm about to pull my hair out and kill myself after my first major
experience with lisp.  it is 2:52 AM and I do not know why this stupid
list is DUPLICATING itself!! 

here is the code:
 ( i am using cmucl)


(defstruct server
  nick host port socket stream state
)


(setq server-list (list
		   (make-server
		    :host "irc.debian.org"
		    :port 6667
		    :nick "timbot2")))


;; uses cmucl stuff
(defun connect-to-server (s)
    (setf (server-socket s)
	  (ext:connect-to-inet-socket (server-host s) (server-port s)))
    (setf (server-stream s)
	  (system:make-fd-stream (server-socket s)
				 :input t :output t :buffering :none
				 :timeout 300))
    (setf (server-state s) `just-opened-socket))




;; get data from server and send off to parse
(defun receive-data (serv)
  (if (eq serv nil) nil)
  (do ((l (read-line (server-stream serv) nil)
	  (read-line (server-stream serv) nil)))
      ((not l) nil)
    (parse-message serv (format nil "~S" l))
    (format t "recv> ~S~%" l)))




;; write directly to server
(defun send-data (serv str)
  (format (server-stream serv) "~S~%" str)
  (format t "send> ~S~%" str))


(defun act-on-state (serv)
  (if (eq serv nil) nil)
  (cond ((eq (server-state serv) 'just-opened-socket)
	 (send-data serv
		    (format nil "USER ~S 0 0 :~S"
			    (server-nick serv)
			      "anonymous coward"))
	 (send-data serv
		    (format nil "NICK ~S"
			    (server-nick serv)))
	 
	 (eq state 'waiting-reply)
	 (format t ".")
	 
	 ))))


(defun connect-loop ()
  (loop 
    (dolist (x server-list) (receive-data x))
    (dolist (x server-list) (act-on-state x))

    (when nil (return))
    ))


;; main stuff
(connect-to-server (car server-list))
(connect-loop)




-----------
so you run it and then interrupt it because it isn't doing anything:

* (load "main.lisp")

; Loading #p"/home/timmy/prgm/timbot2/src/main.lisp".
;; Loading #p"/home/timmy/prgm/timbot2/src/message.lisp".
;; Loading #p"/home/timmy/prgm/timbot2/src/irc_socket.lisp".
Warning:  Declaring SERVER-LIST special. Warning:  Ignoring unmatched
close parenthesis at file position 1671.

In: LAMBDA (SERV STRING)
  #'(LAMBDA (SERV STRING) (BLOCK PARSE-MESSAGE T))
Note: Variable SERV defined but never used. Note: Variable STRING defined
but never used.

Warning: This variable is undefined:
  STATE

Interrupted at #x101C9405.Restarts:
  0: [CONTINUE] Return from BREAK.
  1:            Return NIL from load of "main.lisp".
  2: [ABORT   ] Return to Top-Level.

Debug  (type H for help)

(UNIX::SIGINT-HANDLER #<unavailable-arg>
                      #<unavailable-arg>
                      #.(SYSTEM:INT-SAP #x3FFFE248))
0] (print server-list) 

(#S(SERVER
      :NICK "timbot2"
      :HOST "irc.debian.org"
      :PORT 6667
      :SOCKET 6
      :STREAM #<Stream for descriptor 6>
      :STATE JUST-OPENED-SOCKET)) 
(#S(SERVER
      :NICK "timbot2"      :HOST "irc.debian.org"
      :PORT 6667
      :SOCKET 6
      :STREAM #<Stream for descriptor 6>
      :STATE JUST-OPENED-SOCKET))
0] 



why is it doing this and it would be nice to know why it isn't connecting
to the server correctly either. thank you so much if you can help.

From: Barry Margolin
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <GSul5.13$sn6.2594@burlma1-snr2>
In article <························@news1.rdc1.tn.home.com>,
timmy <···@me.com> wrote:
>
>ok i'm about to pull my hair out and kill myself after my first major
>experience with lisp.  it is 2:52 AM and I do not know why this stupid
>list is DUPLICATING itself!! 
>
>here is the code:
> ( i am using cmucl)
>
>
>(defstruct server
>  nick host port socket stream state
>)
>
>
>(setq server-list (list
>		   (make-server
>		    :host "irc.debian.org"
>		    :port 6667
>		    :nick "timbot2")))
>
>
>;; uses cmucl stuff
>(defun connect-to-server (s)
>    (setf (server-socket s)
>	  (ext:connect-to-inet-socket (server-host s) (server-port s)))
>    (setf (server-stream s)
>	  (system:make-fd-stream (server-socket s)
>				 :input t :output t :buffering :none
>				 :timeout 300))
>    (setf (server-state s) `just-opened-socket))
>
>
>
>
>;; get data from server and send off to parse
>(defun receive-data (serv)
>  (if (eq serv nil) nil)

What's the purpose of the above line?  After it checks whether SERV is NIL,
the IF finishes and then you fall through to the lines below.  The part
below should probably be in the else-clause of the IF.

>  (do ((l (read-line (server-stream serv) nil)
>	  (read-line (server-stream serv) nil)))
>      ((not l) nil)
>    (parse-message serv (format nil "~S" l))
>    (format t "recv> ~S~%" l)))
>
>
>
>
>;; write directly to server
>(defun send-data (serv str)
>  (format (server-stream serv) "~S~%" str)
>  (format t "send> ~S~%" str))
>
>
>(defun act-on-state (serv)
>  (if (eq serv nil) nil)

Again, you just fall through after checking SERV.  Why not make this the
first clause of the COND?

>  (cond ((eq (server-state serv) 'just-opened-socket)
>	 (send-data serv
>		    (format nil "USER ~S 0 0 :~S"
>			    (server-nick serv)
>			      "anonymous coward"))
>	 (send-data serv
>		    (format nil "NICK ~S"
>			    (server-nick serv)))
>	 
>	 (eq state 'waiting-reply)
>	 (format t ".")
>	 
>	 ))))

You have too many close parens here.

>
>
>(defun connect-loop ()
>  (loop 
>    (dolist (x server-list) (receive-data x))
>    (dolist (x server-list) (act-on-state x))
>
>    (when nil (return))
>    ))
>
>
>;; main stuff
>(connect-to-server (car server-list))
>(connect-loop)
>
>
>
>
>-----------
>so you run it and then interrupt it because it isn't doing anything:
>
>* (load "main.lisp")
>
>; Loading #p"/home/timmy/prgm/timbot2/src/main.lisp".
>;; Loading #p"/home/timmy/prgm/timbot2/src/message.lisp".
>;; Loading #p"/home/timmy/prgm/timbot2/src/irc_socket.lisp".
>Warning:  Declaring SERVER-LIST special. Warning:  Ignoring unmatched
>close parenthesis at file position 1671.
>
>In: LAMBDA (SERV STRING)
>  #'(LAMBDA (SERV STRING) (BLOCK PARSE-MESSAGE T))
>Note: Variable SERV defined but never used. Note: Variable STRING defined
>but never used.

I don't see the definition of PARSE-MESSAGE in the code above.  According
to this message, there are some problems with its definition.

>
>Warning: This variable is undefined:
>  STATE

The function ACT-ON-STATE contains:

	(eq state 'waiting-reply)

but there's no variable STATE defined.  I think you meant (server-state
serv).

>
>Interrupted at #x101C9405.Restarts:
>  0: [CONTINUE] Return from BREAK.
>  1:            Return NIL from load of "main.lisp".
>  2: [ABORT   ] Return to Top-Level.
>
>Debug  (type H for help)
>
>(UNIX::SIGINT-HANDLER #<unavailable-arg>
>                      #<unavailable-arg>
>                      #.(SYSTEM:INT-SAP #x3FFFE248))
>0] (print server-list) 
>
>(#S(SERVER
>      :NICK "timbot2"
>      :HOST "irc.debian.org"
>      :PORT 6667
>      :SOCKET 6
>      :STREAM #<Stream for descriptor 6>
>      :STATE JUST-OPENED-SOCKET)) 
>(#S(SERVER
>      :NICK "timbot2"      :HOST "irc.debian.org"
>      :PORT 6667
>      :SOCKET 6
>      :STREAM #<Stream for descriptor 6>
>      :STATE JUST-OPENED-SOCKET))
>0] 
>
>
>
>why is it doing this and it would be nice to know why it isn't connecting
>to the server correctly either. thank you so much if you can help.

The PRINT function is printing the value of SERVER-LIST.  It also returns
the thing that it printed, and the top-level read-eval-print loop prints
what it returned.

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: timmy
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <SVzl5.110266$Yr4.1880145@news1.rdc1.tn.home.com>
In article <·················@burlma1-snr2>, Barry Margolin
<······@genuity.net> wrote:
> In article <························@news1.rdc1.tn.home.com>, timmy
> <···@me.com> wrote:
>>

>>;; get data from server and send off to parse
>>(defun receive-data (serv)
>>  (if (eq serv nil) nil)
> 
> What's the purpose of the above line?  After it checks whether SERV is
> NIL, the IF finishes and then you fall through to the lines below.  The
> part below should probably be in the else-clause of the IF.
> 

hmmm.. you're right. i must have been thinking that I would get nil and
that would exit out of the function.



>>(defun act-on-state (serv)
>>  (if (eq serv nil) nil)
> 
> Again, you just fall through after checking SERV.  Why not make this the
> first clause of the COND?

good idea.


> 
> You have too many close parens here.

that is something you realise about 10 seconds after you post, and then
you are like, "well, forget it"


>>In: LAMBDA (SERV STRING)
>>  #'(LAMBDA (SERV STRING) (BLOCK PARSE-MESSAGE T))
>>Note: Variable SERV defined but never used. Note: Variable STRING
>>defined but never used.
> 
> I don't see the definition of PARSE-MESSAGE in the code above. 
> According to this message, there are some problems with its definition.

yes... it is just an empty function so the receive function could call
something

> 
>>
>>Warning: This variable is undefined:
>>  STATE
> 
> The function ACT-ON-STATE contains:
> 
> 	(eq state 'waiting-reply)
> 
> but there's no variable STATE defined.  I think you meant (server-state
> serv).

oh... yeah... I think my biggest problem was that i had trouble finding
the errors... you know c++ gives you a line number and i'm not that
familiar with how cmucl does it.. i think it might give you a position.



>>
>>why is it doing this and it would be nice to know why it isn't
>>connecting to the server correctly either. thank you so much if you can
>>help.
> 
> The PRINT function is printing the value of SERVER-LIST.  It also
> returns the thing that it printed, and the top-level read-eval-print
> loop prints what it returned.
> 

ohhh.. ok. thanks a lot!!
From: Pierre R. Mai
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <87n1ihqkrd.fsf@orion.bln.pmsf.de>
"timmy" <···@me.com> writes:

> ok i'm about to pull my hair out and kill myself after my first major
> experience with lisp.  it is 2:52 AM and I do not know why this stupid
> list is DUPLICATING itself!! 

Beside the normal Lisp related stuff that Barry has already pointed
out, the program will always hang itself, since you call receive-data
before having sent anything to the server:

> (defun connect-loop ()
>   (loop 
>     (dolist (x server-list) (receive-data x))
>     (dolist (x server-list) (act-on-state x))
> 
>     (when nil (return))
>     ))
> 
> 
> ;; main stuff
> (connect-to-server (car server-list))

You have established a connection here, but haven't sent anything down
the wire...

> (connect-loop)

Now you call receive-data, which will cause a _blocking read_ to
happen on the socket.  Since the server on the other end hasn't gotten
a command from you yet, this will result in deadlock...  You will have
to make sure that receive-data returns when there is nothing to read,
e.g. by calling listen to determine whether there is something to
read or not, and only calling read-line when there is.  Better yet
take a look at the serve-event section of the CMUCL user manual, which
will show you an existing mechanism to handle event-based handling of
multiple input/output streams.

If you are using CMUCL on i86 then you might also consider using the
multi-processing extensions and use a new thread for each server
connection, so that you won't have to worry about blocking reads and
interleaving the handling of different connections.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: timmy
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <S1Al5.110268$Yr4.1880077@news1.rdc1.tn.home.com>
In article <··············@orion.bln.pmsf.de>, "Pierre R. Mai"
<····@acm.org> wrote:
> "timmy" <···@me.com> writes:
> 
>> ok i'm about to pull my hair out and kill myself after my first major
>> experience with lisp.  it is 2:52 AM and I do not know why this stupid
>> list is DUPLICATING itself!! 
> 
> Beside the normal Lisp related stuff that Barry has already pointed out,
> the program will always hang itself, since you call receive-data before
> having sent anything to the server:

hmm... well this was a c++ program and i'm trying to re-write it in lisp
to learn lisp. in c/c++ you can poll() the socket to see if there is
anything to read... which is basically what i want to do.. do you know if
that is possible?  --- ok it is..

> 
>> (defun connect-loop ()
>>   (loop 
>>     (dolist (x server-list) (receive-data x))
>>     (dolist (x server-list) (act-on-state x))
>> 
>>     (when nil (return))
>>     ))
>> 
>> 
>> ;; main stuff
>> (connect-to-server (car server-list))
> 
> You have established a connection here, but haven't sent anything down
> the wire...

ok, i didn't know receive would wait for something..


>> (connect-loop)
> 
> Now you call receive-data, which will cause a _blocking read_ to happen
> on the socket.  Since the server on the other end hasn't gotten a
> command from you yet, this will result in deadlock...  You will have to
> make sure that receive-data returns when there is nothing to read, e.g.
> by calling listen to determine whether there is something to read or
> not, and only calling read-line when there is.  Better yet take a look
> at the serve-event section of the CMUCL user manual, which will show you
> an existing mechanism to handle event-based handling of multiple
> input/output streams.
> 
> If you are using CMUCL on i86 then you might also consider using the
> multi-processing extensions and use a new thread for each server
> connection, so that you won't have to worry about blocking reads and
> interleaving the handling of different connections.
> 


oh that sounds really neat... but i'm not sure if i should use a thread
because i want to have portable code.....i guess i get teh cmucl user
manual at the www.cons.org site? or would I already have it after
installing the debian pacakge? i guess i'll look for it and tell you if 
i don't find it.

thanks for the help!
From: Colin Walters
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <8766p49643.church.of.emacs@meta.verbum.org>
"timmy" <·····@here.com> writes:

> oh that sounds really neat... but i'm not sure if i should use a
> thread because i want to have portable code.....

Well, all of the CMUCL networking functions you are already using
aren't portable, unfortunately.

> i guess i get teh cmucl user manual at the www.cons.org site? or
> would I already have it after installing the debian pacakge?

Naturally, all documentation on a Debian system should be in
"/usr/share/doc/<package name>", in this case "/usr/share/doc/cmucl".
From: timmy
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <_FFl5.110987$Yr4.1893408@news1.rdc1.tn.home.com>
In article <··························@meta.verbum.org>, Colin Walters
<·······@cis.ohio-state.edu> wrote:
> "timmy" <·····@here.com> writes:
> 
>> oh that sounds really neat... but i'm not sure if i should use a thread
>> because i want to have portable code.....
> 
> Well, all of the CMUCL networking functions you are already using aren't
> portable, unfortunately.

well, i sort of knew that but i didn't want to dig myself in a bigger hole
if i have to port it.

>> i guess i get teh cmucl user manual at the www.cons.org site? or would
>> I already have it after installing the debian pacakge?
> 
> Naturally, all documentation on a Debian system should be in
> "/usr/share/doc/<package name>", in this case "/usr/share/doc/cmucl".


ok, i have seen that but unfortunately it does not have enought for a lisp
socket beginner like me. i cannot understnad how to use something like
with-fd-handler so I am trying to use listen.... I've spent about three
hours doing this today.. and i don't really know what is going wrong now.

(btw, i don't see any good examples on this in the manual)
.. there is one about X but that doesn't do what i am doing.


so here is my new listen code:

;; get data from server and send off to parse
(defun receive-data (serv)
  (if (or (eq serv nil) (not (listen (server-stream serv)))) nil
    (do ((l (read-line (server-stream serv) nil)
	    (read-line (server-stream serv) nil)))
	((not l) nil)
      (parse-message serv (format nil "~S" l))
      (format t "recv> ~S~%" l))))




;; write directly to server
(defun send-data (serv str)
  (format (server-stream serv) "~S~%" str)
  (format t "send> ~S~%" str))

---
oh yeah.. is there a way so that sending a string doesn't send the quotes?
that is reallllly annoying!


here is the connection loop:


(defun connect-loop ()
  (loop 
    (dolist (x server-list) (act-on-state x))
    (dolist (x server-list) (receive-data x))
    ))


and if this is important: 


(defun act-on-state (serv)
  (if (eq serv nil) nil)
  (cond 
   ((eq serv nil) nil)
   ((eq (server-state serv) 'just-opened-socket)
	 (send-data serv
		    (format nil "USER ~S 0 0 :~S"
			    (server-nick serv)
			      "anonymous coward"))
	 (send-data serv
		    (format nil "NICK ~S"
			    (server-nick serv)))
	 
	 (setf (server-state serv) 'waiting-reply))

   ((eq (server-state serv) 'waiting-reply)  nil)
   (t nil)))



----
i am not getting any errors when i run this.. it just looks like this:


* (load "main.lisp")

; Loading #p"/home/timmy/prgm/timbot2/src/main.lisp".
;; Loading #p"/home/timmy/prgm/timbot2/src/message.lisp".
;; Loading #p"/home/timmy/prgm/timbot2/src/irc_socket.lisp".
send> "USER \"timbot2\" 0 0 :\"anonymous coward\""
send> "NICK \"timbot2\""
[GC threshold exceeded with 2,002,592 bytes in use.  Commencing GC.]
[GC completed with 268,512 bytes retained and 1,734,080 bytes freed.]
[GC will next occur when at least 2,268,512 bytes are in use.]
[GC threshold exceeded with 2,272,488 bytes in use.  Commencing GC.]
[GC completed with 263,120 bytes retained and 2,009,368 bytes freed.]
[GC will next occur when at least 2,263,120 bytes are in use.]
[GC threshold exceeded with 2,266,064 bytes in use.  Commencing GC.]
[GC completed with 281,584 bytes retained and 1,984,480 bytes freed.]
[GC will next occur when at least 2,281,584 bytes are in use.]

(i got tired of that repeating fast)

Interrupted at #x105BBF12.

Restarts:
  0: [CONTINUE] Return from BREAK.
  1:            Return NIL from load of "main.lisp".
  2: [ABORT   ] Return to Top-Level.

Debug  (type H for help)

(UNIX::SIGINT-HANDLER #<unavailable-arg>
                      #<unavailable-arg>
                      #.(SYSTEM:INT-SAP #x3FFFE568))
0] q



i am also wondering if there is an *easy* way to set breakpoints and step
through code... examples would probably help me best... thanks again.
From: Colin Walters
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <878zu0ej37.church.of.emacs@meta.verbum.org>
"timmy" <·····@here.com> writes:

> (btw, i don't see any good examples on this in the manual) .. there
> is one about X but that doesn't do what i am doing.

I agree, more networking documentation would be nice.  

> so here is my new listen code:
> 
> ;; get data from server and send off to parse
> (defun receive-data (serv)
>   (if (or (eq serv nil) (not (listen (server-stream serv)))) nil
>     (do ((l (read-line (server-stream serv) nil)
> 	    (read-line (server-stream serv) nil)))
> 	((not l) nil)
>       (parse-message serv (format nil "~S" l))
>       (format t "recv> ~S~%" l))))

Hmm.  How about:

(defun receive-data (serv)
  (when (and serv
             (listen (server-stream serv)))
    (do ...
        )))

> ;; write directly to server
> (defun send-data (serv str)
>   (format (server-stream serv) "~S~%" str)
>   (format t "send> ~S~%" str))
> 
> ---
> oh yeah.. is there a way so that sending a string doesn't send the quotes?
> that is reallllly annoying!

Well, the ~S directive tells FORMAT to print in a way that it should
be possible to READ back in the data.  What you really want is ~A,
which prints like PRINC does.

[...]

> i am not getting any errors when i run this.. 

After a quick glance through the code, I don't see where the problem
lies.  However...

> i am also wondering if there is an *easy* way to set breakpoints and
> step through code... examples would probably help me best... thanks
> again.

Yes.  The debugger is your friend.  Did you check out the section "The
Debugger" of the CMUCL manual?

In a nutshell, though:  When you interrupt CMUCL and go into the
debugger, try typing "backtrace".  This will show you what function
you are looping in.  You can then use "up" to go to the frame of that
function, and from there inspect the values of variables with
"(debug:var 'foo)".

Does this help?
From: Pierre R. Mai
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <873dk7u0ps.fsf@orion.bln.pmsf.de>
"timmy" <·····@here.com> writes:

> In article <··························@meta.verbum.org>, Colin Walters
> <·······@cis.ohio-state.edu> wrote:
> > "timmy" <·····@here.com> writes:
> > 
> >> oh that sounds really neat... but i'm not sure if i should use a thread
> >> because i want to have portable code.....
> > 
> > Well, all of the CMUCL networking functions you are already using aren't
> > portable, unfortunately.
> 
> well, i sort of knew that but i didn't want to dig myself in a bigger hole
> if i have to port it.

Most of the threading APIs are very similar, so that porting the
multi-threading stuff will likely be less work than porting the
socket stuff.  I'd definitely suggest using multiple threads, since
that will simplify your code quite a bit, thereby reducing coding and
maintenance.  Indeed it might reduce overall porting effort too, since
you can write the meat of your program utilizing standard CL blocking
I/O operations, using implementation specific stuff only to set-up the
connections and to start up a new thread with a new stream for each
new connection.

> ok, i have seen that but unfortunately it does not have enought for a lisp
> socket beginner like me. i cannot understnad how to use something like
> with-fd-handler so I am trying to use listen.... I've spent about three
> hours doing this today.. and i don't really know what is going wrong now.

I posted an example of how to use the fd-handler stuff to handle
incoming connections a couple of days ago.  For outgoing connections
this is even simpler since you'll only have to add one handler for
each connection using add-fd-handler with :direction :input, and let
that handler read messages and process them until there is no more
input pending.  In simplified terms:

(defun connect-to-server (s)
  (setf (server-socket s)
	(ext:connect-to-inet-socket (server-host s) (server-port s)))
  (setf (server-stream s)
	(system:make-fd-stream (server-socket s)
			       :input t :output t :buffering :none
			       :timeout 300))
  (setf (server-state s) :just-opened-socket)
  (setf (server-handler s)
        (system:add-fd-handler (server-socket s) :input 
                               #'(lambda (fd) 
                                   (declare (ignore fd))
                                   (connection-handler s))))
  ;; Tickle first sending of stuff here...
  s)

(defun connection-handler (server)
  (let ((stream (server-stream server)))
    (loop
      (unless (listen stream) (return nil))
      ;; Handle responses here
      (process-message server (read-line stream nil nil)))))

But note that this might still block in read-line, if the whole message
line didn't arrive in one package.  To avoid that you'll have to do
more clever coding.  You can sidestep this whole issue by going the MP
way, though.

BTW: Note that in the IRC client protocol messages end with CR + LF,
and not just LF, so that using read-line & co. is probably not what
you want to do in any case.

> ;; get data from server and send off to parse
> (defun receive-data (serv)
>   (if (or (eq serv nil) (not (listen (server-stream serv)))) nil
>     (do ((l (read-line (server-stream serv) nil)
> 	    (read-line (server-stream serv) nil)))
> 	((not l) nil)
>       (parse-message serv (format nil "~S" l))

Why do you pass the read line through format before handing it over to
parse-message?  You don't want to do that, do (parse-message serv l)
instead.

This function still has the problem that you will block on subsequent
lines:

(defun receive-data (serv)
  (when (listen (server-stream serv))
    (let ((line (read-line (server-stream serv) nil nil)))
      (when line
        (prog1 (parse-message serv line)
          (format *trace-output* "recv> ~S~%"
                  (string-right-trim '(#\Return) line)))))))


> ;; write directly to server
> (defun send-data (serv str)
>   (format (server-stream serv) "~S~%" str)

You don't want to use format here as well:  Just use 
(write-line str (server-stream serv))

>   (format t "send> ~S~%" str))
> 
> ---
> oh yeah.. is there a way so that sending a string doesn't send the quotes?
> that is reallllly annoying!

See above.  If you insist on using format, you can use the ~A
directive to avoid the printing of escape characters.  But format is
for doing formatted output and not for generic string output so use
write-line or write-string instead, as indicated above.

> i am not getting any errors when i run this.. it just looks like this:
> 
> 
> * (load "main.lisp")
> 
> ; Loading #p"/home/timmy/prgm/timbot2/src/main.lisp".
> ;; Loading #p"/home/timmy/prgm/timbot2/src/message.lisp".
> ;; Loading #p"/home/timmy/prgm/timbot2/src/irc_socket.lisp".
> send> "USER \"timbot2\" 0 0 :\"anonymous coward\""
> send> "NICK \"timbot2\""
> [GC threshold exceeded with 2,002,592 bytes in use.  Commencing GC.]
> [GC completed with 268,512 bytes retained and 1,734,080 bytes freed.]
> [GC will next occur when at least 2,268,512 bytes are in use.]
> [GC threshold exceeded with 2,272,488 bytes in use.  Commencing GC.]
> [GC completed with 263,120 bytes retained and 2,009,368 bytes freed.]
> [GC will next occur when at least 2,263,120 bytes are in use.]
> [GC threshold exceeded with 2,266,064 bytes in use.  Commencing GC.]
> [GC completed with 281,584 bytes retained and 1,984,480 bytes freed.]
> [GC will next occur when at least 2,281,584 bytes are in use.]
> 
> (i got tired of that repeating fast)

This is to be expected:  You are loading your files without compiling
them first, so that the contents will be interpreted.  Since the use
of listen results in fast looping (active polling), you generate
a lot of garbage.  Compile your files (using compile-file) before
loading them, and the garbage generation issue will go away.  Note
that this doesn't solve the problem that you will be consuming lots of
cpu time by doing active polling.  This is why you should use either
the MP or the serve-event stuff.

Regs, Pierre.

-- 
Pierre R. Mai <····@acm.org>                    http://www.pmsf.de/pmai/
 The most likely way for the world to be destroyed, most experts agree,
 is by accident. That's where we come in; we're computer professionals.
 We cause accidents.                           -- Nathaniel Borenstein
From: Paolo Amoroso
Subject: Re: newbie can't understand lists
Date: 
Message-ID: <ihCYOQAb0S=KC2k6Motuid888rM5@4ax.com>
On Sun, 13 Aug 2000 16:29:38 GMT, "timmy" <·····@here.com> wrote:

> because i want to have portable code.....i guess i get teh cmucl user
> manual at the www.cons.org site? or would I already have it after

You might have a look at the EncyCMUCLopedia--see my singature below. I
plan to start working on a new release real soon asap :)


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/