/* stt.c -- Implementation File (module.c template V1.0) Copyright (C) 1995, 1997 Free Software Foundation, Inc. Contributed by James Craig Burley (burley@gnu.ai.mit.edu). 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. */ 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); } } } /* 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. */ 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); } } /* 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. */ 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); } } /* 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. */ 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); } } } /* 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 -- Dump 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. */ 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; } } } /* 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); } }