xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/table.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
14e98e3e1Schristos /* The IGEN simulator generator for GDB, the GNU Debugger.
24e98e3e1Schristos 
3*71f62182Schristos    Copyright 2002-2024 Free Software Foundation, Inc.
44e98e3e1Schristos 
54e98e3e1Schristos    Contributed by Andrew Cagney.
64e98e3e1Schristos 
74e98e3e1Schristos    This file is part of GDB.
84e98e3e1Schristos 
94e98e3e1Schristos    This program is free software; you can redistribute it and/or modify
104e98e3e1Schristos    it under the terms of the GNU General Public License as published by
114e98e3e1Schristos    the Free Software Foundation; either version 3 of the License, or
124e98e3e1Schristos    (at your option) any later version.
134e98e3e1Schristos 
144e98e3e1Schristos    This program is distributed in the hope that it will be useful,
154e98e3e1Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
164e98e3e1Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
174e98e3e1Schristos    GNU General Public License for more details.
184e98e3e1Schristos 
194e98e3e1Schristos    You should have received a copy of the GNU General Public License
204e98e3e1Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
214e98e3e1Schristos 
224e98e3e1Schristos 
234e98e3e1Schristos 
244e98e3e1Schristos #include <sys/types.h>
254e98e3e1Schristos #include <sys/stat.h>
264e98e3e1Schristos #include <stdio.h>
274e98e3e1Schristos #include <fcntl.h>
284e98e3e1Schristos #include <ctype.h>
294e98e3e1Schristos 
304e98e3e1Schristos #include "misc.h"
314e98e3e1Schristos #include "lf.h"
324e98e3e1Schristos #include "table.h"
334e98e3e1Schristos 
344e98e3e1Schristos #include <unistd.h>
354e98e3e1Schristos #include <stdlib.h>
364e98e3e1Schristos 
374e98e3e1Schristos typedef struct _open_table open_table;
384e98e3e1Schristos struct _open_table
394e98e3e1Schristos {
404e98e3e1Schristos   size_t size;
414e98e3e1Schristos   char *buffer;
424e98e3e1Schristos   char *pos;
434e98e3e1Schristos   line_ref pseudo_line;
444e98e3e1Schristos   line_ref real_line;
454e98e3e1Schristos   open_table *parent;
464e98e3e1Schristos   table *root;
474e98e3e1Schristos };
484e98e3e1Schristos struct _table
494e98e3e1Schristos {
504e98e3e1Schristos   open_table *current;
514e98e3e1Schristos };
524e98e3e1Schristos 
534e98e3e1Schristos 
544e98e3e1Schristos static line_ref *
554e98e3e1Schristos current_line (open_table * file)
564e98e3e1Schristos {
574e98e3e1Schristos   line_ref *entry = ZALLOC (line_ref);
584e98e3e1Schristos   *entry = file->pseudo_line;
594e98e3e1Schristos   return entry;
604e98e3e1Schristos }
614e98e3e1Schristos 
624e98e3e1Schristos static table_entry *
634e98e3e1Schristos new_table_entry (open_table * file, table_entry_type type)
644e98e3e1Schristos {
654e98e3e1Schristos   table_entry *entry;
664e98e3e1Schristos   entry = ZALLOC (table_entry);
674e98e3e1Schristos   entry->file = file->root;
684e98e3e1Schristos   entry->line = current_line (file);
694e98e3e1Schristos   entry->type = type;
704e98e3e1Schristos   return entry;
714e98e3e1Schristos }
724e98e3e1Schristos 
734e98e3e1Schristos static void
744e98e3e1Schristos set_nr_table_entry_fields (table_entry *entry, int nr_fields)
754e98e3e1Schristos {
764e98e3e1Schristos   entry->field = NZALLOC (char *, nr_fields + 1);
774e98e3e1Schristos   entry->nr_fields = nr_fields;
784e98e3e1Schristos }
794e98e3e1Schristos 
804e98e3e1Schristos 
814e98e3e1Schristos void
824e98e3e1Schristos table_push (table *root,
834b169a6bSchristos 	    const line_ref *line,
844b169a6bSchristos 	    table_include *includes,
854b169a6bSchristos 	    const char *file_name)
864e98e3e1Schristos {
874e98e3e1Schristos   FILE *ff;
884e98e3e1Schristos   open_table *file;
894e98e3e1Schristos   table_include dummy;
904e98e3e1Schristos   table_include *include = &dummy;
914e98e3e1Schristos 
924e98e3e1Schristos   /* dummy up a search of this directory */
934e98e3e1Schristos   dummy.next = includes;
944e98e3e1Schristos   dummy.dir = "";
954e98e3e1Schristos 
964e98e3e1Schristos   /* create a file descriptor */
974e98e3e1Schristos   file = ZALLOC (open_table);
984e98e3e1Schristos   if (file == NULL)
994e98e3e1Schristos     {
1004e98e3e1Schristos       perror (file_name);
1014e98e3e1Schristos       exit (1);
1024e98e3e1Schristos     }
1034e98e3e1Schristos   file->root = root;
1044e98e3e1Schristos   file->parent = root->current;
1054e98e3e1Schristos   root->current = file;
1064e98e3e1Schristos 
1074e98e3e1Schristos   while (1)
1084e98e3e1Schristos     {
1094e98e3e1Schristos       /* save the file name */
1104e98e3e1Schristos       char *dup_name =
1114e98e3e1Schristos 	NZALLOC (char, strlen (include->dir) + strlen (file_name) + 2);
1124e98e3e1Schristos       if (dup_name == NULL)
1134e98e3e1Schristos 	{
1144e98e3e1Schristos 	  perror (file_name);
1154e98e3e1Schristos 	  exit (1);
1164e98e3e1Schristos 	}
1174e98e3e1Schristos       if (include->dir[0] != '\0')
1184e98e3e1Schristos 	{
1194e98e3e1Schristos 	  strcat (dup_name, include->dir);
1204e98e3e1Schristos 	  strcat (dup_name, "/");
1214e98e3e1Schristos 	}
1224e98e3e1Schristos       strcat (dup_name, file_name);
1234e98e3e1Schristos       file->real_line.file_name = dup_name;
1244e98e3e1Schristos       file->pseudo_line.file_name = dup_name;
1254e98e3e1Schristos       /* open the file */
1264e98e3e1Schristos 
1274e98e3e1Schristos       ff = fopen (dup_name, "rb");
1284e98e3e1Schristos       if (ff)
1294e98e3e1Schristos 	break;
1304e98e3e1Schristos       /* free (dup_name); */
1314e98e3e1Schristos       if (include->next == NULL)
1324e98e3e1Schristos 	{
1334e98e3e1Schristos 	  if (line != NULL)
1344e98e3e1Schristos 	    error (line, "Problem opening file `%s'\n", file_name);
1354e98e3e1Schristos 	  perror (file_name);
1364e98e3e1Schristos 	  exit (1);
1374e98e3e1Schristos 	}
1384e98e3e1Schristos       include = include->next;
1394e98e3e1Schristos     }
1404e98e3e1Schristos 
1414e98e3e1Schristos 
1424e98e3e1Schristos   /* determine the size */
1434e98e3e1Schristos   fseek (ff, 0, SEEK_END);
1444e98e3e1Schristos   file->size = ftell (ff);
1454e98e3e1Schristos   fseek (ff, 0, SEEK_SET);
1464e98e3e1Schristos 
1474e98e3e1Schristos   /* allocate this much memory */
1484e98e3e1Schristos   file->buffer = (char *) zalloc (file->size + 1);
1494e98e3e1Schristos   if (file->buffer == NULL)
1504e98e3e1Schristos     {
1514e98e3e1Schristos       perror (file_name);
1524e98e3e1Schristos       exit (1);
1534e98e3e1Schristos     }
1544e98e3e1Schristos   file->pos = file->buffer;
1554e98e3e1Schristos 
1564e98e3e1Schristos   /* read it all in */
1574e98e3e1Schristos   if (fread (file->buffer, 1, file->size, ff) < file->size)
1584e98e3e1Schristos     {
1594e98e3e1Schristos       perror (file_name);
1604e98e3e1Schristos       exit (1);
1614e98e3e1Schristos     }
1624e98e3e1Schristos   file->buffer[file->size] = '\0';
1634e98e3e1Schristos 
1644e98e3e1Schristos   /* set the initial line numbering */
1654e98e3e1Schristos   file->real_line.line_nr = 1;	/* specifies current line */
1664e98e3e1Schristos   file->pseudo_line.line_nr = 1;	/* specifies current line */
1674e98e3e1Schristos 
1684e98e3e1Schristos   /* done */
1694e98e3e1Schristos   fclose (ff);
1704e98e3e1Schristos }
1714e98e3e1Schristos 
1724e98e3e1Schristos table *
1734e98e3e1Schristos table_open (const char *file_name)
1744e98e3e1Schristos {
1754e98e3e1Schristos   table *root;
1764e98e3e1Schristos 
1774e98e3e1Schristos   /* create a file descriptor */
1784e98e3e1Schristos   root = ZALLOC (table);
1794e98e3e1Schristos   if (root == NULL)
1804e98e3e1Schristos     {
1814e98e3e1Schristos       perror (file_name);
1824e98e3e1Schristos       exit (1);
1834e98e3e1Schristos     }
1844e98e3e1Schristos 
1854e98e3e1Schristos   table_push (root, NULL, NULL, file_name);
1864e98e3e1Schristos   return root;
1874e98e3e1Schristos }
1884e98e3e1Schristos 
1894e98e3e1Schristos char *
1904e98e3e1Schristos skip_spaces (char *chp)
1914e98e3e1Schristos {
1924e98e3e1Schristos   while (1)
1934e98e3e1Schristos     {
1944e98e3e1Schristos       if (*chp == '\0' || *chp == '\n' || !isspace (*chp))
1954e98e3e1Schristos 	return chp;
1964e98e3e1Schristos       chp++;
1974e98e3e1Schristos     }
1984e98e3e1Schristos }
1994e98e3e1Schristos 
2004e98e3e1Schristos 
2014e98e3e1Schristos char *
2024e98e3e1Schristos back_spaces (char *start, char *chp)
2034e98e3e1Schristos {
2044e98e3e1Schristos   while (1)
2054e98e3e1Schristos     {
2064e98e3e1Schristos       if (chp <= start || !isspace (chp[-1]))
2074e98e3e1Schristos 	return chp;
2084e98e3e1Schristos       chp--;
2094e98e3e1Schristos     }
2104e98e3e1Schristos }
2114e98e3e1Schristos 
2124e98e3e1Schristos char *
2134e98e3e1Schristos skip_digits (char *chp)
2144e98e3e1Schristos {
2154e98e3e1Schristos   while (1)
2164e98e3e1Schristos     {
2174e98e3e1Schristos       if (*chp == '\0' || *chp == '\n' || !isdigit (*chp))
2184e98e3e1Schristos 	return chp;
2194e98e3e1Schristos       chp++;
2204e98e3e1Schristos     }
2214e98e3e1Schristos }
2224e98e3e1Schristos 
2234e98e3e1Schristos char *
2244e98e3e1Schristos skip_to_separator (char *chp, char *separators)
2254e98e3e1Schristos {
2264e98e3e1Schristos   while (1)
2274e98e3e1Schristos     {
2284e98e3e1Schristos       char *sep = separators;
2294e98e3e1Schristos       while (1)
2304e98e3e1Schristos 	{
2314e98e3e1Schristos 	  if (*chp == *sep)
2324e98e3e1Schristos 	    return chp;
2334e98e3e1Schristos 	  if (*sep == '\0')
2344e98e3e1Schristos 	    break;
2354e98e3e1Schristos 	  sep++;
2364e98e3e1Schristos 	}
2374e98e3e1Schristos       chp++;
2384e98e3e1Schristos     }
2394e98e3e1Schristos }
2404e98e3e1Schristos 
2414e98e3e1Schristos static char *
2424e98e3e1Schristos skip_to_null (char *chp)
2434e98e3e1Schristos {
2444e98e3e1Schristos   return skip_to_separator (chp, "");
2454e98e3e1Schristos }
2464e98e3e1Schristos 
2474e98e3e1Schristos 
2484e98e3e1Schristos static char *
2494e98e3e1Schristos skip_to_nl (char *chp)
2504e98e3e1Schristos {
2514e98e3e1Schristos   return skip_to_separator (chp, "\n");
2524e98e3e1Schristos }
2534e98e3e1Schristos 
2544e98e3e1Schristos 
2554e98e3e1Schristos static void
2564e98e3e1Schristos next_line (open_table * file)
2574e98e3e1Schristos {
2584e98e3e1Schristos   file->pos = skip_to_nl (file->pos);
2594e98e3e1Schristos   if (*file->pos == '0')
2604e98e3e1Schristos     error (&file->pseudo_line, "Missing <nl> at end of line\n");
2614e98e3e1Schristos   *file->pos = '\0';
2624e98e3e1Schristos   file->pos += 1;
2634e98e3e1Schristos   file->real_line.line_nr += 1;
2644e98e3e1Schristos   file->pseudo_line.line_nr += 1;
2654e98e3e1Schristos }
2664e98e3e1Schristos 
2674e98e3e1Schristos 
2684e98e3e1Schristos extern table_entry *
2694e98e3e1Schristos table_read (table *root)
2704e98e3e1Schristos {
2714e98e3e1Schristos   open_table *file = root->current;
2724e98e3e1Schristos   table_entry *entry = NULL;
2734e98e3e1Schristos   while (1)
2744e98e3e1Schristos     {
2754e98e3e1Schristos 
2764e98e3e1Schristos       /* end-of-file? */
2774e98e3e1Schristos       while (*file->pos == '\0')
2784e98e3e1Schristos 	{
2794e98e3e1Schristos 	  if (file->parent != NULL)
2804e98e3e1Schristos 	    {
2814e98e3e1Schristos 	      file = file->parent;
2824e98e3e1Schristos 	      root->current = file;
2834e98e3e1Schristos 	    }
2844e98e3e1Schristos 	  else
2854e98e3e1Schristos 	    return NULL;
2864e98e3e1Schristos 	}
2874e98e3e1Schristos 
2884e98e3e1Schristos       /* code_block? */
2894e98e3e1Schristos       if (*file->pos == '{')
2904e98e3e1Schristos 	{
2914e98e3e1Schristos 	  char *chp;
2924e98e3e1Schristos 	  next_line (file);	/* discard leading brace */
2934e98e3e1Schristos 	  entry = new_table_entry (file, table_code_entry);
2944e98e3e1Schristos 	  chp = file->pos;
2954e98e3e1Schristos 	  /* determine how many lines are involved - look for <nl> "}" */
2964e98e3e1Schristos 	  {
2974e98e3e1Schristos 	    int nr_lines = 0;
2984e98e3e1Schristos 	    while (*file->pos != '}')
2994e98e3e1Schristos 	      {
3004e98e3e1Schristos 		next_line (file);
3014e98e3e1Schristos 		nr_lines++;
3024e98e3e1Schristos 	      }
3034e98e3e1Schristos 	    set_nr_table_entry_fields (entry, nr_lines);
3044e98e3e1Schristos 	  }
3054e98e3e1Schristos 	  /* now enter each line */
3064e98e3e1Schristos 	  {
3074e98e3e1Schristos 	    int line_nr;
3084e98e3e1Schristos 	    for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
3094e98e3e1Schristos 	      {
3104e98e3e1Schristos 		if (strncmp (chp, "  ", 2) == 0)
3114e98e3e1Schristos 		  entry->field[line_nr] = chp + 2;
3124e98e3e1Schristos 		else
3134e98e3e1Schristos 		  entry->field[line_nr] = chp;
3144e98e3e1Schristos 		chp = skip_to_null (chp) + 1;
3154e98e3e1Schristos 	      }
3164e98e3e1Schristos 	    /* skip trailing brace */
3174e98e3e1Schristos 	    ASSERT (*file->pos == '}');
3184e98e3e1Schristos 	    next_line (file);
3194e98e3e1Schristos 	  }
3204e98e3e1Schristos 	  break;
3214e98e3e1Schristos 	}
3224e98e3e1Schristos 
3234e98e3e1Schristos       /* tab block? */
3244e98e3e1Schristos       if (*file->pos == '\t')
3254e98e3e1Schristos 	{
3264e98e3e1Schristos 	  char *chp = file->pos;
3274e98e3e1Schristos 	  entry = new_table_entry (file, table_code_entry);
3284e98e3e1Schristos 	  /* determine how many lines are involved - look for <nl> !<tab> */
3294e98e3e1Schristos 	  {
3304e98e3e1Schristos 	    int nr_lines = 0;
3314e98e3e1Schristos 	    int nr_blank_lines = 0;
3324e98e3e1Schristos 	    while (1)
3334e98e3e1Schristos 	      {
3344e98e3e1Schristos 		if (*file->pos == '\t')
3354e98e3e1Schristos 		  {
3364e98e3e1Schristos 		    nr_lines = nr_lines + nr_blank_lines + 1;
3374e98e3e1Schristos 		    nr_blank_lines = 0;
3384e98e3e1Schristos 		    next_line (file);
3394e98e3e1Schristos 		  }
3404e98e3e1Schristos 		else
3414e98e3e1Schristos 		  {
3424e98e3e1Schristos 		    file->pos = skip_spaces (file->pos);
3434e98e3e1Schristos 		    if (*file->pos != '\n')
3444e98e3e1Schristos 		      break;
3454e98e3e1Schristos 		    nr_blank_lines++;
3464e98e3e1Schristos 		    next_line (file);
3474e98e3e1Schristos 		  }
3484e98e3e1Schristos 	      }
3494e98e3e1Schristos 	    set_nr_table_entry_fields (entry, nr_lines);
3504e98e3e1Schristos 	  }
3514e98e3e1Schristos 	  /* now enter each line */
3524e98e3e1Schristos 	  {
3534e98e3e1Schristos 	    int line_nr;
3544e98e3e1Schristos 	    for (line_nr = 0; line_nr < entry->nr_fields; line_nr++)
3554e98e3e1Schristos 	      {
3564e98e3e1Schristos 		if (*chp == '\t')
3574e98e3e1Schristos 		  entry->field[line_nr] = chp + 1;
3584e98e3e1Schristos 		else
3594e98e3e1Schristos 		  entry->field[line_nr] = "";	/* blank */
3604e98e3e1Schristos 		chp = skip_to_null (chp) + 1;
3614e98e3e1Schristos 	      }
3624e98e3e1Schristos 	  }
3634e98e3e1Schristos 	  break;
3644e98e3e1Schristos 	}
3654e98e3e1Schristos 
3664e98e3e1Schristos       /* cpp directive? */
3674e98e3e1Schristos       if (file->pos[0] == '#')
3684e98e3e1Schristos 	{
3694e98e3e1Schristos 	  char *chp = skip_spaces (file->pos + 1);
3704e98e3e1Schristos 
3714e98e3e1Schristos 	  /* cpp line-nr directive - # <line-nr> "<file>" */
3724e98e3e1Schristos 	  if (isdigit (*chp)
3734e98e3e1Schristos 	      && *skip_digits (chp) == ' '
3744e98e3e1Schristos 	      && *skip_spaces (skip_digits (chp)) == '"')
3754e98e3e1Schristos 	    {
3764e98e3e1Schristos 	      int line_nr;
3774e98e3e1Schristos 	      char *file_name;
3784e98e3e1Schristos 	      file->pos = chp;
3794e98e3e1Schristos 	      /* parse the number */
3804e98e3e1Schristos 	      line_nr = atoi (file->pos) - 1;
3814e98e3e1Schristos 	      /* skip to the file name */
3824e98e3e1Schristos 	      while (file->pos[0] != '0'
3834e98e3e1Schristos 		     && file->pos[0] != '"' && file->pos[0] != '\0')
3844e98e3e1Schristos 		file->pos++;
3854e98e3e1Schristos 	      if (file->pos[0] != '"')
3864e98e3e1Schristos 		error (&file->real_line,
3874e98e3e1Schristos 		       "Missing opening quote in cpp directive\n");
3884e98e3e1Schristos 	      /* parse the file name */
3894e98e3e1Schristos 	      file->pos++;
3904e98e3e1Schristos 	      file_name = file->pos;
3914e98e3e1Schristos 	      while (file->pos[0] != '"' && file->pos[0] != '\0')
3924e98e3e1Schristos 		file->pos++;
3934e98e3e1Schristos 	      if (file->pos[0] != '"')
3944e98e3e1Schristos 		error (&file->real_line,
3954e98e3e1Schristos 		       "Missing closing quote in cpp directive\n");
3964e98e3e1Schristos 	      file->pos[0] = '\0';
3974e98e3e1Schristos 	      file->pos++;
3984e98e3e1Schristos 	      file->pos = skip_to_nl (file->pos);
3994e98e3e1Schristos 	      if (file->pos[0] != '\n')
4004e98e3e1Schristos 		error (&file->real_line,
4014e98e3e1Schristos 		       "Missing newline in cpp directive\n");
4024e98e3e1Schristos 	      file->pseudo_line.file_name = file_name;
4034e98e3e1Schristos 	      file->pseudo_line.line_nr = line_nr;
4044e98e3e1Schristos 	      next_line (file);
4054e98e3e1Schristos 	      continue;
4064e98e3e1Schristos 	    }
4074e98e3e1Schristos 
4084e98e3e1Schristos 	  /* #define and #undef - not implemented yet */
4094e98e3e1Schristos 
4104e98e3e1Schristos 	  /* Old style # comment */
4114e98e3e1Schristos 	  next_line (file);
4124e98e3e1Schristos 	  continue;
4134e98e3e1Schristos 	}
4144e98e3e1Schristos 
4154e98e3e1Schristos       /* blank line or end-of-file? */
4164e98e3e1Schristos       file->pos = skip_spaces (file->pos);
4174e98e3e1Schristos       if (*file->pos == '\0')
4184e98e3e1Schristos 	error (&file->pseudo_line, "Missing <nl> at end of file\n");
4194e98e3e1Schristos       if (*file->pos == '\n')
4204e98e3e1Schristos 	{
4214e98e3e1Schristos 	  next_line (file);
4224e98e3e1Schristos 	  continue;
4234e98e3e1Schristos 	}
4244e98e3e1Schristos 
4254e98e3e1Schristos       /* comment - leading // or # - skip */
4264e98e3e1Schristos       if ((file->pos[0] == '/' && file->pos[1] == '/')
4274e98e3e1Schristos 	  || (file->pos[0] == '#'))
4284e98e3e1Schristos 	{
4294e98e3e1Schristos 	  next_line (file);
4304e98e3e1Schristos 	  continue;
4314e98e3e1Schristos 	}
4324e98e3e1Schristos 
4334e98e3e1Schristos       /* colon field */
4344e98e3e1Schristos       {
4354e98e3e1Schristos 	char *chp = file->pos;
4364e98e3e1Schristos 	entry = new_table_entry (file, table_colon_entry);
4374e98e3e1Schristos 	next_line (file);
4384e98e3e1Schristos 	/* figure out how many fields */
4394e98e3e1Schristos 	{
4404e98e3e1Schristos 	  int nr_fields = 1;
4414e98e3e1Schristos 	  char *tmpch = chp;
4424e98e3e1Schristos 	  while (1)
4434e98e3e1Schristos 	    {
4444e98e3e1Schristos 	      tmpch = skip_to_separator (tmpch, "\\:");
4454e98e3e1Schristos 	      if (*tmpch == '\\')
4464e98e3e1Schristos 		{
4474e98e3e1Schristos 		  /* eat the escaped character */
4484e98e3e1Schristos 		  char *cp = tmpch;
4494e98e3e1Schristos 		  while (cp[1] != '\0')
4504e98e3e1Schristos 		    {
4514e98e3e1Schristos 		      cp[0] = cp[1];
4524e98e3e1Schristos 		      cp++;
4534e98e3e1Schristos 		    }
4544e98e3e1Schristos 		  cp[0] = '\0';
4554e98e3e1Schristos 		  tmpch++;
4564e98e3e1Schristos 		}
4574e98e3e1Schristos 	      else if (*tmpch != ':')
4584e98e3e1Schristos 		break;
4594e98e3e1Schristos 	      else
4604e98e3e1Schristos 		{
4614e98e3e1Schristos 		  *tmpch = '\0';
4624e98e3e1Schristos 		  tmpch++;
4634e98e3e1Schristos 		  nr_fields++;
4644e98e3e1Schristos 		}
4654e98e3e1Schristos 	    }
4664e98e3e1Schristos 	  set_nr_table_entry_fields (entry, nr_fields);
4674e98e3e1Schristos 	}
4684e98e3e1Schristos 	/* now parse them */
4694e98e3e1Schristos 	{
4704e98e3e1Schristos 	  int field_nr;
4714e98e3e1Schristos 	  for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
4724e98e3e1Schristos 	    {
4734e98e3e1Schristos 	      chp = skip_spaces (chp);
4744e98e3e1Schristos 	      entry->field[field_nr] = chp;
4754e98e3e1Schristos 	      chp = skip_to_null (chp);
4764e98e3e1Schristos 	      *back_spaces (entry->field[field_nr], chp) = '\0';
4774e98e3e1Schristos 	      chp++;
4784e98e3e1Schristos 	    }
4794e98e3e1Schristos 	}
4804e98e3e1Schristos 	break;
4814e98e3e1Schristos       }
4824e98e3e1Schristos 
4834e98e3e1Schristos     }
4844e98e3e1Schristos 
4854e98e3e1Schristos   ASSERT (entry == NULL || entry->field[entry->nr_fields] == NULL);
4864e98e3e1Schristos   return entry;
4874e98e3e1Schristos }
4884e98e3e1Schristos 
4894e98e3e1Schristos extern void
4904b169a6bSchristos table_print_code (lf *file, const table_entry *entry)
4914e98e3e1Schristos {
4924e98e3e1Schristos   int field_nr;
4934e98e3e1Schristos   for (field_nr = 0; field_nr < entry->nr_fields; field_nr++)
4944e98e3e1Schristos     {
4954e98e3e1Schristos       char *chp = entry->field[field_nr];
4964e98e3e1Schristos       int in_bit_field = 0;
4974e98e3e1Schristos       if (*chp == '#')
4984e98e3e1Schristos 	lf_indent_suppress (file);
4994e98e3e1Schristos       while (*chp != '\0')
5004e98e3e1Schristos 	{
5014e98e3e1Schristos 	  if (chp[0] == '{' && !isspace (chp[1]) && chp[1] != '\0')
5024e98e3e1Schristos 	    {
5034e98e3e1Schristos 	      in_bit_field = 1;
504*71f62182Schristos 	      lf_putchr (file, '_');
5054e98e3e1Schristos 	    }
5064e98e3e1Schristos 	  else if (in_bit_field && chp[0] == ':')
5074e98e3e1Schristos 	    {
508*71f62182Schristos 	      lf_putchr (file, '_');
5094e98e3e1Schristos 	    }
5104e98e3e1Schristos 	  else if (in_bit_field && *chp == '}')
5114e98e3e1Schristos 	    {
512*71f62182Schristos 	      lf_putchr (file, '_');
5134e98e3e1Schristos 	      in_bit_field = 0;
5144e98e3e1Schristos 	    }
5154e98e3e1Schristos 	  else
5164e98e3e1Schristos 	    {
517*71f62182Schristos 	      lf_putchr (file, *chp);
5184e98e3e1Schristos 	    }
5194e98e3e1Schristos 	  chp++;
5204e98e3e1Schristos 	}
5214e98e3e1Schristos       if (in_bit_field)
5224e98e3e1Schristos 	{
5234e98e3e1Schristos 	  line_ref line = *entry->line;
5244e98e3e1Schristos 	  line.line_nr += field_nr;
5254e98e3e1Schristos 	  error (&line, "Bit field brace miss match\n");
5264e98e3e1Schristos 	}
527*71f62182Schristos       lf_putchr (file, '\n');
5284e98e3e1Schristos     }
5294e98e3e1Schristos }
5304e98e3e1Schristos 
5314e98e3e1Schristos 
5324e98e3e1Schristos void
5334b169a6bSchristos dump_line_ref (lf *file,
5344b169a6bSchristos 	       const char *prefix,
5354b169a6bSchristos 	       const line_ref *line,
5364b169a6bSchristos 	       const char *suffix)
5374e98e3e1Schristos {
5384b169a6bSchristos   lf_printf (file, "%s(line_ref*) %p", prefix, line);
5394e98e3e1Schristos   if (line != NULL)
5404e98e3e1Schristos     {
5414e98e3e1Schristos       lf_indent (file, +1);
5424e98e3e1Schristos       lf_printf (file, "\n(line_nr %d)", line->line_nr);
5434e98e3e1Schristos       lf_printf (file, "\n(file_name %s)", line->file_name);
5444e98e3e1Schristos       lf_indent (file, -1);
5454e98e3e1Schristos     }
5464e98e3e1Schristos   lf_printf (file, "%s", suffix);
5474e98e3e1Schristos }
5484e98e3e1Schristos 
5494e98e3e1Schristos 
5504e98e3e1Schristos static const char *
5514e98e3e1Schristos table_entry_type_to_str (table_entry_type type)
5524e98e3e1Schristos {
5534e98e3e1Schristos   switch (type)
5544e98e3e1Schristos     {
5554e98e3e1Schristos     case table_code_entry:
5564e98e3e1Schristos       return "code-entry";
5574e98e3e1Schristos     case table_colon_entry:
5584e98e3e1Schristos       return "colon-entry";
5594e98e3e1Schristos     }
5604e98e3e1Schristos   return "*invalid*";
5614e98e3e1Schristos }
5624e98e3e1Schristos 
5634e98e3e1Schristos void
5644e98e3e1Schristos dump_table_entry (lf *file,
5654b169a6bSchristos 		  const char *prefix,
5664b169a6bSchristos 		  const table_entry *entry,
5674b169a6bSchristos 		  const char *suffix)
5684e98e3e1Schristos {
5694b169a6bSchristos   lf_printf (file, "%s(table_entry*) %p", prefix, entry);
5704e98e3e1Schristos   if (entry != NULL)
5714e98e3e1Schristos     {
5724e98e3e1Schristos       int field;
5734e98e3e1Schristos       lf_indent (file, +1);
5744e98e3e1Schristos       dump_line_ref (file, "\n(line ", entry->line, ")");
5754e98e3e1Schristos       lf_printf (file, "\n(type %s)", table_entry_type_to_str (entry->type));
5764e98e3e1Schristos       lf_printf (file, "\n(nr_fields %d)", entry->nr_fields);
5774e98e3e1Schristos       lf_printf (file, "\n(fields");
5784e98e3e1Schristos       lf_indent (file, +1);
5794e98e3e1Schristos       for (field = 0; field < entry->nr_fields; field++)
5804e98e3e1Schristos 	lf_printf (file, "\n\"%s\"", entry->field[field]);
5814e98e3e1Schristos       lf_indent (file, -1);
5824e98e3e1Schristos       lf_printf (file, ")");
5834e98e3e1Schristos       lf_indent (file, -1);
5844e98e3e1Schristos     }
5854e98e3e1Schristos   lf_printf (file, "%s", suffix);
5864e98e3e1Schristos }
5874e98e3e1Schristos 
5884e98e3e1Schristos 
5894e98e3e1Schristos #ifdef MAIN
5904e98e3e1Schristos int
5914e98e3e1Schristos main (int argc, char **argv)
5924e98e3e1Schristos {
5934e98e3e1Schristos   table *t;
5944e98e3e1Schristos   table_entry *entry;
5954e98e3e1Schristos   lf *l;
5964e98e3e1Schristos   int line_nr;
5974e98e3e1Schristos 
5984e98e3e1Schristos   if (argc != 2)
5994e98e3e1Schristos     {
6004e98e3e1Schristos       printf ("Usage: table <file>\n");
6014e98e3e1Schristos       exit (1);
6024e98e3e1Schristos     }
6034e98e3e1Schristos 
6044e98e3e1Schristos   t = table_open (argv[1]);
6054e98e3e1Schristos   l = lf_open ("-", "stdout", lf_omit_references, lf_is_text, "tmp-table");
6064e98e3e1Schristos 
6074e98e3e1Schristos   line_nr = 0;
6084e98e3e1Schristos   do
6094e98e3e1Schristos     {
6104e98e3e1Schristos       char line[10];
6114e98e3e1Schristos       entry = table_read (t);
6124e98e3e1Schristos       line_nr++;
6134e98e3e1Schristos       sprintf (line, "(%d ", line_nr);
6144e98e3e1Schristos       dump_table_entry (l, line, entry, ")\n");
6154e98e3e1Schristos     }
6164e98e3e1Schristos   while (entry != NULL);
6174e98e3e1Schristos 
6184e98e3e1Schristos   return 0;
6194e98e3e1Schristos }
6204e98e3e1Schristos #endif
621