home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / apps / math / euler / source / mainloop.c < prev    next >
C/C++ Source or Header  |  1993-05-05  |  55KB  |  2,305 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <math.h>
  6. #include <float.h>
  7. #include <stdarg.h>
  8.  
  9. #include "header.h"
  10. #include "sysdep.h"
  11. #include "funcs.h"
  12. #include "graphics.h"
  13.     
  14. char *ramstart,*ramend,*udfend,*startlocal,*endlocal,*newram,
  15.     *varstart,*udframend;
  16. char *next,*udfline;
  17.  
  18. FILE *metafile=0;
  19.  
  20. double epsilon;
  21.  
  22. char titel[]="This is EULER, Version 3.04 compiled %s.\n\n"
  23.     "Type help(Return) for help.\n"
  24.     "Enter command: (%ld Bytes free.)\n\n";
  25.  
  26. int error,quit,surpressed,udf=0,errorout,outputing=1,stringon=0,
  27.     trace=0;
  28. char line[1024];
  29.  
  30. long loopindex=0;
  31.  
  32. int fieldw=15,linew=5;
  33. double maxexpo=1.0e5,minexpo=1.0e-7;
  34. char expoformat[16]=" %14.5e";
  35. char fixedformat[16]=" %14.7f";
  36.  
  37. int nosubmref=0;
  38.  
  39. FILE *infile=0,*outfile=0;
  40.  
  41. header commandheader;
  42. int commandtype;
  43.  
  44. /* dumping to file */
  45.  
  46. void output (char *s)
  47. {    text_mode();
  48.     if (outputing || error) gprint(s);
  49.     if (outfile)
  50.     {    fprintf(outfile,"%s",s);
  51.         if (ferror(outfile))
  52.         {    output("Error on dump file (disk full?).\n");
  53.             error=200;
  54.             fclose(outfile); outfile=0;
  55.         }
  56.     }
  57. }
  58.  
  59. void output1 (char *s, ...)
  60. {    char text [1024];
  61.     va_list v;
  62.     text_mode();
  63.     va_start(v,s);
  64.     vsprintf(text,s,v);
  65.     if (outputing || error) gprint(text);
  66.     if (outfile)
  67.     {    vfprintf(outfile,s,v);
  68.         if (ferror(outfile))
  69.         {    output("Error on dump file (disk full?).\n");
  70.             error=200;
  71.             fclose(outfile); outfile=0;
  72.         }
  73.     }
  74. }
  75.  
  76. /* help */
  77.  
  78. extern commandtyp command_list[];
  79.  
  80. int dohelp (char start[256], char extend[16][16])
  81. /* dohelp
  82. Extend a start string in up to 16 ways to a command or function.
  83. This function is called from the line editor, whenever the HELP
  84. key is pressed.
  85. */
  86. {    int count=0,ln,l;
  87.     header *hd=(header *)ramstart;
  88.     builtintyp *b=builtin_list;
  89.     commandtyp *c=command_list;
  90.     ln=(int)strlen(start);
  91.     while (b->name)
  92.     {    if (!strncmp(start,b->name,ln))
  93.         {    l=(int)strlen(b->name)-ln;
  94.             if (l>0 && l<16)
  95.             {    strcpy(extend[count],b->name+ln);
  96.                 count++;
  97.             }
  98.             if (count>=16) return count;
  99.         }
  100.         b++;
  101.     }
  102.     while (hd<(header *)udfend)
  103.     {    if (!strncmp(start,hd->name,ln))
  104.         {    l=(int)strlen(hd->name)-ln;
  105.             if (l>0 && l<16)
  106.             {    strcpy(extend[count],hd->name+ln);
  107.                 count++;
  108.             }
  109.             if (count>=16) return count;
  110.         }
  111.         hd=nextof(hd);
  112.     }
  113.     while (c->name)
  114.     {    if (!strncmp(start,c->name,ln))
  115.         {    l=(int)strlen(c->name)-ln;
  116.             if (l>0 && l<16)
  117.             {    strcpy(extend[count],c->name+ln);
  118.                 count++;
  119.             }
  120.             if (count>=16) return count;
  121.         }
  122.         c++;
  123.     }
  124.     return count;
  125. }
  126.  
  127. /* functions that manipulate the stack */
  128.  
  129. void kill_local (char *name);
  130. void clear (void)
  131. /***** clear
  132.     clears the stack and remove all variables and functions.
  133. *****/
  134. {    char name[32];
  135.     scan_space();
  136.     if (*next==';' || *next==',' || *next==0)
  137.     {    endlocal=startlocal;
  138.     }
  139.     else
  140.     while(1)
  141.     {    scan_name(name); if (error) return;
  142.         kill_local(name);
  143.         scan_space();
  144.         if (*next==',') { next++; continue; }
  145.         else break;
  146.     }
  147. }
  148.  
  149. int xor (char *n)
  150. /***** xor
  151.     compute a hashcode for the name n.
  152. *****/
  153. {    int r=0;
  154.     while (*n) r^=*n++;
  155.     return r;
  156. }
  157.  
  158. void *make_header (stacktyp type, size_t size, char *name)
  159. /***** make_header
  160.     pushes a new element on the stack.
  161.     return the position after the header.
  162. ******/
  163. {    header *hd;
  164.     char *erg;
  165. #ifdef SPECIAL_ALIGNMENT
  166.     size=(((size-1)/8)+1)*8;
  167. #endif
  168.     hd=(header *)(newram);
  169.     if (newram+size>ramend)
  170.     {    output("Stack overflow!\n"); error=2;
  171.         return 0;
  172.     }
  173.     hd=(header *)newram;
  174.     hd->size=size;
  175.     hd->type=type;
  176.     hd->flags=0;
  177.     if (*name)
  178.     {    strcpy(hd->name,name);
  179.         hd->xor=xor(name);
  180.     }
  181.     else
  182.     {    *(hd->name)=0;
  183.         hd->xor=0;
  184.     }
  185.     erg=newram+sizeof(header);
  186.     newram+=size;
  187.     return erg;
  188. }
  189.  
  190. header *new_matrix (int rows, int columns, char *name)
  191. /***** new_matrix
  192.     pops a new matrix on the stack.
  193. *****/
  194. {    size_t size;
  195.     dims *d;
  196.     header *hd=(header *)newram;
  197.     size=matrixsize(rows,columns);
  198.     d=(dims *)make_header(s_matrix,size,name);
  199.     if (d) { d->c=columns; d->r=rows; }
  200.     return hd;
  201. }
  202.  
  203. header *new_cmatrix (int rows, int columns, char *name)
  204. /***** new_matrix
  205.     pops a new matrix on the stack.
  206. *****/
  207. {    size_t size;
  208.     dims *d;
  209.     header *hd=(header *)newram;
  210.     size=matrixsize(rows,2*columns);
  211.     d=(dims *)make_header(s_cmatrix,size,name);
  212.     if (d) { d->c=columns; d->r=rows; }
  213.     return hd;
  214. }
  215.  
  216. header *new_command (int no)
  217. /***** new_command
  218.     pops a command on stack.
  219. *****/
  220. {    size_t size;
  221.     int *d;
  222.     header *hd=(header *)newram;
  223.     size=sizeof(header)+sizeof(int);
  224.     d=(int *)make_header(s_command,size,"");
  225.     if (d) *d=no;
  226.     return hd;
  227. }
  228.  
  229. header *new_real (double x, char *name)
  230. /***** new real
  231.     pops a double on stack.
  232. *****/
  233. {    size_t size;
  234.     double *d;
  235.     header *hd=(header *)newram;
  236.     size=sizeof(header)+sizeof(double);
  237.     d=(double *)make_header(s_real,size,name);
  238.     if (d) *d=x;
  239.     return hd;
  240. }
  241.  
  242. header *new_string (char *s, size_t length, char *name)
  243. /***** new real
  244.     pops a string on stack.
  245. *****/
  246. {    size_t size;
  247.     char *d;
  248.     header *hd=(header *)newram;
  249.     size=sizeof(header)+((int)(length+1)/2+1)*2;
  250.     d=(char *)make_header(s_string,size,name);
  251.     if (d) strncpy(d,s,length); d[length]=0;
  252.     return hd;
  253. }
  254.  
  255. header *new_udf (char *name)
  256. /***** new real
  257.     pops a udf on stack.
  258. *****/
  259. {    size_t size;
  260.     size_t *d;
  261.     header *hd=(header *)newram;
  262.     size=sizeof(header)+sizeof(size_t)+(LONG)2;
  263.     d=(size_t *)make_header(s_udf,size,name);
  264.     if (d) { *d=sizeof(header)+sizeof(size_t); *((char *)(d+1))=0; }
  265.     return hd;
  266. }
  267.  
  268. header *new_complex (double x, double y, char *name)
  269. /***** new real
  270.     pushes a complex on stack.
  271. *****/
  272. {    size_t size;
  273.     double *d;
  274.     header *hd=(header *)newram;
  275.     size=sizeof(header)+2*sizeof(double);
  276.     d=(double *)make_header(s_complex,size,name);
  277.     if (d) *d=x; *(d+1)=y;
  278.     return hd;
  279. }
  280.  
  281. header *new_reference (header *ref, char *name)
  282. {    size_t size;
  283.     header **d;
  284.     header *hd=(header *)newram;
  285.     size=sizeof(header)+sizeof(header *);
  286.     d=(header **)make_header(s_reference,size,name);
  287.     if (d) *d=ref;
  288.     return hd;
  289. }
  290.  
  291. header *new_subm (header *var, LONG l, char *name)
  292. /* makes a new submatrix, which is a single element */
  293. {    size_t size;
  294.     header **d,*hd=(header *)newram;
  295.     dims *dim;
  296.     int *n,r,c;
  297.     size=sizeof(header)+sizeof(header *)+
  298.         sizeof(dims)+2*sizeof(int);
  299.     d=(header **)make_header(s_submatrix,size,name);
  300.     if (d) *d=var;
  301.     else return hd;
  302.     dim=(dims *)(d+1);
  303.     dim->r=1; dim->c=1;
  304.     n=(int *)(dim+1);
  305.     c=dimsof(var)->c;
  306.     if (c==0 || dimsof(var)->r==0)
  307.     {    output("Matrix is empty!\n"); error=1031; return hd;
  308.     }
  309.     else r=(int)(l/c);
  310.     *n++=r;
  311.     *n=(int)(l-(LONG)r*c-1);
  312.     return hd;
  313. }
  314.  
  315. header *new_csubm (header *var, LONG l, char *name)
  316. /* makes a new submatrix, which is a single element */
  317. {    size_t size;
  318.     header **d,*hd=(header *)newram;
  319.     dims *dim;
  320.     int *n,r,c;
  321.     size=sizeof(header)+sizeof(header *)+
  322.         sizeof(dims)+2*sizeof(int);
  323.     d=(header **)make_header(s_csubmatrix,size,name);
  324.     if (d) *d=var;
  325.     else return hd;
  326.     dim=(dims *)(d+1);
  327.     dim->r=1; dim->c=1;
  328.     n=(int *)(dim+1);
  329.     c=dimsof(var)->c;
  330.     if (c==0 || dimsof(var)->r==0)
  331.     {    output("Matrix is empty!\n"); error=1031; return hd;
  332.     }
  333.     else r=(int)(l/c);
  334.     *n++=r;
  335.     *n=(int)(l-r*c-1);
  336.     return hd;
  337. }
  338.  
  339. header *hnew_submatrix (header *var, header *rows, header *cols, 
  340.     char *name, int type)
  341. {    size_t size;
  342.     header **d;
  343.     double *mr,*mc=0,x,*mvar;
  344.     dims *dim;
  345.     int c,r,*n,i,c0,r0,cvar,rvar,allc=0,allr=0;
  346.     header *hd=(header *)newram;
  347.     getmatrix(var,&rvar,&cvar,&mvar);
  348.     if (rows->type==s_matrix)
  349.     {    if (dimsof(rows)->r==1) r=dimsof(rows)->c;
  350.         else if (dimsof(rows)->c==1) r=dimsof(rows)->r;
  351.         else
  352.         {    output("Illegal index!\n"); error=41; return 0;
  353.         }
  354.         mr=matrixof(rows);
  355.     }
  356.     else if (rows->type==s_real)
  357.     {    r=1; mr=realof(rows);
  358.     }
  359.     else if (rows->type==s_command && *commandof(rows)==c_allv)
  360.     {    allr=1; r=rvar;
  361.     }
  362.     else
  363.     {    output("Illegal index!\n"); error=41; return 0;
  364.     }
  365.     if (cols->type==s_matrix)
  366.     {    if (dimsof(cols)->r==1) c=dimsof(cols)->c;
  367.         else if (dimsof(cols)->c==1) c=dimsof(cols)->r;
  368.         else
  369.         {    output("Illegal index!\n"); error=41; return 0;
  370.         }
  371.         mc=matrixof(cols);
  372.     }
  373.     else if (cols->type==s_real)
  374.     {    c=1; mc=realof(cols);
  375.     }
  376.     else if (cols->type==s_command && *commandof(cols)==c_allv)
  377.     {    allc=1; c=cvar;
  378.     }
  379.     else
  380.     {    output("Illegal index!\n"); error=41; return 0;
  381.     }
  382.     size=sizeof(header)+sizeof(header *)+
  383.         sizeof(dims)+((LONG)r+c)*sizeof(int);
  384.     d=(header **)make_header(type,size,name);
  385.     if (d) *d=var;
  386.     else return hd;
  387.     dim = (dims *)(d+1);
  388.     n=(int *)(dim+1);
  389.     r0=0;
  390.     if (allr)
  391.     {    for (i=0; i<rvar; i++) *n++=i;
  392.         r0=rvar;
  393.     }
  394.     else for (i=0; i<r; i++)
  395.     {    x=(*mr++)-1;
  396.         if (!((x<0.0) || (x>=rvar)) )
  397.         {    *n++=(int)x; r0++;
  398.         }
  399.     }
  400.     c0=0;
  401.     if (allc)
  402.     {    for (i=0; i<cvar; i++) *n++=i;
  403.         c0=cvar;
  404.     }
  405.     else for (i=0; i<c; i++) 
  406.     {    x=(*mc++)-1;
  407.         if (!((x<0.0) || (x>=cvar))) 
  408.         {    *n++=(int)x; c0++;
  409.         }
  410.     }
  411.     dim->r=r0; dim->c=c0;
  412.     size=(char *)n-(char *)hd;
  413. #ifdef SPECIAL_ALIGNMENT
  414.     size=((size-1)/8+1)*8;
  415. #endif
  416.     newram=(char *)hd;
  417.     hd->size=size;
  418.     return hd;
  419. }
  420.  
  421. header *built_csmatrix (header *var, header *rows, header *cols)
  422. /***** built_csmatrix
  423.     built a complex submatrix from the matrix hd on the stack.
  424. *****/
  425. {    double *mr,*mc=0,*mvar,*mh,*m;
  426.     int n,c,r,c0,r0,i,j,cvar,rvar,allc=0,allr=0,*pc,*pr,*nc,*nr;
  427.     header *hd;
  428.     char *ram;
  429.     getmatrix(var,&rvar,&cvar,&mvar);
  430.     if (rows->type==s_matrix)
  431.     {    if (dimsof(rows)->r==1) r=dimsof(rows)->c;
  432.         else if (dimsof(rows)->c==1) r=dimsof(rows)->r;
  433.         else
  434.         {    output("Illegal index!\n"); error=41; return 0;
  435.         }
  436.         mr=matrixof(rows);
  437.     }
  438.     else if (rows->type==s_real)
  439.     {    r=1; mr=realof(rows);
  440.     }
  441.     else if (rows->type==s_command && *commandof(rows)==c_allv)
  442.     {    allr=1; r=rvar;
  443.     }
  444.     else
  445.     {    output("Illegal index!\n"); error=41; return 0;
  446.     }
  447.     if (cols->type==s_matrix)
  448.     {    if (dimsof(cols)->r==1) c=dimsof(cols)->c;
  449.         else if (dimsof(cols)->c==1) c=dimsof(cols)->r;
  450.         else
  451.         {    output("Illegal index!\n"); error=41; return 0;
  452.         }
  453.         mc=matrixof(cols);
  454.     }
  455.     else if (cols->type==s_real)
  456.     {    c=1; mc=realof(cols);
  457.     }
  458.     else if (cols->type==s_command && *commandof(cols)==c_allv)
  459.     {    allc=1; c=cvar;
  460.     }
  461.     else
  462.     {    output("Illegal index!\n"); error=41; return 0;
  463.     }
  464.     ram=newram;
  465.     if (ram+((LONG)(c)+(LONG)(r))*sizeof(int)>ramend)
  466.     {    output("Out of memory!\n"); error=710; return 0;
  467.     }
  468.     nr=pr=(int *)ram; nc=pc=pr+r; newram=(char *)(pc+c);
  469.     c0=0; r0=0;
  470.     if (allc) { for (i=0; i<c; i++) pc[i]=i; c0=c; }
  471.     else for (i=0; i<c; i++)
  472.     {    n=(int)(*mc++)-1;
  473.         if (n>=0 && n<cvar) { *nc++=n; c0++; }
  474.     }
  475.     if (allr) { for (i=0; i<r; i++) pr[i]=i; r0=r; }
  476.     else for (i=0; i<r; i++) 
  477.     {    n=(int)(*mr++)-1;
  478.         if (n>=0 && n<rvar) { *nr++=n; r0++; }
  479.     }
  480.     if (c0==1 && r0==1)
  481.     {    m=cmat(mvar,cvar,pr[0],pc[0]);
  482.         return new_complex(*m,*(m+1),"");
  483.     }
  484.     hd=new_cmatrix(r0,c0,""); if (error) return 0;
  485.     m=matrixof(hd);
  486.     for (i=0; i<r0; i++)
  487.         for (j=0; j<c0; j++)
  488.         {    mh=cmat(mvar,cvar,pr[i],pc[j]);
  489.             *m++=*mh++;
  490.             *m++=*mh;
  491.         }
  492.     return hd;
  493. }
  494.  
  495. header *built_smatrix (header *var, header *rows, header *cols)
  496. /***** built_smatrix
  497.     built a submatrix from the matrix hd on the stack.
  498. *****/
  499. {    double *mr,*mc=0,*mvar,*m;
  500.     int n,c,r,c0,r0,i,j,cvar,rvar,allc=0,allr=0,*pr,*pc,*nc,*nr;
  501.     header *hd;
  502.     char *ram;
  503.     getmatrix(var,&rvar,&cvar,&mvar);
  504.     if (rows->type==s_matrix)
  505.     {    if (dimsof(rows)->r==1) r=dimsof(rows)->c;
  506.         else if (dimsof(rows)->c==1) r=dimsof(rows)->r;
  507.         else
  508.         {    output("Illegal index!\n"); error=41; return 0;
  509.         }
  510.         mr=matrixof(rows);
  511.     }
  512.     else if (rows->type==s_real)
  513.     {    r=1; mr=realof(rows);
  514.     }
  515.     else if (rows->type==s_command && *commandof(rows)==c_allv)
  516.     {    allr=1; r=rvar;
  517.     }
  518.     else
  519.     {    output("Illegal index!\n"); error=41; return 0;
  520.     }
  521.     if (cols->type==s_matrix)
  522.     {    if (dimsof(cols)->r==1) c=dimsof(cols)->c;
  523.         else if (dimsof(cols)->c==1) c=dimsof(cols)->r;
  524.         else
  525.         {    output("Illegal index!\n"); error=41; return 0;
  526.         }
  527.         mc=matrixof(cols);
  528.     }
  529.     else if (cols->type==s_real)
  530.     {    c=1; mc=realof(cols);
  531.     }
  532.     else if (cols->type==s_command && *commandof(cols)==c_allv)
  533.     {    allc=1; c=cvar;
  534.     }
  535.     else
  536.     {    output("Illegal index!\n"); error=41; return 0;
  537.     }
  538.     ram=newram;
  539.     if (ram+((LONG)(c)+(LONG)(r))*sizeof(int)>ramend)
  540.     {    output("Out of memory!\n"); error=710; return 0;
  541.     }
  542.     nr=pr=(int *)ram; nc=pc=pr+r; newram=(char *)(pc+c);
  543.     c0=0; r0=0;
  544.     if (allc) { for (i=0; i<c; i++) pc[i]=i; c0=c; }
  545.     else for (i=0; i<c; i++)
  546.     {    n=(int)(*mc++)-1;
  547.         if (n>=0 && n<cvar) { *nc++=n; c0++; }
  548.     }
  549.     if (allr) { for (i=0; i<r; i++) pr[i]=i; r0=r; }
  550.     else for (i=0; i<r; i++) 
  551.     {    n=(int)(*mr++)-1;
  552.         if (n>=0 && n<rvar) { *nr++=n; r0++; }
  553.     }
  554.     if (c0==1 && r0==1)
  555.     {    return new_real(*mat(mvar,cvar,pr[0],pc[0]),"");
  556.     }
  557.     hd=new_matrix(r0,c0,""); if (error) return 0;
  558.     m=matrixof(hd);
  559.     for (i=0; i<r0; i++)
  560.         for (j=0; j<c0; j++)
  561.             *m++=*mat(mvar,cvar,pr[i],pc[j]);
  562.     return hd;
  563. }
  564.  
  565. header *new_submatrix (header *hd, header *rows, header *cols, 
  566.     char *name)
  567. {    if (nosubmref) return built_smatrix(hd,rows,cols);
  568.     return hnew_submatrix(hd,rows,cols,name,s_submatrix);
  569. }
  570.  
  571. header *new_csubmatrix (header *hd, header *rows, header *cols, 
  572.     char *name)
  573. {    if (nosubmref) return built_csmatrix(hd,rows,cols);
  574.     return hnew_submatrix(hd,rows,cols,name,s_csubmatrix);
  575. }
  576.  
  577. /***************** support functions ************************/
  578.  
  579. void print_error (char *p)
  580. {    int i;
  581.     char *q,outline[1024];
  582.     double x;
  583.     commandtyp *com;
  584.     if (errorout) return;
  585.     if (line<=p && line+1024>p)
  586.     {    output1("error in:\n%s\n",line);
  587.         if ((int)(p-line)<linelength-2)
  588.             for (i=0; i<(int)(p-line); i++) output(" ");
  589.         output("^\n");
  590.     }
  591.     else if (udfon)
  592.     {    q=outline; p=udfline;
  593.         while (*p)
  594.         {    if (*p==2)
  595.             {    p++; memmove((char *)(&x),p,sizeof(double));
  596.                 p+=sizeof(double);
  597.                 sprintf(q,"%g",x);
  598.                 q+=strlen(q);
  599.             }
  600.             else if (*p==3)
  601.             {    p++;
  602.                 memmove((char *)(&com),p,sizeof(commandtyp *));
  603.                 p+=sizeof(commandtyp *);
  604.                 sprintf(q,"%s",com->name);
  605.                 q+=strlen(q);
  606.             }
  607.             else *q++=*p++;
  608.             if (q>outline+1022)
  609.             {    q=outline+1023;
  610.                 break;
  611.             }
  612.         }
  613.         *q++=0;
  614.         output1("Error in :\n%s\n",outline); output("\n");
  615.     }
  616.     errorout=1;
  617. }
  618.  
  619. void read_line (char *line)
  620. {    int count=0,input;
  621.     char *p=line;
  622.     while(1)
  623.     {    input=getc(infile);
  624.         if (input==EOF)
  625.         {    fclose(infile); *p++=1; infile=0;
  626.             break; 
  627.         }
  628.         if (input=='\n') break;
  629.         if (count>=1023) 
  630.         {    output("Line to long!\n"); error=50; *line=0; return;
  631.         }
  632.         if ((char)input>=' ' || (signed char)input<0 || (char)input==TAB)
  633.         {    *p++=(char)input; count++;
  634.         }
  635.     }
  636.     *p=0;
  637. }
  638.  
  639. char *type_udfline (char *start)
  640. {    char outline[1024],*p=start,*q;
  641.     double x;
  642.     commandtyp *com;
  643.     q=outline;
  644.     while (*p)
  645.     {    if (*p==2)
  646.         {    p++; memmove((char *)(&x),p,sizeof(double));
  647.             p+=sizeof(double);
  648.             sprintf(q,"%g",x);
  649.             q+=strlen(q);
  650.         }
  651.         else if (*p==3)
  652.         {    p++;
  653.             memmove((char *)(&com),p,sizeof(commandtyp *));
  654.             p+=sizeof(commandtyp *);
  655.             sprintf(q,"%s",com->name);
  656.             q+=strlen(q);
  657.         }
  658.         else *q++=*p++;
  659.         if (q>outline+1022)
  660.         {    q=outline+1023;
  661.             break;
  662.         }
  663.     }
  664.     *q++=0;
  665.     output(outline); output("\n");
  666.     return p+1;
  667. }
  668.  
  669. void minput (header *hd);
  670.  
  671. void trace_udfline (char *next)
  672. {    int scan,oldtrace;
  673.     extern header *running;
  674.     header *hd,*res;
  675.     output1("%s: ",running->name); type_udfline(next);
  676.     again: wait_key(&scan);
  677.     switch (scan)
  678.     {    case fk1 :
  679.         case cursor_down :
  680.             break;
  681.         case fk2 :
  682.         case cursor_up :
  683.             trace=2; break;
  684.         case fk3 :
  685.         case cursor_right :
  686.             trace=0; break;
  687.         case fk4 :
  688.         case help :
  689.             hd=(header *)newram;
  690.             oldtrace=trace; trace=0;
  691.             new_string("Expression",12,""); if (error) goto cont;
  692.             minput(hd); if (error) goto cont;
  693.             res=getvalue(hd); if (error) goto cont;
  694.             give_out(res);
  695.             cont : newram=(char *)hd;
  696.             trace=oldtrace;
  697.             goto again;
  698.         case fk9 :
  699.         case escape :
  700.             output("Trace interrupted\n"); error=11010; break;
  701.         case fk10 :
  702.             trace=-1; break;
  703.         default :
  704.             output(
  705.                 "\nKeys:\n"
  706.                 "F1 (cursor_down)  Single step\n"
  707.                 "F2 (cursor_up)    Step over subroutines\n"
  708.                 "F3 (cursor_right) Go until return\n"
  709.                 "F4 (help)         Evaluate expression\n"
  710.                 "F9 (escape)       Abort execution\n"
  711.                 "F10               End trace\n\n");
  712.             goto again;
  713.     }
  714. }
  715.  
  716. void next_line (void)
  717. /**** next_line
  718.     read a line from keyboard or file.
  719. ****/
  720. {    if (udfon)
  721.     {    while (*next) next++;
  722.         next++;
  723.         if (*next==1) udfon=0; else udfline=next;
  724.         if (trace>0) trace_udfline(next);
  725.         return;
  726.     }
  727.     else
  728.     {    if (trace==-1) trace=1;
  729.         if (stringon)
  730.         {    error=2300; output("Input ended in string!\n");
  731.             return;
  732.         }
  733.         if (!infile) edit(line);
  734.         else read_line(line);
  735.         next=line;
  736.     }
  737. }
  738.  
  739. void scan_space (void)
  740. {    start: while (*next==' ' || *next==TAB) next++;
  741.     if (!udfon && *next=='.' && *(next+1)=='.')
  742.         {    next_line(); if (error) return; goto start; }
  743. }
  744.  
  745. void do_end (void);
  746. void do_loop (void);
  747. void do_repeat (void);
  748. void do_for (void);
  749.  
  750. void scan_end (void)
  751. /***** scan_end
  752.     scan for "end".
  753. *****/
  754. {    commandtyp *com;
  755.     char *oldline=udfline;
  756.     while (1)
  757.     {    switch (*next)
  758.         {    case 1 : 
  759.                 output("End missing!\n");
  760.                 error=110; udfline=oldline; return;
  761.             case 0 : udfline=next+1; next++; break;
  762.             case 2 : next+=1+sizeof(double); break;
  763.             case 3 : next++; 
  764.                 memmove((char *)(&com),next,sizeof(commandtyp *));
  765.                 next+=sizeof(commandtyp *);
  766.                 if (com->f==do_end)
  767.                 {    if (trace>0) trace_udfline(udfline);
  768.                     return;
  769.                 }
  770.                 else if (com->f==do_repeat || com->f==do_loop ||
  771.                     com->f==do_for)
  772.                 {    scan_end(); if (error) return; }
  773.                 break;
  774.             default : next++;
  775.         }
  776.     }
  777. }
  778.  
  779. void do_endif (void);
  780. void do_else (void);
  781. void do_if (void);
  782.  
  783. void scan_endif (void)
  784. /***** scan_endif
  785.     scan for "endif".
  786. *****/
  787. {    commandtyp *com;
  788.     char *oldline=udfline;
  789.     while (1)
  790.     {    switch (*next)
  791.         {    case 1 : 
  792.                 output("Endif missing, searching for endif!\n");
  793.                 error=110; udfline=oldline; return;
  794.             case 0 : udfline=next+1; next++; break;
  795.             case 2 : next+=1+sizeof(double); break;
  796.             case 3 : next++; 
  797.                 memmove((char *)(&com),next,sizeof(commandtyp *));
  798.                 next+=sizeof(commandtyp *);
  799.                 if (com->f==do_endif)
  800.                 {    if (trace>0) trace_udfline(udfline);
  801.                     return;
  802.                 }
  803.                 else if (com->f==do_if)
  804.                 {    scan_endif(); if (error) return; }
  805.                 break;
  806.             default : next++;
  807.         }
  808.     }
  809. }
  810.  
  811. void scan_else (void)
  812. /***** scan_else
  813.     scan for "else".
  814. *****/
  815. {    commandtyp *com;
  816.     char *oldline=udfline;
  817.     while (1)
  818.     {    switch (*next)
  819.         {    case 1 : 
  820.                 output("Endif missing, searching for else!\n");
  821.                 error=110; udfline=oldline; return;
  822.             case 0 : udfline=next+1; next++; break;
  823.             case 2 : next+=1+sizeof(double); break;
  824.             case 3 : next++; 
  825.                 memmove((char *)(&com),next,sizeof(commandtyp *));
  826.                 next+=sizeof(commandtyp *);
  827.                 if (com->f==do_endif || com->f==do_else)
  828.                 {    if (trace>0) trace_udfline(udfline);
  829.                     return;
  830.                 }
  831.                 else if (com->f==do_if)
  832.                 {    scan_endif(); if (error) return; }
  833.                 break;
  834.             default : next++;
  835.         }
  836.     }
  837. }
  838.  
  839. void scan_name (char *name)
  840. {    int count=0;
  841.     if (!isalpha(*next))
  842.     {    error=11; *name=0; return;
  843.     }
  844.     while (isalpha(*next) || isdigit(*next))
  845.     {    *name++=*next++; count++;
  846.         if (count>=15)
  847.         {    output("Name to long!\n");
  848.             error=11; break;
  849.         }
  850.     }
  851.     *name=0;
  852. }
  853.  
  854. void getmatrix (header *hd, int *r, int *c, double **m)
  855. /***** getmatrix
  856.     get rows and columns from a matrix.
  857. *****/
  858. {    dims *d;
  859.     if (hd->type==s_real || hd->type==s_complex)
  860.     {    *r=*c=1;
  861.         *m=realof(hd);
  862.     }
  863.     else
  864.     {    d=dimsof(hd);
  865.         *m=matrixof(hd);
  866.         *r=d->r; *c=d->c;
  867.     }
  868. }
  869.  
  870. header *searchvar (char *name)
  871. /***** searchvar
  872.     search a local variable, named "name".
  873.     return 0, if not found.
  874. *****/
  875. {    int r;
  876.     header *hd=(header *)startlocal;
  877.     r=xor(name);
  878.     while ((char *)hd<endlocal)
  879.     {    if (r==hd->xor && !strcmp(hd->name,name)) return hd;
  880.         hd=nextof(hd);
  881.     }
  882.     return 0;
  883. }
  884.  
  885. header *searchudf (char *name)
  886. /***** searchudf
  887.     search a udf, named "name".
  888.     return 0, if not found.
  889. *****/
  890. {    header *hd;
  891.     int r;
  892.     r=xor(name);
  893.     hd=(header *)ramstart;
  894.     while ((char *)hd<udfend && hd->type==s_udf)
  895.     {    if (r==hd->xor && !strcmp(hd->name,name)) return hd;
  896.         hd=nextof(hd);
  897.     }
  898.     return 0;
  899. }
  900.  
  901. void kill_local (char *name)
  902. /***** kill_local
  903.     kill a loal variable name, if there is one.
  904. *****/
  905. {    size_t size,rest;
  906.     header *hd=(header *)startlocal;
  907.     while ((char *)hd<endlocal)
  908.     {    if (!strcmp(hd->name,name)) /* found! */
  909.         {    size=hd->size;
  910.             rest=newram-(char *)hd-size;
  911.             if (size) memmove((char *)hd,(char *)hd+size,rest);
  912.             endlocal-=size; newram-=size;
  913.             return;
  914.         }
  915.         hd=(header *)((char *)hd+hd->size);
  916.     }
  917. }
  918.  
  919. void kill_udf (char *name)
  920. /***** kill_udf
  921.     kill a local variable name, if there is one.
  922. *****/
  923. {    size_t size,rest;
  924.     header *hd=(header *)ramstart;
  925.     while ((char *)hd<udfend)
  926.     {    if (!strcmp(hd->name,name)) /* found! */
  927.         {    size=hd->size;
  928. #ifndef SPLIT_MEM
  929.             rest=newram-(char *)hd-size;
  930.             if (size && rest) memmove((char *)hd,(char *)hd+size,rest);
  931.             endlocal-=size; startlocal-=size; newram-=size;
  932. #else
  933.             rest=udfend-(char *)hd-size;
  934.             if (size && rest) memmove((char *)hd,(char *)hd+size,rest);
  935. #endif
  936.             udfend-=size;
  937.             return;
  938.         }
  939.         hd=(header *)((char *)hd+hd->size);
  940.     }
  941. }
  942.  
  943. int sametype (header *hd1, header *hd2)
  944. /***** sametype
  945.     returns true, if hd1 and hd2 have the same type and dimensions.
  946. *****/
  947. {    dims *d1,*d2;
  948.     if (hd1->type!=hd2->type || hd1->size!=hd2->size) return 0;
  949.     if (hd1->type==s_matrix)
  950.     {    d1=dimsof(hd1); d2=dimsof(hd2);
  951.             if (d1->r!=d2->r) return 0;
  952.     }
  953.     return 1;
  954. }
  955.  
  956. header *assign (header *var, header *value)
  957. /***** assign
  958.     assign the value to the variable.
  959. *****/
  960. {    char name[16],*nextvar;
  961.     size_t size,dif;
  962.     double *m,*mv,*m1,*m2;
  963.     int i,j,c,r,cv,rv,*rind,*cind;
  964.     dims *d;
  965.     header *help,*orig;
  966.     if (error) return 0;
  967.     size=value->size;
  968.     if (var->type==s_reference && !referenceof(var))
  969.         /* seems to be a new variable */
  970.     {    strcpy(name,var->name);
  971.         if (value->type==s_udf)
  972.         {    strcpy(value->name,name);
  973.             value->xor=xor(name);
  974. #ifndef SPLIT_MEM
  975.             if (newram+size>ramend)
  976.             {    output("Memory overflow.\n"); error=500; return value;
  977.             }
  978.             memmove(ramstart+size,ramstart,newram-ramstart);
  979.             newram+=size; endlocal+=size; startlocal+=size;
  980.             value=(header *)((char *)value+size);
  981. #else
  982.             if (udfend+size>udframend)
  983.             {    output("Memory overflow.\n"); error=500; return value;
  984.             }
  985.             memmove(ramstart+size,ramstart,udfend-ramstart);
  986. #endif
  987.             udfend+=size;
  988.             memmove(ramstart,(char *)value,size);
  989.             return (header *)ramstart;
  990.         }
  991.         memmove(endlocal+size,endlocal,newram-endlocal);
  992.         value=(header *)((char *)value+size);
  993.         newram+=size;
  994.         memmove(endlocal,(char *)value,size);
  995.         strcpy(((header *)endlocal)->name,name);
  996.         ((header *)endlocal)->xor=xor(name);
  997.         value=(header *)endlocal;
  998.         endlocal+=size;
  999.         return value;
  1000.     }
  1001.     else
  1002.     {    while (var && var->type==s_reference) var=referenceof(var);
  1003.         if (!var)
  1004.         {    error=43; output("Internal variable error!\n"); return 0;
  1005.         }
  1006.         if (var->type!=s_udf && value->type==s_udf)
  1007.         {    output("Cannot assign a UDF to a variable!\n"); error=320;
  1008.             return var;
  1009.         }
  1010.         if (var->type==s_submatrix)
  1011.         {    d=submdimsof(var);
  1012.             if (value->type==s_complex || value->type==s_cmatrix)
  1013.             {    orig=submrefof(var);
  1014.                 help=new_reference(orig,""); 
  1015.                 if (error) return 0;
  1016.                     mcomplex(help); if (error) return 0;
  1017.                 var->type=s_csubmatrix;
  1018.                 submrefof(var)=help;
  1019.                 assign(var,value); if (error) return 0;
  1020.                 submrefof(var)=orig;
  1021.                 assign(orig,help); 
  1022.                 return orig;
  1023.             }
  1024.             else if (value->type!=s_real && value->type!=s_matrix)
  1025.             {    output("Illegal assignment!\n"); error=45; return 0;
  1026.             }
  1027.             getmatrix(value,&rv,&cv,&mv);
  1028.             getmatrix(submrefof(var),&r,&c,&m);
  1029.             if (d->r!=rv || d->c!=cv)
  1030.             {    output("Illegal assignment!\n"); error=45; return 0;
  1031.             }
  1032.             rind=rowsof(var); cind=colsof(var);
  1033.             for (i=0; i<d->r; i++)
  1034.             {    m1=mat(m,c,rind[i],0);
  1035.                 m2=mat(mv,cv,i,0);
  1036.                 for (j=0; j<d->c; j++)
  1037.                 {    m1[cind[j]]=*m2++;
  1038.                 }
  1039.             }
  1040.             return submrefof(var);
  1041.         }
  1042.         else if (var->type==s_csubmatrix)
  1043.         {    d=submdimsof(var);
  1044.             if (value->type==s_real || value->type==s_matrix)
  1045.             {    help=new_reference(value,""); if (error) return 0;
  1046.                 mcomplex(help); if (error) return 0;
  1047.                 assign(var,help);
  1048.                 return submrefof(var);
  1049.             }
  1050.             if (value->type!=s_complex && value->type!=s_cmatrix)
  1051.             {    output("Illegal assignment!\n"); error=45; return 0;
  1052.             }
  1053.             getmatrix(value,&rv,&cv,&mv);
  1054.             getmatrix(submrefof(var),&r,&c,&m);
  1055.             if (d->r!=rv || d->c!=cv)
  1056.             {    output("Illegal assignment!\n"); error=45; return 0;
  1057.             }
  1058.             rind=rowsof(var); cind=colsof(var);
  1059.             for (i=0; i<d->r; i++)
  1060.             {    m1=cmat(m,c,rind[i],0);
  1061.                 m2=cmat(mv,cv,i,0);
  1062.                 for (j=0; j<d->c; j++)
  1063.                 {   copy_complex(m1+(LONG)2*cind[j],m2); m2+=2;
  1064.                 }
  1065.             }
  1066.             return submrefof(var);
  1067.         }        
  1068.         else 
  1069.         {    if ((char *)var<startlocal || (char *)var>endlocal) 
  1070.             /* its not a local variable! */
  1071.             {    if (!sametype(var,value))
  1072.                 {    output1("Cannot change type of non-local variable %s!\n",
  1073.                         var->name);
  1074.                     error=12; return 0;
  1075.                 }
  1076.                 memcpy((char *)(var+1),(char *)(value+1),
  1077.                     value->size-sizeof(header));
  1078.                 return var;
  1079.             }
  1080.             dif=value->size-var->size;
  1081.             if (newram+dif>ramend)
  1082.             {    output("Memory overflow\n"); error=501; return value;
  1083.             }
  1084.             nextvar=(char *)var+var->size;
  1085.             if (dif!=0)
  1086.                 memmove(nextvar+dif,nextvar,newram-nextvar);
  1087.             newram+=dif; endlocal+=dif;
  1088.             value=(header *)((char *)value+dif);
  1089.             strcpy(value->name,var->name);
  1090.             value->xor=var->xor;
  1091.             memmove((char *)var,(char *)value,value->size);
  1092.         }
  1093.     }
  1094.     return var;
  1095. }
  1096.  
  1097. header *next_param (header *hd)
  1098. /***** next_param
  1099.     get the next value on stack, if there is one
  1100. *****/
  1101. {    hd=(header *)((char *)hd+hd->size);
  1102.     if ((char *)hd>=newram) return 0;
  1103.     else return hd;
  1104. }
  1105.  
  1106. /********************* interpreter **************************/
  1107.  
  1108. void double_out (double x)
  1109. /***** double_out
  1110.     print a double number.
  1111. *****/
  1112. {    if ((fabs(x)>maxexpo || fabs(x)<minexpo) && x!=0.0) 
  1113.         output1(expoformat,x);
  1114.     else if (x==0.0) output1(fixedformat,0.0); /* take care of -0 */
  1115.     else output1(fixedformat,x);
  1116. }
  1117.  
  1118. void out_matrix (header *hd)
  1119. /***** out_matrix
  1120.    print a matrix.
  1121. *****/
  1122. {    int c,r,i,j,c0,cend;
  1123.     double *m,*x;
  1124.     getmatrix(hd,&r,&c,&m);
  1125.     for (c0=0; c0<c; c0+=linew)
  1126.     {    cend=c0+linew-1; 
  1127.         if (cend>=c) cend=c-1;
  1128.         if (c>linew) output2("Column %d to %d:\n",c0+1,cend+1);
  1129.         for (i=0; i<r; i++)
  1130.         {    x=mat(m,c,i,c0);
  1131.             for (j=c0; j<=cend; j++) double_out(*x++);
  1132.             output("\n");
  1133.             if (test_key()==escape) return;
  1134.         }
  1135.     }
  1136. }
  1137.  
  1138. void complex_out (double x, double y)
  1139. /***** double_out
  1140.     print a complex number.
  1141. *****/
  1142. {    if ((fabs(x)>maxexpo || fabs(x)<minexpo) && x!=0.0) 
  1143.         output1(expoformat,x);
  1144.     else output1(fixedformat,x);
  1145.     output("+");
  1146.     if ((fabs(y)>maxexpo || fabs(y)<minexpo) && y!=0.0) 
  1147.         output1(expoformat,y);
  1148.     else output1(fixedformat,y);
  1149.     output("i ");
  1150. }
  1151.  
  1152. void out_cmatrix (header *hd)
  1153. /***** out_matrix
  1154.    print a complex matrix.
  1155. *****/
  1156. {    int c,r,i,j,c0,cend;
  1157.     double *m,*x;
  1158.     getmatrix(hd,&r,&c,&m);
  1159.     for (c0=0; c0<c; c0+=linew/2)
  1160.     {    cend=c0+linew/2-1; 
  1161.         if (cend>=c) cend=c-1;
  1162.         if (c>linew/2) output2("Column %d to %d:\n",c0+1,cend+1);
  1163.         for (i=0; i<r; i++)
  1164.         {    x=cmat(m,c,i,c0);
  1165.             for (j=c0; j<=cend; j++) { complex_out(*x,*(x+1)); 
  1166.                 x+=2; }
  1167.             output("\n");
  1168.             if (test_key()==escape) return;
  1169.         }
  1170.     }
  1171. }
  1172.  
  1173. void give_out (header *hd)
  1174. /***** give_out
  1175.     print a value.
  1176. *****/
  1177. {    switch(hd->type)
  1178.     {    case s_real : double_out(*realof(hd)); output("\n"); break;
  1179.         case s_complex : complex_out(*realof(hd),*(realof(hd)+1));
  1180.             output("\n"); break;
  1181.         case s_matrix : out_matrix(hd); break;
  1182.         case s_cmatrix : out_cmatrix(hd); break;
  1183.         case s_string : output(stringof(hd)); output("\n"); break;
  1184.         default : output("?\n");
  1185.     }
  1186. }
  1187.  
  1188. /***************** some builtin commands *****************/
  1189.  
  1190. void load_file (void)
  1191. /***** load_file
  1192.     inerpret a file.
  1193. *****/
  1194. {    header *filename;
  1195.     char oldline[1024],fn[256],*oldnext;
  1196.     FILE *oldinfile;
  1197.     filename=scan_value(); if (error) return;
  1198.     if (filename->type!=s_string)
  1199.     {    output("Illegal filename!\n"); error=52; return;
  1200.     }
  1201.     if (udfon)
  1202.     {    output("Cannot load a file in a function!\n");
  1203.         error=221; return;
  1204.     }
  1205.     oldinfile=infile;
  1206.     infile=fopen(stringof(filename),"r");
  1207.     if (!infile)
  1208.     {    strcpy(fn,stringof(filename));
  1209.         strcat(fn,EXTENSION);
  1210.         infile=fopen(fn,"r");
  1211.         if (!infile)
  1212.         {    output1("Could not open %s!\n",stringof(filename));
  1213.             error=53; infile=oldinfile; return;
  1214.         }
  1215.     }
  1216.     strcpy(oldline,line); oldnext=next;
  1217.     *line=0; next=line;
  1218.     while (!error && infile && !quit) command();
  1219.     if (infile) fclose(infile);
  1220.     infile=oldinfile;
  1221.     strcpy(line,oldline); next=oldnext;
  1222. }
  1223.  
  1224. commandtyp *preview_command (size_t *l);
  1225.  
  1226. void get_udf (void)
  1227. /***** get_udf
  1228.     define a user defined function.
  1229. *****/
  1230. {    char name[16],argu[16],*p,*firstchar,*startp;
  1231.     int *ph,*phh,count=0,n;
  1232.     size_t l;
  1233.     header *var,*result,*hd;
  1234.     FILE *actfile=infile;
  1235.     commandtyp *com;
  1236.     double x;
  1237.     if (udfon==1)
  1238.     {    output("Cannot define a function in a function!\n");
  1239.         error=60; return;
  1240.     }
  1241.     scan_space(); scan_name(name); if (error) return;
  1242.     kill_udf(name);
  1243.     var=new_reference(0,name); if (error) return;
  1244.     result=new_udf(""); if (error) return;
  1245.     p=udfof(result); udf=1; /* udf is for the prompt! */
  1246.     scan_space(); 
  1247.     ph=(int *)p; p+=sizeof(int);
  1248.     if (*next=='(')
  1249.     {    while(1)
  1250.         {    next++;
  1251.             scan_space();
  1252.             if (*next==')') break;
  1253.             phh=(int *)p; *phh=0; p+=sizeof(int);
  1254.             scan_name(argu); if (error) goto aborted;
  1255.             count++;
  1256.             strcpy(p,argu); p+=16; 
  1257.             *((int *)p)=xor(argu); p+=sizeof(int);
  1258.             test: scan_space();
  1259.             if (*next==')') break;
  1260.             else if (*next=='=')
  1261.             {    next++;
  1262.                 *phh=1;
  1263.                 newram=p;
  1264.                 hd=(header *)p;
  1265.                 scan_value(); if (error) goto aborted;
  1266.                 strcpy(hd->name,argu);
  1267.                 hd->xor=xor(argu);
  1268.                 p=newram;
  1269.                 goto test;
  1270.             }
  1271.             else if (*next==',') continue;
  1272.             else 
  1273.             {    output("Error in parameter list!\n"); error=701;
  1274.                 goto aborted;
  1275.             }
  1276.         }
  1277.         next++;
  1278.     }
  1279.     *ph=count;
  1280.     if (*next==0) { next_line(); }
  1281.     while (1) /* help section of the udf */
  1282.     {    if (*next=='#' && *(next+1)=='#')
  1283.         {    while (*next)
  1284.             {    *p++=*next++;
  1285.                 if (p>=ramend)
  1286.                 {    output("Memory overflow!\n"); error=210; goto stop;
  1287.                 }
  1288.             }
  1289.             *p++=0; next_line();
  1290.         }
  1291.         else break;
  1292.         if (actfile!=infile)
  1293.         {    output("End of file reached in function definition!\n");
  1294.             error=2200; goto stop;
  1295.         }
  1296.     }
  1297.     *udfstartof(result)=(p-(char *)result);
  1298.     startp=p;
  1299.     firstchar=next;
  1300.     while (1)
  1301.     {    if (error) goto stop;
  1302.         if (!strncmp(next,"endfunction",strlen("endfunction")))
  1303.         {    if (p==startp || *(p-1)) *p++=0;
  1304.             *p++=1; next+=strlen("endfunction"); break;
  1305.         }
  1306.         if (actfile!=infile)
  1307.         {    output("End of file reached in function definition!\n");
  1308.             error=2200; goto stop;
  1309.         }
  1310.         if (*next=='#' && *(next+1)=='#')
  1311.         {    *p++=0; next_line(); firstchar=next;
  1312.         }
  1313.         else 
  1314.         if (*next) 
  1315.         {    if (*next=='"')
  1316.             {    *p++=*next++;
  1317.                 while (*next!='"' && *next) *p++=*next++;
  1318.                 if (*next=='"') *p++=*next++;
  1319.             }
  1320.             else if (isdigit(*next) || 
  1321.                          (*next=='.' && isdigit(*(next+1))) )
  1322.             {    if (next!=firstchar && isalpha(*(next-1)))
  1323.                 {    *p++=*next++;
  1324.                     while (isdigit(*next)) *p++=*next++;
  1325.                 }
  1326.                 else
  1327.                 {
  1328.                     if ((p-(char *)result)%2==0) *p++=' ';
  1329.                     *p++=2;
  1330.                        sscanf(next,"%lg%n",&x,&n);
  1331.                        next+=n;
  1332.                        memmove(p,(char *)(&x),sizeof(double));
  1333.                        p+=sizeof(double);
  1334.                    }
  1335.             }
  1336.             else if (isalpha(*next) &&
  1337.                 (next==firstchar || !isalpha(*(next-1))) &&
  1338.                 (com=preview_command(&l))!=0)
  1339.             /* Try to find a builtin command */
  1340.             {    
  1341.                 if ((p-(char *)result)%2==0) *p++=' ';
  1342.                 *p++=3;
  1343.                 memmove(p,(char *)(&com),sizeof(commandtyp *));
  1344.                 p+=sizeof(commandtyp *);
  1345.                 next+=l;
  1346.             }
  1347.             else if (*next=='.' && *(next+1)=='.')
  1348.             {    *p++=' '; next_line(); firstchar=next;
  1349.             }
  1350.             else *p++=*next++;
  1351.         }
  1352.         else { *p++=0; next_line(); firstchar=next; }
  1353.         if (p>=ramend-80)
  1354.         {    output("Memory overflow!\n"); error=210; goto stop;
  1355.         }
  1356.     }
  1357.     stop:
  1358.     udf=0; if (error) return;
  1359.     result->size=((p-(char *)result)/2+1)*2;
  1360. #ifdef SPECIAL_ALIGNMENT
  1361.     result->size=((result->size-1)/8+1)*8;
  1362. #endif
  1363.     newram=(char *)result+result->size;
  1364.     assign(var,result);
  1365.     aborted:
  1366.     udf=0;
  1367. }
  1368.  
  1369. void do_return (void)
  1370. {    if (!udfon)
  1371.     {    output("No user defined function active!\n");
  1372.         error=56; return;
  1373.     }
  1374.     else udfon=2;
  1375. }
  1376.  
  1377. void do_break (void)
  1378. {    if (!udfon)
  1379.     {    output("End only allowed in functions!\n"); error=57;
  1380.     }
  1381. }
  1382.  
  1383. void do_for (void)
  1384. /***** do_for
  1385.     do a for command in a UDF.
  1386.     for i=value to value step value; .... ; end
  1387. *****/
  1388. {    int h,signum;
  1389.     char name[16],*jump;
  1390.     header *hd,*init,*end,*step;
  1391.     double vend,vstep;
  1392.     struct { header hd; double value; } rv;
  1393.     if (!udfon)
  1394.     {    output("For only allowed in functions!\n"); error=57; return;
  1395.     }
  1396.     rv.hd.type=s_real; *rv.hd.name=0;
  1397.     rv.hd.size=sizeof(header)+sizeof(double); rv.value=0.0;
  1398.     scan_space(); scan_name(name); if (error) return;
  1399.     kill_local(name);
  1400.     newram=endlocal;
  1401.     hd=new_reference(&rv.hd,name); if (error) return;
  1402.     endlocal=newram=(char *)hd+hd->size;
  1403.     scan_space(); if (*next!='=')
  1404.     {    output("Syntax error in for.\n"); error=71; goto end;
  1405.     }
  1406.     next++; init=scan(); if (error) goto end;
  1407.     init=getvalue(init); if (error) goto end;
  1408.     if (init->type!=s_real)
  1409.     {    output("Startvalue must be real!\n"); error=72; goto end;
  1410.     }
  1411.     rv.value=*realof(init);
  1412.     scan_space(); if (strncmp(next,"to",2))
  1413.     {    output("Endvalue missing in for!\n"); error=73; goto end;
  1414.     }
  1415.     next+=2;
  1416.     end=scan(); if (error) goto end;
  1417.     end=getvalue(end); if (error) goto end;
  1418.     if (end->type!=s_real)
  1419.     {    output("Endvalue must be real!\n"); error=73; goto end;
  1420.     }
  1421.     vend=*realof(end);
  1422.     scan_space(); 
  1423.     if (!strncmp(next,"step",4))
  1424.     {    next+=4;
  1425.         step=scan(); if (error) goto end;
  1426.         step=getvalue(step); if (error) goto end;
  1427.         if (step->type!=s_real)
  1428.         {    output("Stepvalue must be real!\n"); error=73; goto end;
  1429.         }
  1430.         vstep=*realof(step);
  1431.     }
  1432.     else vstep=1.0;
  1433.     signum=(vstep>0);
  1434.     if (signum && rv.value>vend) { scan_end(); goto end; }
  1435.     else if (!signum && rv.value<vend) { scan_end(); goto end; }
  1436.     newram=endlocal;
  1437.     scan_space(); if (*next==';' || *next==',') next++;
  1438.     jump=next;
  1439.     vend=vend+epsilon*vstep;
  1440.     while (!error)
  1441.     {    if (*next==1)
  1442.         {    output("End missing!\n");
  1443.             error=401; goto end;
  1444.         }
  1445.         h=command();
  1446.         if (h==c_return) break;
  1447.         if (h==c_break) { scan_end(); break; }
  1448.         if (h==c_end)
  1449.         {    rv.value+=vstep;
  1450.             if (signum==1 && rv.value>vend) break;
  1451.             else if (!signum && rv.value<vend) break;
  1452.             else next=jump;
  1453.             if (test_key()==escape) { error=1; break; }
  1454.         }
  1455.     }
  1456.     end : kill_local(name);
  1457. }
  1458.  
  1459. void do_loop (void)
  1460. /***** do_loop
  1461.     do a loop command in a UDF.
  1462.     loop value to value; .... ; end
  1463. *****/
  1464. {    int h;
  1465.     char *jump;
  1466.     header *init,*end;
  1467.     long vend,oldindex;
  1468.     if (!udfon)
  1469.     {    output("Loop only allowed in functions!\n"); error=57; return;
  1470.     }
  1471.     init=scan(); if (error) return;
  1472.     init=getvalue(init); if (error) return;
  1473.     if (init->type!=s_real)
  1474.     {    output("Startvalue must be real!\n"); error=72; return;
  1475.     }
  1476.     oldindex=loopindex;
  1477.     loopindex=(long)*realof(init);
  1478.     scan_space(); if (strncmp(next,"to",2))
  1479.     {    output("Endvalue missing in for!\n"); error=73; goto end;
  1480.     }
  1481.     next+=2;
  1482.     end=scan(); if (error) goto end;
  1483.     end=getvalue(end); if (error) goto end;
  1484.     if (end->type!=s_real)
  1485.     {    output("Endvalue must be real!\n"); error=73; goto end;
  1486.     }
  1487.     vend=(long)*realof(end);
  1488.     if (loopindex>vend) { scan_end(); goto end; }
  1489.     newram=endlocal;
  1490.     scan_space(); if (*next==';' || *next==',') next++;
  1491.     jump=next;
  1492.     while (!error)
  1493.     {    if (*next==1)
  1494.         {    output("End missing!\n");
  1495.             error=401; goto end;
  1496.         }
  1497.         h=command();
  1498.         if (h==c_return) break;
  1499.         if (h==c_break) { scan_end(); break; }
  1500.         if (h==c_end)
  1501.         {    loopindex++;
  1502.             if (loopindex>vend) break;
  1503.             else next=jump;
  1504.             if (test_key()==escape) { error=1; break; }
  1505.         }
  1506.     }
  1507.     end : loopindex=oldindex;
  1508. }
  1509.  
  1510. void do_repeat (void)
  1511. /***** do_loop
  1512.     do a loop command in a UDF.
  1513.     for value to value; .... ; endfor
  1514. *****/
  1515. {    int h;
  1516.     char *jump;
  1517.     if (!udfon)
  1518.     {    output("Loop only allowed in functions!\n"); error=57; return;
  1519.     }
  1520.     newram=endlocal;
  1521.     scan_space(); if (*next==';' || *next==',') next++;
  1522.     jump=next;
  1523.     while (!error)
  1524.     {    if (*next==1)
  1525.         {    output("End missing!\n");
  1526.             error=401; break;
  1527.         }
  1528.         h=command();
  1529.         if (h==c_return) break;
  1530.         if (h==c_break) { scan_end(); break; }
  1531.         if (h==c_end)
  1532.         {    next=jump;
  1533.             if (test_key()==escape) { error=1; break; }
  1534.         }
  1535.     }
  1536. }
  1537.  
  1538. void do_end (void)
  1539. {    if (!udfon)
  1540.     {    output("End only allowed in functions!\n"); error=57;
  1541.     }
  1542. }
  1543.  
  1544. void do_else (void)
  1545. {    if (!udfon)
  1546.     {    output("Else only allowed in functions!\n"); error=57; return;
  1547.     }
  1548.     scan_endif();
  1549. }
  1550.  
  1551. void do_endif (void)
  1552. {    if (!udfon)
  1553.     {    output("Endif only allowed in functions!\n"); error=57;
  1554.     }
  1555. }
  1556.  
  1557. int ctest (header *hd)
  1558. /**** ctest
  1559.     test, if a matrix contains nonzero elements.
  1560. ****/
  1561. {    double *m;
  1562.     LONG n,i;
  1563.     hd=getvalue(hd); if (error) return 0;
  1564.     if (hd->type==s_string) return (*stringof(hd)!=0);
  1565.     if (hd->type==s_real) return (*realof(hd)!=0.0);
  1566.     if (hd->type==s_complex) return (*realof(hd)!=0.0 &&
  1567.         *imagof(hd)!=0.0);
  1568.     if (hd->type==s_matrix)
  1569.     {    n=(LONG)(dimsof(hd)->r)*dimsof(hd)->c;
  1570.         m=matrixof(hd);
  1571.         for (i=0; i<n; i++) if (*m++==0.0) return 0;
  1572.         return 1;
  1573.     }
  1574.     if (hd->type==s_cmatrix)
  1575.     {    n=(LONG)(dimsof(hd)->r)*dimsof(hd)->c;
  1576.         m=matrixof(hd);
  1577.         for (i=0; i<n; i++) 
  1578.         {    if (*m==0.0 && *m==0.0) return 0; m+=2; }
  1579.         return 1;
  1580.     }
  1581.     return 0;
  1582. }
  1583.  
  1584. void do_if (void)
  1585. {    header *cond;
  1586.     int flag;
  1587.     if (!udfon)
  1588.     {    output("If only allowed in functions!\n"); error=111; return;
  1589.     }
  1590.     cond=scan(); if (error) return;
  1591.     flag=ctest(cond); if (error) return;
  1592.     if (!flag) scan_else();
  1593. }
  1594.  
  1595. void do_clg (void)
  1596. {    graphic_mode(); clear_graphics(); gflush();
  1597. }
  1598.  
  1599. void do_cls (void)
  1600. {    text_mode(); clear_screen();
  1601. }
  1602.  
  1603. void do_clear (void)
  1604. {    if (udfon)
  1605.     {    output("Cannot clear in a function!\n");
  1606.         error=120; return;
  1607.     }
  1608.     clear();
  1609. }
  1610.  
  1611. void do_quit (void)
  1612. {    quit=1;
  1613. }
  1614.  
  1615. void do_exec (void)
  1616. {    header *name;
  1617.     char *s;
  1618.     name=scan_value(); if (error) return;
  1619.     if (name->type!=s_string)
  1620.     {    output("Cannot execute a number or matrix!\n");
  1621.         error=130; return;
  1622.     }
  1623.     s=stringof(name);
  1624.     while (*s && !isspace(*s)) s++;
  1625.     if (*s) *s++=0;
  1626.     if (execute(stringof(name),s))
  1627.     {    output("Execution failed or program returned a failure!\n");
  1628.         error=131;
  1629.     }
  1630. }
  1631.  
  1632. void do_forget (void)
  1633. {    char name[16];
  1634.     header *hd;
  1635.     int r;
  1636.     if (udfon)
  1637.     {    output("Cannot forget functions in a function!\n");
  1638.         error=720; return;
  1639.     }
  1640.     while (1)
  1641.     {    scan_space();
  1642.         scan_name(name);
  1643.         r=xor(name);
  1644.         hd=(header *)ramstart;
  1645.         while ((char *)hd<udfend)
  1646.         {    if (r==hd->xor && !strcmp(hd->name,name)) break;
  1647.             hd=nextof(hd);
  1648.         }
  1649.         if ((char *)hd>=udfend)
  1650.         {    output1("Function %s not found!\n",name);
  1651.             error=160; return;
  1652.         }
  1653.         kill_udf(name);
  1654.         scan_space();
  1655.         if (*next!=',') break;
  1656.         else next++;
  1657.     }
  1658. }
  1659.  
  1660. void do_global (void)
  1661. {    char name[16];
  1662.     int r;
  1663.     header *hd;
  1664.     while (1)
  1665.     {    scan_space(); scan_name(name); r=xor(name);
  1666. #ifdef SPLIT_MEM
  1667.         hd=(header *)varstart;
  1668. #else
  1669.         hd=(header *)udfend;
  1670. #endif
  1671.         if (hd==(header *)startlocal) break;
  1672.         while ((char *)hd<startlocal)
  1673.         {    if (r==hd->xor && !strcmp(hd->name,name)) break;
  1674.             hd=nextof(hd);
  1675.         }
  1676.         if ((char *)hd>=startlocal)
  1677.         {    output1("Variable %s not found!\n",name);
  1678.             error=160; return;
  1679.         }
  1680.         newram=endlocal;
  1681.         hd=new_reference(hd,name);
  1682.         newram=endlocal=(char *)nextof(hd);
  1683.         scan_space();
  1684.         if (*next!=',') break;
  1685.         else next++;
  1686.     }
  1687. }
  1688.  
  1689. void print_commands (void);
  1690.  
  1691. void do_list (void)
  1692. {    header *hd;
  1693.     int lcount=0;
  1694.     output("  *** Builtin functions:\n");
  1695.     print_builtin();
  1696.     output("  *** Commands:\n");
  1697.     print_commands();
  1698.     output("  *** Your functions:\n");
  1699.     hd=(header *)ramstart;
  1700.     while ((char *)hd<udfend)
  1701.     {    if (hd->type!=s_udf) break;
  1702.         if (lcount+(int)strlen(hd->name)+2>=linelength) 
  1703.             { lcount=0; output("\n"); }
  1704.         output1("%s ",hd->name);
  1705.         lcount+=(int)strlen(hd->name)+1; 
  1706.         hd=nextof(hd);
  1707.     }
  1708.     output("\n");
  1709. }
  1710.  
  1711. void do_type (void)
  1712. {    char name[16];
  1713.     header *hd;
  1714.     char *p,*pnote;
  1715.     int i,count,defaults;
  1716.     scan_space();
  1717.     scan_name(name); hd=searchudf(name);
  1718.     if (hd && hd->type==s_udf)
  1719.     {    output1("function %s (",name);
  1720.         p=helpof(hd);
  1721.         count=*((int *)p);
  1722.         p+=sizeof(int);
  1723.         pnote=p;
  1724.         for (i=0; i<count; i++)
  1725.         {    defaults=*(int *)p; p+=sizeof(int);
  1726.             output1("%s",p);
  1727.             p+=16+sizeof(int);
  1728.             if (defaults)
  1729.             {    output("=...");
  1730.                 p=(char *)(nextof((header *)p));
  1731.             }
  1732.             if (i!=count-1) output(",");
  1733.         }
  1734.         output(")\n");
  1735.         p=pnote;
  1736.         for (i=0; i<count; i++)
  1737.         {    defaults=*(int *)p; p+=sizeof(int);
  1738.             if (defaults) output1("## Default for %s :\n",p);
  1739.             p+=16+sizeof(int);
  1740.             if (defaults)
  1741.             {    give_out((header *)p);
  1742.                 p=(char *)nextof((header *)p);
  1743.             }
  1744.         }        
  1745.         p=udfof(hd);
  1746.         while (*p!=1 && p<(char *)nextof(hd))
  1747.             p=type_udfline(p);
  1748.         output("endfunction\n");
  1749.     }
  1750.     else
  1751.     {    output("No such function!\n"); error=173;
  1752.     }
  1753. }
  1754.  
  1755. void do_help (void)
  1756. {    char name[16];
  1757.     header *hd;
  1758.     int count,i,defaults;
  1759.     char *p,*end,*pnote;
  1760.     scan_space();
  1761.     scan_name(name); hd=searchudf(name);
  1762.     if (hd && hd->type==s_udf)
  1763.     {    output1("function %s (",name);
  1764.         end=udfof(hd);
  1765.         p=helpof(hd);
  1766.         count=*((int *)p);
  1767.         p+=sizeof(int);
  1768.         pnote=p;
  1769.         for (i=0; i<count; i++)
  1770.         {    defaults=*(int *)p; p+=sizeof(int);
  1771.             output1("%s",p);
  1772.             p+=16+sizeof(int);
  1773.             if (defaults)
  1774.             {    output("=...");
  1775.                 p=(char *)nextof((header *)p);
  1776.             }
  1777.             if (i!=count-1) output(",");
  1778.         }
  1779.         output(")\n");
  1780.         p=pnote;
  1781.         for (i=0; i<count; i++)
  1782.         {    defaults=*(int *)p; p+=sizeof(int);
  1783.             if (defaults) output1("## Default for %s :\n",p);
  1784.             p+=16+sizeof(int);
  1785.             if (defaults)
  1786.             {    give_out((header *)p);
  1787.                 p=(char *)nextof((header *)p);
  1788.             }
  1789.         }        
  1790.         while (*p!=1 && p<end)
  1791.         {    output(p); output("\n");
  1792.             p+=strlen(p); p++;
  1793.         }
  1794.     }
  1795.     else
  1796.     {    output("\n\n Help needs a function name ,e.g.:"
  1797.             "\n >help shortformat\n"
  1798.             " You can get a list of all functions with\n >list\n\n"
  1799.             " If you need online help for builtin functions enter:\n"
  1800.             " >load \"help\""
  1801.             "\n\n To run a demo use:\n >load \"demo\"\n >demo()\n"
  1802.             "\n >quit\n quits this program.\n\n");
  1803.     }
  1804. }
  1805.  
  1806. void do_dump (void)
  1807. {    header *file;
  1808.     if (outfile)
  1809.     {    if (fclose(outfile))
  1810.         {    output("Error while closing dumpfile.\n");
  1811.         }
  1812.         outfile=0;
  1813.     }
  1814.     scan_space();
  1815.     if (*next==';' || *next==',' || *next==0)
  1816.     {    if (*next) next++; return; }
  1817.     file=scan_value();
  1818.     if (error || file->type!=s_string)
  1819.     {    output("Dump needs a filename!\n");
  1820.         error=201; return;
  1821.     }
  1822.     outfile=fopen(stringof(file),"a");
  1823.     if (!outfile)
  1824.     {    output1("Could not open %s.\n",stringof(file));
  1825.     }
  1826. }
  1827.  
  1828. void do_meta (void)
  1829. {    header *file;
  1830.     if (metafile)
  1831.     {    if (fclose(metafile))
  1832.         {    output("Error while closing metafile.\n");
  1833.         }
  1834.         metafile=0;
  1835.     }
  1836.     scan_space();
  1837.     if (*next==';' || *next==',' || *next==0)
  1838.     {    if (*next) next++; return; }
  1839.     file=scan_value();
  1840.     if (error || file->type!=s_string)
  1841.     {    output("Meta needs a filename!\n");
  1842.         error=201; return;
  1843.     }
  1844.     metafile=fopen(stringof(file),"ab");
  1845.     if (!metafile)
  1846.     {    output1("Could not open %s.\n",stringof(file));
  1847.     }
  1848. }
  1849.  
  1850. void do_remove (void)
  1851. {    header *file;
  1852.     file=scan_value();
  1853.     if (error || file->type!=s_string)
  1854.     {    output("Remove needs a string!\n");
  1855.         error=202; return;
  1856.     }
  1857.     remove(stringof(file));
  1858. }
  1859.  
  1860. void do_do (void)
  1861. {    int udfold;
  1862.     char name[16];
  1863.     char *oldnext=next,*udflineold;
  1864.     header *var;
  1865.     scan_space(); scan_name(name); if (error) return;
  1866.     var=searchudf(name);
  1867.     if (!var || var->type!=s_udf)
  1868.     {    output("Need a udf!\n"); error=220; return;
  1869.     }
  1870.     udflineold=udfline; udfline=next=udfof(var); udfold=udfon; udfon=1;
  1871.     while (!error && udfon==1)
  1872.     {    command();
  1873.         if (udfon==2) break;
  1874.         if (test_key()==escape) 
  1875.         {    output("User interrupted!\n"); error=58; break; 
  1876.         }
  1877.     }
  1878.     if (error) output1("Error in function %s\n",var->name);
  1879.     if (udfon==0)
  1880.     {    output1("Return missing in %s!\n",var->name); error=55; }
  1881.     udfon=udfold; udfline=udflineold;
  1882.     if (udfon) next=oldnext;
  1883.     else { next=line; *next=0; }
  1884. }
  1885.  
  1886. void do_mdump (void)
  1887. {    header *hd;
  1888. #ifndef SPLIT_MEM
  1889.     output1("ramstart : 0\nstartlocal : %ld\n",startlocal-ramstart);
  1890.     output1("endlocal : %ld\n",endlocal-ramstart);
  1891.     output1("newram   : %ld\n",newram-ramstart);
  1892.     output1("ramend   : %ld\n",ramend-ramstart);
  1893. #else
  1894.     output1("ramstart : 0\nstartlocal : %ld\n",startlocal-varstart);
  1895.     output1("endlocal : %ld\n",endlocal-varstart);
  1896.     output1("newram   : %ld\n",newram-varstart);
  1897.     output1("ramend   : %ld\n",ramend-varstart);
  1898. #endif
  1899.     hd=(header *)ramstart;
  1900. #ifdef SPLIT_MEM
  1901.     while ((char *)hd<udfend)
  1902.     {
  1903.         output1("%6ld : %16s, ",(char *)hd-ramstart,hd->name);
  1904.         output1("size %6ld ",(long)hd->size);
  1905.         output1("type %d\n",hd->type);
  1906.         hd=nextof(hd);
  1907.     }
  1908.     hd=(header *)varstart;
  1909. #endif
  1910.     while ((char *)hd<newram)
  1911.     {
  1912. #ifndef SPLIT_MEM
  1913.         output1("%6ld : %16s, ",(char *)hd-ramstart,hd->name);
  1914. #else
  1915.         output1("%6ld : %16s, ",(char *)hd-varstart,hd->name);
  1916. #endif
  1917.         output1("size %6ld ",(long)hd->size);
  1918.         output1("type %d\n",hd->type);
  1919.         hd=nextof(hd);
  1920.     }
  1921. }
  1922.  
  1923. void hex_out1 (int n)
  1924. {    if (n<10) output1("%c",n+'0');
  1925.     else output1("%c",n-10+'A');
  1926. }
  1927.  
  1928. void hex_out (unsigned int n)
  1929. {    hex_out1(n/16);
  1930.     hex_out1(n%16);
  1931.     output(" ");
  1932. }
  1933.  
  1934. void string_out (unsigned char *p)
  1935. {    int i;
  1936.     unsigned char a;
  1937.     for (i=0; i<16; i++) 
  1938.     {    a=*p++;
  1939.         output1("%c",(a<' ')?'_':a);
  1940.     }
  1941. }
  1942.  
  1943. void do_hexdump (void)
  1944. {    char name[16];
  1945.     unsigned char *p,*end;
  1946.     int i=0,j;
  1947.     size_t count=0;
  1948.     header *hd;
  1949.     scan_space(); scan_name(name); if (error) return;
  1950.     hd=searchvar(name);
  1951.     if (!hd) hd=searchudf(name);
  1952.     if (error || hd==0) return;
  1953.     p=(unsigned char *)hd; end=p+hd->size;
  1954.     output1("\n%5lx ",count);
  1955.     while (p<end)
  1956.     {    hex_out(*p++); i++; count++;
  1957.         if (i>=16) 
  1958.         {    i=0; string_out(p-16);
  1959.             output1("\n%5lx ",count);
  1960.             if (test_key()==escape) break;
  1961.         }
  1962.     }
  1963.     for (j=i; j<16; j++) output("   ");
  1964.     string_out(p-i);
  1965.     output("\n");
  1966. }
  1967.  
  1968. void do_output (void)
  1969. /**** do_output
  1970.     toggles output.
  1971. ****/
  1972. {    scan_space();
  1973.     if (!strncmp(next,"off",3))
  1974.     {    outputing=0; next+=3;
  1975.     }
  1976.     else if (!strncmp(next,"on",2))
  1977.     {    outputing=1; output("\n"); next+=2;
  1978.     }
  1979.     else outputing=!outputing;
  1980. }
  1981.  
  1982. void do_comment (void)
  1983. {    FILE *fp=infile;
  1984.     if (!fp || udfon)
  1985.     {    output("comment illegal at this place");
  1986.         error=1001; return;
  1987.     }
  1988.     while (strncmp(next,"endcomment",10)!=0)
  1989.     {    next_line();
  1990.         if (infile!=fp)
  1991.         {    output("endcomment missing!\n"); error=1002;
  1992.             return;
  1993.         }
  1994.     }
  1995.     next_line();
  1996. }
  1997.  
  1998. void do_trace(void)
  1999. /**** do_trace
  2000.     toggles tracing or sets the trace bit of a udf.
  2001. ****/
  2002. {    header *f;
  2003.     char name[64];
  2004.     scan_space();
  2005.     if (!strncmp(next,"off",3))
  2006.     {    trace=0; next+=3;
  2007.     }
  2008.     else if (!strncmp(next,"alloff",6))
  2009.     {    next+=6;
  2010.         f=(header *)ramstart;
  2011.         while ((char *)f<udfend && f->type==s_udf)
  2012.         {    f->flags&=~1;
  2013.             f=nextof(f);
  2014.         }
  2015.         trace=0;
  2016.     }    
  2017.     else if (!strncmp(next,"on",2))
  2018.     {    trace=1; next+=2;
  2019.     }
  2020.     else if (*next==';' || *next==',' || *next==0) trace=!trace;
  2021.     else
  2022.     {    if (*next=='"') next++;
  2023.         scan_name(name); if (error) return;
  2024.         if (*next=='"') next++;
  2025.         f=searchudf(name);
  2026.         if (!f || f->type!=s_udf)
  2027.         {    output("Function not found!\n");
  2028.             error=11021; return;
  2029.         }
  2030.         f->flags^=1;
  2031.         if (f->flags&1) output1("Tracing %s\n",name);
  2032.         else output1("No longer tracing %s\n",name);
  2033.         scan_space();
  2034.     }
  2035.     if (*next==';' || *next==',') next++;
  2036. }
  2037.  
  2038. int command_count;
  2039.  
  2040. commandtyp command_list[] =
  2041.     {{"quit",c_quit,do_quit},
  2042.      {"hold",c_hold,ghold},
  2043.      {"shg",c_shg,show_graphics},
  2044.      {"load",c_load,load_file},
  2045.      {"function",c_udf,get_udf},
  2046.      {"return",c_return,do_return},
  2047.      {"for",c_for,do_for},
  2048.      {"endif",c_endif,do_endif},
  2049.      {"end",c_end,do_end},
  2050.      {"break",c_break,do_break},
  2051.      {"loop",c_loop,do_loop},
  2052.      {"else",c_else,do_else},
  2053.      {"if",c_if,do_if},
  2054.      {"repeat",c_repeat,do_repeat},
  2055.      {"clear",c_clear,do_clear},
  2056.      {"clg",c_clg,do_clg},
  2057.      {"cls",c_cls,do_cls},
  2058.      {"exec",c_exec,do_exec},
  2059.      {"forget",c_forget,do_forget},
  2060.      {"global",c_global,do_global},
  2061.      {"list",c_global,do_list},
  2062.      {"type",c_global,do_type},
  2063.      {"dump",c_global,do_dump},
  2064.      {"remove",c_global,do_remove},
  2065.      {"help",c_global,do_help},
  2066.      {"do",c_global,do_do},
  2067.      {"memorydump",c_global,do_mdump},
  2068.      {"hexdump",c_global,do_hexdump},
  2069.      {"output",c_global,do_output},
  2070.      {"meta",c_global,do_meta},
  2071.      {"comment",c_global,do_comment},
  2072.      {"trace",c_global,do_trace},
  2073.      {0,0,0} };
  2074.  
  2075. void print_commands (void)
  2076. {    int linel=0,i;
  2077.     for (i=0; i<command_count; i++)
  2078.     {    if (linel+strlen(command_list[i].name)+2>linelength)
  2079.             { output("\n"); linel=0; }
  2080.         output1("%s ",command_list[i].name);
  2081.         linel+=(int)strlen(command_list[i].name)+1;
  2082.     }
  2083.     output("\n");
  2084. }
  2085.  
  2086. int command_compare (const commandtyp *p1, const commandtyp *p2)
  2087. {    return strcmp(p1->name,p2->name);
  2088. }
  2089.  
  2090. void sort_command (void)
  2091. {    command_count=0;
  2092.     while (command_list[command_count].name) command_count++;
  2093.     qsort(command_list,command_count,sizeof(commandtyp),
  2094.         (int (*)(const void *, const void *))command_compare);
  2095. }
  2096.  
  2097. commandtyp *preview_command (size_t *l)
  2098. {    commandtyp h;
  2099.     char name[16],*a,*n;
  2100.     *l=0;
  2101.     a=next; n=name;
  2102.     while (*l<15 && isalpha(*a)) { *n++=*a++; *l+=1; }
  2103.     *n++=0; if (isalpha(*a)) return 0;
  2104.     h.name=name;
  2105.     return bsearch(&h,command_list,command_count,sizeof(commandtyp),
  2106.         (int (*)(const void *, const void *))command_compare);
  2107. }
  2108.  
  2109. int builtin (void)
  2110. /***** builtin
  2111.     interpret a builtin command, number no.
  2112. *****/
  2113. {    size_t l;
  2114.     commandtyp *p;
  2115.     if (*next==3)
  2116.     {    next++;
  2117. #ifdef SPECIAL_ALIGNMENT
  2118.         memmove((char *)(&p),next,sizeof(commandtyp *));
  2119. #else
  2120.         p=*((commandtyp **)next);
  2121. #endif
  2122.         l=sizeof(commandtyp *);
  2123.     }
  2124.     else if (udfon) return 0;
  2125.     else p=preview_command(&l);
  2126.     if (p)
  2127.     {    next+=l;
  2128.         p->f();
  2129.         if (*next==';' || *next==',') next++;
  2130.         commandtype=p->nr;
  2131.         return 1;
  2132.     }
  2133.     return 0;
  2134. }
  2135.  
  2136. header *scan_expression (void)
  2137. /***** scan_expression
  2138.     scans a variable, a value or a builtin command.
  2139. *****/
  2140. {    if (builtin()) return &commandheader;
  2141.     return scan();
  2142. }
  2143.  
  2144. #define addsize(hd,size) ((header *)((char *)(hd)+size))
  2145.  
  2146. void do_assignment (header *var)
  2147. /***** do_assignment
  2148.     assign a value to a variable.
  2149. *****/
  2150. {    header *variable[8],*rightside[8],*rs,*v,*mark;
  2151.     int rscount,varcount,i,j;
  2152.     size_t offset,oldoffset,dif;
  2153.     char *oldendlocal;
  2154.     scan_space();
  2155.     if (*next=='=')
  2156.     {    next++;
  2157.         nosubmref=1; rs=scan_value(); nosubmref=0;
  2158.         if (error) return;
  2159.         varcount=0;
  2160.         /* count the variables, that get assigned something */
  2161.         while (var<rs)
  2162.         {    if (var->type!=s_reference && var->type!=s_submatrix
  2163.                 && var->type!=s_csubmatrix)
  2164.             {    output("Illegal assignment!\n");
  2165.                 error=210;
  2166.             }
  2167.             variable[varcount]=var; var=nextof(var); varcount++;
  2168.             if (varcount>=8)
  2169.             {    output("To many commas!\n"); error=100; return;
  2170.             }
  2171.         }
  2172.         /* count and note the values, that are assigned to the
  2173.             variables */
  2174.         rscount=0;
  2175.         while (rs<(header *)newram)
  2176.         {    rightside[rscount]=rs;
  2177.             rs=nextof(rs); rscount++;
  2178.             if (rscount>=8)
  2179.             {    output("To many commas!\n"); error=101; return;
  2180.             }
  2181.         }
  2182.         /* cannot assign 2 values to 3 variables , e.g. */
  2183.         if (rscount>1 && rscount<varcount)
  2184.         {    output("Illegal assignment!\n"); error=102; return;
  2185.         }
  2186.         oldendlocal=endlocal;
  2187.         offset=0;
  2188.         /* do all the assignments */
  2189.         if (varcount==1) var=assign(variable[0],rightside[0]);
  2190.         else
  2191.         for (i=0; i<varcount; i++)
  2192.         {    oldoffset=offset;
  2193.             /* assign a variable */
  2194.             var=assign(addsize(variable[i],offset),
  2195.                 addsize(rightside[(rscount>1)?i:0],offset));
  2196.             offset=endlocal-oldendlocal;
  2197.             if (oldoffset!=offset) /* size of var. changed */
  2198.             {    v=addsize(variable[i],offset);
  2199.                 if (v->type==s_reference) mark=referenceof(v);
  2200.                 else mark=submrefof(v);
  2201.                 /* now shift all references of the var.s */
  2202.                 if (mark) /* not a new variable */
  2203.                     for (j=i+1; j<varcount; j++)
  2204.                     {    v=addsize(variable[j],offset);
  2205.                         dif=offset-oldoffset;
  2206.                         if (v->type==s_reference && referenceof(v)>mark)
  2207.                             referenceof(v)=addsize(referenceof(v),dif);
  2208.                         else if (submrefof(v)>mark)
  2209.                             submrefof(v)=addsize(submrefof(v),dif);
  2210.                     }
  2211.             }
  2212.         }
  2213.     }
  2214.     else /* just an expression which is a variable */
  2215.     {    var=getvalue(var);
  2216.     }
  2217.     if (error) return;
  2218.     if (*next!=';') give_out(var);
  2219.     if (*next==',' || *next==' ' || *next==';') next++;
  2220. }
  2221.  
  2222. int command (void)
  2223. /***** command
  2224.     scan a command and interpret it.
  2225.     return, if the user wants to quit.
  2226. *****/
  2227. {    header *expr;
  2228.     int ret=c_none;
  2229.     quit=0; error=0; errorout=0;
  2230.     while(1)
  2231.     {    scan_space();
  2232.         if (*next) break;
  2233.         else next_line();
  2234.     }
  2235.     if (*next==1) return ret;
  2236.     expr=scan_expression();
  2237.     if (!expr) { newram=endlocal; return ret; }
  2238.     if (error) 
  2239.     {    newram=endlocal; 
  2240.         print_error(next); 
  2241.         next=line; line[0]=0; 
  2242.         return ret; 
  2243.     }
  2244.     if (expr==&commandheader)
  2245.     {    newram=endlocal;
  2246.         return commandtype;
  2247.     }
  2248.     switch (expr->type)
  2249.     {    case s_real :
  2250.         case s_complex :
  2251.         case s_matrix :
  2252.         case s_cmatrix :
  2253.         case s_string :
  2254.             if (*next!=';') give_out(expr);
  2255.             if (*next==',' || *next==' ' || *next==';') next++;
  2256.             break;
  2257.         case s_reference :
  2258.         case s_submatrix :
  2259.         case s_csubmatrix :
  2260.             do_assignment(expr);
  2261.             break;
  2262.         default : break;
  2263.     }
  2264.     if (error) print_error(next);
  2265.     newram=endlocal;
  2266.     if (error) { next=line; line[0]=0; }
  2267.     return ret;
  2268. }
  2269.  
  2270. /******************* main functions ************************/
  2271.  
  2272. void clear_fktext (void)
  2273. {    int i;
  2274.     for (i=0; i<10; i++) fktext[i][0]=0;
  2275. }
  2276.  
  2277. void main_loop (int argc, char *argv[])
  2278. {    int i;
  2279. #ifndef SPLIT_MEM
  2280.     output2(titel,__DATE__,(unsigned long)(ramend-ramstart));
  2281. #else
  2282.     output2(titel,__DATE__,(unsigned long)(ramend-varstart));
  2283. #endif
  2284. #ifndef SPLIT_MEM
  2285.     newram=startlocal=endlocal=ramstart;
  2286. #else
  2287.     newram=startlocal=endlocal=varstart;
  2288. #endif
  2289.     udfend=ramstart;
  2290.     epsilon=10000*DBL_EPSILON;
  2291.     sort_builtin(); sort_command(); make_xors(); clear_fktext();
  2292.     next=line;        /* clear input line */
  2293.     strcpy(line,"load \"euler.cfg\";");
  2294.     for (i=1; i<argc; i++)
  2295.     {    strcat(line," load \"");
  2296.         strcat(line,argv[i]);
  2297.         strcat(line,"\";");
  2298.     }
  2299.     while (!quit)
  2300.     {    command();    /* interpret until "quit" */
  2301.         if (trace<0) trace=0;
  2302.     }
  2303. }
  2304.  
  2305.