Пример #1
0
void patch_symbol_table(ast_node root, symhashtable_t *symtable){

  symhashtable_t *hashtable;
  symnode_t *snode = NULL;

  switch(root->node_type){

    case ID_N:

      hashtable = find_hashtable(symtable, root->curr_level, root->curr_sib);
      if(hashtable != NULL){
        //snode = lookup_symhashtable(hashtable, root->value_string, NOHASHSLOT);
        assert(hashtable != NULL);
        assert(snode == NULL);
        for(;hashtable != NULL && snode == NULL; hashtable = hashtable->parent) {
          snode = lookup_symhashtable(hashtable, root->value_string, NOHASHSLOT);
        }
        if(snode != NULL){
          if(snode->type == VAR_ARRAY_INT_T && root->left_child == NULL){
            root->return_type = ARRAY_TYPE_N;
//           root->node_type = ARRAY_TYPE_N; // change in the future
          }
        }
      break;

    case ARRAY_TYPE_N:
      hashtable = find_hashtable(symtable, root->curr_level, root->curr_sib);
      if(hashtable != NULL){
        snode = lookup_symhashtable(hashtable, root->value_string, NOHASHSLOT);
        if(snode != NULL){
          if(snode->type == VAR_INT_T){
            snode->type = VAR_ARRAY_INT_T;
          }
        }
      }
      break;

    default:
      break;
    }
  }


  ast_node child;

  for(child = root->left_child; child != NULL; child = child->right_sibling){
    patch_symbol_table(child, symtable);
  }
}
Пример #2
0
/*
 * Function to check if a particular variable or function identifier
 * has been redefined.
 */
int check_if_redef(ast_node anode, symboltable_t *symtab ,int lvl, int sibno) {
  symhashtable_t *hash = find_hashtable(symtab->root, lvl, sibno);

  /* If scope with (lvl, sibno) identifier could be found, start search */
  if(hash != NULL) {
    /* node = NULL in case we don't find anything */
    symnode_t *node = NULL;
    node = lookup_symhashtable(hash, anode->value_string, NOHASHSLOT);

    /* Found a match in current or parent scope? */
    if(node != NULL){
      /* If abstract syntax node has a type, it was previously defined */
      if(anode->return_type != ROOT_N && anode->isDecl == 1) {
        symtabError = 1;
        if(anode->node_type == FUNC_DECLARATION_N) {
          fprintf(stderr, "line: %d | error: redefinition of function %s\n", anode->line_num ,anode->value_string);
        }
        if(anode->node_type == ID_N || anode->node_type == ARRAY_TYPE_N) {
          fprintf(stderr, "line: %d | error: redefinition of identifier %s\n", anode->line_num ,anode->value_string);
        }

        return 0;
      }
    }
  }
  /* Not found */
  return 1;
}
Пример #3
0
/*
 * This function creates a hashtable and then appropriately attaches it to its parent,
 * whose identifier is given to us in the form of its identifier (parent_lvl, parent_sibno)
 */
  symhashtable_t *make_insert_hashtable(symhashtable_t  *root, int lvl, int sibno, int parent_lvl, int parent_sibno) {
    symhashtable_t *hashtable, *parent_hashtable, *temp;

    hashtable = create_symhashtable(HASHSIZE);
    assert(hashtable != NULL);

    parent_hashtable = find_hashtable(root, parent_lvl, parent_sibno);  //parent must have been created
    assert(parent_hashtable != NULL);

    // Fill the appropriate values for our hash table.
    hashtable->parent = parent_hashtable;
    hashtable->level = lvl;
    hashtable->sibno = sibno;

    //insert as rightmost child of parent
    if(parent_hashtable->child != NULL) {
      for(temp = parent_hashtable->child ; temp->rightsib != NULL; temp = temp->rightsib) {
        ;}
        temp->rightsib = hashtable;
    }
    else {
      parent_hashtable->child = hashtable;
    }

    return hashtable;
  }
Пример #4
0
/* Lookup a hashtable with given lvl and sibno in a symbol table.
  If found return a pointer to it.
  Otherwise, return NULL */
  symhashtable_t *find_hashtable(symhashtable_t  *root, int lvl, int sib) {

    if(root != NULL) {
      if (lvl == root->level && sib == root->sibno) {
        return(root);
      }
    }

    symhashtable_t *res, *child;
    res = NULL;
    for(child = root->child; child != NULL  && res == NULL; child = child->rightsib) {
      //if(child != NULL) {printf("in find) lvl: %d, sibno: %d\n", child->level,child->sibno);}
      res = find_hashtable(child, lvl, sib);
    }
    return res;
  }
Пример #5
0
char const *
strget(char const *s)
{
	poolelem e, *ep;

	if (strpool == NULL)
		strpool = new_hashtable(&poolinfo);

	e.str = s;

	if (!find_hashtable(strpool, (hashelt *)&e))
		insert_hashtable(strpool, (hashelt *)&e);

	ep = (poolelem *)cur_hashtable(strpool);
	ep->ref++;
	return ep->str;
}
Пример #6
0
void
strdrop(char const *s)
{
	poolelem e, *ep;

	if (strpool == NULL)
		return;

	e.str = s;

	if (!find_hashtable(strpool, &e))
		return;

	ep = (poolelem *)cur_hashtable(strpool);

	if (--ep->ref <= 0)
		remove_hashtable(strpool, ep);
}
Пример #7
0
/*
 * Tests to see if the given directory has already been visited.
 */
static int
already_visited(char *mandir, char *dir, int count_visit)
{
	struct stat st;

	if (stat(dir, &st) < 0) {
		if (mandir != NULL)
			warn("%s/%s", mandir, dir);
		else
			warn("%s", dir);
		exit_code = 1;
		return 1;
	}
	if (find_hashtable(visited, st.st_ino, st.st_dev) != NULL) {
		if (mandir != NULL)
			warnx("already visited %s/%s", mandir, dir);
		else
			warnx("already visited %s", dir);
		return 1;
	}
	if (count_visit)
		insert_hashtable(visited, st.st_ino, st.st_dev, "");
	return 0;
}
Пример #8
0
/*
 * Checks if a particular variable has already been declared.
 */
  int check_if_declared(ast_node anode, symboltable_t *symtab ,int lvl, int sibno) {

    symhashtable_t *hash = find_hashtable(symtab->root, lvl, sibno);

    assert(hash != NULL);
    assert(anode != NULL);

    /* Set node to NULL so that, if no match is found, it will be NULL and we can
     * act accordingly.
     */
    symnode_t *node = NULL;

    /*
     * Recurse up until hash table with matching identifier, or the root, is found.
     */
    for(;hash != NULL && node == NULL; hash = hash->parent) {
      node = lookup_symhashtable(hash, anode->value_string, NOHASHSLOT);
    }

    /* If not found, variable or function is undeclared. */
    if(node == NULL) {
      symtabError = 1;
      if(anode->node_type == FUNCTION_N) {
        fprintf(stderr, "line: %d | error: use of undeclared function %s\n", anode->line_num, anode->value_string);
      }
      else if(anode->node_type == ID_N || anode->node_type == ARRAY_TYPE_N) {
        fprintf(stderr, "line: %d | error: use of undeclared identifier %s\n", anode->line_num, anode->value_string);
      }

      return 0;
    }
    else { /* Otherwise, declaration for variable or function has been found */
      return 1;
    }

  }
Пример #9
0
/*
 * Processes a single man page source by using nroff to create
 * the preformatted cat page.
 */
static void
process_page(char *mandir, char *src, char *cat, enum Ziptype zipped)
{
	int src_test, cat_test;
	time_t src_mtime, cat_mtime;
	char cmd[MAXPATHLEN];
	dev_t src_dev;
	ino_t src_ino;
	const char *link_name;

	src_test = test_path(src, &src_mtime);
	if (!(src_test & (TEST_FILE|TEST_READABLE))) {
		if (!(src_test & TEST_DIR)) {
			warnx("%s/%s: unreadable", mandir, src);
			exit_code = 1;
			if (rm_junk && is_symlink(src))
				junk(mandir, src, "bogus symlink");
		}
		return;
	}
	src_dev = test_st.st_dev;
	src_ino = test_st.st_ino;
	cat_test = test_path(cat, &cat_mtime);
	if (cat_test & (TEST_FILE|TEST_READABLE)) {
		if (!force && cat_mtime >= src_mtime) {
			if (verbose) {
				fprintf(stderr, "\t%s/%s: up to date\n",
				    mandir, src);
			}
			return;
		}
	}
	/*
	 * Is the man page a link to one we've already processed?
	 */
	if ((link_name = find_hashtable(links, src_ino, src_dev)) != NULL) {
		if (verbose || pretend) {
			fprintf(stderr, "%slink %s -> %s\n",
			    verbose ? "\t" : "", cat, link_name);
		}
		if (!pretend)
			link(link_name, cat);
		return;
	}
	insert_hashtable(links, src_ino, src_dev, strdup(cat));
	if (verbose || pretend) {
		fprintf(stderr, "%sformat %s -> %s\n",
		    verbose ? "\t" : "", src, cat);
		if (pretend)
			return;
	}
	snprintf(tmp_file, sizeof tmp_file, "%s.tmp", cat);
	snprintf(cmd, sizeof cmd,
	    "%scat %s | tbl | nroff -c -T%s -man | %s > %s.tmp",
	    zipped == BZIP ? BZ2CAT_CMD : zipped == GZIP ? GZCAT_CMD : "",
	    src, nroff_device,
	    zipped == BZIP ? BZ2_CMD : zipped == GZIP ? GZ_CMD : "cat",
	    cat);
	if (system(cmd) != 0)
		err(1, "formatting pipeline");
	if (rename(tmp_file, cat) < 0)
		warn("%s", cat);
	tmp_file[0] = '\0';
}
Пример #10
0
void link_ast_to_symnode(ast_node root, symboltable_t *symtab) {
  symhashtable_t *hash = NULL;
  symnode_t *snode = NULL;

  /* Depending on node types, go deeper, create sibling scopes, add to hashtable,
   * or take other appropriate action.
   */
  switch (root->node_type) {
    case SEQ_N:     // change main level when see a new sequence
      break;

    case FORMAL_PARAMS_N:
      break;

    case FUNC_DECLARATION_N: // function declaraions
      break;

    case FUNCTION_N:
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && snode == NULL; hash = hash->parent) {
        snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(snode != NULL);
      root->snode = snode;
      break;

    case ID_N:      /* print the id */
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && snode == NULL; hash = hash->parent) {
        snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(snode != NULL);
      root->snode = snode;
      break;

    case ARRAY_TYPE_N:             // check for return types!
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && snode == NULL; hash = hash->parent) {
        snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(snode != NULL);
      root->snode = snode;
      break;

    case INT_LITERAL_N:
      hash = symtab->literal_collection;
      assert(hash != NULL);
      assert(root->value_string != NULL);
      snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      root->snode = snode;
      break;

    case STRING_LITERAL_N:
      hash = symtab->literal_collection;
      assert(hash != NULL);
      assert(root->value_string != NULL);
      snode = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      root->snode = snode;
      break;

    case RETURN_N:

      hash = symtab->literal_collection;
      assert(hash != NULL);
      if(root->left_child->node_type == VOID_TYPE_N){
        snode = lookup_symhashtable(hash, root->left_child->value_string, NOHASHSLOT);
        root->left_child->snode = snode;
      }
      break;


    default:
      break;
  }

/* Recurse on each child of the subtree root */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    link_ast_to_symnode(child, symtab);
}
Пример #11
0
/*declaration of func and identifiers is already checked during  build_symbol_table
* so here, we just check for paramter inputs into functions
*/
int check_function(ast_node root, symboltable_t *symtab) {
  symhashtable_t *hash = NULL;
  symnode_t *node = NULL;
  ast_node anode = NULL;

  switch (root->node_type) {

    case FUNCTION_N:
        hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
        for(;hash != NULL && node == NULL; hash = hash->parent) {
          node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
          //node is the original declaration stored in symbol table
        }
        assert(node != NULL); //as hashtable was built previously, it must be found for func_n

        // Count the number of parameters passed to the function
        int i = 0;
        for(anode = root->left_child; anode != NULL; anode = anode->right_sibling) {
          i++;
        }

        if(node->num_parameters != i) {
          funcError = 1;
          fprintf(stderr, "line: %d | Error: Number of parameters to function %s does not match number of parameters in declaration at line %d\n",
          root->line_num, root->value_string, root->line_declared);
        }
        else {
          int k = 0;
          for(anode = root->left_child; anode != NULL; anode = anode->right_sibling) {
            if(!((anode->return_type == INT_TYPE_N && node->parameters[k] == VAR_INT_T) ||
             (anode->return_type == ARRAY_TYPE_N && node->parameters[k] == VAR_ARRAY_INT_T)) ) {

            // if(!(anode->return_type == INT_TYPE_N && node->parameters[k] == VAR_INT_T)) {
              funcError = 1;
              //printf("\n\n  parm type is: %s return_type is: %s \n\n", TYPE_NAME(node->parameters[k]), NODE_NAME(anode->return_type));
              // fprintf(stderr, "\n\n %s return_type: %s but should be %s \n\n",anode->value_string ,NODE_NAME(anode->return_type), TYPE_NAME(node->parameters[k]));
              assert(anode != NULL);
              //assert(anode->snode
              //assert(anode->snode);
              fprintf(stderr, "%dth param. Expecting  %s, got (%s, %s)\n",
                k, TYPE_NAME(node->parameters[k]), NODE_NAME(anode->return_type), NODE_NAME(anode->node_type));
              //fprintf(stderr, "snode of ^ is %s ", anode->snode->name);
              fprintf(stderr, "line: %d | Error: Input parameters to function %s do not match the declaration at line %d\n",
                root->line_num, root->value_string, root->line_declared);
              return 1;
            }
            k++;
          }
        }
      break;



    default:
      // printf("at default of switch\n");
      assert(symtab->root != NULL);
      break;


  }

  /* Recurse on each child of the subtree root, with a depth one
     greater than the root's depth. */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    check_function(child, symtab);
  return 0;
}
Пример #12
0
/*
* Works on an assumption that build hashtable as already been run. (i.e. no errors generated from building hashtable)
*/
void record_var_type_in_ast(ast_node root, symboltable_t *symtab) {
  symhashtable_t *hash = NULL;
  symnode_t *node = NULL;


  /* Depending on node types, go deeper, create sibling scopes, add to hashtable,
   * or take other appropriate action.
   */
  switch (root->node_type) {

    case FUNC_DECLARATION_N:
        hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
        for(;hash != NULL && node == NULL; hash = hash->parent) {
          node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
        }
        assert(node != NULL); //as hashtable was built prev, it must be found for func_n
        if(node->type == FUNC_VOID_T) {
          root->return_type = VOID_TYPE_N;
        } else if(node->type == FUNC_INT_T) {
          root->return_type = INT_TYPE_N;
        }
        root->line_declared = node->abnode->line_num;
      break;

    case FUNCTION_N: //all function_n nodes are calls not declarations
        hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
        for(;hash != NULL && node == NULL; hash = hash->parent) {
          node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
        }
        assert(node != NULL); //as hashtable was built prev, it must be found for func_n
        if(node->type == FUNC_VOID_T) {
          root->return_type = VOID_TYPE_N;
        } else if(node->type == FUNC_INT_T) {
          root->return_type = INT_TYPE_N;
        }
        root->line_declared = node->abnode->line_num;
      break;

    case ID_N:

      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      assert(hash != NULL);
      for(;hash != NULL && node == NULL; hash = hash->parent) {
          //printf("  \n\n value string is %s\n\n", root->value_string);
        node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(node != NULL); //as hashtable was built prev, it must be found for ID_N

      if(root->return_type == 0) {  // a zero value means that it is not a declaration, since only declarations
                                    // are assigned a return type when building the abstract syntax tree.
        if(node->type == VAR_INT_T) {
          root->return_type = INT_TYPE_N;
        }
      }
      root->line_declared = node->abnode->line_num;
      break;

    case ARRAY_TYPE_N:             // check for return types!
      hash = find_hashtable(symtab->root, root->curr_level, root->curr_sib);
      for(;hash != NULL && node == NULL; hash = hash->parent) {
        node = lookup_symhashtable(hash, root->value_string, NOHASHSLOT);
      }
      assert(node != NULL); //as hashtable was built prev, it must be found for array_type_n
      if(root->return_type == 0) {
        if(node->type == VAR_ARRAY_INT_T){
          if(root->left_child == NULL){
            root->return_type = ARRAY_TYPE_N;
          }
          else{
            root->return_type = INT_TYPE_N;
          }
        }

      }
      root->line_declared = node->abnode->line_num;
      break;

    case INT_LITERAL_N:
      root->return_type = INT_TYPE_N;
      break;

    case RETURN_N: //not sure if we deal with this here...
      assert(symtab->root != NULL);
      break;

    default:
      // printf("at default of switch\n");
      assert(symtab->root != NULL);

      break;
  }


  /* Recurse on each child of the subtree root, with a depth one */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    record_var_type_in_ast(child, symtab);
}
Пример #13
0
/*
 * Builds the symbol table, creating scopes as needed, and linking them together.
 * Adds variable and function identifiers to scopes appropriately.
 */
void build_symbol_table(ast_node root, int level, int sibno, symboltable_t *symtab) {
  //calculate the scope for the variable/func declaration
  //calculate the parent for that variable/func declaration
  //need function to take as input
  //printf("here \n");
  symhashtable_t *hash;

  /* Depending on node types, go deeper, create sibling scopes, add to hashtable,
   * or take other appropriate action.
   */
  switch (root->node_type) {
    ast_node param;
    int param_offset = 4;
    int param_count = 0;

    case SEQ_N:     // change main level when see a new sequence
      level++;
      break;

    case FORMAL_PARAMS_N:
      level++;
      param_count = 0;
      insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) );
    //   for(param = root->left_child; param != NULL; param = param->right_sibling){
    //     if(param->node_type == ARRAY_TYPE_N || param->return_type == ARRAY_TYPE_N){
    //      param_count += DEFAULT_ARRAY_PARAM_SIZE;
    //    }
    //    else{
    //      param_count++;
    //    }
    //  }
    //  printf("PARAM COUNT!!!!! = %d\n", param_count);
    //
    //  for(param = root->left_child; param != NULL; param = param->right_sibling){
    //    if(param->node_type == ARRAY_TYPE_N || param->return_type == ARRAY_TYPE_N){
    //      param->snode->offset = param_count * 4;
    //      param->snode->offset -= DEFAULT_ARRAY_PARAM_SIZE;
    //    }
    //    else{
    //     param->snode->offset = param_count-- * 4;
    //    }
    // }


      break;

    case FUNC_DECLARATION_N: // function declaraions
      //does hashtable exist with given lvl, siblvl (use find_hashtable)
      check_if_redef(root, symtab ,level, sibno);
      hash = find_hashtable(symtab->root, level, sibno);
      if(hash == NULL) {
        hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) );

      }
      insert_into_symhashtable(hash, root); // will only insert if it is empty.
      insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) );
      break;

    case FUNCTION_N:
      check_if_declared(root, symtab ,level, sibno);
      insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) );
      break;

    case ID_N:      /* print the id */

        check_if_redef(root, symtab ,level, sibno);

      //if(root->return_type != 0) {  // a non-zero value means that it is a declaration, since only declarations
                                    // are assigned a return type when building the abstract syntax tree.
      if(root->isDecl){

        hash = find_hashtable(symtab->root, level, sibno);
        if(hash == NULL) {
          hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) );
        }
        insert_into_symhashtable(hash, root);
      }
      else {  // don't know if previously declared
        check_if_declared(root, symtab , level, sibno);
      }
      insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) );
      break;

    case ARRAY_TYPE_N:             // check for return types!

        check_if_redef(root, symtab ,level, sibno);

      //cif(root->return_type != 0) {
      if(root->isDecl){
        hash = find_hashtable(symtab->root, level, sibno);
        if(hash == NULL) {
          hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) );
          }
        insert_into_symhashtable(hash, root);
      }
      else {
        check_if_declared(root, symtab , level, sibno);
      }
      insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) );
      break;

    case RETURN_N:
      insert_scope_info(root, level, sibno, MAX(level - 1, 0), getSibling(level) );
      break;

    default:
      // printf("at default of switch\n");
      assert(symtab->root != NULL);
      hash = find_hashtable(symtab->root, level, sibno);
      if(hash == NULL) {
        hash = make_insert_hashtable(symtab->root, level, sibno, MAX(level - 1, 0), getSibling(level) );
      }
      //note: cannot use insert_scope_info here because siblings[level - 1] causes invalid read as level-1 can go negative
      break;
  }

  if(arraylen == level) {
    arraylen = arraylen + DELTA;
    siblings = realloc(siblings, sizeof(int) * arraylen);

    assert(siblings != NULL);

    for(int k=0; k < DELTA; k++) {
      siblings[arraylen - (DELTA-k)] = 0;
    }
  }

  /* Recurse on each child of the subtree root, with a depth one
     greater than the root's depth. */
  ast_node child;
  for (child = root->left_child; child != NULL; child = child->right_sibling)
    build_symbol_table(child, level, siblings[level], symtab);

  if(root->node_type == SEQ_N){//} || root->node_type == FORMAL_PARAMS_N){
    siblings[level]++;  // change sibling level after you're done printing all
                      // subtrees, i.e., after done recursing.
  }
}