home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / ace / c / libfunc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  16.2 KB  |  713 lines

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: library and machine code function handling **
  6.    ** Copyright (C) 1998 David Benn
  7.    ** 
  8.    ** This program is free software; you can redistribute it and/or
  9.    ** modify it under the terms of the GNU General Public License
  10.    ** as published by the Free Software Foundation; either version 2
  11.    ** of the License, or (at your option) any later version.
  12.    **
  13.    ** This program is distributed in the hope that it will be useful,
  14.    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    ** GNU General Public License for more details.
  17.    **
  18.    ** You should have received a copy of the GNU General Public License
  19.    ** along with this program; if not, write to the Free Software
  20.    ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22.    Author: David J Benn
  23.      Date: 26th October-30th November, 1st-13th December 1991,
  24.        14th,20th-27th January 1992, 
  25.            2nd-17th, 21st-29th February 1992, 
  26.        1st,13th,14th,22nd,23rd March 1992,
  27.        21st,22nd April 1992,
  28.        2nd,3rd,11th,15th,16th May 1992,
  29.        7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
  30.        2nd-8th,14th-19th,26th-29th July 1992,
  31.        1st-3rd,7th,8th,9th August 1992,
  32.        6th,7th,22nd December 1992,
  33.        28th February 1993,
  34.        12th April 1993,
  35.        16th,17th December 1993,
  36.        2nd,3rd,13th January 1994,
  37.        12th June 1994,
  38.        5th,20th,28th August 1994,
  39.        1st,10th September 1994,
  40.        8th,9th March 1995
  41. */
  42.  
  43. #include "acedef.h"
  44.  
  45. /* locals */
  46. static     char     *reg[] = { "  ","d0","d1","d2","d3","d4","d5","d6","d7",
  47.                "a0","a1","a2","a3","a4","a5" };
  48.  
  49. /* externals */
  50. extern    int    sym;
  51. extern    int    lastsym;
  52. extern    int    typ;
  53. extern    int    lev;
  54. extern    char       id[MAXIDSIZE]; 
  55. extern    char       ut_id[MAXIDSIZE];
  56. extern    char     tempshortname[80];
  57. extern    char     templongname[80];
  58. extern    char    stringval[MAXSTRLEN];
  59. extern    SYM    *curr_item;
  60. extern    ACELIBS acelib[NUMACELIBS];
  61. extern    ACELIBS otherlib[NUMLIBS];
  62. extern    char     librarybase[MAXIDSIZE+6];
  63. extern    char     libraryname[MAXIDSIZE+20];
  64. extern    char    bmapname[MAXIDSIZE+20];
  65. extern    BOOL     restore_a4;
  66. extern    BOOL     restore_a5;
  67. extern    BOOL    early_exit;
  68.  
  69. /* ------------------------- */
  70. /* Library Function routines */
  71. /* ------------------------- */
  72.  
  73. BYTE check_for_ace_lib(libname)
  74. char *libname;
  75. {
  76. int c=0;
  77. /* 
  78. ** If libname is a library used by ACE 
  79. ** open & close it in the normal way.
  80. */ 
  81.  
  82.  while(acelib[c].name[0] != '\0' && 
  83.        strcmp(acelib[c].name,"SENTINEL") !=0) 
  84.  {
  85.   if (strcmp(acelib[c].name,libname)==0) 
  86.      { enter_XREF(acelib[c].base); return(c); }
  87.   c++;
  88.  } 
  89.  return(NEGATIVE);
  90. }
  91.  
  92. void enter_new_library(libname)
  93. char *libname;
  94. {
  95. int  cc=0;
  96. /*
  97. ** Enter a library into the list 
  98. ** for future reference by function
  99. ** declarations which don't specify
  100. ** the library to be used.
  101. */
  102.  
  103.   /* 
  104.   ** Find libname, first free or maximum entry.
  105.   ** If it's already in the list, libname will
  106.   ** be ignored.  
  107.   */
  108.   while (otherlib[cc].name[0] != '\0' && 
  109.           strcmp(otherlib[cc].name,libname) != 0 &&
  110.      strcmp(otherlib[cc].name,"SENTINEL") != 0) cc++;
  111.  
  112.   /* maximum? */
  113.   if (strcmp(otherlib[cc].name,"SENTINEL") == 0) 
  114.      _error(76);  /* can't add another library */   
  115.   else
  116.   if (otherlib[cc].name[0] == '\0')
  117.   {
  118.     /* add a new entry */
  119.     strcpy(otherlib[cc].name,libname);
  120.     make_library_base(libname);
  121.     strcpy(otherlib[cc].base,librarybase);
  122.   }
  123. }
  124.  
  125. void make_library_base(libname)
  126. char *libname;    
  127. {
  128.  strcpy(librarybase,"_\0");
  129.  strcat(librarybase,libname);
  130.  strcat(librarybase,"Base");
  131.  enter_BSS(librarybase,"ds.l 1");
  132. }
  133.  
  134. void make_library_name(libname)
  135. char *libname;
  136. {
  137.  strcpy(libraryname,libname);
  138.  strcat(libraryname,".library");
  139. }
  140.  
  141. void make_bmap_name(libname)
  142. char *libname;
  143. {
  144.  strcpy(bmapname,"ACEbmaps:");
  145.  strcat(bmapname,libname);
  146.  strcat(bmapname,".bmap");
  147. }
  148.  
  149. void get_libname(libname,ut_libname)
  150. char *libname,*ut_libname;
  151. {
  152. char *tmp,*ut_tmp;
  153.  
  154.    /* get raw library name (uppercase and untouched) */
  155.    if (sym == ident) 
  156.    {
  157.       strcpy(ut_libname,ut_id);
  158.       strcpy(libname,id);
  159.    }
  160.    else
  161.    {
  162.       strcpy(ut_libname,stringval);
  163.       strcpy(libname,strupr(stringval));
  164.    }
  165.  
  166.    /* chop off extension if ".bmap" or ".library" */ 
  167.    tmp=libname;
  168.    ut_tmp=ut_libname;
  169.    while (*tmp && *tmp != '.') { tmp++; ut_tmp++; }
  170.    if (*tmp == '.' && 
  171.        (strcmp(tmp,".BMAP") == 0 || strcmp(tmp,".LIBRARY") == 0))
  172.    {
  173.     *tmp = '\0';
  174.     *ut_tmp = '\0';
  175.    }
  176. }
  177.  
  178. void library()
  179. {
  180. char libname[MAXIDSIZE],ut_libname[MAXIDSIZE];
  181. char lab[80],lablabel[80];
  182.  
  183.  /* open or close a shared library */
  184.  
  185.  insymbol();
  186.  if (sym == closesym) closelibrary();
  187.  else
  188.  {
  189.   if (sym != ident && sym != stringconst) 
  190.      _error(7);  /* identifier expected */
  191.   else
  192.   {
  193.    get_libname(libname,ut_libname);  /* without extension! */
  194.  
  195.    if (check_for_ace_lib(libname) == NEGATIVE)
  196.    {
  197.      make_library_name(ut_libname); /* exec names are case sensitive */
  198.      make_string_const(libraryname);
  199.      gen("move.l","(sp)+","a1");   /* address of library name in a1 */
  200.      gen("jsr","_open_library","  ");
  201.      make_library_base(libname);
  202.      gen("move.l","d0",librarybase);
  203.      gen("cmpi.l","#0","d0");
  204.      make_label(lab,lablabel);
  205.      gen("bne.s",lab,"  ");
  206.      gen("jmp","_EXIT_PROG","  "); /* quit program if can't open library */
  207.      gen(lablabel,"  ","  ");
  208.      enter_XREF("_open_library");
  209.  
  210.      /* enter new library info' into "other libraries" list */
  211.      enter_new_library(libname);
  212.    }
  213.   }
  214.   insymbol();
  215.  }
  216. }       
  217.  
  218. void closelibrary()
  219. {
  220. char libname[MAXIDSIZE],ut_libname[MAXIDSIZE];
  221. int  cc;
  222.  /* close one or more shared libraries */ 
  223.  
  224.  insymbol();
  225.  if (sym != ident && sym != stringconst) 
  226.  {
  227.    /* 
  228.    ** Close all open shared libraries not 
  229.    ** normally closed by ACE at the end of
  230.    ** the program run.
  231.    */
  232.    cc=0;
  233.    while (otherlib[cc].name[0] != '\0' &&
  234.       strcmp(otherlib[cc].name,"SENTINEL") != 0)
  235.    {
  236.         gen("move.l",otherlib[cc].base,"a1");  /* library base in a1 */
  237.         gen("jsr","_close_library","  ");
  238.     gen("move.l","#0",otherlib[cc].base);
  239.         enter_XREF("_close_library");
  240.     cc++;
  241.    }      
  242.  }   
  243.  else
  244.  {
  245.   /* close a single shared library */
  246.   get_libname(libname,ut_libname);  /* without extension! */
  247.  
  248.   if (check_for_ace_lib(libname) == NEGATIVE)
  249.   {
  250.     make_library_base(libname);
  251.     gen("move.l",librarybase,"a1");  /* library base in a1 */
  252.     gen("jsr","_close_library","  ");
  253.     gen("move.l","#0",librarybase);
  254.     enter_XREF("_close_library");
  255.   }
  256.   insymbol();
  257.  }
  258. }
  259.   
  260. void remove_qualifier(funcname)
  261. char *funcname;
  262. {
  263. /* remove any trailing data type qualifier (%&#!$) @=& [=! */
  264. int cc=0;
  265.  
  266.  /* find end of string */
  267.  while (funcname[cc] != '\0') cc++;
  268.  /* is the last character a qualifier? */
  269.  if ((funcname[cc-1] == '%')||(funcname[cc-1] == '@')||(funcname[cc-1] == '#')
  270.     ||(funcname[cc-1] == '[')||(funcname[cc-1] == '$')) funcname[cc-1]='\0';
  271. }
  272.  
  273. BOOL search_func(bmap,func,declared_func)
  274. char *bmap;
  275. char *func;
  276. SYM  *declared_func;
  277. {
  278. /* 
  279. ** Search for function in .bmap file, recording register usage
  280. ** and library base offset in symbol table entry for function. 
  281. */
  282.  
  283. unsigned char        *buf;
  284. struct FileHandle    *f;
  285. unsigned char        ch,name[MAXIDSIZE];
  286. LONG             bmap_size,count,cc,rc;
  287. SHORT            offset=0;
  288. BOOL             found=FALSE;
  289.  
  290. unsigned char *tmp;
  291.  
  292.  if ((bmap_size=fsize(bmap)) == -1L)  /* if not -1 -> file exists and
  293.                      we get size of file in bytes. */
  294.     { _error(50); return(FALSE); }
  295.  else
  296.  {
  297.   /* read whole bmap file into a buffer */
  298.   buf = (unsigned char *)alloc(bmap_size,MEMF_ANY);
  299.   f = (struct FileHandle *)Open(bmap,MODE_OLDFILE);
  300.   Read(f,buf,bmap_size);
  301.   Close(f);
  302.  
  303.   count=0;  /* start of buffer */
  304.  
  305.   while (!found && count < bmap_size)
  306.   {
  307.    /* build function name */
  308.    cc=0;
  309.    while (count < bmap_size && cc < MAXIDSIZE)
  310.    {
  311.     ch=name[cc++]=buf[count++];
  312.     if (ch == '\0') break;  /* exit loop when EOS reached */
  313.    }
  314.  
  315.    name[cc-1]='\0';  /* make sure we have an EOS symbol (may exit early) */
  316.  
  317.    if (strcmp(name,func) != 0) 
  318.    {
  319.     /* skip 2-byte offset */
  320.     count += 2;
  321.     /* skip to next name */
  322.     while (count < bmap_size && (ch=buf[count++]) != '\0');
  323.    }
  324.    else found=TRUE;  /* that's it! -> get the info' */
  325.   }
  326.  
  327.   if (!found) return(FALSE);
  328.  
  329.   /* get library base offset (2 bytes) */
  330.   if (count < bmap_size)
  331.   {
  332.    ch=buf[count++];
  333.    offset += ch*256;
  334.   }
  335.   else 
  336.       return(FALSE);
  337.  
  338.   if (count < bmap_size)
  339.   {
  340.    ch=buf[count++];
  341.    offset += ch;
  342.   }
  343.   else 
  344.       return(FALSE);
  345.  
  346.   declared_func->address = (SHORT)offset;  /* record library base offset */
  347.  
  348.   /* get n bytes of register data */
  349.   declared_func->reg = (UBYTE *)sym_alloc(15,MEMF_ANY);
  350.   if (declared_func->reg == NULL)
  351.   {
  352.     puts("Can't allocate memory for function register info!");
  353.     early_exit=TRUE;
  354.     kill_all_lists();
  355.            cleanup();
  356.   }
  357.   
  358.   rc=0;
  359.   while (count < bmap_size && 
  360.         (ch=buf[count++]) != '\0') declared_func->reg[rc++]=ch;
  361.  
  362.   declared_func->no_of_params=rc;  /* record no. of parameters */
  363.  
  364.   if (ch != '\0') return(FALSE);  /* last character should be NULL */   
  365.  
  366.   /* we found it -> return */
  367.   return(TRUE);
  368.  }
  369. }
  370.  
  371. BOOL found_func(libname,ut_funcname,declared_func)
  372. char *libname;
  373. char *ut_funcname;
  374. SYM  *declared_func;
  375. {
  376.      /* 
  377.      ** Search for function in bmap file and record register usage
  378.      ** and library base offset in symbol table entry for function.
  379.      */
  380.  
  381.      make_bmap_name(libname);
  382.  
  383.      if (search_func(bmapname,ut_funcname,declared_func))
  384.      {
  385.       /* store library name */
  386.       declared_func->libname = (char *)sym_alloc(MAXIDSIZE+8,MEMF_ANY);
  387.       if (declared_func->libname == NULL)
  388.       {
  389.     puts("Can't allocate memory for library name in symbol table!");
  390.     early_exit=TRUE;
  391.     kill_all_lists();
  392.            cleanup();
  393.       }
  394.       else
  395.       {
  396.     /* found the function */  
  397.         strcpy(declared_func->libname,libname);
  398.     return(TRUE);
  399.       }
  400.      }  
  401.      else
  402.      /* didn't find the function */
  403.          return(FALSE); 
  404. }
  405.  
  406. void declare()
  407. {
  408. /* - declare a library function -- NOT optional. 
  409.    - declare an external function -- NOT optional.
  410.    - declare a forward reference to a SUB. 
  411.    - declare an instance of a structure. 
  412. */
  413.  
  414. char funcname[MAXIDSIZE],ut_funcname[MAXIDSIZE];
  415. char libname[MAXIDSIZE],ut_libname[MAXIDSIZE];
  416. char extfuncname[MAXIDSIZE+1];
  417. BYTE libnum;
  418. int  oldlevel,cc;
  419. int  functype=undefined;
  420. SYM  *declared_func;
  421. BOOL found;
  422.  
  423.  /* all functions and structures must be declared at level ZERO */
  424.  
  425.  oldlevel=lev;
  426.  lev=ZERO;
  427.  
  428.  insymbol();
  429.  
  430.  if (sym == subsym) { lev=oldlevel; forward_ref(); return; }
  431.  
  432.  if (sym == structsym) { lev=oldlevel; declare_structure(); return; }
  433.  
  434.  if (sym != functionsym) _error(47);
  435.  else
  436.  {
  437.   insymbol();
  438.  
  439.   /* type identifiers */
  440.   if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  441.       sym == singlesym || sym == stringsym)
  442.   {
  443.    switch(sym)
  444.    {
  445.     case shortintsym : functype = shorttype;  break;
  446.     case longintsym  : functype = longtype;   break;
  447.     case addresssym  : functype = longtype;   break;
  448.     case singlesym   : functype = singletype; break;
  449.     case stringsym   : functype = stringtype; break;
  450.    }
  451.    insymbol();
  452.   }
  453.  
  454.   if (sym != ident) _error(7);
  455.   else
  456.   {
  457.    /* get the function's name */
  458.    strcpy(funcname,id);
  459.    strcpy(ut_funcname,ut_id);  /* case sensitive version for search! */
  460.    remove_qualifier(funcname);
  461.    remove_qualifier(ut_funcname);
  462.    if (functype == undefined) functype = typ;
  463.  
  464.    /* get the LIBRARY symbol and/or parameter list */ 
  465.    insymbol();
  466.  
  467.    /* parse parameter list? */
  468.    if (sym == lparen)
  469.    {    
  470.     do
  471.     {   
  472.         insymbol();
  473.  
  474.     if (sym == rparen && lastsym == lparen) break;  /* FuncName() */
  475.  
  476.     /* type indentifier? */
  477.         if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  478.               sym == singlesym || sym == stringsym) 
  479.     insymbol();
  480.  
  481.     /* parameter */
  482.     if (sym != ident) _error(7);
  483.     else
  484.         insymbol();
  485.     }
  486.     while (sym == comma);
  487.  
  488.     if (sym != rparen) _error(9);
  489.     else
  490.         insymbol();
  491.    }
  492.  
  493.    /* EXTERNAL or LIBRARY function? */
  494.    if (sym == externalsym) 
  495.    {
  496.     if (ut_funcname[0] != '_')
  497.     {
  498.            strcpy(extfuncname,"_\0");
  499.         strcat(extfuncname,ut_funcname);
  500.     }
  501.     else
  502.         strcpy(extfuncname,ut_funcname);
  503.  
  504.     enter(extfuncname,functype,extfunc,0);
  505.     enter_XREF(extfuncname);    
  506.  
  507.     insymbol();
  508.    }
  509.    else
  510.    if (sym != librarysym) _error(48);
  511.    else
  512.    {
  513.     enter(funcname,functype,function,0); /* enter into symbol table */ 
  514.     declared_func=curr_item;
  515.  
  516.     insymbol();
  517.  
  518.     if (sym != ident && sym != stringconst)
  519.     {
  520.     /* 
  521.     ** Search all bmap files found in acelib and otherlib arrays 
  522.     ** for function since no library was specified.
  523.       */
  524.  
  525.     found=FALSE;
  526.  
  527.     /* acelib array */
  528.     cc=0;
  529.     while (!found && acelib[cc].name[0] != '\0' &&
  530.            strcmp(acelib[cc].name,"SENTINEL") != 0)
  531.     {
  532.       found = found_func(acelib[cc].name,ut_funcname,declared_func);
  533.       cc++;
  534.     }
  535.  
  536.     if (found) { lev=oldlevel; return; }
  537.  
  538.     /* otherlib array */
  539.     cc=0;
  540.     while (!found && otherlib[cc].name[0] != '\0' &&
  541.            strcmp(otherlib[cc].name,"SENTINEL") != 0)
  542.     {
  543.       found = found_func(otherlib[cc].name,ut_funcname,declared_func);
  544.       cc++;
  545.     }    
  546.  
  547.     if (!found) _error(49);
  548.     }
  549.     else
  550.     {
  551.          /* 
  552.     ** Search specified library (bmap file) for the declared function.
  553.     */
  554.          get_libname(libname,ut_libname);  /* without extension! */
  555.  
  556.     if (!found_func(libname,ut_funcname,declared_func)) 
  557.       _error(49); 
  558.  
  559.         insymbol();
  560.     }
  561.    }  
  562.   }    
  563.  }
  564.  lev=oldlevel;
  565. }
  566.  
  567. void load_func_params(func_item)
  568. SYM *func_item;
  569. {
  570. /* 
  571. ** Parse a shared library function's actual parameter-list 
  572. ** and call the function.
  573. */
  574. SHORT i,n;
  575. char  ptemp[14][80];
  576.  
  577.  if (sym != lparen) { _error(14); return; }
  578.  else
  579.  {
  580.   /* get parameters */
  581.   i=0;
  582.   do
  583.   {
  584.    insymbol();
  585.  
  586.    /*
  587.    ** Make ALL parameters longints! 
  588.    */
  589.    if (expr() == shorttype) make_long();
  590.  
  591.    /* 
  592.    ** Store parameter information temporarily 
  593.    ** since expression evaluation may corrupt 
  594.    ** data in registers later if loaded now.
  595.    */
  596.    make_temp_long();
  597.    strcpy(ptemp[i],templongname);  /* later -> move.l srctemp,addrbuf */
  598.  
  599.    /* store it */
  600.    gen("move.l","(sp)+",templongname);
  601.    
  602.    i++;
  603.   }
  604.   while ((i < func_item->no_of_params) && (sym == comma));
  605.  
  606.   if ((i < func_item->no_of_params) || (sym == comma)) 
  607.      _error(39); /* parameter count mismatch - too few or too many. */
  608.   else
  609.   {
  610.    /* load parameters into regs */
  611.    for (n=0;n<func_item->no_of_params;n++)
  612.    {
  613.     /* does reg (a4 or a5 ONLY) need to be preserved? */
  614.     if (func_item->reg[n] == 13)   /* a4 */ 
  615.     { 
  616.      restore_a4=TRUE; 
  617.      gen("move.l","a4","_a4_temp");
  618.      enter_BSS("_a4_temp:","ds.l 1");
  619.     }
  620.     else
  621.     if (func_item->reg[n] == 14)   /* a5 */
  622.     { 
  623.      restore_a5=TRUE; 
  624.      gen("move.l","a5","_a5_temp");
  625.      enter_BSS("_a5_temp:","ds.l 1");
  626.     }
  627.  
  628.     /*
  629.     ** Store value in register.
  630.     */ 
  631.     gen("move.l",ptemp[n],reg[func_item->reg[n]]);
  632.    }
  633.   }
  634.  
  635.   if (sym != rparen) _error(9);
  636.  }
  637. }
  638.  
  639. /* ----------------- */
  640. /* Machine Code CALL */
  641. /* ----------------- */
  642.  
  643. void load_mc_params(sub_ptr)
  644. SYM *sub_ptr;
  645. {
  646. SHORT i,n;
  647. int   ptype;
  648. char  p_temp[MAXPARAMS][80];
  649. int   p_type[MAXPARAMS];
  650.  
  651.   /* 
  652.   ** Store parameters in stack space of MC subroutine 
  653.   ** which is about to be CALLed ala C parameter passing 
  654.   ** convention.
  655.   */
  656.  
  657.   i=0;
  658.   do
  659.   {
  660.    insymbol();
  661.    ptype=expr();
  662.  
  663.    /* store parameters temporarily */  
  664.    if (ptype == shorttype)
  665.    {
  666.     /* save parameter type */
  667.     p_type[i]=shorttype; /* not DATA type but STORE type (2 or 4 bytes) */
  668.  
  669.     /* create a temporary store */
  670.     make_temp_short();
  671.     strcpy(p_temp[i],tempshortname);  /* later -> move.w srctemp,-(sp) */
  672.  
  673.     /* store it */
  674.     gen("move.w","(sp)+",tempshortname);
  675.    }
  676.    else
  677.    /* long,single,string or array */   
  678.    {
  679.     /* save parameter type */
  680.     p_type[i]=longtype;  /* storage requirement is 4 bytes */
  681.  
  682.     /* create a temporary store */
  683.     make_temp_long();
  684.     strcpy(p_temp[i],templongname);
  685.  
  686.     /* store it */
  687.     gen("move.l","(sp)+",templongname);
  688.    }
  689.    
  690.    i++;
  691.   }
  692.   while ((i < MAXPARAMS) && (sym == comma));
  693.  
  694.   /* push parameters onto stack ala C (see AmigaBASIC manual 6-11) */
  695.   for (n=i-1;n>=0;n--)
  696.   {
  697.    if (p_type[n] == shorttype) 
  698.    { 
  699.     gen("move.w",p_temp[n],"-(sp)"); /* short */
  700.     sub_ptr->p_type[n] = shorttype;
  701.    }
  702.    else
  703.    {
  704.     gen("move.l",p_temp[n],"-(sp)"); /* long,string,single,array */
  705.     sub_ptr->p_type[n] = longtype;
  706.    }
  707.   }
  708.  
  709.   sub_ptr->no_of_params = i; /* record number of parameters pushed! */
  710.  
  711.   if (sym != rparen) _error(9);
  712. }
  713.