home *** CD-ROM | disk | FTP | other *** search
- /* $Id: tabutil.c,v 1.2 1999/11/04 14:02:23 shields Exp $ */
- /*
- This software is subject to the terms of the IBM Jikes Compiler
- License Agreement available at the following URL:
- http://www.ibm.com/research/jikes.
- Copyright (C) 1983, 1999, International Business Machines Corporation
- and others. All Rights Reserved.
- You must accept the terms of that agreement to use this software.
- */
- static char hostfile[] = __FILE__;
-
- #include <string.h>
- #include "common.h"
- #include "header.h"
-
- static const char digits[] = "0123456789";
-
- /**************************************************************************/
- /* PRNT_SHORTS: */
- /**************************************************************************/
- void prnt_shorts(char *title, int init, int bound, int perline, short *array)
- {
- int i,
- k;
-
- mystrcpy(title);
-
- padline();
- k = 0;
- for (i = init; i <= bound; i++)
- {
- itoc(array[i]);
- *output_ptr++ = COMMA;
- k++;
- if (k == perline && i != bound)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(sysdcl);
- padline();
- k = 0;
- }
- }
- if (k != 0)
- {
- *(output_ptr - 1) = '\n';
- BUFFER_CHECK(sysdcl);
- }
-
- if (java_bit)
- mystrcpy(" };\n");
- else mystrcpy(" };\n");
-
- return;
- }
-
-
- /**************************************************************************/
- /* PRNT_INTS: */
- /**************************************************************************/
- void prnt_ints(char *title, int init, int bound, int perline, int *array)
- {
- int i,
- k;
-
- mystrcpy(title);
-
- padline();
- k = 0;
- for (i = init; i <= bound; i++)
- {
- itoc(array[i]);
- *output_ptr++ = COMMA;
- k++;
- if (k == perline && i != bound)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(sysdcl);
- padline();
- k = 0;
- }
- }
- if (k != 0)
- {
- *(output_ptr - 1) = '\n';
- BUFFER_CHECK(sysdcl);
- }
-
- if (java_bit)
- mystrcpy(" };\n");
- else mystrcpy(" };\n");
-
- return;
- }
-
-
- /***************************************************************************/
- /* MYSTRCPY: */
- /***************************************************************************/
- void mystrcpy(char *str)
- {
- while (*str != '\0')
- *output_ptr++ = *str++;
-
- BUFFER_CHECK(sysdcl);
-
- return;
- }
-
-
- /***************************************************************************/
- /* PADLINE: */
- /***************************************************************************/
- void padline(void)
- {
- register int i;
-
- for (i = 0; i < 12; i++)
- *output_ptr++ = ' ';
-
- return;
- }
-
-
- /***************************************************************************/
- /* ITOC: */
- /***************************************************************************/
- /* ITOC takes as arguments an integer NUM. NUM is an integer containing at */
- /* most 11 digits which is converted into a character string and placed in */
- /* the iobuffer. Leading zeros are eliminated and if the number is */
- /* negative, a leading "-" is added. */
- /***************************************************************************/
- void itoc(int num)
- {
- register int val;
- register char *p;
- char tmp[12];
-
- val = ABS(num);
- tmp[11] = '\0';
- p = &tmp[11];
- do
- {
- p--;
- *p = digits[val % 10];
- val /= 10;
- } while(val > 0);
-
- if (num < 0)
- {
- p--;
- *p = '-';
- }
-
- while(*p != '\0')
- *(output_ptr++) = *(p++);
-
- return;
- }
-
-
- /***************************************************************************/
- /* FIELD: */
- /***************************************************************************/
- /* FIELD takes as arguments two integers: NUM and LEN. NUM is an integer */
- /* containing at most LEN digits which is converted into a character */
- /* string and placed in the iobuffer. */
- /* Leading zeros are replaced by blanks and if the number is negative, a */
- /* leading "-" is added. */
- /***************************************************************************/
- void field(int num, int len)
- {
- register int val;
- register char *p;
-
- val = ABS(num);
- p = output_ptr + len;
- do
- {
- p--;
- *p = digits[val % 10];
- val /= 10;
- } while(val > 0 && p > output_ptr);
-
- if (num < 0 && p > output_ptr)
- {
- p--;
- *p = '-';
- }
-
- while(p > output_ptr)
- {
- p--;
- *p = ' ';
- }
-
- output_ptr += len;
-
- return;
- }
-
-
- /***************************************************************************/
- /* SORTDES: */
- /***************************************************************************/
- /* SORTDES sorts the elements of ARRAY and COUNT in the range LOW..HIGH */
- /* based on the values of the elements of COUNT. Knowing that the maximum */
- /* value of the elements of count cannot exceed MAX and cannot be lower */
- /* than zero, we can use a bucket sort technique. */
- /***************************************************************************/
- void sortdes(short array[], short count[], int low, int high, int max)
- {
- short *bucket,
- *list;
-
- register int element,
- i,
- k;
-
- /*****************************************************************/
- /* BUCKET is used to hold the roots of lists that contain the */
- /* elements of each bucket. LIST is used to hold these lists. */
- /*****************************************************************/
- bucket = Allocate_short_array(max + 1);
- list = Allocate_short_array(high - low + 1);
-
- for (i = 0; i <= max; i++)
- bucket[i] = NIL;
-
- /*********************************************************************/
- /* We now partition the elements to be sorted and place them in their*/
- /* respective buckets. We iterate backward over ARRAY and COUNT to */
- /* keep the sorting stable since elements are inserted in the buckets*/
- /* in stack-fashion. */
- /* */
- /* NOTE that it is known that the values of the elements of ARRAY */
- /* also lie in the range LOW..HIGH. */
- /*********************************************************************/
- for (i = high; i >= low; i--)
- {
- k = count[i];
- element = array[i];
- list[element - low] = bucket[k];
- bucket[k] = element;
- }
-
- /*********************************************************************/
- /* Iterate over each bucket, and place elements in ARRAY and COUNT */
- /* in sorted order. The iteration is done backward because we want */
- /* the arrays sorted in descending order. */
- /*********************************************************************/
- k = low;
- for (i = max; i >= 0; i--)
- {
- for (element = bucket[i];
- element != NIL; element = list[element - low], k++)
- {
- array[k] = element;
- count[k] = i;
- }
- }
- ffree(bucket);
- ffree(list);
-
- return;
- }
-
-
- /***************************************************************************/
- /* REALLOCATE: */
- /***************************************************************************/
- /* This procedure is invoked when the TABLE being used is not large */
- /* enough. A new table is allocated, the information from the old table */
- /* is copied, and the old space is released. */
- /***************************************************************************/
- void reallocate(void)
- {
- int *n,
- *p;
-
- register int old_size,
- i;
-
- if (table_size == MAX_TABLE_SIZE)
- {
- sprintf(msg_line, "Table has exceeded maximum limit of %d",
- MAX_TABLE_SIZE);
- PRNTERR(msg_line);
- exit(12);
- }
-
- old_size = table_size;
- table_size = MIN(table_size + increment_size, MAX_TABLE_SIZE);
-
- if (verbose_bit)
- {
- if (table_opt == OPTIMIZE_TIME)
- {
- sprintf(msg_line,
- "Reallocating storage for TIME table, "
- "adding %d entries", table_size - old_size);
- }
- else
- {
- sprintf(msg_line,
- "Reallocating storage for SPACE table, "
- "adding %d entries", table_size - old_size);
- }
- PRNT(msg_line);
- }
-
- n = Allocate_int_array(table_size + 1);
- p = Allocate_int_array(table_size + 1);
-
- for (i = 1; i <= old_size; i++) /* Copy old information */
- {
- n[i] = next[i];
- p[i] = previous[i];
- }
-
- ffree(next);
- ffree(previous);
-
- next = n;
- previous = p;
-
- if (first_index == NIL)
- {
- first_index = old_size + 1;
- previous[first_index] = NIL;
- }
- else
- {
- next[last_index] = old_size + 1;
- previous[old_size + 1] = last_index;
- }
-
- next[old_size + 1] = old_size + 2;
- for (i = old_size + 2; i < (int) table_size; i++)
- {
- next[i] = i + 1;
- previous[i] = i - 1;
- }
- last_index = table_size;
- next[last_index] = NIL;
- previous[last_index] = last_index - 1;
-
- return;
- }
-
-
- /*****************************************************************************/
- /* PROCESS_ERROR_MAPS: */
- /*****************************************************************************/
- /* if ERROR_MAPS are requested, we print them out in the following order: */
- /* */
- /* 1) The FOLLOW map (NEWFOLL) */
- /* 2) The SORTED_STATE vector */
- /* 3) The ORIGINAL_STATE vector */
- /* 4) The map from states into valid symbols on which actions are */
- /* defined within the state in question: ACTION_SYMBOLS */
- /* 5) The map from each symbol into the set of staes that can */
- /* possibly be reached after a transition on the symbol in */
- /* question: TRANSITION_STATES */
- /* */
- /*****************************************************************************/
- void process_error_maps(void)
- {
- short *state_start,
- *state_stack,
- *temp,
- *original = NULL,
- *symbol_root,
- *symbol_count,
- *term_list,
- *as_size,
- *action_symbols_range,
- *naction_symbols_range;
-
- int offset,
- item_no,
- lhs_symbol,
- state_no,
- symbol,
- max_len,
- i,
- k,
-
- terminal_ubound,
- non_terminal_ubound;
-
- long num_bytes;
-
- char tok[SYMBOL_SIZE + 1];
-
- terminal_ubound = (table_opt == OPTIMIZE_TIME
- ? num_symbols
- : num_terminals);
-
- non_terminal_ubound = (table_opt == OPTIMIZE_TIME
- ? num_symbols
- : num_non_terminals);
-
- symbol_root = Allocate_short_array(num_symbols + 1);
- symbol_count = Allocate_short_array(num_symbols + 1);
- state_start = Allocate_short_array(num_states + 2);
- state_stack = Allocate_short_array(num_states + 1);
- term_list = Allocate_short_array(num_symbols + 1);
-
- PRNT("\nError maps storage:");
-
- /*********************************************************************/
- /* The FOLLOW map is written out as two vectors where the first */
- /* vector indexed by a Symbol gives the starting location in the */
- /* second vector where the elements of the follow set of that symbol */
- /* starts. Note that since the terminal and non-terminal symbols */
- /* have been intermixed, the FOLLOW map is written out with the */
- /* complete set of symbols as its domain even though it is only */
- /* defined on non-terminals. */
- /* */
- /* We now compute and write the starting location for each symbol. */
- /* The offset for the first symbol is 1, and hence does not */
- /* have to be computed. However, we compute an extra offset to */
- /* indicate the extent of the last symbol. */
- /*********************************************************************/
- for (symbol = 1; symbol <= non_terminal_ubound; symbol++)
- {
- symbol_count[symbol] = 0;
- symbol_root[symbol] = OMEGA;
- }
-
- for ALL_NON_TERMINALS(lhs_symbol)
- {
- if (table_opt == OPTIMIZE_TIME)
- symbol = symbol_map[lhs_symbol];
- else
- symbol = symbol_map[lhs_symbol] - num_terminals;
- symbol_root[symbol] = lhs_symbol;
- for ALL_TERMINALS(i)
- {
- if IS_IN_SET(follow, (lhs_symbol + 1), (i + 1))
- symbol_count[symbol]++;
- }
- }
-
- offset = 1;
- k = 1;
- field(offset, 6); /* Offset of the first state */
- for (symbol = 1; symbol <= non_terminal_ubound; symbol++)
- {
- offset += symbol_count[symbol];
- field(offset, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /***************************************************************/
- /* We now write the elements in the range of the FOLLOW map. */
- /***************************************************************/
- k = 0;
- for (symbol = 1; symbol <= non_terminal_ubound; symbol++)
- {
- lhs_symbol = symbol_root[symbol];
- if (lhs_symbol != OMEGA)
- {
- for ALL_TERMINALS(i)
- {
- if IS_IN_SET(follow, (lhs_symbol + 1), (i + 1))
- {
- field(symbol_map[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- }
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*****************************************************************/
- /* Compute and list amount of space required for the Follow map. */
- /*****************************************************************/
- if (table_opt == OPTIMIZE_TIME)
- {
- num_bytes = 2 * (num_symbols + offset);
- if (byte_bit)
- {
- if (last_non_terminal <= 255)
- num_bytes = num_bytes - offset + 1;
- }
- }
- else
- {
- num_bytes = 2 * (num_non_terminals + offset);
- if (byte_bit)
- {
- if (num_terminals <= 255)
- num_bytes = num_bytes - offset + 1;
- }
- }
- sprintf(msg_line,
- " Storage required for FOLLOW map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
-
- /**************************************************************/
- /* We now write out the states in sorted order: SORTED_STATE. */
- /**************************************************************/
- k = 0;
- for ALL_STATES(i)
- {
- field(ordered_state[i], 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*****************************************************************/
- /* Compute and list space required for SORTED_STATE map. */
- /*****************************************************************/
- num_bytes = 2 * num_states;
- sprintf(msg_line,
- " Storage required for SORTED_STATE map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
-
- /********************************************************************/
- /* We now write a vector parallel to SORTED_STATE that gives us the */
- /* original number associated with the state: ORIGINAL_STATE. */
- /********************************************************************/
- k = 0;
- for (i = 1; i <= (int) num_states; i++)
- {
- field(state_list[i], 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*****************************************************************/
- /* Compute and list space required for ORIGINAL_STATE map. */
- /*****************************************************************/
- num_bytes = 2 * num_states;
- sprintf(msg_line,
- " Storage required for ORIGINAL_STATE map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
-
- /********************************************************************/
- /* We now construct a bit map for the set of terminal symbols that */
- /* may appear in each state. Then, we invoke PARTSET to apply the */
- /* Partition Heuristic and print it. */
- /********************************************************************/
- as_size = Allocate_short_array(num_states + 1);
-
- if (table_opt == OPTIMIZE_TIME)
- {
- original = Allocate_short_array(num_symbols + 1);
-
- /*************************************************************/
- /* In a compressed TIME table, the terminal and non-terminal */
- /* symbols are mixed together when they are remapped. */
- /* We shall now recover the original number associated with */
- /* each terminal symbol since it lies very nicely in the */
- /* range 1..NUM_TERMINALS. This will save a considerable */
- /* amount of space in the bit_string representation of sets */
- /* as well as time when operations are performed on those */
- /* bit-strings. */
- /*************************************************************/
- for ALL_TERMINALS(symbol)
- original[symbol_map[symbol]] = symbol;
- }
-
- /***********************************************************************/
- /* NOTE that the arrays ACTION_SYMBOLS and NACTION_SYMBOLS are global */
- /* variables that are allocated in the procedure PROCESS_TABLES by */
- /* calloc which automatically initializes them to 0. */
- /***********************************************************************/
- for ALL_STATES(state_no)
- {
- struct shift_header_type sh;
- struct reduce_header_type red;
-
- sh = shift[statset[state_no].shift_number];
- as_size[state_no] = sh.size;
- for (i = 1; i <= sh.size; i++)
- {
- if (table_opt == OPTIMIZE_TIME)
- symbol = original[SHIFT_SYMBOL(sh, i)];
- else
- symbol = SHIFT_SYMBOL(sh, i);
- SET_BIT_IN(action_symbols, state_no, symbol);
- }
-
- red = reduce[state_no];
- as_size[state_no] += red.size;
- for (i = 1; i <= red.size; i++)
- {
- if (table_opt == OPTIMIZE_TIME)
- symbol = original[REDUCE_SYMBOL(red, i)];
- else
- symbol = REDUCE_SYMBOL(red, i);
- SET_BIT_IN(action_symbols, state_no, symbol);
- }
- }
-
- partset(action_symbols, as_size, state_list, state_start,
- state_stack, num_terminals);
-
- ffree(action_symbols);
-
- /*********************************************************************/
- /* We now write the starting location for each state in the domain */
- /* of the ACTION_SYMBOL map. */
- /* The starting locations are contained in the STATE_START vector. */
- /*********************************************************************/
- offset = state_start[num_states + 1];
- k = 0;
- for ALL_STATES(i)
- {
- field(ABS(state_start[state_list[i]]), 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- field(offset, 6);
- k++;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
-
- /**************************************************************/
- /* Compute and write out the range of the ACTION_SYMBOLS map. */
- /**************************************************************/
- action_symbols_range = Allocate_short_array(offset);
-
- compute_action_symbols_range(state_start, state_stack,
- state_list, action_symbols_range);
-
- k = 0;
- for (i = 0; i < (offset - 1); i++)
- {
- field(action_symbols_range[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*************************************************************/
- /* Compute and list space required for ACTION_SYMBOLS map. */
- /*************************************************************/
- num_bytes = 2 * (num_states + offset);
- if (byte_bit)
- {
- if (offset <= 255)
- num_bytes -= (num_states + 1);
- if (((table_opt == OPTIMIZE_TIME) && (last_terminal <= 255)) ||
- ((table_opt != OPTIMIZE_TIME) && (num_terminals <= 255)))
- num_bytes -= (offset - 1);
- }
- sprintf(msg_line,
- " Storage required for ACTION_SYMBOLS map: "
- "%ld Bytes", num_bytes);
- PRNT(msg_line);
-
- ffree(action_symbols_range);
-
- /***********************************************************************/
- /* We now repeat the same process for the domain of the GOTO table. */
- /***********************************************************************/
- for ALL_STATES(state_no)
- {
- as_size[state_no] = gd_index[state_no + 1] - gd_index[state_no];
- for (i = gd_index[state_no]; i < gd_index[state_no + 1]; i++)
- {
- symbol = gd_range[i] - num_terminals;
- NTSET_BIT_IN(naction_symbols, state_no, symbol);
- }
- }
-
- partset(naction_symbols, as_size, state_list, state_start,
- state_stack, num_non_terminals);
-
- ffree(as_size);
- ffree(naction_symbols);
-
- for (i = 1; i <= gotodom_size; i++) /* Remap non-terminals */
- {
- if (table_opt == OPTIMIZE_TIME)
- gd_range[i] = symbol_map[gd_range[i]];
- else
- gd_range[i] = symbol_map[gd_range[i]] - num_terminals;
- }
-
- /*****************************************************************/
- /* We now write the starting location for each state in the */
- /* domain of the NACTION_SYMBOLS map. The starting locations are */
- /* contained in the STATE_START vector. */
- /*****************************************************************/
- offset = state_start[num_states + 1];
-
- k = 0;
- for ALL_STATES(i)
- {
- field(ABS(state_start[state_list[i]]), 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- field(offset, 6);
- k++;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
-
- /**************************************************************/
- /* Compute and write out the range of the NACTION_SYMBOLS map.*/
- /**************************************************************/
- naction_symbols_range = Allocate_short_array(offset);
-
- compute_naction_symbols_range(state_start, state_stack,
- state_list, naction_symbols_range);
-
- k = 0;
- for (i = 0; i < (offset - 1); i++)
- {
- field(naction_symbols_range[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*************************************************************/
- /* Compute and list space required for NACTION_SYMBOLS map. */
- /*************************************************************/
- num_bytes = 2 * (num_states + offset);
- if (byte_bit)
- {
- if (offset <= 255)
- num_bytes -= (num_states + 1);
- if (((table_opt == OPTIMIZE_TIME) && (last_non_terminal <= 255)) ||
- ((table_opt != OPTIMIZE_TIME) && (num_non_terminals <= 255)))
- num_bytes -= (offset - 1);
- }
- sprintf(msg_line,
- " Storage required for NACTION_SYMBOLS map: "
- "%ld Bytes", num_bytes);
- PRNT(msg_line);
-
- ffree(naction_symbols_range);
-
- /***********************************************************************/
- /* Compute map from each symbol to state into which that symbol can */
- /* cause a transition: TRANSITION_STATES */
- /* TRANSITION_STATES is also written as two vectors like the FOLLOW */
- /* map and the ACTION_DOMAIN map. */
- /* The first vector contains the starting location in the second */
- /* vector for each symbol. */
- /* Construct the TRANSITION_STATES map using an array SYMBOL_ROOT */
- /* (indexable by each symbol) whose elements are the root of a linked */
- /* stack built in STATE_STACK. Another array SYMBOL_COUNT is used to */
- /* keep count of the number of states associated with each symbol. */
- /* For space tables, the TRANSITION_STATES map is written as two */
- /* separate tables: SHIFT_STATES and GOTO_STATES. */
- /***********************************************************************/
- for ALL_SYMBOLS(symbol)
- {
- symbol_root[symbol] = NIL;
- symbol_count[symbol] = 0;
- }
-
- for (state_no = 2; state_no <= (int) num_states; state_no++)
- {
- struct node *q;
-
- q = statset[state_no].kernel_items;
- if (q == NULL) /* is the state a single production state? */
- {
- q = statset[state_no].complete_items; /* pick arbitrary item */
- }
-
- item_no = q -> value - 1;
- i = item_table[item_no].symbol;
- symbol = symbol_map[i];
- state_stack[state_no] = symbol_root[symbol];
- symbol_root[symbol] = state_no;
- symbol_count[symbol]++;
- }
-
- /***************************************************************************/
- /* We now compute and write the starting location for each terminal symbol */
- /***************************************************************************/
- offset = 1; /* Offset of the first state */
- field(offset, 6);
- k = 1;
- for (symbol = 1; symbol <= terminal_ubound; symbol++)
- {
- offset += symbol_count[symbol];
- field(offset, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* We now write out the range elements of SHIFT_STATES for space */
- /* tables or TRANSITION_STATES for time tables. */
- /*********************************************************************/
- k = 0;
- for (symbol = 1; symbol <= terminal_ubound; symbol++)
- {
- for (state_no = symbol_root[symbol];
- state_no != NIL; state_no = state_stack[state_no])
- {
- field(state_index[state_no] + num_rules, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* If space tables are requested we compute and list space required */
- /* for SHIFT_STATES map. The base vector contains NUM_TERMINALS+ 1 */
- /* elements, and the vector containing the range elements has size */
- /* OFFSET - 1. If time tables are requested we compute and list space*/
- /* requirements for TRANSITION_STATES map. The base vector has */
- /* NUM_SYMBOLS + 1 elements, and the range elements vector contains */
- /* OFFSET - 1 elements. */
- /*********************************************************************/
- if (table_opt == OPTIMIZE_TIME)
- {
- num_bytes = 2 * (num_symbols + offset);
- sprintf(msg_line,
- " Storage required for TRANSITION_STATES map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
- }
- else
- {
- num_bytes = 2 * (num_terminals + offset);
- sprintf(msg_line,
- " Storage required for SHIFT_STATES map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
-
- /************************************************************/
- /* We now compute and write the starting location for each */
- /* non-terminal symbol... */
- /************************************************************/
- offset = 1;
- field(offset, 6); /* Offset of the first state */
- k = 1;
- for ALL_NON_TERMINALS(symbol)
- {
- offset += symbol_count[symbol];
- field(offset, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* We now write out the range elements of GOTO_STATES whose domain */
- /* is a non-terminal symbol. */
- /*********************************************************************/
- k = 0;
- for ALL_NON_TERMINALS(symbol)
- {
- for (state_no = symbol_root[symbol];
- state_no != NIL; state_no = state_stack[state_no])
- {
- field(state_index[state_no] + num_rules, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* We compute and list space required for GOTO_STATES map. The */
- /* base vector contains NUM_NON_TERMINALS+ 1 elements, and the vector*/
- /* containing the range elements has size OFFSET - 1 */
- /*********************************************************************/
- num_bytes = 2 * (num_non_terminals + offset);
- sprintf(msg_line," Storage required for GOTO_STATES map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
- }
-
- /*********************************************************************/
- /* Write the number associated with the ERROR symbol. */
- /*********************************************************************/
-
- field(error_image, 4);
- field(eolt_image, 4);
- field(num_names, 4);
- field(num_scopes, 4);
- field(scope_rhs_size, 4);
- field(scope_state_size, 4);
- if (table_opt == OPTIMIZE_SPACE)
- field(num_error_rules, 4);
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
-
- /*********************************************************************/
- /* We write out the names map. */
- /*********************************************************************/
- num_bytes = 0;
- max_len = 0;
- for (i = 1; i <= num_names; i++)
- {
- int name_len;
-
- strcpy(tok, RETRIEVE_NAME(i));
- if (tok[0] == '\n') /* we're dealing with special symbol? */
- tok[0] = escape; /* replace initial marker with escape. */
- name_len = strlen(tok);
- num_bytes += name_len;
- if (max_len < name_len)
- max_len = name_len;
-
- field(name_len, 4);
-
- if (name_len <= 68)
- strcpy(output_ptr, tok);
- else
- {
- memcpy(output_ptr, tok, 68);
- output_ptr+= 68;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);;
- strcpy(tok, tok+68);
-
- for (name_len = strlen(tok); name_len > 72; name_len = strlen(tok))
- {
- memcpy(output_ptr, tok, 72);
- output_ptr+= 72;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- strcpy(tok, tok+72);
- }
- memcpy(output_ptr, tok, name_len);
- }
- output_ptr += name_len;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* We write the name_index of each terminal symbol. The array TEMP */
- /* is used to remap the NAME_INDEX values based on the new symbol */
- /* numberings. If time tables are requested, the terminals and non- */
- /* terminals are mixed together. */
- /*********************************************************************/
- temp = Allocate_short_array(num_symbols + 1);
-
- if (table_opt == OPTIMIZE_TIME)
- {
- for ALL_SYMBOLS(symbol)
- temp[symbol_map[symbol]] = symno[symbol].name_index;
-
- k = 0;
- for ALL_SYMBOLS(symbol)
- {
- field(temp[symbol], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
- }
- else
- {
- for ALL_TERMINALS(symbol)
- temp[symbol_map[symbol]] = symno[symbol].name_index;
-
- k = 0;
- for ALL_TERMINALS(symbol)
- {
- field(temp[symbol], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /****************************************************************/
- /* We write the name_index of each non_terminal symbol. The */
- /* array TEMP is used to remap the NAME_INDEX values based on */
- /* the new symbol numberings. */
- /****************************************************************/
- for ALL_NON_TERMINALS(symbol)
- temp[symbol_map[symbol]] = symno[symbol].name_index;
-
- k = 0;
- for ALL_NON_TERMINALS(symbol)
- {
- field(temp[symbol], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
- }
-
- /*****************************************************/
- /* Compute and list space requirements for NAME map. */
- /*****************************************************/
- if (max_len > 255)
- offset = 2 * num_symbols;
- else
- offset = num_symbols;
-
- if (num_bytes > 255)
- offset += (2 * num_symbols);
- else
- offset += num_symbols;
-
- sprintf(msg_line,
- " Storage required for direct NAME map: %d Bytes",
- num_bytes + offset);
- PRNT(msg_line);
-
- if (max_len > 255)
- offset = 2 * num_names;
- else
- offset = num_names;
-
- if (num_bytes > 255)
- offset += (2 * num_names);
- else
- offset += num_names;
-
- if (num_names > 255)
- offset += (2 * num_symbols);
- else
- offset += num_symbols;
-
- sprintf(msg_line,
- " Storage required for indirect NAME map: %d Bytes",
- num_bytes + offset);
- PRNT(msg_line);
-
- if (scopes_bit)
- {
- for (i = 1; i <= scope_rhs_size; i++)
- {
- if (scope_right_side[i] != 0)
- scope_right_side[i] = symbol_map[scope_right_side[i]];
- }
-
- for (i = 1; i <= num_scopes; i++)
- {
- scope[i].look_ahead = symbol_map[scope[i].look_ahead];
- if (table_opt == OPTIMIZE_TIME)
- scope[i].lhs_symbol = symbol_map[scope[i].lhs_symbol];
- else
- scope[i].lhs_symbol = symbol_map[scope[i].lhs_symbol]
- - num_terminals;
- }
-
- k = 0;
- for (i = 1; i <= num_scopes; i++)
- {
- field(scope[i].prefix, 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for (i = 1; i <= num_scopes; i++)
- {
- field(scope[i].suffix, 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for (i = 1; i <= num_scopes; i++)
- {
- field(scope[i].lhs_symbol, 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for (i = 1; i <= num_scopes; i++)
- {
- field(scope[i].look_ahead, 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for (i = 1; i <= num_scopes; i++)
- {
- field(scope[i].state_set, 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for (i = 1; i <= scope_rhs_size; i++)
- {
- field(scope_right_side[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for (i = 1; i <= scope_state_size; i++)
- {
- if (scope_state[i] == 0)
- field(0, 6);
- else
- field(state_index[scope_state[i]] + num_rules, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- if (table_opt == OPTIMIZE_TIME)
- {
- num_bytes = 5 * num_scopes +
- scope_rhs_size+ scope_state_size;
- if (num_symbols > 255)
- num_bytes += (2 * num_scopes + scope_rhs_size);
- }
- else
- {
- num_bytes = 5 * num_scopes +
- scope_rhs_size+ 2 * scope_state_size;
- if (num_non_terminals > 255)
- num_bytes += num_scopes;
- if (num_terminals > 255)
- num_bytes += num_scopes;
- if (num_symbols > 255)
- num_bytes += scope_rhs_size;
- }
- if (scope_rhs_size > 255)
- num_bytes += (2 * num_scopes);
- if (scope_state_size > 255)
- num_bytes += num_scopes;
- sprintf(msg_line,
- " Storage required for SCOPE map: %d Bytes",
- num_bytes);
- PRNT(msg_line);
- }
-
- if (original != NULL)
- {
- ffree(original);
- }
- ffree(symbol_root);
- ffree(symbol_count);
- ffree(temp);
- ffree(state_start);
- ffree(state_stack);
- ffree(term_list);
-
- return;
- }
-
-
- /*********************************************************************/
- /* COMPUTE_ACTION_SYMBOLS_RANGE: */
- /*********************************************************************/
- /* */
- /* This procedure computes the range of the ACTION_SYMBOLS map after */
- /* Optimal Partitioning has been used to compress that map. Its */
- /* first argument is an array, STATE_START, that indicates the */
- /* starting location in the compressed vector for each state. When */
- /* a value of STATE_START is negative it indicates that the state in */
- /* question shares its elements with another state. Its second */
- /* argument, STATE_STACK, is an array that contains the elements of */
- /* the partition created by PARTSET. Each element of the partition */
- /* is organized as a circular list where the smallest sets appear */
- /* first in the list. */
- /* */
- /*********************************************************************/
- void compute_action_symbols_range(short *state_start,
- short *state_stack,
- short *state_list,
- short *action_symbols_range)
- {
- int i,
- j,
- k,
- state_no,
- state,
- symbol,
- symbol_root;
-
- BOOLEAN end_node;
-
- short *symbol_list;
-
- symbol_list = Allocate_short_array(num_symbols + 1);
-
- /*********************************************************************/
- /* We now write out the range elements of the ACTION_SYMBOLS map. */
- /* Recall that if STATE_START has a negative value, then the set in */
- /* question is sharing elements and does not need to be processed. */
- /*********************************************************************/
- k = 0;
- for ALL_SYMBOLS(j)
- symbol_list[j] = OMEGA; /* Initialize all links to OMEGA */
-
- for ALL_STATES(i)
- {
- state_no = state_list[i];
- if (state_start[state_no] > 0)
- {
- symbol_root = 0; /* Add "fence" element: 0 to list */
- symbol_list[symbol_root] = NIL;
-
- /*************************************************************/
- /* Pop a state from the stack, and add each of its elements */
- /* that has not yet been processed into the list. */
- /* Continue until stack is empty... */
- /* Recall that the stack is represented by a circular queue. */
- /*************************************************************/
- for (end_node = ((state = state_no) == NIL);
- ! end_node; end_node = (state == state_no))
- {
- struct shift_header_type sh;
- struct reduce_header_type red;
-
- state = state_stack[state];
- sh = shift[statset[state].shift_number];
- for (j = 1; j <= sh.size; j++)
- {
- symbol = SHIFT_SYMBOL(sh, j);
- if (symbol_list[symbol] == OMEGA)
- {
- symbol_list[symbol] = symbol_root;
- symbol_root = symbol;
- }
- }
-
- red = reduce[state];
- for (j = 1; j <= red.size; j++)
- {
- symbol = REDUCE_SYMBOL(red, j);
- if (symbol_list[symbol] == OMEGA)
- {
- symbol_list[symbol] = symbol_root;
- symbol_root = symbol;
- }
- }
- }
-
- /*************************************************************/
- /* Write the list out. */
- /*************************************************************/
- for (symbol = symbol_root; symbol != NIL; symbol = symbol_root)
- {
- symbol_root = symbol_list[symbol];
-
- symbol_list[symbol] = OMEGA;
- action_symbols_range[k++] = symbol;
- }
- }
- }
-
- ffree(symbol_list);
-
- return;
- }
-
-
- /*********************************************************************/
- /* COMPUTE_NACTION_SYMBOLS_RANGE: */
- /*********************************************************************/
- /* This procedure computes the range of the NACTION_SYMBOLS map. It */
- /* organization is analoguous to COMPUTE_ACTION_SYMBOLS_RANGE. */
- /*********************************************************************/
- void compute_naction_symbols_range(short *state_start,
- short *state_stack,
- short *state_list,
- short *naction_symbols_range)
- {
- int i,
- j,
- k,
- state_no,
- state,
- symbol,
- symbol_root;
-
- BOOLEAN end_node;
-
- short *symbol_list;
-
- symbol_list = Allocate_short_array(num_symbols + 1);
-
- /*********************************************************************/
- /* We now write out the range elements of the NACTION_SYMBOLS map. */
- /* Recall that if STATE_START has a negative value, then the set in */
- /* question is sharing elements and does not need to be processed. */
- /*********************************************************************/
- k = 0;
- for ALL_SYMBOLS(j)
- symbol_list[j] = OMEGA; /* Initialize all links to OMEGA */
-
- for ALL_STATES(i)
- {
- state_no = state_list[i];
- if (state_start[state_no] > 0)
- {
- symbol_root = 0; /* Add "fence" element: 0 to list */
- symbol_list[symbol_root] = NIL;
-
- /*************************************************************/
- /* Pop a state from the stack, and add each of its elements */
- /* that has not yet been processed into the list. */
- /* Continue until stack is empty... */
- /* Recall that the stack is represented by a circular queue. */
- /*************************************************************/
- for (end_node = ((state = state_no) == NIL);
- ! end_node; end_node = (state == state_no))
- {
- state = state_stack[state];
- for (j = gd_index[state];
- j <= gd_index[state + 1] - 1; j++)
- {
- symbol = gd_range[j];
- if (symbol_list[symbol] == OMEGA)
- {
- symbol_list[symbol] = symbol_root;
- symbol_root = symbol;
- }
- }
- }
-
- /**********************************************************/
- /* Write the list out. */
- /**********************************************************/
- for (symbol = symbol_root; symbol != NIL; symbol = symbol_root)
- {
- symbol_root = symbol_list[symbol];
-
- symbol_list[symbol] = OMEGA;
- naction_symbols_range[k++] = symbol;
- }
- }
- }
-
- ffree(symbol_list);
-
- return;
- }
-