Carrie (1976 film)

Template:Short description
Template:Use mdy dates

***Carrie*** is a 1976 American supernatural horror film directed by Brian De Palma from a screenplay written by Lawrence D. Cohen, adapted from Stephen King's 1974 epistolary novel of the same name. The film stars Sissy Spacek as Carrie White, a diffident 16-year-old who is consistently mocked and bullied at school. Her peers are unaware that she possesses telekinetic powers. The film also featured Piper Laurie, Amy Irving, Nancy Allen, William Katt, P. J. Soles, Betty Buckley, and John Travolta in supporting roles. It is the first film in the *Carrie* franchise.

The film was based on King's first novel by the same name. De Palma was intrigued by the story and pushed for the studio to direct it while Spacek was encouraged by her husband to audition. It is the first of more than 100 film and television productions adapted from, or based on, the published works of King.

*Carrie* was theatrically released on November 3, 1976, by United Artists. The film became a critical and commercial success, grossing over $33.8 million against its $1.8 million budget. It received two nominations at the 49th Academy Awards: Best Actress (for Spacek) and Best Supporting Actress (for Laurie).
It is widely cited by critics and audience members alike as the best adaptation of the novel amongst the numerous films and television shows based on the character, as well as one of the best films based on King's publications. The film has had a significant influence on popular culture. Several publications have regarded it as one of the greatest horror films ever made. In 2008, *Carrie* was ranked 86th on *Empire*'s list of The 500 Greatest Movies of All Time. It was ranked 15th on *Entertainment Weekly'*s list of the 50 Best High School Movies, and 46th on the *American Film Institute* list *AFI's 100 Years...100 Thrills*. The film's prom scene has had a major influence on popular culture and was ranked eighth on *Bravo*'s 2004 program *The 100 Scariest Movie Moments*.

## Plot

Carrie White is a shy 16-year-old girl who lives with her fanatically religious mother Margaret. Carrie is unpopular at school and is often ostracized by her peers. When Carrie experiences her first period in the school shower, she panics because she was never told of this process. Carrie's classmates humiliate her by throwing tampons and chanting "Plug it up" until the gym teacher, Miss Collins, intervenes. Following conversations with Miss Collins and the principal, Carrie is dismissed from school. After arriving home, Margaret considers Carrie's menstruation to be a manifestation of sinful sexual fantasies, and she locks Carrie in an altar-like "prayer closet" to pray for forgiveness. At school, Collins reprimands Carrie's tormentors and punishes them with a week-long after-school detention in gym class. Those who skip the punitive measure are suspended for three days and banned from the upcoming prom. Christine "Chris" Hargensen, a wealthy, popular girl who is Carrie's longtime bully and the leader of Carrie's classmates, walks out.

Chris plots vengeance against Carrie with her boyfriend Billy Nolan and her best friend Norma. They break into a local farm and kill pigs to drain their blood into a bucket, which they place above the school's main stage in the gymnasium. Norma, a prominent figure in the school's student council regime, plans to rig the Prom Queen election in Carrie's favor to get her on the stage. Meanwhile, Sue Snell, a deeply remorseful classmate, asks her handsome and popular boyfriend, Tommy Ross, to invite Carrie to prom. Carrie initially thinks the proposition is a prank, but he insists that it is genuine and she reluctantly accepts after being consoled by Miss Collins. Back at home, she begins to discover that she has the power of telekinesis as she shakes off her shyness. In spite of Margaret's cries of protest that Tommy is using her, Carrie puts on a flattering dress and hairstyle for the prom. Margaret sees Carrie's telekinetic powers and denounces her as a witch before Carrie leaves with Tommy.

During the prom, Chris and Billy hide under the stage while the other conspirators switch the ballots to ensure that Carrie wins the Prom Queen title. As Carrie stands onstage with Tommy, finally beginning to feel accepted by her peers, Chris pulls the rope attached to the bucket of pig blood and douses her. The empty bucket hits Tommy in the head, knocking him unconscious, and the crowd is left shocked and speechless at the prank as Chris and Billy sneak out. Carrie begins to hallucinate that everyone is mocking her, remembering her mother's claim that "they're all gonna laugh at you." In a sudden fit of rage, she uses her telekinesis to seal the exits from the gym and set it on fire, killing most of the attendees. Sue survives, having been thrown out of the prom by Miss Collins earlier, but watches as the students and teachers die. As Carrie walks home, Chris and Billy attempt to run her over with Billy's car, but Carrie senses their presence and kills them by causing their car to overturn and explode.

As Carrie scrubs herself clean at home, Margaret reveals that she was conceived after a rape by her drunken father, an act that Margaret shamefully admits she enjoyed. Saying that "sin never dies," Margaret comforts Carrie, then stabs her in the back with a kitchen knife and begins to chase her through the house. Carrie levitates several sharp implements and sends them flying toward Margaret, pinning her to a doorway and crucifying her. Carrie then incinerates the house with them still inside.

Some time later, Sue - the only survivor of the prom - struggles to deal with the trauma she has experienced. She has a nightmare in which she lays flowers on the charred remains of Carrie's home, with a "for sale" sign vandalized in red paint with the phrase "Carrie White burns in Hell!" Suddenly, Carrie's bloody arm reaches from beneath the rubble and grabs Sue's forearm. Sue wakes up screaming as her mother comforts her.

## Cast

Template:Div col

* Sissy Spacek as Carrie White
* Piper Laurie as Margaret White
* Amy Irving as Sue Snell
* William Katt as Tommy Ross
* Betty Buckley as Miss Collins
* Nancy Allen as Chris Hargensen
* John Travolta as Billy Nolan
* P. J. Soles as Norma Watson
* Sydney Lassick as Mr. Fromm
* Stefan Gierasch as Principal Morton
* Priscilla Pointer as Eleanor Snell
* Edie McClurg as Helen Shyres
* Michael Talbott as Freddy
* Cindy Daly as Cora
* Deirdre Berthrong as Rhonda
* Harry Gold as George
* Noelle North as Frieda
* Doug Cox as The Beak
* Anson Downes as Ernest

Template:Div col end

### Development

*Carrie* was the first Stephen King novel to be published and the first to be adapted into a feature film. In an interview in Port Charlotte, Florida at a public appearance near his home on the Gulf coast on March 20, 2010, King said he was 26 years old at the time and was paid just $2,500 for the film rights, but added, "I was fortunate to have that happen to my first book." De Palma told *Cinefantastique* magazine in an interview in 1977:

“*I read the book. It was suggested to me by a writer friend of mine. A writer friend of his, Stephen King, had written it. I guess this was almost two years ago [circa 1975]. I liked it a lot and proceeded to call my agent to find out who owned it. I found out that nobody had bought it yet. A lot of studios were considering it, so I called around to some of the people I knew and said it was a terrific book and I'm very interested in doing it. Then nothing happened for, I guess, six months.*”
―{{{2}}}

Lawrence D. Cohen was hired as the screenwriter, and produced the first draft, which had closely followed the novel's intentions. United Artists accepted the second draft but only allocated De Palma a budget of $1.6 million, a small amount considering the popularity of horror films at the time. The budget eventually rose to $1.8 million. Certain scripted scenes were omitted from the final version, mainly due to financial limitations.

### Casting

Many young actresses auditioned for the lead role, including Melanie Griffith. Sissy Spacek was persuaded by husband Jack Fisk to audition for the title role. Fisk then convinced De Palma to let her audition, and she read for all of the parts. De Palma's first choice for the role of Carrie was Betsy Slade, who received good notices for her role in the film *Our Time* (1974). Determined to land the leading role, Spacek backed out of a television commercial she was scheduled to film, rubbed Vaseline into her hair, left her face unwashed, and arrived for her screen test clad in a sailor dress which her mother had made her in the seventh grade, with the hem cut off, and was given the part.

Nancy Allen was the last to audition, and her audition came just as she was on the verge of leaving Hollywood. She and De Palma later married.

### Filming

De Palma began with director of photography Isidore Mankofsky, who was eventually replaced by Mario Tosi after conflict between Mankofsky and De Palma ensued. Gregory M. Auer, assisted by Ken Pepiot, served as the special effects supervisor for *Carrie*, with Jack Fisk, Spacek's husband, as art director.

The White house was filmed in Santa Paula, California. To give the house a Gothic theme, the director and producers visited religious souvenir shops to find artifacts to decorate the set location.

A wraparound segment at the beginning and end of the film was scripted and filmed, which featured the Whites' home being pummeled by stones that hailed from the sky. The opening scene was filmed as planned, though on celluloid, the tiny pebbles looked like rain water. A mechanical malfunction botched filming the night when the model of the Whites' home was set to be destroyed by stones, so the filmmakers burned it down instead and deleted the scenes with the stones altogether. The original opening scene is presumed lost.

The final scene, in which Sue reaches toward Carrie's grave, was shot backwards to give it a dreamlike quality. This scene was inspired by the final scene in *Deliverance* (1972). Rather than let a stunt double perform the scene underground, Spacek insisted on using her own hand in the scene, so she was positioned under the rocks and gravel. De Palma explains that crew members "had to bury her. Bury her! We had to put her in a box and stick her underneath the ground. Well, I had her husband [Fisk] bury her because I certainly didn't want to bury her."

### Music

The score for *Carrie* was composed by Pino Donaggio. In addition, Donaggio scored two pop songs ("Born to Have It All" and "I Never Dreamed Someone Like You Could Love Someone Like Me") with lyrics by Merrit Malloy for the early portion of the prom sequence. These songs were performed by Katie Irving (sister of Amy Irving and daughter of Priscilla Pointer). Donaggio would work again with De Palma on *Home Movies*, *Dressed to Kill*, *Blow Out*, *Body Double*, *Raising Cain*, *Passion*, and *Domino*.

The soundtrack album was originally released on vinyl in 1976 from United Artists Records. A deluxe CD edition containing a few tracks of dialogue from the film was released by Rykodisc in 1997, and a 2005 CD re-release of the original soundtrack (minus dialogue) was available from Varèse Sarabande. In 2010, Kritzerland Records released all 35 cues of Donaggio's score for the film on a two-disc CD set which was presented as the complete score. Also included in this edition were the versions of "Born to Have It All" and "I Never DreamedTemplate:Nbsp..."which were heard in the film, as well as instrumentals of both songs, and hidden at the end of the final track, a version of the "Calisthenics" cue with Betty Buckley's studio-recorded voice-over from the detention scene. The second disc was a remastered copy of the original 13-track album. The Kritzerland release was a limited edition of 1,200 copies. Kritzerland rereleased the first disc as "The Encore Edition" in February 2013; this release was limited to 1,000 copies.

## Release

The film opened November 3, 1976 in 17 theaters in the Washington D.C.-Baltimore area. Two days later it opened in 9 theaters in Chicago, before opening in 53 theaters in New York City on November 16 and in Los Angeles on November 17.

## Reception and legacy

*Carrie* received widespread critical acclaim and was cited as one of the best films of the year. The review aggregator Rotten Tomatoes gives the film an approval rating of 92% based on 66 reviews, with an average rating of 8.3/10. The website's critical consensus reads, "*Carrie* is a horrifying look at supernatural powers, high school cruelty, and teen angst—and it brings us one of the most memorable and disturbing prom scenes in history." On Metacritic, which assigns a normalized rating based on reviews, the film has a weighted average score of 85 out of 100, based on 14 critics.

Roger Ebert of the *Chicago Sun-Times* stated the film was an "absolutely spellbinding horror movie", as well as an "observant human portrait", giving three and a half stars out of four. Pauline Kael of *The New Yorker* stated that *Carrie* was "the best scary-funny movie since *Jaws*—a teasing, terrifying, lyrical shocker." *Take One Magazine* critic Susan Schenker said she was "angry at the way *Carrie* manipulated me to the point where my heart was thudding, and embarrassed because the film really works." A 1998 edition of *The Movie Guide* stated *Carrie* was a "landmark horror film", while Stephen Farber prophetically stated in a 1978 issue of *New West Magazine*, "it's a horror classic, and years from now it will still be written and argued about, and it will still be scaring the daylights out of new generations of moviegoers." Quentin Tarantino placed *Carrie* at number 8 in a list of his favorite films ever.

In a 2010 interview, King replied that he thought, although dated now, *Carrie* was a "good movie."

Nevertheless, the film was not without its detractors. Andrew Sarris of *The Village Voice* commented, "There are so few incidents that two extended sequences are rendered in slow-motion as if to pad out the running timeTemplate:Nbsp..." Gene Siskel of the *Chicago Tribune* gave the film two-and-a-half stars out of four and called it "a crude shocker with a little style," praising the "strong performances" but opining that the movie "falls apart" during the climax which he described as "crude and sloppy."

Template:Anchor

### Box office

*Carrie* was a box office success earning $14.5 million in theatrical rentals in the United States and Canada by January 1978 from a gross of $33.8 million. In its first 19 days from 60 markets, the film had grossed $3,882,827. Overseas, the film earned rentals of $7 million for a worldwide total of $22 million.

### Accolades

*Carrie* is one of the few horror films to be nominated for multiple Academy Awards. Spacek and Laurie received nominations for Best Actress and Best Supporting Actress awards, respectively. The film also won the grand prize at the Avoriaz Fantastic Film Festival, while Spacek was given the Best Actress award by the National Society of Film Critics. In 2008, *Carrie* was ranked number 86 on *Empire Magazine*'s list of *The 500 Greatest Movies of All Time*. The movie also ranked number 15 on the *Entertainment Weekly* list of the 50 Best High School Movies, and No. 46 on the American Film Institute's list of 100 Greatest Cinema Thrills, and was also ranked eighth for its ending sequence on Bravo's *The 100 Scariest Movie Moments* (2004).

* AFI's 100 Years ... 100 Thrills – #46
* AFI's 100 Years ... 100 Heroes and Villains – Carrie White – Nominated Villain

## Related productions

*Main article: Carrie (franchise)*
*Carrie*, along with the novel, has been reproduced and adapted several times.

### Sequel

*Main article: The Rage: Carrie 2*
*The Rage: Carrie 2* was released in 1999. It featured another teenager with telekinetic powers who is revealed to have shared a father with Carrie White. The film received universally negative reviews and was a box office failure. Amy Irving reprises her role of Sue Snell from the previous film.

### 2002 television film

*Main article: Carrie (2002 film)*
In 2002, a television film based on King's novel and starring Angela Bettis in the titular role was released. The film updated the events of the story to modern-day settings and technology while simultaneously attempting to be more faithful to the book's original structure, storyline, and specific events. However, the ending was drastically changed: instead of killing her mother and then herself, the film has Carrie killing her mother, being revived via CPR by Sue Snell and being driven to Florida to hide. This new ending marked a complete divergence from the novel and was a signal that the film served as a pilot for a *Carrie* television series, which never materialized. In the new ending, the rescued Carrie vows to help others with similar gifts to her own. Although Bettis' portrayal of Carrie was highly praised, the film was cited by most critics as inferior to the original.

### 2013 film

*Main article: Carrie (2013 film)*
In May 2011, Metro-Goldwyn-Mayer and Screen Gems announced that *Carrie* would be adapted to film once more. Playwright Roberto Aguirre-Sacasa wrote the script as "a more faithful adaptation" of King's novel but shared a screenplay credit with the 1976 film's writer Lawrence D. Cohen. Aguirre-Sacasa had previously adapted King's epic novel *The Stand* into comic-book form in 2008.

The role of Carrie was played by 16-year-old actress Chloë Grace Moretz. Julianne Moore starred as Carrie's mother Margaret White, and Gabriella Wilde as Sue Snell. Alex Russell and Broadway actor Ansel Elgort played Billy Nolan and Tommy Ross respectively. Portia Doubleday was given the role of Chris Hargensen and Judy Greer was cast as Miss Desjardin.

Kimberly Peirce, known for her work on *Boys Don't Cry*, directed the new adaptation. It was released on October 18, 2013, and received mixed reviews.

### Stage productions

*Main article: Carrie (musical)*
A 1988 Broadway musical of the same name, based on King's novel and starring Betty Buckley, Linzi Hateley, and Darlene Love, closed after only sixteen previews and five performances. An English pop opera filtered through Greek tragedy, the show was so notorious that it provided the title to Ken Mandelbaum's survey of theatrical disasters, *Not Since Carrie: Forty Years of Broadway Musical Flops*.

Early in the 21st century, playwright Erik Jackson attempted to secure the rights to stage another production of *Carrie* the musical, but his request was rejected. Jackson eventually earned the consent of King to mount a new, officially sanctioned, non-musical production of *Carrie*, which debuted Off-Broadway in 2006 with drag queen Sherry Vine in the lead role. Similarly, many other *un*official spoofs have been staged over the years, usually with a gym teacher named "Miss Collins" (as opposed to the novel's "Miss Desjardin" and the musical's "Miss Gardner"), most notably the "parodage" *Scarrie the Musical*, which hit the Illinois stage in 1998 and was revived in 2005; Dad's Garage Theatre's 2002 production of *Carrie White the Musical*; and the 2007 New Orleans production of *Carrie's Facts of Life*, which was a hybrid of *Carrie* and the classic American sitcom *The Facts of Life*. A high school production of the musical is the focus of "Chapter Thirty-One: A Night to Remember" episode of *Riverdale*.

## Home media

*Carrie* was originally released on VHS and LaserDisc formats, for which it received numerous editions throughout the world.

In the United States and Canada, *Carrie* has been made available several times on DVD format from MGM Home Entertainment, debuting on September 29, 1998, while a "Special Edition" set was released on August 28, 2001. On December 4, 2007, the film was released a part of MGM's "Decades Collection," which included a soundtrack CD. The film was additionally released within multiple sets via MGM; first with *Carrie*, *The Rage: Carrie 2*, and *Carrie* (the 2002 television film) on January 18, 2011, and the second, as part of MGM's 90th anniversary, featured with *Misery* and *The Silence of the Lambs*.

The film was released for the first time on Blu-ray in the U.S. and Canada from MGM on October 7, 2008, which contained an MPEG-2 codec, with new DTS-HD 5.1 Master Lossless Audio, while retaining the original English Mono, and included Spanish Audio and French 5.1 Dolby Surround. The only special feature on the set is a theatrical trailer. The film was again released on Blu-ray on July 18, 2013, when it was available exclusively through Comic-Con in San Diego from MGM and FoxConnect, containing a slipcover with exclusive artwork. Two further editions were made available from MGM in 2014; a "Carrie 2-Pack" set containing the original film and the 2013 adaptation, released September 9, 2014, and finally, a re-issue Blu-ray with a collectible Halloween faceplate, on October 21, 2014. Home distribution rights are currently held by Shout Factory, and the film was released via their subsidiary label, Scream Factory on October 11, 2016, in a two-disc "Collector's Edition," now available with MPEG-4 coding, and a new 4K scan. Special features on the set include the theatrical trailer, *Carrie* franchise trailer gallery, new interviews with writer Lawrence D. Cohen, editor Paul Hirsch, actors Piper Laurie, P.J. Soles, Nancy Allen, Betty Buckley, William Katt, and Edie McClurg, casting director Harriet B. Helberg, director of photography Mario Tosi, and composer Pino Donaggio, "Horror's Hallowed Grounds" – Revisiting the Film's Original Locations, "Acting Carrie" featurette, "Visualizing Carrie" featurette, a look at "Carrie the Musical," TV spots, radio spots, still gallery, "Stephen King and the Evolution of Carrie" text gallery. The set also includes reversible sleeve containing original artwork and newly commissioned artwork from Shout Factory, and a slipcover containing the new artwork. On October 11, 2016, Shout Factory additionally released a "Deluxe Limited Edition" of 2000 copies, which includes the slipcover contained in the "Collector's Edition," with an additional poster matching the slipcover, and an alternative slipcover and poster consisting of different artwork.
In the United Kingdom, the film received its initial DVD release on February 1, 2000, via MGM. A reissue "Special Edition" DVD was made available from MGM on October 22, 2001, while a two-disc standard set was released on September 7, 2006. A DVD set, "The Carrie Collection," consisting of both the original film, and *The Rage: Carrie 2*, was released from 20th Century Fox Home Entertainment on October 7, 2013, while on the same day, a reissue DVD containing newly commissioned artwork, as well as the first-ever Blu-ray release in the UK was made available from 20th Century Fox. A second Blu-ray edition became available in the form of a steelbook, released on September 29, 2014; a set which reverted to the previous-style artwork.

On September 22, 2017, it was announced that *Carrie* would receive a "Limited Collector's Edition" Blu-ray of 5,000 copies from Arrow Films, providing the definitive release of the film. The set contained a new 4K restoration, with special features, including commentary by authors Lee Gambin and Alexandra Heller-Nicholas, recorded exclusively for the release; brand-new visual essay comparing the various versions and adaptations of *Carrie*; "Acting Carrie" featurette, "More Acting Carrie" featurette; "Writing Carrie," an interview with writer Lawrence D. Cohen/"Shooting Carrie," an interview with cinematographer Mario Tosi; "Cutting Carrie," an interview with editor Paul Hirsch/"Casting Carrie," an interview with casting director Harriet B. Helberg; "Bucket of Blood," an interview with composer Pino Donaggio; "Horror's Hallowed Grounds," a look back at the film's locations, gallery, trailer, TV spots, radio spots; *Carrie* trailer reel; and 60-page limited-edition booklet featuring new writing on the film by author Neil Mitchell, alongside reversible artwork, poster and art cards. The set was released on December 11, 2017.

On most of the later VHS releases and DVD sets, John Travolta's name was included on the artwork alongside Sissy Spacek. Although Travolta only appeared in a minor supporting role in the film, his name was featured to capitalize on his high-profile career in his many films following *Carrie*, therefore possibly increasing sales.

## References

1. ↑ *CARRIE* (X). *United Artists*. British Board of Film Classification (November 4, 1976). Retrieved on June 20, 2014.
2. ↑ 2.0 2.1 Carrie, Box Office Information. Retrieved on January 15, 2020.
3. ↑ Carrie Movie Review – Stephen King's Teen Horror Classic Carrie – the Movie. Classicfilm.about.com (April 10, 2012). Retrieved on October 2, 2012.
4. ↑ 4.0 4.1 Empire's 500 Greatest Movies of All Time. *Empire* (December 5, 2006). Retrieved on October 2, 2012.
5. ↑ 5.0 5.1 The 100 Scariest Movie Moments. bravotv.com. Archived from the original on July 19, 2006. Retrieved on August 6, 2006.
6. ↑ "How Carrie Changed Stephen King's Life, and Began a Generation of Horror", April 4, 2014.
7. ↑ 7.0 7.1 Stetson, Nancy (March 25–31, 2010). "King rules The Big read for a day in Port Charlotte". *Florida Weekly*: B8.  Newspaper column review of a live interview by Christy Arnold of King onstage at the Cultural Center of Charlotte County, Florida, March 20, 2010: "Although the film "Carrie" is dated now, he said he thought it was a good movie. 'I was fortunate to have that happen to my first book.' (He was 26 years old and was paid $2,500, he said.)"
8. ↑ 8.0 8.1 Brian De Palma interview (July 1977). Retrieved 30 June 2010.
9. ↑ 9.0 9.1 9.2 9.3 9.4 9.5 Template:Cite video
10. ↑ Neil Mitchell (5 August 2014). *Carrie*. Auteur Publishing, page 31. ISBN 978-1-906733-92-6.
11. ↑ "How Carrie: the Growing Pains of a Horror Classic", November 26, 2013.
12. ↑ Sissy Spacek Interviews – Cult Oddities. Retrieved on September 13, 2017.
13. ↑ Template:Cite video
14. ↑ "7 Months Enough for DePalma, Wife", April 28, 1996.
15. ↑ Brian De Palma.net. Retrieved May 27, 2007. --[[ ----------------------------------

Lua module implementing the Template loop detected: Template:Webarchive template.

A merger of the functionality of three templates: Template:Wayback, Template:Webcite and Template:Cite archives

]]

--[[--------------------------< D E P E N D E N C I E S >------------------------------------------------------
]]

require('Module:No globals');
local getArgs = require ('Module:Arguments').getArgs;

--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
]]

local categories = {}; -- category names
local config = {}; -- global configuration settings
local digits = {}; -- for i18n; table that translates local-wiki digits to western digits
local err\_warn\_msgs = {}; -- error and warning messages
local excepted\_pages = {};
local month\_num = {}; -- for i18n; table that translates local-wiki month names to western digits
local prefixes = {}; -- service provider tail string prefixes
local services = {}; -- archive service provider data from
local s\_text = {}; -- table of static text strings used to build final rendering
local uncategorized\_namespaces = {}; -- list of namespaces that we should not categorize
local uncategorized\_subpages = {}; -- list of subpages that should not be categorized

--[[--------------------------< P A G E S C O P E I D E N T I F I E R S >----------------------------------
]]

local non\_western\_digits; -- boolean flag set true when data.digits.enable is true
local this\_page = mw.title.getCurrentTitle();

local track = {}; -- Associative array to hold tracking categories
local ulx = {}; -- Associative array to hold template data

--[[--------------------------< S U B S T I T U T E >----------------------------------------------------------

Populates numbered arguments in a message string using an argument table.

]]

local function substitute (msg, args)
 return args and mw.message.newRawMessage (msg, args):plain() or msg;
end

--[[--------------------------< tableLength >-----------------------

Given a 1-D table, return number of elements

]]

local function tableLength(T)
 local count = 0
 for \_ in pairs(T) do count = count + 1 end
 return count
end

--[=[-------------------------< M A K E \_ W I K I L I N K >----------------------------------------------------

Makes a wikilink; when both link and display text is provided, returns a wikilink in the form D; if only
link is provided, returns a wikilink in the form L; if neither are provided or link is omitted, returns an
empty string.

]=]

local function make\_wikilink (link, display, no\_link)
 if nil == no\_link then
 if link and ( *~= link) then*
 if display and ( *~= display) then*
 return table.concat ({'', display, ''});
 else
 return table.concat ({'', link, ''});
 end
 end
 return display or *; -- link not set so return the display text*

 else -- no\_link
 if display and ( *~= display) then -- if there is display text*
 return display; -- return that
 else
 return link or *; -- return the target article name or empty string*
 end
 end
end

--[[--------------------------< createTracking >-----------------------

Return data in track[] ie. tracking categories

]]

local function createTracking()
 if not excepted\_pages[this\_page.fullText] then -- namespace:title/fragment is allowed to be categorized (typically this module's / template's testcases page(s))
 if uncategorized\_namespaces[this\_page.nsText] then
 return *; -- this page not to be categorized so return empty string*
 end
 for \_,v in ipairs (uncategorized\_subpages) do -- cycle through page name patterns
 if this\_page.text:match (v) then -- test page name against each pattern
 return *; -- this subpage type not to be categorized so return empty string*
 end
 end
 end

 local out = {};
 if tableLength(track) > 0 then
 for key, \_ in pairs(track) do -- loop through table
 table.insert (out, make\_wikilink (key)); -- and convert category names to links
 end
 end
 return table.concat (out); -- concat into one big string; empty string if table is empty

end

--[[--------------------------< inlineError >-----------------------

Critical error. Render output completely in red. Add to tracking category.

This function called as the last thing before abandoning this module

]]

local function inlineError (msg, args)
 track[categories.error] = 1
 return table.concat ({
 'Error in ', -- open the error message span
 config.tname, -- insert the local language template name
 ' template: ',
 substitute (msg, args), -- insert the formatted error message
 '.', -- close the span
 createTracking() -- add the category
 })
end

--[[--------------------------< inlineRed >-----------------------

Render a text fragment in red, such as a warning as part of the final output.
Add tracking category.

 ]]

local function inlineRed(msg, trackmsg)
 if trackmsg == "warning" then
 track[categories.warning] = 1;
 elseif trackmsg == "error" then
 track[categories.error] = 1;
 end

 return '' .. msg .. ''
end

--[[--------------------------< base62 >-----------------------

Convert base-62 to base-10
Credit: https://de.wikipedia.org/wiki/Modul:Expr

]]

local function base62( value )
 local r = 1 -- default return value is input value is malformed

 if value:match ('%W') then -- value must only be in the set [0-9a-zA-Z]
 return; -- nil return when value contains extraneous characters
 end

 local n = #value -- number of characters in value
 local k = 1
 local c
 r = 0
 for i = n, 1, -1 do -- loop through all characters in value from ls digit to ms digit
 c = value:byte( i, i )
 if c >= 48 and c <= 57 then -- character is digit 0-9
 c = c - 48
 elseif c >= 65 and c <= 90 then -- character is ascii a-z
 c = c - 55
 else -- must be ascii A-Z
 c = c - 61
 end
 r = r + c \* k -- accumulate this base62 character's value
 k = k \* 62 -- bump for next
 end -- for i

 return r
end

--[[--------------------------< D E C O D E \_ D A T E >--------------------------------------------------------

Given a date string, return it in iso format along with an indicator of the date's format. Except that month names
must be recognizable as legitimate month names with proper capitalization, and that the date string must match one
of the recognized date formats, no error checking is done here; return nil else

]]

local function decode\_date (date\_str)
 local patterns = {
 ['dmy'] = {'^(%d%d?) +([^%s%d]+) +(%d%d%d%d)$', 'd', 'm', 'y'}, -- %a does not recognize unicode combining characters used by some languages
 ['mdy'] = {'^([^%s%d]+) (%d%d?), +(%d%d%d%d)$', 'm', 'd', 'y'},
 ['ymd'] = {'^(%d%d%d%d) +([^%s%d]+) (%d%d?)$', 'y', 'm', 'd'}, -- not mos compliant at en.wiki but may be acceptible at other wikis
 };

 local t = {};

 if non\_western\_digits then -- this wiki uses non-western digits?
 date\_str = mw.ustring.gsub (date\_str, '%d', digits); -- convert this wiki's non-western digits to western digits
 end

 if date\_str:match ('^%d%d%d%d%-%d%d%-%d%d$') then -- already an iso format date, return western digits form
 return date\_str, 'iso';
 end

 for k, v in pairs (patterns) do
 local c1, c2, c3 = mw.ustring.match (date\_str, patterns[k][1]); -- c1 .. c3 are captured but we don't know what they hold

 if c1 then -- set on match
 t = { -- translate unspecified captures to y, m, and d
 [patterns[k][2]] = c1, -- fill the table of captures with the captures
 [patterns[k][3]] = c2, -- take index names from src\_pattern table and assign sequential captures
 [patterns[k][4]] = c3,
 };
 if month\_num[t.m] then -- when month not already a number
 t.m = month\_num[t.m]; -- replace valid month name with a number
 else
 return nil, 'iso'; -- not a valid date form because month not valid
 end

 return mw.ustring.format ('%.4d-%.2d-%.2d', t.y, t.m, t.d), k; -- return date in iso format
 end
 end
 return nil, 'iso'; -- date could not be decoded; return nil and default iso date
end

--[[--------------------------< makeDate >-----------------------

Given year, month, day numbers, (zero-padded or not) return a full date in df format
where df may be one of:
 mdy, dmy, iso, ymd

on entry, year, month, day are presumed to be correct for the date that they represent; all are required

in this module, makeDate() is sometimes given an iso-format date in year:
 makeDate (2018-09-20, nil, nil, df)
this works because table.concat() sees only one table member

]]

local function makeDate (year, month, day, df)
 local format = {
 ['dmy'] = 'j F Y',
 ['mdy'] = 'F j, Y',
 ['ymd'] = 'Y F j',
 ['iso'] = 'Y-m-d',
 };

 local date = table.concat ({year, month, day}, '-'); -- assemble year-initial numeric-format date (zero padding not required here)

 if non\_western\_digits then -- this wiki uses non-western digits?
 date = mw.ustring.gsub (date, '%d', digits); -- convert this wiki's non-western digits to western digits
 end

 return mw.getContentLanguage():formatDate (format[df], date);
end

--[[--------------------------< I S \_ V A L I D \_ D A T E >----------------------------------------------------

Returns true if date is after 31 December 1899 (why is 1900 the min year? shouldn't the internet's date-of-birth
be min year?), not after today's date, and represents a valid date (29 February 2017 is not a valid date). Applies
Gregorian leapyear rules.

all arguments are required

]]

local function is\_valid\_date (year, month, day)
 local days\_in\_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 local month\_length;
 local y, m, d;
 local today = os.date ('\*t'); -- fetch a table of current date parts

 if not year or  *== year or not month or*  == month or not day or  *== day then*
 return false; -- something missing
 end

 y = tonumber (year);
 m = tonumber (month);
 d = tonumber (day);

 if 1900 > y or today.year < y or 1 > m or 12 < m then -- year and month are within bounds TODO: 1900?
 return false;
 end

 if (2==m) then -- if February
 month\_length = 28; -- then 28 days unless
 if (0==(y%4) and (0~=(y%100) or 0==(y%400))) then -- is a leap year?
 month\_length = 29; -- if leap year then 29 days in February
 end
 else
 month\_length=days\_in\_month[m];
 end

 if 1 > d or month\_length < d then -- day is within bounds
 return false;
 end
 -- here when date parts represent a valid date
 return os.time({['year']=y, ['month']=m, ['day']=d, ['hour']=0}) <= os.time(); -- date at midnight must be less than or equal to current date/time
end

--[[--------------------------< decodeWebciteDate >-----------------------

Given a URI-path to Webcite (eg. /67xHmVFWP) return the encoded date in df format

returns date string in df format - webcite date is a unix timestamp encoded as bae62
or the string 'query'

]]

local function decodeWebciteDate(path, df)

 local dt = {};
 local decode;

 dt = mw.text.split(path, "/")

 -- valid URL formats that are not base62

 -- http://www.webcitation.org/query?id=1138911916587475
 -- http://www.webcitation.org/query?url=http..&date=2012-06-01+21:40:03
 -- http://www.webcitation.org/1138911916587475
 -- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e
 -- http://www.webcitation.org/getfile.php?fileid=1c46e791d68e89e12d0c2532cc3cf629b8bc8c8e

 if dt[2]:find ('query', 1, true) or
 dt[2]:find ('cache', 1, true) or
 dt[2]:find ('getfile', 1, true) or
 tonumber(dt[2]) then
 return 'query';
 end

 decode = base62(dt[2]); -- base62 string -> exponential number
 if not decode then
 return nil; -- nil return when dt[2] contains characters not in %w
 end
 dt = os.date('\*t', string.format("%d", decode):sub(1,10)) -- exponential number -> text -> first 10 characters (a unix timestamp) -> a table of date parts

 decode = makeDate (dt.year, dt.month, dt.day, 'iso'); -- date comparisons are all done in iso format with western digits
 if non\_western\_digits then -- this wiki uses non-western digits?
 decode = mw.ustring.gsub (decode, '%d', digits); -- convert this wiki's non-western digits to western digits
 end

 return decode;
end

--[[--------------------------< decodeWaybackDate >-----------------------

Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com )
or Library of Congress Web Archives (eg. /all/20160901010101/http://example.com)
or UK Government Web Archive (eg. /ukgwa/20160901010101/http://example.com or /tna/20160901010101/http://example.com)

return the formatted date eg. "September 1, 2016" in df format
Handle non-digits in snapshot ID such as "re\_" and "-" and "\*"

 valid date string in df format - wayback date is valid (including the text string 'index' when date is '/\*/')
 empty string - wayback date is malformed (less than 8 digits, not a valid date)
 nil - wayback date is '/save/' or otherwise not a number

 second return value is an appropriate 'message' may or may not be formatted

]]

local function decodeWaybackDate(path, df)

 local msg, snapdate;

 snapdate = path:gsub ('^/web/', *):gsub ('^/all/',* ):gsub ('^/ukgwa/', *):gsub ('^/tna/',* ):gsub ('^/', *); -- remove leading /web/, /all/, /ukgwa/, /tna/, or /*
 snapdate = snapdate:match ('^[^/]+'); -- get timestamp
 if snapdate == "\*" then -- eg. /web/\*/http.., etc.
 return 'index'; -- return indicator that this url has an index date
 end

 snapdate = snapdate:gsub ('%a%a\_%d?$', *):gsub ('%-',* ); -- from date, remove any trailing "re\_", dashes

 msg = *;*
 if snapdate:match ('%\*$') then -- a trailing '\*' causes calendar display at archive .org
 snapdate = snapdate:gsub ('%\*$', *); -- remove so not part of length calc later*
 msg = inlineRed (err\_warn\_msgs.ts\_cal, 'warning'); -- make a message
 end

 if not tonumber(snapdate) then
 return nil, 'ts\_nan'; -- return nil (fatal error flag) and message selector
 end

 local dlen = snapdate:len();
 if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits?
 return *, inlineRed (err\_warn\_msgs.ts\_short, 'error'); -- return empty string and error message*
 end

 local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here

 if not is\_valid\_date (year, month, day) then
 return *, inlineRed (err\_warn\_msgs.ts\_date, 'error'); -- return empty string and error message*
 end

 snapdate = table.concat ({year, month, day}, '-'); -- date comparisons are all done in iso format
 if 14 == dlen then
 return snapdate, msg; -- return date with message if any
 else
 return snapdate, msg .. inlineRed (err\_warn\_msgs.ts\_len, 'warning'); -- return date with warning message(s)
 end
end

--[[--------------------------< decodeArchiveisDate >-----------------------

Given an Archive.is "long link" URI-path (e.g. /2016.08.28-144552/http://example.com)
return the date in df format (e.g. if df = dmy, return 28 August 2016)
Handles "." and "-" in snapshot date, so 2016.08.28-144552 is same as 20160828144552

 valid date string in df format - archive.is date is valid (including the text string 'short link' when url is the short form)
 empty string - wayback date is malformed (not a number, less than 8 digits, not a valid date)
 nil - wayback date is '/save/'

 second return value is an appropriate 'message' may or may not be formatted

]]

local function decodeArchiveisDate(path, df)
 local snapdate

 if path:match ('^/%w+$') then -- short form url path is '/' followed by some number of base 62 digits and nothing else
 return "short link" -- e.g. http://archive.is/hD1qz
 end

 snapdate = mw.text.split (path, '/')[2]:gsub('[%.%-]', *); -- get snapshot date, e.g. 2016.08.28-144552; remove periods and hyphens*

 local dlen = string.len(snapdate)
 if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits?
 return *, inlineRed (err\_warn\_msgs.ts\_short, 'error'); -- return empty string and error message*
 end

 local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here

 if not is\_valid\_date (year, month, day) then
 return *, inlineRed (err\_warn\_msgs.ts\_date, 'error'); -- return empty string and error message*
 end

 snapdate = table.concat ({year, month, day}, '-'); -- date comparisons are all done in iso format
 if 14 == dlen then
 return snapdate; -- return date
 else
 return snapdate, inlineRed (err\_warn\_msgs.ts\_len, 'warning'); -- return date with warning message
 end
 end

--[[--------------------------< serviceName >-----------------------

Given a domain extracted by mw.uri.new() (eg. web.archive.org) set tail string and service ID

]]

local function serviceName(host, no\_link)
 local tracking;
 local index;

 host = host:lower():gsub ('^web%.(.+)', '%1'):gsub ('^www%.(.+)', '%1'); -- lowercase, remove web. and www. subdomains

 if services[host] then
 index = host;
 else
 for k, \_ in pairs (services) do
 if host:find ('%f[%a]'..k:gsub ('([%.%-])', '%%%1')) then
 index = k;
 break;
 end
 end
 end

 if index then
 local out = {*}; -- empty string in [1] so that concatenated result has leading single space*
 ulx.url1.service = services[index][4] or 'other';
 tracking = services[index][5] or categories.other;
 -- build tail string
 if false == services[index][1] then -- select prefix
 table.insert (out, prefixes.at);
 elseif true == services[index][1] then
 table.insert (out, prefixes.atthe);
 else
 table.insert (out, services[index][1]);
 end

 table.insert (out, make\_wikilink (services[index][2], services[index][3], no\_link)); -- add article wikilink
 if services[index][6] then -- add tail postfix if it exists
 table.insert (out, services[index][6]);
 end

 ulx.url1.tail = table.concat (out, ' '); -- put it all together; result has leading space character

 else -- here when unknown archive
 ulx.url1.service = 'other';
 tracking = categories.unknown;
 ulx.url1.tail = table.concat ({*, prefixes.at, host, inlineRed (err\_warn\_msgs.unknown\_url, error)}, ' ');*
 end

 track[tracking] = 1
end

--[[--------------------------< parseExtraArgs >-----------------------

Parse numbered arguments starting at 2, such as url2..url10, date2..date10, title2..title10
 For example: Template loop detected: Template:Webarchive
 Three url arguments not in numeric sequence (1..4..7).
 Function only processes arguments numbered 2 or greater (in this case 4 and 7)
 It creates numeric sequenced table entries like:
 urlx.url2.url = <argument value for url4>
 urlx.url3.url = <argument value for url7>
 Returns the number of URL arguments found numbered 2 or greater (in this case returns "2")

 ]]

local function parseExtraArgs(args)

 local i, j, argurl, argurl2, argdate, argtitle

 j = 2
 for i = 2, config.maxurls do
 argurl = "url" .. i
 if args[argurl] then
 argurl2 = "url" .. j
 ulx[argurl2] = {}
 ulx[argurl2]["url"] = args[argurl]
 argdate = "date" .. i
 if args[argdate] then
 ulx[argurl2]["date"] = args[argdate]
 else
 ulx[argurl2]["date"] = inlineRed (err\_warn\_msgs.date\_miss, 'warning');
 end

 argtitle = "title" .. i
 if args[argtitle] then
 ulx[argurl2]["title"] = args[argtitle]
 else
 ulx[argurl2]["title"] = nil
 end
 j = j + 1
 end
 end

 if j == 2 then
 return 0
 else
 return j - 2
 end
end

--[[--------------------------< comma >-----------------------

Given a date string, return "," if it's MDY

]]

local function comma(date)
 return (date and date:match ('%a+ +%d%d?(,) +%d%d%d%d')) or *;*
end

--[[--------------------------< createRendering >-----------------------

Return a rendering of the data in ulx[][]

]]

local function createRendering()

 local displayfield
 local out = {};

 local index\_date, msg = ulx.url1.date:match ('(index)(.\*)'); -- when ulx.url1.date extract 'index' text and message text (if there is a message)
 ulx.url1.date = ulx.url1.date:gsub ('index.\*', 'index'); -- remove message

 if 'none' == ulx.url1.format then -- For Template:Wayback, Template:Webcite
 table.insert (out, '['); -- open extlink markup
 table.insert (out, ulx.url1.url); -- add url

 if ulx.url1.title then
 table.insert (out, ' ') -- the required space
 table.insert (out, ulx.url1.title) -- the title
 table.insert (out, ']'); -- close extlink markup
 table.insert (out, ulx.url1.tail); -- tail text
 if ulx.url1.date then
 table.insert (out, ' ('); -- open date text; TODO: why the html entity? replace with regular space?
 table.insert (out, 'index' == ulx.url1.date and s\_text.archive or s\_text.archived); -- add text
 table.insert (out, ' '); -- insert a space
 table.insert (out, ulx.url1.date); -- add date
 table.insert (out, ')'); -- close date text
 end
 else -- no title
 if index\_date then -- when url date is 'index'
 table.insert (out, table.concat ({' ', s\_text.Archive\_index, ']'})); -- add the index link label
 table.insert (out, msg or *); -- add date mismatch message when url date is /\*/ and |date= has valid date*
 else
 table.insert (out, table.concat ({' ', s\_text.Archived, '] '})); -- add link label for url has timestamp date (will include mismatch message if there is one)
 end
 if ulx.url1.date then
 if 'index' ~= ulx.url1.date then
 table.insert (out, ulx.url1.date); -- add date when data is not 'index'
 end
 table.insert (out, comma(ulx.url1.date)); -- add ',' if date format is mdy
 table.insert (out, ulx.url1.tail); -- add tail text
 else -- no date
 table.insert (out, ulx.url1.tail); -- add tail text
 end
 end

 if 0 < ulx.url1.extraurls then -- For multiple archive URLs
 local tot = ulx.url1.extraurls + 1
 table.insert (out, '.') -- terminate first url
 table.insert (out, table.concat ({' ', s\_text.addlarchives, ': '})); -- add header text

 for i=2, tot do -- loop through the additionals
 local index = table.concat ({'url', i}); -- make an index
 displayfield = ulx[index]['title'] and 'title' or 'date'; -- choose display text
 table.insert (out, '['); -- open extlink markup
 table.insert (out, ulx[index]['url']); -- add the url
 table.insert (out, ' '); -- the required space
 table.insert (out, ulx[index][displayfield]); -- add the label
 table.insert (out, ']'); -- close extlink markup
 table.insert (out, i==tot and '.' or ', '); -- add terminator
 end
 end
 return table.concat (out); -- make a big string and done

 else -- For Template:Cite archives
 if 'addlarchives' == ulx.url1.format then -- Multiple archive services
 table.insert (out, table.concat ({s\_text.addlarchives, ': '})); -- add header text
 else -- Multiple pages from the same archive
 table.insert (out, table.concat ({s\_text.addlpages, ' '})); -- add header text
 table.insert (out, ulx.url1.date); -- add date to header text
 table.insert (out, ': '); -- close header text
 end

 local tot = ulx.url1.extraurls + 1;
 for i=1, tot do -- loop through the additionals
 local index = table.concat ({'url', i}); -- make an index
 table.insert (out, '['); -- open extlink markup
 table.insert (out, ulx[index]['url']); -- add url
 table.insert (out, ' '); -- add required space

 displayfield = ulx[index]['title'];
 if 'addlarchives' == ulx.url1.format then
 if not displayfield then
 displayfield = ulx[index]['date']
 end
 else -- must be addlpages
 if not displayfield then
 displayfield = table.concat ({s\_text.Page, ' ', i});
 end
 end
 table.insert (out, displayfield); -- add title, date, page label text
 table.insert (out, ']'); -- close extlink markup
 table.insert (out, (i==tot and '.' or ', ')); -- add terminator
 end
 return table.concat (out); -- make a big string and done
 end
end

--[[--------------------------< P A R A M E T E R \_ N A M E \_ X L A T E >--------------------------------------

for internaltionalization, translate local-language parameter names to their English equivalents

TODO: return error message if multiple aliases of the same canonical parameter name are found?

returns two tables:
 new\_args - holds canonical form parameters and their values either from translation or because the parameter was already in canonical form
 origin - maps canonical-form parameter names to their untranslated (local language) form for error messaging in the local language

unrecognized parameters are ignored

]]

local function parameter\_name\_xlate (args, params, enum\_params)
 local name; -- holds modifiable name of the parameter name during evaluation
 local enum; -- for enumerated parameters, holds the enumerator during evaluation
 local found = false; -- flag used to break out of nested for loops
 local new\_args = {}; -- a table that holds canonical and translated parameter k/v pairs
 local origin = {}; -- a table that maps original (local language) parameter names to their canonical name for local language error messaging
 local unnamed\_params; -- set true when unsupported positional parameters are detected

 for k, v in pairs (args) do -- loop through all of the arguments in the args table
 name = k; -- copy of original parameter name

 if 'string' == type (k) then
 if non\_western\_digits then -- true when non-western digits supported at this wiki
 name = mw.ustring.gsub (name, '%d', digits); -- convert this wiki's non-western digits to western digits
 end

 enum = name:match ('%d+$'); -- get parameter enumerator if it exists; nil else

 if not enum then -- no enumerator so looking for non-enumnerated parameters
 -- TODO: insert shortcut here? if params[name] then name holds the canonical parameter name; no need to search further
 for pname, aliases in pairs (params) do -- loop through each parameter the params table
 for \_, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table
 if name == alias then
 new\_args[pname] = v; -- create a new entry in the new\_args table
 origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name
 found = true; -- flag so that we can break out of these nested for loops
 break; -- no need to search the rest of the aliases table for name so go on to the next k, v pair
 end
 end

 if found then -- true when we found an alias that matched name
 found = false; -- reset the flag
 break; -- go do next args k/v pair
 end
 end
 else -- enumerated parameters
 name = name:gsub ('%d$', '#'); -- replace enumeration digits with place holder for table search
 -- TODO: insert shortcut here? if num\_params[name] then name holds the canonical parameter name; no need to search further
 for pname, aliases in pairs (enum\_params) do -- loop through each parameter the num\_params table
 for \_, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table
 if name == alias then
 pname = pname:gsub ('#$', enum); -- replace the '#' place holder with the actual enumerator
 new\_args[pname] = v; -- create a new entry in the new\_args table
 origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name
 found = true; -- flag so that we can break out of these nested for loops
 break; -- no need to search the rest of the aliases table for name so go on to the next k, v pair
 end
 end

 if found then -- true when we found an alias that matched name
 found = false; -- reset the flag
 break; -- go do next args k/v pair
 end
 end
 end
 else
 unnamed\_params = true; -- flag for unsupported positional parameters
 end
 end -- for k, v
 return new\_args, origin, unnamed\_params;
end

--[[--------------------------< W E B A R C H I V E >----------------------------------------------------------

template entry point

]]

local function webarchive(frame)
 local args = getArgs (frame);

 local data = mw.loadData (table.concat ({ -- make a data module name; sandbox or live
 'Module:Webarchive/data',
 frame:getTitle():find('sandbox', 1, true) and '/sandbox' or  *-- this instance is ./sandbox then append /sandbox*
 }));
 categories = data.categories; -- fill in the forward declarations
 config = data.config;
 if data.digits.enable then
 digits = data.digits; -- for i18n; table of digits in the local wiki's language
 non\_western\_digits = true; -- use\_non\_western\_digits
 end
 err\_warn\_msgs = data.err\_warn\_msgs;
 excepted\_pages = data.excepted\_pages;
 month\_num = data.month\_num; -- for i18n; table of month names in the local wiki's language
 prefixes = data.prefixes;
 services = data.services;
 s\_text = data.s\_text;
 uncategorized\_namespaces = data.uncategorized\_namespaces;
 uncategorized\_subpages = data.uncategorized\_subpages;

 local origin = {}; -- holds a map of English to local language parameter names used in the current template; not currently used
 local unnamed\_params; -- boolean set to true when template call has unnamed parameters
 args, origin, unnamed\_params = parameter\_name\_xlate (args, data.params, data.enum\_params); -- translate parameter names in args to English

 local date, format, msg, udate, uri, url;
 local ldf = 'iso'; -- when there is no |date= parameter, render url dates in iso format

 if args.url and args.url1 then -- URL argument (first)
 return inlineError (data.crit\_err\_msgs.conflicting, {origin.url, origin.url1});
 end

 url = args.url or args.url1;

 if not url then
 return inlineError (data.crit\_err\_msgs.empty);
 end
 -- these iabot bugs perportedly fixed; removing these causes lua script error
--[[ -- at Template:Webarchive/testcases/Production; resolve that before deleting these tests
 if mw.ustring.find( url, "https://web.http", 1, true ) then -- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferred
 track[categories.error] = 1;
 return inlineError (data.crit\_err\_msgs.iabot1);
 end
 if url == "https://web.archive.org/http:/" then -- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferred
 track[categories.error] = 1;
 return inlineError (data.crit\_err\_msgs.iabot2);
 end
]]

 if not (url:lower():find ('^http') or url:find ('^//')) then
 return inlineError (data.crit\_err\_msgs.invalid\_url );
 end

 ulx.url1 = {}
 ulx.url1.url = url

 ulx.url1.extraurls = parseExtraArgs(args)

 local good = false;
 good, uri = pcall (mw.uri.new, ulx.url1.url); -- get a table of uri parts from this url; protected mode to prevent lua error when ulx.url1.url is malformed

 if not good or nil == uri.host then -- abandon when ulx.url1.url is malformed
 return inlineError (data.crit\_err\_msgs.invalid\_url);
 end

 serviceName(uri.host, args.nolink)

 if args.date and args.date1 then -- Date argument
 return inlineError (data.crit\_err\_msgs.conflicting, {origin.date, origin.date1});
 end

 date = args.date or args.date1;
 date = date and date:gsub (' +', ' '); -- replace multiple spaces with a single space

 if date and config.verifydates then
 if '\*' == date then
 date = 'index';
 ldf = 'iso'; -- set to default format
 elseif 'mdy' == date then
 date = nil; -- if date extracted from URL,
 ldf = 'mdy'; -- then |date=mdy overrides iso
 elseif 'dmy' == date then
 date = nil; -- if date extracted from URL,
 ldf = 'dmy'; -- then |date=dmy overrides iso
 elseif 'ymd' == date then
 date = nil; -- if date extracted from URL,
 ldf = 'ymd'; -- then |date=ymd overrides iso
 else
 date, ldf = decode\_date (date); -- get an iso format date from date and get date's original format
 end
 end

 if 'wayback' == ulx.url1.service or 'locwebarchives' == ulx.url1.service or 'ukgwa' == ulx.url1.service then
 if date then
 if config.verifydates then
 if ldf then
 udate, msg = decodeWaybackDate (uri.path); -- get the url date in iso format and format of date in |date=; 'index' when wayback url date is \*
 if not udate then -- this is the only 'fatal' error return
 return inlineError (data.crit\_err\_msgs[msg]);
 end

 if udate ~= date then -- date comparison using iso format dates
 date = udate;
 msg = table.concat ({
 inlineRed (err\_warn\_msgs.mismatch, 'warning'), -- add warning message
 msg, -- add message if there is one
 });
 end
 end
 end
 else -- no |date=
 udate, msg = decodeWaybackDate (uri.path);

 if not udate then -- this is the only 'fatal' error return
 return inlineError (data.crit\_err\_msgs[msg]);
 end

 if  *== udate then*
 date = nil; -- unset
 else
 date = udate;
 end
 end

 elseif 'webcite' == ulx.url1.service then
 if date then
 if config.verifydates then
 if ldf then
 udate = decodeWebciteDate (uri.path); -- get the url date in iso format
 if 'query' ~= udate then -- skip if query
 if udate ~= date then -- date comparison using iso format dates
 date = udate;
 msg = table.concat ({
 inlineRed (err\_warn\_msgs.mismatch, 'warning'),
 });
 end
 end
 end
 end
 else
 date = decodeWebciteDate( uri.path, "iso" )
 if date == "query" then
 date = nil; -- unset
 msg = inlineRed (err\_warn\_msgs.date\_miss, 'warning');
 elseif not date then -- invalid base62 string
 date = inlineRed (err\_warn\_msgs.date1, 'error');
 end
 end

 elseif 'archiveis' == ulx.url1.service then
 if date then
 if config.verifydates then
 if ldf then
 udate, msg = decodeArchiveisDate (uri.path) -- get the url date in iso format
 if 'short link' ~= udate then -- skip if short link
 if udate ~= date then -- date comparison using iso format dates
 date = udate;
 msg = table.concat ({
 inlineRed (err\_warn\_msgs.mismatch, 'warning'), -- add warning message
 msg, -- add message if there is one
 });
 end
 end
 end
 end
 else -- no |date=
 udate, msg = decodeArchiveisDate( uri.path, "iso" )
 if udate == "short link" then
 date = nil; -- unset
 msg = inlineRed (err\_warn\_msgs.date\_miss, 'warning');
 elseif  *== udate then*
 date = nil; -- unset
 else
 date = udate;
 end
 end

 else -- some other service
 if not date then
 msg = inlineRed (err\_warn\_msgs.date\_miss, 'warning');
 end
 end

 if 'index' == date then
 ulx.url1.date = date .. (msg or *); -- create index + message (if there is one)*
 elseif date then
 ulx.url1.date = makeDate (date, nil, nil, ldf) .. (msg or *); -- create a date in the wiki's local language + message (if there is one)*
 else
 ulx.url1.date = msg;
 end

 format = args.format; -- Format argument

 if not format then
 format = "none"
 else
 for k, v in pairs (data.format\_vals) do -- |format= accepts two specific values loop through a table of those values
 local found; -- declare a nil flag
 for \_, p in ipairs (v) do -- loop through local language variants
 if format == p then -- when |format= value matches
 format = k; -- use name from table key
 found = true; -- declare found so that we can break out of outer for loop
 break; -- break out of inner for loop
 end
 end

 if found then
 break;
 end
 end

 if format == "addlpages" then
 if not ulx.url1.date then
 format = "none"
 end
 elseif format == "addlarchives" then
 format = "addlarchives"
 else
 format = "none"
 end
 end
 ulx.url1.format = format

 if args.title and args.title1 then -- Title argument
 return inlineError (data.crit\_err\_msgs.conflicting, {origin.title, origin.title1});
 end

 ulx.url1.title = args.title or args.title1;

 local rend = createRendering()
 if not rend then
 return inlineError (data.crit\_err\_msgs.unknown);
 end

 return rend .. ((unnamed\_params and inlineRed (err\_warn\_msgs.unnamed\_params, 'warning')) or *) .. createTracking();*

end

--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]

return {webarchive = webarchive};
16. ↑ Eggertsen, Chris (November 4, 2016). CARRIE's Prom Scene: An Oral History (Part Two). Retrieved on September 13, 2017.
17. ↑ Sears, John: Stephen King's Gothic (2011) *978-0-7083-2402-8 p. 31*
18. ↑ "Carrie- Original Motion Picture Soundtrack LP". Retrieved on July 11, 2017.
19. ↑ *Carrie* [Original Motion Picture Soundtrack: Releases]. All Media Network, LLC. Retrieved on July 11, 2017.
20. ↑ Special 2-CD soundtrack "Carrie" full score composed by Pino Donaggio. kritzerland.com. Retrieved on August 3, 2013.
21. ↑ 21.0 21.1 Template:Cite magazine
22. ↑ *Template:PAGENAMEBASE* at the American Film Institute Catalog**Script error: No such module "EditAtWikidata".**
23. ↑ Greatest Films of 1976. Filmsite.org. Retrieved on October 2, 2012.
24. ↑ The Best Movies of 1976 by Rank. Films101.com. Retrieved on October 2, 2012.
25. ↑ IMDb: Year: 1976.
26. ↑ Carrie (1976). *Rotten Tomatoes*. Fandango. Retrieved on April 22, 2019.
27. ↑ Carrie Reviews. *Metacritic*. CBS Interactive. Retrieved on April 5, 2019.
28. ↑ Ebert, Roger. Roger Ebert (Chicago Sun Times) Review of *Carrie* (1976). Retrieved May 27, 2007.
29. ↑ *Take One Magazine*, January 1977 at Carrie... A Fan's Site
30. ↑ 30.0 30.1 Pundits Page. Take One Magazine, p.57 (March 1997).
31. ↑ Quentin Tarantino's Handwritten List of the 11 Greatest Movies. *Empire* (2008). Retrieved on October 2, 2013.
32. ↑ Siskel, Gene (November 9, 1976). "'Carrie' has style but violence carries the day". *Chicago Tribune*. Section 2, p. 7.
33. ↑ Template:Cite magazine
34. ↑ Richard Nowell, *Blood Money: A History of the First Teen Slasher Film Cycle* Continuum, 2011 p 256
35. ↑ Template:Cite magazine
36. ↑ AFI's 100 Years ... 100 Thrills. American Film Institute. Retrieved on March 7, 2012.
37. ↑ AFI's 100 Years... 100 Heroes and Villains. American Film Institute. Retrieved on October 25, 2018.
38. ↑ TV Reviews: "Carrie" (November 4, 2002).
39. ↑ Kit, Borys. "MGM, Screen Gems Team for 'Carrie' Remake", *The Hollywood Reporter*, May 19, 2011.
40. ↑ Template:Cite magazine
41. ↑ Julianne Moore And Gabriella Wilde Board Carrie Remake. CinemaBlend.com (May 14, 2012). Retrieved on October 2, 2012.
42. ↑ "Chronicle" star Alex Russell and Broadway actor Ansel Elgort join "Carrie" remake opposite Chloe Moretz. Up and Comers. Retrieved on October 2, 2012.
43. ↑ UPDATE: Judy Greer HAS NOT Signed On To The Carrie Remake As The Gym Teacher. CinemaBlend.com (May 25, 2012). Retrieved on October 2, 2012.
44. ↑ Template:Cite magazine
45. ↑ Schulman, Michael. "Is 'Carrie' the Worst Musical of All Time?", January 27, 2012. Retrieved on April 3, 2017.
46. ↑ Eric Jackson Interview. horrorking.com. Retrieved on February 27, 2008.
47. ↑ "New York Times Theater Review", *The New York Times*, November 26, 2006. Retrieved on February 27, 2008.
48. ↑ Hell in a Handbag's Scarrie site. handbagproductions.org. Retrieved on February 27, 2008.
49. ↑ Sci-Fi Dimensions Review. scifidimensions. Archived from the original on March 6, 2008. Retrieved on February 27, 2008.
50. ↑ Carrie's Facts of Life – Official Site. norunningwithscissors.com. Retrieved on February 27, 2008.
51. ↑ Template:Cite magazine
52. ↑ Carrie DVD. Blu-ray.com. Retrieved on September 30, 2017.
53. ↑ Carrie DVD: Special Edition. Blu-ray.com. Retrieved on September 30, 2017.
54. ↑ Carrie DVD: Decades Collection with CD / DVD + CD. Blu-ray.com. Retrieved on September 30, 2017.
55. ↑ 55.0 55.1 Carrie Triple Feature DVD. Blu-ray.com. Retrieved on September 30, 2017.
56. ↑ Carrie Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
57. ↑ Carrie Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
58. ↑ Carrie: 2-Pack Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
59. ↑ Carrie w/ Collectible Halloween Faceplate Blu-ray. Blu-ray.com. Retrieved on September 30, 2017.
60. ↑ Carrie Blu-ray: Collector's Edition. Blu-ray.com. Retrieved on September 30, 2017.
61. ↑ Carrie Blu-ray: Shout Factory Exclusive / Deluxe Limited Edition. Blu-ray.com. Retrieved on September 30, 2017.
62. ↑ Carrie (Special Edition) [DVD [1976]]. Amazon.co.uk. Retrieved on September 30, 2017.
63. ↑ CARRIE [DVD]. Amazon.co.uk. Retrieved on September 30, 2017.
64. ↑ Carrie / The Rage: Carrie 2 Double Pack [DVD [1976]]. Amazon.co.uk. Retrieved on September 30, 2017.
65. ↑ Carrie [DVD [1976]]. Amazon.co.uk. Retrieved on September 30, 2017.
66. ↑ Carrie [Blu-ray [1976]]. Retrieved on September 30, 2017.
67. ↑ Carrie (FuturePak) [Blu-ray]. Retrieved on September 30, 2017.
68. ↑ Carrie – Limited Edition. Arrow Films. Retrieved on September 30, 2017.
69. ↑ Squires, JohnArrow Video Bringing 4K Restoration of Original 'Carrie' to Blu-ray. Bloody Disgusting (22 December 2017). Retrieved on September 30, 2017.

## Further reading

* Ehlers, Leigh A. "Carrie: Book and film." *Literature/Film Quarterly* 9.1 (1981): 32–39.
* Shih, Paris Shun-Hsiang. "Fearing the Witch, Hating the Bitch: The Double Structure of Misogyny in Stephen King’s Carrie." in *Perceiving Evil: Evil Women and the Feminine* (Brill, 2015) pp. 49–58.
* Tibbetts, John C., and James M. Welsh, eds. *The Encyclopedia of Novels Into Film* (2nd ed. 2005) pp 49–50.

## External links

Template:Wikiquote

**Lua error: bad argument #2 to 'title.new' (unrecognized namespace name 'Portal').**

* *Template:PAGENAMEBASE* at the American Film Institute Catalog**Script error: No such module "EditAtWikidata".**
* Template:Mojo title
* *Carrie* at the Internet Movie Database
* Template:Rotten-tomatoes

Template:Carrie
Template:Media based on Stephen King works
Template:Brian De Palma
Template:Authority control