0

I am writing a software in C. For that purpose I use lex. I wrote a piece of code in C to create a symbol table and manage it. So, whenever lex finds a new symbol, it puts it in a symbol table. Problem is, when I try to print all results from symbol table, I get output I didn't expect. If, for example, the input file was:

int main(){}

the output should be:

int
main
(
)
{
}

but the output is:

int main(){}
main(){}
(){}
...

and so on. The function used for printing is something like this

void print_entries(struct symtab *start) {
   struct symtab *s = start;
   while(s != NULL) {
      printf("%s\n", s->name);
      s = s->next;
   }
}

Here is the code for adding new symbols:

void add_entry(char* name, int type, struct symtab *start)
{
   struct symtab *new;
   new = malloc(sizeof(struct symtab));
   last_entry(start)->next = new;
   new->name = name;
   new->type = type;
   new->next = NULL;
}

Any ideas?

Community
  • 1
  • 1
Melvin Smiley
  • 99
  • 2
  • 8
  • (This might be a silly question, but are you only calling print_entries once?) – marnir May 30 '11 at 03:16
  • Yes, i'm only calling it once :) – Melvin Smiley May 30 '11 at 03:19
  • Sorry, I thought I should ask :P – marnir May 30 '11 at 03:20
  • It looks like you're not creating your symbols correctly. If you look at your output, the name doesn't hold the contents of the token but rather is just a pointer into the text. You should allocate the names to hold just the token. – Jeff Mercado May 30 '11 at 03:36
  • I noticed the same thing.But i can't see an error in my code. – Melvin Smiley May 30 '11 at 03:38
  • 1
    And how is `add_entry()` called? You haven't allocated anything for the name here. – Jeff Mercado May 30 '11 at 03:45
  • 1
    Jeff is correct. You are stashing pointers into the input buffer in your `->name` fields; you need to allocate space for the correct number of characters (which it appears you currently do not know in `add_entry` - that'll need to be passed in), copy, and nul-terminate. – zwol May 30 '11 at 03:45
  • Can you give me example code for that? :) – Melvin Smiley May 30 '11 at 03:47
  • easiest would be to use `strdup(yytext)` in your lex code that calls add_entry. Alternately use `new->name = strdup(name);` in add_entry – Chris Dodd May 30 '11 at 04:37
  • I could be misremembering, but I thought `yytext` wasn't guaranteed to be nul-terminated. – zwol May 30 '11 at 05:19

1 Answers1

0

You need to copy the symbol names into the symbol table entries. If for some peculiar reason your system does not have strdup() already, then use:

#include <string.h>
#include <stdlib.h>

char *strdup(const char *str)
{
   size_t len = strlen(str) + 1;
   char *dup = malloc(len);
   if (dup != 0)
       memmove(dup, str, len);
   return dup;
}

(In this context, I could use memcpy() safely; I use memmove() because it always works and memcpy() does not. And I use memmove() because I know exactly how long the string is so the copy doesn't need to test each character for nullness as it goes.)

With strdup() on hand:

void add_entry(char* name, int type, struct symtab *start)
{
   struct symtab *sym;
   sym = malloc(sizeof(struct symtab));
   last_entry(start)->next = sym;
   sym->name = strdup(name);
   sym->type = type;
   sym->next = NULL;
}

Note that this still omits the error checking from the two memory allocations, which is not a good habit to get into. I've revised it to use sym rather than new because the latter is a C++ keyword and I avoid using those as identifiers, even in C code.

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185