Annotation of gcc/cp/repo.c, revision 1.1.1.1

1.1       root        1: /* Code to maintain a C++ template repository.
                      2:    Copyright (C) 1995 Free Software Foundation, Inc.
                      3:    Contributed by Jason Merrill ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify
                      8: it under the terms of the GNU General Public License as published by
                      9: the Free Software Foundation; either version 2, or (at your option)
                     10: any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful,
                     13: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: GNU General Public License for more details.
                     16: 
                     17: You should have received a copy of the GNU General Public License
                     18: along with GNU CC; see the file COPYING.  If not, write to
                     19: the Free Software Foundation, 59 Temple Place - Suite 330,
                     20: Boston, MA 02111-1307, USA.  */
                     21: 
                     22: /* My strategy here is as follows:
                     23: 
                     24:    Everything should be emitted in a translation unit where it is used.
                     25:    The results of the automatic process should be easily reproducible with
                     26:    explicit code.  */
                     27: 
                     28: #include <stdio.h>
                     29: #include "config.h"
                     30: #include "tree.h"
                     31: #include "cp-tree.h"
                     32: #include "input.h"
                     33: #include "obstack.h"
                     34: 
                     35: extern char * rindex ();
                     36: extern char * getenv ();
                     37: extern char * getpwd ();
                     38: 
                     39: static tree pending_repo;
                     40: static tree original_repo;
                     41: static char *repo_name;
                     42: static FILE *repo_file;
                     43: 
                     44: extern int flag_use_repository;
                     45: extern int errorcount, sorrycount;
                     46: extern struct obstack temporary_obstack;
                     47: extern struct obstack permanent_obstack;
                     48: 
                     49: #define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
                     50: #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
                     51: 
                     52: /* Record the flags used to compile this translation unit.  */
                     53: 
                     54: void
                     55: repo_compile_flags (argc, argv)
                     56:      int argc;
                     57:      char **argv;
                     58: {
                     59: }
                     60: 
                     61: /* If this template has not been seen before, add a note to the repository
                     62:    saying where the declaration was.  This may be used to find the
                     63:    definition at link time.  */
                     64: 
                     65: void
                     66: repo_template_declared (t)
                     67:      tree t;
                     68: {}
                     69: 
                     70: /* Note where the definition of a template lives so that instantiations can
                     71:    be generated later.  */
                     72: 
                     73: void
                     74: repo_template_defined (t)
                     75:      tree t;
                     76: {}
                     77: 
                     78: /* Note where the definition of a class lives to that template
                     79:    instantiations can use it.  */
                     80: 
                     81: void
                     82: repo_class_defined (t)
                     83:      tree t;
                     84: {}
                     85: 
                     86: tree
                     87: repo_get_id (t)
                     88:      tree t;
                     89: {
                     90:   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
                     91:     {
                     92:       t = TYPE_BINFO_VTABLE (t);
                     93:       if (t == NULL_TREE)
                     94:        return t;
                     95:     }
                     96:   return DECL_ASSEMBLER_NAME (t);
                     97: }
                     98: 
                     99: /* Note that a template has been used.  If we can see the definition, offer
                    100:    to emit it. */
                    101: 
                    102: void
                    103: repo_template_used (t)
                    104:      tree t;
                    105: {
                    106:   tree id;
                    107: 
                    108:   if (! flag_use_repository)
                    109:     return;
                    110: 
                    111:   id = repo_get_id (t);
                    112:   if (id == NULL_TREE)
                    113:     return;
                    114:   
                    115:   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
                    116:     {
                    117:       if (IDENTIFIER_REPO_CHOSEN (id))
                    118:        mark_class_instantiated (t, 0);
                    119:     }
                    120:   else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
                    121:     {
                    122:       if (IDENTIFIER_REPO_CHOSEN (id))
                    123:        mark_function_instantiated (t, 0);
                    124:     }
                    125:   else
                    126:     my_friendly_abort (1);
                    127: 
                    128:   if (! IDENTIFIER_REPO_USED (id))
                    129:     {
                    130:       IDENTIFIER_REPO_USED (id) = 1;
                    131:       pending_repo = perm_tree_cons (NULL_TREE, id, pending_repo);
                    132:     }
                    133: }
                    134: 
                    135: /* Note that the vtable for a class has been used, and offer to emit it.  */
                    136: 
                    137: void
                    138: repo_vtable_used (t)
                    139:      tree t;
                    140: {
                    141:   if (! flag_use_repository)
                    142:     return;
                    143: 
                    144:   pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
                    145: }
                    146: 
                    147: /* Note that an inline with external linkage has been used, and offer to
                    148:    emit it.  */
                    149: 
                    150: void
                    151: repo_inline_used (fn)
                    152:      tree fn;
                    153: {
                    154:   if (! flag_use_repository)
                    155:     return;
                    156: 
                    157:   /* Member functions of polymorphic classes go with their vtables.  */
                    158:   if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn)))
                    159:     {
                    160:       repo_vtable_used (DECL_CLASS_CONTEXT (fn));
                    161:       return;
                    162:     }
                    163: 
                    164:   pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo);
                    165: }
                    166: 
                    167: /* Note that a particular typeinfo node has been used, and offer to
                    168:    emit it.  */
                    169: 
                    170: void
                    171: repo_tinfo_used (ti)
                    172:      tree ti;
                    173: {
                    174: }
                    175: 
                    176: void
                    177: repo_template_instantiated (t, extern_p)
                    178:      tree t;
                    179:      int extern_p;
                    180: {
                    181:   if (! extern_p)
                    182:     {
                    183:       tree id = repo_get_id (t);
                    184:       if (id)
                    185:        IDENTIFIER_REPO_CHOSEN (id) = 1;
                    186:     }
                    187: }
                    188: 
                    189: static char *
                    190: save_string (s, len)
                    191:      char *s;
                    192:      int len;
                    193: {
                    194:   return obstack_copy0 (&temporary_obstack, s, len);
                    195: }
                    196: 
                    197: static char *
                    198: get_base_filename (filename)
                    199:      char *filename;
                    200: {
                    201:   char *p = getenv ("COLLECT_GCC_OPTIONS");
                    202:   char *output = 0;
                    203:   int compiling = 0;
                    204: 
                    205:   if (p)
                    206:     while (*p)
                    207:       {
                    208:        char *q = p;
                    209:        while (*q && *q != ' ') q++;
                    210:        if (*p == '-' && p[1] == 'o')
                    211:          {
                    212:            p += 2;
                    213:            if (p == q)
                    214:              {
                    215:                p++; q++;
                    216:                if (*q)
                    217:                  while (*q && *q != ' ') q++;
                    218:              }
                    219: 
                    220:            output = save_string (p, q - p);
                    221:          }
                    222:        else if (*p == '-' && p[1] == 'c')
                    223:          compiling = 1;
                    224:        if (*q) q++;
                    225:        p = q;
                    226:       }
                    227: 
                    228:   if (compiling && output)
                    229:     return output;
                    230: 
                    231:   if (p && ! compiling)
                    232:     {
                    233:       warning ("-frepo must be used with -c");
                    234:       flag_use_repository = 0;
                    235:       return NULL;
                    236:     }
                    237: 
                    238:   p = rindex (filename, '/');
                    239:   if (p)
                    240:     return p+1;
                    241:   else
                    242:     return filename;
                    243: }        
                    244: 
                    245: static void
                    246: open_repo_file (filename)
                    247:      char *filename;
                    248: {
                    249:   register char *p, *q;
                    250:   char *s = get_base_filename (filename);
                    251: 
                    252:   if (s == NULL)
                    253:     return;
                    254: 
                    255:   p = rindex (s, '/');
                    256:   if (! p)
                    257:     p = s;
                    258:   p = rindex (p, '.');
                    259:   if (! p)
                    260:     p = s + strlen (s);
                    261: 
                    262:   obstack_grow (&permanent_obstack, s, p - s);
                    263:   repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4);
                    264: 
                    265:   repo_file = fopen (repo_name, "r");
                    266: }
                    267: 
                    268: static char *
                    269: afgets (stream)
                    270:      FILE *stream;
                    271: {
                    272:   int c;
                    273:   while ((c = getc (stream)) != EOF && c != '\n')
                    274:     obstack_1grow (&temporary_obstack, c);
                    275:   if (obstack_object_size (&temporary_obstack) == 0)
                    276:     return NULL;
                    277:   obstack_1grow (&temporary_obstack, '\0');
                    278:   return obstack_finish (&temporary_obstack);
                    279: }
                    280: 
                    281: void
                    282: init_repo (filename)
                    283:      char *filename;
                    284: {
                    285:   char *buf;
                    286: 
                    287:   if (! flag_use_repository)
                    288:     return;
                    289: 
                    290:   open_repo_file (filename);
                    291: 
                    292:   if (repo_file == 0)
                    293:     return;
                    294: 
                    295:   while (buf = afgets (repo_file))
                    296:     {
                    297:       switch (buf[0])
                    298:        {
                    299:        case 'A':
                    300:        case 'D':
                    301:        case 'M':
                    302:          break;
                    303:        case 'C':
                    304:        case 'O':
                    305:          {
                    306:            tree id = get_identifier (buf + 2);
                    307:            tree orig;
                    308: 
                    309:            if (buf[0] == 'C')
                    310:              {
                    311:                IDENTIFIER_REPO_CHOSEN (id) = 1;
                    312:                orig = integer_one_node;
                    313:              }
                    314:            else
                    315:              orig = NULL_TREE;
                    316: 
                    317:            original_repo = perm_tree_cons (orig, id, original_repo);
                    318:          }
                    319:          break;
                    320:        default:
                    321:          error ("mysterious repository information in %s", repo_name);
                    322:        }
                    323:       obstack_free (&temporary_obstack, buf);
                    324:     }
                    325: }
                    326: 
                    327: static void
                    328: reopen_repo_file_for_write ()
                    329: {
                    330:   if (repo_file)
                    331:     fclose (repo_file);
                    332:   repo_file = fopen (repo_name, "w");
                    333: 
                    334:   if (repo_file == 0)
                    335:     {
                    336:       error ("can't create repository information file `%s'", repo_name);
                    337:       flag_use_repository = 0;
                    338:     }
                    339: }
                    340: 
                    341: /* Emit any pending repos.  */
                    342: 
                    343: void
                    344: finish_repo ()
                    345: {
                    346:   tree t;
                    347:   char *p;
                    348:   int repo_changed = 0;
                    349: 
                    350:   if (! flag_use_repository)
                    351:     return;
                    352: 
                    353:   /* Do we have to write out a new info file?  */
                    354: 
                    355:   /* Are there any old templates that aren't used any longer or that are
                    356:      newly chosen?  */
                    357:   
                    358:   for (t = original_repo; t; t = TREE_CHAIN (t))
                    359:     {
                    360:       if (! IDENTIFIER_REPO_USED (TREE_VALUE (t))
                    361:          || (! TREE_PURPOSE (t) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t))))
                    362:        {
                    363:          repo_changed = 1;
                    364:          break;
                    365:        }
                    366:       IDENTIFIER_REPO_USED (TREE_VALUE (t)) = 0;
                    367:     }
                    368: 
                    369:   /* Are there any templates that are newly used?  */
                    370:   
                    371:   if (! repo_changed)
                    372:     for (t = pending_repo; t; t = TREE_CHAIN (t))
                    373:       {
                    374:        if (IDENTIFIER_REPO_USED (TREE_VALUE (t)))
                    375:          {
                    376:            repo_changed = 1;
                    377:            break;
                    378:          }
                    379:       }
                    380: 
                    381:   if (! repo_changed || errorcount || sorrycount)
                    382:     goto out;
                    383: 
                    384:   reopen_repo_file_for_write ();
                    385: 
                    386:   if (repo_file == 0)
                    387:     goto out;
                    388: 
                    389:   fprintf (repo_file, "M %s\n", main_input_filename);
                    390: 
                    391:   p = getpwd ();
                    392:   fprintf (repo_file, "D %s\n", p);
                    393: 
                    394:   p = getenv ("COLLECT_GCC_OPTIONS");
                    395:   if (p != 0)
                    396:     fprintf (repo_file, "A %s\n", p);
                    397: 
                    398:   for (t = pending_repo; t; t = TREE_CHAIN (t))
                    399:     {
                    400:       tree val = TREE_VALUE (t);
                    401:       char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
                    402: 
                    403:       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
                    404:     }
                    405: 
                    406:  out:
                    407:   if (repo_file)
                    408:     fclose (repo_file);
                    409: }

unix.superglobalmegacorp.com

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