home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / vsl-lex.L < prev    next >
Text File  |  1998-11-23  |  10KB  |  485 lines

  1. /* $Id: vsl-lex.L,v 1.21 1998/11/23 17:43:48 zeller Exp $ -*- C++ -*- */
  2. /* VSL lexical analysis */
  3.  
  4. %{
  5. // Copyright (C) 1995 Technische Universitaet Braunschweig, Germany.
  6. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  7. // 
  8. // This file is part of DDD.
  9. // 
  10. // DDD is free software; you can redistribute it and/or
  11. // modify it under the terms of the GNU General Public
  12. // License as published by the Free Software Foundation; either
  13. // version 2 of the License, or (at your option) any later version.
  14. // 
  15. // DDD is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18. // See the GNU General Public License for more details.
  19. // 
  20. // You should have received a copy of the GNU General Public
  21. // License along with DDD -- see the file COPYING.
  22. // If not, write to the Free Software Foundation, Inc.,
  23. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24. // 
  25. // DDD is the data display debugger.
  26. // For details, see the DDD World-Wide-Web page, 
  27. // `http://www.cs.tu-bs.de/softech/ddd/',
  28. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  29.  
  30. char VSL_lex_rcsid[] = 
  31.     "$Id: vsl-lex.L,v 1.21 1998/11/23 17:43:48 zeller Exp $";
  32.  
  33. // Define BAD_ISTREAM != 0, if istream::open() aborts upon
  34. // non-existing file
  35. #define BAD_ISTREAM 1
  36.  
  37. #include <stdio.h>
  38. #include <errno.h>
  39. #include "strclass.h"
  40.  
  41. static const int max_include_nesting = 40;    // max include nesting
  42.  
  43. static istream    *streamstack[max_include_nesting]; // File descriptors
  44. static string    namestack[max_include_nesting];       // File names
  45. static int    linestack[max_include_nesting];       // File lines
  46. static int    topstack = 0;               // Next free position
  47.  
  48. #ifdef FLEX_SCANNER
  49. static YY_BUFFER_STATE bufstack[max_include_nesting]; // Buffer states
  50. #endif
  51.  
  52. static istream *yystream = &cin;
  53.  
  54. static int yylinenumber;
  55.  
  56. static int switchdown();
  57. static int switchup(char *filename, bool thisdir);
  58.  
  59. static char pushback[BUFSIZ];
  60. static char *pushback_ptr = pushback;
  61.  
  62. inline int do_unput(char c) 
  63. {
  64.     if (c != '\0')
  65.     *pushback_ptr++ = c;
  66.  
  67.     return c;
  68. }
  69.  
  70. static int do_input() 
  71. {
  72.     if (pushback_ptr != pushback)
  73.     return *--pushback_ptr;
  74.  
  75.     char c;
  76.  
  77.     yystream->get(c);
  78.     if (yystream->eof())
  79.     return 0;
  80.  
  81.     if (c == '\n')
  82.     yylinenumber++;
  83.     return c;
  84. }
  85.  
  86. // The way SUN lex wants input
  87. #ifdef input
  88. #undef input
  89. #define input do_input
  90. #endif
  91.  
  92. #ifdef unput
  93. #undef unput
  94. #define unput do_unput
  95. #endif
  96.  
  97. // The way FLEX wants input
  98. #ifdef FLEX_SCANNER
  99. #undef YY_INPUT
  100. #define YY_INPUT(buf, result, max_size) \
  101. {\
  102.     int c = do_input(); \
  103.     result = (c == '\0') ? YY_NULL : (buf[0] = c, 1); \
  104. }
  105. #endif
  106.  
  107. #undef yywrap
  108. #define YY_SKIP_YYWRAP
  109. extern "C" int yywrap() 
  110.     if (switchdown())
  111.     return 1;
  112.     return yystream->eof();
  113. }
  114.  
  115.  
  116. // Anything not in the list is a single character
  117. #ifdef ECHO
  118. #undef ECHO
  119. #endif
  120. #define ECHO                 return yytext[0]
  121.  
  122.  
  123. #ifdef FLEX_SCANNER
  124. // #defining YY_BREAK to empty disables warnings about unreachable breaks.
  125. #define YY_BREAK DO_NOT_BREAK
  126. #define DO_NOT_BREAK
  127. #define BREAK break;
  128. #endif // FLEX_SCANNER
  129.  
  130. %}
  131.  
  132. /* C-Bezeichner */
  133. I            [_a-zA-Z][_a-zA-Z0-9]*
  134.  
  135. /* C-Strings */
  136. S            \"(\\.|[^\"\n])*\"
  137.  
  138. /* C-Integers */
  139. N            [0-9]+
  140.  
  141. /* #include-Strings */
  142. CS            \"[^\"\n]*\"
  143. CC            \<[^\>\n]*\>
  144.  
  145. /* Whitespace */
  146. W            [ \f\t]*
  147.  
  148. %%
  149.  
  150. {S}        return STRING;            // string
  151.  
  152. "//".*        BREAK                // C++ comment
  153. "/*"        {                // C comment
  154.             // aus `man lex`
  155.             loop:
  156.             while (yyinput() != '*');
  157.             switch (yyinput())
  158.                 {
  159.                 case '/': break;
  160.                 case '*': unput('*');
  161.                 default : goto loop;
  162.                 }
  163.             BREAK
  164.         }
  165. ^{W}#!.*        BREAK            // Unix exec() tag
  166.  
  167. ^{W}#{W}include{W}{CS}.* {            // #include "..."
  168.             char buf[BUFSIZ];
  169.             strcpy(buf, (char *)yytext);
  170.             char *start = buf;
  171.             while (*start != '\"') 
  172.                 start++;
  173.             char *end = ++start;
  174.             while (*end != '\"') 
  175.                 end++;
  176.             *end = '\0';
  177.             switchup(start, true);
  178.             BREAK
  179.         }
  180. ^{W}#{W}include{W}{CC}.* {            // #include <...>
  181.             char buf[BUFSIZ];
  182.             strcpy(buf, (char *)yytext);
  183.             char *start = buf;
  184.             while (*start != '<') 
  185.                 start++;
  186.             char *end = ++start;
  187.             while (*end != '>') 
  188.                 end++;
  189.             *end = '\0';
  190.             switchup(start, false);
  191.             BREAK
  192.         }
  193. ^{W}#{W}line[ \f\t]{W}.* {            // #line LINE ["FILE"]
  194.             string buf((char *)yytext);
  195.             buf = buf.after("line");
  196.             char *s = (char *)buf.chars();
  197.             int line = strtol(s, &s, 10);
  198.             if (s == buf.chars())
  199.                 VSLLib::parse_error("illegal #line number");
  200.             else
  201.                 yylinenumber = line;
  202.  
  203.             buf = buf.after('"');
  204.             if (buf != "")
  205.             {
  206.                 buf = buf.before('"');
  207.                 if (buf == "")
  208.                 VSLLib::parse_error("illegal #line file");
  209.                 else
  210.                 yyfilename = uncook(buf);
  211.             }
  212.             BREAK
  213.         }
  214.  
  215. ^{W}#{W}override   return OVERRIDE;        // Other manipulators
  216. ^{W}#{W}undef       return OVERRIDE;
  217. ^{W}#{W}replace       return REPLACE;
  218. ^{W}#{W}pragma{W}override   return OVERRIDE;    // Other manipulators
  219. ^{W}#{W}pragma{W}undef        return OVERRIDE;
  220. ^{W}#{W}pragma{W}replace    return REPLACE;
  221.  
  222. if        return IF;            // Tokens
  223. then        return THEN;
  224. else        return ELSE;
  225. elsif        return ELSIF;
  226. fi        return FI;
  227. or        return OR;
  228. and        return AND;
  229. not        return NOT;
  230. let        return LET;
  231. in        return IN;
  232. where        return WHERE;
  233. {I}        return IDENTIFIER;
  234.  
  235. "->"        return ARROW;
  236. "::"        return CONS;
  237. ":"        return APPEND;
  238. "&"        return HALIGN;
  239. "|"        return VALIGN;
  240. "^"        return UALIGN;
  241. "~"        return TALIGN;
  242. "="        return EQ;
  243. "<>"        return NE;
  244. ">"        return GT;
  245. ">="        return GE;
  246. "<"        return LT;
  247. "<="        return LE;
  248.  
  249. "..."        return THREEDOTS;
  250.  
  251. {N}        return INTEGER;
  252.  
  253. {W}        BREAK                // Whitespace (ignore)
  254. "\n"        BREAK                // Likewise
  255. .        return yytext[0];        // All other characters
  256. %%
  257. class yyNameSet {
  258. private:
  259.     string _name;
  260.     yyNameSet *_next;
  261.  
  262. public:
  263.     yyNameSet(const char *name)
  264.     : _name(name), _next(0)
  265.     {}
  266.     ~yyNameSet()       { reset(); }
  267.     void reset();
  268.     int add(const char *name);
  269.  
  270. private:
  271.     yyNameSet(const yyNameSet&)
  272.     : _name(), _next(0)
  273.     {
  274.     assert(0);
  275.     }
  276.     yyNameSet& operator = (const yyNameSet&)
  277.     {
  278.     assert(0); return *this;
  279.     }
  280. } yynameSet("xyzzy");
  281.  
  282. // Delete name set
  283. void yyNameSet::reset()
  284.     if (_next) 
  285.     delete _next; 
  286.     _next = 0; 
  287. }
  288.  
  289. // Add to name set; if already there, return -1
  290. int yyNameSet::add(const char *name)
  291. {
  292.     if (strcmp(_name.chars(), name) == 0)
  293.     return -1;
  294.  
  295.     if (_next)
  296.     return _next->add(name);
  297.  
  298.     _next = new yyNameSet(name);
  299.     return 0;
  300. }
  301.  
  302. // Clear name set
  303. static void switchreset()
  304. {
  305.     yynameSet.reset();
  306. }
  307.  
  308.  
  309. // Return to original file
  310. static int switchdown() 
  311. {
  312.     if (topstack <= 0)
  313.     return -1;
  314.     
  315.     if (yystream != 0)
  316.     {
  317.     if (VSEFlags::verbose)
  318.     {
  319.         cout << ")";
  320.         cout.flush();
  321.     }
  322.     delete yystream;
  323.     }
  324.  
  325.     topstack--;
  326.     yystream     = streamstack[topstack];
  327.     yyfilename     = namestack[topstack];
  328.     yylinenumber = linestack[topstack];
  329.  
  330. #ifdef FLEX_SCANNER
  331.     if (YY_CURRENT_BUFFER != 0)
  332.     yy_delete_buffer(YY_CURRENT_BUFFER);
  333.     yy_switch_to_buffer(bufstack[topstack]);
  334. #endif
  335.  
  336.     return 0;
  337. }
  338.  
  339. #ifndef VSL_INCLUDE_PATH
  340. #define VSL_INCLUDE_PATH "/usr/local/lib/vsl-include"
  341. #endif
  342.  
  343. // Search file in directories -I, $VSL_INCLUDE suchen
  344. // as well as in ".", if THISDIR == true
  345. // If not found, return FILENAME
  346. static char *searchpath(char *filename, bool thisDir)
  347. {
  348.     char includeList[BUFSIZ];
  349.  
  350.     // If "-I" is given, use this path
  351.     char *s = VSEFlags::include_search_path;
  352.     if (s == NULL || s[0] == '\0')
  353.     {
  354.     // Otherwise: Use environment or default path
  355.     s = getenv("VSL_INCLUDE");
  356.     if (s == NULL)
  357.     {
  358.         static string path = 
  359.         string(VSL_INCLUDE_PATH) +
  360.         ":/usr/local/vse/vsl-include"
  361.         ":/usr/vse/vsl-include"
  362.         ":/usr/local/lib/vse/vsl-include"
  363.         ":/usr/lib/vse/vsl-include"
  364.         ":/usr/local/lib/vsl-include"
  365.         ":/usr/lib/vsl-include";
  366.         
  367.         s = path;
  368.     }
  369.     }
  370.  
  371.     // If this dir is supposed to be searched, prepend ".:"
  372.     if (thisDir)
  373.     strcpy(includeList, ".:");
  374.     else
  375.     strcpy(includeList, "");
  376.     strncat(includeList, s, BUFSIZ - 2);
  377.  
  378.     // Check dirs; if file can be opened, return full path
  379.     for (char *p = strtok(includeList, ":"); p != NULL; p = strtok(NULL, ":"))
  380.     {
  381.     static char path[BUFSIZ];
  382.     strcpy(path, p);
  383.     strcat(path, "/");
  384.     strcat(path, filename);
  385.  
  386.     FILE *fp = fopen(path, "r");
  387.     if (fp != NULL && fclose(fp) != EOF)
  388.     {
  389.         // Remove "./" prefix
  390.         if (path[0] == '.' && path[1] == '/')
  391.         return path + 2;
  392.         else
  393.         return path;
  394.     }
  395.     }
  396.  
  397.     return filename;
  398. }
  399.  
  400. // Switch to file FILENAME
  401. static int switchup(char *filename, bool thisdir) 
  402. {
  403.     if (string(filename) != "")
  404.     {
  405.     // Search file
  406.     filename = searchpath(filename, thisdir);
  407.  
  408.     // Add to name set; if we already have read it, don't care
  409.     if (yynameSet.add(filename))
  410.         return 0;
  411.     }
  412.  
  413.     if (topstack >= max_include_nesting)
  414.     {
  415.     VSLLib::parse_error("too many #include's");
  416.     return -1;
  417.     }
  418.  
  419. #ifdef FLEX_SCANNER
  420.     if (YY_CURRENT_BUFFER == 0)
  421.     {
  422.     YY_CURRENT_BUFFER = yy_new_buffer(stdin, YY_BUF_SIZE);
  423.     yy_load_buffer_state();
  424.     }
  425.  
  426.     bufstack[topstack]      = YY_CURRENT_BUFFER;
  427. #endif
  428.  
  429.     streamstack[topstack] = yystream;
  430.     namestack[topstack]      = yyfilename;
  431.     linestack[topstack]      = yylinenumber;
  432.     topstack++;
  433.  
  434.     yylinenumber = 1;
  435.     yyfilename = filename;
  436.  
  437. #ifdef FLEX_SCANNER
  438.     yy_switch_to_buffer(yy_new_buffer(stdin, YY_BUF_SIZE));
  439. #endif
  440.  
  441.     if (string(filename) == "")
  442.     {
  443.     yystream   = &cin;
  444.     yyfilename = "standard input";
  445.     }
  446.     else
  447.     {
  448. #if BAD_ISTREAM
  449.     yystream = 0;
  450.     FILE *fp = fopen(filename, "r");
  451.     if (fp == NULL || fclose(fp) == EOF) 
  452.     {
  453. #else
  454.     yystream = new ifstream(filename, ios::in);
  455.     if (!yystream->readable()) 
  456.     {
  457. #endif
  458.     switchdown();
  459.     VSLLib::parse_error(string(filename) + ": " + strerror(errno));
  460.     return -1;
  461.     }
  462.  
  463. #if BAD_ISTREAM
  464.     // yystream can now be opened
  465.     yystream = new ifstream(filename, ios::in);
  466. #endif
  467.     }
  468.  
  469.     if (VSEFlags::verbose)
  470.     {
  471.     cout << "(" << yyfilename;
  472.     cout.flush();
  473.     }
  474.  
  475. #ifdef FLEX_SCANNER
  476.     // Avoid warnings about unused vslunput() function
  477.     if (false)
  478.     vslunput(0, 0);        // Never called
  479. #endif
  480.  
  481.     return 0;
  482. }
  483.