summaryrefslogtreecommitdiff
path: root/ghc/compiler/yaccParser/hslexer.flex
diff options
context:
space:
mode:
authorpartain <unknown>1996-01-08 20:28:12 +0000
committerpartain <unknown>1996-01-08 20:28:12 +0000
commite7d21ee4f8ac907665a7e170c71d59e13a01da09 (patch)
tree93715bf4e6e4bbe8049e4d8d4d3fbd19158a88d6 /ghc/compiler/yaccParser/hslexer.flex
parente48474bff05e6cfb506660420f025f694c870d38 (diff)
downloadhaskell-e7d21ee4f8ac907665a7e170c71d59e13a01da09.tar.gz
[project @ 1996-01-08 20:28:12 by partain]
Initial revision
Diffstat (limited to 'ghc/compiler/yaccParser/hslexer.flex')
-rw-r--r--ghc/compiler/yaccParser/hslexer.flex1362
1 files changed, 1362 insertions, 0 deletions
diff --git a/ghc/compiler/yaccParser/hslexer.flex b/ghc/compiler/yaccParser/hslexer.flex
new file mode 100644
index 0000000000..7d0ce0fc60
--- /dev/null
+++ b/ghc/compiler/yaccParser/hslexer.flex
@@ -0,0 +1,1362 @@
+%{
+/**********************************************************************
+* *
+* *
+* LEX grammar for Haskell. *
+* ------------------------ *
+* *
+* (c) Copyright K. Hammond, University of Glasgow, *
+* 10th. February 1989 *
+* *
+* Modification History *
+* -------------------- *
+* *
+* 22/08/91 kh Initial Haskell 1.1 version. *
+* 18/10/91 kh Added 'ccall'. *
+* 19/11/91 kh Tidied generally. *
+* 04/12/91 kh Added Int#. *
+* 31/01/92 kh Haskell 1.2 version. *
+* 24/04/92 ps Added 'scc'. *
+* 03/06/92 kh Changed Infix/Prelude Handling. *
+* 23/08/93 jsm Changed to support flex *
+* *
+* *
+* Known Problems: *
+* *
+* None, any more. *
+* *
+**********************************************************************/
+
+#include "../../includes/config.h"
+
+#include <stdio.h>
+
+#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
+#include <string.h>
+/* An ANSI string.h and pre-ANSI memory.h might conflict. */
+#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+#include <memory.h>
+#endif /* not STDC_HEADERS and HAVE_MEMORY_H */
+#define index strchr
+#define rindex strrchr
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
+#define bzero(s, n) memset ((s), 0, (n))
+#else /* not STDC_HEADERS and not HAVE_STRING_H */
+#include <strings.h>
+/* memory.h and strings.h conflict on some systems. */
+#endif /* not STDC_HEADERS and not HAVE_STRING_H */
+
+#include "hspincl.h"
+#include "hsparser.tab.h"
+#include "constants.h"
+#include "utils.h"
+
+/* Our substitute for <ctype.h> */
+
+#define NCHARS 256
+#define _S 0x1
+#define _D 0x2
+#define _H 0x4
+#define _O 0x8
+#define _C 0x10
+
+#define _isconstr(s) (CharTable[*s]&(_C))
+BOOLEAN isconstr PROTO((char *)); /* fwd decl */
+
+unsigned char CharTable[NCHARS] = {
+/* nul */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* bs */ 0, _S, _S, _S, _S, 0, 0, 0,
+/* dle */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* can */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* sp */ _S, 0, 0, 0, 0, 0, 0, 0,
+/* '(' */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* '0' */ _D|_H|_O,_D|_H|_O,_D|_H|_O,_D|_H|_O,_D|_H|_O,_D|_H|_O,_D|_H|_O,_D|_H|_O,
+/* '8' */ _D|_H, _D|_H, _C, 0, 0, 0, 0, 0,
+/* '@' */ 0, _H|_C, _H|_C, _H|_C, _H|_C, _H|_C, _H|_C, _C,
+/* 'H' */ _C, _C, _C, _C, _C, _C, _C, _C,
+/* 'P' */ _C, _C, _C, _C, _C, _C, _C, _C,
+/* 'X' */ _C, _C, _C, 0, 0, 0, 0, 0,
+/* '`' */ 0, _H, _H, _H, _H, _H, _H, 0,
+/* 'h' */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 'p' */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* 'x' */ 0, 0, 0, 0, 0, 0, 0, 0,
+
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+/* */ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/**********************************************************************
+* *
+* *
+* Declarations *
+* *
+* *
+**********************************************************************/
+
+char *input_filename = NULL; /* Always points to a dynamically allocated string */
+
+/*
+ * For my own sanity, things that are not part of the flex skeleton
+ * have been renamed as hsXXXXX rather than yyXXXXX. --JSM
+ */
+
+int hslineno = 0; /* Line number at end of token */
+int hsplineno = 0; /* Line number at end of previous token */
+
+int hscolno = 0; /* Column number at end of token */
+int hspcolno = 0; /* Column number at end of previous token */
+int hsmlcolno = 0; /* Column number for multiple-rule lexemes */
+
+int startlineno = 0; /* The line number where something starts */
+int endlineno = 0; /* The line number where something ends */
+
+static BOOLEAN noGap = TRUE; /* For checking string gaps */
+static BOOLEAN forgetindent = FALSE; /* Don't bother applying indentation rules */
+
+static int nested_comments; /* For counting comment nesting depth */
+
+/* Hacky definition of yywrap: see flex doc.
+
+ If we don't do this, then we'll have to get the default
+ yywrap from the flex library, which is often something
+ we are not good at locating. This avoids that difficulty.
+ (Besides which, this is the way old flexes (pre 2.4.x) did it.)
+ WDP 94/09/05
+*/
+#define yywrap() 1
+
+/* Essential forward declarations */
+
+static VOID hsnewid PROTO((char *, int));
+static VOID layout_input PROTO((char *, int));
+static VOID cleartext (NO_ARGS);
+static VOID addtext PROTO((char *, unsigned));
+static VOID addchar PROTO((char));
+static char *fetchtext PROTO((unsigned *));
+
+/* Special file handling for IMPORTS */
+/* Note: imports only ever go *one deep* (hence no need for a stack) WDP 94/09 */
+
+static YY_BUFFER_STATE hsbuf_save = NULL; /* Saved input buffer */
+static char *filename_save; /* File Name */
+static int hslineno_save = 0, /* Line Number */
+ hsplineno_save = 0, /* Line Number of Prev. token */
+ hscolno_save = 0, /* Indentation */
+ hspcolno_save = 0; /* Left Indentation */
+static short icontexts_save = 0; /* Indent Context Level */
+
+static BOOLEAN etags_save; /* saved: whether doing etags stuff or not */
+extern BOOLEAN etags; /* that which is saved */
+
+extern BOOLEAN nonstandardFlag; /* Glasgow extensions allowed */
+
+static BOOLEAN in_interface = FALSE; /* TRUE if we are reading a .hi file */
+
+extern BOOLEAN ignorePragmas; /* True when we should ignore pragmas */
+extern int minAcceptablePragmaVersion; /* see documentation in main.c */
+extern int maxAcceptablePragmaVersion;
+extern int thisIfacePragmaVersion;
+
+static int hssttok = -1; /* Stacked Token: -1 -- no token; -ve -- ";"
+ * inserted before token +ve -- "}" inserted before
+ * token */
+
+short icontexts = 0; /* Which context we're in */
+
+
+
+/*
+ Table of indentations: right bit indicates whether to use
+ indentation rules (1 = use rules; 0 = ignore)
+
+ partain:
+ push one of these "contexts" at every "case" or "where"; the right bit says
+ whether user supplied braces, etc., or not. pop appropriately (hsendindent).
+
+ ALSO, a push/pop when enter/exit a new file (e.g., on importing). A -1 is
+ pushed (the "column" for "module", "interface" and EOF). The -1 from the initial
+ push is shown just below.
+
+*/
+
+
+static short indenttab[MAX_CONTEXTS] = {-1};
+
+#define INDENTPT (indenttab[icontexts]>>1)
+#define INDENTON (indenttab[icontexts]&1)
+
+#define RETURN(tok) return(Return(tok))
+
+#undef YY_DECL
+#define YY_DECL int yylex1()
+
+/* We should not peek at yy_act, but flex calls us even for the internal action
+ triggered on 'end-of-buffer' (This is not true of flex 2.4.4 and up, but
+ to support older versions of flex, we'll continue to peek for now.
+ */
+#define YY_USER_ACTION \
+ if (yy_act != YY_END_OF_BUFFER) layout_input(yytext, yyleng);
+
+#if 0/*debug*/
+#undef YY_BREAK
+#define YY_BREAK if (etags) fprintf(stderr,"%d %d / %d %d / %d\n",hsplineno,hspcolno,hslineno,hscolno,startlineno); break;
+#endif
+
+/* Each time we enter a new start state, we push it onto the state stack.
+ Note that the rules do not allow us to underflow or overflow the stack.
+ (At least, they shouldn't.) The maximum expected depth is 4:
+ 0: Code -> 1: String -> 2: StringEsc -> 3: Comment
+*/
+static int StateStack[5];
+static int StateDepth = -1;
+
+#ifdef HSP_DEBUG
+#define PUSH_STATE(n) do {\
+ fprintf(stderr,"Pushing %d (%d)\n", n, StateDepth + 1);\
+ StateStack[++StateDepth] = (n); BEGIN(n);} while(0)
+#define POP_STATE do {--StateDepth;\
+ fprintf(stderr,"Popping %d (%d)\n", StateStack[StateDepth], StateDepth);\
+ BEGIN(StateStack[StateDepth]);} while(0)
+#else
+#define PUSH_STATE(n) do {StateStack[++StateDepth] = (n); BEGIN(n);} while(0)
+#define POP_STATE do {--StateDepth; BEGIN(StateStack[StateDepth]);} while(0)
+#endif
+
+%}
+
+/* The start states are:
+ Code -- normal Haskell code (principal lexer)
+ GlaExt -- Haskell code with Glasgow extensions
+ Comment -- Nested comment processing
+ String -- Inside a string literal with backslashes
+ StringEsc -- Immediately following a backslash in a string literal
+ Char -- Inside a character literal with backslashes
+ CharEsc -- Immediately following a backslash in a character literal
+
+ Note that the INITIAL state is unused. Also note that these states
+ are _exclusive_. All rules should be prefixed with an appropriate
+ list of start states.
+ */
+
+%x Char CharEsc Code Comment GlaExt GhcPragma UserPragma String StringEsc
+
+D [0-9]
+O [0-7]
+H [0-9A-Fa-f]
+N {D}+
+F {N}"."{N}(("e"|"E")("+"|"-")?{N})?
+S [!#$%&*+./<=>?@\\^|~:]
+SId ({S}|~|-){S}*
+CHAR [ !#$%&()*+,\-./0-9:;<=>?@A-Z\[\]^_`a-z{|}~]
+L [A-Z]
+I [A-Za-z]
+i [A-Za-z0-9'_]
+Id {I}({i})*
+WS [ \t\n\r\f\v]
+CNTRL [@A-Z\[\\\]^_]
+NL [\n\r]
+
+%%
+
+%{
+ /*
+ * Special GHC pragma rules. Do we need a start state for interface files,
+ * so these won't be matched in source files? --JSM
+ */
+%}
+
+<Code,GlaExt>^"# ".*{NL} {
+ char tempf[FILENAME_SIZE];
+ sscanf(yytext+1, "%d \"%[^\"]", &hslineno, tempf);
+ new_filename(tempf);
+ hsplineno = hslineno; hscolno = 0; hspcolno = 0;
+ }
+
+<Code,GlaExt>^"#line ".*{NL} {
+ char tempf[FILENAME_SIZE];
+ sscanf(yytext+5, "%d \"%[^\"]", &hslineno, tempf);
+ new_filename(tempf);
+ hsplineno = hslineno; hscolno = 0; hspcolno = 0;
+ }
+
+<Code,GlaExt>"{-# LINE ".*"-}"{NL} {
+ /* partain: pragma-style line directive */
+ char tempf[FILENAME_SIZE];
+ sscanf(yytext+9, "%d \"%[^\"]", &hslineno, tempf);
+ new_filename(tempf);
+ hsplineno = hslineno; hscolno = 0; hspcolno = 0;
+ }
+<Code,GlaExt>"{-# GHC_PRAGMA INTERFACE VERSION "{D}+" #-}" {
+ sscanf(yytext+33,"%d ",&thisIfacePragmaVersion);
+ }
+<Code,GlaExt>"{-# GHC_PRAGMA " {
+ if ( ignorePragmas ||
+ thisIfacePragmaVersion < minAcceptablePragmaVersion ||
+ thisIfacePragmaVersion > maxAcceptablePragmaVersion) {
+ nested_comments = 1;
+ PUSH_STATE(Comment);
+ } else {
+ PUSH_STATE(GhcPragma);
+ RETURN(GHC_PRAGMA);
+ }
+ }
+<GhcPragma>"_N_" { RETURN(NO_PRAGMA); }
+<GhcPragma>"_NI_" { RETURN(NOINFO_PRAGMA); }
+<GhcPragma>"_ABSTRACT_" { RETURN(ABSTRACT_PRAGMA); }
+<GhcPragma>"_DEFOREST_" { RETURN(DEFOREST_PRAGMA); }
+<GhcPragma>"_SPECIALISE_" { RETURN(SPECIALISE_PRAGMA); }
+<GhcPragma>"_M_" { RETURN(MODNAME_PRAGMA); }
+<GhcPragma>"_A_" { RETURN(ARITY_PRAGMA); }
+<GhcPragma>"_U_" { RETURN(UPDATE_PRAGMA); }
+<GhcPragma>"_S_" { RETURN(STRICTNESS_PRAGMA); }
+<GhcPragma>"_K_" { RETURN(KIND_PRAGMA); }
+<GhcPragma>"_MF_" { RETURN(MAGIC_UNFOLDING_PRAGMA); }
+<GhcPragma>"_F_" { RETURN(UNFOLDING_PRAGMA); }
+
+<GhcPragma>"_!_" { RETURN(COCON); }
+<GhcPragma>"_#_" { RETURN(COPRIM); }
+<GhcPragma>"_APP_" { RETURN(COAPP); }
+<GhcPragma>"_TYAPP_" { RETURN(COTYAPP); }
+<GhcPragma>"_ALG_" { RETURN(CO_ALG_ALTS); }
+<GhcPragma>"_PRIM_" { RETURN(CO_PRIM_ALTS); }
+<GhcPragma>"_NO_DEFLT_" { RETURN(CO_NO_DEFAULT); }
+<GhcPragma>"_LETREC_" { RETURN(CO_LETREC); }
+
+<GhcPragma>"_PRELUDE_DICTS_CC_" { RETURN(CO_PRELUDE_DICTS_CC); }
+<GhcPragma>"_ALL_DICTS_CC_" { RETURN(CO_ALL_DICTS_CC); }
+<GhcPragma>"_USER_CC_" { RETURN(CO_USER_CC); }
+<GhcPragma>"_AUTO_CC_" { RETURN(CO_AUTO_CC); }
+<GhcPragma>"_DICT_CC_" { RETURN(CO_DICT_CC); }
+
+<GhcPragma>"_DUPD_CC_" { RETURN(CO_DUPD_CC); }
+<GhcPragma>"_CAF_CC_" { RETURN(CO_CAF_CC); }
+
+<GhcPragma>"_SDSEL_" { RETURN(CO_SDSEL_ID); }
+<GhcPragma>"_METH_" { RETURN(CO_METH_ID); }
+<GhcPragma>"_DEFM_" { RETURN(CO_DEFM_ID); }
+<GhcPragma>"_DFUN_" { RETURN(CO_DFUN_ID); }
+<GhcPragma>"_CONSTM_" { RETURN(CO_CONSTM_ID); }
+<GhcPragma>"_SPEC_" { RETURN(CO_SPEC_ID); }
+<GhcPragma>"_WRKR_" { RETURN(CO_WRKR_ID); }
+<GhcPragma>"_ORIG_" { RETURN(CO_ORIG_NM); /* fully-qualified original name*/ }
+
+<GhcPragma>"_ALWAYS_" { RETURN(UNFOLD_ALWAYS); }
+<GhcPragma>"_IF_ARGS_" { RETURN(UNFOLD_IF_ARGS); }
+
+<GhcPragma>"_NOREP_I_" { RETURN(NOREP_INTEGER); }
+<GhcPragma>"_NOREP_R_" { RETURN(NOREP_RATIONAL); }
+<GhcPragma>"_NOREP_S_" { RETURN(NOREP_STRING); }
+
+<GhcPragma>" #-}" { POP_STATE; RETURN(END_PRAGMA); }
+
+<Code,GlaExt>"{-#"{WS}*"SPECIALI"[SZ]E {
+ PUSH_STATE(UserPragma);
+ RETURN(SPECIALISE_UPRAGMA);
+ }
+<Code,GlaExt>"{-#"{WS}*"INLINE" {
+ PUSH_STATE(UserPragma);
+ RETURN(INLINE_UPRAGMA);
+ }
+<Code,GlaExt>"{-#"{WS}*"MAGIC_UNFOLDING" {
+ PUSH_STATE(UserPragma);
+ RETURN(MAGIC_UNFOLDING_UPRAGMA);
+ }
+<Code,GlaExt>"{-#"{WS}*"DEFOREST" {
+ PUSH_STATE(UserPragma);
+ RETURN(DEFOREST_UPRAGMA);
+ }
+<Code,GlaExt>"{-#"{WS}*"ABSTRACT" {
+ PUSH_STATE(UserPragma);
+ RETURN(ABSTRACT_UPRAGMA);
+ }
+<UserPragma>"#-}" { POP_STATE; RETURN(END_UPRAGMA); }
+
+%{
+ /*
+ * Haskell keywords. `scc' is actually a Glasgow extension, but it is
+ * intentionally accepted as a keyword even for normal <Code>.
+ */
+%}
+
+<Code,GlaExt,GhcPragma>"case" { RETURN(CASE); }
+<Code,GlaExt>"class" { RETURN(CLASS); }
+<Code,GlaExt,UserPragma>"data" { RETURN(DATA); }
+<Code,GlaExt>"default" { RETURN(DEFAULT); }
+<Code,GlaExt>"deriving" { RETURN(DERIVING); }
+<Code,GlaExt>"else" { RETURN(ELSE); }
+<Code,GlaExt>"hiding" { RETURN(HIDING); }
+<Code,GlaExt>"if" { RETURN(IF); }
+<Code,GlaExt>"import" { RETURN(IMPORT); }
+<Code,GlaExt>"infix" { RETURN(INFIX); }
+<Code,GlaExt>"infixl" { RETURN(INFIXL); }
+<Code,GlaExt>"infixr" { RETURN(INFIXR); }
+<Code,GlaExt,UserPragma>"instance" { RETURN(INSTANCE); }
+<Code,GlaExt>"interface" { RETURN(INTERFACE); }
+<Code,GlaExt>"module" { RETURN(MODULE); }
+<Code,GlaExt,GhcPragma>"of" { RETURN(OF); }
+<Code,GlaExt>"renaming" { RETURN(RENAMING); }
+<Code,GlaExt>"then" { RETURN(THEN); }
+<Code,GlaExt>"to" { RETURN(TO); }
+<Code,GlaExt>"type" { RETURN(TYPE); }
+<Code,GlaExt>"where" { RETURN(WHERE); }
+<Code,GlaExt,GhcPragma>"in" { RETURN(IN); }
+<Code,GlaExt,GhcPragma>"let" { RETURN(LET); }
+<GlaExt,GhcPragma>"_ccall_" { RETURN(CCALL); }
+<GlaExt,GhcPragma>"_ccall_GC_" { RETURN(CCALL_GC); }
+<GlaExt,GhcPragma>"_casm_" { RETURN(CASM); }
+<GlaExt,GhcPragma>"_casm_GC_" { RETURN(CASM_GC); }
+<Code,GlaExt,GhcPragma>"_scc_" { RETURN(SCC); }
+<GhcPragma>"_forall_" { RETURN(FORALL); }
+
+%{
+ /*
+ * Haskell operators. Nothing special about these.
+ */
+%}
+
+<Code,GlaExt>".." { RETURN(DOTDOT); }
+<Code,GlaExt,GhcPragma>";" { RETURN(SEMI); }
+<Code,GlaExt,GhcPragma,UserPragma>"," { RETURN(COMMA); }
+<Code,GlaExt,GhcPragma>"|" { RETURN(VBAR); }
+<Code,GlaExt,GhcPragma,UserPragma>"=" { RETURN(EQUAL); }
+<Code,GlaExt>"<-" { RETURN(LARROW); }
+<Code,GlaExt,GhcPragma,UserPragma>"->" { RETURN(RARROW); }
+<Code,GlaExt,GhcPragma,UserPragma>"=>" { RETURN(DARROW); }
+<Code,GlaExt,GhcPragma,UserPragma>"::" { RETURN(DCOLON); }
+<Code,GlaExt,GhcPragma,UserPragma>"(" { RETURN(OPAREN); }
+<Code,GlaExt,GhcPragma,UserPragma>")" { RETURN(CPAREN); }
+<Code,GlaExt,GhcPragma,UserPragma>"[" { RETURN(OBRACK); }
+<Code,GlaExt,GhcPragma,UserPragma>"]" { RETURN(CBRACK); }
+<Code,GlaExt,GhcPragma>"{" { RETURN(OCURLY); }
+<Code,GlaExt,GhcPragma>"}" { RETURN(CCURLY); }
+<Code,GlaExt>"+" { RETURN(PLUS); }
+<Code,GlaExt>"@" { RETURN(AT); }
+<Code,GlaExt,GhcPragma>"\\" { RETURN(LAMBDA); }
+<GhcPragma>"_/\\_" { RETURN(TYLAMBDA); }
+<Code,GlaExt>"_" { RETURN(WILDCARD); }
+<Code,GlaExt,GhcPragma>"`" { RETURN(BQUOTE); }
+<Code,GlaExt>"~" { RETURN(LAZY); }
+<Code,GlaExt>"-" { RETURN(MINUS); }
+
+%{
+ /*
+ * Integers and (for Glasgow extensions) primitive integers. Note that
+ * we pass all of the text on to the parser, because flex/C can't handle
+ * arbitrary precision numbers.
+ */
+%}
+
+<GlaExt>("-")?"0o"{O}+"#" { /* octal */
+ yylval.uid = xstrndup(yytext, yyleng - 1);
+ RETURN(INTPRIM);
+ }
+<Code,GlaExt>"0o"{O}+ { /* octal */
+ yylval.uid = xstrndup(yytext, yyleng);
+ RETURN(INTEGER);
+ }
+<GlaExt>("-")?"0x"{H}+"#" { /* hexadecimal */
+ yylval.uid = xstrndup(yytext, yyleng - 1);
+ RETURN(INTPRIM);
+ }
+<Code,GlaExt>"0x"{H}+ { /* hexadecimal */
+ yylval.uid = xstrndup(yytext, yyleng);
+ RETURN(INTEGER);
+ }
+<GlaExt,GhcPragma>("-")?{N}"#" {
+ yylval.uid = xstrndup(yytext, yyleng - 1);
+ RETURN(INTPRIM);
+ }
+<Code,GlaExt,GhcPragma>{N} {
+ yylval.uid = xstrndup(yytext, yyleng);
+ RETURN(INTEGER);
+ }
+
+%{
+ /*
+ * Floats and (for Glasgow extensions) primitive floats/doubles.
+ */
+%}
+
+<GlaExt,GhcPragma>("-")?{F}"##" {
+ yylval.uid = xstrndup(yytext, yyleng - 2);
+ RETURN(DOUBLEPRIM);
+ }
+<GlaExt,GhcPragma>("-")?{F}"#" {
+ yylval.uid = xstrndup(yytext, yyleng - 1);
+ RETURN(FLOATPRIM);
+ }
+<Code,GlaExt>{F} {
+ yylval.uid = xstrndup(yytext, yyleng);
+ RETURN(FLOAT);
+ }
+
+%{
+ /*
+ * Funky ``foo'' style C literals for Glasgow extensions
+ */
+%}
+
+<GlaExt,GhcPragma>"``"[^']+"''" {
+ hsnewid(yytext + 2, yyleng - 4);
+ RETURN(CLITLIT);
+ }
+
+%{
+ /*
+ * Identifiers, both variables and operators. The trailing hash is allowed
+ * for Glasgow extensions.
+ */
+%}
+
+<GhcPragma>"_NIL_" { hsnewid(yytext, yyleng); RETURN(CONID); }
+<GhcPragma>"_TUP_"{D}+ { hsnewid(yytext, yyleng); RETURN(CONID); }
+<GhcPragma>[a-z]{i}*"$"[a-z]{i}* { hsnewid(yytext, yyleng); RETURN(TYVAR_TEMPLATE_ID); }
+
+<GlaExt,GhcPragma,UserPragma>{Id}"#" {
+ hsnewid(yytext, yyleng);
+ RETURN(_isconstr(yytext) ? CONID : VARID);
+ }
+%{
+/* This SHOULDNAE work in "Code" (sigh) */
+%}
+<Code,GlaExt,GhcPragma,UserPragma>_+{Id} {
+ if (! (nonstandardFlag || in_interface)) {
+ char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "Non-standard identifier (leading underscore): %s\n", yytext);
+ hsperror(errbuf);
+ }
+ hsnewid(yytext, yyleng);
+ RETURN(isconstr(yytext) ? CONID : VARID);
+ /* NB: ^^^^^^^^ : not the macro! */
+ }
+<Code,GlaExt,GhcPragma,UserPragma>{Id} {
+ hsnewid(yytext, yyleng);
+ RETURN(_isconstr(yytext) ? CONID : VARID);
+ }
+<Code,GlaExt,GhcPragma,UserPragma>{SId} {
+ hsnewid(yytext, yyleng);
+ RETURN(_isconstr(yytext) ? CONSYM : VARSYM);
+ }
+
+%{
+ /* Why is `{Id}#` matched this way, and `{Id}` lexed as three tokens? --JSM */
+
+ /* Because we can make the former well-behaved (we defined them).
+
+ Sadly, the latter is defined by Haskell, which allows such
+ la-la land constructs as `{-a 900-line comment-} foo`. (WDP 94/12)
+ */
+%}
+
+<GlaExt,GhcPragma,UserPragma>"`"{Id}"#`" {
+ hsnewid(yytext + 1, yyleng - 2);
+ RETURN(_isconstr(yytext+1) ? CONSYM : VARSYM);
+ }
+
+%{
+ /*
+ * Character literals. The first form is the quick form, for character
+ * literals that don't contain backslashes. Literals with backslashes are
+ * lexed through multiple rules. First, we match the open ' and as many
+ * normal characters as possible. This puts us into the <Char> state, where
+ * a backslash is legal. Then, we match the backslash and move into the
+ * <CharEsc> state. When we drop out of <CharEsc>, we collect more normal
+ * characters and the close '. We may end up with too many characters, but
+ * this allows us to easily share the lex rules with strings. Excess characters
+ * are ignored with a warning.
+ */
+%}
+
+<GlaExt,GhcPragma>'({CHAR}|"\"")"'#" {
+ yylval.uhstring = installHstring(1, yytext+1);
+ RETURN(CHARPRIM);
+ }
+<Code,GlaExt>'({CHAR}|"\"")' {
+ yylval.uhstring = installHstring(1, yytext+1);
+ RETURN(CHAR);
+ }
+<Code,GlaExt>'' {char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "'' is not a valid character (or string) literal\n");
+ hsperror(errbuf);
+ }
+<Code,GlaExt,GhcPragma>'({CHAR}|"\"")* {
+ hsmlcolno = hspcolno;
+ cleartext();
+ addtext(yytext+1, yyleng-1);
+ PUSH_STATE(Char);
+ }
+<Char>({CHAR}|"\"")*'# {
+ unsigned length;
+ char *text;
+
+ addtext(yytext, yyleng - 2);
+ text = fetchtext(&length);
+
+ if (! (nonstandardFlag || in_interface)) {
+ char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "`Char-hash' literals are non-standard: %s\n", text);
+ hsperror(errbuf);
+ }
+
+ if (length > 1) {
+ fprintf(stderr, "\"%s\", line %d, column %d: Unboxed character literal '",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) text, length);
+ fputs("' too long\n", stderr);
+ hsperror("");
+ }
+ yylval.uhstring = installHstring(1, text);
+ hspcolno = hsmlcolno;
+ POP_STATE;
+ RETURN(CHARPRIM);
+ }
+<Char>({CHAR}|"\"")*' {
+ unsigned length;
+ char *text;
+
+ addtext(yytext, yyleng - 1);
+ text = fetchtext(&length);
+
+ if (length > 1) {
+ fprintf(stderr, "\"%s\", line %d, column %d: Character literal '",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) text, length);
+ fputs("' too long\n", stderr);
+ hsperror("");
+ }
+ yylval.uhstring = installHstring(1, text);
+ hspcolno = hsmlcolno;
+ POP_STATE;
+ RETURN(CHAR);
+ }
+<Char>({CHAR}|"\"")+ { addtext(yytext, yyleng); }
+
+
+%{
+ /*
+ * String literals. The first form is the quick form, for string literals
+ * that don't contain backslashes. Literals with backslashes are lexed
+ * through multiple rules. First, we match the open " and as many normal
+ * characters as possible. This puts us into the <String> state, where
+ * a backslash is legal. Then, we match the backslash and move into the
+ * <StringEsc> state. When we drop out of <StringEsc>, we collect more normal
+ * characters, moving back and forth between <String> and <StringEsc> as more
+ * backslashes are encountered. (We may even digress into <Comment> mode if we
+ * find a comment in a gap between backslashes.) Finally, we read the last chunk
+ * of normal characters and the close ".
+ */
+%}
+
+<GlaExt,GhcPragma>"\""({CHAR}|"'")*"\""# {
+ yylval.uhstring = installHstring(yyleng-3, yytext+1);
+ /* the -3 accounts for the " on front, "# on the end */
+ RETURN(STRINGPRIM);
+ }
+<Code,GlaExt,GhcPragma>"\""({CHAR}|"'")*"\"" {
+ yylval.uhstring = installHstring(yyleng-2, yytext+1);
+ RETURN(STRING);
+ }
+<Code,GlaExt,GhcPragma>"\""({CHAR}|"'")* {
+ hsmlcolno = hspcolno;
+ cleartext();
+ addtext(yytext+1, yyleng-1);
+ PUSH_STATE(String);
+ }
+<String>({CHAR}|"'")*"\"#" {
+ unsigned length;
+ char *text;
+
+ addtext(yytext, yyleng-2);
+ text = fetchtext(&length);
+
+ if (! (nonstandardFlag || in_interface)) {
+ char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "`String-hash' literals are non-standard: %s\n", text);
+ hsperror(errbuf);
+ }
+
+ yylval.uhstring = installHstring(length, text);
+ hspcolno = hsmlcolno;
+ POP_STATE;
+ RETURN(STRINGPRIM);
+ }
+<String>({CHAR}|"'")*"\"" {
+ unsigned length;
+ char *text;
+
+ addtext(yytext, yyleng-1);
+ text = fetchtext(&length);
+
+ yylval.uhstring = installHstring(length, text);
+ hspcolno = hsmlcolno;
+ POP_STATE;
+ RETURN(STRING);
+ }
+<String>({CHAR}|"'")+ { addtext(yytext, yyleng); }
+
+%{
+ /*
+ * Character and string escapes are roughly the same, but strings have the
+ * extra `\&' sequence which is not allowed for characters. Also, comments
+ * are allowed in the <StringEsc> state. (See the comment section much
+ * further down.)
+ *
+ * NB: Backslashes and tabs are stored in strings as themselves.
+ * But if we print them (in printtree.c), they must go out as
+ * "\\\\" and "\\t" respectively. (This is because of the bogus
+ * intermediate format that the parser produces. It uses '\t' fpr end of
+ * string, so it needs to be able to escape tabs, which means that it
+ * also needs to be able to escape the escape character ('\\'). Sigh.
+ */
+%}
+
+<Char>\\ { PUSH_STATE(CharEsc); }
+<String>\\& /* Ignore */ ;
+<String>\\ { PUSH_STATE(StringEsc); noGap = TRUE; }
+
+<CharEsc>\\ { addchar(*yytext); POP_STATE; }
+<StringEsc>\\ { if (noGap) { addchar(*yytext); } POP_STATE; }
+
+<CharEsc,StringEsc>["'] { addchar(*yytext); POP_STATE; }
+<CharEsc,StringEsc>NUL { addchar('\000'); POP_STATE; }
+<CharEsc,StringEsc>SOH { addchar('\001'); POP_STATE; }
+<CharEsc,StringEsc>STX { addchar('\002'); POP_STATE; }
+<CharEsc,StringEsc>ETX { addchar('\003'); POP_STATE; }
+<CharEsc,StringEsc>EOT { addchar('\004'); POP_STATE; }
+<CharEsc,StringEsc>ENQ { addchar('\005'); POP_STATE; }
+<CharEsc,StringEsc>ACK { addchar('\006'); POP_STATE; }
+<CharEsc,StringEsc>BEL |
+<CharEsc,StringEsc>a { addchar('\007'); POP_STATE; }
+<CharEsc,StringEsc>BS |
+<CharEsc,StringEsc>b { addchar('\010'); POP_STATE; }
+<CharEsc,StringEsc>HT |
+<CharEsc,StringEsc>t { addchar('\011'); POP_STATE; }
+<CharEsc,StringEsc>LF |
+<CharEsc,StringEsc>n { addchar('\012'); POP_STATE; }
+<CharEsc,StringEsc>VT |
+<CharEsc,StringEsc>v { addchar('\013'); POP_STATE; }
+<CharEsc,StringEsc>FF |
+<CharEsc,StringEsc>f { addchar('\014'); POP_STATE; }
+<CharEsc,StringEsc>CR |
+<CharEsc,StringEsc>r { addchar('\015'); POP_STATE; }
+<CharEsc,StringEsc>SO { addchar('\016'); POP_STATE; }
+<CharEsc,StringEsc>SI { addchar('\017'); POP_STATE; }
+<CharEsc,StringEsc>DLE { addchar('\020'); POP_STATE; }
+<CharEsc,StringEsc>DC1 { addchar('\021'); POP_STATE; }
+<CharEsc,StringEsc>DC2 { addchar('\022'); POP_STATE; }
+<CharEsc,StringEsc>DC3 { addchar('\023'); POP_STATE; }
+<CharEsc,StringEsc>DC4 { addchar('\024'); POP_STATE; }
+<CharEsc,StringEsc>NAK { addchar('\025'); POP_STATE; }
+<CharEsc,StringEsc>SYN { addchar('\026'); POP_STATE; }
+<CharEsc,StringEsc>ETB { addchar('\027'); POP_STATE; }
+<CharEsc,StringEsc>CAN { addchar('\030'); POP_STATE; }
+<CharEsc,StringEsc>EM { addchar('\031'); POP_STATE; }
+<CharEsc,StringEsc>SUB { addchar('\032'); POP_STATE; }
+<CharEsc,StringEsc>ESC { addchar('\033'); POP_STATE; }
+<CharEsc,StringEsc>FS { addchar('\034'); POP_STATE; }
+<CharEsc,StringEsc>GS { addchar('\035'); POP_STATE; }
+<CharEsc,StringEsc>RS { addchar('\036'); POP_STATE; }
+<CharEsc,StringEsc>US { addchar('\037'); POP_STATE; }
+<CharEsc,StringEsc>SP { addchar('\040'); POP_STATE; }
+<CharEsc,StringEsc>DEL { addchar('\177'); POP_STATE; }
+<CharEsc,StringEsc>"^"{CNTRL} { char c = yytext[1] - '@'; addchar(c); POP_STATE; }
+<CharEsc,StringEsc>{D}+ {
+ int i = strtol(yytext, NULL, 10);
+ if (i < NCHARS) {
+ addchar((char) i);
+ } else {
+ char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "Numeric escape \"\\%s\" out of range\n",
+ yytext);
+ hsperror(errbuf);
+ }
+ POP_STATE;
+ }
+<CharEsc,StringEsc>o{O}+ {
+ int i = strtol(yytext + 1, NULL, 8);
+ if (i < NCHARS) {
+ addchar((char) i);
+ } else {
+ char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "Numeric escape \"\\%s\" out of range\n",
+ yytext);
+ hsperror(errbuf);
+ }
+ POP_STATE;
+ }
+<CharEsc,StringEsc>x{H}+ {
+ int i = strtol(yytext + 1, NULL, 16);
+ if (i < NCHARS) {
+ addchar((char) i);
+ } else {
+ char errbuf[ERR_BUF_SIZE];
+ sprintf(errbuf, "Numeric escape \"\\%s\" out of range\n",
+ yytext);
+ hsperror(errbuf);
+ }
+ POP_STATE;
+ }
+
+%{
+ /*
+ * Simple comments and whitespace. Normally, we would just ignore these, but
+ * in case we're processing a string escape, we need to note that we've seen
+ * a gap.
+ */
+%}
+
+<Code,GlaExt,StringEsc>"--".*{NL}{WS}* |
+<Code,GlaExt,GhcPragma,UserPragma,StringEsc>{WS}+ { noGap = FALSE; }
+
+%{
+ /*
+ * Nested comments. The major complication here is in trying to match the
+ * longest lexemes possible, for better performance. (See the flex document.)
+ * That's why the rules look so bizarre.
+ */
+%}
+
+<Code,GlaExt,GhcPragma,UserPragma,StringEsc>"{-" {
+ noGap = FALSE; nested_comments = 1; PUSH_STATE(Comment);
+ }
+
+<Comment>[^-{]* |
+<Comment>"-"+[^-{}]+ |
+<Comment>"{"+[^-{}]+ ;
+<Comment>"{-" { nested_comments++; }
+<Comment>"-}" { if (--nested_comments == 0) POP_STATE; }
+<Comment>(.|\n) ;
+
+%{
+ /*
+ * Illegal characters. This used to be a single rule, but we might as well
+ * pass on as much information as we have, so now we indicate our state in
+ * the error message.
+ */
+%}
+
+<INITIAL,Code,GlaExt,GhcPragma,UserPragma>(.|\n) {
+ fprintf(stderr, "\"%s\", line %d, column %d: Illegal character: `",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) yytext, 1);
+ fputs("'\n", stderr);
+ hsperror("");
+ }
+<Char>(.|\n) {
+ fprintf(stderr, "\"%s\", line %d, column %d: Illegal character: `",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) yytext, 1);
+ fputs("' in a character literal\n", stderr);
+ hsperror("");
+ }
+<CharEsc>(.|\n) {
+ fprintf(stderr, "\"%s\", line %d, column %d: Illegal character escape: `\\",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) yytext, 1);
+ fputs("'\n", stderr);
+ hsperror("");
+ }
+<String>(.|\n) { if (nonstandardFlag) {
+ addtext(yytext, yyleng);
+ } else {
+ fprintf(stderr, "\"%s\", line %d, column %d: Illegal character: `",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) yytext, 1);
+ fputs("' in a string literal\n", stderr);
+ hsperror("");
+ }
+ }
+<StringEsc>(.|\n) {
+ if (noGap) {
+ fprintf(stderr, "\"%s\", line %d, column %d: Illegal string escape: `\\",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) yytext, 1);
+ fputs("'\n", stderr);
+ hsperror("");
+ } else {
+ fprintf(stderr, "\"%s\", line %d, column %d: Illegal character: `",
+ input_filename, hsplineno, hspcolno + 1);
+ format_string(stderr, (unsigned char *) yytext, 1);
+ fputs("' in a string gap\n", stderr);
+ hsperror("");
+ }
+ }
+
+%{
+ /*
+ * End of file. In any sub-state, this is an error. However, for the primary
+ * <Code> and <GlaExt> states, this is perfectly normal. We just return an EOF
+ * and let the yylex() wrapper deal with whatever has to be done next (e.g.
+ * adding virtual close curlies, or closing an interface and returning to the
+ * primary source file.
+ *
+ * Note that flex does not call YY_USER_ACTION for <<EOF>> rules. Hence the
+ * line/column advancement has to be done by hand.
+ */
+%}
+
+<Char,CharEsc><<EOF>> {
+ hsplineno = hslineno; hspcolno = hscolno;
+ hsperror("unterminated character literal");
+ }
+<Comment><<EOF>> {
+ hsplineno = hslineno; hspcolno = hscolno;
+ hsperror("unterminated comment");
+ }
+<String,StringEsc><<EOF>> {
+ hsplineno = hslineno; hspcolno = hscolno;
+ hsperror("unterminated string literal");
+ }
+<GhcPragma><<EOF>> {
+ hsplineno = hslineno; hspcolno = hscolno;
+ hsperror("unterminated interface pragma");
+ }
+<UserPragma><<EOF>> {
+ hsplineno = hslineno; hspcolno = hscolno;
+ hsperror("unterminated user-specified pragma");
+ }
+<Code,GlaExt><<EOF>> { hsplineno = hslineno; hspcolno = hscolno; return(EOF); }
+
+%%
+
+/**********************************************************************
+* *
+* *
+* YACC/LEX Initialisation etc. *
+* *
+* *
+**********************************************************************/
+
+/*
+ We initialise input_filename to "<stdin>".
+ This allows unnamed sources to be piped into the parser.
+*/
+
+void
+yyinit()
+{
+ extern BOOLEAN acceptPrim;
+
+ input_filename = xstrdup("<stdin>");
+
+ /* We must initialize the input buffer _now_, because we call
+ setyyin _before_ calling yylex for the first time! */
+ yy_switch_to_buffer(yy_create_buffer(stdin, YY_BUF_SIZE));
+
+ if (acceptPrim)
+ PUSH_STATE(GlaExt);
+ else
+ PUSH_STATE(Code);
+}
+
+void
+new_filename(f) /* This looks pretty dodgy to me (WDP) */
+ char *f;
+{
+ if (input_filename != NULL)
+ free(input_filename);
+ input_filename = xstrdup(f);
+}
+
+/**********************************************************************
+* *
+* *
+* Layout Processing *
+* *
+* *
+**********************************************************************/
+
+/*
+ The following section deals with Haskell Layout conventions
+ forcing insertion of ; or } as appropriate
+*/
+
+BOOLEAN
+hsshouldindent()
+{
+ return (!forgetindent && INDENTON);
+}
+
+
+/* Enter new context and set new indentation level */
+void
+hssetindent()
+{
+#ifdef HSP_DEBUG
+ fprintf(stderr, "hssetindent:hscolno=%d,hspcolno=%d,INDENTPT[%d]=%d\n", hscolno, hspcolno, icontexts, INDENTPT);
+#endif
+
+ /*
+ * partain: first chk that new indent won't be less than current one; this code
+ * doesn't make sense to me; hscolno tells the position of the _end_ of the
+ * current token; what that has to do with indenting, I don't know.
+ */
+
+
+ if (hscolno - 1 <= INDENTPT) {
+ if (INDENTPT == -1)
+ return; /* Empty input OK for Haskell 1.1 */
+ else {
+ char errbuf[ERR_BUF_SIZE];
+
+ sprintf(errbuf, "Layout error -- indentation should be > %d cols", INDENTPT);
+ hsperror(errbuf);
+ }
+ }
+ hsentercontext((hspcolno << 1) | 1);
+}
+
+
+/* Enter a new context without changing the indentation level */
+void
+hsincindent()
+{
+#ifdef HSP_DEBUG
+ fprintf(stderr, "hsincindent:hscolno=%d,hspcolno=%d,INDENTPT[%d]=%d\n", hscolno, hspcolno, icontexts, INDENTPT);
+#endif
+ hsentercontext(indenttab[icontexts] & ~1);
+}
+
+
+/* Turn off indentation processing, usually because an explicit "{" has been seen */
+void
+hsindentoff()
+{
+ forgetindent = TRUE;
+}
+
+
+/* Enter a new layout context. */
+void
+hsentercontext(indent)
+ int indent;
+{
+ /* Enter new context and set indentation as specified */
+ if (++icontexts >= MAX_CONTEXTS) {
+ char errbuf[ERR_BUF_SIZE];
+
+ sprintf(errbuf, "`wheres' and `cases' nested too deeply (>%d)", MAX_CONTEXTS - 1);
+ hsperror(errbuf);
+ }
+ forgetindent = FALSE;
+ indenttab[icontexts] = indent;
+#ifdef HSP_DEBUG
+ fprintf(stderr, "hsentercontext:indent=%d,hscolno=%d,hspcolno=%d,INDENTPT[%d]=%d\n", indent, hscolno, hspcolno, icontexts, INDENTPT);
+#endif
+}
+
+
+/* Exit a layout context */
+void
+hsendindent()
+{
+ --icontexts;
+#ifdef HSP_DEBUG
+ fprintf(stderr, "hsendindent:hscolno=%d,hspcolno=%d,INDENTPT[%d]=%d\n", hscolno, hspcolno, icontexts, INDENTPT);
+#endif
+}
+
+/*
+ * Return checks the indentation level and returns ;, } or the specified token.
+ */
+
+int
+Return(tok)
+ int tok;
+{
+#ifdef HSP_DEBUG
+ extern int yyleng;
+#endif
+
+ if (hsshouldindent()) {
+ if (hspcolno < INDENTPT) {
+#ifdef HSP_DEBUG
+ fprintf(stderr, "inserted '}' before %d (%d:%d:%d:%d)\n", tok, hspcolno, hscolno, yyleng, INDENTPT);
+#endif
+ hssttok = tok;
+ return (VCCURLY);
+ } else if (hspcolno == INDENTPT) {
+#ifdef HSP_DEBUG
+ fprintf(stderr, "inserted ';' before %d (%d:%d)\n", tok, hspcolno, INDENTPT);
+#endif
+ hssttok = -tok;
+ return (SEMI);
+ }
+ }
+ hssttok = -1;
+#ifdef HSP_DEBUG
+ fprintf(stderr, "returning %d (%d:%d)\n", tok, hspcolno, INDENTPT);
+#endif
+ return (tok);
+}
+
+
+/*
+ * Redefine yylex to check for stacked tokens, yylex1() is the original yylex()
+ */
+int
+yylex()
+{
+ int tok;
+ static BOOLEAN eof = FALSE;
+
+ if (!eof) {
+ if (hssttok != -1) {
+ if (hssttok < 0) {
+ tok = -hssttok;
+ hssttok = -1;
+ return tok;
+ }
+ RETURN(hssttok);
+ } else {
+ endlineno = hslineno;
+ if ((tok = yylex1()) != EOF)
+ return tok;
+ else
+ eof = TRUE;
+ }
+ }
+ if (icontexts > icontexts_save) {
+ if (INDENTON) {
+ eof = TRUE;
+ indenttab[icontexts] = 0;
+ return (VCCURLY);
+ } else
+ hsperror("missing '}' at end of file");
+ } else if (hsbuf_save != NULL) {
+ fclose(yyin);
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(hsbuf_save);
+ hsbuf_save = NULL;
+ new_filename(filename_save);
+ free(filename_save);
+ hslineno = hslineno_save;
+ hsplineno = hsplineno_save;
+ hscolno = hscolno_save;
+ hspcolno = hspcolno_save;
+ etags = etags_save;
+ in_interface = FALSE;
+ icontexts = icontexts_save - 1;
+ icontexts_save = 0;
+#ifdef HSP_DEBUG
+ fprintf(stderr, "finished reading interface (%d:%d:%d)\n", hscolno, hspcolno, INDENTPT);
+#endif
+ eof = FALSE;
+ RETURN(LEOF);
+ } else {
+ yyterminate();
+ }
+ abort(); /* should never get here! */
+ return(0);
+}
+
+/**********************************************************************
+* *
+* *
+* Input Processing for Interfaces *
+* *
+* *
+**********************************************************************/
+
+/* setyyin(file) open file as new lex input buffer */
+void
+setyyin(file)
+ char *file;
+{
+ extern FILE *yyin;
+
+ hsbuf_save = YY_CURRENT_BUFFER;
+ if ((yyin = fopen(file, "r")) == NULL) {
+ char errbuf[ERR_BUF_SIZE];
+
+ sprintf(errbuf, "can't read \"%-.50s\"", file);
+ hsperror(errbuf);
+ }
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+
+ hslineno_save = hslineno;
+ hsplineno_save = hsplineno;
+ hslineno = hsplineno = 1;
+
+ filename_save = input_filename;
+ input_filename = NULL;
+ new_filename(file);
+ hscolno_save = hscolno;
+ hspcolno_save = hspcolno;
+ hscolno = hspcolno = 0;
+ in_interface = TRUE;
+ etags_save = etags; /* do not do "etags" stuff in interfaces */
+ etags = 0; /* We remember whether we are doing it in
+ the module, so we can restore it later [WDP 94/09] */
+ hsentercontext(-1); /* partain: changed this from 0 */
+ icontexts_save = icontexts;
+#ifdef HSP_DEBUG
+ fprintf(stderr, "reading %s (%d:%d:%d)\n", input_filename, hscolno_save, hspcolno_save, INDENTPT);
+#endif
+}
+
+static VOID
+layout_input(text, len)
+char *text;
+int len;
+{
+#ifdef HSP_DEBUG
+ fprintf(stderr, "Scanning \"%s\"\n", text);
+#endif
+
+ hsplineno = hslineno;
+ hspcolno = hscolno;
+
+ while (len-- > 0) {
+ switch (*text++) {
+ case '\n':
+ case '\r':
+ case '\f':
+ hslineno++;
+ hscolno = 0;
+ break;
+ case '\t':
+ hscolno += 8 - (hscolno % 8); /* Tabs stops are 8 columns apart */
+ break;
+ case '\v':
+ break;
+ default:
+ ++hscolno;
+ break;
+ }
+ }
+}
+
+void
+setstartlineno()
+{
+ startlineno = hsplineno;
+#if 1/*etags*/
+#else
+ if (etags)
+ fprintf(stderr,"%u\tsetstartlineno (col %u)\n",startlineno,hscolno);
+#endif
+}
+
+/**********************************************************************
+* *
+* *
+* Text Caching *
+* *
+* *
+**********************************************************************/
+
+#define CACHE_SIZE YY_BUF_SIZE
+
+static struct {
+ unsigned allocated;
+ unsigned next;
+ char *text;
+} textcache = { 0, 0, NULL };
+
+static VOID
+cleartext()
+{
+/* fprintf(stderr, "cleartext\n"); */
+ textcache.next = 0;
+ if (textcache.allocated == 0) {
+ textcache.allocated = CACHE_SIZE;
+ textcache.text = xmalloc(CACHE_SIZE);
+ }
+}
+
+static VOID
+addtext(text, length)
+char *text;
+unsigned length;
+{
+/* fprintf(stderr, "addtext: %d %s\n", length, text); */
+
+ if (length == 0)
+ return;
+
+ if (textcache.next + length + 1 >= textcache.allocated) {
+ textcache.allocated += length + CACHE_SIZE;
+ textcache.text = xrealloc(textcache.text, textcache.allocated);
+ }
+ bcopy(text, textcache.text + textcache.next, length);
+ textcache.next += length;
+}
+
+static VOID
+#ifdef __STDC__
+addchar(char c)
+#else
+addchar(c)
+ char c;
+#endif
+{
+/* fprintf(stderr, "addchar: %c\n", c); */
+
+ if (textcache.next + 2 >= textcache.allocated) {
+ textcache.allocated += CACHE_SIZE;
+ textcache.text = xrealloc(textcache.text, textcache.allocated);
+ }
+ textcache.text[textcache.next++] = c;
+}
+
+static char *
+fetchtext(length)
+unsigned *length;
+{
+/* fprintf(stderr, "fetchtext: %d\n", textcache.next); */
+
+ *length = textcache.next;
+ textcache.text[textcache.next] = '\0';
+ return textcache.text;
+}
+
+/**********************************************************************
+* *
+* *
+* Identifier Processing *
+* *
+* *
+**********************************************************************/
+
+/*
+ hsnewid Enters an id of length n into the symbol table.
+*/
+
+static VOID
+hsnewid(name, length)
+char *name;
+int length;
+{
+ char save = name[length];
+
+ name[length] = '\0';
+ yylval.uid = installid(name);
+ name[length] = save;
+}
+
+BOOLEAN
+isconstr(s) /* walks past leading underscores before using the macro */
+ char *s;
+{
+ char *temp = s;
+
+ for ( ; temp != NULL && *temp == '_' ; temp++ );
+
+ return _isconstr(temp);
+}