include $(TOP)/mk/target.mk
dist :: dist-post
-#
-# Automatically remake update configuration files
-# (from autoconf manual)
-#
-configure: configure.in
- autoconf
-#
-# autoheader might not change config.h.in, so touch a stamp file.
-#
-mk/config.h.in: mk/stamp-h.in
-mk/stamp-h.in: configure.in
- autoheader
- echo timestamp > mk/stamp-h.in
-
-mk/config.h: mk/stamp-h
-mk/stamp-h: mk/config.h.in config.status
- ./config.status
-
-config.status: configure
- ./config.status --recheck
-
-.PHONY: config
-
-config: config.status
- @:
TOP = ..
include $(TOP)/mk/boilerplate.mk
-DOC_SRCS = installing.lit release.lit
+DOC_SRCS = installing.lit
SRC_TEXI2HTML_OPTS += -number -monolithic -invisible xbm
You need to be a bit careful, though, that any new files you create
(if you do any development work) are in the source tree, not a build tree!
+Remember, that the source files in the build tree are {\em symbolic
+links} to the files in the source tree. (The build tree soon
+accumulates lots of built files like @Foo.o@, as well.) You can {\em
+delete} a source file from the build tree without affecting the source
+tree (though it's an odd thing to do). On the other hand, if you {\em
+edit} a source file from the build tree, you'll edit the source-tree
+file directly. (You can set up Emacs so that if you edit a source
+file from the build tree, Emacs will silently create an edited copy of
+the source file in the build tree, leaving the source file unchanged;
+but the danger is that you think you've edited the source file whereas
+actually all you've done is edit the build-tree copy. More commonly
+you do want to edit the source file.)
+
Like the source tree, the top level of your build tree must (a linked copy of)
the root directory of the @fptools@ suite.
Inside Makefiles, the root of your build tree is called @$(FPTOOLS_TOP)@.
extra consistency-checking code gets included) or off. And so on.
All of this stuff is called the {\em configuration} of your build.
-You set the configuration using an exciting two-step process.
+You set the configuration using an exciting three-step process.
\begin{description}
-\item[Step 1: system configuration.] This is easy, provided you
-have the programs mentioned in Section~\ref{sect_std-utils}. Just
-@cd@ to @$(FPTOOLS)@ and say @gmake configure@. This
-command does three things:
-\begin{itemize}
-\item
-It runs a GNU program called @autoconf@, which
+\item[Step 1: get ready for configuration.]
+Change directory to @$(FPTOOLS)@ and issue the following two commands (with no arguments):
+\begin{enumerate}
+\item @autoconf@. This GNU program
converts @$(FPTOOLS)/configure.in@ to a shell script
called @$(FPTOOLS)/configure@.
-This step is completely platform-independent; it just means
+\item @autoheader@. This second GNU program converts
+@$(FPTOOLS)/configure.in@ to @$(FPTOOLS)/mk/config.h.in@.
+\end{enumerate}
+Both these steps are completely platform-independent; they just mean
that the human-written file (@configure.in@) can be short, although
-the resulting shell script, @configure@ is long.
+the resulting shell script, @configure@, and @mk/config.h.in@, are long.
-\item It runs a second GNU program called @autoheader@, which converts
-@$(FPTOOLS)/configure.in@ to @$(FPTOOLS)/mk/config.h.in@.
-Again, this step is platform-independent.
+In case you don't have @autoconf@ and @autoheader@ we distribute
+the results, @configure@, and @mk/config.h.in@, with the source distribution.
+They aren't kept in the repository, though.
-\item It then runs the newly-created @configure@ script. @configure@'s mission
+\item[Step 2: system configuration.]
+Runs the newly-created @configure@ script, thus:
+\begin{verbatim}
+ ./configure
+\end{verbatim}
+@configure@'s mission
is to scurry round your computer working out what architecture it has,
what operating system, whether it has the @vfork@ system call,
where @yacc@ is kept, whether @gcc@ is available, where various
The latter is @#include@d by various C programs, which
can thereby make use of configuration information.
\end{itemize}
-\end{itemize}
-\item[Step 2: build configuration.] Next, you say how this build
+\item[Step 3: build configuration.] Next, you say how this build
of @fptools@ is to differ from the standard defaults by creating a new
file @mk/build.mk@
{\em in the build tree}. This file is the one and only
For example, @config.mk.in@ contains the definition:
\begin{verbatim}
- SUBDIRS = glafp-utils literate ghc
+ ProjectsToBuild = glafp-utils literate ghc hslibs
\end{verbatim}
The accompanying comment explains that this is the list of enabled
projects; that is, if (after configuring) you type @gmake all@
in @FPTOOLS_TOP@ three specified projects will be made.
If you want to add @happy@, you can add this line to @build.mk@:
\begin{verbatim}
- SUBDIRS += happy
+ ProjectsToBuild += happy
\end{verbatim}
or, if you prefer,
\begin{verbatim}
- SUBDIRS = glafp-utils literate ghc happy
+ ProjectsToBuild = glafp-utils literate ghc hslibs happy
\end{verbatim}
(GNU @make@ allows existing definitions to have new text appended using
the ``@+=@'' operator, which is quite a convenient feature.)
\begin{verbatim}
cd /scratch/joe-bloggs/myfptools-sun4
\end{verbatim}
+\item Prepare for system configuration:
+\begin{verbatim}
+ autoconf
+ autoheader
+\end{verbatim}
+(You can skip this step if you are starting from a source distribution,
+and you already have @configure@ and @mk/config.h.in@.)
+
\item Do system configuration:
\begin{verbatim}
- gmake configure
+ ./configure
\end{verbatim}
+
\item Create the file @mk/build.mk@,
adding definitions for your desired configuration options.
\begin{verbatim}
#-----------------------------------------------------------------------------
-# $Id: Makefile,v 1.3 1997/03/14 07:53:55 simonpj Exp $
+# $Id: Makefile,v 1.4 1997/03/17 20:34:29 simonpj Exp $
#
TOP=.
$(line)
@echo "Booting Prelude libraries"
$(line)
- @$(MAKE) -C compiler boot
+ @$(MAKE) -C lib boot
# "CONTRIB" is also a SUBDIR, but there is nothing to build there.
# -----------------------------------------------------------------------------
-# $Id: Makefile,v 1.8 1997/03/14 07:55:43 simonpj Exp $
+# $Id: Makefile,v 1.9 1997/03/17 20:34:30 simonpj Exp $
TOP = ..
include $(TOP)/mk/boilerplate.mk
hsp: parser/printtree.o parser/main.o libhsp.a
$(CC) -o $@ $(CC_OPTS) $^
+CLEAN_FILES += hsp
#-----------------------------------------------------------------------------
# Interface files
-- Argument and return registers
| VanillaReg -- pointers, unboxed ints and chars
- PrimRep -- PtrRep, IntRep, CharRep, StablePtrRep or ForeignObjRep
+ PrimRep -- PtrRep, IntRep, CharRep, StablePtrRep or ForeignObjRep
-- (in case we need to distinguish)
FAST_INT -- its number (1 .. mAX_Vanilla_REG)
(result_type, assign_result)
= case r_kind of
-{- @ForeignObj@s replaces MallocPtrs and are *not* CReturnable.
- Instead, external references have to be turned into ForeignObjs
+{-
+ @ForeignObj@s replaces MallocPtrs and are *not* CReturnable.
+ Instead, external references have to explicitly turned into ForeignObjs
using the primop makeForeignObj#. Benefit: Multiple finalisation
routines can be accommodated and the below special case is not needed.
Price is, of course, that you have to explicitly wrap `foreign objects'
with makeForeignObj#.
-+
+
ForeignObjRep ->
(uppPStr SLIT("StgForeignObj"),
uppBesides [ uppPStr SLIT("constructForeignObj"),uppChar '(',
liveness, uppComma,
result_reg, uppComma,
local_var,
- pp_paren_semi ]) -}
+ pp_paren_semi ])
+-}
_ ->
(pprPrimKind sty r_kind,
uppBesides [ result_reg, uppEquals, local_var, uppSemi ])
stateTyConKey,
synchVarPrimTyConKey,
thenMClassOpKey,
+ toEnumClassOpKey,
traceIdKey,
trueDataConKey,
unpackCString2IdKey,
returnMClassOpKey = mkPreludeMiscIdUnique 68
-- Used for minusClassOp 69
otherwiseIdKey = mkPreludeMiscIdUnique 70
+toEnumClassOpKey = mkPreludeMiscIdUnique 71
\end{code}
= ppCat [ppPStr SLIT("in the definition of function"), ppQuote (ppr sty fun)]
pp_match CaseMatch pats
- = ppHang (ppPStr SLIT("in a group of case alternative beginning:"))
+ = ppHang (ppPStr SLIT("in a group of case alternatives beginning:"))
4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot])
pp_match PatBindMatch pats
eq_RDR, ne_RDR, le_RDR, lt_RDR, ge_RDR, gt_RDR, max_RDR, min_RDR, compare_RDR,
minBound_RDR, maxBound_RDR, enumFrom_RDR, enumFromTo_RDR, enumFromThen_RDR,
- enumFromThenTo_RDR, fromEnum_RDR,
+ enumFromThenTo_RDR, fromEnum_RDR, toEnum_RDR,
range_RDR, index_RDR, inRange_RDR, readsPrec_RDR, readList_RDR,
showsPrec_RDR, showList_RDR, plus_RDR, times_RDR, ltTag_RDR, eqTag_RDR, gtTag_RDR,
eqH_Char_RDR, ltH_Char_RDR, eqH_Word_RDR, ltH_Word_RDR, eqH_Addr_RDR, ltH_Addr_RDR,
, (enumFromTo_RDR, enumFromToClassOpKey)
, (enumFromThenTo_RDR, enumFromThenToClassOpKey)
, (fromEnum_RDR, fromEnumClassOpKey)
+ , (toEnum_RDR, toEnumClassOpKey)
, (eq_RDR, eqClassOpKey)
, (thenM_RDR, thenMClassOpKey)
, (returnM_RDR, returnMClassOpKey)
fromInt_RDR = varQual (pREL_BASE, SLIT("fromInt"))
fromInteger_RDR = varQual (pREL_BASE, SLIT("fromInteger"))
minus_RDR = varQual (pREL_BASE, SLIT("-"))
+toEnum_RDR = varQual (pREL_BASE, SLIT("toEnum"))
fromEnum_RDR = varQual (pREL_BASE, SLIT("fromEnum"))
enumFrom_RDR = varQual (pREL_BASE, SLIT("enumFrom"))
enumFromTo_RDR = varQual (pREL_BASE, SLIT("enumFromTo"))
| TakeMVarOp | PutMVarOp
| ReadIVarOp | WriteIVarOp
- | MakeForeignObjOp -- foreign objects (malloc pointers or any old URL)
+ | MakeForeignObjOp -- foreign objects (malloc pointers or any old URL)
+ | WriteForeignObjOp -- modifying foreign objects [obscuro factor: 200]
| MakeStablePtrOp | DeRefStablePtrOp
\end{code}
tagOf_PrimOp ReadIVarOp = ILIT(153)
tagOf_PrimOp WriteIVarOp = ILIT(154)
tagOf_PrimOp MakeForeignObjOp = ILIT(155)
-tagOf_PrimOp MakeStablePtrOp = ILIT(156)
-tagOf_PrimOp DeRefStablePtrOp = ILIT(157)
-tagOf_PrimOp (CCallOp _ _ _ _ _) = ILIT(158)
-tagOf_PrimOp ErrorIOPrimOp = ILIT(159)
-tagOf_PrimOp ReallyUnsafePtrEqualityOp = ILIT(160)
-tagOf_PrimOp SeqOp = ILIT(161)
-tagOf_PrimOp ParOp = ILIT(162)
-tagOf_PrimOp ForkOp = ILIT(163)
-tagOf_PrimOp DelayOp = ILIT(164)
-tagOf_PrimOp WaitReadOp = ILIT(165)
-tagOf_PrimOp WaitWriteOp = ILIT(166)
-
-tagOf_PrimOp ParGlobalOp = ILIT(167)
-tagOf_PrimOp ParLocalOp = ILIT(168)
-tagOf_PrimOp ParAtOp = ILIT(169)
-tagOf_PrimOp ParAtAbsOp = ILIT(170)
-tagOf_PrimOp ParAtRelOp = ILIT(171)
-tagOf_PrimOp ParAtForNowOp = ILIT(172)
-tagOf_PrimOp CopyableOp = ILIT(173)
-tagOf_PrimOp NoFollowOp = ILIT(174)
+tagOf_PrimOp WriteForeignObjOp = ILIT(156)
+tagOf_PrimOp MakeStablePtrOp = ILIT(157)
+tagOf_PrimOp DeRefStablePtrOp = ILIT(158)
+tagOf_PrimOp (CCallOp _ _ _ _ _) = ILIT(159)
+tagOf_PrimOp ErrorIOPrimOp = ILIT(160)
+tagOf_PrimOp ReallyUnsafePtrEqualityOp = ILIT(161)
+tagOf_PrimOp SeqOp = ILIT(162)
+tagOf_PrimOp ParOp = ILIT(163)
+tagOf_PrimOp ForkOp = ILIT(164)
+tagOf_PrimOp DelayOp = ILIT(165)
+tagOf_PrimOp WaitReadOp = ILIT(166)
+tagOf_PrimOp WaitWriteOp = ILIT(167)
+
+tagOf_PrimOp ParGlobalOp = ILIT(168)
+tagOf_PrimOp ParLocalOp = ILIT(169)
+tagOf_PrimOp ParAtOp = ILIT(170)
+tagOf_PrimOp ParAtAbsOp = ILIT(171)
+tagOf_PrimOp ParAtRelOp = ILIT(172)
+tagOf_PrimOp ParAtForNowOp = ILIT(173)
+tagOf_PrimOp CopyableOp = ILIT(174)
+tagOf_PrimOp NoFollowOp = ILIT(175)
tagOf_PrimOp _ = panic# "tagOf_PrimOp: pattern-match"
ReadIVarOp,
WriteIVarOp,
MakeForeignObjOp,
+ WriteForeignObjOp,
MakeStablePtrOp,
DeRefStablePtrOp,
ReallyUnsafePtrEqualityOp,
%************************************************************************
%* *
-\subsubsection[PrimOps-makeForeignObj]{PrimOpInfo for Foreign Objects}
+\subsubsection[PrimOps-ForeignObj]{PrimOpInfo for Foreign Objects}
%* *
%************************************************************************
associated with the object is invoked (currently, each ForeignObj has a
direct reference to its finaliser). -- SOF
-The only function defined over @ForeignObj@s is:
+A @ForeignObj@ is created by the @makeForeignObj#@ primitive:
\begin{pseudocode}
makeForeignObj# :: Addr# -- foreign object
-> StateAndForeignObj# _RealWorld# ForeignObj#
\end{pseudocode}
+
\begin{code}
primOpInfo MakeForeignObjOp
= AlgResult SLIT("makeForeignObj#") []
stateAndForeignObjPrimTyCon [realWorldTy]
\end{code}
+[Experimental--SOF]
+In addition, another @ForeignObj@ primitive is provided for destructively modifying
+the external object wrapped up inside a @ForeignObj@. This primitive is used
+when a mixed programming interface of implicit and explicit de-allocation is used,
+e.g., if @ForeignObj@s are used to implement @Handle@s, then @Handle@s can be
+released either explicitly (through @hClose@) or implicitly (via a finaliser).
+When releasing/closing the @Handle@ explicitly, care must be taken to avoid having
+the finaliser for the embedded @ForeignObj@ attempt the same thing later.
+We deal with this situation, by allowing the programmer to destructively modify
+the data field of the @ForeignObj@ to hold a special value the finaliser recognises,
+and does not attempt to free (e.g., filling the data slot with \tr{NULL}).
+
+\begin{pseudocode}
+writeForeignObj# :: ForeignObj# -- foreign object
+ -> Addr# -- new data value
+ -> StateAndForeignObj# _RealWorld# ForeignObj#
+\end{pseudocode}
+
+\begin{code}
+primOpInfo WriteForeignObjOp
+ = let {
+ s = alphaTy; s_tv = alphaTyVar
+ } in
+ PrimResult SLIT("writeForeignObj#") [s_tv]
+ [foreignObjPrimTy, addrPrimTy, mkStatePrimTy s]
+ statePrimTyCon VoidRep [s]
+\end{code}
+
%************************************************************************
%* *
\subsubsection[PrimOp-stable-pointers]{PrimOpInfo for ``stable pointers''}
primOpHeapReq (CCallOp _ _ mayGC@False _ _) = NoHeapRequired
primOpHeapReq MakeForeignObjOp = VariableHeapRequired
+primOpHeapReq WriteForeignObjOp = NoHeapRequired
-- this occasionally has to expand the Stable Pointer table
primOpHeapReq MakeStablePtrOp = VariableHeapRequired
fragilePrimOp ParOp = True
fragilePrimOp ForkOp = True
fragilePrimOp SeqOp = True
-fragilePrimOp MakeForeignObjOp = True -- SOF
+fragilePrimOp MakeForeignObjOp = True -- SOF
+fragilePrimOp WriteForeignObjOp = True -- SOF
fragilePrimOp MakeStablePtrOp = True
fragilePrimOp DeRefStablePtrOp = True -- ??? JSM & ADR
primOpNeedsWrapper DoubleDecodeOp = True
primOpNeedsWrapper MakeForeignObjOp = True
+primOpNeedsWrapper WriteForeignObjOp = True
primOpNeedsWrapper MakeStablePtrOp = True
primOpNeedsWrapper DeRefStablePtrOp = True
'&'# -> True; '*'# -> True; '+'# -> True; '.'# -> True;
'/'# -> True; '<'# -> True; '='# -> True; '>'# -> True;
'?'# -> True; '\\'# -> True; '^'# -> True; '|'# -> True;
- '-'# -> True; '~'# -> True; _ -> False }
+ '-'# -> True; '~'# -> True; '@'# -> True; _ -> False }
--isAlphanum c || c `elem` ":_'!#$%&*+./<=>?@\\^|-~" -- ToDo: add ISOgraphic
import RdrHsSyn ( SYN_IE(RdrNameHsDecl), SYN_IE(RdrNameInstDecl),
RdrName, rdrNameOcc
)
-import RnEnv ( newGlobalName, lookupRn, addImplicitOccsRn, availName, availNames, addAvailToNameSet )
+import RnEnv ( newGlobalName, lookupRn, addImplicitOccsRn,
+ availName, availNames, addAvailToNameSet, pprAvail
+ )
import RnSource ( rnHsType )
import RnMonad
import ParseIface ( parseIface )
importDecl name necessity
= checkSlurped name `thenRn` \ already_slurped ->
if already_slurped then
+ -- traceRn (ppSep [ppStr "Already slurped:", ppr PprDebug name]) `thenRn_`
returnRn Nothing -- Already dealt with
else
if isWiredInName name then
\begin{code}
getWiredInDecl name
- = -- Force in the home module in case it has instance decls for
- -- the thing we are interested in
- (if not is_tycon || mod == gHC__ then
- returnRn () -- Mini hack 1: no point for non-tycons; and if we
- -- do this we find PrelNum trying to import PackedString,
- -- because PrelBase's .hi file mentions PackedString.unpackString
- -- But PackedString.hi isn't built by that point!
- --
- -- Mini hack 2; GHC is guaranteed not to have
- -- instance decls, so it's a waste of time
- -- to read it
+ = get_wired `thenRn` \ avail ->
+ recordSlurp Nothing avail `thenRn_`
+
+ -- Force in the home module in case it has instance decls for
+ -- the thing we are interested in.
+ --
+ -- Mini hack 1: no point for non-tycons/class; and if we
+ -- do this we find PrelNum trying to import PackedString,
+ -- because PrelBase's .hi file mentions PackedString.unpackString
+ -- But PackedString.hi isn't built by that point!
+ --
+ -- Mini hack 2; GHC is guaranteed not to have
+ -- instance decls, so it's a waste of time to read it
+ --
+ -- NB: We *must* look at the availName of the slurped avail,
+ -- not the name passed to getWiredInDecl! Why? Because if a data constructor
+ -- or class op is passed to getWiredInDecl we'll pull in the whole data/class
+ -- decl, and recordSlurp will record that fact. But since the data constructor
+ -- isn't a tycon/class we won't force in the home module. And even if the
+ -- type constructor/class comes along later, loadDecl will say that it's already
+ -- been slurped, so getWiredInDecl won't even be called. Pretty obscure bug, this was.
+ let
+ main_name = availName avail
+ main_is_tc = case avail of { AvailTC _ _ -> True; Avail _ -> False }
+ (mod,_) = modAndOcc main_name
+ doc_str = ppSep [ppPStr SLIT("Need home module for wired in thing"), ppr PprDebug name]
+ in
+ (if not main_is_tc || mod == gHC__ then
+ returnRn ()
else
loadInterface doc_str mod `thenRn_`
returnRn ()
) `thenRn_`
- get_wired `thenRn` \ avail ->
- recordSlurp Nothing avail `thenRn_`
returnRn Nothing -- No declaration to process further
where
- doc_str = ppSep [ppPStr SLIT("Need home module for wired in thing"), ppr PprDebug name]
- (mod,_) = modAndOcc name
- maybe_wired_in_tycon = maybeWiredInTyConName name
- is_tycon = maybeToBool maybe_wired_in_tycon
- maybe_wired_in_id = maybeWiredInIdName name
- Just the_tycon = maybe_wired_in_tycon
- Just the_id = maybe_wired_in_id
get_wired | is_tycon -- ... a type constructor
= get_wired_tycon the_tycon
- -- Else, must be a wired-in-Id
| (isDataCon the_id) -- ... a wired-in data constructor
= get_wired_tycon (dataConTyCon the_id)
| otherwise -- ... a wired-in non data-constructor
= get_wired_id the_id
+ maybe_wired_in_tycon = maybeWiredInTyConName name
+ is_tycon = maybeToBool maybe_wired_in_tycon
+ maybe_wired_in_id = maybeWiredInIdName name
+ Just the_tycon = maybe_wired_in_tycon
+ Just the_id = maybe_wired_in_id
+
get_wired_id id
= addImplicitOccsRn (nameSetToList id_mentioned) `thenRn_`
returnRn (name `elemNameSet` slurped_names)
recordSlurp maybe_version avail
- = getIfacesRn `thenRn` \ ifaces ->
+ = -- traceRn (ppSep [ppStr "Record slurp:", pprAvail PprDebug avail]) `thenRn_`
+ getIfacesRn `thenRn` \ ifaces ->
let
Ifaces this_mod mod_vers export_envs decls slurped_names imp_names insts inst_mods = ifaces
new_slurped_names = addAvailToNameSet slurped_names avail
| otherwise
= readMutVarSST occs_var `thenSST` \ occs ->
--- pprTrace "Add occurrence:" (ppr PprDebug name) $
writeMutVarSST occs_var ((name,necessity) : occs) `thenSST_`
returnSST name
where
-- expression.
specExpr (Var v) args
- = specId v $ \ lookupId v `thenSM` \ vlookup ->
- case vlookup of
- Lifted vl vu
- -> -- Binding has been lifted, need to extract un-lifted value
- -- NB: a function binding will never be lifted => args always null
- -- i.e. no call instance required or call to be constructed
- ASSERT (null args)
- returnSM (bindUnlift vl vu (Var vu), singleFvUDs (VarArg vl))
-
- NoLift vatom@(VarArg new_v)
- -> mapSM specOutArg args `thenSM` \ arg_info ->
- mkCallInstance v new_v arg_info `thenSM` \ call_uds ->
- mkCall new_v arg_info `thenSM` \ call ->
- let
- call mkGenApp (Var new_id) [arg | (arg, _, _) <- arg_infos])
- uds = unionUDList [call_uds,
- singleFvUDs vatom,
- unionUDList [uds | (_,uds,_) <- arg_info]
- ]
- in
- returnSM (call, {- tickSpecCall speced -} uds)
+ = specId v $ \ v_arg ->
+ case v_arg of
+ LitArg lit -> ASSERT( null args )
+ returnSM (Lit lit, emptyUDs)
+
+ VarArg new_v -> mkCallInstance v new_v args `thenSM` \ uds ->
+ returnSM (mkGenApp (Var new_v) args, uds)
specExpr expr@(Lit _) null_args
= ASSERT (null null_args)
specExpr (App fun arg) args
- = -- If TyArg, arg will be processed; otherwise, left alone
- specArg arg `thenSM` \ new_arg ->
- specExpr fun (new_arg : args) `thenSM` \ (expr,uds) ->
+ = specArg arg `thenSM` \ new_arg ->
+ specExpr fun (new_arg : args) `thenSM` \ (expr,uds) ->
returnSM (expr, uds)
specExpr (Lam (ValBinder binder) body) (arg : args) | isValArg arg
----------
specId :: Id
- -> (Id -> SpecM (CoreExpr, UsageDetails))
+ -> (CoreArg -> SpecM (CoreExpr, UsageDetails))
-> SpecM (CoreExpr, UsageDetails)
specId v
= lookupId v `thenSM` \ vlookup ->
case vlookup of
Lifted vl vu
- -> thing_inside vu `thenSM` \ (expr, uds) ->
+ -> thing_inside (VarArg vu) `thenSM` \ (expr, uds) ->
returnSM (bindUnlift vl vu expr, singleFvUDs (VarArg vl) `unionUDs` uds)
NoLift vatom
- -> thing_inside vatom `thenSM` \ (expr, uds) ->
+ -> thing_inside vatom `thenSM` \ (expr, uds) ->
returnSM (expr, singleFvUDs vatom `unionUDs` uds)
specArg :: CoreArg
newTyVars (length [() | Nothing <- spec_tys]) `thenSM` \ poly_tyvars ->
let
-- arg_tys is spec_tys with tyvars instead of the Nothing spec_tys
- -- which correspond to unspeciailsed args
+ -- which correspond to unspecialised args
arg_tys :: [Type]
(_,arg_tys) = mapAccumL do_the_wotsit poly_tyvars spec_tys
-> [CoreArg]
-> SpecM UsageDetails
-mkCallInstance id new_id []
- = returnSM emptyUDs
-
mkCallInstance id new_id args
-
- -- No specialised versions for "error" and friends are req'd.
- -- This is a special case in core lint etc.
-
- | isBottomingId id
+ | null args || -- No args at all
+ isBottomingId id || -- No point in specialising "error" and friends
+ -- even at unboxed types
+ idWantsToBeINLINEd id || -- It's going to be inlined anyway
+ not enough_args || -- Not enough type and dict args
+ not interesting_overloading -- Overloaded types are just tyvars
= returnSM emptyUDs
- -- No call instances for SuperDictSelIds
- -- These are a special case in mkCall
-
- | maybeToBool (isSuperDictSelId_maybe id)
- = returnSM emptyUDs
-
- -- There are also no call instances for ClassOpIds
- -- However, we need to process it to get any second-level call
- -- instances for a ConstMethodId extracted from its SpecEnv
-
| otherwise
- = let
- (tyvars, class_tyvar_pairs) = getIdOverloading id
- constrained_tyvars = map snd class_tyvar_pairs -- May contain dups
- constraint_vec = [tyvar `elem` constrained_tyvars | tyvar <- tyvars]
+ = returnSM (singleCI new_id spec_tys dicts)
- arg_res = take_type_args tyvars class_tyvar_pairs args
- enough_args = maybeToBool arg_res
-
-
- (Just (tys, dicts, rest_args)) = arg_res
-
- record_spec id tys
- = (record, lookup, spec_tys)
- where
- spec_tys = specialiseCallTys constraint_vec tys
-
- record = any (not . isTyVarTy) (catMaybes spec_tys)
-
- lookup = lookupSpecEnv (getIdSpecialisation id) tys
- in
- if (not enough_args) then
- pprTrace "Specialise:recordCallInst: Unsaturated Type & Dict Application:\n\t"
- (ppCat (ppr PprDebug id : map (ppr_arg PprDebug) args)) $
- returnSM emptyUDs
-
- else
- case record_spec id tys of
- (False, _, _)
- -> -- pprTrace "CallInst:NotReqd\n"
- -- (ppCat [ppr PprDebug id, ppCat (map (ppr PprDebug) args)])
- (returnSM emptyUDs)
-
- (True, Nothing, spec_tys)
- -> if isClassOpId id then -- No CIs for class ops, dfun will give SPEC inst
- returnSM emptyUDs
- else
- -- pprTrace "CallInst:Reqd\n"
- -- (ppAboves [ppCat [ppr PprDebug id, ppCat (map (ppr PprDebug) args)],
- -- ppCat [ppPStr SLIT("CI"), ppCat (map (pprMaybeTy PprDebug) spec_tys),
- -- ppCat (map (ppr PprDebug) dicts)]])
- (returnSM (singleCI new_id spec_tys dicts))
-
- (True, Just (spec_id, tys_left, toss), _)
- -> if maybeToBool (isConstMethodId_maybe spec_id) then
- -- If we got a const method spec_id see if further spec required
- -- NB: const method is top-level so spec_id will not be cloned
- case record_spec spec_id tys_left of
- (False, _, _)
- -> -- pprTrace "CallInst:Exists\n"
- -- (ppAboves [ppCat [ppr PprDebug id, ppCat (map (ppr PprDebug) args)],
- -- ppCat [ppPStr SLIT("->"), ppr PprDebug spec_id,
- -- ppr PprDebug (tys_left ++ drop toss dicts)]])
- (returnSM emptyUDs)
-
- (True, Nothing, spec_tys)
- -> -- pprTrace "CallInst:Exists:Reqd\n"
- -- (ppAboves [ppCat [ppr PprDebug id, ppCat (map (ppr PprDebug) args)],
- -- ppCat [ppPStr SLIT("->"), ppr PprDebug spec_id,
- -- ppr PprDebug (tys_left ++ drop toss dicts)],
- -- ppCat [ppPStr SLIT("CI"), ppCat (map (pprMaybeTy PprDebug) spec_tys),
- -- ppCat (map (ppr PprDebug) (drop toss dicts))]])
- (returnSM (singleCI spec_id spec_tys (drop toss dicts)))
-
- (True, Just (spec_spec_id, tys_left_left, toss_toss), _)
- -> -- pprTrace "CallInst:Exists:Exists\n"
- -- (ppAboves [ppCat [ppr PprDebug id, ppCat (map (ppr PprDebug) args)],
- -- ppCat [ppPStr SLIT("->"), ppr PprDebug spec_id,
- -- ppr PprDebug (tys_left ++ drop toss dicts)],
- -- ppCat [ppPStr SLIT("->"), ppr PprDebug spec_spec_id,
- -- ppr PprDebug (tys_left_left ++ drop (toss + toss_toss) dicts)]])
- (returnSM emptyUDs)
-
- else
- -- pprTrace "CallInst:Exists\n"
- -- (ppAboves [ppCat [ppr PprDebug id, ppCat (map (ppr PprDebug) args)],
- -- ppCat [ppPStr SLIT("->"), ppr PprDebug spec_id,
- -- ppr PprDebug (tys_left ++ drop toss dicts)]])
- (returnSM emptyUDs)
-
-
-take_type_args (_:tyvars) class_tyvar_pairs (TyArg ty : args)
- = case (take_type_args tyvars class_tyvar_pairs args) of
- Nothing -> Nothing
+ where
+ (tyvars, class_tyvar_pairs) = getIdOverloading id
+ constrained_tyvars = map snd class_tyvar_pairs -- May contain dups
+ constraint_vec = [tyvar `elem` constrained_tyvars | tyvar <- tyvars]
+
+ arg_res = take_type_args tyvars class_tyvar_pairs args
+ enough_args = maybeToBool arg_res
+ (Just (tys, dicts, rest_args)) = arg_res
+
+ interesting_overloading = any (not . isTyVarTy) (catMaybes spec_tys)
+ spec_tys = specialiseCallTys constraint_vec tys
+
+ ----------------- Rather a gruesome help-function ---------------
+ take_type_args (_:tyvars) (TyArg ty : args)
+ = case (take_type_args tyvars args) of
+ Nothing -> Nothing
Just (tys, dicts, others) -> Just (ty:tys, dicts, others)
-take_type_args (_:tyvars) class_tyvar_pairs [] = Nothing
+ take_type_args (_:tyvars) [] = Nothing
-take_type_args [] class_tyvar_pairs args
+ take_type_args [] args
= case (take_dict_args class_tyvar_pairs args) of
Nothing -> Nothing
Just (dicts, others) -> Just ([], dicts, others)
-take_dict_args (_:class_tyvar_pairs) (dict : args) | isValArg dict
+ take_dict_args (_:class_tyvar_pairs) (dict : args) | isValArg dict
= case (take_dict_args class_tyvar_pairs args) of
Nothing -> Nothing
Just (dicts, others) -> Just (dict:dicts, others)
-take_dict_args (_:class_tyvar_pairs) [] = Nothing
+ take_dict_args (_:class_tyvar_pairs) args = Nothing
-take_dict_args [] args = Just ([], args)
+ take_dict_args [] args = Just ([], args)
\end{code}
-\begin{code}
-mkCall :: Id
- -> [(CoreArg, UsageDetails, CoreExpr -> CoreExpr)]
- -> SpecM CoreExpr
-
-mkCall new_id arg_infos = returnSM (
-
-{-
- | maybeToBool (isSuperDictSelId_maybe new_id)
- && any isUnboxedType ty_args
- -- No specialisations for super-dict selectors
- -- Specialise unboxed calls to SuperDictSelIds by extracting
- -- the super class dictionary directly form the super class
- -- NB: This should be dead code since all uses of this dictionary should
- -- have been specialised. We only do this to keep core-lint happy.
- = let
- Just (_, super_class) = isSuperDictSelId_maybe new_id
- super_dict_id = case lookupClassInstAtSimpleType super_class (head ty_args) of
- Nothing -> panic "Specialise:mkCall:SuperDictId"
- Just id -> id
- in
- returnSM (False, Var super_dict_id)
-
- | otherwise
- = case lookupSpecEnv (getIdSpecialisation new_id) ty_args of
- Nothing -> checkUnspecOK new_id ty_args (
- returnSM (False, unspec_call)
- )
-
- Just spec_1_details@(spec_id_1, tys_left_1, dicts_to_toss_1)
- -> let
- -- It may be necessary to specialsie a constant method spec_id again
- (spec_id, tys_left, dicts_to_toss) =
- case (maybeToBool (isConstMethodId_maybe spec_id_1),
- lookupSpecEnv (getIdSpecialisation spec_id_1) tys_left_1) of
- (False, _ ) -> spec_1_details
- (True, Nothing) -> spec_1_details
- (True, Just (spec_id_2, tys_left_2, dicts_to_toss_2))
- -> (spec_id_2, tys_left_2, dicts_to_toss_1 + dicts_to_toss_2)
-
- args_left = toss_dicts dicts_to_toss val_args
- in
- checkSpecOK new_id ty_args spec_id tys_left (
-
- -- The resulting spec_id may be a top-level unboxed value
- -- This can arise for:
- -- 1) constant method values
- -- eq: class Num a where pi :: a
- -- instance Num Double# where pi = 3.141#
- -- 2) specilised overloaded values
- -- eq: i1 :: Num a => a
- -- i1 Int# d.Num.Int# ==> i1.Int#
- -- These top level defns should have been lifted.
- -- We must add code to unlift such a spec_id.
-
- if isUnboxedType (idType spec_id) then
- ASSERT (null tys_left && null args_left)
- if toplevelishId spec_id then
- liftId spec_id `thenSM` \ (lift_spec_id, unlift_spec_id) ->
- returnSM (True, bindUnlift lift_spec_id unlift_spec_id
- (Var unlift_spec_id))
- else
- pprPanic "Specialise:mkCall: unboxed spec_id not top-level ...\n"
- (ppCat [ppr PprDebug new_id,
- ppInterleave ppNil (map (pprParendGenType PprDebug) ty_args),
- ppPStr SLIT("==>"),
- ppr PprDebug spec_id])
- else
- let
- (vals_left, _, unlifts_left) = unzip3 args_left
- applied_tys = mkTyApp (Var spec_id) tys_left
- applied_vals = mkGenApp applied_tys vals_left
- in
- returnSM (True, applyBindUnlifts unlifts_left applied_vals)
- )
- where
- (tys_and_vals, _, unlifts) = unzip3 args
- unspec_call = applyBindUnlifts unlifts (mkGenApp (Var new_id) tys_and_vals)
-
-
- -- ty_args is the types at the front of the arg list
- -- val_args is the rest of the arg-list
-
- (ty_args, val_args) = get args
- where
- get ((TyArg ty,_,_) : args) = (ty : tys, rest) where (tys,rest) = get args
- get args = ([], args)
-
-
- -- toss_dicts chucks away dict args, checking that they ain't types!
- toss_dicts 0 args = args
- toss_dicts n ((a,_,_) : args)
- | isValArg a = toss_dicts (n-1) args
-
-\end{code}
-
-\begin{code}
-checkUnspecOK :: Id -> [Type] -> a -> a
-checkUnspecOK check_id tys
- = if isLocallyDefined check_id && any isUnboxedType tys
- then pprPanic "Specialise:checkUnspecOK: unboxed instance for local id not found\n"
- (ppCat [ppr PprDebug check_id,
- ppInterleave ppNil (map (pprParendGenType PprDebug) tys)])
- else id
-
-checkSpecOK :: Id -> [Type] -> Id -> [Type] -> a -> a
-checkSpecOK check_id tys spec_id tys_left
- = if any isUnboxedType tys_left
- then pprPanic "Specialise:checkSpecOK: unboxed type args in specialised application\n"
- (ppAboves [ppCat [ppr PprDebug check_id,
- ppInterleave ppNil (map (pprParendGenType PprDebug) tys)],
- ppCat [ppr PprDebug spec_id,
- ppInterleave ppNil (map (pprParendGenType PprDebug) tys_left)]])
- else id
--}
-\end{code}
\begin{code}
mkTyConInstance :: Id
-> UniqSupply
-> result
-initSM m uniqs
- = m nullTyVarEnv nullIdEnv uniqs
+initSM m uniqs = m nullTyVarEnv nullIdEnv uniqs
returnSM :: a -> SpecM a
thenSM :: SpecM a -> (a -> SpecM b) -> SpecM b
newSpecIds new_ids maybe_tys dicts_to_ignore tvenv idenv us
= [ mkSpecId uniq id maybe_tys (spec_id_ty id) (selectIdInfoForSpecId id)
- | (id,uniq) <- zipEqual "newSpecIds" new_ids uniqs ]
+ | (id,uniq) <- zipEqual "newSpecIds" new_ids uniqs ]
where
uniqs = getUniques (length new_ids) us
spec_id_ty id = specialiseTy (idType id) maybe_tys dicts_to_ignore
returnSM ((r1:rs1),(r2:rs2),(r3:rs3),(r4:rs4))
-}
\end{code}
+
+
+
+===================== OLD CODE, scheduled for deletion =================
+
+\begin{code}
+{-
+mkCall :: Id
+ -> [(CoreArg, UsageDetails, CoreExpr -> CoreExpr)]
+ -> SpecM CoreExpr
+
+mkCall new_id arg_infos = returnSM (
+
+ | maybeToBool (isSuperDictSelId_maybe new_id)
+ && any isUnboxedType ty_args
+ -- No specialisations for super-dict selectors
+ -- Specialise unboxed calls to SuperDictSelIds by extracting
+ -- the super class dictionary directly form the super class
+ -- NB: This should be dead code since all uses of this dictionary should
+ -- have been specialised. We only do this to keep core-lint happy.
+ = let
+ Just (_, super_class) = isSuperDictSelId_maybe new_id
+ super_dict_id = case lookupClassInstAtSimpleType super_class (head ty_args) of
+ Nothing -> panic "Specialise:mkCall:SuperDictId"
+ Just id -> id
+ in
+ returnSM (False, Var super_dict_id)
+
+ | otherwise
+ = case lookupSpecEnv (getIdSpecialisation new_id) ty_args of
+ Nothing -> checkUnspecOK new_id ty_args (
+ returnSM (False, unspec_call)
+ )
+
+ Just spec_1_details@(spec_id_1, tys_left_1, dicts_to_toss_1)
+ -> let
+ -- It may be necessary to specialsie a constant method spec_id again
+ (spec_id, tys_left, dicts_to_toss) =
+ case (maybeToBool (isConstMethodId_maybe spec_id_1),
+ lookupSpecEnv (getIdSpecialisation spec_id_1) tys_left_1) of
+ (False, _ ) -> spec_1_details
+ (True, Nothing) -> spec_1_details
+ (True, Just (spec_id_2, tys_left_2, dicts_to_toss_2))
+ -> (spec_id_2, tys_left_2, dicts_to_toss_1 + dicts_to_toss_2)
+
+ args_left = toss_dicts dicts_to_toss val_args
+ in
+ checkSpecOK new_id ty_args spec_id tys_left (
+
+ -- The resulting spec_id may be a top-level unboxed value
+ -- This can arise for:
+ -- 1) constant method values
+ -- eq: class Num a where pi :: a
+ -- instance Num Double# where pi = 3.141#
+ -- 2) specilised overloaded values
+ -- eq: i1 :: Num a => a
+ -- i1 Int# d.Num.Int# ==> i1.Int#
+ -- These top level defns should have been lifted.
+ -- We must add code to unlift such a spec_id.
+
+ if isUnboxedType (idType spec_id) then
+ ASSERT (null tys_left && null args_left)
+ if toplevelishId spec_id then
+ liftId spec_id `thenSM` \ (lift_spec_id, unlift_spec_id) ->
+ returnSM (True, bindUnlift lift_spec_id unlift_spec_id
+ (Var unlift_spec_id))
+ else
+ pprPanic "Specialise:mkCall: unboxed spec_id not top-level ...\n"
+ (ppCat [ppr PprDebug new_id,
+ ppInterleave ppNil (map (pprParendGenType PprDebug) ty_args),
+ ppPStr SLIT("==>"),
+ ppr PprDebug spec_id])
+ else
+ let
+ (vals_left, _, unlifts_left) = unzip3 args_left
+ applied_tys = mkTyApp (Var spec_id) tys_left
+ applied_vals = mkGenApp applied_tys vals_left
+ in
+ returnSM (True, applyBindUnlifts unlifts_left applied_vals)
+ )
+ where
+ (tys_and_vals, _, unlifts) = unzip3 args
+ unspec_call = applyBindUnlifts unlifts (mkGenApp (Var new_id) tys_and_vals)
+
+
+ -- ty_args is the types at the front of the arg list
+ -- val_args is the rest of the arg-list
+
+ (ty_args, val_args) = get args
+ where
+ get ((TyArg ty,_,_) : args) = (ty : tys, rest) where (tys,rest) = get args
+ get args = ([], args)
+
+
+ -- toss_dicts chucks away dict args, checking that they ain't types!
+ toss_dicts 0 args = args
+ toss_dicts n ((a,_,_) : args)
+ | isValArg a = toss_dicts (n-1) args
+
+\end{code}
+
+\begin{code}
+checkUnspecOK :: Id -> [Type] -> a -> a
+checkUnspecOK check_id tys
+ = if isLocallyDefined check_id && any isUnboxedType tys
+ then pprPanic "Specialise:checkUnspecOK: unboxed instance for local id not found\n"
+ (ppCat [ppr PprDebug check_id,
+ ppInterleave ppNil (map (pprParendGenType PprDebug) tys)])
+ else id
+
+checkSpecOK :: Id -> [Type] -> Id -> [Type] -> a -> a
+checkSpecOK check_id tys spec_id tys_left
+ = if any isUnboxedType tys_left
+ then pprPanic "Specialise:checkSpecOK: unboxed type args in specialised application\n"
+ (ppAboves [ppCat [ppr PprDebug check_id,
+ ppInterleave ppNil (map (pprParendGenType PprDebug) tys)],
+ ppCat [ppr PprDebug spec_id,
+ ppInterleave ppNil (map (pprParendGenType PprDebug) tys_left)]])
+ else id
+-}
+\end{code}
\begin{verbatim}
instance ... Enum (Foo ...) where
+ toEnum i = tag2con_Foo i
+
enumFrom a = map tag2con_Foo [con2tag_Foo a .. maxtag_Foo]
-- or, really...
gen_Enum_binds :: TyCon -> RdrNameMonoBinds
gen_Enum_binds tycon
- = enum_from `AndMonoBinds`
+ = to_enum `AndMonoBinds`
+ enum_from `AndMonoBinds`
enum_from_then `AndMonoBinds`
from_enum
where
tycon_loc = getSrcLoc tycon
+
+ to_enum
+ = mk_easy_FunMonoBind tycon_loc toEnum_RDR [a_Pat] [] $
+ mk_easy_App (tag2con_RDR tycon) [a_RDR]
+
enum_from
= mk_easy_FunMonoBind tycon_loc enumFrom_RDR [a_Pat] [] $
untag_Expr tycon [(a_RDR, ah_RDR)] $
concatFS ls = mkFastString (concat (map (unpackFS) ls)) -- ToDo: do better
headFS :: FastString -> Char
-headFS (FastString _ l# ba#) =
- if l# ># 0# then C# (indexCharArray# ba# 0#) else error "headFS: empty FS"
-headFS (CharStr a# l#) =
- if l# ># 0# then C# (indexCharOffAddr# a# 0#) else error "headFS: empty FS"
+headFS f@(FastString _ l# ba#) =
+ if l# ># 0# then C# (indexCharArray# ba# 0#) else error ("headFS: empty FS: " ++ unpackFS f)
+headFS f@(CharStr a# l#) =
+ if l# ># 0# then C# (indexCharOffAddr# a# 0#) else error ("headFS: empty FS: " ++ unpackFS f)
tailFS :: FastString -> FastString
tailFS (FastString _ l# ba#) = mkFastSubStringBA# ba# 1# (l# -# 1#)
#
export WAYS=
-SUBDIRS = users_guide install_guide release_notes state_interface
+SUBDIRS = users_guide
include $(TOP)/mk/target.mk
# multi-line regexp matching:
local($*) = 1;
local($i, $c);
+
+
&init_TARGET_STUFF();
&init_FUNNY_THINGS();
+ # perl4 on alphas SEGVs when give ${foo} substitutions in patterns.
+ # To avoid them we declare some locals that allows to avoid using curlies.
+ local($TUS) = ${T_US};
+ local($TPOSTLBL) = ${T_POST_LBL};
+ local($TMOVEDIRVS) = ${T_MOVE_DIRVS};
+ local($TPREAPP) = ${T_PRE_APP};
+ local($TCOPYDIRVS) = ${T_COPY_DIRVS};
+ local($TDOTWORD) = ${T_DOT_WORD};
+
open(INASM, "< $in_asmf")
|| &tidy_up_and_die(1,"$Pgm: failed to open `$in_asmf' (to read)\n");
open(OUTASM,"> $out_asmf")
$i = 0; $chkcat[0] = 'misc'; $chk[0] = '';
while (<INASM>) {
- next if $T_STABBY && /^\.stab.*${T_US}__stg_split_marker/o;
+ next if $T_STABBY && /^\.stab.*$TUS[@]?__stg_split_marker/o;
next if $T_STABBY && /^\.stab.*ghc.*c_ID/;
- next if /${T_PRE_APP}(NO_)?APP/o;
-
+ next if /$TPREAPP(NO_)?APP/o;
next if /^;/ && $TargetPlatform =~ /^hppa/;
next if /(^$|^\t\.file\t|^ # )/ && $TargetPlatform =~ /^(mips|powerpc)-/;
$chkcat[$i] = 'literal';
$chksymb[$i] = $1;
- } elsif ( /^${T_US}__stg_split_marker(\d+)${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?__stg_split_marker(\d+)$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'splitmarker';
$chksymb[$i] = $1;
- } elsif ( /^${T_US}([A-Za-z0-9_]+)_info${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?([A-Za-z0-9_]+)_info$TPOSTLBL[@]?$/o ) {
$symb = $1;
$chk[++$i] = $_;
$chkcat[$i] = 'infotbl';
$infochk{$symb} = $i;
- } elsif ( /^${T_US}([A-Za-z0-9_]+)_entry${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?([A-Za-z0-9_]+)_entry$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'slow';
$chksymb[$i] = $1;
$slowchk{$1} = $i;
- } elsif ( /^${T_US}([A-Za-z0-9_]+)_fast\d+${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?([A-Za-z0-9_]+)_fast\d+$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'fast';
$chksymb[$i] = $1;
$fastchk{$1} = $i;
- } elsif ( /^${T_US}([A-Za-z0-9_]+)_closure${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?([A-Za-z0-9_]+)_closure$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'closure';
$chksymb[$i] = $1;
$closurechk{$1} = $i;
- } elsif ( /^${T_US}ghc.*c_ID${T_POST_LBL}/o ) {
+ } elsif ( /^$TUS[@]?ghc.*c_ID$TPOSTLBL/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'consist';
- } elsif ( /^(${T_US}__gnu_compiled_c|gcc2_compiled\.)${T_POST_LBL}/o ) {
+ } elsif ( /^($TUS[@]?__gnu_compiled_c|gcc2_compiled\.)$TPOSTLBL/o ) {
; # toss it
- } elsif ( /^${T_US}ErrorIO_call_count${T_POST_LBL}$/o # HACK!!!!
- || /^${T_US}[A-Za-z0-9_]+\.\d+${T_POST_LBL}$/o
- || /^${T_US}.*_CAT${T_POST_LBL}$/o # PROF: _entryname_CAT
- || /^${T_US}CC_.*_struct${T_POST_LBL}$/o # PROF: _CC_ccident_struct
- || /^${T_US}.*_done${T_POST_LBL}$/o # PROF: _module_done
- || /^${T_US}_module_registered${T_POST_LBL}$/o # PROF: _module_registered
+ } elsif ( /^$TUS[@]?ErrorIO_call_count$TPOSTLBL[@]?$/o # HACK!!!!
+ || /^$TUS[A-Za-z0-9_]+\.\d+$TPOSTLBL[@]?$/o
+ || /^$TUS[@]?.*_CAT$TPOSTLBL[@]?$/o # PROF: _entryname_CAT
+ || /^$TUS[@]?CC_.*_struct$TPOSTLBL[@]?$/o # PROF: _CC_ccident_struct
+ || /^$TUS[@]?.*_done$TPOSTLBL[@]?$/o # PROF: _module_done
+ || /^$TUS[@]?_module_registered$TPOSTLBL[@]?$/o # PROF: _module_registered
) {
$chk[++$i] = $_;
$chkcat[$i] = 'data';
$chkcat[$i] = 'bss';
$chksymb[$i] = $1;
- } elsif ( /^${T_US}(ret_|djn_)/o ) {
+ } elsif ( /^$TUS[@]?(ret_|djn_)/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'misc';
$chksymb[$i] = '';
- } elsif ( /^${T_US}vtbl_([A-Za-z0-9_]+)${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?vtbl_([A-Za-z0-9_]+)$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'vector';
$chksymb[$i] = $1;
$vectorchk{$1} = $i;
- } elsif ( /^${T_US}([A-Za-z0-9_]+)DirectReturn${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?([A-Za-z0-9_]+)DirectReturn$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'direct';
$chksymb[$i] = $1;
$directchk{$1} = $i;
- } elsif ( /^${T_US}[A-Za-z0-9_]+_upd${T_POST_LBL}$/o ) {
+ } elsif ( /^$TUS[@]?[A-Za-z0-9_]+_upd$TPOSTLBL[@]?$/o ) {
$chk[++$i] = $_;
$chkcat[$i] = 'misc';
$chksymb[$i] = '';
$chkcat[$i] = 'toss';
$chksymb[$i] = $1;
- } elsif ( /^${T_US}[A-Za-z0-9_]/o
+ } elsif ( /^$TUS[@]?[A-Za-z0-9_]/o
&& ( $TargetPlatform !~ /^hppa/ # need to avoid local labels in this case
|| ! /^L\$\d+$/ )
&& ( $TargetPlatform !~ /^powerpc/ # ditto
chop($thing = $_);
print STDERR "Funny global thing?: $_"
unless $KNOWN_FUNNY_THING{$thing}
- || /^${T_US}_(PRIn|PRStart).*${T_POST_LBL}$/o # pointer reversal GC routines
- || /^${T_US}CC_.*${T_POST_LBL}$/o # PROF: _CC_ccident
- || /^${T_US}_reg.*${T_POST_LBL}$/o; # PROF: __reg<module>
+ || /^$TUS[@]?_(PRIn|PRStart).*$TPOSTLBL[@]?$/o # pointer reversal GC routines
+ || /^$TUS[@]?CC_.*$TPOSTLBL$/o # PROF: _CC_ccident ([@]? is a silly hack (see above))
+ || /^$TUS[@]?_reg.*$TPOSTLBL$/o; # PROF: __reg<module>
$chk[++$i] = $_;
$chkcat[$i] = 'misc';
$chksymb[$i] = '';
# On Alphas, the prologue mangling is done a little later (below)
# toss all calls to __DISCARD__
- $c =~ s/^\t(call|jbsr|jal)\s+${T_US}__DISCARD__\n//go;
+ $c =~ s/^\t(call|jbsr|jal)\s+$TUS[@]?__DISCARD__\n//go;
# MIPS: that may leave some gratuitous asm macros around
# (no harm done; but we get rid of them to be tidier)
# pin a funny end-thing on (for easier matching):
$c .= 'FUNNY#END#THING';
- while ( $c =~ /${T_MOVE_DIRVS}FUNNY#END#THING/o ) {
+ while ( $c =~ /$TMOVEDIRVS[@]?FUNNY#END#THING/o ) { # [@]? is a silly hack to avoid having to use curlies for T_PRE_APP
+ # (this SEGVs perl4 on alphas, you see)
+
$to_move = $1;
if ( $i < ($numchks - 1)
- && ( $to_move =~ /${T_COPY_DIRVS}/
+ && ( $to_move =~ /$TCOPYDIRVS/
|| ($TargetPlatform =~ /^hppa/ && $to_move =~ /align/ && $chkcat[$i+1] eq 'literal') )) {
$chk[$i + 1] = $to_move . $chk[$i + 1];
# otherwise they're tossed
}
- $c =~ s/${T_MOVE_DIRVS}FUNNY#END#THING/FUNNY#END#THING/o;
+ $c =~ s/$TMOVEDIRVS[@]?FUNNY#END#THING/FUNNY#END#THING/o; # [@]? is a hack (see above)
}
if ( $TargetPlatform =~ /^alpha-/ && $c =~ /^\t\.ent\s+(\S+)/ ) {
# entry code will be put here!
# paranoia
- if ( $chk[$infochk{$symb}] =~ /${T_DOT_WORD}\s+([A-Za-z0-9_]+_entry)$/o
+ if ( $chk[$infochk{$symb}] =~ /$TDOTWORD[@]?\s+([A-Za-z0-9_]+_entry)$/o
&& $1 ne "${T_US}${symb}_entry" ) {
print STDERR "!!! entry point???\n",$chk[$infochk{$symb}];
}
# references to fast-entry point.
# (questionable re hppa and mips...)
print STDERR "still has jump to fast entry point:\n$c"
- if $c =~ /${T_US}${symb}_fast/; # NB: paranoia
+ if $c =~ /$TUS[@]?$symb[@]?_fast/; # NB: paranoia
}
print OUTASM $T_HDR_entry;
local($after) = '';
local(@lines) = split(/\n/, $tbl);
local($i, $extra, $words_to_pad, $j);
-
- for ($i = 0; $i <= $#lines && $lines[$i] !~ /^\t${T_DOT_WORD}\s+/o; $i++) {
+
+ # see comment in mangleAsm as to why this silliness is needed.
+ local($TDOTWORD) = ${T_DOT_WORD};
+ local($TDOTGLOBAL) = ${T_DOT_GLOBAL};
+ local($TUS) = ${T_US};
+ local($TPOSTLBL) = ${T_POST_LBL};
+
+ for ($i = 0; $i <= $#lines && $lines[$i] !~ /^\t$TDOTWORD\s+/o; $i++) {
$label .= $lines[$i] . "\n",
- next if $lines[$i] =~ /^[A-Za-z0-9_]+_info${T_POST_LBL}$/o
- || $lines[$i] =~ /${T_DOT_GLOBAL}/o
- || $lines[$i] =~ /^${T_US}vtbl_\S+${T_POST_LBL}$/o;
+ next if $lines[$i] =~ /^[A-Za-z0-9_]+_info$TPOSTLBL[@]?$/o
+ || $lines[$i] =~ /$TDOTGLOBAL/o
+ || $lines[$i] =~ /^$TUS[@]?vtbl_\S+$TPOSTLBL[@]?$/o;
$before .= $lines[$i] . "\n"; # otherwise...
}
if ( $TargetPlatform !~ /^hppa/ ) {
- for ( ; $i <= $#lines && $lines[$i] =~ /^\t${T_DOT_WORD}\s+/o; $i++) {
+ for ( ; $i <= $#lines && $lines[$i] =~ /^\t$TDOTWORD\s+/o; $i++) {
push(@words, $lines[$i]);
}
} else { # hppa weirdness
&init_TARGET_STUFF();
+ # see mangleAsm comment
+ local($TUS) = ${T_US};
+ local($TPOSTLBL)=${T_POST_LBL};
+
open(INASM, "< $in_asmf")
|| &tidy_up_and_die(1,"$Pgm: failed to open `$in_asmf' (to read)\n");
open(OUTASM,"> $out_asmf")
print OUTASM;
next unless
- /^${T_US}(PerformGC|StackOverflow|Yield|PerformReschedule)_wrapper${T_POST_LBL}\n/o;
+ /^$TUS[@]?(PerformGC|StackOverflow|Yield|PerformReschedule)_wrapper$TPOSTLBL\n/o;
print OUTASM "\tmovl \%esp, ${T_US}__temp_esp\n";
print OUTASM "\tmovl \%eax, ${T_US}__temp_eax\n";
}
StorageMgrInfo.ForeignObjList = result; \
\
\
-/*fprintf(stderr,"DEBUG: ForeignObj(0x%x) = <0x%x, 0x%x, 0x%x, 0x%x>\n", \
+ /*fprintf(stderr,"DEBUG: ForeignObj(0x%x) = <0x%x, 0x%x, 0x%x, 0x%x>\n", \
result, \
result[0],result[1], \
result[2],result[3]);*/ \
(r) = (P_) result; \
} while (0)
+#define writeForeignObjZh(res,datum) ((PP_) ForeignObj_CLOSURE_DATA(res)) = ((P_)datum)
+
#else
#define makeForeignObjZh(r, liveness, mptr, finalise) \
do { \
EXIT(EXIT_FAILURE); \
} while(0)
+#define writeForeignObjZh(res,datum) \
+do { \
+ fflush(stdout); \
+ fprintf(stderr, "writeForeignObj#: no foreign object support.\n");\
+ EXIT(EXIT_FAILURE); \
+} while(0)
+
#endif /* !PAR */
\end{code}
#
# Makefile for building the GHC Prelude libraries umpteen ways
#
-# $Id: Makefile,v 1.5 1997/03/14 05:30:36 sof Exp $
+# $Id: Makefile,v 1.6 1997/03/17 20:34:49 simonpj Exp $
#
#
#################################################################################
# per-module flags
-ghc/PackedString_HC_OPTS = -monly-3-regs
-required/Directory_HC_OPTS = -monly-3-regs
-concurrent/Parallel_HC_OPTS = -fglasgow-exts
+ghc/PackedString_HC_OPTS += -monly-3-regs
+required/Directory_HC_OPTS += -monly-3-regs
+concurrent/Parallel_HC_OPTS += -fglasgow-exts
+required/Time_HC_OPTS += -monly-3-regs
#-----------------------------------------------------------------------------
# Dependency generation
-SRC_MKDEPENDHS_OPTS += -irequired:ghc:hbc:glaExts:concurrent
+SRC_MKDEPENDHS_OPTS += -irequired:ghc:hbc:glaExts:concurrent -I$(GHC_INCLUDE_DIR)
#-----------------------------------------------------------------------------
# Rules
/* getClockTime.lc */
StgInt getClockTime PROTO((StgByteArray, StgByteArray));
+StgAddr showTime PROTO((I_, StgByteArray, StgByteArray));
+StgAddr toClockSec PROTO((I_, I_, I_, I_, I_, I_, I_, StgByteArray));
+StgAddr toLocalTime PROTO((I_, StgByteArray, StgByteArray));
+StgAddr toUTCTime PROTO((I_, StgByteArray, StgByteArray));
/* getCPUTime.lc */
StgByteArray getCPUTime PROTO((StgByteArray));
ForeignObj#
makeForeignObj#
+ writeForeignObj#
StablePtr#
makeStablePtr#
data Handle__
= ErrorHandle IOError
| ClosedHandle
+#ifndef PAR
| SemiClosedHandle ForeignObj (Addr, Int)
| ReadHandle ForeignObj (Maybe BufferMode) Bool
| WriteHandle ForeignObj (Maybe BufferMode) Bool
| AppendHandle ForeignObj (Maybe BufferMode) Bool
| ReadWriteHandle ForeignObj (Maybe BufferMode) Bool
+#else
+ | SemiClosedHandle Addr (Addr, Int)
+ | ReadHandle Addr (Maybe BufferMode) Bool
+ | WriteHandle Addr (Maybe BufferMode) Bool
+ | AppendHandle Addr (Maybe BufferMode) Bool
+ | ReadWriteHandle Addr (Maybe BufferMode) Bool
+#endif
-- Standard Instances as defined by the Report..
import PrelTup
import PrelBase
import GHC
-import Foreign ( makeForeignObj )
+import Foreign ( makeForeignObj, writeForeignObj )
import PrelList (span)
#if defined(__CONCURRENT_HASKELL__)
import ConcBase
%*********************************************************
\begin{code}
+#ifndef PAR
filePtr :: Handle__ -> ForeignObj
+#else
+filePtr :: Handle__ -> Addr
+#endif
filePtr (SemiClosedHandle fp _) = fp
filePtr (ReadHandle fp _ _) = fp
filePtr (WriteHandle fp _ _) = fp
_ccall_ getLock (``stdin''::Addr) 0 >>= \ rc ->
(case rc of
0 -> new_handle ClosedHandle
- 1 -> makeForeignObj (``stdin''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
+ 1 ->
+#ifndef PAR
+ makeForeignObj (``stdin''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
new_handle (ReadHandle fp Nothing False)
+#else
+ new_handle (ReadHandle ``stdin'' Nothing False)
+#endif
_ -> constructError "stdin" >>= \ ioError ->
new_handle (ErrorHandle ioError)
) >>= \ handle ->
_ccall_ getLock (``stdout''::Addr) 1 >>= \ rc ->
(case rc of
0 -> new_handle ClosedHandle
- 1 -> makeForeignObj (``stdout''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
+ 1 ->
+#ifndef PAR
+ makeForeignObj (``stdout''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
new_handle (WriteHandle fp Nothing False)
+#else
+ new_handle (WriteHandle ``stdout'' Nothing False)
+#endif
_ -> constructError "stdout" >>= \ ioError ->
new_handle (ErrorHandle ioError)
) >>= \ handle ->
_ccall_ getLock (``stderr''::Addr) 1 >>= \ rc ->
(case rc of
0 -> new_handle ClosedHandle
- 1 -> makeForeignObj (``stderr''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
+ 1 ->
+#ifndef PAR
+ makeForeignObj (``stderr''::Addr) (``&freeStdChannel''::Addr) >>= \ fp ->
new_handle (WriteHandle fp (Just NoBuffering) False)
+#else
+ new_handle (WriteHandle ``stderr'' (Just NoBuffering) False)
+#endif
_ -> constructError "stderr" >>= \ ioError ->
new_handle (ErrorHandle ioError)
) >>= \ handle ->
openFile f m =
stToIO (_ccall_ openFile f m') >>= \ ptr ->
if ptr /= ``NULL'' then
- stToIO (makeForeignObj ptr ((``&freeFile'')::Addr)) >>= \ fp ->
+#ifndef PAR
+ makeForeignObj ptr ((``&freeFile'')::Addr) `thenIO_Prim` \ fp ->
newHandle (htype fp Nothing False)
+#else
+ newHandle (htype ptr Nothing False)
+#endif
else
stToIO (constructError "openFile") >>= \ ioError@(IOError hn iot msg) ->
let
hClose handle =
readHandle handle >>= \ htype ->
- writeHandle handle ClosedHandle >>
case htype of
ErrorHandle ioError ->
+ writeHandle handle htype >>
fail ioError
ClosedHandle ->
+ writeHandle handle htype >>
ioe_closedHandle handle
SemiClosedHandle fp (buf,_) ->
(if buf /= ``NULL'' then
has been performed, the ForeignObj embedded in the Handle
is still lying around in the heap, so care is taken
to avoid closing the file object when the ForeignObj
- is finalised. (see freeFile()) -}
+ is finalised. -}
if rc == 0 then
- return ()
+#ifndef PAR
+ -- Mark the foreign object data value as gone to the finaliser (freeFile())
+ writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
+#endif
+ writeHandle handle ClosedHandle
else
+ writeHandle handle htype >>
constructErrorAndFail "hClose"
else
- return ()
+ writeHandle handle htype
other ->
- _ccall_ closeFile (filePtr other) `thenIO_Prim` \ rc ->
+ let fp = filePtr other in
+ _ccall_ closeFile fp `thenIO_Prim` \ rc ->
if rc == 0 then
- return ()
+#ifndef PAR
+ -- Mark the foreign object data
+ writeForeignObj fp ``NULL'' `thenIO_Prim` \ () ->
+#endif
+ writeHandle handle ClosedHandle
else
+ writeHandle handle htype >>
constructErrorAndFail "hClose"
\end{code}
BlockBuffering Nothing -> -2
BlockBuffering (Just n) -> n
+#ifndef PAR
hcon :: Handle__ -> (ForeignObj -> (Maybe BufferMode) -> Bool -> Handle__)
+#else
+ hcon :: Handle__ -> (Addr -> (Maybe BufferMode) -> Bool -> Handle__)
+#endif
hcon (ReadHandle _ _ _) = ReadHandle
hcon (WriteHandle _ _ _) = WriteHandle
hcon (AppendHandle _ _ _) = AppendHandle
instance CCallable ForeignObj
instance CCallable ForeignObj#
-eqForeignObj :: ForeignObj -> ForeignObj -> Bool
-makeForeignObj :: Addr -> Addr -> PrimIO ForeignObj
+eqForeignObj :: ForeignObj -> ForeignObj -> Bool
+makeForeignObj :: Addr -> Addr -> PrimIO ForeignObj
+writeForeignObj :: ForeignObj -> Addr -> PrimIO ()
-makeForeignObj (A# obj) (A# finaliser) = ST $ \ (S# s#) ->
+{- derived op - attaching a free() finaliser to a malloc() allocated reference. -}
+makeMallocPtr :: Addr -> PrimIO ForeignObj
+
+makeForeignObj (A# obj) (A# finaliser) = ST ( \ (S# s#) ->
case makeForeignObj# obj finaliser s# of
- StateAndForeignObj# s1# fo# -> (ForeignObj fo#, S# s1#)
+ StateAndForeignObj# s1# fo# -> (ForeignObj fo#, S# s1#))
+
+writeForeignObj (ForeignObj fo#) (A# datum#) = ST ( \ (S# s#) ->
+ case writeForeignObj# fo# datum# s# of { s1# -> ((), S# s1#) } )
+
+makeMallocPtr a = makeForeignObj a (``&free''::Addr)
eqForeignObj mp1 mp2
= unsafePerformPrimIO (_ccall_ eqForeignObj mp1 mp2) /= (0::Int)
%
% (c) The AQUA Project, Glasgow University, 1994-1997
%
-
-\section[Directory]{Module @Directory@}
+\section[Directory]{Directory interface}
A directory contains a series of entries, each of which is a named
reference to a file system object (file, directory etc.). Some
are relative to the current directory.
\begin{code}
-module Directory (
--- Permissions(Permissions),
- createDirectory, removeDirectory, removeFile,
- renameDirectory, renameFile, getDirectoryContents,
- getCurrentDirectory, setCurrentDirectory
-{-
- ,doesFileExist, doesDirectoryExist,
- getPermissions, setPermissions,
+{-# OPTIONS -#include <sys/stat.h> #-}
+module Directory
+ (
+ Permissions(Permissions),
+
+ createDirectory,
+ removeDirectory,
+ renameDirectory,
+ getDirectoryContents,
+ getCurrentDirectory,
+ setCurrentDirectory,
+
+ removeFile,
+ renameFile,
+
+ doesFileExist,
+ doesDirectoryExist,
+ getPermissions,
+ setPermissions,
getModificationTime
--}
- ) where
+ ) where
-import Prelude
+import PrelBase
import Foreign
import IOBase
-import STBase ( PrimIO )
-import PackedString ( packCBytesST, unpackPS )
+import STBase
+import ArrBase
+import PackedString ( packCBytesST, unpackPS, psToByteArrayST )
+import Time ( ClockTime(..) )
+
\end{code}
%*********************************************************
getDirectoryContents :: FilePath -> IO [FilePath]
getCurrentDirectory :: IO FilePath
setCurrentDirectory :: FilePath -> IO ()
+doesFileExist :: FilePath -> IO Bool
+doesDirectoryExist :: FilePath -> IO Bool
+getPermissions :: FilePath -> IO Permissions
+setPermissions :: FilePath -> Permissions -> IO ()
+getModificationTime :: FilePath -> IO ClockTime
\end{code}
%* *
%*********************************************************
-The @Permissions@ type is used to record whether certain operations are permissible on a
-file/directory:
+The @Permissions@ type is used to record whether certain
+operations are permissible on a file/directory:
+[to whom? - owner/group/world - the Report don't say much]
\begin{code}
data Permissions
readable, writeable,
executable, searchable :: Bool
} deriving (Eq, Ord, Read, Show)
-
\end{code}
%*********************************************************
\begin{code}
-{-
-doesFileExist :: FilePath -> IO Bool
+--doesFileExist :: FilePath -> IO Bool
doesFileExist name =
psToByteArrayST name `thenIO_Prim` \ path ->
_ccall_ access path (``F_OK''::Int) `thenIO_Prim` \ rc ->
return (rc == 0)
-doesDirectoryExist :: FilePath -> IO Bool
-doesDirectoryExist name =
- (getFileStatus >>= isDirectory) `catch` (\ _ -> return False)
+--doesDirectoryExist :: FilePath -> IO Bool
+doesDirectoryExist name =
+ (getFileStatus name >>= \ st -> return (isDirectory st))
+ `catch`
+ (\ _ -> return False)
-getModificationTime :: FilePath -> IO Bool
+--getModificationTime :: FilePath -> IO ClockTime
getModificationTime name =
- getFileStatus >>= \ st ->
- return (modificationTime st)
+ getFileStatus name >>= \ st ->
+ modificationTime st
-getPermissions :: FilePath -> IO Permissions
+--getPermissions :: FilePath -> IO Permissions
getPermissions name =
- getFileStatus >>= \ st ->
+ getFileStatus name >>= \ st ->
let
fm = fileMode st
isect v = intersectFileMode v fm == v
searchable = not (isRegularFile st) && isect ownerExecuteMode
}
)
--}
+
+--setPermissions :: FilePath -> Permissions -> IO ()
+setPermissions name (Permissions r w e s) =
+ let
+ read# = case (if r then ownerReadMode else ``0'') of { W# x# -> x# }
+ write# = case (if w then ownerWriteMode else ``0'') of { W# x# -> x# }
+ exec# = case (if e || s then ownerExecuteMode else ``0'') of { W# x# -> x# }
+
+ mode = I# (word2Int# (read# `or#` write# `or#` exec#))
+ in
+ psToByteArrayST name `thenIO_Prim` \ path ->
+ _ccall_ chmod path mode `thenIO_Prim` \ rc ->
+ if rc == 0 then
+ return ()
+ else
+ fail (IOError Nothing SystemError "Directory.setPermissions")
+
+\end{code}
+
+
+(Sigh)..copied from Posix.Files to avoid dep. on posix library
+
+\begin{code}
+type FileStatus = ByteArray Int
+
+getFileStatus :: FilePath -> IO FileStatus
+getFileStatus name =
+ psToByteArrayST name `thenIO_Prim` \ path ->
+ newCharArray (0,``sizeof(struct stat)'') `thenIO_Prim` \ bytes ->
+ _casm_ ``%r = stat(%0,(struct stat *)%1);'' path bytes
+ `thenIO_Prim` \ rc ->
+ if rc == 0 then
+ unsafeFreezeByteArray bytes `thenIO_Prim` \ stat ->
+ return stat
+ else
+ fail (IOError Nothing SystemError "Directory.getFileStatus")
+
+modificationTime :: FileStatus -> IO ClockTime
+modificationTime stat =
+ malloc1 `thenIO_Prim` \ i1 ->
+ _casm_ ``((unsigned long *)%1)[0] = ((struct stat *)%0)->st_mtime;'' stat i1 `thenIO_Prim` \ () ->
+ cvtUnsigned i1 `thenIO_Prim` \ secs ->
+ return (TOD secs 0)
+ where
+ malloc1 = ST $ \ (S# s#) ->
+ case newIntArray# 1# s# of
+ StateAndMutableByteArray# s2# barr# -> (MutableByteArray bnds barr#, S# s2#)
+
+ bnds = (0,1)
+ -- The C routine fills in an unsigned word. We don't have `unsigned2Integer#,'
+ -- so we freeze the data bits and use them for an MP_INT structure. Note that
+ -- zero is still handled specially, although (J# 1# 1# (ptr to 0#)) is probably
+ -- acceptable to gmp.
+
+ cvtUnsigned (MutableByteArray _ arr#) = ST $ \ (S# s#) ->
+ case readIntArray# arr# 0# s# of
+ StateAndInt# s2# r# ->
+ if r# ==# 0# then
+ (0, S# s2#)
+ else
+ case unsafeFreezeByteArray# arr# s2# of
+ StateAndByteArray# s3# frozen# -> (J# 1# 1# frozen#, S# s3#)
+
+isDirectory :: FileStatus -> Bool
+isDirectory stat = unsafePerformPrimIO $
+ _casm_ ``%r = S_ISDIR(((struct stat *)%0)->st_mode);'' stat >>= \ rc ->
+ return (rc /= 0)
+
+isRegularFile :: FileStatus -> Bool
+isRegularFile stat = unsafePerformPrimIO $
+ _casm_ ``%r = S_ISREG(((struct stat *)%0)->st_mode);'' stat >>= \ rc ->
+ return (rc /= 0)
+
+
+\end{code}
+
+\begin{code}
+type FileMode = Word
+ownerReadMode :: FileMode
+ownerReadMode = ``S_IRUSR''
+
+ownerWriteMode :: FileMode
+ownerWriteMode = ``S_IWUSR''
+
+ownerExecuteMode :: FileMode
+ownerExecuteMode = ``S_IXUSR''
+
+intersectFileMode :: FileMode -> FileMode -> FileMode
+intersectFileMode (W# m1#) (W# m2#) = W# (m1# `and#` m2#)
+
+fileMode :: FileStatus -> FileMode
+fileMode stat = unsafePerformPrimIO $
+ _casm_ ``%r = ((struct stat *)%0)->st_mode;'' stat >>= \ mode ->
+ return mode
+
\end{code}
import PackedString ( nilPS, packCBytesST, unpackPS )
import PrelBase
import GHC
-import Foreign ( makeForeignObj )
+import Foreign ( makeForeignObj, writeForeignObj )
\end{code}
%*********************************************************
then return nilPS
else packCBytesST bytes buf) >>= \ some ->
if bytes < 0 then
- makeForeignObj ``NULL'' ``&freeFile'' >>= \ null_fp ->
- ioToST (writeHandle handle (SemiClosedHandle null_fp (``NULL'', 0)))
- >>
_ccall_ free buf >>= \ () ->
_ccall_ closeFile fp >>
+#ifndef PAR
+ writeForeignObj fp ``NULL'' >>
+ ioToST (writeHandle handle (SemiClosedHandle fp (``NULL'', 0))) >>
+#else
+ ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0))) >>
+#endif
returnPrimIO (unpackPS some)
else
ioToST (writeHandle handle htype) >>
then return nilPS
else packCBytesST bytes buf) >>= \ some ->
if bytes < 0 then
- makeForeignObj ``NULL'' ``&freeFile'' >>= \ null_fp ->
- ioToST (writeHandle handle (SemiClosedHandle null_fp (``NULL'', 0)))
- >>
_ccall_ free buf >>= \ () ->
_ccall_ closeFile fp >>
+#ifndef PAR
+ writeForeignObj fp ``NULL'' >>
+ ioToST (writeHandle handle (SemiClosedHandle fp (``NULL'', 0))) >>
+#else
+ ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0))) >>
+#endif
returnPrimIO (unpackPS some)
else
ioToST (writeHandle handle htype) >>
SemiClosedHandle fp buf_info ->
_ccall_ readChar fp >>= \ char ->
if char == ``EOF'' then
- makeForeignObj ``NULL'' ``&freeFile'' >>= \ null_fp ->
- ioToST (writeHandle handle (SemiClosedHandle null_fp buf_info))
- >>
_ccall_ closeFile fp >>
+#ifndef PAR
+ writeForeignObj fp ``NULL'' >>
+ ioToST (writeHandle handle (SemiClosedHandle fp (``NULL'', 0))) >>
+#else
+ ioToST (writeHandle handle (SemiClosedHandle ``NULL'' (``NULL'', 0))) >>
+#endif
returnPrimIO ""
else
ioToST (writeHandle handle htype) >>
else
constructErrorAndFail "hPutStr"
where
+#ifndef PAR
writeLines :: ForeignObj -> String -> PrimIO Bool
+#else
+ writeLines :: Addr -> String -> PrimIO Bool
+#endif
writeLines = writeChunks ``BUFSIZ'' True
+#ifndef PAR
writeBlocks :: ForeignObj -> Int -> String -> PrimIO Bool
+#else
+ writeBlocks :: Addr -> Int -> String -> PrimIO Bool
+#endif
writeBlocks fp size s = writeChunks size False fp s
{-
a whole lot quicker. -- SOF 3/96
-}
+#ifndef PAR
writeChunks :: Int -> Bool -> ForeignObj -> String -> PrimIO Bool
-
+#else
+ writeChunks :: Int -> Bool -> Addr -> String -> PrimIO Bool
+#endif
writeChunks (I# bufLen) chopOnNewLine fp s =
newCharArray (0,I# bufLen) >>= \ arr@(MutableByteArray _ arr#) ->
let
in
shoveString 0# s
+#ifndef PAR
writeChars :: ForeignObj -> String -> PrimIO Bool
+#else
+ writeChars :: Addr -> String -> PrimIO Bool
+#endif
writeChars fp "" = returnPrimIO True
writeChars fp (c:cs) =
_ccall_ filePutc fp (ord c) >>= \ rc ->
its use of Coordinated Universal Time (UTC).
\begin{code}
+{-# OPTIONS -#include "cbits/timezone.h" -#include "cbits/stgio.h" #-}
+
module Time
(
CalendarTime(..),
Day,
CalendarTime(CalendarTime),
TimeDiff(TimeDiff),
- ClockTime,
+ ClockTime(..), -- non-standard, lib. report gives this as abstract
getClockTime, addToClockTime, diffClockTimes,
toCalendarTime, toUTCTime, toClockTime,
- calendarToTimeString, formatCalendarTime
+ calendarTimeToString, formatCalendarTime
) where
import PrelBase
import ST
-import IOBase ( IOError(..), constructErrorAndFail )
+import IOBase
import ArrBase
import STBase
-
+import ST
+import Ix
+import Char (intToDigit)
import PackedString (unpackPS, packCBytesST)
-import PosixUtil (allocWords, allocChars)
+import Locale
+
\end{code}
One way to partition and give name to chunks of a year and a week:
external calendar time @CalendarTime@.
\begin{code}
-data ClockTime = TOD Integer Integer
- deriving (Eq, Ord)
+data ClockTime = TOD Integer Integer deriving (Eq, Ord)
\end{code}
When a @ClockTime@ is shown, it is converted to a string of the form
_ccall_ strlen zone >>= \ len ->
packCBytesST len zone >>= \ tzname ->
returnPrimIO (CalendarTime (1900+year) mon mday hour min sec psec
- wday yday (unpackPS tzname) tz (isdst /= 0))
+ (toEnum wday) yday (unpackPS tzname) tz (isdst /= 0))
toUTCTime :: ClockTime -> CalendarTime
toUTCTime (TOD sec@(J# a# s# d#) psec) = unsafePerformPrimIO (
_casm_ ``%r = ((struct tm *)%0)->tm_wday;'' tm >>= \ wday ->
_casm_ ``%r = ((struct tm *)%0)->tm_yday;'' tm >>= \ yday ->
returnPrimIO (CalendarTime (1900+year) mon mday hour min sec psec
- wday yday "UTC" 0 False)
+ (toEnum wday) yday "UTC" 0 False)
)
toClockTime :: CalendarTime -> ClockTime
bottom :: (Int,Int)
bottom = error "Time.bottom"
+
+
+-- (copied from PosixUtil, for now)
+-- Allocate a mutable array of characters with no indices.
+
+allocChars :: Int -> ST s (MutableByteArray s ())
+allocChars (I# size#) = ST $ \ (S# s#) ->
+ case newCharArray# size# s# of
+ StateAndMutableByteArray# s2# barr# -> (MutableByteArray bot barr#, S# s2#)
+ where
+ bot = error "Time.allocChars"
+
+-- Allocate a mutable array of words with no indices
+
+allocWords :: Int -> ST s (MutableByteArray s ())
+allocWords (I# size#) = ST $ \ (S# s#) ->
+ case newIntArray# size# s# of
+ StateAndMutableByteArray# s2# barr# -> (MutableByteArray bot barr#, S# s2#)
+ where
+ bot = error "Time.allocWords"
+
\end{code}
\begin{code}
-calendarTimeToString :: CalendarTime -> String
-calendarTimeToString = formatCalendarTime defaultTimeLocale "%c"
-
-formatCalendarTime :: TimeLocale -> String -> CalendarTime -> String
-formatCalendarTime l
- fmt
- ct@(CalendarTime
- year mon
- day hour
- min sec
- sdec
- wday yday tzname _ _)
- = doFmt fmt
- where
- doFmt ('%':c:cs) = decode c ++ doFmt cs
- doFmt (c:cs) = c : doFmt cs
- doFmt "" = ""
-
- to12 h = let h' = h `mod` 12 in if h == 0 then 12 else h
-
- decode 'A' = fst (wdays l !! fromEnum wday)
- decode 'a' = snd (wdays l !! fromEnum wday)
- decode 'B' = fst (months l !! fromEnum mon)
- decode 'b' = snd (months l !! fromEnum mon)
- decode 'h' = snd (months l !! fromEnum mon)
- decode 'C' = show2 (year `quot` 100)
- decode 'c' = doFmt (dateTimeFmt l)
- decode 'D' = doFmt "%m/%d/%y"
- decode 'd' = show2 day
- decode 'e' = show2' day
- decode 'H' = show2 hour
- decode 'I' = show2 (to12 hour)
- decode 'j' = show3 yday
- decode 'k' = show2' hour
- decode 'l' = show2' (to12 hour)
- decode 'M' = show2 min
- decode 'm' = show2 (fromEnum mon+1)
- decode 'n' = "\n"
- decode 'p' = (if hour < 12 then fst else snd) (amPm l)
- decode 'R' = doFmt "%H:%M"
- decode 'r' = doFmt (time12Fmt l)
- decode 'T' = doFmt "%H:%M:%S"
- decode 't' = "\t"
- decode 'S' = show2 sec
- decode 's' = show2 sec -- Implementation-dependent, sez the lib doc..
- decode 'U' = show2 ((yday + 7 - fromEnum wday) `div` 7)
- decode 'u' = show (let n = fromEnum wday in if n == 0 then 7 else n)
- decode 'V' =
- let (week, days) =
- (yday + 7 - if fromEnum wday > 0 then
- fromEnum wday - 1 else 6) `divMod` 7
- in
- show2 (if days >= 4
- then week+1
- else if week == 0 then 53 else week)
- decode 'W' =
- show2 ((yday + 7 - if fromEnum wday > 0 then
- fromEnum wday - 1 else 6) `div` 7)
- decode 'w' = show (fromEnum wday)
- decode 'X' = doFmt (timeFmt l)
- decode 'x' = doFmt (dateFmt l)
- decode 'Y' = show year
- decode 'y' = show2 (year `rem` 100)
- decode 'Z' = tzname
- decode '%' = "%"
- decode c = [c]
-
-show2, show2', show3 :: Int -> String
-show2 x = [intToDigit (x `quot` 10), intToDigit (x `rem` 10)]
-show2' x = if x < 10 then [ ' ', intToDigit x] else show2 x
-show3 x = intToDigit (x `quot` 100) : show2 (x `rem` 100)
-
+calendarTimeToString :: CalendarTime -> String
+calendarTimeToString = formatCalendarTime defaultTimeLocale "%c"
+
+formatCalendarTime :: TimeLocale -> String -> CalendarTime -> String
+formatCalendarTime l fmt ct@(CalendarTime year mon day hour min sec sdec
+ wday yday tzname _ _) =
+ doFmt fmt
+ where doFmt ('%':c:cs) = decode c ++ doFmt cs
+ doFmt (c:cs) = c : doFmt cs
+ doFmt "" = ""
+ to12 h = let h' = h `mod` 12 in if h == 0 then 12 else h
+ decode 'A' = fst (wDays l !! fromEnum wday)
+ decode 'a' = snd (wDays l !! fromEnum wday)
+ decode 'B' = fst (months l !! fromEnum mon)
+ decode 'b' = snd (months l !! fromEnum mon)
+ decode 'h' = snd (months l !! fromEnum mon)
+ decode 'C' = show2 (year `quot` 100)
+ decode 'c' = doFmt (dateTimeFmt l)
+ decode 'D' = doFmt "%m/%d/%y"
+ decode 'd' = show2 day
+ decode 'e' = show2' day
+ decode 'H' = show2 hour
+ decode 'I' = show2 (to12 hour)
+ decode 'j' = show3 yday
+ decode 'k' = show2' hour
+ decode 'l' = show2' (to12 hour)
+ decode 'M' = show2 min
+ decode 'm' = show2 (fromEnum mon+1)
+ decode 'n' = "\n"
+ decode 'p' = (if hour < 12 then fst else snd) (amPm l)
+ decode 'R' = doFmt "%H:%M"
+ decode 'r' = doFmt (time12Fmt l)
+ decode 'T' = doFmt "%H:%M:%S"
+ decode 't' = "\t"
+ decode 'S' = show2 sec
+ decode 's' = show2 sec -- Implementation-dependent, sez the lib doc..
+ decode 'U' = show2 ((yday + 7 - fromEnum wday) `div` 7)
+ decode 'u' = show (let n = fromEnum wday in
+ if n == 0 then 7 else n)
+ decode 'V' =
+ let (week, days) =
+ (yday + 7 - if fromEnum wday > 0 then
+ fromEnum wday - 1 else 6) `divMod` 7
+ in show2 (if days >= 4 then
+ week+1
+ else if week == 0 then 53 else week)
+
+ decode 'W' =
+ show2 ((yday + 7 - if fromEnum wday > 0 then
+ fromEnum wday - 1 else 6) `div` 7)
+ decode 'w' = show (fromEnum wday)
+ decode 'X' = doFmt (timeFmt l)
+ decode 'x' = doFmt (dateFmt l)
+ decode 'Y' = show year
+ decode 'y' = show2 (year `rem` 100)
+ decode 'Z' = tzname
+ decode '%' = "%"
+ decode c = [c]
+
+show2, show2', show3 :: Int -> String
+show2 x = [intToDigit (x `quot` 10), intToDigit (x `rem` 10)]
+
+show2' x = if x < 10 then [ ' ', intToDigit x] else show2 x
+
+show3 x = intToDigit (x `quot` 100) : show2 (x `rem` 100)
\end{code}
# -----------------------------------------------------------------
# Everything after this point
# augments or overrides previously set variables.
-# (these files are optional, so `make' won't fret if
-# cannot get to them).
# -----------------------------------------------------------------
--include $(TOP)/mk/paths.mk
--include $(TOP)/mk/opts.mk
+include $(TOP)/mk/paths.mk
+include $(TOP)/mk/opts.mk
include $(TOP)/mk/suffix.mk
# What ways to build the RTS+libs
WAYS=$(GhcLibWays)
+GCap=-optc-DGCap
+#GC2s=-optc-DGC2s
+#GC1s=-optc-DGC1s
MKDEPENDHSSRC = $(GHC_UTILS_DIR)/mkdependHS
UNLIT = $(GHC_UNLIT_DIR)/unlit
+GHC_UNLIT = $(GHC_UNLIT_DIR)/unlit
GHC_UNLIT_DIR = $(GHC_UTILS_DIR)/unlit
#-----------------------------------------------------------------------------
# Ugen
ifdef UseInstalledUtils
-UGEN = ugen
+UGEN = ugen
else
UGEN = $(UGEN_DIR)/ugen
-UGENSRC = $(GHC_UTILS_DIR)/ugen
+UGEN_DIR = $(GHC_UTILS_DIR)/ugen
endif
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
-# $Id: Makefile,v 1.4 1997/03/14 05:11:52 sof Exp $
+# $Id: Makefile,v 1.5 1997/03/17 20:34:59 simonpj Exp $
# This is the Makefile for the runtime-system stuff.
# This stuff is written in C (and cannot be written in Haskell).
#
# dependencies
#
-SRC_HC_OPTS += -I$(GHC_INCLUDE_DIR) -O -optc-DIN_GHC_RTS=1 -I$(GHC_RUNTIME_DIR)/storage
+SRC_HC_OPTS += -I$(GHC_INCLUDE_DIR) $(GCap) $(GC2s) $(GC1s) -O -optc-DIN_GHC_RTS=1 -I$(GHC_RUNTIME_DIR)/storage
-SRC_MKDEPENDC_OPTS += $(GCap) $(GC2s) $(GC1s)
+SRC_MKDEPENDC_OPTS += -I$(GHC_INCLUDE_DIR) $(GCap) $(GC2s) $(GC1s)
#-----------------------------------------------------------------------------
# file-specific options
because it has no return value */
I_ n;
{
+ /* Storage manager shutdown */
+ shutdownHaskell();
EXIT(n);
return(0); /* GCC warning food */
}
# Build the Haskell Readline bindings?
#
HsLibsWithReadline=YES
+#
+# Include path to readline.h
+# (no path == in standard include path)
+#
+ReadlineIncludePath=
# Build the socket libraries?
#
#
HsLibWays=$(GhcLibWays)
+# Option flags for hslibs are by default the same as for the options
+# used for the prelude libs (see above).
+HsLibHcOpts=$(GhcLibHcOpts)
#################################################################################
#
#
#################################################################################
-# These variables are all ":=" variables so that you can easily attach
-# extra stuff to the end of them, like this:
-#
-# libdir := $(libdir)/ghc
-
-TMPDIR := /tmp
+TMPDIR = /tmp
# FPTOOLS_TOP: the top of the fptools hierarchy, absolute path.
-FPTOOLS_TOP_ABS := @hardtop@
+FPTOOLS_TOP_ABS = @hardtop@
#
# Installation directories, we don't use half of these,
# but since the configure script has them on offer while
# passing through, we might as well set them.
-prefix := @prefix@
-exec_prefix := @exec_prefix@
-bindir := @bindir@
-sbindir := @sbindir@
-libexecdir := @libexecdir@
-datadir := @datadir@
-sysconfdir := @datadir@
-sharedstatedir := @sharedstatedir@
-localstatedir := @localstatedir@
-libdir := @libdir@
-infodir := @infodir@
-includedir := @includedir@
-oldincludedir := @oldincludedir@
-mandir := @mandir@
-srcdir := @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @datadir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+includedir = @includedir@
+oldincludedir = @oldincludedir@
+mandir = @mandir@
+srcdir = @srcdir@
#################################################################################
#
$(LIT2TEXI) -S -c $(LIT2TEXI_OPTS) -o $(patsubst %.html,%.itxi,$@) $(addsuffix .lit,$(basename $@))
$(LIT2TEXI) -S $(LIT2TEXI_OPTS) -o $(patsubst %.html,%.texi,$@) $(addsuffix .itxi,$(basename $@))
$(TEXI2HTML) $(TEXI2HTML_OPTS) $(patsubst %.html,%.texi,$@)
+ cp $(TEXI2HTML_PREFIX)invisible.xbm .
else
$(RM) html/$(basename $@)*
$(MKDIRHIER) html
$(LIT2TEXI) -S -c $(LIT2TEXI_OPTS) -o $(patsubst %.html,%.itxi,$@) $(addsuffix .lit,$(basename $@))
$(LIT2TEXI) -S $(LIT2TEXI_OPTS) -o html/$(patsubst %.html,%.texi,$@) $(addsuffix .itxi,$(basename $@))
(cd html; ../$(TEXI2HTML) $(TEXI2HTML_OPTS) $(patsubst %.html,%.texi,$@); cd ..)
+ cp $(TEXI2HTML_PREFIX)invisible.xbm html/
@touch $@
endif
-
###########################################
#
# Targets: clean