home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / me34src.zip / me3 / mc / defun.c < prev    next >
C/C++ Source or Header  |  1995-01-14  |  14KB  |  583 lines

  1. /*
  2. Groups:  keywords, targets
  3. Keywords:  Mutt keywords, External Tokens, global vars, local vars,
  4.     prototypes, constants, programs
  5. targets:  named labels, structures
  6.  
  7. Precedence:  High to low, same line means ==
  8.   Keyword group:
  9.     Mutt Keywords
  10.     External Tokens
  11.     Local Vars, Prototypes
  12.     Global Vars, Constants, programs
  13.  
  14. Name Spaces:
  15.   Share:        Overwritable
  16.     Mutt Keywords    No
  17.     External Tokens     Yes: if asked to, complain if overwriten
  18.     Global Vars        No
  19.     Constants            No  
  20.     Programs        No
  21.     ?Structures
  22.   Share:  Can't collide with Mutt Keywords
  23.     Local Vars        No
  24.     Prototypes        No
  25.   Share:
  26.     Named labels    No
  27.     
  28. Scope:
  29.   Global:
  30.     Mutt Keywords
  31.     External Tokens
  32.     Global Vars
  33.     Constants
  34.     Programs
  35.     ?Structures
  36.   Local to a defun:
  37.     Local Vars
  38.     Prototypes
  39.     Named labels
  40.     
  41. Prototype:
  42.   Local scope:  name and type...
  43.   Global scope: program name, type list
  44. */
  45.  
  46.  
  47. #include <stdio.h>
  48. #include <os.h>
  49. #include <dtable.h>
  50. #include "mc.h"
  51. #include "opcode.h"
  52. #include "mm.h"
  53.  
  54. extern address pcaddr();
  55. extern char *sheap_add(), *spoof(), *keyword_type_name(), *typename();
  56. extern char ebuf[], token[];
  57. extern unsigned int class;    /* in mc.c */
  58. extern int moders;
  59. extern MuttCmd muttcmds[], modifiers[];
  60. extern KeyWord *global_look_up(), *global_look_for(), *global_check();
  61.  
  62. address get_pgm();
  63.  
  64. /* ******************************************************************** */
  65. /* **************************** Variables ***************************** */
  66. /* ******************************************************************** */
  67.  
  68. static int
  69.   num_vars = 0, local_start = 0, any_local_vars = FALSE,
  70.   local_objects = 0,
  71.   global_objects = 0,
  72.   global_vars = 0,    /* number of global variables */
  73.   size_of_global_vars = 0,
  74.   size_of_local_vars = 0;
  75.  
  76. static declare_and_init_dTable(var_table, Var);
  77.  
  78. #define VID_TO_VAR(n) (&var_table.table[n])
  79.  
  80. Var *vid_to_Var(n) { return VID_TO_VAR(n); }
  81.  
  82.     /* ************ Var Names ************************ */
  83.  
  84. static char *global_vname_heap = NULL, *local_vname_heap = NULL;
  85.  
  86. char *add_var_name(name, forever) char *name;
  87. {
  88.   char *ptr;
  89.  
  90.   ptr = sheap_add(
  91.         (forever ? &global_vname_heap : &local_vname_heap),
  92.         name);
  93.   if (!ptr) bail("Out of memory! Can't expand var name heap.");
  94.  
  95.   return ptr;
  96. }
  97.  
  98. char *save_string(string) char *string; { return add_var_name(string, TRUE); }
  99.  
  100. void var_init()
  101. {
  102. }
  103.  
  104.     /* Create a Var and pass back its id.
  105.      * Input:
  106.      *   name  : Pointer to name of var
  107.      *   type  :
  108.      *   var_size : Size of the var.  0 if part of a protoype.  Context
  109.      *           dependent.
  110.      *   is_proto : TRUE if this is a function protype
  111.      * Returns:
  112.      *   Var id.
  113.      * Notes:
  114.      *   This always works.
  115.      */
  116. create_var(name,type,var_size,scope) char *name; unsigned int type;
  117. {
  118.   int n, is_object, is_proto, vid;
  119.   Var *the_var;
  120.  
  121.   is_proto = (scope == PROTOTYPE);
  122.  
  123.   if (scope == GLOBAL)
  124.   {
  125.     KeyWord *kw;
  126.  
  127.     if (kw = global_check(name))
  128.     {
  129.       if (kw->type == KWGlobalVar) return kw->token;
  130.       /* else go ahead and add it */
  131.     }
  132.   }
  133.   else        /* Local => local var or prototype */
  134.     if (find_local_var(name) != -1)
  135.       moan(spoof(ebuf,"\"%s\" already in use (as a local variable or arg).",
  136.            name));
  137.  
  138.   is_object = is_object_type(type);
  139.  
  140.   if (!xpand_dTable(&var_table, 1, 200,100))
  141.     bail("Out of memory! Can't expand Var table.");
  142.  
  143.   vid = num_vars++;
  144.   the_var = VID_TO_VAR(vid);
  145.   the_var->name     = add_var_name(name, is_proto || scope == GLOBAL);
  146.   the_var->type     = type;
  147.   the_var->sub_type = 0;
  148.   the_var->offset   = 0;
  149.   the_var->scope    = scope;
  150.   the_var->blobs    = 0;
  151.   the_var->dims     = 0;
  152.  
  153.   if (scope == LOCAL)
  154.   {
  155.     if (is_object) the_var->offset = local_objects++;
  156.     else
  157.     {
  158.       the_var->offset = size_of_local_vars;
  159.       size_of_local_vars += var_size;
  160.     }
  161.   }
  162.   else
  163.     if (scope == GLOBAL)
  164.     {
  165.       global_vars++;
  166.       if (is_object) the_var->offset = global_objects++;
  167.       else
  168.       {
  169.     the_var->offset = size_of_global_vars;
  170.     size_of_global_vars += var_size;
  171.       }
  172.       add_keyword(the_var->name, KWGlobalVar, vid, 3);
  173.   }
  174.  
  175.   return vid;    /* pass back the var */
  176. }
  177.  
  178. add_array(name,type,size,scope,dims,dim)
  179.   char *name; unsigned int type; int dim[];
  180. {
  181.   int j,n;
  182.   Var *var;
  183.  
  184.   n = create_var(name,ARRAY,size,scope);
  185.   var = VID_TO_VAR(n);
  186.   var->sub_type = type;
  187.   var->dims = dims;
  188.   for (j = 0; j < dims; j++) var->dim[j] = dim[j];
  189.  
  190.   return n;
  191. }
  192.  
  193. #define VNAME(n) (VID_TO_VAR(n)->name)
  194. char *vname(n) { return VNAME(n); }
  195. vscope(n)      { return (int)VID_TO_VAR(n)->scope; }
  196. voffset(n)     { return VID_TO_VAR(n)->offset; }
  197.  
  198. find_local_var(name) char *name;
  199. {
  200.   int i;
  201.  
  202.   if (any_local_vars)
  203.     for (i = local_start; i < num_vars; i++)
  204.       if (0 == strcmp(name, VNAME(i))) return i;
  205.  
  206.   return -1;
  207. }
  208.  
  209. getvar(name) char *name;
  210. {
  211.   int n;
  212.   KeyWord *kw;
  213.  
  214.   if (-1 != (n = find_local_var(name))) return n;
  215.   if (kw = global_look_for(name, KWGlobalVar)) return kw->token;
  216.   return -1;
  217. }
  218.  
  219. unsigned int vtype(n) { return (unsigned int)VID_TO_VAR(n)->type; }
  220. unsigned int vctype(n) unsigned int n; { return mmtype(vtype(n)); }
  221.  
  222. num_global_vars() { return global_vars; }    /* number of global vars */
  223.     /* space needed to hold global vars */
  224. gvspace() { return size_of_global_vars; }
  225.  
  226. num_global_objects() { return global_objects; }
  227.  
  228.     /* Return the id of the next globabl object variable with id >= n, -1 if
  229.      *   none.
  230.      */
  231. get_global_object(n)
  232. {
  233.   for (; n < num_vars; n++)
  234.     if (vscope(n) == GLOBAL && is_object_type(vtype(n))) return n;
  235.  
  236.   return -1;
  237. }
  238.  
  239.     /* Return the id of the next globabl variable with id >= n, -1 if none.
  240.      */
  241. get_global_var(n)
  242. {
  243.   for (; n < num_vars; n++)
  244.     if (vscope(n) == GLOBAL) return n;
  245.  
  246.   return -1;
  247. }
  248.  
  249. static int compare2vars(a,b) Var *a, *b;
  250. { return strcmp(a->name,b->name); }
  251.  
  252. void sort_global_vars()
  253. {
  254.   ssort(var_table.table, num_vars, sizeof(Var), compare2vars);
  255. }
  256.  
  257. void print_global_vars(lstfile) FILE *lstfile;
  258. {
  259.   int j;
  260.  
  261.   sort_global_vars();
  262.   if (num_global_vars() == 0) fputs("\nNo global variables.\n",lstfile);
  263.   else
  264.   {
  265.     fputs("\n   Global Variables\nName                        Offset Type\n",
  266.       lstfile);
  267.     for (j = 0; -1 != (j = get_global_var(j)); j++)    /* global vars */
  268.     {
  269.       if (vtype(j) == ARRAY)
  270.     fprintf(lstfile,"%-27s %5d  array of %s\n",
  271.       vname(j),voffset(j),typename(VID_TO_VAR(j)->sub_type));
  272.       else
  273.     fprintf(lstfile,"%-27s %5d  %s\n",
  274.       vname(j),voffset(j),typename(vtype(j)));
  275.     }
  276.   }
  277. }
  278.  
  279. /* ******************************************************************** */
  280. /* **************************** Prototypes **************************** */
  281. /* ******************************************************************** */
  282.  
  283. addproto(name) char *name;    /* !!! */
  284. {
  285.   return 0;
  286. }
  287.  
  288. void add_to_proto(name,nth_arg,type,dims,dim)    /* !!!moreproto */
  289.   char *name; unsigned int type; int dim[];
  290. {
  291.   int j;
  292.   Var *var;
  293.  
  294.   j = create_var(name,type,0,PROTOTYPE);
  295.   var = VID_TO_VAR(j);
  296.  
  297.   var->offset = nth_arg;
  298.  
  299.   if (dims)
  300.   {
  301.     var->sub_type = type;
  302.     var->type = ARRAY;
  303.   }
  304.  
  305.   var->dims = dims;
  306.   for (j = 0; j < dims; j++) var->dim[j] = dim[j];
  307. }
  308.  
  309. /* ******************************************************************** */
  310. /* *************************** Named Labels *************************** */
  311. /* ******************************************************************** */
  312.  
  313.     /* Notes:
  314.      *   Named labels (label foo) are only legal inside a defun and share
  315.      *     scope with the defun.
  316.      */
  317.  
  318. typedef struct { char *name; int label; } NamedLabel;
  319.  
  320. static declare_and_init_dTable(named_label_table,NamedLabel);
  321. static int named_labels = 0, named_label_base = 0;
  322.  
  323. gen_named_label(name) char *name;
  324. {
  325.   if (get_named_label(name) != -1)
  326.   {
  327.     moan(spoof(ebuf,"Label \"%s\" already in use.",name));
  328.     return 0;
  329.   }
  330.  
  331.   if (!xpand_dTable(&named_label_table, 1, 10,10))
  332.     bail("Out of memory! Can't expand named label table.");
  333.  
  334.   named_label_table.table[named_labels].name = add_var_name(name, FALSE);
  335.   return (named_label_table.table[named_labels++].label = genlabel());
  336. }
  337.  
  338. get_named_label(name) char *name;    /* return label */
  339. {
  340.   int j;
  341.   NamedLabel *label = named_label_table.table;
  342.  
  343.   for (j = named_labels; j--; label++)
  344.     if (0 == strcmp(name, label->name)) return label->label;
  345.  
  346.   return -1;
  347. }
  348.  
  349. void reset_named_labels(base, nlabels)
  350. {
  351.   int j;
  352.   NamedLabel *label;
  353.  
  354.   for (j = named_label_base; j < named_labels; j++)
  355.   {
  356.     label = &named_label_table.table[j];
  357.     if (getlabel(label->label) == NIL)
  358.       moan(spoof(ebuf,"Label \"%s\" unresolved.", label->name));
  359.   }
  360.   named_label_base = base;
  361.   named_labels = nlabels;
  362.   sizeof_dTable(&named_label_table) = named_labels;
  363. }
  364.  
  365. /* ******************************************************************** */
  366. /* *************************** Defun Frames *************************** */
  367. /* ******************************************************************** */
  368.  
  369. typedef struct
  370. {
  371.   int
  372.     num_vars, local_objects, size_of_local_vars, local_start,
  373.     named_labels, named_label_base;
  374. } DefunFrame;
  375.  
  376. #define DFpush    0
  377. #define DFarg    1
  378.  
  379. static int df_level = 0;
  380.  
  381. void push_dframe(dframe, op) DefunFrame *dframe;
  382. {
  383.   if (op == DFarg)
  384.   {
  385. /*    dframe->num_vars = num_vars;    /*  */
  386.     return;
  387.   }
  388.  
  389.   df_level++;
  390.  
  391.   dframe->num_vars = num_vars;
  392.   dframe->local_start = local_start;
  393.   dframe->local_objects = local_objects;
  394.   dframe->size_of_local_vars = size_of_local_vars;
  395.  
  396.   dframe->named_labels = named_labels;
  397.   dframe->named_label_base = named_label_base;
  398.  
  399.   local_start = num_vars;
  400.   local_objects = 0;
  401.   size_of_local_vars = 0;
  402.  
  403.   any_local_vars = TRUE;
  404. }
  405.  
  406. void pop_dframe(dframe) DefunFrame *dframe;
  407. {
  408. /*  num_vars = dframe->num_vars;    /*  */
  409.   num_vars = local_start;    /*  */
  410.  
  411.   local_objects = dframe->local_objects;
  412.   size_of_local_vars = dframe->size_of_local_vars;
  413.  
  414.   local_start = dframe->local_start;
  415.  
  416.   sizeof_dTable(&var_table) = num_vars;
  417.  
  418.   reset_named_labels(dframe->named_label_base, dframe->named_labels);
  419.  
  420.   if (--df_level == 0)
  421.   {
  422.     sheap_reset(local_vname_heap);
  423.     any_local_vars = FALSE;
  424.   }
  425. }
  426.  
  427. /* ******************************************************************** */
  428. /* ****************************** Defun ******************************* */
  429. /* ******************************************************************** */
  430.  
  431. extern int ntharg;    /* in vcomp.c */
  432.  
  433.     /* Define a function
  434.      * Syntax:
  435.      *   (defun pgm-name [(arg list)] [modifiers] pgm [another fcn])
  436.      *     pgm-name: TOKEN or STRING: name of the function being defined
  437.      *     arg-list:  a list of the function parameters.  Used to to a give
  438.      *       name to (arg n).
  439.      *       (type name ...)
  440.      *       (array type name [dims] ...)
  441.      *       (pointer type name ...)
  442.      *       (name ...)        Unknown type: same as (arg n)
  443.      *     modifiers:  stuff like HIDDEN, etc.
  444.      *     pgm:  the actual function code.
  445.      *     If another pgm-name follows the end of pgm, another function is
  446.      *       defined.
  447.      */
  448. void defun()
  449. {
  450.   DefunFrame vf;
  451.   int t, pgm, dim[MAXDIM];
  452.   unsigned int type;
  453.   KeyWord *kw;
  454.  
  455.   do
  456.   {
  457.         /* Get the name of the function */
  458.     get_token();
  459.     if (class != TOKEN && class != STRING)
  460.       bitch("Function names are tokens or strings.");
  461.     pgm = add_pgm(token);
  462. /*strcpy(temp,token);    /* save pgm name */
  463.  
  464.     /* Parse arg-list */
  465.     push_dframe(&vf, DFpush);
  466.     ntharg = 0; addproto("pgm-name");
  467.     while (TRUE)
  468.     {
  469.       lookahead();
  470.       if (class != DELIMITER || *token != START_EXP) break;
  471.       get_token();    /* suck up "(" */
  472.       lookahead(); t = -2;
  473.       if (class == TOKEN)    /* (type arg-name) or (arg-name) */
  474.       {
  475.           t = -1;        /* at least its a token */
  476.     if (kw = global_look_for(token,KWMutt))
  477.     {
  478.       t = kw->token;
  479.       get_token();        /* suck up type */
  480.     }
  481.       }
  482.       switch (t)
  483.       {
  484.     default: moan(spoof(ebuf,"\"%s\" is not an arg type.",token));
  485.       /* FALL THROUGH */
  486.     case -1: type = UNKNOWN; goto defvar; /* unknown token => untyped var */
  487.     case 62:                    /* bool */
  488.       type = BOOLEAN;
  489.       defvar:
  490.       do
  491.       {
  492.         get_token();    /* suck up arg-name */
  493.         if (class != TOKEN)
  494.         bitch(spoof(ebuf,"\"%s\" is not an arg name.",token));
  495.         add_to_proto(token,ntharg++,type,0,dim);
  496.         lookahead();
  497.       } while (class == TOKEN);
  498.       break;
  499.     case 61: case 75: case 31:  /* byte, small-int, int all are NUMBER */
  500.          type = NUMBER; goto defvar;
  501.     case 60: type = STRING; goto defvar;        /* string */
  502.     case 27: type = LIST; goto defvar;        /* list */
  503.     case 73: array(LOCAL,TRUE); break;        /* array */
  504.     case 72: /* (pointer bool | byte | small-int | int | defun name ...) */
  505.       get_token();    /* suck up the pointer type */
  506.       t = -1;
  507.       if (class == TOKEN &&
  508.           (kw = global_look_for(token,KWMutt))) t = kw->token;
  509.       switch (t)
  510.       {
  511.         default:
  512.           moan(spoof(ebuf,"\"%s\" is not a pointer type.",token));
  513.                  type = UNKNOWN;        goto defvar;
  514.         case 62: type = POINTER | BOOLEAN;    goto defvar;    /* bool */
  515.         case 75: type = POINTER | INT8;    goto defvar;    /* byte */
  516.         case 61: type = POINTER | INT16;    goto defvar;    /* small-int */
  517.         case 31: type = POINTER | INT32;    goto defvar;    /* int */
  518.         case 2:  type = FCNPTR;        goto defvar;    /* defun */
  519.       }
  520.       }
  521.       get_token();
  522.       if (class != DELIMITER || *token != END_EXP) bitch("Bad arg list.");
  523.     }
  524.  
  525.         /* suck up function modifiers */
  526.     while (lookahead(), class == TOKEN)
  527.     {
  528.       get_token();
  529.       if ((t = lookup_pgm_modifier(token)) != -1) modpgm(pgm,t);
  530.       else moan(spoof(ebuf,"\"%s\" is an invalid pgm modifer.",token));
  531.     }
  532.  
  533.     push_dframe(&vf, DFarg);    /*  */
  534.  
  535.         /* Compile the code */
  536.     if (class != DELIMITER || *token != START_PGM)
  537.     bitch("Pgms must start with a {");
  538.     class = VAROK;
  539.     compile(); genop(DONE);
  540.     pop_dframe(&vf);
  541.  
  542.         /* Clean up and get ready for another defun */
  543.     lookahead();
  544.   } while (class == TOKEN || class == STRING);
  545. }
  546.  
  547.  
  548.     /* Compile an Anonymous Defun:  {{ code }}
  549.      * !!!??? (anon-defun ...)
  550.      * or (defun ANON
  551.      */
  552. void anon_defun()
  553. {
  554.   address addr;
  555.   int label;
  556.   unsigned int lastclass;
  557.   DefunFrame vf;
  558.  
  559.   push_dframe(&vf, DFpush);
  560.  
  561.   gojmp(JMP, label = genlabel());
  562.   addr = pcaddr();
  563.   lastclass = VAROK;
  564.   while (TRUE)
  565.   {
  566.     lookahead();
  567.     if (class == DELIMITER)
  568.       if (*token == END_IPGM) break;
  569.     class = lastclass;
  570.     compile();
  571.     lastclass = class;
  572.   }
  573.   get_token();        /* suck up }} */
  574.  
  575.   pop_dframe(&vf);
  576.  
  577.   genop(DONE);
  578.   stufflabel(label);
  579.   genfa(addr, "Anon defun");
  580.  
  581.   class = FCNPTR;
  582. }
  583.