Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - iNPRwANG

#1
Source funtion could not get the corresponding result while nest list element type of arrays, code like this:



> (array 1)
(nil)
> (setq *a* (array 1))
(nil)
> (setf (nth 0 *a*) '(1 2 3))
(1 2 3)
> (source '*a*)
"(set '*a* (array 1 (flat '(rn  (1 2 3)))))rnrn"
>


The *a* symbol's value is: ((1 2 3)), bt the result: (set '*a* (array 1 (flat '((1 2 3))))) regard the *a* to (1), is this a bug?
#2
Here are some share tips of doing remoting debug with newLisp : )



Before, I suggested to add a "debugConsole" function for embedded newLisp library debugging, that can establish a new console window for windows GUI applications and can do the step debug in the window.



Now, I want to step debug the newLisp for embedded device, such as android devices or embedded linux facilities, a remote debugger can make debug works be very comfortable.



With these codes, U may have a simple remote debug without change any newLisp's source, these two parts code is a remote debugger services and a debugger terminal, the debugger services looks like this:



(import "libc.so.6" "dup2")

;Standard input value, stdin. Its value is 0.
(constant 'STDIN_FILENO 0)
   
;Standard output value, stdout. Its value is 1.
(constant 'STDOUT_FILENO 1)
   
;Standard error value, stderr. Its value is 2.
(constant 'STDERR_FILENO 2)

(println STDOUT_FILENO)

(set 'socket (net-listen 1234))
(set 'cnn (net-accept socket))
(net-close socket)

(println "Connection successed!")

;/* duplicate socket on stdout */
(dup2 cnn STDOUT_FILENO)

;  /* duplicate socket on stderr too */
(dup2 cnn STDIN_FILENO)

(debug (fibo 2))

(exit)


The "fibo" function is a route you want to debug, and the debugger terminal looks like this:




(set 'socket (net-connect "127.0.0.1" 1234))
(println "Connection successed!")

(setq g_end "s|tep n|ext c|ont q|uit >")

(catch
(let ((buffer (dup "x00" 1))
 (output ""))
(while true
;判断是否 s|tep n|ext c|ont q|uit > 结尾,如果是,则打印出来后再读取一个字符

(net-select socket "e" 0)
(when (net-error)
(println (net-error))
(throw 'Exception))

(net-receive socket buffer 1)
(print buffer)

(setq output (append output buffer))
(when (ends-with output g_end)
(setq output "")

(letn ((cmd (read-line))
  (send_cmd (append cmd "n")))
(net-send socket send_cmd)
)
)
)
)
'Result)

(exit)





Then, run the debugger services and then run the debugger terminal, U will like the remote debuger practice : )



Under are some notes for remote debug with a newLisp library:



The library of newLisp does not use the standard IO for debugger, unless you set a debug console flag for it. The "newlispLibConsole" exported function of newLisp.so can be called and to enable the flag, then it will use the standard IO and the above codes will works good.
#3
Use this makefile can compile newLisp to newlisp-js in emscripten v1.37 by enable webassembly support.

Notice of the  "-s WASM=1" option let the emscripten generate webassembly, and should use the " -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' " for function exporting (the "ccall" and "cwrap" not export by default in emscripten version above 1.3)



The approximate performance about webassembly enabled newlisp-js is 5% faster than asm.js version (tested in Firefox 58.0.1), and the total file size is less than the asm.js version about 20%.



# makefile for newLISP v. 10.5.x and after with UTF8 support for the Emscripten SDK
#
# With Emscripten version v1.22.0 all execption handling related problems
# known have been solved. (November 2014)
#
# see also: https://github.com/kripken/emscripten/wiki
#
# Uses custom random() and srandom() in nl-filesys.c
#
# Does not implement the newLISP functions:
# semaphore, net-packet, net-service, fork, spawn, sync, abort
#
# Will not do file and network I/O functions in the sandboxed JavaScript
# environment
#
# Generates newlisp-js-lib.js and newlisp-js-lib.html.
# The html file can be discarded use newlisp-js/newlisp-js.html instead
#
# this makefile has been tested on a MAC OSX 10.9/10 platforms

OBJS = newlisp.o nl-symbol.o nl-math.o nl-list.o nl-liststr.o nl-string.o nl-filesys.o
 nl-sock.o nl-web.o nl-xml-json.o nl-matrix.o nl-debug.o pcre.o nl-utf8.o unix-lib.o

CFLAGS = -m32 -Wall -c -DMAC_OSX -DLIBRARY -DEMSCRIPTEN -DSUPPORT_UTF8

CC = emcc

default: $(OBJS)
 cp qa-specific-tests/qa-bench newlisp-js
 cp modules/canvas.lsp newlisp-js
 $(CC) $(OBJS) -m32 -O2 -s WASM=1 -o newlisp-js-lib.html -s EXPORTED_FUNCTIONS="['_newlispEvalStr']"
 -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'
 -s TOTAL_MEMORY=33554432 --closure 1
 --embed-file newlisp-js/readme.txt --embed-file newlisp-js/qa-bench --embed-file newlisp-js/canvas.lsp
 rm newlisp-js/qa-bench newlisp-js/canvas.lsp

.c.o:
 $(CC) -O2 --closure 1 $(CFLAGS) $<

$(OBJS): primes.h protos.h makefile_emscripten_lib_utf8

#4
OS version is win10 x64 1709 (Chinese simplified).

   

    After I upgraded Jre from 8.x to 9.0.1, and running any newLisp script that used guiserver(such as the widgets-demo.lsp), all of the program that use the internal image (such as gs:image-button that use a image "/local/newLISP32.png") will cause a error message. And, the program will finally startup and show the main interface with not any image.



    I am not good at Java, I can not delimit is it a incompatible changes by Jre 9.x ?
#5
Why this forum's link not exists in newlisp's home page?
#6
newLISP in the real world / Crashed while step debug
October 20, 2014, 08:23:45 PM
I have obtain newlisp.exe from:

http://www.newlisp.org/downloads/UTF-8_win32/">//http://www.newlisp.org/downloads/UTF-8_win32/



Verion is 10.6.0.



And let it run this program:



(define (db-clear-sync-queues-vlog clearlist)
(let ((conds '())
 (sql ""))

(dolist (_item clearlist)
(if (and (> (length _item) 1)
(string? (nth 0 _item))
(number? (nth 2 _item))
)
(extend conds (list (format "(tablename='%s' and orderid=%d)" (nth 0 _item) (nth 2 _item))))
)
)

(setq sql (append "delete from tbl_sync_queues_vlog where " (join conds " or ")))
))

(debug (db-clear-sync-queues-vlog '(("tbl_test" "2014-10-21 10:35:35.873000000" 1))))


While in step debugging, the debug output like this:



(define (db-clear-sync-queues-vlog clearlist)
  (let ((conds '()) (sql ""))
   (dolist (_item clearlist)
    (if (and (> (length _item) 1) (string? (nth 0 _item)) (number? (nth 2 _item)))
     (extend conds (list (format "(tablename='(null)' and orderid=10503914)" (nth 0 _item)
        (nth 2 _item))))))
   (setq sql (append "delete from tbl_sync_queues_vlog where " (join conds " or ")))))


Take notice of the string "(tablename='(null)' and orderid=10503914)", that's different from my code.



And while I step and step, the program will crash in this step:



(define (db-clear-sync-queues-vlog clearlist)
  (let ((conds '()) (sql ""))
   #(dolist (_item clearlist)
    (if (and (> (length _item) 1) (string? (nth 0 _item)) (number? (nth 2 _item)))
     (extend conds (list (format "(tablename='(null)' and orderid=10503914)" (nth 0 _item)
        (nth 2 _item))))))#
   (setq sql (append "delete from tbl_sync_queues_vlog where " (join conds " or ")))))


Any suggestions??
#7
OS is windows xp sp3, these code works better on newLisp 10.4.5:



(import "msvcrt.dll" "sscanf")

(let ((day 0) (mon 0) (year 0))
(sscanf "1990-01-01" "%d-%d-%d" (address year) (address mon) (address day)))


But crashed on newLisp 10.5.0, is any changes of the int datatype address?
#8
newLISP in the real world / Catch form problem
June 14, 2012, 02:23:09 AM
The newLisp document said:
Quote
In the second syntax, catch evaluates the expression exp, stores the result in symbol, and returns true. If an error occurs during evaluation, catch returns nil and stores the error message in symbol. This form can be useful when errors are expected as a normal potential outcome of a function and are dealt with during program execution.


And in my code, I'd throwed a exception in catch of second syntax, why it always get "true" result instead of nil?



(setq result nil)

(println (catch (dotimes (x 100)
  (if (= x 50) (throw "fin"))) 'result))
#9
While I compile newlisp 10.4.2 on windows mingw gcc(4.6.1), and run the target, it looks good for all test.

But if only cause a error in code, like run a undefine function:



(aa)


That will show a error message, and make a fatal error messagebox, then program will crash.



I try to build a version with no -O1 option with gcc(4.6.1), It works better!



I try to find the error from source, it looks crash at the "longjump" function while resume from error.



I try to compile newlisp on mingw gcc(3.4.5), the result is it woks all good.
#10
newLISP in the real world / The length of nil value
April 17, 2012, 08:10:04 PM
This is code:



(setq mylst '(nil nil nil nil nil nil nil nil nil nil nil nil))
(dolist (item mylst) (println (length item)))


Why the result is:



3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3

3
#11
System is Windows xp, while loop call of the "process" function of newlisp 10.4.2, you may saw that the "Handle Count" of Task manager increment every call.



    I have readed the source of win32-util.c:69, the "CreateProcess" systemcall return a PROCESS_INFORMATION

struct, the function call return the hProcess of this struct. I try to add a "CloseHandle" function call to close the hThread of this struct and recompile the newlisp, it looks work good.



    Is this a leak?  : )




UINT winPipedProcess(char * cmd, int inpipe, int outpipe, int option)
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION process;
int result;
long fin, fout;

if(inpipe == -1 && outpipe == -1)
    {
    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    si.wShowWindow = option;
    memset(&process, 0, sizeof(process));
    }
else
    {
    /* GetStartupInfo(&si);  */
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = option; /* SW_SHOW, SW_HIDE  get additional user option in Win32 versions */

    fin = _get_osfhandle(inpipe);
    fout = _get_osfhandle(outpipe);

    si.hStdInput = (inpipe) ? (HANDLE)fin : GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput = (outpipe) ? (HANDLE)fout : GetStdHandle(STD_OUTPUT_HANDLE);
    si.hStdError = (outpipe) ? (HANDLE)fout : GetStdHandle(STD_OUTPUT_HANDLE);
    }

if((result = CreateProcess(NULL,cmd,NULL,NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&si, &process)) == 0)
    return(0);

//Try close hThread here
CloseHandle(process.hThread);
return((UINT)process.hProcess);
}


#12
For I was often to call some OS native API in newlisp, and alloc some kernel handle.

While I alloc the native handle, I should free then. Or it will cause the leak.



I known the Steel Bank Common Lisp has a extend function named "finalize", it can bind a designated function to a object and let it to be called when there are no more references to object.

I think that's a good idea for mainten FFI's alloced pointer, is it? : )

So I wish newlisp may has the similar mechanism for usage.





Under is the part of the "finalize" function of SBCL's document.



— Function: finalize [sb-ext] object function &key dont-save



    Arrange for the designated function to be called when there are no more references to object, including references in function itself.



    If dont-save is true, the finalizer will be cancelled when save-lisp-and-die is called: this is useful for finalizers deallocating system memory, which might otherwise be called with addresses from the old image.



    In a multithreaded environment function may be called in any thread. In both single and multithreaded environments function may be called in any dynamic scope: consequences are unspecified if function is not fully re-entrant.



    Errors from function are handled and cause a warning to be signalled in whichever thread the function was called in.



    Examples:

;;; GOOD, assuming RELEASE-HANDLE is re-entrant.
(let* ((handle (get-handle))
  (object (make-object handle)))
 (finalize object (lambda () (release-handle handle)))
 object)

;;; BAD, finalizer refers to object being finalized, causing
;;; it to be retained indefinitely!
(let* ((handle (get-handle))
  (object (make-object handle)))
  (finalize object
(lambda ()
 (release-handle (object-handle object)))))

;;; BAD, not re-entrant!
(defvar *rec* nil)

(defun oops ()
 (when *rec*
   (error "recursive OOPS"))
 (let ((*rec* t))
   (gc))) ; or just cons enough to cause one

(progn
  (finalize "oops" #'oops)
  (oops)) ; GC causes re-entry to #'oops due to the finalizer
 ; -> ERROR, caught, WARNING signalled

#13
While run this code:



(define (hello-world a)
(letn ((tmp 10)
      (val1 (* tmp 2))
  (val2 (* tmp 2)))
)
)

(debug (hello-world 10))




(define (hello-world a)

  #(letn ((tmp 10) (val1 (* tmp 2)) (val2 (* tmp 2))))#)





[-> 3 ] s|tep n|ext c|ont q|uit > s



-----



(define (hello-world a)

  (letn ((tmp 10) (val1 #(* tmp 2)#) (val2 (* tmp 2)))))





[-> 4 ] s|tep n|ext c|ont q|uit > s



-----



(define (hello-world a)

  (letn ((tmp 10) (val1 #(* tmp 2)#) (val2 (* tmp 2)))))





RESULT: 20



[<- 4 ] s|tep n|ext c|ont q|uit > s



-----



(define (hello-world a)

  (letn ((tmp 10) (val1 #(* tmp 2)#) (val2 (* tmp 2)))))





; This cause the bracket match error.



Is it should be]






[-> 4 ] s|tep n|ext c|ont q|uit > s



-----



(define (hello-world a)

  (letn ((tmp 10) (val1 #(* tmp 2)#) (val2 (* tmp 2)))))





RESULT: 20



[<- 4 ] s|tep n|ext c|ont q|uit > s



-----



(define (hello-world a)

  #(letn ((tmp 10) (val1 (* tmp 2)) (val2 (* tmp 2))))#)





RESULT: nil



[<- 3 ] s|tep n|ext c|ont q|uit >
#14
I'm sorry for my english.  While I run under codes, I can not understand why the result is 10 unless the myfun's lambda parameter use the variable "a" defined of myfun2. And the common lisp get the right results :30.







(define (myfun2 fun)
(let ((a 20))
(apply fun '())
)
)

(define (myfun)
(let ((a 10))
(myfun2
(lambda ()
(setq a 30))
)
a
)
)
       
(print (myfun))

(exit)
#15
Hi everyone!

I'm a Chinese and with a little English : )  and this is my first post.

I used newlisp period of time, I think it's a very good and easy to use script as a lisp language.



One day, I want to use it in a Microsoft Windows GUI application,  I use the export function "newlispEvalStr" to eval script, It looks worked good. But I can not use the "debug" function to step run a newlisp route, then I add the function in source code:





void EXPORT AllocDebugConsole() {

IOchannel = stdin;

AllocConsole();
freopen("CONOUT$","w+t",stdout);
freopen("CONIN$","r+t",stdin);  
}


And I invoked it in the GUI application intialize time. The console window had be showed, and the debug features of newlisp worked!





The second problem:



Sometimes I want to use the newlisp with multiple thread or mutiple instance.

Because of the GUI application could not block the user input route at any time, and the user input could fire the multiple things to do, if I want to do these things with newlisp script, I must use the newlisp as multi-thread environment.



I'd read the source code of newlisp, the "newlispEvalStr" route is not thread safe, this means it could not run at the same time because of newlisp use many global variables like cellCount, symbolCount, envStack, resultStack and so on.



Then, I modified the source code: collect the global variables with a ENVCONTEXT, and modified all the functions with a first argument, just as the ENVCONTEXT,like this:





typedef struct tagEnvContext
{
char startupDir[PATH_MAX]; /* start up directory, if defined via -w */
FILE * IOchannel;          
int ADDR_FAMILY;
int IOchannelIsSocket;
int MAX_CPU_STACK;
long MAX_CELL_COUNT;
size_t cellCount;
size_t symbolCount;
int recursionCount;
UINT printDevice;
UINT * resultStack;
UINT * resultStackIdx;
UINT * envStack;        
UINT * envStackIdx;
CELL * trueCell;
CELL * nilCell;
STREAM strStream;
SYMBOL * nilSymbol;
SYMBOL * trueSymbol;
SYMBOL * startSymbol;
SYMBOL * questionSymbol;
SYMBOL * atSymbol;
SYMBOL * mainContext;
SYMBOL * currentContext;
SYMBOL * errorEvent;
SYMBOL * symbolCheck;
SYMBOL * itSymbol;
void * stringIndexPtr;
CELL * stringCell;
int traceFlag;
int errorReg;
jmp_buf errorJump;
int pushResultFlag;
int prettyPrintFlags;
char lc_decimal_point;
CELL * xmlTags;
CELL * xmlCallback;
CELL * (*evalFunc)(void * pContext, CELL *);
CELL * firstFreeCell;
CELL * lastCellCopied;
SYMBOL * plusSymbol;
SYMBOL * currentFunc;
SYMBOL * argsSymbol;
SYMBOL * mainArgsSymbol;
SYMBOL * dolistIdxSymbol;
SYMBOL * sysSymbol[MAX_REGEX_EXP];
SYMBOL * timerEvent;
SYMBOL * promptEvent;
SYMBOL * commandEvent;
SYMBOL * transferEvent;
SYMBOL * readerEvent;
SYMBOL * symHandler[32];
int currentSignal;
CELL * throwResult;
STREAM readLineStream;
STREAM errorStream;
int parStackCounter;
UINT * envStackTop;
UINT * resultStackTop;
UINT * lambdaStack;
UINT * lambdaStackIdx;
SYMBOL objSymbol;
CELL * objCell;
int evalSilent;
int evalCatchFlag;
int prettyPrintPars;
int prettyPrintCurrent;
int prettyPrintLength;
char * prettyPrintTab;
char * prettyPrintFloat;
UINT prettyPrintMaxLength;
int stringOutputRaw;
char logFile[PATH_MAX];
int pagesize;
int logTraffic;
int connectionTimeout;
char * IOdomain;
int IOport;
int IOchannelIsSocketStream;
int isTTY;
int demonMode;
int noPromptMode;
int forcePromptMode;
int httpMode;
CELL * cellMemory;/* start of cell memory */
CELL * cellBlock; /* the last block allocated */
int dllInitialized;
STREAM libStrStream;
}ENVCONTEXT, * PENVCONTEXT;




And functions are modified like this: (this is the example, and I'd modified all of the functions)





The old:

void initStacks(PENVCONTEXT pContext)
{
MAX_ENV_STACK = MAX_CPU_STACK * 8 * 2;
MAX_RESULT_STACK = MAX_CPU_STACK * 2;
if(envStack != NULL) freeMemory(envStack);
if(resultStack != NULL) freeMemory(resultStack);
if(lambdaStack != NULL) freeMemory(lambdaStack);
envStackIdx = envStack = (UINT *)allocMemory((MAX_ENV_STACK + 16) * sizeof(UINT));
envStackTop = envStack + MAX_ENV_STACK;
resultStackIdx = resultStack = (UINT *)allocMemory((MAX_RESULT_STACK + 16) * sizeof(UINT));
resultStackTop = resultStack + MAX_RESULT_STACK;
lambdaStackIdx = lambdaStack = (UINT *)allocMemory((MAX_RESULT_STACK + 16) * sizeof(UINT));
}




And the new:

void initStacks(PENVCONTEXT pContext)
{
MAX_ENV_STACK = (pContext->MAX_CPU_STACK * 8 * 2);
MAX_RESULT_STACK = (pContext->MAX_CPU_STACK * 2);
if(pContext->envStack != NULL) freeMemory(pContext->envStack);
if(pContext->resultStack != NULL) freeMemory(pContext->resultStack);
if(pContext->lambdaStack != NULL) freeMemory(pContext->lambdaStack);
pContext->envStackIdx = pContext->envStack = (UINT *)allocMemory(pContext, (MAX_ENV_STACK + 16) * sizeof(UINT));
pContext->envStackTop = pContext->envStack + MAX_ENV_STACK;
pContext->resultStackIdx = pContext->resultStack = (UINT *)allocMemory(pContext, (MAX_RESULT_STACK + 16) * sizeof(UINT));
pContext->resultStackTop = pContext->resultStack + MAX_RESULT_STACK;
pContext->lambdaStackIdx = pContext->lambdaStack = (UINT *)allocMemory(pContext, (MAX_RESULT_STACK + 16) * sizeof(UINT));
}




And I export a rote named "CreateContext" to create the new newlisp environment context:



PENVCONTEXT EXPORT CreateContext() {
return (PENVCONTEXT)malloc(sizeof(ENVCONTEXT));
}




After these changes, I could use the code under C to create multiple environment context and run these in difference theads:



PENVCONTEXT p_contextA = CreateContext();
PENVCONTEXT p_contextB = CreateContext();


and in thread A
newlispEvalStr(p_contextA, "codes...");

and in thread B
newlispEvalStr(p_contextB, "codes...");


If I want to change data with threads, I may use the share memory.









Then, I have another thinking: the newlisp had a "import" route, it can import the export function from a module, but the GUI application of mine is a single executable file, I can not use the "import".

 

In order to resolve the problem, I just add a "importFunc" route in the source code:



int EXPORT importFunc(const char * szFunName, UINT ufuncAddr, DWORD dwCallType)
{
    SYMBOL * symbol;
    CELL * pCell;
   
    if (dwCallType == 0)
        pCell = getCell(pContext, CELL_IMPORT_DLL);    
    else if (dwCallType == 1)
        pCell = getCell(pContext, CELL_IMPORT_CDECL);
       
    symbol = translateCreateSymbol(pContext, szFunName, pCell->type, pContext->currentContext, TRUE);
    if(isProtected(symbol->flags))
        return(errorProcExt2(pContext, ERR_SYMBOL_PROTECTED, stuffSymbol(pContext, symbol)));

    deleteList(pContext, (CELL *)symbol->contents);
    symbol->contents = (UINT)pCell;
    pCell->contents = ufuncAddr;
    pCell->aux = (UINT)symbol->name;
   
    if(pCell->contents == 0)
        return 0;
   
    return 1;
}


The first argument "szFunName" has specify the name of the rote to import to newlisp, the second argument "ufuncAddr" has specify the function address to import. The invoke example in C code like this:



//fun1 is a C rote with stdcall type

importFunc("fun1", fun1, 0);



It works good.