Esempio n. 1
0
/* FOLLOW(parameter-list) = { ')' }, peek to return empty list; even though K&R
 * require at least specifier: (void)
 * Set parameter-type-list = parameter-list, including the , ...
 */
static struct typetree *parameter_list(const struct typetree *base)
{
    struct typetree *func = type_init(T_FUNCTION);
    func->next = base;

    while (peek().token != ')') {
        const char *name = NULL;
        struct typetree *type;

        type = declaration_specifiers(NULL);
        type = declarator(type, &name);
        if (is_void(type)) {
            if (nmembers(func)) {
                error("Incomplete type in parameter list.");
            }
            break;
        }

        type_add_member(func, name, type);
        if (peek().token != ',') {
            break;
        }

        consume(',');
        if (peek().token == ')') {
            error("Unexpected trailing comma in parameter list.");
            exit(1);
        } else if (peek().token == DOTS) {
            consume(DOTS);
            assert(!is_vararg(func));
            type_add_member(func, "...", NULL);
            assert(is_vararg(func));
            break;
        }
    }

    return func;
}
Esempio n. 2
0
static void generate_stub(int nparms)
{
  FILE *stream = open_stub();
  char formal[MAX_PARMSIZE];
  char actual[MAX_PARMSIZE];
  int i;
  int j;

  /* Generate "up-front" information, include correct header files */

  fprintf(stream, "/* Auto-generated %s stub file -- do not edit */\n\n", g_parm[0]);
  fprintf(stream, "#include <nuttx/config.h>\n");
  fprintf(stream, "#include <stdint.h>\n");
  fprintf(stream, "#include <%s>\n\n", g_parm[HEADER_INDEX]);

  if (g_parm[COND_INDEX][0] != '\0')
    {
      fprintf(stream, "#if %s\n\n", g_parm[COND_INDEX]);
    }

  /* Generate the function definition that matches standard function prototype */

  if (g_inline)
    {
      fprintf(stream, "static inline ");
    }
  fprintf(stream, "uintptr_t STUB_%s(", g_parm[NAME_INDEX]);

  /* Generate the formal parameter list.  A function received no parameters is a special case. */

  if (nparms <= 0)
    {
      fprintf(stream, "void");
    }
  else
    {
      for (i = 0; i < nparms; i++)
        {
          /* Treat the first argument in the list differently from the others..
           * It does not need a comma before it.
           */

          if (i > 0)
            {
              /* Check for a variable number of arguments */

              if (is_vararg(g_parm[PARM1_INDEX+i], i, nparms))
                {
                  /* Always receive six arguments in this case */

                  for (j = i+1; j <= 6; j++)
                    {
                      fprintf(stream, ", uintptr_t parm%d", j);
                    }
                }
              else
                {
                  fprintf(stream, ", uintptr_t parm%d", i+1);
                }
            }
          else
            {
              fprintf(stream, "uintptr_t parm%d", i+1);
            }
        }
    }
  fprintf(stream, ")\n{\n");

  /* Then call the proxied function.  Functions that have no return value are
   * a special case.
   */

  if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0)
    {
      fprintf(stream, "  %s(", g_parm[NAME_INDEX]);
    }
  else
    {
      fprintf(stream, "  return (uintptr_t)%s(", g_parm[NAME_INDEX]);
    }

  /* The pass all of the system call parameters, casting to the correct type
   * as necessary.
   */

  for (i = 0; i < nparms; i++)
    {
      /* Get the formal type of the parameter, and get the type that we
       * actually have to cast to.  For example for a formal type like 'int parm[]'
       * we have to cast the actual parameter to 'int*'.  The worst is a union
       * type like 'union sigval' where we have to cast to (union sigval)((FAR void *)parm)
       * -- Yech.
       */

     get_formalparmtype(g_parm[PARM1_INDEX+i], formal);
     get_actualparmtype(g_parm[PARM1_INDEX+i], actual);

      /* Treat the first argument in the list differently from the others..
       * It does not need a comma before it.
       */

      if (i > 0)
        {
          /* Check for a variable number of arguments */

          if (is_vararg(actual, i, nparms))
            {
              /* Always pass six arguments */

              for (j = i+1; j <=6; j++)
                {
                  fprintf(stream, ", parm%d", j);
                }
            }
          else
            {
              if (is_union(formal))
                {
                  fprintf(stream, ", (%s)((%s)parm%d)", formal, actual, i+1);
                }
              else
                {
                  fprintf(stream, ", (%s)parm%d", actual, i+1);
                }
            }
        }
      else
        {
          if (is_union(formal))
            {
              fprintf(stream, "(%s)((%s)parm%d)", formal, actual, i+1);
            }
          else
            {
              fprintf(stream, "(%s)parm%d",actual, i+1);
            }
        }
    }

  /* Tail end of the function.  If the proxied function has no return
   * value, just return zero (OK).
   */

  if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0)
    {
      fprintf(stream, ");\n  return 0;\n}\n\n");
    }
  else
    {
      fprintf(stream, ");\n}\n\n");
    }

  if (g_parm[COND_INDEX][0] != '\0')
    {
      fprintf(stream, "#endif /* %s */\n", g_parm[COND_INDEX]);
    }
  stub_close(stream);
}
Esempio n. 3
0
static void generate_proxy(int nparms)
{
  FILE *stream = open_proxy();
  char formal[MAX_PARMSIZE];
  char fieldname[MAX_PARMSIZE];
  bool bvarargs = false;
  int nformal;
  int nactual;
  int i;

  /* Generate "up-front" information, include correct header files */

  fprintf(stream, "/* Auto-generated %s proxy file -- do not edit */\n\n", g_parm[NAME_INDEX]);
  fprintf(stream, "#include <nuttx/config.h>\n");

  /* Does this function have a variable number of parameters?  If so then the
   * final parameter type will be encoded as "..."
   */

  if (is_vararg(g_parm[PARM1_INDEX+nparms-1], nparms-1, nparms))
    {
      nformal = nparms-1;
      bvarargs = true;
      fprintf(stream, "#include <stdarg.h>\n");
    }
  else
    {
      nformal = nparms;
    }

  fprintf(stream, "#include <%s>\n", g_parm[HEADER_INDEX]);
  fprintf(stream, "#include <syscall.h>\n\n");

  if (g_parm[COND_INDEX][0] != '\0')
    {
      fprintf(stream, "#if %s\n\n", g_parm[COND_INDEX]);
    }

  /* Generate the function definition that matches standard function prototype */

  fprintf(stream, "%s %s(", g_parm[RETTYPE_INDEX], g_parm[NAME_INDEX]);

  /* Generate the formal parameter list */

  if (nformal <= 0)
    {
      fprintf(stream, "void");
    }
  else
    {
      for (i = 0; i < nformal; i++)
        {
          /* The formal and actual parameter types may be encoded.. extra the
           * formal parameter type.
           */

          get_formalparmtype(g_parm[PARM1_INDEX+i], formal);

          /* Arguments after the first must be separated from the preceding
           * parameter with a comma.
           */

          if (i > 0)
            {
              fprintf(stream, ", ");
            }
          print_formalparm(stream, formal, i+1);
        }
    }

  /* Handle the end of the formal parameter list */

  if (bvarargs)
    {
       fprintf(stream, ", ...)\n{\n");

       /* Get parm variables .. some from the parameter list and others from
        * the varargs.
        */

       if (nparms < 7)
         {
           fprintf(stream, "  va_list ap;\n");
           for (i = nparms; i < 7; i++)
             {
               fprintf(stream, "  uintptr_t parm%d;\n", i);
             }

           fprintf(stream, "\n  va_start(ap, parm%d);\n", nparms-1);
           for (i = nparms; i < 7; i++)
             {
               fprintf(stream, "  parm%d = va_arg(ap, uintptr_t);\n", i);
             }
           fprintf(stream, "  va_end(ap);\n\n");
         }
    }
  else
    {
      fprintf(stream, ")\n{\n");
    }

  /* Generate the system call.  Functions that do not return or return void
   * are special cases.
   */

  nactual = bvarargs ? 6 : nparms;
  if (strcmp(g_parm[RETTYPE_INDEX], "void") == 0)
    {
      fprintf(stream, "  (void)sys_call%d(", nactual);
    }
  else
    {
      fprintf(stream, "  return (%s)sys_call%d(", g_parm[RETTYPE_INDEX], nactual);
    }

  /* Create the parameter list with the matching types.  The first parameter
   * is always the syscall number.
   */

  fprintf(stream, "(unsigned int)SYS_%s", g_parm[NAME_INDEX]);

  for (i = 0; i < nactual; i++)
    {
      /* Is the parameter a union member */

      if (i < nparms && is_union(g_parm[PARM1_INDEX+i]))
        {
          /* Then we will have to pick a field name that can be cast to a
           * uintptr_t.  There probably should be some error handling here
           * to catch the case where the fieldname was not supplied.
           */

          get_fieldname(g_parm[PARM1_INDEX+i], fieldname);
          fprintf(stream, ", (uintptr_t)parm%d.%s", i+1, fieldname);          
        }
      else
        {
          fprintf(stream, ", (uintptr_t)parm%d", i+1);
        }
    }

  /* Handle the tail end of the function. */

  fprintf(stream, ");\n}\n\n");
  if (g_parm[COND_INDEX][0] != '\0')
    {
      fprintf(stream, "#endif /* %s */\n", g_parm[COND_INDEX]);
    }

  fclose(stream);
}
Esempio n. 4
0
static struct block *postfix_expression(struct block *block)
{
    struct var root;

    block = primary_expression(block);
    root = block->expr;

    while (1) {
        const struct member *field;
        const struct typetree *type;
        struct var expr, copy, *arg;
        struct token tok;
        int i, j;

        switch ((tok = peek()).token) {
        case '[':
            do {
                /* Evaluate a[b] = *(a + b). The semantics of pointer arithmetic
                 * takes care of multiplying b with the correct width. */
                consume('[');
                block = expression(block);
                root = eval_expr(block, IR_OP_ADD, root, block->expr);
                root = eval_deref(block, root);
                consume(']');
            } while (peek().token == '[');
            break;
        case '(':
            type = root.type;
            if (is_pointer(root.type) && is_function(root.type->next))
                type = type_deref(root.type);
            else if (!is_function(root.type)) {
                error("Expression must have type pointer to function, was %t.",
                    root.type);
                exit(1);
            }
            consume('(');
            arg = calloc(nmembers(type), sizeof(*arg));
            for (i = 0; i < nmembers(type); ++i) {
                if (peek().token == ')') {
                    error("Too few arguments, expected %d but got %d.",
                        nmembers(type), i);
                    exit(1);
                }
                block = assignment_expression(block);
                arg[i] = block->expr;
                /* todo: type check here. */
                if (i < nmembers(type) - 1) {
                    consume(',');
                }
            }
            while (is_vararg(type) && peek().token != ')') {
                consume(',');
                arg = realloc(arg, (i + 1) * sizeof(*arg));
                block = assignment_expression(block);
                arg[i] = block->expr;
                i++;
            }
            consume(')');
            for (j = 0; j < i; ++j)
                param(block, arg[j]);
            free(arg);
            root = eval_call(block, root);
            break;
        case '.':
            consume('.');
            tok = consume(IDENTIFIER);
            field = find_type_member(root.type, tok.strval);
            if (!field) {
                error("Invalid field access, no member named '%s'.",
                    tok.strval);
                exit(1);
            }
            root.type = field->type;
            root.offset += field->offset;
            break;
        case ARROW:
            consume(ARROW);
            tok = consume(IDENTIFIER);
            if (is_pointer(root.type) && is_struct_or_union(root.type->next)) {
                field = find_type_member(type_deref(root.type), tok.strval);
                if (!field) {
                    error("Invalid field access, no member named '%s'.",
                        tok.strval);
                    exit(1);
                }

                /* Make it look like a pointer to the field type, then perform
                 * normal dereferencing. */
                root.type = type_init(T_POINTER, field->type);
                root = eval_deref(block, root);
                root.offset = field->offset;
            } else {
                error("Invalid field access.");
                exit(1);
            }
            break;
        case INCREMENT:
            consume(INCREMENT);
            copy = create_var(root.type);
            eval_assign(block, copy, root);
            expr = eval_expr(block, IR_OP_ADD, root, var_int(1));
            eval_assign(block, root, expr);
            root = copy;
            break;
        case DECREMENT:
            consume(DECREMENT);
            copy = create_var(root.type);
            eval_assign(block, copy, root);
            expr = eval_expr(block, IR_OP_SUB, root, var_int(1));
            eval_assign(block, root, expr);
            root = copy;
            break;
        default:
            block->expr = root;
            return block;
        }
    }
}