LTP GCOV extension - code coverage report
Current view: directory - src/libexpr - parser.cc
Test: app.info
Date: 2004-12-21 Instrumented lines: 60
Code covered: 90.0 % Executed lines: 54

       1                 : #include <sstream>
       2                 : 
       3                 : #include <sys/types.h>
       4                 : #include <sys/stat.h>
       5                 : #include <fcntl.h>
       6                 : #include <unistd.h>
       7                 : 
       8                 : #include "aterm.hh"
       9                 : #include "parser.hh"
      10                 : #include "nixexpr-ast.hh"
      11                 : 
      12                 : 
      13                 : struct ParseData 
      14                 : {
      15                 :     Expr result;
      16                 :     Path basePath;
      17                 :     Path path;
      18                 :     string error;
      19                 : };
      20                 : 
      21                 : 
      22                 : extern "C" {
      23                 : 
      24                 : #include "parser-tab.h"
      25                 : #include "lexer-tab.h"
      26                 :     
      27                 : /* Callbacks for getting from C to C++.  Due to a (small) bug in the
      28                 :    GLR code of Bison we cannot currently compile the parser as C++
      29                 :    code. */
      30                 : 
      31                 : void setParseResult(ParseData * data, ATerm t)
      32              23 : {
      33              23 :     data->result = t;
      34                 : }
      35                 : 
      36                 : ATerm absParsedPath(ParseData * data, ATerm t)
      37              19 : {
      38              19 :     return toATerm(absPath(aterm2String(t), data->basePath));
      39                 : }
      40                 :     
      41                 : void parseError(ParseData * data, char * error, int line, int column)
      42               0 : {
      43               0 :     data->error = (format("%1%, at `%2%':%3%:%4%")
      44                 :         % error % data->path % line % column).str();
      45                 : }
      46                 :         
      47                 : ATerm fixAttrs(int recursive, ATermList as)
      48              32 : {
      49              32 :     ATermList bs = ATempty, cs = ATempty;
      50              32 :     ATermList * is = recursive ? &cs : &bs;
      51             150 :     for (ATermIterator i(as); i; ++i) {
      52             118 :         ATermList names;
      53             118 :         Expr src;
      54             118 :         ATerm pos;
      55             118 :         if (matchInherit(*i, src, names, pos)) {
      56               6 :             bool fromScope = matchScope(src);
      57              22 :             for (ATermIterator j(names); j; ++j) {
      58              16 :                 Expr rhs = fromScope ? makeVar(*j) : makeSelect(src, *j);
      59              16 :                 *is = ATinsert(*is, makeBind(*j, rhs, pos));
      60                 :             }
      61             112 :         } else bs = ATinsert(bs, *i);
      62                 :     }
      63              32 :     if (recursive)
      64               8 :         return makeRec(bs, cs);
      65                 :     else
      66              24 :         return makeAttrs(bs);
      67                 : }
      68                 : 
      69                 : const char * getPath(ParseData * data)
      70             141 : {
      71             141 :     return data->path.c_str();
      72                 : }
      73                 : 
      74                 : int yyparse(yyscan_t scanner, ParseData * data);
      75                 : }
      76                 : 
      77                 : 
      78                 : static Expr parse(EvalState & state,
      79                 :     const char * text, const Path & path,
      80                 :     const Path & basePath)
      81              23 : {
      82              23 :     yyscan_t scanner;
      83             115 :     ParseData data;
      84              23 :     data.basePath = basePath;
      85              23 :     data.path = path;
      86                 : 
      87              23 :     yylex_init(&scanner);
      88              23 :     yy_scan_string(text, scanner);
      89              23 :     int res = yyparse(scanner, &data);
      90              23 :     yylex_destroy(scanner);
      91                 :     
      92              23 :     if (res) throw Error(data.error);
      93                 : 
      94              23 :     try {
      95              23 :         checkVarDefs(state.primOps, data.result);
      96               1 :     } catch (Error & e) {
      97               1 :         throw Error(format("%1%, in `%2%'") % e.msg() % path);
      98                 :     }
      99                 : 
     100              22 :     return data.result;
     101                 : }
     102                 : 
     103                 : 
     104                 : Expr parseExprFromFile(EvalState & state, Path path)
     105              11 : {
     106              11 :     SwitchToOriginalUser sw;
     107                 : 
     108              11 :     assert(path[0] == '/');
     109                 : 
     110                 : #if 0
     111                 :     /* Perhaps this is already an imploded parse tree? */
     112                 :     Expr e = ATreadFromNamedFile(path.c_str());
     113                 :     if (e) return e;
     114                 : #endif
     115                 : 
     116                 :     /* If `path' is a symlink, follow it.  This is so that relative
     117                 :        path references work. */
     118              11 :     struct stat st;
     119              11 :     if (lstat(path.c_str(), &st))
     120               0 :         throw SysError(format("getting status of `%1%'") % path);
     121              11 :     if (S_ISLNK(st.st_mode)) path = absPath(readLink(path), dirOf(path));
     122                 : 
     123                 :     /* If `path' refers to a directory, append `/default.nix'. */
     124              11 :     if (stat(path.c_str(), &st))
     125               0 :         throw SysError(format("getting status of `%1%'") % path);
     126              11 :     if (S_ISDIR(st.st_mode))
     127               0 :         path = canonPath(path + "/default.nix");
     128                 : 
     129                 :     /* Read the input file.  We can't use SGparseFile() because it's
     130                 :        broken, so we read the input ourselves and call
     131                 :        SGparseString(). */
     132              11 :     AutoCloseFD fd = open(path.c_str(), O_RDONLY);
     133              11 :     if (fd == -1) throw SysError(format("opening `%1%'") % path);
     134                 : 
     135              11 :     if (fstat(fd, &st) == -1)
     136               0 :         throw SysError(format("statting `%1%'") % path);
     137                 : 
     138              11 :     char text[st.st_size + 1];
     139              11 :     readFull(fd, (unsigned char *) text, st.st_size);
     140              11 :     text[st.st_size] = 0;
     141                 : 
     142              11 :     return parse(state, text, path, dirOf(path));
     143                 : }
     144                 : 
     145                 : 
     146                 : Expr parseExprFromString(EvalState & state,
     147                 :     const string & s, const Path & basePath)
     148              12 : {
     149              12 :     return parse(state, s.c_str(), "(string)", basePath);
     150                 : }

Generated by: LTP GCOV extension version 1.1