G:/ScriptBasic/source/lsp.c

Go to the documentation of this file.
00001 /*
00002 FILE: lsp.c
00003 HEADER: lsp.h
00004 
00005 For documentation of this module read the embedded documentation.
00006 
00007 TO_HEADER:
00008 
00009 typedef struct NODE
00010 {
00011    unsigned char ntype;
00012    union
00013    {
00014       struct
00015       {
00016          struct NODE *_car,*_cdr;
00017       } n_cons;
00018       double fvalue;
00019       long ivalue;
00020       char *svalue;
00021 
00022    }
00023    n_value;
00024 } *LVAL;
00025 
00026 #define NTYPE_CON 1
00027 #define NTYPE_FLO 2
00028 #define NTYPE_INT 3
00029 #define NTYPE_STR 4
00030 #define NTYPE_SYM 5
00031 #define NTYPE_CHR 6
00032 #define NTYPE_FRE 7
00033 
00034 
00035 #define null(x)       ((x) == NIL)
00036 #define freep(x)      ((x)->ntype == NTYPE_FRE)
00037 #define numberp(x)    (floatp(x)||integerp(x))
00038 #define endp(x) null(x)
00039 #define eq(x,y)   ((x)==(y))
00040 
00041 #define evenp(x)  (!oddp(x))
00042 #define oddp(x)   (getint(x)&1)
00043 #define minusp(x) (floatp(x) ? getfloat(x) < 0.0 : getint(x) < 0 )
00044 #define plusp(x)  (floatp(x) ? getfloat(x) > 0.0 : getint(x) > 0 )
00045 #define zerop(x)  (floatp(x) ? getfloat(x) == 0.0 : getint(x) == 0 )
00046 
00047 #define first(x)  car(x)
00048 #define second(x) cadr(x)
00049 #define third(x)  caddr(x)
00050 #define fourth(x) cadddr(x)
00051 
00052 #define listp(x)  (consp(x)||null(x))
00053 #define gettype(x)     ((x)->ntype)
00054 #define getstring(x)   ((x)->n_value.svalue)
00055 #define getint(x)      ((x)->n_value.ivalue)
00056 #define getfloat(x)    ((x)->n_value.fvalue)
00057 #define getchr(x)      getint(x)
00058 #define getsymbol(x)   getstring(x)
00059 
00060 #define caar(x) car(car(x))
00061 #define cadr(x) car(cdr(x))
00062 #define cdar(x) cdr(car(x))
00063 #define cddr(x) cdr(cdr(x))
00064 
00065 #define caaar(x) car(car(car(x)))
00066 #define caadr(x) car(car(cdr(x)))
00067 #define cadar(x) car(cdr(car(x)))
00068 #define caddr(x) car(cdr(cdr(x)))
00069 #define cdaar(x) cdr(car(car(x)))
00070 #define cdadr(x) cdr(car(cdr(x)))
00071 #define cddar(x) cdr(cdr(car(x)))
00072 #define cdddr(x) cdr(cdr(cdr(x)))
00073 
00074 #define caaaar(x) car(car(car(car(x))))
00075 #define caaadr(x) car(car(car(cdr(x))))
00076 #define caadar(x) car(car(cdr(car(x))))
00077 #define caaddr(x) car(car(cdr(cdr(x))))
00078 #define cadaar(x) car(cdr(car(car(x))))
00079 #define cadadr(x) car(cdr(car(cdr(x))))
00080 #define caddar(x) car(cdr(cdr(car(x))))
00081 #define cadddr(x) car(cdr(cdr(cdr(x))))
00082 #define cdaaar(x) cdr(car(car(car(x))))
00083 #define cdaadr(x) cdr(car(car(cdr(x))))
00084 #define cdadar(x) cdr(car(cdr(car(x))))
00085 #define cdaddr(x) cdr(car(cdr(cdr(x))))
00086 #define cddaar(x) cdr(cdr(car(car(x))))
00087 #define cddadr(x) cdr(cdr(car(cdr(x))))
00088 #define cdddar(x) cdr(cdr(cdr(car(x))))
00089 #define cddddr(x) cdr(cdr(cdr(cdr(x))))
00090 
00091 #define settype(x,v)    ((x)->ntype=(v))
00092 #define setcar(x,v)     ((x)->n_value.n_cons._car=(v))
00093 #define setcdr(x,v)     ((x)->n_value.n_cons._cdr=(v))
00094 #define setint(x,v)     ((x)->n_value.ivalue=(v))
00095 #define setfloat(x,v)   ((x)->n_value.fvalue=(v))
00096 #define setstring(x,v)  ((x)->n_value.svalue=(v))
00097 #define setchar(x,v)    setint(x,v)
00098 #define setsymbol(x,v)  setstring(x,v)
00099 #define sassoc(x,y) nthsassoc((x),(y),1)
00100 
00101 
00102 #define dolist(X,Y,z) for( X= (z=Y)      ? car(z) : NIL ; z ; \
00103                            X= (z=cdr(z)) ? car(z) : NIL )
00104 
00105 #define dotimes(i,x) for(i = 0 ; i < x ; i++ )
00106 #define loop         for(;;)
00107 
00108 #define newstring()  newnode(NTYPE_STR)
00109 #define newsymbol()  newnode(NTYPE_SYM)
00110 #define newint()     newnode(NTYPE_INT)
00111 #define newfloat()   newnode(NTYPE_FLO)
00112 #define newchar()    newnode(NTYPE_CHR)
00113 #define NIL (LVAL)0
00114 
00115 #define SCR_WIDTH 70
00116 #define BUFFERLENGTH 1024
00117 #define BUFFERINC    1024
00118 #define ERRSTRLEN 5
00119 #define UNGET_BUFFER_LENGTH 10
00120 
00121 typedef struct _tLspObject {
00122   void *(*memory_allocating_function)(size_t, void *);
00123   void (*memory_releasing_function)(void *, void *);
00124   void *pMemorySegment;
00125   FILE *f;
00126   char cOpen,cClose; // the ( and the ) characters
00127   int tabpos,scrsize;
00128   char *buffer;
00129   long cbBuffer;
00130   int SymbolLength;
00131   int CaseFlag;
00132   int UngetBuffer[UNGET_BUFFER_LENGTH];
00133   int UngetCounter;
00134   } tLspObject,*tpLspObject;
00135 
00136 */
00137 
00138 /*POD
00139 =H Functions to handle LISP syntax files.
00140 
00141 This module implements list handling. The actual structures and
00142 names resemble the LISP naming as well as the handled file format is
00143 LISP.
00144 
00145 Using this module the programmer can easily read and write
00146 LISP syntax file and can also handle the structures built up
00147 in the memory.
00148 
00149 Known bug:
00150 
00151 You can only read a single file at a time.
00152 
00153 CUT*/
00154 
00155 #include <stdio.h>
00156 #include <stdlib.h>
00157 #include <string.h>
00158 #include <ctype.h>
00159 #include "lsp.h"
00160 
00161 static char escapers[] = "t\tn\nr\r";
00162 
00163 #define ALLOC(X) (pLSP->memory_allocating_function((X),pLSP->pMemorySegment))
00164 #define FREE(X)  (pLSP->memory_releasing_function((X),pLSP->pMemorySegment))
00165 #define BUFFER   (pLSP->buffer)
00166 #define TABPOS   (pLSP->tabpos)
00167 #define SCRSIZE  (pLSP->scrsize)
00168 /*
00169  * local function to decide wheter a character is within some set
00170  */
00171 static isinset(int ch,char *string)
00172 {
00173    while( ch != *string && *++string );
00174    return *string;
00175 }
00176 
00177 /*
00178  * Local defines used within this file.
00179  */
00180 #define getnode() (LVAL)malloc(sizeof(struct NODE))
00181 #define SRC_WIDTH 80  /* The width of the screen for pretty printing. */
00182 #define WSPACE "\t \f\r\n"
00183 #define CONST1 "!$%&*-+./0123456789:<=>?@[]^_{}~"
00184 #define CONST2 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
00185 #define NUMSET "0123456789"
00186 #define NUMSET1 "0123456789-+"
00187 #define numeral1(x) (isinset((x),NUMSET1))
00188 #define space_p(x) isinset((x),WSPACE)
00189 #define const_p(x) (isinset((x),CONST1)||isinset((x),CONST2))
00190 #define const_p1(x) ((const_p(x))&&(!numeral1(x)))
00191 #define numeral(x) (isinset((x),NUMSET))
00192 #define spaceat(x,f) while(space_p(((x)=getC(pLSP,(f)))))
00193 
00194 /*
00195  * StrDup well known, however rarely implemented function
00196  */
00197 #define StrDup(x) c_StrDup(pLSP,(x))
00198 static char * c_StrDup(tpLspObject pLSP,char *s)
00199 {
00200    char *p;
00201 
00202    p = (char *)ALLOC(sizeof(char)*(strlen(s)+1));
00203    if( p == NULL )return NULL;
00204    strcpy(p,s);
00205    return p;
00206 }
00207 /*-----------------------------------------------------*/
00208 /* Calculate 10^[a]                                    */
00209 static double pow10(double a)
00210 {
00211    int j,i;
00212    double pro,k;
00213 
00214    for( (i= a<0.0) && (a = -a) , j=(int)a , pro=1.0 , k=10; j ;
00215        j%2 && (pro *=k) , j /= 2 , k *= k )
00216       continue;
00217    i && (pro=1.0/pro);
00218    return pro;
00219 }
00220 /*
00221  * Convert a string to double or long.
00222  * string should contain the string
00223  * whatis 0 string is invalid
00224  *        1 string is float
00225  *        2 string is integer
00226  * dres   contains the result if whatis 1
00227  * lres   contains the result if whatis 2
00228  *
00229  * First version if MINIMOS in FORTRAN
00230  * Second version in MINIMOS2LISP converter
00231  * This version in lsp.c
00232  *   (Could you tell the origin?)
00233  */
00234 static void cnumeric(char *string, int *whatis, double *dres, long *lres)
00235 {
00236    double intpart,fracpart,exppart,man;
00237    int i,sig,esig;
00238 
00239    i=1;
00240    sig= 1;
00241    esig=1;
00242    (( *string == '-' && (sig=(-1)) ) || *string == '+') && string++;
00243    for( intpart = 0 ; numeral(*string) ; string++ )
00244    {
00245       intpart *= 10;
00246       intpart += (*string)-'0';
00247    }
00248    if( *string == '.' )
00249       for( man = 1.0 , fracpart = 0.0 ,i = 0 , string ++ ; numeral(*string)
00250           ; string ++ )
00251          fracpart += (man *= 0.1) * ((*string)-'0');
00252    if( *string == 'E' )
00253    {  string++;
00254       (*string == '-' && (esig=(-1))) || *string == '+' && string++;
00255       for( exppart=0.0 , i = 0 ; numeral(*string) ; string++)
00256          exppart = 10*exppart + (*string)-'0';
00257    }
00258    while( space_p(*string) )string++;
00259    if( *string )
00260    {
00261       *whatis = 0;
00262       return;
00263    }
00264    if( i )
00265    {
00266       *lres   = sig*(long)intpart;
00267       *whatis = 2;
00268       return;
00269    }
00270    *dres = sig*(intpart + fracpart)*pow10(esig*exppart);
00271    *whatis = 1;
00272    return;
00273 }
00274 
00275 
00276 static int __GETC(int (*pfGetCharacter)(void *),
00277                 void *pvInput,
00278                 int *UngetBuffer,
00279                 int *UngetCounter
00280                ){
00281   if( *UngetCounter ){
00282     (*UngetCounter) --;
00283     return UngetBuffer[*UngetCounter];
00284     }
00285   return pfGetCharacter(pvInput);
00286   }
00287 
00288 static void __UNGETC(int *UngetBuffer,
00289               int *UngetCounter,
00290               int ch
00291              ){
00292   UngetBuffer[(*UngetCounter)++] = ch;
00293   }
00294 
00295 #define GETC(x) __GETC((int (*)(void *))getc,(x),pLSP->UngetBuffer,&(pLSP->UngetCounter))
00296 #define UNGETC(x) __UNGETC(pLSP->UngetBuffer,&(pLSP->UngetCounter),x)
00297 
00298 /*
00299  * getC to read skipping the comments from the file.
00300  *
00301  * Each comment returns a newline or EOF
00302  *
00303  * Reading strings normal getc is used!
00304  */
00305 static int getC(tpLspObject pLSP,
00306                 FILE *f){
00307    int ch;
00308 
00309    if( (ch=GETC(f)) == ';' )
00310       while( (ch=GETC(f)) != '\n' && ch != EOF )
00311             ;
00312    return ch;
00313 }
00314 
00315 #define SYMBOLLENGTH (pLSP->SymbolLength)
00316 #define CASEFLAG     (pLSP->CaseFlag)
00317 
00318 static void * _mya(size_t x,void *y){
00319   return malloc(x);
00320   }
00321 static void _myf(void *x, void *y){
00322   free(x);
00323   }
00324 
00325 /*POD
00326 =section lsp_init
00327 =H Inititlaize the LSP system
00328 /*FUNCTION*/
00329 LVAL lsp_init(tpLspObject pLSP,
00330               int SymLen,
00331               int CaseFlg,
00332               void *(*memory_allocating_function)(size_t, void *),
00333               void (*memory_releasing_function)(void *, void *),
00334               void *pMemorySegment
00335   ){
00336 /*noverbatim
00337 CUT*/
00338    SYMBOLLENGTH = SymLen;
00339    CASEFLAG     = CaseFlg;
00340    pLSP->memory_allocating_function = memory_allocating_function ?
00341                                       memory_allocating_function
00342                                                :
00343                                       _mya;
00344    pLSP->memory_releasing_function = memory_releasing_function ?
00345                                      memory_releasing_function
00346                                                :
00347                                      _myf;
00348    pLSP->pMemorySegment = pMemorySegment;
00349    pLSP->UngetCounter = 0;
00350    pLSP->cbBuffer = 0;
00351    pLSP->buffer = NULL;
00352    pLSP->cOpen = '(';
00353    pLSP->cClose = ')';
00354    return NIL;
00355 }
00356 
00357 /*POD
00358 =section cons
00359 =H Create a new cons node
00360 /*FUNCTION*/
00361 LVAL c_cons(tpLspObject pLSP
00362   ){
00363 /*noverbatim
00364 CUT*/
00365 /*
00366 TO_HEADER:
00367 #define cons() c_cons(pLSP)
00368 */
00369    LVAL p;
00370 
00371    if( null((p = getnode())) )
00372       return NIL;
00373    settype(p,NTYPE_CON);
00374    setcar(p,NIL);
00375    setcdr(p,NIL);
00376    return p;
00377 }
00378 
00379 /*
00380 TO_HEADER:
00381 #define newnode(x) c_newnode(pLSP,(x))
00382 */
00383 /*POD
00384 =section newnode
00385 =H Create a new node
00386 Create a new node with the given type.
00387 /*FUNCTION*/
00388 LVAL c_newnode(tpLspObject pLSP,
00389                unsigned char type
00390   ){
00391 /*noverbatim
00392 CUT*/
00393    LVAL p;
00394 
00395    if( null((p = getnode())) )
00396       return NIL;
00397 
00398    settype(p,type);
00399    switch( type )
00400    {
00401    case NTYPE_CON:
00402       return NULL;
00403    case NTYPE_FLO:
00404       setfloat(p,0.0);
00405       break;
00406    case NTYPE_INT:
00407       setint(p,0);
00408       break;
00409    case NTYPE_STR:
00410       setstring(p,NULL);
00411       break;
00412    case NTYPE_SYM:
00413       setsymbol(p,NULL);
00414       break;
00415    case NTYPE_CHR:
00416       setchar(p,(char)0);
00417       break;
00418    default:
00419       return NULL;
00420    }
00421    return p;
00422 }
00423 
00424 /*
00425 TO_HEADER:
00426 #define symcmp(x,y) c_symcmp(pLSP,(x),(y))
00427 */
00428 /*POD
00429 =section symcmp
00430 =H Compare a symbol to a string.
00431 
00432 If the symbol is the same as the string then it returns the pointer to the
00433 symbol! (Garanteed.) Otherwise it returns NIL.
00434 
00435 The symbol and the string matches if the first SymbolLength characters
00436 are matching, and CaseFlag says the case sensitivity.
00437 
00438 /*FUNCTION*/
00439 LVAL c_symcmp(tpLspObject pLSP,
00440               LVAL p,
00441               char *s
00442   ){
00443 /*noverbatim
00444 CUT*/
00445   int i;
00446   char *w,cw,cs;
00447 
00448   if( null(p) || !symbolp(p) )return NIL;
00449   /* NOTE: A string should not be so long that decrementing -1 gets to 0! */
00450   for( i = SYMBOLLENGTH , w = getstring(p) ;
00451        i && *s && *w ; i-- , s++ , w++  ){
00452     cw = !CASEFLAG && islower(*w) ? toupper(*w) : *w;
00453     cs = !CASEFLAG && islower(*s) ? toupper(*s) : *s;
00454     if( cw != cs )
00455           return NIL;
00456     }
00457   return  i && ( *w || *s ) ? NIL : p;
00458   }
00459 
00460 /*
00461 TO_HEADER:
00462 #define nthsassoc(x,y,z) c_nthsassoc(pLSP,(x),(y),(z))
00463 */
00464 /*POD
00465 =section nthsassoc
00466 =H Get the nth assoc from a list.
00467 
00468 This works only for B<symbols> !!!
00469 The second argument should be a 
00470 string for symbol comparision.
00471 
00472 /*FUNCTION*/
00473 LVAL c_nthsassoc(tpLspObject pLSP,
00474                  LVAL p,
00475                  char *s,
00476                  int n
00477   ){
00478 /*noverbatim
00479 CUT*/
00480   LVAL fp;
00481 
00482   if( null(p) || !consp(p) )return NIL;
00483   for( fp = p ; fp ; fp = cdr(fp) )
00484     if( !car(fp) || !consp(car(fp)) || !symbolp(caar(fp)) )
00485             continue;
00486     else
00487       if( symcmp(caar(fp),s) && !--n )return car(fp);
00488   return NIL;
00489   }
00490 
00491 /*
00492 TO_HEADER:
00493 #define freelist(x) c_freelist(pLSP,(x))
00494 */
00495 /*POD
00496 =section freelist
00497 =H Free a list
00498 
00499 /*FUNCTION*/
00500 LVAL c_freelist(tpLspObject pLSP,
00501               LVAL p
00502   ){
00503 /*noverbatim
00504 CUT*/
00505    if( null(p) || freep(p) )return NIL;
00506    if(consp(p) )
00507    {
00508       settype(p,NTYPE_FRE);
00509       freelist(car(p));
00510       freelist(cdr(p));
00511    }
00512    if( stringp(p) )
00513       FREE(getstring(p));
00514    else if( symbolp(p) )
00515       FREE(getsymbol(p));
00516    FREE(p);
00517    return NIL;
00518 }
00519 
00520 /*
00521 TO_HEADER:
00522 #define flatc(x) c_flatc(pLSP,(x))
00523 */
00524 /*POD
00525 =section flatc
00526 =H flatc returns the length of printstring
00527 
00528 /*FUNCTION*/
00529 int c_flatc(tpLspObject pLSP,
00530             LVAL p
00531   ){
00532 /*noverbatim
00533 CUT*/
00534   int j;
00535   LVAL fp;
00536 
00537   if( null(p) )return 3;
00538   switch( gettype(p) ){
00539     case NTYPE_CON:
00540       for( fp = p , j = 1/*(*/ ; fp ; fp = cdr(fp) )
00541       j+= flatc(car(fp))+1/*space*/;
00542       return p ? j : 1+j; /*) was calculated as a space. (Not always.) */
00543     case NTYPE_FLO:
00544       sprintf(BUFFER,"%lf",getfloat(p));
00545       break;
00546     case NTYPE_INT:
00547       sprintf(BUFFER,"%ld",getint(p));
00548       break;
00549     case NTYPE_STR:
00550       sprintf(BUFFER,"\"%s\"",getstring(p));
00551       break;
00552     case NTYPE_SYM:
00553       sprintf(BUFFER,"%s",getsymbol(p));
00554       break;
00555     case NTYPE_CHR:
00556       sprintf(BUFFER,"#\\%c",getchr(p));
00557       break;
00558     default:
00559       return 0;
00560       }
00561   return strlen(BUFFER);
00562   }
00563 
00564 /*
00565  * local pprinting function
00566  *
00567  * Do not try to understand how it works. When I wrote it I and God knew how
00568  * it worked. I have forgotten...
00569  * Ask God!
00570  *
00571  * p is the expression is to print.
00572  * k is magic argument to handle non-algorithmic behaviour of pprint.
00573  *   (k holds internal beautiness (!) factor of printout. (AI!) :-)
00574  *  Serious:
00575  *    k=1  we dunno anything about expression
00576  *    k=1  the tabulatig spaces were alrady printed!
00577  *    k=2  we are in flatc mode
00578  *          -dont print tabulating space
00579  *          -there is no need to check flatc size.
00580  */
00581 static LVAL __pprint(tpLspObject pLSP,LVAL p,int k)
00582 #define _pprint(x) __pprint(pLSP,(x),1)
00583 {
00584    LVAL fp;
00585    int j,multiline;
00586    char *s;
00587 
00588    if( null(p) )
00589    {
00590       fprintf(pLSP->f,"NIL");
00591       return NIL;
00592    }
00593    switch(gettype(p))
00594    {
00595    case NTYPE_CON:
00596       if( k == 2 || flatc(p) < SCRSIZE-TABPOS )
00597       {
00598          /* Print in flat mode. */
00599          if( k == 1 )
00600             fprintf(pLSP->f,"%*s(",TABPOS,"");
00601          else
00602             fprintf(pLSP->f,"(");
00603          for( fp = p ; fp ;  )
00604          {
00605             __pprint(pLSP,car(fp),2);
00606             fp = cdr(fp);
00607             if( fp )
00608                fprintf(pLSP->f," ");
00609          }
00610          fprintf(pLSP->f,")");
00611          return NIL;
00612       }
00613       if( atom(fp=car(p)) || flatc(fp) < (SCRSIZE-TABPOS)/2 )
00614       {
00615          fprintf(pLSP->f,"(");
00616          SCRSIZE--; /* Schrink screen size thinking of the closing paren. */
00617          j = flatc(fp)+2;/* ([flatc]SPACE */
00618          TABPOS += j;
00619          __pprint(pLSP,fp,0);
00620          if( cdr(p) )
00621          {
00622             fprintf(pLSP->f," ");
00623             __pprint(pLSP,cadr(p),0);
00624             fprintf(pLSP->f,"\n");
00625             for( fp = cdr(cdr(p)) ; fp ; )
00626             {
00627                fprintf(pLSP->f,"%*s",TABPOS,"");
00628                __pprint(pLSP,car(fp),0);
00629                fp = cdr(fp);
00630                if( fp )
00631                   fprintf(pLSP->f,"\n");
00632             }
00633          }
00634          TABPOS -= j;
00635          fprintf(pLSP->f,")");
00636          SCRSIZE++;
00637          return NIL;
00638       }
00639       fprintf(pLSP->f,"(");
00640        /* Schrink screen size thinking of the closing paren. */
00641       SCRSIZE--;
00642       TABPOS++;
00643       __pprint(pLSP,car(p),0);
00644       if( fp = cdr(p) )
00645          fprintf(pLSP->f,"\n");
00646       while( fp )
00647       {
00648          fprintf(pLSP->f,"%*s",TABPOS,"");
00649          _pprint(car(fp));
00650          fp = cdr(fp);
00651             if( fp )
00652                fprintf(pLSP->f,"\n");
00653       }
00654       TABPOS--;
00655       fprintf(pLSP->f,")");
00656       SCRSIZE++;
00657       return NIL;
00658    case NTYPE_FLO:
00659       fprintf(pLSP->f,"%lf",getfloat(p));
00660       return NIL;
00661    case NTYPE_INT:
00662       fprintf(pLSP->f,"%ld",getint(p));
00663       return NIL;
00664    case NTYPE_STR:
00665       multiline = 0;
00666       for( s=getstring(p) ; *s ; s++ )
00667         if( *s == '\n' ){
00668           multiline = 1;
00669           break;
00670           }
00671 
00672       fprintf(pLSP->f,multiline ? "\"\"\"" : "\"");
00673       for( s=getstring(p) ; *s ; s++ )
00674          switch( *s )
00675          {                      /* Handle spacial characters. */
00676          case '\"':
00677             fprintf(pLSP->f,"\\\"");
00678             break;
00679          default:
00680             fprintf(pLSP->f,"%c",*s);
00681             break;
00682          }
00683       fprintf(pLSP->f,multiline ? "\"\"\"" : "\"");
00684       return NIL;
00685    case NTYPE_SYM:
00686       fprintf(pLSP->f,"%s",getsymbol(p));
00687       return NIL;
00688    case NTYPE_CHR:
00689       fprintf(pLSP->f,"#\\%c",getchr(p));
00690       return NIL;
00691    default:
00692       return NIL;
00693    }
00694    fprintf(pLSP->f,BUFFER);
00695    return NIL;
00696 }
00697 
00698 
00699 /*
00700 TO_HEADER:
00701 #define pprint(x,y) c_pprint(pLSP,(x),(y))
00702 */
00703 /*POD
00704 =section pprint
00705 =H Pretty print a list.
00706 =verbatim
00707 pp-list
00708  Pretty-print a list expression.
00709      IF <the flatsize length of *expr is less than pp-maxlen*>
00710          THEN print the expression on one line,
00711      ELSE
00712      IF <the car of the expression is an atom> or
00713         <the flatsize length of the car of the expression is less than
00714          the half of the rest of the space>
00715          THEN print the expression in the following form:
00716                  "(<item0> <item1>
00717                            <item2>
00718                              ...
00719                            <itemn> )"
00720      ELSE
00721      IF <the car of the expression is a list>
00722          THEN print the expression in the following form:
00723                  "(<list1>
00724                    <item2>
00725                      ...
00726                    <itemn> )"
00727 
00728 
00729 If an expression can not fit into the area
00730 | -------------------------------------------------------- | then it falls out and gets the end into the new line without printing \n :-(
00731 =noverbatim
00732 /*FUNCTION*/
00733 LVAL c_pprint(tpLspObject pLSP,
00734             LVAL p,
00735             FILE *file
00736   ){
00737 /*noverbatim
00738 CUT*/
00739   /* We start in the first column. */
00740   TABPOS = 0;
00741   /* Screen is not schrinked. */
00742   SCRSIZE = SCR_WIDTH;
00743   pLSP->f = file;
00744   _pprint(p);
00745   fprintf(pLSP->f,"\n");
00746   return NIL;
00747   }
00748 
00749 /*
00750  * local function to read a cons node
00751  */
00752 static LVAL readcons(tpLspObject pLSP,FILE *f)
00753 {
00754    int ch;
00755 
00756    spaceat(ch,f);
00757    if( ch == pLSP->cClose )return NIL;
00758    UNGETC(ch);
00759    return readlist(f);
00760 }
00761 
00762 /* Store a character in the buffer at position 'index'
00763    reallocate the buffer if neccessary.
00764 */
00765 static int storech(tpLspObject pLSP,int i,int ch){
00766   char *pszNewBuffer;
00767   if( i >= pLSP->cbBuffer - 1 ){
00768     pszNewBuffer = ALLOC(pLSP->cbBuffer+BUFFERINC);
00769     if( pszNewBuffer == NULL )return 1;
00770     if( pLSP->cbBuffer )
00771       memcpy(pszNewBuffer,pLSP->buffer,pLSP->cbBuffer);
00772     if( pLSP->buffer )
00773       FREE(pLSP->buffer);
00774     pLSP->buffer = pszNewBuffer;
00775     pLSP->cbBuffer += BUFFERINC;
00776     }
00777   pLSP->buffer[i++] = ch;
00778   pLSP->buffer[i] = (char)0;
00779   return 0;
00780   }
00781 
00782 /*
00783  * local function to read an expression
00784  */
00785 static LVAL _readexpr(tpLspObject pLSP,FILE *f)
00786 {
00787    int ch,ch1,ch2,i;
00788    LVAL p;
00789    char *s;
00790    double dval;
00791    long lval;
00792 
00793 
00794    spaceat(ch,f);
00795    if( ch == EOF )
00796    {
00797       return NIL;
00798    }
00799    if( ch == pLSP->cClose )
00800    {
00801       return NIL;
00802    }
00803 
00804    if( ch == pLSP->cOpen )/* Read a cons node. */
00805       return readcons(pLSP,f);
00806 
00807    /**** Note: XLISP allows 1E++10 as a symbol. This is dangerous.
00808          We do not change XLISP (so far), but here I exclude all symbol
00809          names starting with numeral. */
00810    if( const_p1(ch) )/* Read a symbol. */
00811    {
00812       for( i = 0 ; const_p(ch) ; i++ ){
00813         if( storech(pLSP,i,ch) )return NIL;
00814         ch = getC(pLSP,f);
00815         }
00816       UNGETC(ch);
00817       /* Recognize NIL and nil symbols. */
00818       if( !strcmp(BUFFER,"NIL") || !strcmp(BUFFER,"nil") )
00819          return NIL;
00820       p = newsymbol();
00821       s = StrDup( BUFFER );
00822       if( null(p) || s == NULL )return NIL;
00823       setsymbol(p,s);
00824       return p;
00825    }
00826    if( ch == '\"' ){
00827      ch = GETC(f);
00828      storech(pLSP,0,0); /* inititalize the buffer */
00829      if( ch != '\"' )goto SimpleString;
00830      ch = GETC(f);
00831      if( ch != '\"' ){
00832        UNGETC(ch);
00833        ch = '\"';/* ch should hold the first character of the string that is " now */
00834        goto SimpleString;
00835        }
00836      ch = GETC(f);     
00837      /* multi line string */
00838      for( i = 0 ; ch != EOF ; i++ ){
00839        if( ch == '\"' ){
00840          ch1 = GETC(f);
00841          ch2 = GETC(f);
00842          if( ch1 == '\"' && ch2 == '\"' )break;
00843          UNGETC(ch2);
00844          UNGETC(ch1);
00845          }
00846        if( ch == '\\' ){
00847          ch = GETC(f);
00848          s = escapers;
00849          while( *s ){
00850            if( *s++ == ch ){
00851              ch = *s;
00852              break;
00853              }
00854            if( *s )s++;
00855            }
00856          }
00857        if( storech(pLSP,i,ch) )return NIL;
00858        ch = GETC(f);
00859        }
00860      p = newstring();
00861      s = StrDup( BUFFER );
00862      if( null(p) || s == NULL )return NIL;
00863      setstring(p,s);
00864      return p;
00865      }
00866 
00867    if( ch == '\"' ){/* Read a string. */
00868      ch = GETC(f);/* Eat the " character. */
00869 SimpleString:
00870      for( i = 0 ; ch != '\"' && ch != EOF ; i++ ){
00871        if( ch == '\\' ){
00872          ch = GETC(f);
00873          s = escapers;
00874          while( *s ){
00875            if( *s++ == ch ){
00876              ch = *s;
00877              break;
00878              }
00879            if( *s )s++;
00880            }
00881          }
00882        if( ch == '\n' )return NIL;
00883        if( storech(pLSP,i,ch) )return NIL;
00884        ch = GETC(f);
00885        }
00886       p = newstring();
00887       s = StrDup( BUFFER );
00888       if( null(p) || s == NULL )
00889       {
00890          return NIL;
00891       }
00892       setstring(p,s);
00893       return p;
00894    }
00895    if( numeral1(ch) )
00896    {
00897       for( i = 0 ; isinset(ch,"0123456789+-eE.") ; i++ )
00898       {
00899          if( storech(pLSP,i,ch) )return NIL;
00900          ch = getC(pLSP,f);
00901       }
00902       UNGETC(ch);
00903       cnumeric(BUFFER,&i,&dval,&lval);
00904       switch( i )
00905       {
00906       case 0:
00907          return NIL;
00908       case 1:
00909          /* A float number is coming. */
00910          p = newfloat();
00911          if( null(p) )
00912          {
00913             return NIL;
00914          }
00915          setfloat(p,dval);
00916          return p;
00917       case 2:
00918          /* An integer is coming. */
00919          p = newint();
00920          if( null(p) )
00921          {
00922             return NIL;
00923          }
00924          setint(p,lval);
00925          return p;
00926       default:
00927          return NIL;
00928       }
00929    }
00930    return NIL;
00931 }
00932 
00933 /*
00934 TO_HEADER:
00935 #define readlist(x) c_readlist(pLSP,(x))
00936 */
00937 /*POD
00938 =section readlist
00939 =H Read a list from a file.
00940 
00941 The opening '(' character should be away already!
00942 /*FUNCTION*/
00943 LVAL c_readlist(tpLspObject pLSP,
00944                 FILE *f
00945   ){
00946 /*noverbatim
00947 CUT*/
00948    int ch;
00949    LVAL p,q;
00950 
00951    spaceat(ch,f);
00952    if( ch == pLSP->cClose || ch == EOF )return NIL;
00953    UNGETC(ch);
00954    q = cons();
00955    if( null(q) )
00956    {
00957       return NIL;
00958    }
00959    p = _readexpr(pLSP,f);
00960    setcar(q,p);
00961    setcdr(q,readlist(f));
00962    return q;
00963 }
00964 
00965 
00966 /*
00967 TO_HEADER:
00968 #define readexpr(x) c_readexpr(pLSP,(x))
00969 */
00970 /*POD
00971 =section readexpr
00972 =H Read an expression from a file.
00973 /*FUNCTION*/
00974 LVAL c_readexpr(tpLspObject pLSP,
00975                 FILE *f
00976   ){
00977 /*noverbatim
00978 CUT*/
00979   int ch;
00980 
00981   spaceat(ch,f);
00982   if( ch == EOF )return NIL;
00983   UNGETC(ch);
00984   return _readexpr(pLSP,f);
00985   }
00986 
00987 /*
00988 TO_HEADER:
00989 #define skipexpr(x) c_skipexpr(pLSP,(x))
00990 */
00991 /*POD
00992 =section skipexpr
00993 =H  Reads an expression and forgets
00994 /*FUNCTION*/
00995 LVAL c_skipexpr(tpLspObject pLSP,
00996                 FILE *f
00997   ){
00998 /*noverbatim
00999 CUT*/
01000   LVAL p;
01001 
01002   p = readexpr(f);
01003   freelist(p);
01004   return NIL;
01005   }
01006 
01007 /*
01008 TO_HEADER:
01009 #define llength(x) c_llength(pLSP,(x))
01010 */
01011 /*POD
01012 =section llength
01013 =H  Calculates the length of a list.
01014 /*FUNCTION*/
01015 int c_llength(tpLspObject pLSP,
01016               LVAL p
01017   ){
01018 /*noverbatim
01019 CUT*/
01020   int k;
01021 
01022   for( k = 0 ; p ; k++ )
01023     p = cdr(p);
01024   return k;
01025   }
01026 
01027 /*
01028 TO_HEADER:
01029 #define nth(x,y) c_nth(pLSP,(x),(y))
01030 */
01031 /*POD
01032 =section nth
01033 =H Returns the nth element of a list.
01034 /*FUNCTION*/
01035 LVAL c_nth(tpLspObject pLSP,
01036          int n,
01037          LVAL p
01038   ){
01039 /*noverbatim
01040 CUT*/
01041   LVAL q;
01042 
01043   for( q = p ; n && q ; q = cdr(q) )n--;
01044 
01045   return q ? car(q) : NIL;
01046   }
01047 
01048 /*
01049 TO_HEADER:
01050 #define nthcdr(x,y) c_nthcdr(pLSP,(x),(y))
01051 */
01052 /*POD
01053 =section nthcdr
01054 =H Returns the nthcdr element of a list.
01055 /*FUNCTION*/
01056 LVAL c_nthcdr(tpLspObject pLSP,
01057               int n,
01058               LVAL p
01059   ){
01060 /*noverbatim
01061 CUT*/
01062   LVAL q;
01063 
01064   for( q = p ; n && q ; q = cdr(q) )n--;
01065 
01066   return q;
01067   }
01068 
01069 /*
01070 TO_HEADER:
01071 #define char_code(x) c_char_code(pLSP,(x))
01072 */
01073 /*POD
01074 =section char_code
01075 =H Returns the character code of a character.
01076 /*FUNCTION*/
01077 LVAL c_char_code(tpLspObject pLSP,
01078                  LVAL p
01079   ){
01080 /*noverbatim
01081 CUT*/
01082   LVAL q;
01083 
01084   if( null(p) || !characterp(p) )return NIL;
01085   q = newint();
01086   setint(q,(int)getchr(p));
01087   return q;
01088   }
01089 
01090 /*
01091 TO_HEADER:
01092 #define code_char(x) c_code_char(pLSP,(x))
01093 */
01094 /*POD
01095 =section code_char
01096 =H Returns the character character of a code.
01097 /*FUNCTION*/
01098 LVAL c_code_char(tpLspObject pLSP,
01099                  LVAL p
01100   ){
01101 /*noverbatim
01102 CUT*/
01103   LVAL q;
01104 
01105   if( null(p) || !integerp(p) )return NIL;
01106   q = newchar();
01107   setchar(q,(char)getint(p));
01108   return q;
01109   }
01110 
01111 /*
01112 TO_HEADER:
01113 #define char_downcase(x) c_char_downcase(pLSP,(x))
01114 */
01115 /*POD
01116 =section char_downcase
01117 =H Returns the lower case equivalent of the character.
01118 /*FUNCTION*/
01119 LVAL c_char_downcase(tpLspObject pLSP,
01120                      LVAL p
01121   ){
01122 /*noverbatim
01123 CUT*/
01124   LVAL q;
01125 
01126   if( null(p) || !characterp(p) )return NIL;
01127   q = newchar();
01128   setchar(q, (isalpha(getchr(p)) && isupper(getchr(p))) ?
01129           tolower((int) getchr(p)) : getchr(p));
01130   return q;
01131   }
01132 
01133 /*
01134 TO_HEADER:
01135 #define char_upcase(x) c_char_upcase(pLSP,(x))
01136 */
01137 /*POD
01138 =section char_upcase
01139 =H Returns the upper case equivalent of the character.
01140 /*FUNCTION*/
01141 LVAL c_char_upcase(tpLspObject pLSP,
01142                    LVAL p
01143   ){
01144 /*noverbatim
01145 CUT*/
01146   LVAL q;
01147 
01148   if( null(p) || !characterp(p) )return NIL;
01149   q = newchar();
01150   setchar(q, (isalpha(getchr(p)) && islower(getchr(p))) ?
01151           toupper((int) getchr(p)) : getchr(p));
01152   return q;
01153   }
01154 
01155 /*
01156 TO_HEADER:
01157 #define equal(x,y) c_equal(pLSP,(x),(y))
01158 */
01159 /*POD
01160 =section equal
01161 =H Performs equal LISP function.
01162 
01163 Returns 1 if p and q are equal and 0 if not.
01164 /*FUNCTION*/
01165 int c_equal(tpLspObject pLSP,
01166             LVAL p,
01167             LVAL q
01168   ){
01169 /*noverbatim
01170 CUT*/
01171   if( p == q ) return 1;
01172   if( gettype(p) != gettype(q) )return 0;
01173   switch( gettype(p) ){
01174     case NTYPE_CON:
01175       return equal(car(p),car(q)) && equal(cdr(p),cdr(q));
01176     case NTYPE_FLO:
01177       return getfloat(p)==getfloat(q);
01178     case NTYPE_INT:
01179       return getint(p)==getint(q);
01180     case NTYPE_STR:
01181       return  getstring(p) == getstring(q) ||
01182                        !strcmp(getstring(p),getstring(q));
01183     case NTYPE_SYM:
01184       return getsymbol(p) == getsymbol(q) ||
01185                  !strcmp(getsymbol(p),getsymbol(q));
01186     case NTYPE_CHR:
01187       return getchr(p) == getchr(q);
01188     default:
01189       return 0;
01190       break;
01191     }
01192   }
01193 
01194 /*
01195 TO_HEADER:
01196 #define car(x) c_car(pLSP,(x))
01197 */
01198 /*POD
01199 =section car
01200 =H car
01201 
01202 /*FUNCTION*/
01203 LVAL c_car(tpLspObject pLSP,
01204          LVAL x
01205   ){
01206 /*noverbatim
01207 CUT*/
01208   if( null(x) )return NIL;
01209   return ((x)->n_value.n_cons._car);
01210   }
01211 
01212 /*
01213 TO_HEADER:
01214 #define cdr(x) c_cdr(pLSP,(x))
01215 */
01216 /*POD
01217 =section cdr
01218 =H cdr
01219 
01220 /*FUNCTION*/
01221 LVAL c_cdr(tpLspObject pLSP,
01222          LVAL x
01223   ){
01224 /*noverbatim
01225 CUT*/
01226    if( null(x) )return NIL;
01227    return ((x)->n_value.n_cons._cdr);
01228 }
01229 
01230 /*
01231 TO_HEADER:
01232 #define consp(x) c_consp(pLSP,(x))
01233 */
01234 /*POD
01235 =section consp
01236 =H consp
01237 
01238 /*FUNCTION*/
01239 int c_consp(tpLspObject pLSP,
01240             LVAL x
01241   ){
01242 /*noverbatim
01243 CUT*/
01244   if( null(x) )return 0;
01245   return ((x)->ntype == NTYPE_CON);
01246   }
01247 
01248 /*
01249 TO_HEADER:
01250 #define floatp(x) c_floatp(pLSP,(x))
01251 */
01252 /*POD
01253 =section floatp
01254 =H floatp
01255 
01256 /*FUNCTION*/
01257 int c_floatp(tpLspObject pLSP,
01258          LVAL x
01259   ){
01260 /*noverbatim
01261 CUT*/
01262   if( null(x) )return 0;
01263   return ((x)->ntype == NTYPE_FLO);
01264   }
01265 
01266 /*
01267 TO_HEADER:
01268 #define integerp(x) c_integerp(pLSP,(x))
01269 */
01270 /*POD
01271 =section integerp
01272 =H integerp
01273 
01274 /*FUNCTION*/
01275 int c_integerp(tpLspObject pLSP,
01276          LVAL x
01277   ){
01278 /*noverbatim
01279 CUT*/
01280   if( null(x) )return 0;
01281   return ((x)->ntype == NTYPE_INT);
01282   }
01283 
01284 /*
01285 TO_HEADER:
01286 #define stringp(x) c_stringp(pLSP,(x))
01287 */
01288 /*POD
01289 =section stringp
01290 =H stringp
01291 
01292 /*FUNCTION*/
01293 int c_stringp(tpLspObject pLSP,
01294          LVAL x
01295   ){
01296 /*noverbatim
01297 CUT*/
01298   if( null(x) )return 0;
01299   return ((x)->ntype == NTYPE_STR);
01300   }
01301 
01302 /*
01303 TO_HEADER:
01304 #define symbolp(x) c_symbolp(pLSP,(x))
01305 */
01306 /*POD
01307 =section symbolp
01308 =H symbolp
01309 
01310 /*FUNCTION*/
01311 int c_symbolp(tpLspObject pLSP,
01312          LVAL x
01313   ){
01314 /*noverbatim
01315 CUT*/
01316   if( null(x) )return 0;
01317   return ((x)->ntype == NTYPE_SYM);
01318   }
01319 
01320 /*
01321 TO_HEADER:
01322 #define characterp(x) c_characterp(pLSP,(x))
01323 */
01324 /*POD
01325 =section characterp
01326 =H characterp
01327 
01328 /*FUNCTION*/
01329 int c_characterp(tpLspObject pLSP,
01330          LVAL x
01331   ){
01332 /*noverbatim
01333 CUT*/
01334   if( null(x) )return 0;
01335   return ((x)->ntype == NTYPE_CHR);
01336   }
01337 
01338 /*
01339 TO_HEADER:
01340 #define atom(x) c_atom(pLSP,(x))
01341 */
01342 /*POD
01343 =section atom
01344 =H atom
01345 
01346 /*FUNCTION*/
01347 int c_atom(tpLspObject pLSP,
01348          LVAL x
01349   ){
01350 /*noverbatim
01351 CUT*/
01352   if( null(x) )return 0;
01353   return ((x)->ntype != NTYPE_CON);
01354   }

Generated on Sun Mar 12 23:56:31 2006 for ScriptBasic by  doxygen 1.4.6-NO