TweetFollow Us on Twitter

LS FORTRAN 2.0
Volume Number:6
Issue Number:3
Column Tag:Jörg's Folder

Language Systems FORTRAN 2.0

By Jörg Langowski, MacTutor Editorial Board

“Language Systems FORTRAN 2.0”

A new version of the Languages Systems FORTRAN for MPW has just arrived here. Version 2.0 has been improved a lot compared to the previous version - not that version 1.2.1 wasn’t already a very good product. I’d like to give a short overview and some code examples in this month’s column, so that you can appreciate the ease with which Fortran application can now be created on the Mac, or ported from a mainframe to the Mac.

But first of all, a figure that might be very important for many of you Fortran users: the new compiler runs the Whetstone benchmark at 1072 K whetstones/sec (Language Systems FORTRAN 2.0, opt=3, MacIIx) instead of the 425 K whetstones/sec that the version 1 compiler produced. The optimizer now actually works, and depending on the type of the code there can be very significant speed differences from one optimization level to the other. The matrix multiplication benchmark that I described in the V5#8 column, now runs in 2.66 seconds (opt=3, MacIIx) instead of 6.52 seconds (145% faster), if you don’t take the constant index expression out of the loop; or in 2.55 instead of 4.65 seconds (82% faster), if the common subexpression elimination is done by hand on the source code. Thus - at least for these cases - LS Fortran produces code that is now even faster that MPW Pascal’s code, and significantly faster than the same Fortran code on a MicroVAX II.

Built-in Mac interface to FTN programs

The Macintosh interface to Fortran programs has been extensively improved and simplified. It has always been possible to create a typical Macintosh application around a central event loop with mouse down, update and activate handlers etc. entirely in Fortran, and there is a Multifinder-compatible sample Fortran application on the Examples disk. But this is not what the typical Fortran user would have in mind when porting a functioning application from a mainframe to the Mac. Rather, one would like to conserve most of the existing Fortran code and add to it the ease of use of the Macintosh, without having to write a whole new user interface around it.

With the new LS Fortran, such an operation is extremely easy, as long as your program is well-written, i.e., sufficiently modular. There are enough examples of GOTO-clobbered spaghetti code with 25-page long subroutines that I wouldn’t wish my worst enemy having to adapt to a new machine, but as long as you can cut up your code into distinct routines that each fulfil a defined task and then return to a main program, porting the program to the Macintosh becomes child’s play.

To achieve this, Language Systems have expanded on a feature of their system: namely, that a LS Fortran program does not immediately exit to the Finder after the END statement, but returns into a run time system that lets you edit, save or print the output window. The new compiler version allows the user to add new menus and menu items to the menu bar that is drawn after exit from the main program. Each of the menu items can be assigned a pointer to a subroutine that will be executed when the menu is selected. Control returns to the Fortran run time system when the subroutine finishes; there, a new menu selection may be made, either from the default Fortran File, Edit, and Fonts menus, or from any added user menus.

Furthermore, a routine has been added that gives the Fortran program access to the menu items in the Fortran run time menu bar. For instance, to quit to the Finder immediately at the end of a program - instead of keeping the editable output window and the menus available - all you need to do is

CALL DoMenu(‘File’,’Quit’)

at the end of your main program.

The example - a simple graphics display program

Using the new menu features, the Fortran program will be structured in such a way that the main program only does data, window, etc. initialization and sets up the user menus, while the actual work is done by subroutines that are invoked through menu selections. Listing 1 gives an example of such a program, a simple facility to read a file with consecutive lines of x/y coordinate pairs and to plot the corresponding graph in various ways in a graphics window.

Furthermore, one of the subroutines (Listing 2) is written in Pascal and illustrates the possibility of passing parameters either through the procedure’s parameter list or through accessing Fortran’s COMMON data directly.

You’ll notice that two new Fortran compiler directives appear at the beginning of the program. The compiler directive !!G Toolbox.finc is used to load a precompiled ‘global include’ file that contains toolbox variable, structure and parameter definitions. This speeds up recompiling a program considerably if you use lots of toolbox definitions. Global include files can be created to the needs of each individual program, including only those definitions used in the code; or one can simply create one file that contains all the definitions. In the latter case, compiling takes only slightly longer.

Just as the directive !!M Inlines.f was used in version 1.2.1 to make the trap definitions known to the compiler, we can now use !!MP Inlines.f to simplify the calling mechanism. In the latter case, all trap routines are automatically declared as PEXTERNAL, which means that parameter will be passed by value rather than by reference (the Fortran default). This allows you to write

 call SetRect  (%ref(myRect),
 1 int2(20),int2(40),int2(500),int2(235))

rather than

C 1

 call SetRect  (myRect,
 1 %val(int2(20)),%val(int2(40)),
 2 %val(int2(500)),%val(int2(235)))

as you would have to do when call-by-reference is the default. Since toolbox calls receive a great number of their parameters by value, this saves a lot of writing and makes the program much more readable. Of course, the old directive !!M Inlines.f is still available. You may now also declare any other subroutine PEXTERNAL, and further CALLs to that routine will use Pascal calling conventions.

Fortran subroutines may also be declared to receive some of their arguments by value; you write, in the subroutine definition,

C 2

SUBROUTINE XX(A,B,%VAL(I)),

and the routine will expect the value of I on the stack, not its address. This can be important for writing certain filter procedures that are called by toolbox routines.

The Main Program

The main program will first move the Fortran output window to the bottom of the (Mac+) screen, then set up the user menu with its items and their corresponding subroutines. Routines which are not defined in the same source file must of course be declared EXTERNAL (or PEXTERNAL or CEXTERNAL). OutWindowClear, which erases the Fortran output window, is such a case.

After the calls to AddMenuItem, we type a blank line (type *) to have at least one reference to the window output routines in the main program, and thus create the output window. Thereafter, a graphics output window is created.

We must call DoMenu at least once before the main program exits if we want to modify some of the user menu items, for instance set a check mark. Since the menu bar is not created before the main program exits or DoMenu is called, any calls to CheckItem, SetItem, etc. won’t have an effect before.

One line - commented out in the example - calls a routine that was undocumented in the version of the manual that I received (thanks, Claudia Vaughan from Language Systems, for the information!): SetIdleProc receives a pointer to a routine that will be called regularly from the Fortran run time system’s main event loop. Here, that routine would just beep once (that’s why I commented it out in the final version). SetIdleProc could be used to do background calculations or refresh graphics windows, since the present system does not allow to associate update routines with windows, unless the complete event loop is rewritten in Fortran.

File access through the SF dialog

The routine that reads in the data, readData, shows a non-standard extension that LS has made to the Fortran OPEN statement:

C 3

open(unit, file=*, status=’OLD’)

will display the standard file dialog for opening a file and assign the selected file to the Fortran unit number;

C 4

open(unit, file=*, status=’NEW’)

of course, will display the ‘Save File’ dialog and have the user input the file name. The actual file name, if needed, can be obtained through the Fortran INQUIRE statement. By default, files are of type ‘TEXT’, creator ‘MPS ‘; this can be changed through the keywords CREATOR and FILETYPE in the Open statement. The latter keyword also changes the files displayed in the ‘Open File’ dialog.

Many other keywords have been added to the Open statement, some of which have no effect at all, but ensure compatibility with other Fortran dialects (e.g. VAX) that use them.

Cross-language calling and COMMON access

Most of the remaining routines which display the data, play around with the output windows, and change some parameters, require no comment; However, I added one subroutine which calls a Pascal procedure, which in turn accesses the Fortran COMMON.

Calling a Pascal procedure from Fortran is easy; you simply declare the routine PEXTERNAL and pass the parameters in the same order as in the Pascal declaration. The default parameter passing is by value, references to variables can be passed by writing %ref(param). The Pascal procedure (Listing 2) receives a window pointer and a string, and displays the string in the window.

The window pointer - in our particular example - is also accessible through a named COMMON block, /windows/. The old LS Fortran allocated common memory dynamically, i.e., when a common block was first used, a heap object of the size of the common was created. This method still exists in Fortran 2.0; if you compile a program with the -dyn option, common blocks are created dynamically on the heap. However, with MPW 3.0 it is possible to use the linker for keeping static common blocks in the global data area. Fortran 2.0 programs compiled under MPW 3.0 will automatically static commons, unless you use the -dyn option.

The -f option in the MPW Link command causes the linker to treat duplicate definitions of a global data block as references to the same data block; thus, common blocks from different modules that have the same name will be automatically mapped onto each other.

All we need to do to access a static Fortran common from Pascal is to create a global variable with ‘the same name’ as the common block (thanks, Claudia Vaughan, again). ‘The same name’ has a particular meaning: Fortran names are uppercased for the linker, and COMMON names are enclosed between underscores; thus, the /windows/ common block is called _WINDOWS_ in the link map. The Pascal routine must define a global variable named _WINDOWS_, and the compiler must be told by the {$J+} directive that global variables may be defined externally. We define _WINDOWS_ as a global Pascal record having the same fields as the common block in the Fortran program, so that all common variables can be accessed conveniently through the fields of the record.

The Fortran version that I used still had some problems with dynamic commons, so that I couldn’t try out the old strategy to access COMMONs from Pascal using the run time library routine COMMONADDRESS; dynamic Fortran handling will work in the released version, as LS assured me.

More extensions

Language Systems have gone to great lengths to make sure compatibility of their Fortran with most mainframe implementations, notably VAX Fortran. Apart from the extensions I already mentioned, you can now omit arguments from subroutine calls (an integer*4 zero is pushed on the stack for each omitted argument), you can initialize data in the type declaration (real*4 x/4.0/ is a legal construct), BYTE may be used instead of INTEGER*1, and all the VAX keywords in I/O statements are recognized as syntactically legal. NAMELIST and ENCODE/DECODE also have the same syntax as on the VAX. Even the IOSTAT error codes have been changed to be equal to the corresponding VAX error numbers, where applicable.

What this means in practice is that you can take almost any code that runs on a VAX, feed it unchanged to the Language Systems compiler, and it will not just swallow it without complaints, but in most cases produce an application that produces the same result as the VAX program. In fact, the efforts for VAX compatibility have been extended to the point where Language Systems is encouraging third-party developers to create libraries that emulate VAX system calls, which would make the compatibility even closer.

I’d like to conclude with some remarks on the excellent manual; its format has been changed, starting with general remarks on how to get a Fortran program to run under MPW, and putting the formal language definitions to the end of the text. The MPW introduction has obviously been written by someone who exactly understands the difficulties that the average mainframe Fortran person would have dealing with such a bizarre object as the Macintosh and MPW running on it. I quote: “Using the Directory command. Type the line DIRECTORY. Then press the enter key (not the return key).” Just one example (there are many more) for the attention that the manual writer has given to the details.

In summary, the Fortran that combines ease of porting from mainframes with easy user interface creation, full Toolbox access and speed seems to have finally arrived. Expect to hear more of it later. We’ll continue next month with C++, and even some Forth again (!). Till then.

Listing 1: 
 program Plot
c(c) J. Langowski/MacTutor Jan. 1990
cexample that uses some of the new features of
cLanguage Systems Fortran 2.0 for MPW
csome of the lines might have been split by editing

!!G Toolbox.finc
!!MP Inlines.f

 real*4 x(500),y(500)
 integer*4 ndata,plotType,nil
 parameter (nil=0)
 record /WindowPtr/ wPtr  
 common /windows/ wPtr
 common /theData/ x,y,ndata,plotType
 
 record /Rect/ myRect
 string title
 external OutWindowClear,MyIdleProc
 
 call MoveOutWindow (20,260,500,342)
 
 call addmenuitem (‘Graph’,’Read ’,readData)
 call addmenuitem (‘Graph’,’Display Graph’,plotGraph)
 call addmenuitem (‘Graph’,’Erase Graph’,clearGraph)
 call addmenuitem (‘Graph’,’Hide Graph’,hideGraph)
 call addmenuitem (‘Graph’,’Erase Text’, OutWindowClear)
 call addmenuitem (‘Graph’,’(-’,dummy)
 call addmenuitem (‘Graph’,’By item #’,byItem)
 call addmenuitem (‘Graph’,’By x value’,byXval)
 call addmenuitem (‘Graph’,’(-’,dummy)
 call addmenuitem (‘Graph’,’Draw a string’, DrawAString)
 call addmenuitem (‘Graph’,’Sort data’,sortData)
 
 type * ! shows text output window
 
 title = ‘Graphics Window’
 call SetRect (%ref(myRect),int2(20),int2(40), int2(500),int2(235))

 wPtr.wp = NewWindow (nil,myRect,title,int2(.true.),
 1 noGrowDocProc,nil,int2(.false.),int4(0))
 
 call DoMenu (‘Graph’,’By item #’)
cinitializes plot flag & sets check mark
 
ccall SetIdleProc(MyIdleProc)
 
 end
 
 subroutine MyIdleProc
 call sysbeep(1)
 return
 end
 
 subroutine dummy
 return
 end  
 
 subroutine readData
 real*4 x(500),y(500)
 integer*4 ndata,plotType,iores
 common /theData/ x,y,ndata,plotType
 
 open (10,file=*,status=’OLD’,iostat=iores)
 
 if (iores.eq.0) then
 ndata = 0
 do while (iores.eq.0)
 ndata = ndata + 1
 read (10,*,iostat=iores) x(ndata),y(ndata)
 end do
 
 if (iores .lt. 0) then
 type *,ndata,’ points read.’
 else
 type *,’Read error - nothing read.’
 end if
 close (unit=10)
 
 end if
 return
 end
 
 subroutine plotGraph
 record /WindowPtr/ wPtr  
 common /windows/ wPtr
 
 real*4 x(500),y(500)
 real*4 maxx,minx,maxy,miny,deltax,deltay
 integer*2 xplot,yplot,winh,winw
 integer*4 ndata,plotType
 common /theData/ x,y,ndata,plotType
 
 call ShowWindow(wPtr)
 call SelectWindow(wPtr)
 maxx = x(1)
 minx=maxx
 maxy=y(1)
 miny=maxy
 
 do i=2,ndata
 maxx = max(x(i),maxx)
 minx = min(x(i),minx)
 maxy = max(y(i),maxy)
 miny = min(y(i),miny)
 end do
 
ctype *,minx,maxx,miny,maxy
 
 deltax = maxx-minx
 deltay = maxy-miny
 winh = wPtr.wp^.portRect.bottom - wPtr.wp^.portRect.top - 4
 winw = wPtr.wp^.portRect.right  - wPtr.wp^.portRect.left - 4
 
ctype *,deltax,deltay,winh,winw
 
 call SetPort(wPtr)
 call PenNormal
 call MoveTo(int2(0),int2(0))
 
 do i=1,ndata
 yplot = winh*(1.-(y(i)-miny)/deltay) + 2
 select case (plotType)
 case (0)
 xplot = winw*(i/(ndata*1.)) + 2
 case (1)
 xplot = winw*(x(i)-minx)/deltax + 2
 case default
 end select
 call lineto(xplot,yplot)
 end do
 return
 end
 
 subroutine clearGraph
 record /WindowPtr/ wPtr  
 common /windows/ wPtr
 
 call SetPort(wPtr)
 call EraseRect(wPtr.wp^.portRect)
 return
 end
 
 subroutine hideGraph
 record /WindowPtr/ wPtr  
 common /windows/ wPtr
 
 call HideWindow(wPtr)
 return
 end
 
 subroutine byItem
 real*4 x(500),y(500)
 integer*4 ndata,plotType
 common /theData/ x,y,ndata,plotType
 record /MenuHandle/ GraphMenu

 integer*2 menuGraph,itemNum,xVal
 parameter(menuGraph=5,itemNum=7,xVal=8)
 
 plotType = 0
 GraphMenu.MenuH = GetMHandle(menuGraph)
 call CheckItem(GraphMenu.MenuH, itemNum,int2(.true.))
 call CheckItem(GraphMenu.MenuH,xVal,int2(.false.))
 return
 end  
 
 subroutine byXval
 real*4 x(500),y(500)
 integer*4 ndata,plotType
 common /theData/ x,y,ndata,plotType
 record /MenuHandle/ GraphMenu

 integer*2 menuGraph,itemNum,xVal
 parameter(menuGraph=5,itemNum=7,xVal=8)
 
 plotType = 1
 GraphMenu.MenuH = GetMHandle(menuGraph)
 call CheckItem(GraphMenu.MenuH, itemNum,int2(.false.))
 call CheckItem(GraphMenu.MenuH,xVal,int2(.true.))
 return
 end
 
 subroutine drawAString
 string st
 record /WindowPtr/ wPtr  
 common /windows/ wPtr
 pexternal DrawMyString
 
 st = ‘This String comes from Fortran.’
 call DrawMyString(wPtr,st)
 return
 end
 
 subroutine sortData
 
 call AlertBox (‘Not implemented yet.’)
 return
 end
Listing 2
{$J+}
 { This directive tells linker to externalize global variable references 
so that the static common /WINDOWS/ is made known to the Pascal routine. 
Its name in the linker symbol table is _WINDOWS_; thus our variable must 
have that name. }
unit PasSub;
interface
uses MemTypes, QuickDraw, OSIntf, ToolIntf, Traps;
procedure DrawMyString (wp:WindowPtr; st:Str255);
implementation
 
type  commonWind =  record
 wp:WindowPtr
 end;

var_WINDOWS_ : commonWind;

procedure DrawMyString (wp:WindowPtr; st:Str255);
varmyStr : Str255;
begin
 SetPort(wp);
 PenNormal; MoveTo(50,50);
 TextFont(Monaco); TextSize(12);
 DrawString(st);
 
 SetPort(_WINDOWS_.wp);
 PenNormal; MoveTo(50,100);
 TextFont(Geneva); TextSize(12);
 DrawString(‘The COMMON can also be 
 accessed through Pascal.’);
end;
end.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Posterino 3.3.6 - Create posters, collag...
Posterino offers enhanced customization and flexibility including a variety of new, stylish templates featuring grids of identical or odd-sized image boxes. You can customize the size and shape of... Read more
Together 3.8.3 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Features Smart storage. With simple drag-and-drop... Read more
iClock Pro 3.4.9 - Customize your menuba...
iClock Pro is a menu bar replacement clock for Apple's default clock. iClock Pro is an update, total rewrite and improvement to the popular iClock. Have the day, date and time in different fonts and... Read more
Things 2.8.12 - Elegant personal task ma...
Things is a task management solution that helps to organize your tasks in an elegant and intuitive way. Things combines powerful features with simplicity through the use of tags and its intelligent... Read more
Typinator 7.2 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Spotify 1.0.53.758. - Stream music, crea...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
beaTunes 4.6.14 - Organize your music co...
beaTunes is a full-featured music player and organizational tool for music collections. How well organized is your music library? Are your artists always spelled the same way? Any R.E.M. vs REM?... Read more
Vienna 3.1.10 :d05d7a5d: - RSS and Atom...
Vienna is a freeware and Open-Source RSS/Atom newsreader with article storage and management via a SQLite database, written in Objective-C and Cocoa, for the OS X operating system. It provides... Read more
Day One 2.1.8 - Maintain a daily journal...
Day One is the easiest and best-looking way to use a journal / diary / text-logging application for the Mac. Day One is well designed and extremely focused to encourage you to write more through... Read more
iDefrag 5.1.8 - Disk defragmentation and...
iDefrag helps defragment and optimize your disk for improved performance. Features include: Supports HFS and HFS+ (Mac OS Extended). Supports case sensitive and journaled filesystems. Supports... Read more

Latest Forum Discussions

See All

Fantasy MMORPG MU Origin adds new modes,...
MU Origin, Webzen’s highly popular fantasy MMORPG is getting ready to shake things up for the second time this year, as a new update makes its way to the Google Play and App Store from today. Introducing new systems, modes, and events, the land of... | Read more »
Blizzard is looking to hire a mobile dev...
A new thread on the popular video game rumor forum, NeoGAF, uncovered an interesting job listing over at Blizzard Entertainment. It appears the studio behindStarCraft, World of WarCraft, Hearthstone,andOverwatch is looking to bring on a new hire... | Read more »
Legend of Zelda meets Cooking Mama in ne...
Dungeon Chef is what happens when you mix the RPG elements (and style) of a Legend of Zelda game, with cooking elements. Although, now that The Legend of Zelda: Breath of the Wild also has cookingelements, so maybe the gameplay is not so novel.... | Read more »
ChordFlow (Music)
ChordFlow 1.0.0 Device: iOS Universal Category: Music Price: $6.99, Version: 1.0.0 (iTunes) Description: ChordFlow is a chord sequencer with a unique 4-track polyphonic arpeggiator, extensive chord library, MIDI out and Ableton Link... | Read more »
The Walking Dead: A New Frontier is out...
The newest season of Telltale Games'The Walking Dead is well underway. After the release of the third episode, "Above the Law" about a month ago, episode four, "Thicker Than Water" is hot and ready for more zombies and gut-wrenching emotional... | Read more »
Best games we played this week
Another week, another new wave of mobile games do dive into. We've dug through the list of apps that came out this week to tell you which apps are worth your sweet time. And while there weren't too many games this week, there were some big ones.... | Read more »
Vignettes (Games)
Vignettes 1.0.1 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.1 (iTunes) Description: Vignettes is a casual but unique exploration game without text or characters, where objects shapeshift as you spin them around... | Read more »
Get Me Outta Here is an 80s retro shoote...
Are you ready to fight some aliens? Because Crescent Moon Games has released the retro shooter Get Me Outta Here on iOS devices today. [Read more] | Read more »
Get a bunch of Apple productivity apps f...
If you're an Apple Mac owner, you're probably aware of the host of Apple productivity apps the company includes in all new Mac purchases. Apps like iMovie, Keynote, and of course, GarageBand. While you used to be able to also buy these apps... | Read more »
Terra Mystica (Games)
Terra Mystica 1.03 Device: iOS Universal Category: Games Price: $9.99, Version: 1.03 (iTunes) Description: Short Summary:≈≈≈≈≈≈≈≈≈≈≈≈≈ | Read more »

Price Scanner via MacPrices.net

HyperX Ships Pulsefire FPS Gaming Mouse, Winn...
Your reporter is a longtime fan of gaming mice for general purpose coomnputing use, finding them typically superior in comfort and performance. HyperX, a division of Kingston Technology Company, Inc... Read more
Penske Truck Leasing Unveils “Penske Fleet” M...
Penske Truck Leasing has introduced a free mobile app called “Penske Fleet” to benefit its full-service truck leasing and contract maintenance customers. The mobile app enables Penske’s customers to... Read more
DEVONthink To Go 2.1.3 For iOS Adds New Declu...
DEVONtechnologies has updated DEVONthink To Go, its iOS companion to DEVONthink for Mac. Enhancements and bug fixes in Version 2.1.3 include DEVONtechnologies’ new decluttering service for clipping... Read more
Use Apple’s Education discount to save up to...
Purchase a new Mac or iPad using Apple’s Education Store and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free: -... Read more
Apple refurbished Apple Watches available sta...
Apple is now offering Certified Refurbished Series 1 and Series 2 Apple Watches for 14-16% off MSRP, starting at $229. An Apple one-year warranty is included with each watch. Shipping is free: Series... Read more
15-inch Touch Bar MacBook Pros, Apple refurbi...
Apple is offering Certified Refurbished 2016 15″ Touch Bar MacBook Pros for $360 to $420 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2.6GHz... Read more
13-inch MacBook Airs on sale for up to $150 o...
Overstock.com has 13″ MacBook Airs on sale for up to $150 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $869.99 $130 off MSRP - 13″ 1.6GHz/256GB MacBook Air (sku... Read more
15-inch Touch Bar MacBook Pros on sale for $1...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $200 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more
15-inch 2.7GHz Touch Bar MacBook Pros on sale...
Amazon has 2016 15″ 2.7GHz Apple Touch Bar MacBook Pros in stock today and on sale for $150-$200 off MSRP. Shipping is free: - 15″ 2.7GHz Touch Bar MacBook Pro Space Gray (sku MLH42LL/A): $2599 $200... Read more
Apple now offering Certified Refurbished 13-i...
Apple is now offering Certified Refurbished 2016 13″ Touch Bar MacBook Pros for $270-$300 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 13″ 2.9GHz... Read more

Jobs Board

Music Marketing Lead, iTunes & *Apple*...
# Music Marketing Lead, iTunes & Apple Music Job Number: 56868140 Culver City, California, United States Posted: Apr. 17, 2017 Weekly Hours: 40.00 **Job Summary** Read more
Best Buy *Apple* Computing Master - Best Bu...
**498001BR** **Job Title:** Best Buy Apple Computing Master **Location Number:** 000356-Manassas-Store **Job Description:** **What does a Best Buy Apple Read more
*Apple* Mac Computer Technician - GeekHampto...
…complex computer issues over the phone and in person? GeekHampton, Long Island's Apple Premium Service Provider, is looking for you! Come work with our crew Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Music Marketing Lead, iTunes & *Apple*...
# Music Marketing Lead, iTunes & Apple Music Job Number: 56868140 Culver City, California, United States Posted: Apr. 17, 2017 Weekly Hours: 40.00 **Job Summary** Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.