Annotation of GNUtools/cc/c-iterate.c, revision 1.1

1.1     ! root        1: /* Build expressions with type checking for C compiler.
        !             2:    Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 2, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /* This file is part of the C front end.
        !            22:    It is responsible for implementing iterators,
        !            23:    both their declarations and the expansion of statements using them.  */
        !            24: 
        !            25: #include "config.h"
        !            26: #include <stdio.h>
        !            27: #include "tree.h"
        !            28: #include "c-tree.h"
        !            29: #include "flags.h"
        !            30: #include "obstack.h"
        !            31: #include "rtl.h"
        !            32: 
        !            33: static void expand_stmt_with_iterators_1 ();
        !            34: static tree collect_iterators ();
        !            35: static void iterator_loop_prologue ();
        !            36: static void iterator_loop_epilogue ();
        !            37: static void add_ixpansion ();
        !            38: static void delete_ixpansion();
        !            39: static int top_level_ixpansion_p ();
        !            40: static void istack_sublevel_to_current ();
        !            41: 
        !            42: /* A special obstack, and a pointer to the start of
        !            43:    all the data in it (so we can free everything easily).  */
        !            44: static struct obstack ixp_obstack;
        !            45: static char *ixp_firstobj;
        !            46: 
        !            47: /*
        !            48:                KEEPING TRACK OF EXPANSIONS
        !            49: 
        !            50:    In order to clean out expansions corresponding to statements inside
        !            51:    "{(...)}" constructs we have to keep track of all expansions.  The
        !            52:    cleanup is needed when an automatic, or implicit, expansion on
        !            53:    iterator, say X, happens to a statement which contains a {(...)}
        !            54:    form with a statement already expanded on X.  In this case we have
        !            55:    to go back and cleanup the inner expansion.  This can be further
        !            56:    complicated by the fact that {(...)} can be nested.
        !            57: 
        !            58:    To make this cleanup possible, we keep lists of all expansions, and
        !            59:    to make it work for nested constructs, we keep a stack.  The list at
        !            60:    the top of the stack (ITER_STACK.CURRENT_LEVEL) corresponds to the
        !            61:    currently parsed level.  All expansions of the levels below the
        !            62:    current one are kept in one list whose head is pointed to by
        !            63:    ITER_STACK.SUBLEVEL_FIRST (SUBLEVEL_LAST is there for making merges
        !            64:    easy).  The process works as follows:
        !            65: 
        !            66:    -- On "({"  a new node is added to the stack by PUSH_ITERATOR_STACK.
        !            67:               The sublevel list is not changed at this point.
        !            68: 
        !            69:    -- On "})" the list for the current level is appended to the sublevel
        !            70:              list. 
        !            71: 
        !            72:    -- On ";"  sublevel lists are appended to the current level lists.
        !            73:              The reason is this: if they have not been superseded by the
        !            74:              expansion at the current level, they still might be
        !            75:              superseded later by the expansion on the higher level.
        !            76:              The levels do not have to distinguish levels below, so we
        !            77:              can merge the lists together.  */
        !            78: 
        !            79: struct  ixpansion
        !            80: {
        !            81:   tree ixdecl;                 /* Iterator decl */
        !            82:   rtx  ixprologue_start;       /* First insn of epilogue. NULL means */
        !            83:   /* explicit (FOR) expansion*/
        !            84:   rtx  ixprologue_end;
        !            85:   rtx  ixepilogue_start;
        !            86:   rtx  ixepilogue_end;
        !            87:   struct ixpansion *next;      /* Next in the list */
        !            88: };
        !            89: 
        !            90: struct iter_stack_node
        !            91: {
        !            92:   struct ixpansion *first;     /* Head of list of ixpansions */
        !            93:   struct ixpansion *last;      /* Last node in list  of ixpansions */
        !            94:   struct iter_stack_node *next; /* Next level iterator stack node  */
        !            95: };
        !            96: 
        !            97: struct iter_stack_node *iter_stack;
        !            98: 
        !            99: struct iter_stack_node sublevel_ixpansions;
        !           100: 
        !           101: /* During collect_iterators, a list of SAVE_EXPRs already scanned.  */
        !           102: static tree save_exprs;
        !           103: 
        !           104: /* Initialize our obstack once per compilation.  */
        !           105: 
        !           106: void
        !           107: init_iterators ()
        !           108: {
        !           109:   gcc_obstack_init (&ixp_obstack);
        !           110:   ixp_firstobj = (char *) obstack_alloc (&ixp_obstack, 0);
        !           111: }
        !           112: 
        !           113: /* Handle the start of an explicit `for' loop for iterator IDECL.  */
        !           114: 
        !           115: void
        !           116: iterator_for_loop_start (idecl)
        !           117:      tree idecl;
        !           118: {
        !           119:   ITERATOR_BOUND_P (idecl) = 1;
        !           120:   add_ixpansion (idecl, 0, 0, 0, 0);
        !           121:   iterator_loop_prologue (idecl, 0, 0);
        !           122: }
        !           123: 
        !           124: /* Handle the end of an explicit `for' loop for iterator IDECL.  */
        !           125: 
        !           126: void
        !           127: iterator_for_loop_end (idecl)
        !           128:      tree idecl;
        !           129: {
        !           130:   iterator_loop_epilogue (idecl, 0, 0);
        !           131:   ITERATOR_BOUND_P (idecl) = 0;
        !           132: }
        !           133: 
        !           134: /*
        !           135:                ITERATOR RTL EXPANSIONS
        !           136: 
        !           137:    Expanding simple statements with iterators is straightforward:
        !           138:    collect the list of all free iterators in the statement, and
        !           139:    generate a loop for each of them.
        !           140: 
        !           141:    An iterator is "free" if it has not been "bound" by a FOR
        !           142:    operator.  The DECL_RTL of the iterator is the loop counter.  */
        !           143: 
        !           144: /* Expand a statement STMT, possibly containing iterator usage, into RTL.  */
        !           145: 
        !           146: void
        !           147: iterator_expand (stmt)
        !           148:     tree stmt;
        !           149: {
        !           150:   tree iter_list;
        !           151:   save_exprs = NULL_TREE;
        !           152:   iter_list = collect_iterators (stmt, NULL_TREE);
        !           153:   expand_stmt_with_iterators_1 (stmt, iter_list);
        !           154:   istack_sublevel_to_current ();
        !           155: }
        !           156: 
        !           157: 
        !           158: static void 
        !           159: expand_stmt_with_iterators_1 (stmt, iter_list)
        !           160:      tree stmt, iter_list;
        !           161: {
        !           162:   if (iter_list == 0)
        !           163:     expand_expr_stmt (stmt);
        !           164:   else
        !           165:     {
        !           166:       tree current_iterator = TREE_VALUE (iter_list);
        !           167:       tree iter_list_tail   = TREE_CHAIN (iter_list);
        !           168:       rtx p_start, p_end, e_start, e_end;
        !           169: 
        !           170:       iterator_loop_prologue (current_iterator, &p_start, &p_end);
        !           171:       expand_stmt_with_iterators_1 (stmt, iter_list_tail);
        !           172:       iterator_loop_epilogue (current_iterator, &e_start, &e_end);
        !           173: 
        !           174:       /** Delete all inner expansions based on current_iterator **/
        !           175:       /** before adding the outer one. **/
        !           176: 
        !           177:       delete_ixpansion (current_iterator);
        !           178:       add_ixpansion (current_iterator, p_start, p_end, e_start, e_end);
        !           179:     }
        !           180: }
        !           181: 
        !           182: 
        !           183: /* Return a list containing all the free (i.e. not bound by a
        !           184:    containing `for' statement) iterators mentioned in EXP, plus those
        !           185:    in LIST.  Do not add duplicate entries to the list.  */
        !           186: 
        !           187: static tree
        !           188: collect_iterators (exp, list)
        !           189:      tree exp, list;
        !           190: {
        !           191:   if (exp == 0) return list;
        !           192: 
        !           193:   switch (TREE_CODE (exp))
        !           194:     {
        !           195:     case VAR_DECL:
        !           196:       if (! ITERATOR_P (exp) || ITERATOR_BOUND_P (exp))
        !           197:        return list;
        !           198:       if (value_member (exp, list))
        !           199:        return list;
        !           200:       return tree_cons (NULL_TREE, exp, list);
        !           201: 
        !           202:     case TREE_LIST:
        !           203:       {
        !           204:        tree tail;
        !           205:        for (tail = exp; tail; tail = TREE_CHAIN (tail))
        !           206:          list = collect_iterators (TREE_VALUE (tail), list);
        !           207:        return list;
        !           208:       }
        !           209: 
        !           210:     case SAVE_EXPR:
        !           211:       /* In each scan, scan a given save_expr only once.  */
        !           212:       if (value_member (exp, save_exprs))
        !           213:        return list;
        !           214: 
        !           215:       save_exprs = tree_cons (NULL_TREE, exp, save_exprs);
        !           216:       return collect_iterators (TREE_OPERAND (exp, 0), list);
        !           217: 
        !           218:       /* we do not automatically iterate blocks -- one must */
        !           219:       /* use the FOR construct to do that */
        !           220: 
        !           221:     case BLOCK:
        !           222:       return list;
        !           223: 
        !           224:     default:
        !           225:       switch (TREE_CODE_CLASS (TREE_CODE (exp)))
        !           226:        {
        !           227:        case '1':
        !           228:          return collect_iterators (TREE_OPERAND (exp, 0), list);
        !           229: 
        !           230:        case '2':
        !           231:        case '<':
        !           232:          return collect_iterators (TREE_OPERAND (exp, 0),
        !           233:                                    collect_iterators (TREE_OPERAND (exp, 1),
        !           234:                                                       list));
        !           235: 
        !           236:        case 'e':
        !           237:        case 'r':
        !           238:          {
        !           239:            int num_args = tree_code_length[(int) TREE_CODE (exp)];
        !           240:            int i;
        !           241: 
        !           242:            /* Some tree codes have RTL, not trees, as operands.  */
        !           243:            switch (TREE_CODE (exp))
        !           244:              {
        !           245:              case CALL_EXPR:
        !           246:                num_args = 2;
        !           247:                break;
        !           248:              case METHOD_CALL_EXPR:
        !           249:                num_args = 3;
        !           250:                break;
        !           251:              case WITH_CLEANUP_EXPR:
        !           252:                num_args = 1;
        !           253:                break;
        !           254:              case RTL_EXPR:
        !           255:                return list;
        !           256:              }
        !           257:                
        !           258:            for (i = 0; i < num_args; i++)
        !           259:              list = collect_iterators (TREE_OPERAND (exp, i), list);
        !           260:            return list;
        !           261:          }
        !           262:        default:
        !           263:          return list;
        !           264:        }
        !           265:     }
        !           266: }
        !           267: 
        !           268: /* Emit rtl for the start of a loop for iterator IDECL.
        !           269: 
        !           270:    If necessary, create loop counter rtx and store it as DECL_RTL of IDECL.
        !           271: 
        !           272:    The prologue normally starts and ends with notes, which are returned
        !           273:    by this function in *START_NOTE and *END_NODE.
        !           274:    If START_NOTE and END_NODE are 0, we don't make those notes.  */
        !           275: 
        !           276: static void
        !           277: iterator_loop_prologue (idecl, start_note, end_note)
        !           278:      tree idecl;
        !           279:      rtx *start_note, *end_note;
        !           280: {
        !           281:   tree expr;
        !           282: 
        !           283:   /* Force the save_expr in DECL_INITIAL to be calculated
        !           284:      if it hasn't been calculated yet.  */
        !           285:   expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode, 0);
        !           286: 
        !           287:   if (DECL_RTL (idecl) == 0)
        !           288:     expand_decl (idecl);
        !           289: 
        !           290:   if (start_note)
        !           291:     *start_note = emit_note (0, NOTE_INSN_DELETED);
        !           292: 
        !           293:   /* Initialize counter.  */
        !           294:   expr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, integer_zero_node);
        !           295:   TREE_SIDE_EFFECTS (expr) = 1;
        !           296:   expand_expr (expr, const0_rtx, VOIDmode, 0);
        !           297: 
        !           298:   expand_start_loop_continue_elsewhere (1);
        !           299: 
        !           300:   ITERATOR_BOUND_P (idecl) = 1;
        !           301: 
        !           302:   if (end_note)
        !           303:     *end_note = emit_note (0, NOTE_INSN_DELETED);
        !           304: }
        !           305: 
        !           306: /* Similar to the previous function, but for the end of the loop.
        !           307: 
        !           308:    DECL_RTL is zeroed unless we are inside "({...})". The reason for that is
        !           309:    described below.
        !           310: 
        !           311:    When we create two (or more) loops based on the same IDECL, and
        !           312:    both inside the same "({...})"  construct, we must be prepared to
        !           313:    delete both of the loops and create a single one on the level
        !           314:    above, i.e.  enclosing the "({...})". The new loop has to use the
        !           315:    same counter rtl because the references to the iterator decl
        !           316:    (IDECL) have already been expanded as references to the counter
        !           317:    rtl.
        !           318: 
        !           319:    It is incorrect to use the same counter reg in different functions,
        !           320:    and it is desirable to use different counters in disjoint loops
        !           321:    when we know there's no need to combine them (because then they can
        !           322:    get allocated separately).  */
        !           323: 
        !           324: static void
        !           325: iterator_loop_epilogue (idecl, start_note, end_note)
        !           326:      tree idecl;
        !           327:      rtx *start_note, *end_note;
        !           328: {
        !           329:   tree test, incr;
        !           330: 
        !           331:   if (start_note)
        !           332:     *start_note = emit_note (0, NOTE_INSN_DELETED);
        !           333:   expand_loop_continue_here ();
        !           334:   incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0);
        !           335:   incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr);
        !           336:   TREE_SIDE_EFFECTS (incr) = 1;
        !           337:   expand_expr (incr, const0_rtx, VOIDmode, 0);
        !           338:   test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0);
        !           339:   expand_exit_loop_if_false (0, test);
        !           340:   expand_end_loop ();
        !           341: 
        !           342:   ITERATOR_BOUND_P (idecl) = 0;
        !           343:   /* we can reset rtl since there is not chance that this expansion */
        !           344:   /* would be superceded by a higher level one */
        !           345:   if (top_level_ixpansion_p ())
        !           346:     DECL_RTL (idecl) = 0;
        !           347:   if (end_note)
        !           348:     *end_note = emit_note (0, NOTE_INSN_DELETED);
        !           349: }
        !           350: 
        !           351: /* Return true if we are not currently inside a "({...})" construct.  */
        !           352: 
        !           353: static int
        !           354: top_level_ixpansion_p ()
        !           355: {
        !           356:   return iter_stack == 0;
        !           357: }
        !           358: 
        !           359: /* Given two chains of iter_stack_nodes,
        !           360:    append the nodes in X into Y.  */
        !           361: 
        !           362: static void
        !           363: isn_append (x, y)
        !           364:      struct iter_stack_node *x, *y;
        !           365: {
        !           366:   if (x->first == 0) 
        !           367:     return;
        !           368: 
        !           369:   if (y->first == 0)
        !           370:     {
        !           371:       y->first = x->first;
        !           372:       y->last  = x->last;
        !           373:     }
        !           374:   else
        !           375:     {
        !           376:       y->last->next = x->first;
        !           377:       y->last = x->last;
        !           378:     }
        !           379: }
        !           380: 
        !           381: /** Make X empty **/
        !           382: 
        !           383: #define ISN_ZERO(X) (X).first=(X).last=0
        !           384: 
        !           385: /* Move the ixpansions in sublevel_ixpansions into the current
        !           386:    node on the iter_stack, or discard them if the iter_stack is empty.
        !           387:    We do this at the end of a statement.  */
        !           388: 
        !           389: static void
        !           390: istack_sublevel_to_current ()
        !           391: {
        !           392:   /* At the top level we can throw away sublevel's expansions  **/
        !           393:   /* because there is nobody above us to ask for a cleanup **/
        !           394:   if (iter_stack != 0)
        !           395:     /** Merging with empty sublevel list is a no-op **/
        !           396:     if (sublevel_ixpansions.last)
        !           397:       isn_append (&sublevel_ixpansions, iter_stack);
        !           398: 
        !           399:   if (iter_stack == 0)
        !           400:     obstack_free (&ixp_obstack, ixp_firstobj);
        !           401: 
        !           402:   ISN_ZERO (sublevel_ixpansions);
        !           403: }
        !           404: 
        !           405: /* Push a new node on the iter_stack, when we enter a ({...}).  */
        !           406: 
        !           407: void
        !           408: push_iterator_stack ()
        !           409: {
        !           410:   struct iter_stack_node *new_top
        !           411:     = (struct iter_stack_node*) 
        !           412:       obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node));
        !           413: 
        !           414:   new_top->first = 0;
        !           415:   new_top->last = 0;
        !           416:   new_top->next = iter_stack;
        !           417:   iter_stack = new_top;
        !           418: }
        !           419: 
        !           420: /* Pop iter_stack, moving the ixpansions in the node being popped
        !           421:    into sublevel_ixpansions.  */
        !           422: 
        !           423: void
        !           424: pop_iterator_stack ()
        !           425: {
        !           426:   if (iter_stack == 0)
        !           427:     abort ();
        !           428: 
        !           429:   isn_append (iter_stack, &sublevel_ixpansions);
        !           430:   /** Pop current level node: */
        !           431:   iter_stack = iter_stack->next;
        !           432: }
        !           433: 
        !           434: 
        !           435: /* Record an iterator expansion ("ixpansion") for IDECL.
        !           436:    The remaining paramters are the notes in the loop entry
        !           437:    and exit rtl.  */
        !           438: 
        !           439: static void
        !           440: add_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end)
        !           441:      tree idecl;
        !           442:      rtx pro_start, pro_end, epi_start, epi_end;
        !           443: {
        !           444:   struct ixpansion* newix;
        !           445:     
        !           446:   /* Do nothing if we are not inside "({...})",
        !           447:      as in that case this expansion can't need subsequent RTL modification.  */
        !           448:   if (iter_stack == 0)
        !           449:     return;
        !           450: 
        !           451:   newix = (struct ixpansion*) obstack_alloc (&ixp_obstack,
        !           452:                                             sizeof (struct ixpansion));
        !           453:   newix->ixdecl = idecl;
        !           454:   newix->ixprologue_start = pro_start;
        !           455:   newix->ixprologue_end   = pro_end;
        !           456:   newix->ixepilogue_start = epi_start;
        !           457:   newix->ixepilogue_end   = epi_end;
        !           458: 
        !           459:   newix->next = iter_stack->first;
        !           460:   iter_stack->first = newix;
        !           461:   if (iter_stack->last == 0)
        !           462:     iter_stack->last = newix;
        !           463: }
        !           464: 
        !           465: /* Delete the RTL for all ixpansions for iterator IDECL
        !           466:    in our sublevels.  We do this when we make a larger
        !           467:    containing expansion for IDECL.  */
        !           468: 
        !           469: static void
        !           470: delete_ixpansion (idecl)
        !           471:      tree idecl;
        !           472: {
        !           473:   struct ixpansion* previx = 0, *ix;
        !           474: 
        !           475:   for (ix = sublevel_ixpansions.first; ix; ix = ix->next)
        !           476:     if (ix->ixdecl == idecl)
        !           477:       {
        !           478:        /** zero means that this is a mark for FOR -- **/
        !           479:        /** we do not delete anything, just issue an error. **/
        !           480: 
        !           481:        if (ix->ixprologue_start == 0)
        !           482:          error_with_decl (idecl,
        !           483:                           "`for (%s)' appears within implicit iteration");
        !           484:        else
        !           485:          {
        !           486:            rtx insn;
        !           487:            /* We delete all insns, including notes because leaving loop */
        !           488:            /* notes and barriers produced by iterator expansion would */
        !           489:            /* be misleading to other phases */
        !           490: 
        !           491:            for (insn = NEXT_INSN (ix->ixprologue_start);
        !           492:                 insn != ix->ixprologue_end;
        !           493:                 insn = NEXT_INSN (insn)) 
        !           494:              delete_insn (insn);
        !           495:            for (insn = NEXT_INSN (ix->ixepilogue_start);
        !           496:                 insn != ix->ixepilogue_end;
        !           497:                 insn = NEXT_INSN (insn)) 
        !           498:              delete_insn (insn);
        !           499:          }
        !           500: 
        !           501:        /* Delete this ixpansion from sublevel_ixpansions.  */
        !           502:        if (previx)
        !           503:          previx->next = ix->next;
        !           504:        else 
        !           505:          sublevel_ixpansions.first = ix->next;
        !           506:        if (sublevel_ixpansions.last == ix)
        !           507:          sublevel_ixpansions.last = previx;
        !           508:       }
        !           509:     else
        !           510:       previx = ix;
        !           511: }
        !           512: 
        !           513: #ifdef DEBUG_ITERATORS
        !           514: 
        !           515: /* The functions below are for use from source level debugger.
        !           516:    They print short forms of iterator lists and the iterator stack.  */
        !           517: 
        !           518: /* Print the name of the iterator D.  */
        !           519: 
        !           520: void
        !           521: prdecl (d)
        !           522:      tree d;
        !           523: {
        !           524:   if (d)
        !           525:     {
        !           526:       if (TREE_CODE (d) == VAR_DECL)
        !           527:        {
        !           528:          tree tname = DECL_NAME (d);
        !           529:          char *dname = IDENTIFIER_POINTER (tname);
        !           530:          fprintf (stderr, dname);
        !           531:        }
        !           532:       else
        !           533:        fprintf (stderr, "<<Not a Decl!!!>>");
        !           534:     }
        !           535:   else
        !           536:     fprintf (stderr, "<<NULL!!>>");
        !           537: }
        !           538: 
        !           539: /* Print Iterator List -- names only */
        !           540: 
        !           541: tree
        !           542: pil (head)
        !           543:      tree head;
        !           544: {
        !           545:   tree current, next;
        !           546:   for (current = head; current; current = next)
        !           547:     {
        !           548:       tree node = TREE_VALUE (current);
        !           549:       prdecl (node);
        !           550:       next = TREE_CHAIN (current);
        !           551:       if (next) fprintf (stderr, ",");
        !           552:     }
        !           553:   fprintf (stderr, "\n");
        !           554: }
        !           555: 
        !           556: /* Print IXpansion List */
        !           557: 
        !           558: struct ixpansion *
        !           559: pixl (head)
        !           560:      struct ixpansion *head;
        !           561: {
        !           562:   struct ixpansion *current, *next;
        !           563:   fprintf (stderr, "> ");
        !           564:   if (head == 0)
        !           565:     fprintf (stderr, "(empty)");
        !           566:        
        !           567:   for (current=head; current; current = next)
        !           568:     {
        !           569:       tree node = current->ixdecl;
        !           570:       prdecl (node);
        !           571:       next = current->next;
        !           572:       if (next)
        !           573:        fprintf (stderr, ",");
        !           574:     }
        !           575:   fprintf (stderr, "\n");
        !           576:   return head;
        !           577: }
        !           578: 
        !           579: /* Print Iterator Stack*/
        !           580: 
        !           581: void
        !           582: pis ()
        !           583: {
        !           584:   struct iter_stack_node *stack_node;
        !           585: 
        !           586:   fprintf (stderr, "--SubLevel: ");
        !           587:   pixl (sublevel_ixpansions.first);
        !           588:   fprintf (stderr, "--Stack:--\n");
        !           589:   for (stack_node = iter_stack;
        !           590:        stack_node;
        !           591:        stack_node = stack_node->next)
        !           592:     pixl (stack_node->first);
        !           593: }
        !           594: 
        !           595: #endif /* DEBUG_ITERATORS */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.