1045 lines
25 KiB
C
1045 lines
25 KiB
C
/* stt.c -- Implementation File (module.c template V1.0)
|
||
Copyright (C) 1995, 1997 Free Software Foundation, Inc.
|
||
Contributed by James Craig Burley (burley@gnu.org).
|
||
|
||
This file is part of GNU Fortran.
|
||
|
||
GNU Fortran is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 2, or (at your option)
|
||
any later version.
|
||
|
||
GNU Fortran is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GNU Fortran; see the file COPYING. If not, write to
|
||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||
02111-1307, USA.
|
||
|
||
Related Modules:
|
||
None
|
||
|
||
Description:
|
||
Manages lists of tokens and related info for parsing.
|
||
|
||
Modifications:
|
||
*/
|
||
|
||
/* Include files. */
|
||
|
||
#include "proj.h"
|
||
#include "stt.h"
|
||
#include "bld.h"
|
||
#include "expr.h"
|
||
#include "info.h"
|
||
#include "lex.h"
|
||
#include "malloc.h"
|
||
#include "sta.h"
|
||
#include "stp.h"
|
||
|
||
/* Externals defined here. */
|
||
|
||
|
||
/* Simple definitions and enumerations. */
|
||
|
||
|
||
/* Internal typedefs. */
|
||
|
||
|
||
/* Private include files. */
|
||
|
||
|
||
/* Internal structure definitions. */
|
||
|
||
|
||
/* Static objects accessed by functions in this module. */
|
||
|
||
|
||
/* Static functions (internal). */
|
||
|
||
|
||
/* Internal macros. */
|
||
|
||
|
||
/* ffestt_caselist_append -- Append case to list of cases
|
||
|
||
ffesttCaseList list;
|
||
ffelexToken t;
|
||
ffestt_caselist_append(list,range,case1,case2,t);
|
||
|
||
list must have already been created by ffestt_caselist_create. The
|
||
list is allocated out of the scratch pool. The token is consumed. */
|
||
|
||
void
|
||
ffestt_caselist_append (ffesttCaseList list, bool range, ffebld case1,
|
||
ffebld case2, ffelexToken t)
|
||
{
|
||
ffesttCaseList new;
|
||
|
||
new = (ffesttCaseList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST case list", sizeof (*new));
|
||
new->next = list->previous->next;
|
||
new->previous = list->previous;
|
||
new->next->previous = new;
|
||
new->previous->next = new;
|
||
new->expr1 = case1;
|
||
new->expr2 = case2;
|
||
new->range = range;
|
||
new->t = t;
|
||
}
|
||
|
||
/* ffestt_caselist_create -- Create new list of cases
|
||
|
||
ffesttCaseList list;
|
||
list = ffestt_caselist_create();
|
||
|
||
The list is allocated out of the scratch pool. */
|
||
|
||
ffesttCaseList
|
||
ffestt_caselist_create ()
|
||
{
|
||
ffesttCaseList new;
|
||
|
||
new = (ffesttCaseList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST case list root",
|
||
sizeof (*new));
|
||
new->next = new->previous = new;
|
||
new->t = NULL;
|
||
new->expr1 = NULL;
|
||
new->expr2 = NULL;
|
||
new->range = FALSE;
|
||
return new;
|
||
}
|
||
|
||
/* ffestt_caselist_dump -- Dump list of cases
|
||
|
||
ffesttCaseList list;
|
||
ffestt_caselist_dump(list);
|
||
|
||
The cases in the list are dumped with commas separating them. */
|
||
|
||
#if FFECOM_targetCURRENT == FFECOM_targetFFE
|
||
void
|
||
ffestt_caselist_dump (ffesttCaseList list)
|
||
{
|
||
ffesttCaseList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
if (next != list->next)
|
||
fputc (',', dmpout);
|
||
if (next->expr1 != NULL)
|
||
ffebld_dump (next->expr1);
|
||
if (next->range)
|
||
{
|
||
fputc (':', dmpout);
|
||
if (next->expr2 != NULL)
|
||
ffebld_dump (next->expr2);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* ffestt_caselist_kill -- Kill list of cases
|
||
|
||
ffesttCaseList list;
|
||
ffestt_caselist_kill(list);
|
||
|
||
The tokens on the list are killed.
|
||
|
||
02-Mar-90 JCB 1.1
|
||
Don't kill the list itself or change it, since it will be trashed when
|
||
ffesta_scratch_pool is killed anyway, so kill only the lex tokens. */
|
||
|
||
void
|
||
ffestt_caselist_kill (ffesttCaseList list)
|
||
{
|
||
ffesttCaseList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
ffelex_token_kill (next->t);
|
||
}
|
||
}
|
||
|
||
/* ffestt_dimlist_append -- Append dim to list of dims
|
||
|
||
ffesttDimList list;
|
||
ffelexToken t;
|
||
ffestt_dimlist_append(list,lower,upper,t);
|
||
|
||
list must have already been created by ffestt_dimlist_create. The
|
||
list is allocated out of the scratch pool. The token is consumed. */
|
||
|
||
void
|
||
ffestt_dimlist_append (ffesttDimList list, ffebld lower, ffebld upper,
|
||
ffelexToken t)
|
||
{
|
||
ffesttDimList new;
|
||
|
||
new = (ffesttDimList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST dim list", sizeof (*new));
|
||
new->next = list->previous->next;
|
||
new->previous = list->previous;
|
||
new->next->previous = new;
|
||
new->previous->next = new;
|
||
new->lower = lower;
|
||
new->upper = upper;
|
||
new->t = t;
|
||
}
|
||
|
||
/* Convert list of dims into ffebld format.
|
||
|
||
ffesttDimList list;
|
||
ffeinfoRank rank;
|
||
ffebld array_size;
|
||
ffebld extents;
|
||
ffestt_dimlist_as_expr (list, &rank, &array_size, &extents);
|
||
|
||
The dims in the list are converted to a list of ITEMs; the rank of the
|
||
array, an expression representing the array size, a list of extent
|
||
expressions, and the list of ITEMs are returned.
|
||
|
||
If is_ugly_assumed, treat a final dimension with no lower bound
|
||
and an upper bound of 1 as a * bound. */
|
||
|
||
ffebld
|
||
ffestt_dimlist_as_expr (ffesttDimList list, ffeinfoRank *rank,
|
||
ffebld *array_size, ffebld *extents,
|
||
bool is_ugly_assumed)
|
||
{
|
||
ffesttDimList next;
|
||
ffebld expr;
|
||
ffebld as;
|
||
ffebld ex; /* List of extents. */
|
||
ffebld ext; /* Extent of a given dimension. */
|
||
ffebldListBottom bottom;
|
||
ffeinfoRank r;
|
||
ffeinfoKindtype nkt;
|
||
ffetargetIntegerDefault low;
|
||
ffetargetIntegerDefault high;
|
||
bool zero = FALSE; /* Zero-size array. */
|
||
bool any = FALSE;
|
||
bool star = FALSE; /* Adjustable array. */
|
||
|
||
assert (list != NULL);
|
||
|
||
r = 0;
|
||
ffebld_init_list (&expr, &bottom);
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
++r;
|
||
if (((next->lower == NULL)
|
||
|| (ffebld_op (next->lower) == FFEBLD_opCONTER))
|
||
&& (ffebld_op (next->upper) == FFEBLD_opCONTER))
|
||
{
|
||
if (next->lower == NULL)
|
||
low = 1;
|
||
else
|
||
low = ffebld_constant_integerdefault (ffebld_conter (next->lower));
|
||
high = ffebld_constant_integerdefault (ffebld_conter (next->upper));
|
||
if (low
|
||
> high)
|
||
zero = TRUE;
|
||
if ((next->next == list)
|
||
&& is_ugly_assumed
|
||
&& (next->lower == NULL)
|
||
&& (high == 1)
|
||
&& (ffebld_conter_orig (next->upper) == NULL))
|
||
{
|
||
star = TRUE;
|
||
ffebld_append_item (&bottom,
|
||
ffebld_new_bounds (NULL, ffebld_new_star ()));
|
||
continue;
|
||
}
|
||
}
|
||
else if (((next->lower != NULL)
|
||
&& (ffebld_op (next->lower) == FFEBLD_opANY))
|
||
|| (ffebld_op (next->upper) == FFEBLD_opANY))
|
||
any = TRUE;
|
||
else if (ffebld_op (next->upper) == FFEBLD_opSTAR)
|
||
star = TRUE;
|
||
ffebld_append_item (&bottom,
|
||
ffebld_new_bounds (next->lower, next->upper));
|
||
}
|
||
ffebld_end_list (&bottom);
|
||
|
||
if (zero)
|
||
{
|
||
as = ffebld_new_conter (ffebld_constant_new_integerdefault_val (0));
|
||
ffebld_set_info (as, ffeinfo_new
|
||
(FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
ex = NULL;
|
||
}
|
||
else if (any)
|
||
{
|
||
as = ffebld_new_any ();
|
||
ffebld_set_info (as, ffeinfo_new_any ());
|
||
ex = ffebld_copy (as);
|
||
}
|
||
else if (star)
|
||
{
|
||
as = ffebld_new_star ();
|
||
ex = ffebld_new_star (); /* ~~Should really be list as below. */
|
||
}
|
||
else
|
||
{
|
||
as = NULL;
|
||
ffebld_init_list (&ex, &bottom);
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
if ((next->lower == NULL)
|
||
|| ((ffebld_op (next->lower) == FFEBLD_opCONTER)
|
||
&& (ffebld_constant_integerdefault (ffebld_conter
|
||
(next->lower)) == 1)))
|
||
ext = ffebld_copy (next->upper);
|
||
else
|
||
{
|
||
ext = ffebld_new_subtract (next->upper, next->lower);
|
||
nkt
|
||
= ffeinfo_kindtype_max (FFEINFO_basictypeINTEGER,
|
||
ffeinfo_kindtype (ffebld_info
|
||
(next->lower)),
|
||
ffeinfo_kindtype (ffebld_info
|
||
(next->upper)));
|
||
ffebld_set_info (ext,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
nkt,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
((ffebld_op (ffebld_left (ext))
|
||
== FFEBLD_opCONTER)
|
||
&& (ffebld_op (ffebld_right
|
||
(ext))
|
||
== FFEBLD_opCONTER))
|
||
? FFEINFO_whereCONSTANT
|
||
: FFEINFO_whereFLEETING,
|
||
FFETARGET_charactersizeNONE));
|
||
ffebld_set_left (ext,
|
||
ffeexpr_convert_expr (ffebld_left (ext),
|
||
next->t, ext, next->t,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (ext,
|
||
ffeexpr_convert_expr (ffebld_right (ext),
|
||
next->t, ext,
|
||
next->t,
|
||
FFEEXPR_contextLET));
|
||
ext = ffeexpr_collapse_subtract (ext, next->t);
|
||
|
||
nkt
|
||
= ffeinfo_kindtype_max (FFEINFO_basictypeINTEGER,
|
||
ffeinfo_kindtype (ffebld_info (ext)),
|
||
FFEINFO_kindtypeINTEGERDEFAULT);
|
||
ext
|
||
= ffebld_new_add (ext,
|
||
ffebld_new_conter
|
||
(ffebld_constant_new_integerdefault_val
|
||
(1)));
|
||
ffebld_set_info (ffebld_right (ext), ffeinfo_new
|
||
(FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT,
|
||
0,
|
||
FFEINFO_kindENTITY,
|
||
FFEINFO_whereCONSTANT,
|
||
FFETARGET_charactersizeNONE));
|
||
ffebld_set_info (ext,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
nkt, 0, FFEINFO_kindENTITY,
|
||
(ffebld_op (ffebld_left (ext))
|
||
== FFEBLD_opCONTER)
|
||
? FFEINFO_whereCONSTANT
|
||
: FFEINFO_whereFLEETING,
|
||
FFETARGET_charactersizeNONE));
|
||
ffebld_set_left (ext,
|
||
ffeexpr_convert_expr (ffebld_left (ext),
|
||
next->t, ext,
|
||
next->t,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (ext,
|
||
ffeexpr_convert_expr (ffebld_right (ext),
|
||
next->t, ext,
|
||
next->t,
|
||
FFEEXPR_contextLET));
|
||
ext = ffeexpr_collapse_add (ext, next->t);
|
||
}
|
||
ffebld_append_item (&bottom, ext);
|
||
if (as == NULL)
|
||
as = ext;
|
||
else
|
||
{
|
||
nkt
|
||
= ffeinfo_kindtype_max (FFEINFO_basictypeINTEGER,
|
||
ffeinfo_kindtype (ffebld_info (as)),
|
||
ffeinfo_kindtype (ffebld_info (ext)));
|
||
as = ffebld_new_multiply (as, ext);
|
||
ffebld_set_info (as,
|
||
ffeinfo_new (FFEINFO_basictypeINTEGER,
|
||
nkt, 0, FFEINFO_kindENTITY,
|
||
((ffebld_op (ffebld_left (as))
|
||
== FFEBLD_opCONTER)
|
||
&& (ffebld_op (ffebld_right
|
||
(as))
|
||
== FFEBLD_opCONTER))
|
||
? FFEINFO_whereCONSTANT
|
||
: FFEINFO_whereFLEETING,
|
||
FFETARGET_charactersizeNONE));
|
||
ffebld_set_left (as,
|
||
ffeexpr_convert_expr (ffebld_left (as),
|
||
next->t, as, next->t,
|
||
FFEEXPR_contextLET));
|
||
ffebld_set_right (as,
|
||
ffeexpr_convert_expr (ffebld_right (as),
|
||
next->t, as,
|
||
next->t,
|
||
FFEEXPR_contextLET));
|
||
as = ffeexpr_collapse_multiply (as, next->t);
|
||
}
|
||
}
|
||
ffebld_end_list (&bottom);
|
||
as = ffeexpr_convert (as, list->next->t, NULL,
|
||
FFEINFO_basictypeINTEGER,
|
||
FFEINFO_kindtypeINTEGERDEFAULT, 0,
|
||
FFETARGET_charactersizeNONE,
|
||
FFEEXPR_contextLET);
|
||
}
|
||
|
||
*rank = r;
|
||
*array_size = as;
|
||
*extents = ex;
|
||
return expr;
|
||
}
|
||
|
||
/* ffestt_dimlist_create -- Create new list of dims
|
||
|
||
ffesttDimList list;
|
||
list = ffestt_dimlist_create();
|
||
|
||
The list is allocated out of the scratch pool. */
|
||
|
||
ffesttDimList
|
||
ffestt_dimlist_create ()
|
||
{
|
||
ffesttDimList new;
|
||
|
||
new = (ffesttDimList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST dim list root", sizeof (*new));
|
||
new->next = new->previous = new;
|
||
new->t = NULL;
|
||
new->lower = NULL;
|
||
new->upper = NULL;
|
||
return new;
|
||
}
|
||
|
||
/* ffestt_dimlist_dump -- Dump list of dims
|
||
|
||
ffesttDimList list;
|
||
ffestt_dimlist_dump(list);
|
||
|
||
The dims in the list are dumped with commas separating them. */
|
||
|
||
#if FFECOM_targetCURRENT == FFECOM_targetFFE
|
||
void
|
||
ffestt_dimlist_dump (ffesttDimList list)
|
||
{
|
||
ffesttDimList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
if (next != list->next)
|
||
fputc (',', dmpout);
|
||
if (next->lower != NULL)
|
||
ffebld_dump (next->lower);
|
||
fputc (':', dmpout);
|
||
if (next->upper != NULL)
|
||
ffebld_dump (next->upper);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* ffestt_dimlist_kill -- Kill list of dims
|
||
|
||
ffesttDimList list;
|
||
ffestt_dimlist_kill(list);
|
||
|
||
The tokens on the list are killed. */
|
||
|
||
void
|
||
ffestt_dimlist_kill (ffesttDimList list)
|
||
{
|
||
ffesttDimList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
ffelex_token_kill (next->t);
|
||
}
|
||
}
|
||
|
||
/* Determine type of list of dimensions.
|
||
|
||
Return KNOWN for all-constant bounds, ADJUSTABLE for constant
|
||
and variable but no * bounds, ASSUMED for constant and * but
|
||
not variable bounds, ADJUSTABLEASSUMED for constant and variable
|
||
and * bounds.
|
||
|
||
If is_ugly_assumed, treat a final dimension with no lower bound
|
||
and an upper bound of 1 as a * bound. */
|
||
|
||
ffestpDimtype
|
||
ffestt_dimlist_type (ffesttDimList list, bool is_ugly_assumed)
|
||
{
|
||
ffesttDimList next;
|
||
ffestpDimtype type;
|
||
|
||
if (list == NULL)
|
||
return FFESTP_dimtypeNONE;
|
||
|
||
type = FFESTP_dimtypeKNOWN;
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
bool ugly_assumed = FALSE;
|
||
|
||
if ((next->next == list)
|
||
&& is_ugly_assumed
|
||
&& (next->lower == NULL)
|
||
&& (next->upper != NULL)
|
||
&& (ffebld_op (next->upper) == FFEBLD_opCONTER)
|
||
&& (ffebld_constant_integerdefault (ffebld_conter (next->upper))
|
||
== 1)
|
||
&& (ffebld_conter_orig (next->upper) == NULL))
|
||
ugly_assumed = TRUE;
|
||
|
||
if (next->lower != NULL)
|
||
{
|
||
if (ffebld_op (next->lower) != FFEBLD_opCONTER)
|
||
{
|
||
if (type == FFESTP_dimtypeASSUMED)
|
||
type = FFESTP_dimtypeADJUSTABLEASSUMED;
|
||
else
|
||
type = FFESTP_dimtypeADJUSTABLE;
|
||
}
|
||
}
|
||
if (next->upper != NULL)
|
||
{
|
||
if (ugly_assumed
|
||
|| (ffebld_op (next->upper) == FFEBLD_opSTAR))
|
||
{
|
||
if (type == FFESTP_dimtypeADJUSTABLE)
|
||
type = FFESTP_dimtypeADJUSTABLEASSUMED;
|
||
else
|
||
type = FFESTP_dimtypeASSUMED;
|
||
}
|
||
else if (ffebld_op (next->upper) != FFEBLD_opCONTER)
|
||
type = FFESTP_dimtypeADJUSTABLE;
|
||
}
|
||
}
|
||
|
||
return type;
|
||
}
|
||
|
||
/* ffestt_exprlist_append -- Append expr to list of exprs
|
||
|
||
ffesttExprList list;
|
||
ffelexToken t;
|
||
ffestt_exprlist_append(list,expr,t);
|
||
|
||
list must have already been created by ffestt_exprlist_create. The
|
||
list is allocated out of the scratch pool. The token is consumed. */
|
||
|
||
void
|
||
ffestt_exprlist_append (ffesttExprList list, ffebld expr, ffelexToken t)
|
||
{
|
||
ffesttExprList new;
|
||
|
||
new = (ffesttExprList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST expr list", sizeof (*new));
|
||
new->next = list->previous->next;
|
||
new->previous = list->previous;
|
||
new->next->previous = new;
|
||
new->previous->next = new;
|
||
new->expr = expr;
|
||
new->t = t;
|
||
}
|
||
|
||
/* ffestt_exprlist_create -- Create new list of exprs
|
||
|
||
ffesttExprList list;
|
||
list = ffestt_exprlist_create();
|
||
|
||
The list is allocated out of the scratch pool. */
|
||
|
||
ffesttExprList
|
||
ffestt_exprlist_create ()
|
||
{
|
||
ffesttExprList new;
|
||
|
||
new = (ffesttExprList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST expr list root", sizeof (*new));
|
||
new->next = new->previous = new;
|
||
new->expr = NULL;
|
||
new->t = NULL;
|
||
return new;
|
||
}
|
||
|
||
/* ffestt_exprlist_drive -- Drive list of token pairs into function
|
||
|
||
ffesttExprList list;
|
||
void fn(ffebld expr,ffelexToken t);
|
||
ffestt_exprlist_drive(list,fn);
|
||
|
||
The expr/token pairs in the list are passed to the function one pair
|
||
at a time. */
|
||
|
||
void
|
||
ffestt_exprlist_drive (ffesttExprList list, void (*fn) ())
|
||
{
|
||
ffesttExprList next;
|
||
|
||
if (list == NULL)
|
||
return;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
(*fn) (next->expr, next->t);
|
||
}
|
||
}
|
||
|
||
/* ffestt_exprlist_dump -- Dump list of exprs
|
||
|
||
ffesttExprList list;
|
||
ffestt_exprlist_dump(list);
|
||
|
||
The exprs in the list are dumped with commas separating them. */
|
||
|
||
#if FFECOM_targetCURRENT == FFECOM_targetFFE
|
||
void
|
||
ffestt_exprlist_dump (ffesttExprList list)
|
||
{
|
||
ffesttExprList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
if (next != list->next)
|
||
fputc (',', dmpout);
|
||
ffebld_dump (next->expr);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* ffestt_exprlist_kill -- Kill list of exprs
|
||
|
||
ffesttExprList list;
|
||
ffestt_exprlist_kill(list);
|
||
|
||
The tokens on the list are killed.
|
||
|
||
02-Mar-90 JCB 1.1
|
||
Don't kill the list itself or change it, since it will be trashed when
|
||
ffesta_scratch_pool is killed anyway, so kill only the lex tokens. */
|
||
|
||
void
|
||
ffestt_exprlist_kill (ffesttExprList list)
|
||
{
|
||
ffesttExprList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
ffelex_token_kill (next->t);
|
||
}
|
||
}
|
||
|
||
/* ffestt_formatlist_append -- Append null format to list of formats
|
||
|
||
ffesttFormatList list, new;
|
||
new = ffestt_formatlist_append(list);
|
||
|
||
list must have already been created by ffestt_formatlist_create. The
|
||
new item is allocated out of the scratch pool. The caller must initialize
|
||
it appropriately. */
|
||
|
||
ffesttFormatList
|
||
ffestt_formatlist_append (ffesttFormatList list)
|
||
{
|
||
ffesttFormatList new;
|
||
|
||
new = (ffesttFormatList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST format list", sizeof (*new));
|
||
new->next = list->previous->next;
|
||
new->previous = list->previous;
|
||
new->next->previous = new;
|
||
new->previous->next = new;
|
||
return new;
|
||
}
|
||
|
||
/* ffestt_formatlist_create -- Create new list of formats
|
||
|
||
ffesttFormatList list;
|
||
list = ffestt_formatlist_create(NULL);
|
||
|
||
The list is allocated out of the scratch pool. */
|
||
|
||
ffesttFormatList
|
||
ffestt_formatlist_create (ffesttFormatList parent, ffelexToken t)
|
||
{
|
||
ffesttFormatList new;
|
||
|
||
new = (ffesttFormatList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST format list root", sizeof (*new));
|
||
new->next = new->previous = new;
|
||
new->type = FFESTP_formattypeNone;
|
||
new->t = t;
|
||
new->u.root.parent = parent;
|
||
return new;
|
||
}
|
||
|
||
/* ffestt_formatlist_kill -- Kill tokens on list of formats
|
||
|
||
ffesttFormatList list;
|
||
ffestt_formatlist_kill(list);
|
||
|
||
The tokens on the list are killed. */
|
||
|
||
void
|
||
ffestt_formatlist_kill (ffesttFormatList list)
|
||
{
|
||
ffesttFormatList next;
|
||
|
||
/* Always kill from the very top on down. */
|
||
|
||
while (list->u.root.parent != NULL)
|
||
list = list->u.root.parent->next;
|
||
|
||
/* Kill first token for this list. */
|
||
|
||
if (list->t != NULL)
|
||
ffelex_token_kill (list->t);
|
||
|
||
/* Kill each item in this list. */
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
ffelex_token_kill (next->t);
|
||
switch (next->type)
|
||
{
|
||
case FFESTP_formattypeI:
|
||
case FFESTP_formattypeB:
|
||
case FFESTP_formattypeO:
|
||
case FFESTP_formattypeZ:
|
||
case FFESTP_formattypeF:
|
||
case FFESTP_formattypeE:
|
||
case FFESTP_formattypeEN:
|
||
case FFESTP_formattypeG:
|
||
case FFESTP_formattypeL:
|
||
case FFESTP_formattypeA:
|
||
case FFESTP_formattypeD:
|
||
if (next->u.R1005.R1004.t != NULL)
|
||
ffelex_token_kill (next->u.R1005.R1004.t);
|
||
if (next->u.R1005.R1006.t != NULL)
|
||
ffelex_token_kill (next->u.R1005.R1006.t);
|
||
if (next->u.R1005.R1007_or_R1008.t != NULL)
|
||
ffelex_token_kill (next->u.R1005.R1007_or_R1008.t);
|
||
if (next->u.R1005.R1009.t != NULL)
|
||
ffelex_token_kill (next->u.R1005.R1009.t);
|
||
break;
|
||
|
||
case FFESTP_formattypeQ:
|
||
case FFESTP_formattypeDOLLAR:
|
||
case FFESTP_formattypeP:
|
||
case FFESTP_formattypeT:
|
||
case FFESTP_formattypeTL:
|
||
case FFESTP_formattypeTR:
|
||
case FFESTP_formattypeX:
|
||
case FFESTP_formattypeS:
|
||
case FFESTP_formattypeSP:
|
||
case FFESTP_formattypeSS:
|
||
case FFESTP_formattypeBN:
|
||
case FFESTP_formattypeBZ:
|
||
case FFESTP_formattypeSLASH:
|
||
case FFESTP_formattypeCOLON:
|
||
if (next->u.R1010.val.t != NULL)
|
||
ffelex_token_kill (next->u.R1010.val.t);
|
||
break;
|
||
|
||
case FFESTP_formattypeR1016:
|
||
break; /* Nothing more to do. */
|
||
|
||
case FFESTP_formattypeFORMAT:
|
||
if (next->u.R1003D.R1004.t != NULL)
|
||
ffelex_token_kill (next->u.R1003D.R1004.t);
|
||
next->u.R1003D.format->u.root.parent = NULL; /* Parent already dying. */
|
||
ffestt_formatlist_kill (next->u.R1003D.format);
|
||
break;
|
||
|
||
default:
|
||
assert (FALSE);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* ffestt_implist_append -- Append token pair to list of token pairs
|
||
|
||
ffesttImpList list;
|
||
ffelexToken t;
|
||
ffestt_implist_append(list,start_token,end_token);
|
||
|
||
list must have already been created by ffestt_implist_create. The
|
||
list is allocated out of the scratch pool. The tokens are consumed. */
|
||
|
||
void
|
||
ffestt_implist_append (ffesttImpList list, ffelexToken first, ffelexToken last)
|
||
{
|
||
ffesttImpList new;
|
||
|
||
new = (ffesttImpList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST token list", sizeof (*new));
|
||
new->next = list->previous->next;
|
||
new->previous = list->previous;
|
||
new->next->previous = new;
|
||
new->previous->next = new;
|
||
new->first = first;
|
||
new->last = last;
|
||
}
|
||
|
||
/* ffestt_implist_create -- Create new list of token pairs
|
||
|
||
ffesttImpList list;
|
||
list = ffestt_implist_create();
|
||
|
||
The list is allocated out of the scratch pool. */
|
||
|
||
ffesttImpList
|
||
ffestt_implist_create ()
|
||
{
|
||
ffesttImpList new;
|
||
|
||
new = (ffesttImpList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST token list root",
|
||
sizeof (*new));
|
||
new->next = new->previous = new;
|
||
new->first = NULL;
|
||
new->last = NULL;
|
||
return new;
|
||
}
|
||
|
||
/* ffestt_implist_drive -- Drive list of token pairs into function
|
||
|
||
ffesttImpList list;
|
||
void fn(ffelexToken first,ffelexToken last);
|
||
ffestt_implist_drive(list,fn);
|
||
|
||
The token pairs in the list are passed to the function one pair at a time. */
|
||
|
||
void
|
||
ffestt_implist_drive (ffesttImpList list, void (*fn) ())
|
||
{
|
||
ffesttImpList next;
|
||
|
||
if (list == NULL)
|
||
return;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
(*fn) (next->first, next->last);
|
||
}
|
||
}
|
||
|
||
/* ffestt_implist_dump -- Dump list of token pairs
|
||
|
||
ffesttImpList list;
|
||
ffestt_implist_dump(list);
|
||
|
||
The token pairs in the list are dumped with commas separating them. */
|
||
|
||
#if FFECOM_targetCURRENT == FFECOM_targetFFE
|
||
void
|
||
ffestt_implist_dump (ffesttImpList list)
|
||
{
|
||
ffesttImpList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
if (next != list->next)
|
||
fputc (',', dmpout);
|
||
assert (ffelex_token_type (next->first) == FFELEX_typeNAME);
|
||
fputs (ffelex_token_text (next->first), dmpout);
|
||
if (next->last != NULL)
|
||
{
|
||
fputc ('-', dmpout);
|
||
assert (ffelex_token_type (next->last) == FFELEX_typeNAME);
|
||
fputs (ffelex_token_text (next->last), dmpout);
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* ffestt_implist_kill -- Kill list of token pairs
|
||
|
||
ffesttImpList list;
|
||
ffestt_implist_kill(list);
|
||
|
||
The tokens on the list are killed. */
|
||
|
||
void
|
||
ffestt_implist_kill (ffesttImpList list)
|
||
{
|
||
ffesttImpList next;
|
||
|
||
for (next = list->next; next != list; next = next->next)
|
||
{
|
||
ffelex_token_kill (next->first);
|
||
if (next->last != NULL)
|
||
ffelex_token_kill (next->last);
|
||
}
|
||
}
|
||
|
||
/* ffestt_tokenlist_append -- Append token to list of tokens
|
||
|
||
ffesttTokenList tl;
|
||
ffelexToken t;
|
||
ffestt_tokenlist_append(tl,t);
|
||
|
||
tl must have already been created by ffestt_tokenlist_create. The
|
||
list is allocated out of the scratch pool. The token is consumed. */
|
||
|
||
void
|
||
ffestt_tokenlist_append (ffesttTokenList tl, ffelexToken t)
|
||
{
|
||
ffesttTokenItem ti;
|
||
|
||
ti = (ffesttTokenItem) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST token item", sizeof (*ti));
|
||
ti->next = (ffesttTokenItem) &tl->first;
|
||
ti->previous = tl->last;
|
||
ti->next->previous = ti;
|
||
ti->previous->next = ti;
|
||
ti->t = t;
|
||
++tl->count;
|
||
}
|
||
|
||
/* ffestt_tokenlist_create -- Create new list of tokens
|
||
|
||
ffesttTokenList tl;
|
||
tl = ffestt_tokenlist_create();
|
||
|
||
The list is allocated out of the scratch pool. */
|
||
|
||
ffesttTokenList
|
||
ffestt_tokenlist_create ()
|
||
{
|
||
ffesttTokenList tl;
|
||
|
||
tl = (ffesttTokenList) malloc_new_kp (ffesta_scratch_pool,
|
||
"FFEST token list", sizeof (*tl));
|
||
tl->first = tl->last = (ffesttTokenItem) &tl->first;
|
||
tl->count = 0;
|
||
return tl;
|
||
}
|
||
|
||
/* ffestt_tokenlist_drive -- Drive list of tokens
|
||
|
||
ffesttTokenList tl;
|
||
void fn(ffelexToken t);
|
||
ffestt_tokenlist_drive(tl,fn);
|
||
|
||
The tokens in the list are passed to the given function. */
|
||
|
||
void
|
||
ffestt_tokenlist_drive (ffesttTokenList tl, void (*fn) ())
|
||
{
|
||
ffesttTokenItem ti;
|
||
|
||
if (tl == NULL)
|
||
return;
|
||
|
||
for (ti = tl->first; ti != (ffesttTokenItem) &tl->first; ti = ti->next)
|
||
{
|
||
(*fn) (ti->t);
|
||
}
|
||
}
|
||
|
||
/* ffestt_tokenlist_dump -- Dump list of tokens
|
||
|
||
ffesttTokenList tl;
|
||
ffestt_tokenlist_dump(tl);
|
||
|
||
The tokens in the list are dumped with commas separating them. */
|
||
|
||
#if FFECOM_targetCURRENT == FFECOM_targetFFE
|
||
void
|
||
ffestt_tokenlist_dump (ffesttTokenList tl)
|
||
{
|
||
ffesttTokenItem ti;
|
||
|
||
for (ti = tl->first; ti != (ffesttTokenItem) &tl->first; ti = ti->next)
|
||
{
|
||
if (ti != tl->first)
|
||
fputc (',', dmpout);
|
||
switch (ffelex_token_type (ti->t))
|
||
{
|
||
case FFELEX_typeNUMBER:
|
||
case FFELEX_typeNAME:
|
||
case FFELEX_typeNAMES:
|
||
fputs (ffelex_token_text (ti->t), dmpout);
|
||
break;
|
||
|
||
case FFELEX_typeASTERISK:
|
||
fputc ('*', dmpout);
|
||
break;
|
||
|
||
default:
|
||
assert (FALSE);
|
||
fputc ('?', dmpout);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* ffestt_tokenlist_handle -- Handle list of tokens
|
||
|
||
ffesttTokenList tl;
|
||
ffelexHandler handler;
|
||
handler = ffestt_tokenlist_handle(tl,handler);
|
||
|
||
The tokens in the list are passed to the handler(s). */
|
||
|
||
ffelexHandler
|
||
ffestt_tokenlist_handle (ffesttTokenList tl, ffelexHandler handler)
|
||
{
|
||
ffesttTokenItem ti;
|
||
|
||
for (ti = tl->first; ti != (ffesttTokenItem) &tl->first; ti = ti->next)
|
||
handler = (ffelexHandler) (*handler) (ti->t);
|
||
|
||
return (ffelexHandler) handler;
|
||
}
|
||
|
||
/* ffestt_tokenlist_kill -- Kill list of tokens
|
||
|
||
ffesttTokenList tl;
|
||
ffestt_tokenlist_kill(tl);
|
||
|
||
The tokens on the list are killed.
|
||
|
||
02-Mar-90 JCB 1.1
|
||
Don't kill the list itself or change it, since it will be trashed when
|
||
ffesta_scratch_pool is killed anyway, so kill only the lex tokens. */
|
||
|
||
void
|
||
ffestt_tokenlist_kill (ffesttTokenList tl)
|
||
{
|
||
ffesttTokenItem ti;
|
||
|
||
for (ti = tl->first; ti != (ffesttTokenItem) &tl->first; ti = ti->next)
|
||
{
|
||
ffelex_token_kill (ti->t);
|
||
}
|
||
}
|