home *** CD-ROM | disk | FTP | other *** search
/ Mega A/V / mega_av.zip / mega_av / GRAPHUTL / FRPOR172.ZIP / LSYS.C < prev    next >
C/C++ Source or Header  |  1992-03-14  |  23KB  |  912 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #ifdef __TURBOC__
  6. #include <alloc.h>
  7. #else
  8. #include <malloc.h>
  9. #endif
  10. #include "fractint.h"
  11. #define size    ssize
  12. /* Needed for use of asm -- helps decide which pointer to function
  13.  * to put into the struct lsys_cmds.
  14.  */
  15. extern int cpu;
  16. extern int fpu;
  17. extern int debugflag;
  18. extern int xdots,ydots;
  19. extern int colors;
  20. extern char LFileName[];
  21. extern char LName[];
  22. extern double param[];
  23. extern int overflow;
  24.  
  25. int Lsystem();
  26. extern int thinking(int,char *);
  27.  
  28. struct lsys_cmd {
  29.   char ch;
  30.   void (*f)(long n);
  31.   long n;
  32. };
  33.  
  34. static double      _fastcall getnumber(char far **);
  35. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_cmd far **,int);
  36. static int      _fastcall findscale(struct lsys_cmd far *, struct lsys_cmd far **, int);
  37. static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *, struct lsys_cmd far **, int);
  38. static int      _fastcall readLSystemFile(char *);
  39. static void      _fastcall free_rules_mem(void);
  40. static int      _fastcall save_rule(char *,char far **);
  41. static struct lsys_cmd far *SizeTransform(char far *s);
  42. static struct lsys_cmd far *DrawTransform(char far *s);
  43. static void free_lcmds();
  44.  
  45. static long aspect; /* aspect ratio of each pixel, ysize/xsize */
  46.  
  47. /* Some notes to Adrian from PB, made when I integrated with v15:
  48.      printfs changed to work with new user interface
  49.      bug at end of readLSystemFile, the line which said rulind=0 fixed
  50.        to say *rulind=0
  51.      the calloc was not worthwhile, it was just for a 54 byte area, cheaper
  52.        to keep it as a static;    but there was a static 201 char buffer I
  53.        changed to not be static
  54.      use of strdup was a nono, caused problems running out of space cause
  55.        the memory allocated each time was never freed; I've changed to
  56.        use far memory and to free when done
  57.    */
  58.  
  59. long sins[50];
  60. long coss[50];
  61. /* dmaxangle is maxangle - 1. */
  62. char maxangle,dmaxangle,curcolor;
  63. long size;
  64. unsigned long realangle;
  65. long xpos,ypos;
  66. char counter,angle,reverse,stackoflow;
  67. long lsys_Xmin, lsys_Xmax, lsys_Ymin, lsys_Ymax;
  68.  
  69. /* Macro to take an FP number and turn it into a
  70.  * 16/16-bit fixed-point number.
  71.  */
  72. #define FIXEDMUL    524288L
  73. #define FIXEDPT(x)    ((long) (FIXEDMUL * (x)))
  74.  
  75. /* The number by which to multiply sines, cosines and other
  76.  * values with magnitudes less than or equal to 1.
  77.  * sins and coss are a 3/29 bit fixed-point scheme (so the
  78.  * range is +/- 2, with good accuracy.    The range is to
  79.  * avoid overflowing when the aspect ratio is taken into
  80.  * account.
  81.  */
  82. #define FIXEDLT1    536870912.0
  83.  
  84. /* Multiply by this number to convert an unsigned 32-bit long
  85.  * to an angle from 0-2PI.
  86.  */
  87. #define ANGLE2DOUBLE    (2*PI / 4294967296.)
  88.  
  89. static int ispow2(long n)
  90. {
  91.   return (n == (n & -n));
  92. }
  93.  
  94. extern void lsys_doplus(long n);
  95.  
  96. #ifdef XFRACT
  97. static void lsys_doplus(long n)
  98. {
  99.   if (reverse) {
  100.     if (++angle == maxangle)
  101.       angle = 0;
  102.   }
  103.   else {
  104.     if (angle)
  105.       angle--;
  106.     else
  107.       angle = dmaxangle;
  108.   }
  109. }
  110. #endif
  111.  
  112. extern void lsys_doplus_pow2(long n);
  113.  
  114. #ifdef XFRACT
  115. /* This is the same as lsys_doplus, except maxangle is a power of 2. */
  116. static void lsys_doplus_pow2(long n)
  117. {
  118.   if (reverse) {
  119.     angle++;
  120.     angle &= dmaxangle;
  121.   }
  122.   else {
  123.     angle--;
  124.     angle &= dmaxangle;
  125.   }
  126. }
  127. #endif
  128.  
  129. extern void lsys_dominus(long n);
  130.  
  131. #ifdef XFRACT
  132. static void lsys_dominus(long n)
  133. {
  134.   if (reverse) {
  135.     if (angle)
  136.       angle--;
  137.     else
  138.       angle = dmaxangle;
  139.   }
  140.   else {
  141.     if (++angle == maxangle)
  142.       angle = 0;
  143.   }
  144. }
  145. #endif
  146.  
  147. extern void lsys_dominus_pow2(long n);
  148.  
  149. #ifdef XFRACT
  150. static void lsys_dominus_pow2(long n)
  151. {
  152.   if (reverse) {
  153.     angle--;
  154.     angle &= dmaxangle;
  155.   }
  156.   else {
  157.     angle++;
  158.     angle &= dmaxangle;
  159.   }
  160. }
  161. #endif
  162.  
  163. static void lsys_doslash(long n)
  164. {
  165.   if (reverse)
  166.     realangle -= n;
  167.   else
  168.     realangle += n;
  169. }
  170. #ifndef XFRACT
  171. extern void lsys_doslash_386(long n);
  172. #else
  173. #define lsys_doslash_386 lsys_doslash
  174. #endif
  175.  
  176. static void lsys_dobslash(long n)
  177. {
  178.   if (reverse)
  179.     realangle += n;
  180.   else
  181.     realangle -= n;
  182. }
  183.  
  184. #ifndef XFRACT
  185. extern void lsys_dobslash_386(long n);
  186. #else
  187. #define lsys_dobslash_386 lsys_dobslash
  188. #endif
  189.  
  190. static void lsys_doat(long n)
  191. {
  192.   size = multiply(size, n, 19);
  193. }
  194.  
  195. #ifndef XFRACT
  196. extern void lsys_doat_386(long n);
  197. #else
  198. #define lsys_doat_386 lsys_doat
  199. #endif
  200.  
  201. static void lsys_dopipe(long n)
  202. {
  203.   angle += maxangle / 2;
  204.   angle %= maxangle;
  205. }
  206.  
  207. extern void lsys_dopipe_pow2(long n);
  208.  
  209. #ifdef XFRACT
  210. static void lsys_dopipe_pow2(long n)
  211. {
  212.   angle += maxangle >> 1;
  213.   angle &= dmaxangle;
  214. }
  215. #endif
  216.  
  217. extern void lsys_dobang(long n);
  218.  
  219. #ifdef XFRACT
  220. static void lsys_dobang(long n)
  221. {
  222.   reverse = ! reverse;
  223. }
  224. #endif
  225.  
  226. static void lsys_dosizedm(long n)
  227. {
  228.   double angle = (double) realangle * ANGLE2DOUBLE;
  229.   double s, c;
  230.   long fixedsin, fixedcos;
  231.   FPUsincos(&angle, &s, &c);
  232.   fixedsin = (long) (s * FIXEDLT1);
  233.   fixedcos = (long) (c * FIXEDLT1);
  234.  
  235.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  236.   ypos += multiply(size, fixedsin, 29);
  237.  
  238. /* xpos+=size*aspect*cos(realangle*PI/180);  */
  239. /* ypos+=size*sin(realangle*PI/180);         */
  240.   if (xpos>lsys_Xmax) lsys_Xmax=xpos;
  241.   if (ypos>lsys_Ymax) lsys_Ymax=ypos;
  242.   if (xpos<lsys_Xmin) lsys_Xmin=xpos;
  243.   if (ypos<lsys_Ymin) lsys_Ymin=ypos;
  244. }
  245.  
  246. static void lsys_dosizegf(long n)
  247. {
  248.   xpos += multiply(size, (long) coss[angle], 29);
  249.   ypos += multiply(size, (long) sins[angle], 29);
  250. /* xpos+=size*coss[angle];                   */
  251. /* ypos+=size*sins[angle];                   */
  252.   if (xpos>lsys_Xmax) lsys_Xmax=xpos;
  253.   if (ypos>lsys_Ymax) lsys_Ymax=ypos;
  254.   if (xpos<lsys_Xmin) lsys_Xmin=xpos;
  255.   if (ypos<lsys_Ymin) lsys_Ymin=ypos;
  256. }
  257.  
  258. #ifndef XFRACT
  259. extern void lsys_dosizegf_386(long n);
  260. #else
  261. #define lsys_dosizegf_386 lsys_dosizegf
  262. #endif
  263.  
  264. static void lsys_dodrawd(long n)
  265. {
  266.   double angle = (double) realangle * ANGLE2DOUBLE;
  267.   double s, c;
  268.   long fixedsin, fixedcos;
  269.   int lastx, lasty;
  270.   FPUsincos(&angle, &s, &c);
  271.   fixedsin = (long) (s * FIXEDLT1);
  272.   fixedcos = (long) (c * FIXEDLT1);
  273.  
  274.   lastx=(int) (xpos >> 19);
  275.   lasty=(int) (ypos >> 19);
  276.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  277.   ypos += multiply(size, fixedsin, 29);
  278. /* xpos+=size*aspect*cos(realangle*PI/180);   */
  279. /* ypos+=size*sin(realangle*PI/180);          */
  280.   draw_line(lastx,lasty,(int)(xpos >> 19),(int)(ypos>>19),curcolor);
  281. }
  282.  
  283. static void lsys_dodrawm(long n)
  284. {
  285.   double angle = (double) realangle * ANGLE2DOUBLE;
  286.   double s, c;
  287.   long fixedsin, fixedcos;
  288.   FPUsincos(&angle, &s, &c);
  289.   fixedsin = (long) (s * FIXEDLT1);
  290.   fixedcos = (long) (c * FIXEDLT1);
  291.  
  292. /* xpos+=size*aspect*cos(realangle*PI/180);   */
  293. /* ypos+=size*sin(realangle*PI/180);          */
  294.   xpos += multiply(multiply(size, aspect, 19), fixedcos, 29);
  295.   ypos += multiply(size, fixedsin, 29);
  296. }
  297.  
  298. static void lsys_dodrawg(long n)
  299. {
  300.   xpos += multiply(size, (long) coss[angle], 29);
  301.   ypos += multiply(size, (long) sins[angle], 29);
  302. /* xpos+=size*coss[angle];                    */
  303. /* ypos+=size*sins[angle];                    */
  304. }
  305.  
  306. #ifndef XFRACT
  307. extern void lsys_dodrawg_386(long n);
  308. #else
  309. #define  lsys_dodrawg_386 lsys_dodrawg
  310. #endif
  311.  
  312. static void lsys_dodrawf(long n)
  313. {
  314.   int lastx = (int) (xpos >> 19);
  315.   int lasty = (int) (ypos >> 19);
  316.   xpos += multiply(size, (long) coss[angle], 29);
  317.   ypos += multiply(size, (long) sins[angle], 29);
  318. /* xpos+=size*coss[angle];                    */
  319. /* ypos+=size*sins[angle];                    */
  320.   draw_line(lastx,lasty,(int)(xpos>>19),(int)(ypos>>19),curcolor);
  321. }
  322.  
  323. static void lsys_dodrawc(long n)
  324. {
  325.   curcolor = ((int) n) % colors;
  326. }
  327.  
  328. static void lsys_dodrawgt(long n)
  329. {
  330.   curcolor -= n;
  331.   if ((curcolor &= colors-1) == 0)
  332.     curcolor = colors-1;
  333. }
  334.  
  335. static void lsys_dodrawlt(long n)
  336. {
  337.   curcolor += n;
  338.   if ((curcolor &= colors-1) == 0)
  339.     curcolor = 1;
  340. }
  341.  
  342. static double _fastcall getnumber(char far **str)
  343. {
  344.    char numstr[30];
  345.    float ret;
  346.    int i,root,inverse;
  347.  
  348.    root=0;
  349.    inverse=0;
  350.    strcpy(numstr,"");
  351.    (*str)++;
  352.    switch (**str)
  353.    {
  354.    case 'q':
  355.       root=1;
  356.       (*str)++;
  357.       break;
  358.    case 'i':
  359.       inverse=1;
  360.       (*str)++;
  361.       break;
  362.    }
  363.    switch (**str)
  364.    {
  365.    case 'q':
  366.       root=1;
  367.       (*str)++;
  368.       break;
  369.    case 'i':
  370.       inverse=1;
  371.       (*str)++;
  372.       break;
  373.    }
  374.    i=0;
  375.    while (**str<='9' && **str>='0' || **str=='.')
  376.    {
  377.       numstr[i++]=**str;
  378.       (*str)++;
  379.    }
  380.    (*str)--;
  381.    numstr[i]=0;
  382.    ret=atof(numstr);
  383.    if (root)
  384.      ret=sqrt(ret);
  385.    if (inverse)
  386.      ret = 1/ret;
  387.    return ret;
  388. }
  389.  
  390. static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
  391. {
  392.    struct lsys_cmd far **rulind;
  393.    int tran;
  394.  
  395. if (overflow)     /* integer math routines overflowed */
  396.     return NULL;
  397.  
  398. #ifndef __TURBOC__
  399.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  400.       stackoflow = 1;
  401.       return NULL;
  402.       }
  403. #endif
  404.  
  405.    while (command->ch && command->ch !=']') {
  406.       if (! (counter++)) {
  407.      /* let user know we're not dead */
  408.      if (thinking(1,"L-System thinking (higher orders take longer)")) {
  409.         counter--;
  410.         return NULL;
  411.      }
  412.       }
  413.       tran=0;
  414.       if (depth) {
  415.      for(rulind=rules;*rulind;rulind++)
  416.         if ((*rulind)->ch==command->ch) {
  417.            tran=1;
  418.            if (findsize((*rulind)+1,rules,depth-1) == NULL)
  419.           return(NULL);
  420.         }
  421.       }
  422.       if (!depth || !tran) {
  423.     if (command->f)
  424.       (*command->f)(command->n);
  425.     else if (command->ch == '[') {
  426.       char saveang,saverev;
  427.       long savesize,savex,savey;
  428.       unsigned long saverang;
  429.  
  430.       saveang=angle;
  431.       saverev=reverse;
  432.       savesize=size;
  433.       saverang=realangle;
  434.       savex=xpos;
  435.       savey=ypos;
  436.       if ((command=findsize(command+1,rules,depth)) == NULL)
  437.          return(NULL);
  438.       angle=saveang;
  439.       reverse=saverev;
  440.       size=savesize;
  441.       realangle=saverang;
  442.       xpos=savex;
  443.       ypos=savey;
  444.     }
  445.       }
  446.       command++;
  447.    }
  448.    return command;
  449. }
  450.  
  451. static int _fastcall findscale(struct lsys_cmd far *command, struct lsys_cmd far **rules, int depth)
  452. {
  453.    float horiz,vert;
  454.    double xmin, xmax, ymin, ymax;
  455.    double locsize;
  456.    double locaspect;
  457.    int i;
  458.    struct lsys_cmd far *fsret;
  459.    locaspect=SCREENASPECT*xdots/ydots;
  460.    aspect = FIXEDPT(locaspect);
  461.    for(i=0;i<maxangle;i++) {
  462.       sins[i]=(long) ((sin(2*i*PI/maxangle)) * FIXEDLT1);
  463.       coss[i]=(long) ((locaspect * cos(2*i*PI/maxangle)) * FIXEDLT1);
  464.    }
  465.    xpos=ypos=lsys_Xmin=lsys_Xmax=lsys_Ymax=lsys_Ymin=angle=reverse=realangle=counter=0;
  466.    size=FIXEDPT(1);
  467.    fsret = findsize(command,rules,depth);
  468.    thinking(0, NULL); /* erase thinking message if any */
  469.    xmin = (double) lsys_Xmin / FIXEDMUL;
  470.    xmax = (double) lsys_Xmax / FIXEDMUL;
  471.    ymin = (double) lsys_Ymin / FIXEDMUL;
  472.    ymax = (double) lsys_Ymax / FIXEDMUL;
  473.    locsize = (double) size / FIXEDMUL;
  474.    if (fsret == NULL)
  475.       return 0;
  476.    if (xmax == xmin)
  477.       horiz = 1E37;
  478.    else
  479.       horiz = (xdots-10)/(xmax-xmin);
  480.    if (ymax == ymin)
  481.       vert = 1E37;
  482.    else
  483.       vert = (ydots-6) /(ymax-ymin);
  484.    locsize = (vert<horiz) ? vert : horiz;
  485.  
  486.    if (horiz == 1E37)
  487.       xpos = FIXEDPT(xdots/2);
  488.    else
  489.       xpos = FIXEDPT(-xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2);
  490.    if (vert == 1E37)
  491.       ypos = FIXEDPT(ydots/2);
  492.    else
  493.       ypos = FIXEDPT(-ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2);
  494.    size = FIXEDPT(locsize);
  495.    return 1;
  496. }
  497.  
  498. static struct lsys_cmd far * _fastcall drawLSys(struct lsys_cmd far *command,struct lsys_cmd far **rules,int depth)
  499. {
  500.    struct lsys_cmd far **rulind;
  501.    int tran;
  502.  
  503. if (overflow)     /* integer math routines overflowed */
  504.     return NULL;
  505.  
  506. #ifndef __TURBOC__
  507.    if (stackavail() < 400) { /* leave some margin for calling subrtns */
  508.       stackoflow = 1;
  509.       return NULL;
  510.       }
  511. #endif
  512.  
  513.    while (command->ch && command->ch !=']') {
  514.       if (!(counter++)) {
  515.      if (check_key()) {
  516.         counter--;
  517.         return NULL;
  518.      }
  519.       }
  520.       tran=0;
  521.       if (depth) {
  522.      for(rulind=rules;*rulind;rulind++)
  523.         if ((*rulind)->ch == command->ch) {
  524.            tran=1;
  525.            if (drawLSys((*rulind)+1,rules,depth-1) == NULL)
  526.           return NULL;
  527.         }
  528.       }
  529.       if (!depth||!tran) {
  530.     if (command->f)
  531.       (*command->f)(command->n);
  532.     else if (command->ch == '[') {
  533.       char saveang,saverev,savecolor;
  534.       long savesize,savex,savey;
  535.       unsigned long saverang;
  536.  
  537.       saveang=angle;
  538.       saverev=reverse;
  539.       savesize=size;
  540.       saverang=realangle;
  541.       savex=xpos;
  542.       savey=ypos;
  543.       savecolor=curcolor;
  544.       if ((command=drawLSys(command+1,rules,depth)) == NULL)
  545.          return(NULL);
  546.       angle=saveang;
  547.       reverse=saverev;
  548.       size=savesize;
  549.       realangle=saverang;
  550.       xpos=savex;
  551.       ypos=savey;
  552.       curcolor=savecolor;
  553.     }
  554.       }
  555.       command++;
  556.    }
  557.    return command;
  558. }
  559.  
  560. #define MAXRULES 27 /* this limits rules to 25 */
  561. static char far *ruleptrs[MAXRULES];
  562. static struct lsys_cmd far *rules2[MAXRULES];
  563.  
  564. static int _fastcall readLSystemFile(char *str)
  565. {
  566.    int c;
  567.    char far **rulind;
  568.    int err=0;
  569.    int linenum,check=0;
  570.    char inline[161],fixed[161],*word;
  571.    FILE *infile;
  572.    char msgbuf[481]; /* enough for 6 full lines */
  573.  
  574.    if (find_file_item(LFileName,str,&infile) < 0)
  575.       return -1;
  576.    while ((c = fgetc(infile)) != '{')
  577.       if (c == EOF) return -1;
  578.  
  579.    maxangle=0;
  580.    for(linenum=0;linenum<MAXRULES;++linenum) ruleptrs[linenum]=NULL;
  581.    rulind=&ruleptrs[1];
  582.    msgbuf[0]=linenum=0;
  583.  
  584.    while(fgets(inline,160,infile))  /* Max line length 160 chars */
  585.    {
  586.       linenum++;
  587.       if ((word = strchr(inline,';'))) /* strip comment */
  588.      *word = 0;
  589.       strlwr(inline);
  590.  
  591.       if (strspn(inline," \t\n") < strlen(inline)) /* not a blank line */
  592.       {
  593.      word=strtok(inline," =\t\n");
  594.      if (!strcmp(word,"axiom"))
  595.      {
  596.         save_rule(strtok(NULL," \t\n"),&ruleptrs[0]);
  597.         check=1;
  598.      }
  599.      else if (!strcmp(word,"angle"))
  600.      {
  601.         maxangle=atoi(strtok(NULL," \t\n"));
  602.         dmaxangle = maxangle - 1;
  603.         check=1;
  604.      }
  605.      else if (!strcmp(word,"}"))
  606.         break;
  607.      else if (strlen(word)==1)
  608.      {
  609.         char *tok;
  610.         tok = strtok(NULL, " \t\n");
  611.         strcpy(fixed, word);
  612.         if (tok != NULL) {     /* Some strcat's die if they cat with NULL */
  613.         strcat(fixed, tok);
  614.         }
  615.         save_rule(fixed, rulind++);
  616.         check=1;
  617.      }
  618.      else
  619.         if (err<6)
  620.         {
  621.            sprintf(&msgbuf[strlen(msgbuf)],
  622.                "Syntax error line %d: %s\n",linenum,word);
  623.            ++err;
  624.         }
  625.      if (check)
  626.      {
  627.         check=0;
  628.         if(word=strtok(NULL," \t\n"))
  629.            if (err<6)
  630.            {
  631.           sprintf(&msgbuf[strlen(msgbuf)],
  632.              "Extra text after command line %d: %s\n",linenum,word);
  633.           ++err;
  634.            }
  635.      }
  636.       }
  637.    }
  638.    fclose(infile);
  639.    if (!ruleptrs[0] && err<6)
  640.    {
  641.       strcat(msgbuf,"Error:  no axiom\n");
  642.       ++err;
  643.    }
  644.    if ((maxangle<3||maxangle>50) && err<6)
  645.    {
  646.       strcat(msgbuf,"Error:  illegal or missing angle\n");
  647.       ++err;
  648.    }
  649.    if (err)
  650.    {
  651.       msgbuf[strlen(msgbuf)-1]=0; /* strip trailing \n */
  652.       stopmsg(0,msgbuf);
  653.       return -1;
  654.    }
  655.    *rulind=NULL;
  656.    return 0;
  657. }
  658.  
  659. static char loaded=0;
  660.  
  661. int Lsystem()
  662. {
  663.    int order;
  664.    char far **rulesc;
  665.    struct lsys_cmd far **sc;
  666.  
  667.    if ( (!loaded) && LLoad())
  668.      return -1;
  669.  
  670.    overflow = 0;        /* reset integer math overflow flag */
  671.  
  672.    order=param[0];
  673.    if (order<=0)
  674.      order=0;
  675.    stackoflow = 0;
  676.  
  677.    sc = rules2;
  678.    for (rulesc = ruleptrs; *rulesc; rulesc++)
  679.      *sc++ = SizeTransform(*rulesc);
  680.    *sc = NULL;
  681.  
  682.    if (findscale(rules2[0], &rules2[1], order)) {
  683.       realangle = angle = reverse = 0;
  684.  
  685.       free_lcmds();
  686.       sc = rules2;
  687.       for (rulesc = ruleptrs; *rulesc; rulesc++)
  688.     *sc++ = DrawTransform(*rulesc);
  689.       *sc = NULL;
  690.  
  691.       /* !! HOW ABOUT A BETTER WAY OF PICKING THE DEFAULT DRAWING COLOR */
  692.       if ((curcolor=15) > colors) curcolor=colors-1;
  693.       drawLSys(rules2[0], &rules2[1], order);
  694.    }
  695.    if (stackoflow)
  696.    {
  697.       static char far msg[]={"insufficient memory, try a lower order"};
  698.       stopmsg(0,msg);
  699.    }
  700.    if (overflow) {
  701.       static char far msg[]={"Integer math routines failed, try a lower order"};
  702.       stopmsg(0,msg);
  703.       }
  704.    free_rules_mem();
  705.    free_lcmds();
  706.    loaded=0;
  707.    return 0;
  708. }
  709.  
  710. int LLoad()
  711. {
  712.    char i;
  713.    if (readLSystemFile(LName)) { /* error occurred */
  714.       free_rules_mem();
  715.       loaded=0;
  716.       return -1;
  717.    }
  718.    for(i=0;i<maxangle;i++) {
  719.       sins[i]=(long) ((sin(2*i*PI/maxangle)) * FIXEDLT1);
  720.       coss[i]=(long) (((double) aspect / (double) FIXEDMUL * cos(2*i*PI/maxangle)) * FIXEDLT1);
  721.    }
  722.    loaded=1;
  723.    return 0;
  724. }
  725.  
  726. static void _fastcall free_rules_mem()
  727. {
  728.    int i;
  729.    for(i=0;i<MAXRULES;++i)
  730.       if(ruleptrs[i]) farmemfree(ruleptrs[i]);
  731. }
  732.  
  733. static int _fastcall save_rule(char *rule,char far **saveptr)
  734. {
  735.    int i;
  736.    char far *tmpfar;
  737.    i=strlen(rule)+1;
  738.    if((tmpfar=farmemalloc((long)i))==NULL) {
  739.        stackoflow = 1;
  740.        return -1;
  741.        }
  742.    *saveptr=tmpfar;
  743.    while(--i>=0) *(tmpfar++)=*(rule++);
  744.    return 0;
  745. }
  746.  
  747. static struct lsys_cmd far *SizeTransform(char far *s)
  748. {
  749.   struct lsys_cmd far *ret;
  750.   struct lsys_cmd far *doub;
  751.   int maxval = 10;
  752.   int n = 0;
  753.   void (*f)(long);
  754.   long num;
  755.  
  756.   void (*plus)(long) = (ispow2(maxangle)) ? lsys_doplus_pow2 : lsys_doplus;
  757.   void (*minus)(long) = (ispow2(maxangle)) ? lsys_dominus_pow2 : lsys_dominus;
  758.   void (*pipe)(long) = (ispow2(maxangle)) ? lsys_dopipe_pow2 : lsys_dopipe;
  759.  
  760.   void (*slash)(long) =  (cpu == 386) ? lsys_doslash_386 : lsys_doslash;
  761.   void (*bslash)(long) = (cpu == 386) ? lsys_dobslash_386 : lsys_dobslash;
  762.   void (*at)(long) =     (cpu == 386) ? lsys_doat_386 : lsys_doat;
  763.   void (*dogf)(long) =   (cpu == 386) ? lsys_dosizegf_386 : lsys_dosizegf;
  764.  
  765.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  766.   if (ret == NULL) {
  767.        stackoflow = 1;
  768.        return NULL;
  769.        }
  770.   while (*s) {
  771.     f = NULL;
  772.     num = 0;
  773.     ret[n].ch = *s;
  774.     switch (*s) {
  775.       case '+': f = plus;            break;
  776.       case '-': f = minus;           break;
  777.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  778.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  779.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  780.       case '|': f = pipe;            break;
  781.       case '!': f = lsys_dobang;     break;
  782.       case 'd':
  783.       case 'm': f = lsys_dosizedm;   break;
  784.       case 'g':
  785.       case 'f': f = dogf;       break;
  786.       case '[': num = 1;        break;
  787.       case ']': num = 2;        break;
  788.       default:
  789.     num = 3;
  790.     break;
  791.     }
  792.     ret[n].f = f;
  793.     ret[n].n = num;
  794.     if (++n == maxval) {
  795.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  796.       if (doub == NULL) {
  797.          farmemfree(ret);
  798.          stackoflow = 1;
  799.          return NULL;
  800.          }
  801.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  802.       farmemfree(ret);
  803.       ret = doub;
  804.       maxval <<= 1;
  805.     }
  806.     s++;
  807.   }
  808.   ret[n].ch = 0;
  809.   ret[n].f = NULL;
  810.   ret[n].n = 0;
  811.   n++;
  812.  
  813.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  814.   if (doub == NULL) {
  815.        farmemfree(ret);
  816.        stackoflow = 1;
  817.        return NULL;
  818.        }
  819.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  820.   farmemfree(ret);
  821.   return doub;
  822. }
  823.  
  824. static struct lsys_cmd far *DrawTransform(char far *s)
  825. {
  826.   struct lsys_cmd far *ret;
  827.   struct lsys_cmd far *doub;
  828.   int maxval = 10;
  829.   int n = 0;
  830.   void (*f)(long);
  831.   long num;
  832.  
  833.   void (*plus)(long) = (ispow2(maxangle)) ? lsys_doplus_pow2 : lsys_doplus;
  834.   void (*minus)(long) = (ispow2(maxangle)) ? lsys_dominus_pow2 : lsys_dominus;
  835.   void (*pipe)(long) = (ispow2(maxangle)) ? lsys_dopipe_pow2 : lsys_dopipe;
  836.  
  837.   void (*slash)(long) =  (cpu == 386) ? lsys_doslash_386 : lsys_doslash;
  838.   void (*bslash)(long) = (cpu == 386) ? lsys_dobslash_386 : lsys_dobslash;
  839.   void (*at)(long) =     (cpu == 386) ? lsys_doat_386 : lsys_doat;
  840.   void (*drawg)(long) =  (cpu == 386) ? lsys_dodrawg_386 : lsys_dodrawg;
  841.  
  842.   ret = (struct lsys_cmd far *) farmemalloc((long) maxval * sizeof(struct lsys_cmd));
  843.   if (ret == NULL) {
  844.        stackoflow = 1;
  845.        return NULL;
  846.        }
  847.   while (*s) {
  848.     f = NULL;
  849.     num = 0;
  850.     ret[n].ch = *s;
  851.     switch (*s) {
  852.       case '+': f = plus;            break;
  853.       case '-': f = minus;           break;
  854.       case '/': f = slash;           num = (long) (getnumber(&s) * 11930465L);    break;
  855.       case '\\': f = bslash;         num = (long) (getnumber(&s) * 11930465L);    break;
  856.       case '@': f = at;              num = FIXEDPT(getnumber(&s));    break;
  857.       case '|': f = pipe;            break;
  858.       case '!': f = lsys_dobang;     break;
  859.       case 'd': f = lsys_dodrawd;    break;
  860.       case 'm': f = lsys_dodrawm;    break;
  861.       case 'g': f = drawg;           break;
  862.       case 'f': f = lsys_dodrawf;    break;
  863.       case 'c': f = lsys_dodrawc;    num = getnumber(&s);    break;
  864.       case '<': f = lsys_dodrawlt;   num = getnumber(&s);    break;
  865.       case '>': f = lsys_dodrawgt;   num = getnumber(&s);    break;
  866.       case '[': num = 1;        break;
  867.       case ']': num = 2;        break;
  868.       default:
  869.     num = 3;
  870.     break;
  871.     }
  872.     ret[n].f = f;
  873.     ret[n].n = num;
  874.     if (++n == maxval) {
  875.       doub = (struct lsys_cmd far *) farmemalloc((long) maxval*2*sizeof(struct lsys_cmd));
  876.       if (doub == NULL) {
  877.            farmemfree(ret);
  878.            stackoflow = 1;
  879.            return NULL;
  880.            }
  881.       far_memcpy(doub, ret, maxval*sizeof(struct lsys_cmd));
  882.       farmemfree(ret);
  883.       ret = doub;
  884.       maxval <<= 1;
  885.     }
  886.     s++;
  887.   }
  888.   ret[n].ch = 0;
  889.   ret[n].f = NULL;
  890.   ret[n].n = 0;
  891.   n++;
  892.  
  893.   doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
  894.   if (doub == NULL) {
  895.        farmemfree(ret);
  896.        stackoflow = 1;
  897.        return NULL;
  898.        }
  899.   far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
  900.   farmemfree(ret);
  901.   return doub;
  902. }
  903.  
  904. static void free_lcmds()
  905. {
  906.   struct lsys_cmd far **sc = rules2;
  907.  
  908.   while (*sc)
  909.     farmemfree(*sc++);
  910. }
  911.  
  912.