%{ /* This routine parses the pidf grammar and creates a data structure holding the parameters. */ #include #include #include #include "symtab.h" extern symtab *GLOBAL_pidf; static symtab *p; static int symsize; static int symtype; static int counter; typedef union { float *dval_ptr; long *lval_ptr; char **str_ptr; } arrayType; static arrayType tmp_array; void *pidf_get_list_head (symtab *p); int p_lex (); int p_error (char *); %} %union { float dval; long lval; int ival; char cval; char *sval; void *pval; symtab *sym; } /* All these are ivals since they tell the type of line */ %token Y_PIDF %token Y_STRUCT %token Y_CHAR %token Y_INT %token Y_FLOAT %token Y_STRING /* these are actual values */ %token Y_NAME %token Y_FLOAT_NUM %token Y_INT_NUM %token Y_QUOTED_STRING %type array_size %type array %type declarator %type initializer %type type_specifier %type struct_specifier %type struct_decl_list %type declaration_list %type declaration %type pidfdef %type type %% pidfdef: Y_PIDF declarator '{' declaration_list '}' { $$ = (symtab *) malloc (sizeof (symtab)); $$->symtype = $1; $$->symname = $2; $$->ptr = pidf_get_list_head ((symtab *) $4); ((symtab *)$4)->parent = $$; $$->next = $$->prev = NULL; GLOBAL_pidf = $$; } ; declarator: Y_NAME ; declaration_list: declaration { $$ = $1; } | declaration_list declaration { $1->next = $2; $2->prev = $1; $$ = $2; } ; declaration : type_specifier declarator '[' array_size ']' '=' '{' array '}' ';' { $1->symname = $2; $1->ptr = tmp_array.lval_ptr; $1->array_length = $4; $$ = $1; if (counter > 0) { yyerror ("WARNING: array size does not match the number of elements (too big)!"); } } ; declaration: type_specifier declarator '=' initializer ';' { $1->symname = $2; $1->ptr = $4; if ($1->symsize == 0) $1->symsize = strlen ((char *) $1->ptr); $$ = $1; } | struct_specifier ';' { $$ = $1; } ; type_specifier: type { p = (symtab *) malloc ((size_t) sizeof (symtab)); p->symtype = $1; p->symsize = symsize; p->array_length = 1; p->next = p->prev = p->parent = NULL; $$ = p; } ; struct_specifier: Y_STRUCT declarator '{' struct_decl_list '}' { $$ = (symtab *) malloc (sizeof (symtab)); $$->symtype = $1; $$->symname = (char *)$2; $$->ptr = pidf_get_list_head ((symtab *)$4); ((symtab *)$4)->parent = $$; $$->next = $$->prev = NULL; } ; struct_decl_list: declaration { $$ = $1; } | struct_decl_list declaration { $1->next = $2; $2->prev = $1; $$ = $2;} ; type: Y_INT { symsize = sizeof (long); symtype = $1; $$ = $1; } | Y_CHAR { symsize = sizeof (char); symtype = $1; $$ = $1; } | Y_FLOAT { symsize = sizeof (float); symtype = $1; $$ = $1; } | Y_STRING { symsize = 0; symtype = $1; $$ = $1; } ; initializer: Y_QUOTED_STRING { $$ = (void *) $1; } | Y_FLOAT_NUM { memcpy ($$, $1, sizeof (float)); } | Y_INT_NUM { memcpy ($$, $1, sizeof (long)); } ; array_size : Y_INT_NUM { counter = *((int *) $1); free ($1); switch (symtype) { case Y_STRING : tmp_array.lval_ptr = (long *) malloc (counter * sizeof (char *)); break; case Y_INT : tmp_array.lval_ptr = (long *) malloc (counter * sizeof (long)); break; case Y_FLOAT : tmp_array.dval_ptr = (float *) malloc (counter * sizeof (float)); break; } $$ = counter; /* set the array size to be a number for use above */ } ; array : initializer ',' array { if (counter < 0) { yyerror ("WARNING: array size is too small compared to the number of elements!"); } else { counter--; switch (symtype) { case Y_STRING : tmp_array.str_ptr [counter] = (char *) $1; break; case Y_INT : tmp_array.lval_ptr [counter] = *((long *)$1); free ($1); break; case Y_FLOAT : tmp_array.dval_ptr [counter] = *((float *)$1); free ($1); break; } } } | initializer { counter--; if (counter < 0) { yyerror ("WARNING: array size does not match the number of elements (too small)!"); } else { switch (symtype) { case Y_STRING : tmp_array.str_ptr [counter] = (char *) $1; $$ = (void *) tmp_array.str_ptr; break; case Y_INT : tmp_array.lval_ptr [counter] = *((long *)$1); free ($1); $$ = (void *) tmp_array.lval_ptr; break; case Y_FLOAT : tmp_array.dval_ptr [counter] = *((float *)$1); free ($1); $$ = (void *) tmp_array.dval_ptr; break; } /* switch */ } } ; %% extern FILE *yyin; /* Given a pointer into a list, return a pointer to the head of the list */ void *pidf_get_list_head (symtab *p) { while (p->prev != NULL) p = p->prev; return ((void *) p); }