Logo Search packages:      
Sourcecode: codeblocks version File versions  Download package

headers.c

/*
 * -= Copyright 2005 Tim Baker (treectrl@hotmail.com) =-
 *
 * This file is part of depslib.
 *
 * License is hereby granted to use this software and distribute it
 * freely, as long as this copyright notice is retained and modifications 
 * are clearly marked.
 *
 * ALL WARRANTIES ARE HEREBY DISCLAIMED.
 * 
 * Modifications:
 * - D support (search for "D support")
 * - Depth level counting (needed for D support)
 * - Simple optimization by avoiding regexec most of the time
 * - Special cache keys for source files (needed for D support)
 */
#include "jam.h"
#include "alloc.h"
#include "hash.h"
#include "lists.h"
#include "newstr.h"
#include "regexp.h"
#include "headers.h"
#ifdef USE_CACHE
#include "cache.h"
#endif

#include "depslib.h" /* for struct depsStats */
extern struct depsStats g_stats;

struct hash *headerhash = 0;
static regexp *hdrre = 0;
//D support
static regexp *dimpre = 0;

LIST *headers1(const char *file, int depth)
{
      FILE *f;
      regexp *re;
      LIST *result = 0;
      char buf[1024];
      int fnlen=strlen(file);
      
      //D support
      int dMode=0;
      int dState=0;
      if(file[fnlen-2] == '.' && file[fnlen-1] == 'd')
      {
            dMode=1;
            if( DEBUG_HEADER )
                  printf("D file detected\n");
      }

      if (!(f = fopen(file, "r")))
            return result;

      if( DEBUG_HEADER )
          printf("header scan %s\n", file);

      if (!hdrre)
            hdrre = my_regcomp("^[  ]*#[  ]*include[  ]*([<\"])([^\">]*)([\">]).*$");
      re = hdrre;
      
      //D support
      if(dMode)
      {
            if(!dimpre)
                  dimpre = my_regcomp(
                        "^.*import[ \t]*([[A-Za-z_ \t]+=[ \t]*)?([A-Za-z_\\.]+)(\\:.+)?;.*$");
            re = dimpre;
      }
      
      while (fgets(buf, sizeof(buf), f))
      {
            //D support
            if(dMode)
            {
                  if(dState == 0)
                  {
                        if(strstr(buf, "public"))
                              dState=1;
                  }
                  if(dState >= 1)
                  {
                        if(strchr(buf, '{'))
                              ++dState;
                        if(strchr(buf, '}'))
                              --dState;
                  }
            }
            
            //Simple reduction of regex overhead
            if(strstr(buf, dMode ? "import" : "include"))
                  if (my_regexec(re, buf))
                  {
                        char buf2[MAXSYM];

                        //FIXME: don't add duplicate headers
                        if(!dMode && re->startp[3])
                        {
                              int l = re->endp[3] - re->startp[1];
                              memcpy(buf2, re->startp[1], l);
                              buf2[l] = '\0';
                        }
                        //D support
                        else if(re->startp[2])
                        {
                              if(depth > 0)
                              {
                                    //private import?
                                    if(dState == 0)
                                          continue;
                              }
                              
                              buf2[0] = '<';
                              const char* p;
                              int j = 0;
                              for(p = re->startp[2];p < re->endp[2];++p)
                              {
                                    char c=*p;
                                    ++j;
                                    if(c == '.')
                                          buf2[j] = '/';
                                    else buf2[j] = c;
                              }
                              buf2[++j]='.';
                              buf2[++j]='d';
                              buf2[++j]='>';
                              buf2[++j] = '\0';
                        }
                        result = list_new(result, buf2, 0);

                        if (DEBUG_HEADER)
                              printf("header found: %s\n", buf2);
                  }
            
            //D support
            if(dMode)
            {
                  if(dState == 1)
                  {
                        if(strchr(buf, ';'))
                              dState=0;
                        
                        if(strchr(buf, '}'))
                              dState=0;
                  }
            }
      }

      fclose(f);

      g_stats.scanned++;

      return result;
}

static ALLOC *hdralloc = 0;

HEADERS *headerentry(HEADERS *chain, HEADER *header)
{
      HEADERS *c;

#if 1
      if (!hdralloc)
            hdralloc = alloc_init(sizeof(HEADERS), 64);
      c = (HEADERS *) alloc_enter(hdralloc);
#else
      c = (HEADERS *)malloc(sizeof(HEADERS));
#endif
      c->header = header;

      if (!chain) chain = c;
      else chain->tail->next = c;
      chain->tail = c;
      c->next = 0;

      return chain;
}

HEADER *headersDepth(const char *t, time_t time, int depth)
{
      HEADER hdr, *h = &hdr;
      LIST *l;
      const char* cachekey=t;

      //D support (doesn't affect C(++), because a source file is never included)
      if(depth == 0)
      {
            cachekey=malloc(strlen(t)+sizeof("source:"));
            strcpy((char*)cachekey,"source:");
            strcpy((char*)cachekey+7,t);
      }
      
      if (!headerhash)
            headerhash = hashinit(sizeof(HEADER), "headers");

      h->key = cachekey;
      h->includes = 0;
      h->time = time;
      h->headers = 0;
      h->newest = 0;
      if (!hashenter(headerhash, (HASHDATA **)&h))
            return h;

      h->key = newstr(t);
#ifdef USE_CACHE
      if (!cache_check(cachekey, time, &h->includes))
      {
            h->includes = headers1(t, depth);
            cache_enter(cachekey, time, h->includes);
      }
#else
      h->includes = headers1(t, depth);
#endif
      if(depth == 0)
            free((char*)cachekey);

      l = h->includes;
      while (l)
      {
            const char *t2 = search(t, l->string, &time);
            if (time)
                  h->headers = headerentry(h->headers, headersDepth(t2, time, depth+1));
            l = list_next(l);
      }

      return h;
}

HEADER *headers(const char *t, time_t time)
{
      return headersDepth(t, time, 0);
}

void headernewest(HEADER *h)
{
      HEADERS *hs = h->headers;

      if (h->newest)
            return;
      h->newest = h;
      while (hs)
      {
            headernewest(hs->header);
            if (hs->header->newest->time > h->newest->time)
                  h->newest = hs->header->newest;
            hs = hs->next;
      }
}

void donehdrs(void)
{
      my_redone(hdrre);
      hdrre = 0;
      //D support
      my_redone(dimpre);
      dimpre = 0;
      hashdone(headerhash);
      headerhash = 0;
      alloc_free(hdralloc);
      hdralloc = 0;
}

Generated by  Doxygen 1.6.0   Back to index