Re: MTASC has been forked, perhaps you would like to update?

View: New views
6 Messages — Rating Filter:   Alert me  

Parent Message unknown Re: MTASC has been forked, perhaps you would like to update?

by Paul Wise-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 2009-10-30 at 13:16 +0100, Tristan Schmelcher wrote:

> I'm just writing to let you know that I recently forked MTASC, the
> Motion-Twin ActionScript 2.0 compiler, which is packaged in both
> Debian and Ubuntu as "mtasc". Motion-Twin has ceased development of
> MTASC and my attempts to get patches submitted fell on deaf ears, so I
> have made a new site and released a new version, 1.15. See
> http://sourceforge.net/projects/mtasc/ for the code and binaries.

Tristan, I know how you feel, some of my simple Debian patches are still
waiting as far as I know.

Nicolas, when will you be able to merge our patches?

Nicolas, even if you do merge Tristan's patches, I think it would be a
good idea to turn mtasc development over to the community and moving
everything to a sourceforge project is probably the best way to do that.
Would you consider doing that? One issue with doing that is the extc
static library, which is currently an embedded code copy in mtasc. I
guess that could be moved to its own project too.

Tristan, why are you not distributing a source code tarball?

Tristan, if you haven't yet looked at the Git version control system,
I'd strongly suggest doing so. If you need someone to do a good
conversion from CVS -> SVN -> Git, I'd be happy to help out since I have
a fair bit of experience with that.

> The new version adds two major features: support for classes
> containing more than 32 KB of bytecode, and support for Flash 9. These
> changes have been in use internally at Google for almost two years
> with no problems.

I'm sure mtasc users would very much appreciate these two features.

> I'd be pleased if you would consider updating your mtasc packages to
> the new version.

I'm not actually using the Debian mtasc package and am only maintaining
it out of inertia. If you would like to take it over and upload your
fork to Debian (which would then be automatically copied to Ubuntu), I'd
be happy to sponsor you until you become a DD or get DM privileges.

You might want to contact the maintainers of the FreeBSD and Fink
packages too, you can find them using the 'whohas' tool in Debian:

http://www.philippwesche.org/200811/whohas/intro.html

--
bye,
pabs

http://wiki.debian.org/PaulWise


--
MTASC : no more coffee break while compiling

signature.asc (205 bytes) Download Attachment

Re: MTASC has been forked, perhaps you would like to update?

by Tristan Schmelcher-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks for the quick reply, Paul.

2009/10/30 Paul Wise <pabs@...>
On Fri, 2009-10-30 at 13:16 +0100, Tristan Schmelcher wrote:

> I'm just writing to let you know that I recently forked MTASC, the
> Motion-Twin ActionScript 2.0 compiler, which is packaged in both
> Debian and Ubuntu as "mtasc". Motion-Twin has ceased development of
> MTASC and my attempts to get patches submitted fell on deaf ears, so I
> have made a new site and released a new version, 1.15. See
> http://sourceforge.net/projects/mtasc/ for the code and binaries.

Tristan, I know how you feel, some of my simple Debian patches are still
waiting as far as I know.

Nicolas, when will you be able to merge our patches?

Nicolas, even if you do merge Tristan's patches, I think it would be a
good idea to turn mtasc development over to the community and moving
everything to a sourceforge project is probably the best way to do that.
Would you consider doing that? One issue with doing that is the extc
static library, which is currently an embedded code copy in mtasc. I
guess that could be moved to its own project too.

Tristan, why are you not distributing a source code tarball?


I read over SourceForge's current policy docs and couldn't find any reference to their old requirement that projects release source tarballs, so I assumed it was no longer required. The source is all in SVN of course. I'm not committed against source tarballs though.
 
Tristan, if you haven't yet looked at the Git version control system,
I'd strongly suggest doing so. If you need someone to do a good
conversion from CVS -> SVN -> Git, I'd be happy to help out since I have
a fair bit of experience with that.

I'm aware of Git, though I don't have much experience with it. From what I know of Git it sounds awesome, but it also sounds like most of its benefits are for projects with large numbers of contributors and patches (e.g., the Linux kernel). I don't expect a fork of MTASC to have either, so I'm not sure the gains would be worth the migration effort.
 

> The new version adds two major features: support for classes
> containing more than 32 KB of bytecode, and support for Flash 9. These
> changes have been in use internally at Google for almost two years
> with no problems.

I'm sure mtasc users would very much appreciate these two features.

> I'd be pleased if you would consider updating your mtasc packages to
> the new version.

I'm not actually using the Debian mtasc package and am only maintaining
it out of inertia. If you would like to take it over and upload your
fork to Debian (which would then be automatically copied to Ubuntu), I'd
be happy to sponsor you until you become a DD or get DM privileges.

You might want to contact the maintainers of the FreeBSD and Fink
packages too, you can find them using the 'whohas' tool in Debian:

http://www.philippwesche.org/200811/whohas/intro.html

--
bye,
pabs

http://wiki.debian.org/PaulWise


--
MTASC : no more coffee break while compiling

Re: MTASC has been forked, perhaps you would like to update?

by Paul Wise-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 2009-10-30 at 18:04 +0100, Tristan Schmelcher wrote:

> I read over SourceForge's current policy docs and couldn't find any
> reference to their old requirement that projects release source
> tarballs, so I assumed it was no longer required. The source is all in
> SVN of course. I'm not committed against source tarballs though.

It is just standard practice to do so and quite weird to not do so.
Also, if you don't provide tarballs it is hard to know what is the
corresponding source for the binaries (see the GNU GPL).

> I'm aware of Git, though I don't have much experience with it. From
> what I know of Git it sounds awesome, but it also sounds like most of
> its benefits are for projects with large numbers of contributors and
> patches (e.g., the Linux kernel). I don't expect a fork of MTASC to
> have either, so I'm not sure the gains would be worth the migration
> effort.

git is worth using even for a single-person project. I wouldn't start a
FLOSS project using an SVN repository these days. The only thing that
would stop me using git (or other DVCS) would be Windows support, which
some FLOSS people still rely on unfortunately.

--
bye,
pabs

http://wiki.debian.org/PaulWise


--
MTASC : no more coffee break while compiling

signature.asc (205 bytes) Download Attachment

Parent Message unknown Re: Re: MTASC has been forked, perhaps you would like to update?

by Tristan Schmelcher-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'd be fine with moving to Github if there's interest in further MTASC development. I'll contact the HAMTASC list and see.

I've finally gotten around to releasing a source archive on the SF site, and attached the two patches here taken right from svn diff. patch -p0 < FILE should work.

(Paul: the Flash 9 support will require a small packaging change, in that there is a new "std9" directory that must be shipped in the same way as the std and std8 directories.)

2009/11/13 Luke Bayes <lbayes@...>
I could be wrong, but I'm pretty sure Git works fine on Windows.

For whatever it's worth, I also vote for Github.

Having managed a handful of moderately successful open source projects
on Sourceforge over the past 8 years, I've never seen anything close
to the quantity or quality of contributions that we've seen from
Github in the past 12 months. They're not even close to equivalent
systems.

Github encourages and facilitates contribution while Sourceforge
actively inhibits it. And don't get me started on the spammy
SourceForge download pages.


Luke Bayes
http://asunit.org
http://projectsprouts.org


[mtasc-patch-support-flash9.diff]

Index: ocaml/mtasc/std9/MovieClipLoader.as
===================================================================
--- ocaml/mtasc/std9/MovieClipLoader.as (revision 0)
+++ ocaml/mtasc/std9/MovieClipLoader.as (revision 10)
@@ -0,0 +1,17 @@
+//****************************************************************************
+// ActionScript Standard Library
+// MovieClipLoader object
+//****************************************************************************
+
+intrinsic class MovieClipLoader
+{
+ var checkPolicyFile : Boolean;
+
+ function MovieClipLoader();
+
+ function addListener(listener:Object):Boolean;
+ function getProgress(target:Object):Object;
+ function loadClip(url:String, target:Object):Boolean;
+ function removeListener(listener:Object):Boolean;
+ function unloadClip(target:Object):Boolean;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/NetStream.as
===================================================================
--- ocaml/mtasc/std9/NetStream.as (revision 0)
+++ ocaml/mtasc/std9/NetStream.as (revision 10)
@@ -0,0 +1,33 @@
+//****************************************************************************
+// ActionScript Standard Library
+// NetStream object
+//****************************************************************************
+
+dynamic intrinsic class NetStream
+{
+ var bufferLength:Number;
+ var bufferTime:Number;
+ var bytesLoaded:Number;
+ var bytesTotal:Number;
+ var currentFps:Number;
+ var liveDelay:Number;
+ var time:Number;
+ var checkPolicyFile : Boolean;
+
+ function NetStream(connection:NetConnection);
+
+ function attachAudio(theMicrophone:Microphone):Void;
+ function attachVideo(theCamera:Camera,snapshotMilliseconds:Number):Void;
+ function close():Void;
+ function pause(flag:Boolean):Void;
+ function play(name:Object, start:Number, len:Number, reset:Object):Void;
+ function publish(name:Object, type:String):Void;
+ function receiveAudio(flag:Boolean):Void;
+ function receiveVideo(flag:Object):Void;
+ function seek(offset:Number):Void;
+ function send(handlerName:String):Void;
+ function setBufferTime(bufferTime:Number):Void;
+ function onResult(streamId:Number);
+ function onStatus(infoObject:Object):Void;
+ function onCuePoint(infoObject:Object):Void;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/Stage.as
===================================================================
--- ocaml/mtasc/std9/Stage.as (revision 0)
+++ ocaml/mtasc/std9/Stage.as (revision 10)
@@ -0,0 +1,19 @@
+//****************************************************************************
+// ActionScript Standard Library
+// Stage object
+//****************************************************************************
+
+intrinsic class Stage
+{
+ static var align:String;
+    static var displayState:String;
+ static var height:Number;
+ static var scaleMode:String;
+ static var showMenu:Boolean;
+ static var width:Number;
+
+ static function addListener(listener:Object):Void;
+ static function removeListener(listener:Object):Boolean;
+
+    function onFullScreen(bFull:Boolean):Void;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/MovieClip.as
===================================================================
--- ocaml/mtasc/std9/MovieClip.as (revision 0)
+++ ocaml/mtasc/std9/MovieClip.as (revision 10)
@@ -0,0 +1,117 @@
+//****************************************************************************
+// ActionScript Standard Library
+// Movie Clip object
+//****************************************************************************
+import flash.display.BitmapData;
+import flash.geom.Matrix;
+import flash.geom.Rectangle;
+import flash.geom.Transform;
+
+dynamic intrinsic class MovieClip
+{
+ var _alpha:Number;
+ var _currentframe:Number;
+ var _droptarget:String;
+ var _focusrect:Boolean;
+ var _framesloaded:Number;
+ var _height:Number;
+ var _highquality:Number;
+ var _lockroot:Boolean;
+ var _name:String;
+ var _parent:MovieClip;
+ var _quality:String;
+ var _rotation:Number;
+ var _soundbuftime:Number;
+ var _target:String;
+ var _totalframes:Number;
+ var _url:String;
+ var _visible:Boolean;
+ var _width:Number;
+ var _x:Number;
+ var _xmouse:Number;
+ var _xscale:Number;
+ var _y:Number;
+ var _ymouse:Number;
+ var _yscale:Number;
+ var scale9Grid:Rectangle;
+ var enabled:Boolean;
+ var focusEnabled:Boolean;
+ var hitArea:Object;
+ var menu:ContextMenu;
+ var tabChildren:Boolean;
+ var tabEnabled:Boolean;
+ var tabIndex:Number;
+ var tooltipText:String; // Central API
+ var trackAsMenu:Boolean;
+ var useHandCursor:Boolean;
+ var cacheAsBitmap:Boolean;
+ var filters:Array;
+ var opaqueBackground:Number;
+ var scrollRect:Object;
+ var transform:Transform;
+ var blendMode:Object;
+ var forceSmoothing:Boolean;
+
+ function attachAudio(id:Object):Void;
+ function attachBitmap(bmp:BitmapData, depth:Number, pixelSnapping:String, smoothing:Boolean):Void;
+ function attachMovie(id:String,name:String,depth:Number,initObject:Object):MovieClip;
+ function clear():Void;
+ function createEmptyMovieClip(name:String,depth:Number):MovieClip;
+ function beginBitmapFill(bmp:BitmapData, matrix:Matrix, repeat:Boolean, smoothing:Boolean):Void;
+ function beginFill(rgb:Number,alpha:Number):Void;
+ function beginGradientFill(fillType:String,colors:Array,alphas:Array,ratios:Array,matrix:Object,spreadMethod:String,interpolationMethod:String,focalPointRatio:Number):Void;
+ function lineGradientStyle(fillType:String,colors:Array,alphas:Array,ratios:Array,matrix:Object,spreadMethod:String,interpolationMethod:String,focalPointRatio:Number):Void;
+ function createTextField(instanceName:String,depth:Number,x:Number,y:Number,width:Number,height:Number):TextField;
+ function curveTo(controlX:Number,controlY:Number,anchorX:Number,anchorY:Number):Void;
+ function duplicateMovieClip(name:String,depth:Number,initObject:Object):MovieClip;
+ function endFill():Void;
+ function getBounds(bounds:Object):Object;
+ function getRect(bounds:Object):Object;
+ function getBytesLoaded():Number;
+ function getBytesTotal():Number;
+ function getDepth():Number;
+ function getInstanceAtDepth(depth:Number):MovieClip;
+ function getNextHighestDepth():Number;
+ function getSWFVersion():Number;
+ function getTextSnapshot():TextSnapshot;
+ function getURL(url:String,window:String,method:String):Void;
+ function globalToLocal(pt:Object):Void;
+ function gotoAndPlay(frame:Object):Void; // frame can be String or Number
+ function gotoAndStop(frame:Object):Void; // frame can be String or Number
+ function hitTest():Boolean; // arguments can be either target or x/y/shapeFlag
+ function lineStyle(thickness:Number,rgb:Number,alpha:Number,pixelHinting:Boolean,noScale:String,capsStyle:String,jointStyle:String,miterLimit:Number):Void;
+ function lineTo(x:Number,y:Number):Void;
+ function loadMovie(url:String,method:String):Void;
+ function loadVariables(url:String,method:String):Void;
+ function localToGlobal(pt:Object):Void;
+ function moveTo(x:Number,y:Number):Void;
+ function nextFrame():Void;
+ function play():Void;
+ function prevFrame():Void;
+ function removeMovieClip():Void;
+ function setMask(mc:Object):Void;
+ function startDrag(lockCenter:Boolean,left:Number,top:Number,right:Number,bottom:Number):Void;
+ function stop():Void;
+ function stopDrag():Void;
+ function swapDepths(target:Object):Void;
+ function unloadMovie():Void;
+ function valueOf():MovieClip;
+ function onData():Void;
+ function onDragOut():Void;
+ function onDragOver():Void;
+ function onEnterFrame():Void;
+ function onKeyDown():Void;
+ function onKeyUp():Void;
+ function onKillFocus(newFocus:Object):Void;
+ function onLoad():Void;
+ function onMouseDown():Void;
+ function onMouseMove():Void;
+ function onMouseUp():Void;
+ function onPress():Void;
+ function onRelease():Void;
+ function onReleaseOutside():Void;
+ function onRollOut():Void;
+ function onRollOver():Void;
+ function onSetFocus(oldFocus:Object):Void;
+ function onUnload():Void;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/Sound.as
===================================================================
--- ocaml/mtasc/std9/Sound.as (revision 0)
+++ ocaml/mtasc/std9/Sound.as (revision 10)
@@ -0,0 +1,35 @@
+//****************************************************************************
+// ActionScript Standard Library
+// Sound object
+//****************************************************************************
+
+intrinsic class Sound
+{
+ var duration:Number;
+ var id3:Object;
+ var ID3:Object;
+ var position:Number;
+ var checkPolicyFile : Boolean;
+
+ function Sound(target:Object);
+
+ function onID3():Void;
+ function onLoad(success:Boolean):Void;
+ function onSoundComplete():Void;
+ function attachSound(id:String):Void;
+ function getBytesLoaded():Number;
+ function getBytesTotal():Number;
+ function getDuration():Number;
+ function getPan():Number;
+ function getPosition():Number;
+ function getTransform():Object;
+ function getVolume():Number;
+ function loadSound(url:String, isStreaming:Boolean):Void;
+ function setDuration(value:Number):Void;
+ function setPan(value:Number):Void;
+ function setPosition(value:Number):Void;
+ function setTransform(transformObject:Object):Void;
+ function setVolume(value:Number):Void;
+ function start(secondOffset:Number, loops:Number):Void;
+ function stop(linkageID:String):Void;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/flash/text/TextRenderer.as
===================================================================
--- ocaml/mtasc/std9/flash/text/TextRenderer.as (revision 0)
+++ ocaml/mtasc/std9/flash/text/TextRenderer.as (revision 10)
@@ -0,0 +1,12 @@
+//****************************************************************************
+// ActionScript Standard Library
+// TextRenderer object
+//****************************************************************************
+
+intrinsic class flash.text.TextRenderer
+{
+ static var maxLevel:Number;
+ static var displayMode:String;
+
+ public static function setAdvancedAntialiasingTable( fontName:String, fontStyle:String, colorType:String, advancedAntialiasingTable:Array):Void;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/flash/display/BitmapData.as
===================================================================
--- ocaml/mtasc/std9/flash/display/BitmapData.as (revision 0)
+++ ocaml/mtasc/std9/flash/display/BitmapData.as (revision 10)
@@ -0,0 +1,91 @@
+//****************************************************************************
+// ActionScript Standard Library
+// flash.display.BitmapData object
+//****************************************************************************
+import flash.geom.Matrix;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.geom.ColorTransform;
+import flash.filters.BitmapFilter;
+
+intrinsic class flash.display.BitmapData
+{
+ var width:Number;
+ var height:Number;
+ var transparent:Boolean;
+ var rectangle:Rectangle;
+
+ static function loadBitmap(id:String):BitmapData;
+
+ function BitmapData (width:Number, height:Number, transparent:Boolean, fillColor:Number);
+ function clone():BitmapData;
+ function getPixel(x:Number, y:Number):Number;
+ function getPixel32(x:Number, y:Number):Number;
+ function setPixel(x:Number, y:Number, color:Number):Void;
+ function setPixel32(x:Number, y:Number, color:Number):Void;
+ function applyFilter (sourceBitmap:BitmapData, sourceRect:Rectangle, destPoint:Point, filter:BitmapFilter):Number;
+ function colorTransform(rect:Rectangle, colorTransform:ColorTransform):Void;
+ public function copyChannel(sourceBitmap:BitmapData, sourceRect:Rectangle,
+ destPoint:Point, sourceChannel:Number, destChannel:Number):Void;
+ public function copyPixels(sourceBitmap:BitmapData,
+  sourceRect:Rectangle,
+  destPoint:Point,
+  alphaBitmap:BitmapData,
+  alphaPoint:Point,
+  mergeAlpha:Boolean):Void;
+ public function dispose():Void;
+ public function draw(source:Object,
+ matrix:Matrix,
+ colorTransform:ColorTransform,
+ blendMode:Object,
+ clipRect:Rectangle,
+ smooth:Boolean):Void;
+ public function fillRect (rect:Rectangle, color:Number):Void;
+ public function floodFill (x:Number, y:Number, color:Number):Void;
+ public function generateFilterRect (sourceRect:Rectangle, filter:BitmapFilter):Rectangle;
+ public function getColorBoundsRect (mask:Number, color:Number, findColor:Boolean):Rectangle;
+ public function hitTest(firstPoint:Point,
+   firstAlphaThreshold:Number,
+   secondObject:Object,
+   secondBitmapPoint:Point,
+   secondAlphaThreshold:Number):Boolean;
+ public function merge(sourceBitmap:BitmapData,
+ sourceRect:Rectangle,
+ destPoint:Point,
+ redMult:Number,
+ greenMult:Number,
+ blueMult:Number,
+ alphaMult:Number):Void;
+ public function noise(randomSeed:Number, low:Number, high:Number,
+ channelOptions:Number,
+ grayScale:Boolean):Void;
+ public function paletteMap(sourceBitmap:BitmapData,
+  sourceRect:Rectangle,
+  destPoint:Point,
+  redArray:Array,
+  greenArray:Array,
+  blueArray:Array,
+  alphaArray:Array):Void;
+ public function perlinNoise(baseX:Number, baseY:Number,
+   numOctaves:Number, randomSeed:Number,
+   stitch:Boolean, fractalNoise:Boolean,
+   channelOptions:Number,
+   grayScale:Boolean,
+   offsets:Object):Void;
+ public function pixelDissolve(sourceBitmap:BitmapData,
+ sourceRect:Rectangle,
+ destPoint:Point,
+ randomSeed:Number,
+ numberOfPixels:Number,
+ fillColor:Number):Number;
+ public function scroll(x:Number, y:Number):Void;
+ public function threshold(sourceBitmap:BitmapData,
+ sourceRect:Rectangle,
+ destPoint:Point,
+ operation:String,
+ threshold:Number,
+ color:Number,
+ mask:Number,
+ copySource:Boolean):Number;
+ public function compare(otherBitmapData:BitmapData):Object;
+}
\ No newline at end of file
Index: ocaml/mtasc/std9/flash/net/FileReference.as
===================================================================
--- ocaml/mtasc/std9/flash/net/FileReference.as (revision 0)
+++ ocaml/mtasc/std9/flash/net/FileReference.as (revision 10)
@@ -0,0 +1,23 @@
+//****************************************************************************
+// ActionScript Standard Library
+// FileReference object
+//****************************************************************************
+
+intrinsic class flash.net.FileReference
+{
+ var creationDate:Date;
+ var modificationDate:Date;
+ var name:String;
+ var size:Number;
+ var creator:String;
+ var type:String;
+ var postData:String;
+
+ public function FileReference();
+ public function browse(typelist:Array):Boolean;
+ public function upload(url:String, uploadDataFieldName:String, testUpload:Boolean):Boolean;
+ public function download(url:String, defaultFileName:String):Boolean;
+ public function cancel():Void;
+ function addListener(listener:Object):Void;
+ function removeListener(listener:Object):Boolean;
+}
\ No newline at end of file
Index: ocaml/mtasc/main.ml
===================================================================
--- ocaml/mtasc/main.ml (revision 9)
+++ ocaml/mtasc/main.ml (revision 10)
@@ -134,7 +134,12 @@
  ] @ !Plugin.options in
  Arg.parse args_spec (fun file -> files := file :: !files) usage;
  Plugin.class_path := (base_path ^ "std/") :: !Plugin.class_path;
- if (match !GenSwf.version with Some x -> x >= 8 | None -> false) then Plugin.class_path := (base_path ^ "std8/") :: !Plugin.class_path;
+ let ver = match !GenSwf.version with
+ | None -> 0
+ | Some x -> x
+ in
+ if ver >= 8 then Plugin.class_path := (base_path ^ "std8/") :: !Plugin.class_path;
+ if ver >= 9 then Plugin.class_path := (base_path ^ "std9/") :: !Plugin.class_path;
  Hashtbl.remove Lexer.keywords "add";
  Parser.warning := (fun msg pos -> report ~do_exit:false (msg,pos) "Warning" (fun msg -> msg));
  if !files = [] then begin


[mtasc-patch-support-overlength-classes.diff]

Index: ocaml/mtasc/genSwf.ml
===================================================================
--- ocaml/mtasc/genSwf.ml (revision 8)
+++ ocaml/mtasc/genSwf.ml (revision 9)
@@ -1291,6 +1291,261 @@
  in
  loop (List.rev path)
 
+(* The AS2 bytecode language requires jump offsets to be 16-bit. As a result,
+   we have to eliminate overlength jumps. We do this by inserting "islands";
+   i.e., the offending jump gets redirected to a new jump that we insert
+   partway to the destination, and that jump goes the rest of the way (or to
+   another jump, etc.). A second additional jump is inserted immediately before
+   the island, which skips to the next instruction. Naturally, all other jump
+   indices must then be adjusted. We endeavour to place jump islands at somewhat
+   efficient locations (specifically, outside of nested function definitions),
+   though there is no guarantee that we accomplish this with a minimal number of
+   islands.
+
+   Note that jump island insertion is not always possible. In such cases this
+   algorithm will run forever. However, this basically never happens in
+   practice. *)
+(* This function requires tons of helper functions which are all very different
+   from the rest of the code for class generation, so we stick them all inside
+   this definition to keep it self-contained. *)
+let eliminate_overlength_jumps =
+ let maybe_get_jump_target act =
+ match act with
+ AJump target -> Some target
+ | ACondJump target -> Some target
+ | _ -> None
+ in let get_jump_target act =
+ match (maybe_get_jump_target act) with
+ Some target -> target
+ | None -> raise (Error "Not a jump instruction")
+ in let set_jump_target acts i target =
+ match (DynArray.get acts i) with
+ AJump _ -> DynArray.set acts i (AJump target)
+ | ACondJump _ -> DynArray.set acts i (ACondJump target)
+ | _ -> raise (Error "Not a jump instruction")
+ in let find_overlength_jump acts =
+ (* Returns the index in "acts" of the first overlength jump, if any. *)
+ (* We tail-recursively iterate over the actions and check each jump's size. *)
+ let rec helper acts i =
+ if i == (DynArray.length acts) - 1 then None (* end of array; no overlength jumps *)
+ else
+ let maybe_target = maybe_get_jump_target (DynArray.get acts i)
+ in match maybe_target with
+ None -> helper acts (i + 1) (* not a jump; continue *)
+ | Some target ->
+ let size = ActionScript.jump_index_to_size acts i target in
+ if size < -0x8000 || size > 0x7FFF
+ (* Uncomment to stick jump islands all over the place for testing.
+   (Must be larger than the largest instruction in the code.) *)
+ (* if size < -0x106 || size > 0x100 *)
+ then Some i (* overlength jump *)
+ else helper acts (i + 1) (* not overlength; continue *)
+ in helper acts 0
+ in let fixup_target i target island_index island_length =
+ (* Adjusts the instruction offset "target" for the instruction at index "i" to
+   account for an island having been inserted at "island_index" of length
+   "island_length". Note: given the choice, we jump to the beginning of
+   the island instead of the end, since we want to avoid putting islands inside
+   of nested functions. *)
+ if i < island_index && (i + target + 1) > island_index then
+ (* Jump goes forwards from before the island to after/into it; increase
+   by length of island. *)
+ target + island_length
+ else if i >= (island_index + island_length) && (i + target + 1) < (island_index + island_length) then
+ (* Jump goes backwards from after the island to before/into it; decrease
+   by length of island (i.e., increase magnitude). *)
+ target - island_length
+ else
+ (* Jump does not intersect with island; no change. *)
+ target
+ in let fixup_instruction_targets acts island_index island_length exempt_index =
+ (* Iterates through an action sequence and fixes all instruction offsets
+   to account for new code having been inserted at island_index and of length
+   island_length, except for instructions inside it or at exempt_index. *)
+ let helper i =
+ if (i >= island_index && i < island_index + island_length) || i == exempt_index then function _ -> ()
+ else function
+ | AJump target ->
+ DynArray.set acts i (AJump (fixup_target i target island_index island_length))
+ | ACondJump target ->
+ DynArray.set acts i (ACondJump (fixup_target i target island_index island_length))
+ | AFunction f ->
+ DynArray.set acts i (AFunction { f with f_codelen = fixup_target i f.f_codelen island_index island_length })
+ | AFunction2 f ->
+ DynArray.set acts i (AFunction2 { f with f2_codelen = fixup_target i f.f2_codelen island_index island_length })
+ | AWith size ->
+ DynArray.set acts i (AWith (fixup_target i size island_index island_length))
+ | ATry t ->
+ let fixed_trylen = fixup_target i t.tr_trylen island_index island_length in
+ let fixed_catchlen =
+ match t.tr_catchlen with
+ None -> None
+ | Some catchlen -> Some (fixup_target (i + fixed_trylen) catchlen island_index island_length) in
+ let fixed_finallylen =
+ match t.tr_finallylen with
+ None -> None
+ | Some finallylen -> Some (fixup_target (i + fixed_trylen + (match fixed_catchlen with None -> 0 | Some i -> i)) finallylen island_index island_length) in
+ DynArray.set acts i (ATry { t with tr_trylen = fixed_trylen; tr_catchlen = fixed_catchlen; tr_finallylen = fixed_finallylen })
+ | _ ->
+ ()
+ in
+ DynArray.iteri helper acts
+ in let get_function_target act =
+ (* Returns the jump index needed to get to the end of the given function
+   instruction's definition, or 0 if not a function instruction. *)
+ match act with
+ AFunction f -> f.f_codelen
+ | AFunction2 f -> f.f2_codelen
+ | _ -> 0
+ in let jump_instruction_size =
+ (* Constant value equal to the size of an unconditional jump instruction in
+   bytes. *)
+ ActionScript.action_length (AJump 0)
+ in let insert_jump_island acts i orig_target island_index =
+ (* Inserts a jump island at "island_index" for the jump at "i" of length
+   "orig_target". *)
+ (* "target" is relative to the instruction after "i", and "insert" inserts
+   _before_ the given index, so that's -1, but the hop jump has to come first,
+   so that's +1, so this is just island_index - i. *)
+ let target = island_index - i in (* new target for the jump *)
+ (* Compute the target value for the island's main jump. We will have gone
+   "target" instructions worth so far (so -target), but the number of
+   instructions to cover will have increased by 2 (so +2 if forward, -2 if
+   back). However, the target is relative to the instruction _after_ the new
+   jump (so -1). *)
+ let island_target = orig_target - target - 1 + if orig_target > 0 then 2 else -2 in
+ (* Now actually insert the jump island. *)
+ DynArray.insert acts island_index (AJump 1); (* hop jump *)
+ DynArray.insert acts (island_index + 1) (AJump island_target); (* main jump *)
+ (* Now change the original jump. Note that if the jump goes backwards then
+   we've put the island before it so the index has changed. *)
+ let new_i = if orig_target > 0 then i else i+2 in
+ set_jump_target acts new_i target;
+ (* Now iterate through the code and fix the targets of all other
+   instructions. *)
+ fixup_instruction_targets acts island_index 2 new_i
+ in let is_region_larger_than acts start stop compare_to =
+ (* Checks whether or not the sum of action lengths in indices [start, end) is
+   greater than the given number. *)
+ let rec helper acts curr stop acc compare_to =
+ if acc > compare_to then true (* already larger *)
+ else if curr >= stop then false (* done. never became larger so must not be *)
+ else helper acts (curr+1) stop (acc+(ActionScript.action_length (DynArray.get acts curr))) compare_to
+ in helper acts start stop 0 compare_to
+ in let choose_nice_jump_island_index_in_range acts start stop is_forward_not_backward =
+ (* Chooses an index (if any) in the range (start, end] where we can usefully
+   insert a jump island for a jump between "start" and "end" (in either
+   direction) without putting the island inside a nested function definition,
+   which would typically be mildly inefficient.
+
+   Specifically, this considers locations that are not inside a nested
+   function block and which would decrease the largest jump size involved.
+   From among those such points, it chooses the one closest to the halfway
+   point. This will not always result in a minimal number of jumps, but no
+   one will really care.
+
+   It is _not_ a requirement that "start" and "end" are in the same function,
+   and indeed there are cases where that property will not hold, b/c even
+   if we give up on a nice island we will still call this for future island
+   insertion, yet at that point some jumps in the code will span
+   function definitions. *)
+ (* Note: curr here is the index to examine as a potential place _after_ which
+   to insert an island, which is different from the semantics above. *)
+ let rec helper acts start stop curr best =
+ if curr >= stop then best
+ else
+ (* Check if this index is the start of a function. If so, we skip past
+   it. *)
+ let skip = get_function_target (DynArray.get acts curr) in
+ if skip > 0 then
+ (* This is a function. Skip to the end. *)
+ helper acts start stop (curr + skip) best
+ else
+ (* Else we could safely insert an island here. See if that will actually
+   decrease the jump sizes. If we didn't bother with this, we'd get
+   into an infinite loop whenever there's a function that we can't
+   jump over, because we can always add useless jump islands at the
+   edges. *)
+ let useful = if is_forward_not_backward then
+ (* Jump goes from start to end. Redirecting it to the island's main
+   jump will leave out the instructions after the island but add in
+   the island's hop jump. Thus the jump size decreases iff the former
+   is larger than the latter. Further, the island's main jump gets to
+   leave out all instructions before the island and does not add in
+   any, so that decreases iff there is at least one instruction before
+   the island. *)
+ (is_region_larger_than acts (curr+1) stop jump_instruction_size)
+ && (curr > start)
+ else
+ (* Jump goes from end to start. Redirecting it to the island's main
+   jump will leave out the instructions before the island but add in
+   the island's main jump. Thus the jump size decreases iff the
+   former is larger than the latter. Further, the island's main jump
+   gets to leave out all instructions after the island, but adds in
+   itself and the hop jump before it, so that decreases iff the
+   former is larger than the latter. *)
+ (is_region_larger_than acts start (curr+1) jump_instruction_size) &&
+ (is_region_larger_than acts (curr+1) (stop+1)
+ (2*jump_instruction_size))
+ in let best =
+ if not useful then
+ best
+ else
+ Some (match best with
+ None -> curr+1
+ | Some best ->
+ if (abs ((stop + start)/2 - best)) >
+ (abs ((stop + start)/2 - (curr+1)))
+ then curr+1 else best)
+ in helper acts start stop (curr+1) best
+ in helper acts start stop start None
+ in let choose_nice_jump_island_index acts i orig_target =
+ (* Like choose_island_index_in_range, but specified in terms of the jump and its
+   target. *)
+ if orig_target > 0 then
+ choose_nice_jump_island_index_in_range acts i (i+orig_target+1) true
+ else
+ choose_nice_jump_island_index_in_range acts (i+orig_target+1) i false
+ in let split_jump acts i =
+ (* Splits the jump in "acts" at index "i" by inserting a jump island partway to
+   the destination. Returns true if it was able to place it outside of any
+   nested functions, or false if it had to place it within one or more. *)
+ let orig_target = get_jump_target (DynArray.get acts i) in (* original jump target *)
+ let (nice, island_index) = match choose_nice_jump_island_index acts i orig_target with
+ None ->
+ (* There is no nice spot to put an island, so just put it in the middle.
+   (This happens if the jump goes across a function of size greater than
+   about 32 KiB.) *)
+ (false, (i + (i + orig_target + 1))/2)
+ | Some i ->
+ (* Use that. *)
+ (true, i)
+ (* For simplicity, we only insert one jump island--regardless of how many are
+   necessary--and leave insertion of additional ones up to the later
+   iterations (since the one we insert will itself be an overlength jump of
+   smaller size). *)
+ in insert_jump_island acts i orig_target island_index;
+ nice
+ in function acts ->
+ (* This is now the actual definition of eliminate_overlength_jumps. *)
+ let rec helper acts count bad_count =
+ let index = find_overlength_jump acts
+ in match index with
+ None ->
+ if count != 0 then prerr_endline ("Note: Jump island insertion successful with " ^ (string_of_int count) ^ " island(s) created" ^ (if bad_count = 0 then "." else " (at least " ^ (string_of_int bad_count) ^ " of them inefficient)."));
+ | Some i ->
+ if count = 0 then begin
+ prerr_endline ("Note: Bytecode sequence contains one or more overlength jumps; attempting jump island insertion.");
+ (* Flush stderr so that the user will always see the above message even if jump island insertion runs forever,
+   which can happen for pathological cases. *)
+ flush stderr
+ end;
+ let nice = split_jump acts i in
+ helper acts (count + 1) (if nice then bad_count else bad_count + 1)
+ in helper acts 0 0
+
+let support_overlength_classes = ref true
+
 let generate file out ~compress exprs =
  let file , linkage =
  (try
@@ -1331,9 +1586,21 @@
  generate_class_code ctx clctx (if !separate then Hashtbl.create 0 else hpackages);
  if !separate then tags := ("__Packages." ^ s_type_path (Class.path clctx),ctx.idents,ctx.ops) :: !tags;
  let size = ActionScript.actions_length ctx.ops in
- if size - ssize >= 1 lsl 15 then failwith ("Class " ^ s_type_path (Class.path clctx) ^ " excess 32K bytecode limit, please split it");
+ if size - ssize >= 1 lsl 15 then
+ begin
+ if !support_overlength_classes then
+ prerr_endline ("Warning: Class " ^ s_type_path (Class.path clctx) ^ " has 32 KiB or more of bytecode, which is not supported by older MTASC versions.")
+ else
+ failwith ("Error: Class " ^ s_type_path (Class.path clctx) ^ " has 32 KiB or more of bytecode; please refactor it or recompile without -32k-limit.");
+ eliminate_overlength_jumps ctx.ops
+ (* Note: It is possible here for the UInt16 parameters in (for example) function/try/catch/finally/with instructions to be overlength too.
+   However, we don't support dealing with that, since it should be way less common in real-world code than even overlength
+   classes, which are already very uncommon. For that same reason, we also don't bother to output nice error messages
+   in such a case; the user will just see an Overflow exception from IO.write_ui16. If we ever do want to check for overlength
+   UInt16's, though, this would be the spot to do it. *)
+ end;
  end;
- ) exprs;
+ ) exprs;
  if not !separate then tags := ("__Packages.MTASC",ctx.idents,ctx.ops) :: !tags;
  (match !(ctx.main) with
  | None ->
@@ -1558,6 +1825,7 @@
  ("-exclude",Arg.String (fun f -> exclude_file f),"<file> : exclude classes listed in file");
  ("-version",Arg.Int (fun n -> version := Some n),": change SWF version (6,7,8,...)");
  ("-trace",Arg.String (fun t -> ftrace := Some t),"<function> : specify a TRACE function");
+ ("-32k-limit",Arg.Unit (fun () -> support_overlength_classes := false),": treat overlength classes (>= 32 KiB of bytecode) as an error");
 ]
 (fun t ->
  if !keep && !header <> None then failwith "-keep cannot be used together with -header";


--
MTASC : no more coffee break while compiling

Re: Re: MTASC has been forked, perhaps you would like to update?

by bomberstudios :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I say +1 for Github.


--
Ale Muñoz
http://sofanaranja.com
http://bomberstudios.com

--
MTASC : no more coffee break while compiling

Re: Re: MTASC has been forked, perhaps you would like to update?

by jean-michel fan_de_teamspeak :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

very happy for  further improvments on mtasc


2009/11/23 Tristan Schmelcher <tschmelcher@...>
I'd be fine with moving to Github if there's interest in further MTASC development. I'll contact the HAMTASC list and see.

I've finally gotten around to releasing a source archive on the SF site, and attached the two patches here taken right from svn diff. patch -p0 < FILE should work.

(Paul: the Flash 9 support will require a small packaging change, in that there is a new "std9" directory that must be shipped in the same way as the std and std8 directories.)

2009/11/13 Luke Bayes <lbayes@...>
I could be wrong, but I'm pretty sure Git works fine on Windows.

For whatever it's worth, I also vote for Github.

Having managed a handful of moderately successful open source projects
on Sourceforge over the past 8 years, I've never seen anything close
to the quantity or quality of contributions that we've seen from
Github in the past 12 months. They're not even close to equivalent
systems.

Github encourages and facilitates contribution while Sourceforge
actively inhibits it. And don't get me started on the spammy
SourceForge download pages.


Luke Bayes
http://asunit.org
http://projectsprouts.org


--
MTASC : no more coffee break while compiling



--
http://jeanmichel.gens.free.fr

--
MTASC : no more coffee break while compiling