"Fossies" - the Fresh Open Source Software Archive

Member "bc-1.06.95/bc/scan.l" (5 Sep 2006, 9154 Bytes) of package /linux/misc/old/bc-1.06.95.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "scan.l": 1.06.95_vs_1.07.

    1 /*  This file is part of GNU bc.
    2 
    3     Copyright (C) 1991-1994, 1997, 2006 Free Software Foundation, Inc.
    4 
    5     This program is free software; you can redistribute it and/or modify
    6     it under the terms of the GNU General Public License as published by
    7     the Free Software Foundation; either version 2 of the License , or
    8     (at your option) any later version.
    9 
   10     This program is distributed in the hope that it will be useful,
   11     but WITHOUT ANY WARRANTY; without even the implied warranty of
   12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13     GNU General Public License for more details.
   14 
   15     You should have received a copy of the GNU General Public License
   16     along with this program; see the file COPYING.  If not, write to:
   17       The Free Software Foundation, Inc.
   18       Foundation, Inc.  51 Franklin Street, Fifth Floor,
   19       Boston, MA 02110-1301  USA
   20 
   21     You may contact the author by:
   22        e-mail:  philnelson@acm.org
   23       us-mail:  Philip A. Nelson
   24                 Computer Science Department, 9062
   25                 Western Washington University
   26                 Bellingham, WA 98226-9062
   27        
   28 *************************************************************************/
   29 
   30 /* scan.l: the (f)lex description file for the scanner. */
   31 
   32 %{
   33 
   34 #include "bcdefs.h"
   35 #include "bc.h"
   36 #include "global.h"
   37 #include "proto.h"
   38 #include <errno.h>
   39 
   40 /* Using flex, we can ask for a smaller input buffer.  With lex, this
   41    does nothing! */
   42 
   43 #ifdef SMALL_BUF
   44 #undef YY_READ_BUF_SIZE
   45 #define YY_READ_BUF_SIZE 512
   46 #endif
   47 
   48 /* Force . as last for now. */
   49 #define DOT_IS_LAST
   50 
   51 /* We want to define our own yywrap. */
   52 #undef yywrap
   53 _PROTOTYPE(int yywrap, (void));
   54 
   55 #if defined(LIBEDIT)
   56 /* Support for the BSD libedit with history for
   57    nicer input on the interactive part of input. */
   58 
   59 #include <histedit.h>
   60 
   61 /* Have input call the following function. */
   62 #undef  YY_INPUT
   63 #define YY_INPUT(buf,result,max_size) \
   64         bcel_input((char *)buf, &result, max_size)
   65 
   66 /* Variables to help interface editline with bc. */
   67 static const char *bcel_line = (char *)NULL;
   68 static int   bcel_len = 0;
   69 
   70 
   71 /* Required to get rid of that ugly ? default prompt! */
   72 char *
   73 null_prompt (EditLine *el)
   74 {
   75   return "";
   76 }
   77 
   78 
   79 /* bcel_input puts upto MAX characters into BUF with the number put in
   80    BUF placed in *RESULT.  If the yy input file is the same as
   81    stdin, use editline.  Otherwise, just read it.
   82 */
   83 
   84 static void
   85 bcel_input (buf, result, max)
   86     char *buf;
   87     int  *result;
   88     int   max;
   89 {
   90   if (!edit || yyin != stdin)
   91     {
   92       while ( (*result = read( fileno(yyin), buf, max )) < 0 )
   93         if (errno != EINTR)
   94       {
   95         yyerror( "read() in flex scanner failed" );
   96         exit (1);
   97       }
   98       return;
   99     }
  100 
  101   /* Do we need a new string? */
  102   if (bcel_len == 0)
  103     {
  104       bcel_line = el_gets(edit, &bcel_len);
  105       if (bcel_line == NULL) {
  106     /* end of file */
  107     *result = 0;
  108     bcel_len = 0;
  109     return;
  110       }
  111       if (bcel_len != 0)
  112     history (hist, &histev, H_ENTER, bcel_line); 
  113       fflush (stdout);
  114     }
  115 
  116   if (bcel_len <= max)
  117     {
  118       strncpy (buf, bcel_line, bcel_len);
  119       *result = bcel_len;
  120       bcel_len = 0;
  121     }
  122   else
  123     {
  124       strncpy (buf, bcel_line, max);
  125       *result = max;
  126       bcel_line += max;
  127       bcel_len -= max;
  128     }
  129 }
  130 #endif
  131 
  132 #ifdef READLINE
  133 /* Support for the readline and history libraries.  This allows
  134    nicer input on the interactive part of input. */
  135 
  136 /* Have input call the following function. */
  137 #undef  YY_INPUT
  138 #define YY_INPUT(buf,result,max_size) \
  139         rl_input((char *)buf, &result, max_size)
  140 
  141 /* Variables to help interface readline with bc. */
  142 static char *rl_line = (char *)NULL;
  143 static char *rl_start = (char *)NULL;
  144 static int   rl_len = 0;
  145 
  146 /* Definitions for readline access. */
  147 extern FILE *rl_instream;
  148 
  149 /* rl_input puts upto MAX characters into BUF with the number put in
  150    BUF placed in *RESULT.  If the yy input file is the same as
  151    rl_instream (stdin), use readline.  Otherwise, just read it.
  152 */
  153 
  154 static void
  155 rl_input (buf, result, max)
  156     char *buf;
  157     int  *result;
  158     int   max;
  159 {
  160   if (yyin != rl_instream)
  161     {
  162       while ( (*result = read( fileno(yyin), buf, max )) < 0 )
  163         if (errno != EINTR)
  164       {
  165         yyerror( "read() in flex scanner failed" );
  166         exit (1);
  167       }
  168       return;
  169     }
  170 
  171   /* Do we need a new string? */
  172   if (rl_len == 0)
  173     {
  174       if (rl_start)
  175     free(rl_start);
  176       rl_start = readline ("");
  177       if (rl_start == NULL) {
  178     /* end of file */
  179     *result = 0;
  180     rl_len = 0;
  181     return;
  182       }
  183       rl_line = rl_start;
  184       rl_len = strlen (rl_line)+1;
  185       if (rl_len != 1)
  186     add_history (rl_line); 
  187       rl_line[rl_len-1] = '\n';
  188       fflush (stdout);
  189     }
  190 
  191   if (rl_len <= max)
  192     {
  193       strncpy (buf, rl_line, rl_len);
  194       *result = rl_len;
  195       rl_len = 0;
  196     }
  197   else
  198     {
  199       strncpy (buf, rl_line, max);
  200       *result = max;
  201       rl_line += max;
  202       rl_len -= max;
  203     }
  204 }
  205 #endif
  206 
  207 #if !defined(READLINE) && !defined(LIBEDIT)
  208 
  209 /* MINIX returns from read with < 0 if SIGINT is  encountered.
  210    In flex, we can redefine YY_INPUT to the following.  In lex, this
  211    does nothing! */
  212 #undef  YY_INPUT
  213 #define YY_INPUT(buf,result,max_size) \
  214     while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
  215         if (errno != EINTR) \
  216         YY_FATAL_ERROR( "read() in flex scanner failed" );
  217 #endif
  218 
  219 %}
  220 DIGIT [0-9A-F]
  221 LETTER [a-z]
  222 %s slcomment
  223 %%
  224 "#"     {
  225           if (!std_only)
  226             BEGIN(slcomment);
  227           else
  228             yyerror ("illegal character: #");
  229         }
  230 <slcomment>[^\n]* { BEGIN(INITIAL); }
  231 <slcomment>"\n" { line_no++; BEGIN(INITIAL); return(ENDOFLINE); }
  232 define return(Define);
  233 break  return(Break);
  234 quit   return(Quit);
  235 length return(Length);
  236 return return(Return);
  237 for    return(For);
  238 if     return(If);
  239 while  return(While);
  240 sqrt   return(Sqrt);
  241 scale  return(Scale);
  242 ibase  return(Ibase);
  243 obase  return(Obase);
  244 auto   return(Auto);
  245 else   return(Else);
  246 read   return(Read);
  247 random return(Random);
  248 halt   return(Halt);
  249 last   return(Last);
  250 void   return(Void); 
  251 history {
  252 #if defined(READLINE) || defined(LIBEDIT)
  253       return(HistoryVar);
  254 #else
  255       yylval.s_value = strcopyof(yytext); return(NAME);
  256 #endif
  257     }
  258 
  259 warranty return(Warranty);
  260 continue return(Continue);
  261 print  return(Print);
  262 limits return(Limits);
  263 "." {
  264 #ifdef DOT_IS_LAST
  265        return(Last);
  266 #else
  267        yyerror ("illegal character: %s",yytext);
  268 #endif
  269     }
  270 "+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0]; 
  271                           return((int)yytext[0]); }
  272 && { return(AND); }
  273 \|\| { return(OR); }
  274 "!" { return(NOT); }
  275 "*"|"/"|"%"|"&" { yylval.c_value = yytext[0]; return((int)yytext[0]); }
  276 "="|\+=|-=|\*=|\/=|%=|\^=  { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
  277 =\+|=-|=\*|=\/|=%|=\^  { 
  278 #ifdef OLD_EQ_OP
  279              char warn_save;
  280              warn_save = warn_not_std;
  281              warn_not_std = TRUE;
  282              warn ("Old fashioned =<op>");
  283              warn_not_std = warn_save;
  284              yylval.c_value = yytext[1];
  285 #else
  286              yylval.c_value = '=';
  287              yyless (1);
  288 #endif
  289              return(ASSIGN_OP);
  290                }
  291 ==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof(yytext); return(REL_OP); }
  292 \+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
  293 "\n" { line_no++; return(ENDOFLINE); }
  294 \\\n {  line_no++;  /* ignore a "quoted" newline */ }
  295 [ \t]+  { /* ignore spaces and tabs */ }
  296 "/*"  {
  297     int c;
  298 
  299     for (;;)
  300       {
  301         while ( ((c=input()) != '*') && (c != EOF)) 
  302           /* eat it */
  303           if (c == '\n') line_no++;
  304         if (c == '*')
  305           {
  306         while ( (c=input()) == '*') /* eat it*/;
  307         if (c == '/') break; /* at end of comment */
  308         if (c == '\n') line_no++;
  309           }
  310         if (c == EOF)
  311           {
  312         fprintf (stderr,"EOF encountered in a comment.\n");
  313         break;
  314           }
  315       }
  316       }
  317 [a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
  318 \"[^\"]*\"  {
  319           const char *look;
  320           int count = 0;
  321           yylval.s_value = strcopyof(yytext);
  322           for (look = yytext; *look != 0; look++)
  323         {
  324           if (*look == '\n') line_no++;
  325           if (*look == '"')  count++;
  326         }
  327           if (count != 2) yyerror ("NUL character in string.");
  328           return(STRING);
  329         }
  330 {DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
  331           char *src, *dst;
  332           int len;
  333           /* remove a trailing decimal point. */
  334           len = strlen(yytext);
  335           if (yytext[len-1] == '.')
  336             yytext[len-1] = 0;
  337           /* remove leading zeros. */
  338           src = yytext;
  339           dst = yytext;
  340           while (*src == '0') src++;
  341           if (*src == 0) src--;
  342           /* Copy strings removing the newlines. */
  343           while (*src != 0)
  344         {
  345               if (*src == '\\')
  346             {
  347               src++; src++;
  348               line_no++;
  349             }
  350           else
  351             *dst++ = *src++;
  352             }
  353           *dst = 0;
  354           yylval.s_value = strcopyof(yytext); 
  355           return(NUMBER);
  356         }
  357 .       {
  358       if (yytext[0] < ' ')
  359         yyerror ("illegal character: ^%c",yytext[0] + '@');
  360       else
  361         if (yytext[0] > '~')
  362           yyerror ("illegal character: \\%03o", (int) yytext[0]);
  363         else
  364           yyerror ("illegal character: %s",yytext);
  365     }
  366 %%
  367 
  368 
  369 
  370 /* This is the way to get multiple files input into lex. */
  371 
  372 int
  373 yywrap()
  374 {
  375   if (!open_new_file ()) return (1);    /* EOF on standard in. */
  376   return (0);               /* We have more input. */
  377 }