/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 *
 */

/*
 * mNew, portObject, baudRate, playerType  creates a
 *    new instance and returns error code
 *    portObject is an instance from SerialPort XObject.
 *    baudRate should be the same as machine setting.
 *        9600(default for Pioneer 8000),
 *        4800(preferred for Pioneer 2200, 4200),
 *        2400, and 1200.
 *    playerType:
 *        0 for Pioneer 2200, 4200 and 8000
 *        1 for Sony Laser Max 1200, 1500, and 2000
 *    Error codes:
 *        -1 : incorrect BaudRate.
 *        -2 : memory error.
 *        -3 : SerialPort Drivers would not open.
 *
 * mDispose  frees this instance from memory.
 * mName  returns my name.
 * mPlayer  returns the player.
 *
 * Note: all of the following methods will return either "OK" or an error message. Possible error messages include:
 *     "No Response" -- bad connection or wrong baud rate.
 *     "Not Ready"    -- disc ejected or motor stopped.
 *
 * mPlay  normal playback mode in the forward direction.
 * mPlayRev  playback mode in the reverse direction.
 *
 * mFastFwd  fast forward playback mode.
 *     3 times normal speed.
 * mFastRev  fast reverse playback mode.
 *     3 times normal speed.
 *
 * mSlowFwd  slow forward playback mode.
 *     1/5 times normal speed.
 * mSlowRev  slow reverse playback mode
 *     1/5 times normal speed.
 *
 * mStepFwd  step forward a single frame.
 * mStepRev  step reverse a single frame.
 *
 * mPlayJog, nFrame  step multiple frames either forward
 *     or reverse
 *
 * mPlaySpeed, rate  play at slower than normal speed.
 *     rate can be any of the following:
 *         30 is 1x; 15 is 1/2x; 10 is 1/3x; 5 is 1/6x
 *     Example: -10 is one third normal speed, backwards.
 *
 * mPlaySegment, start, end  play a segment of video disc.
 *     Start and end are frame numbers.
 *
 * mPause  set player to display freeze picture (STILL)
 *     When this method is called a second time, this will
 *     continue the mode prior to first call.
 * mStop  halts playback of videodisc.
 * mEject  opens disc compartment and ejects disc.
 *
 * mStopAtFrame, frameNum  set to stop at frameNum
 *
 * mSearchWait, frameNum  search for frameNum and
 *     returns "OK" when search is completed.
 *
 * mReadPos  return the current frame position
 * mShowDisplay, flag  enable/disable frame display
 *
 * mClear  clear all modes of player. Remove Stop markers
 *
 * mVideoControl, videoState  control squelch condition
 *     of video image.
 *
 * mAudioControl, audioState
 *     audioState is one of the following
 *         0 : Turn off both audio channels.
 *         1 : Turn on channel 1 only.
 *         2 : Turn on channel 2 only.
 *         3 : Turn on both audio channels.
 *
 * mStatus  return either "OK" or error message
 *     See the mDescribe for a full list of errors.
 */

#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/xlibs/videodiscxobj.h"

namespace Director {

const char *VideodiscXObj::xlibName = "LaserDisc";
const char *VideodiscXObj::fileNames[] = {
	"Videodisc XObj",
	0
};

static MethodProto xlibMethods[] = {
	{ "new",			VideodiscXObj::m_new,			 3, 3,	200 },	// D2
	{ "Name",			VideodiscXObj::m_name,			 0, 0,	200 },	// D2
	{ "Player",			VideodiscXObj::m_player,		 0, 0,	200 },	// D2
	{ "Play",			VideodiscXObj::m_play,			 0, 0,	200 },	// D2
	{ "PlayRev",		VideodiscXObj::m_playRev,		 0, 0,	200 },	// D2
	{ "FastFwd",		VideodiscXObj::m_fastFwd,		 0, 0,	200 },	// D2
	{ "FastRev",		VideodiscXObj::m_fastRev,		 0, 0,	200 },	// D2
	{ "SlowFwd",		VideodiscXObj::m_slowFwd,		 0, 0,	200 },	// D2
	{ "SlowRev",		VideodiscXObj::m_slowRev,		 0, 0,	200 },	// D2
	{ "StepFwd",		VideodiscXObj::m_stepFwd,		 0, 0,	200 },	// D2
	{ "StepRev",		VideodiscXObj::m_stepRev,		 0, 0,	200 },	// D2
	{ "PlayJog",		VideodiscXObj::m_playJog,		 1, 1,	200 },	// D2
	{ "PlaySpeed",		VideodiscXObj::m_playSpeed,		 1, 1,	200 },	// D2
	{ "PlaySegment",	VideodiscXObj::m_playSegment,	 2, 2,	200 },	// D2
	{ "Pause",			VideodiscXObj::m_pause,			 0, 0,	200 },	// D2
	{ "Stop",			VideodiscXObj::m_stop,			 0, 0,	200 },	// D2
	{ "Eject",			VideodiscXObj::m_eject,			 0, 0,	200 },	// D2
	{ "StopAtFrame",	VideodiscXObj::m_stopAtFrame,	 1, 1,	200 },	// D2
	{ "SearchWait",		VideodiscXObj::m_searchWait,	 1, 1,	200 },	// D2
	{ "ReadPos",		VideodiscXObj::m_readPos,		 0, 0,	200 },	// D2
	{ "ShowDisplay",	VideodiscXObj::m_showDisplay,	 0, 0,	200 },	// D2
	{ "Clear",			VideodiscXObj::m_clear,			 0, 0,	200 },	// D2
	{ "VideoControl",	VideodiscXObj::m_videoControl,	 1, 1,	200 },	// D2
	{ "AudioControl",	VideodiscXObj::m_audioControl,	 1, 1,	200 },	// D2
	{ "Status",			VideodiscXObj::m_status,		 0, 0,	200 },	// D2
	{ 0, 0, 0, 0, 0 }
};

void VideodiscXObj::open(int type)

	if (type == kXObj) {
		VideodiscXObject::initMethods(xlibMethods);
		VideodiscXObject *xobj = new VideodiscXObject(kXObj);
		g_lingo->_globalvars[xlibName] = xobj;
	}
}

void VideodiscXObj::close(int type) {
	if (type == kXObj) {
		VideodiscXObject::cleanupMethods();
		g_lingo->_globalvars[xlibName] = Datum();
	}
}

VideodiscXObject::VideodiscXObject(ObjectType ObjectType) :Object<VideodiscXObject>("LaserDisc") {
	_objType = ObjectType;
}

void VideodiscXObj::m_new(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_new", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(g_lingo->_currentMe);
}

void VideodiscXObj::m_name(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_name", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_player(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_player", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_play(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_play", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playJog(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playJog", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSpeed(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSpeed", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSegment(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSegment", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_pause(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_pause", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stop(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stop", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_eject(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_eject", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stopAtFrame(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stopAtFrame", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_searchWait(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_searchWait", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_readPos(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_readPos", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_showDisplay(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_showDisplay", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_clear(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_clear", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_videoControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_videoControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_audioControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_audioControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_status(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_status", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

} // End of namespace Director


if (type == kXObj) {
		VideodiscXObject::initMethods(xlibMethods);
		VideodiscXObject *xobj = new VideodiscXObject(kXObj);
		g_lingo->_globalvars[xlibName] = xobj;
	}

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 *
 */

/*
 * mNew, portObject, baudRate, playerType  creates a
 *    new instance and returns error code
 *    portObject is an instance from SerialPort XObject.
 *    baudRate should be the same as machine setting.
 *        9600(default for Pioneer 8000),
 *        4800(preferred for Pioneer 2200, 4200),
 *        2400, and 1200.
 *    playerType:
 *        0 for Pioneer 2200, 4200 and 8000
 *        1 for Sony Laser Max 1200, 1500, and 2000
 *    Error codes:
 *        -1 : incorrect BaudRate.
 *        -2 : memory error.
 *        -3 : SerialPort Drivers would not open.
 *
 * mDispose  frees this instance from memory.
 * mName  returns my name.
 * mPlayer  returns the player.
 *
 * Note: all of the following methods will return either "OK" or an error message. Possible error messages include:
 *     "No Response" -- bad connection or wrong baud rate.
 *     "Not Ready"    -- disc ejected or motor stopped.
 *
 * mPlay  normal playback mode in the forward direction.
 * mPlayRev  playback mode in the reverse direction.
 *
 * mFastFwd  fast forward playback mode.
 *     3 times normal speed.
 * mFastRev  fast reverse playback mode.
 *     3 times normal speed.
 *
 * mSlowFwd  slow forward playback mode.
 *     1/5 times normal speed.
 * mSlowRev  slow reverse playback mode
 *     1/5 times normal speed.
 *
 * mStepFwd  step forward a single frame.
 * mStepRev  step reverse a single frame.
 *
 * mPlayJog, nFrame  step multiple frames either forward
 *     or reverse
 *
 * mPlaySpeed, rate  play at slower than normal speed.
 *     rate can be any of the following:
 *         30 is 1x; 15 is 1/2x; 10 is 1/3x; 5 is 1/6x
 *     Example: -10 is one third normal speed, backwards.
 *
 * mPlaySegment, start, end  play a segment of video disc.
 *     Start and end are frame numbers.
 *
 * mPause  set player to display freeze picture (STILL)
 *     When this method is called a second time, this will
 *     continue the mode prior to first call.
 * mStop  halts playback of videodisc.
 * mEject  opens disc compartment and ejects disc.
 *
 * mStopAtFrame, frameNum  set to stop at frameNum
 *
 * mSearchWait, frameNum  search for frameNum and
 *     returns "OK" when search is completed.
 *
 * mReadPos  return the current frame position
 * mShowDisplay, flag  enable/disable frame display
 *
 * mClear  clear all modes of player. Remove Stop markers
 *
 * mVideoControl, videoState  control squelch condition
 *     of video image.
 *
 * mAudioControl, audioState
 *     audioState is one of the following
 *         0 : Turn off both audio channels.
 *         1 : Turn on channel 1 only.
 *         2 : Turn on channel 2 only.
 *         3 : Turn on both audio channels.
 *
 * mStatus  return either "OK" or error message
 *     See the mDescribe for a full list of errors.
 */

#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/xlibs/videodiscxobj.h"

namespace Director {

const char *VideodiscXObj::xlibName = "LaserDisc";
const char *VideodiscXObj::fileNames[] = {
	"Videodisc XObj",
	0
};

static MethodProto xlibMethods[] = {
	{ "new",			VideodiscXObj::m_new,			 3, 3,	200 },	// D2
	{ "Name",			VideodiscXObj::m_name,			 0, 0,	200 },	// D2
	{ "Player",			VideodiscXObj::m_player,		 0, 0,	200 },	// D2
	{ "Play",			VideodiscXObj::m_play,			 0, 0,	200 },	// D2
	{ "PlayRev",		VideodiscXObj::m_playRev,		 0, 0,	200 },	// D2
	{ "FastFwd",		VideodiscXObj::m_fastFwd,		 0, 0,	200 },	// D2
	{ "FastRev",		VideodiscXObj::m_fastRev,		 0, 0,	200 },	// D2
	{ "SlowFwd",		VideodiscXObj::m_slowFwd,		 0, 0,	200 },	// D2
	{ "SlowRev",		VideodiscXObj::m_slowRev,		 0, 0,	200 },	// D2
	{ "StepFwd",		VideodiscXObj::m_stepFwd,		 0, 0,	200 },	// D2
	{ "StepRev",		VideodiscXObj::m_stepRev,		 0, 0,	200 },	// D2
	{ "PlayJog",		VideodiscXObj::m_playJog,		 1, 1,	200 },	// D2
	{ "PlaySpeed",		VideodiscXObj::m_playSpeed,		 1, 1,	200 },	// D2
	{ "PlaySegment",	VideodiscXObj::m_playSegment,	 2, 2,	200 },	// D2
	{ "Pause",			VideodiscXObj::m_pause,			 0, 0,	200 },	// D2
	{ "Stop",			VideodiscXObj::m_stop,			 0, 0,	200 },	// D2
	{ "Eject",			VideodiscXObj::m_eject,			 0, 0,	200 },	// D2
	{ "StopAtFrame",	VideodiscXObj::m_stopAtFrame,	 1, 1,	200 },	// D2
	{ "SearchWait",		VideodiscXObj::m_searchWait,	 1, 1,	200 },	// D2
	{ "ReadPos",		VideodiscXObj::m_readPos,		 0, 0,	200 },	// D2
	{ "ShowDisplay",	VideodiscXObj::m_showDisplay,	 0, 0,	200 },	// D2
	{ "Clear",			VideodiscXObj::m_clear,			 0, 0,	200 },	// D2
	{ "VideoControl",	VideodiscXObj::m_videoControl,	 1, 1,	200 },	// D2
	{ "AudioControl",	VideodiscXObj::m_audioControl,	 1, 1,	200 },	// D2
	{ "Status",			VideodiscXObj::m_status,		 0, 0,	200 },	// D2
	{ 0, 0, 0, 0, 0 }
};

void VideodiscXObj::open(int type) {

}

void VideodiscXObj::close(int type) {
	if (type == kXObj) {
		VideodiscXObject::cleanupMethods();
		g_lingo->_globalvars[xlibName] = Datum();
	}
}

VideodiscXObject::VideodiscXObject(ObjectType ObjectType) :Object<VideodiscXObject>("LaserDisc") {
	_objType = ObjectType;
}

void VideodiscXObj::m_new(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_new", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(g_lingo->_currentMe);
}

void VideodiscXObj::m_name(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_name", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_player(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_player", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_play(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_play", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playJog(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playJog", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSpeed(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSpeed", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSegment(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSegment", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_pause(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_pause", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stop(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stop", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_eject(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_eject", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stopAtFrame(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stopAtFrame", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_searchWait(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_searchWait", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_readPos(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_readPos", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_showDisplay(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_showDisplay", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_clear(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_clear", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_videoControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_videoControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_audioControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_audioControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_status(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_status", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

} // End of namespace Director


/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 *
 */

/*
 * mNew, portObject, baudRate, playerType  creates a
 *    new instance and returns error code
 *    portObject is an instance from SerialPort XObject.
 *    baudRate should be the same as machine setting.
 *        9600(default for Pioneer 8000),
 *        4800(preferred for Pioneer 2200, 4200),
 *        2400, and 1200.
 *    playerType:
 *        0 for Pioneer 2200, 4200 and 8000
 *        1 for Sony Laser Max 1200, 1500, and 2000
 *    Error codes:
 *        -1 : incorrect BaudRate.
 *        -2 : memory error.
 *        -3 : SerialPort Drivers would not open.
 *
 * mDispose  frees this instance from memory.
 * mName  returns my name.
 * mPlayer  returns the player.
 *
 * Note: all of the following methods will return either "OK" or an error message. Possible error messages include:
 *     "No Response" -- bad connection or wrong baud rate.
 *     "Not Ready"    -- disc ejected or motor stopped.
 *
 * mPlay  normal playback mode in the forward direction.
 * mPlayRev  playback mode in the reverse direction.
 *
 * mFastFwd  fast forward playback mode.
 *     3 times normal speed.
 * mFastRev  fast reverse playback mode.
 *     3 times normal speed.
 *
 * mSlowFwd  slow forward playback mode.
 *     1/5 times normal speed.
 * mSlowRev  slow reverse playback mode
 *     1/5 times normal speed.
 *
 * mStepFwd  step forward a single frame.
 * mStepRev  step reverse a single frame.
 *
 * mPlayJog, nFrame  step multiple frames either forward
 *     or reverse
 *
 * mPlaySpeed, rate  play at slower than normal speed.
 *     rate can be any of the following:
 *         30 is 1x; 15 is 1/2x; 10 is 1/3x; 5 is 1/6x
 *     Example: -10 is one third normal speed, backwards.
 *
 * mPlaySegment, start, end  play a segment of video disc.
 *     Start and end are frame numbers.
 *
 * mPause  set player to display freeze picture (STILL)
 *     When this method is called a second time, this will
 *     continue the mode prior to first call.
 * mStop  halts playback of videodisc.
 * mEject  opens disc compartment and ejects disc.
 *
 * mStopAtFrame, frameNum  set to stop at frameNum
 *
 * mSearchWait, frameNum  search for frameNum and
 *     returns "OK" when search is completed.
 *
 * mReadPos  return the current frame position
 * mShowDisplay, flag  enable/disable frame display
 *
 * mClear  clear all modes of player. Remove Stop markers
 *
 * mVideoControl, videoState  control squelch condition
 *     of video image.
 *
 * mAudioControl, audioState
 *     audioState is one of the following
 *         0 : Turn off both audio channels.
 *         1 : Turn on channel 1 only.
 *         2 : Turn on channel 2 only.
 *         3 : Turn on both audio channels.
 *
 * mStatus  return either "OK" or error message
 *     See the mDescribe for a full list of errors.
 */

#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/xlibs/videodiscxobj.h"

namespace Director {

const char *VideodiscXObj::xlibName = "LaserDisc";
const char *VideodiscXObj::fileNames[] = {
	"Videodisc XObj",
	0
};

static MethodProto xlibMethods[] = {
	{ "new",			VideodiscXObj::m_new,			 3, 3,	200 },	// D2
	{ "Name",			VideodiscXObj::m_name,			 0, 0,	200 },	// D2
	{ "Player",			VideodiscXObj::m_player,		 0, 0,	200 },	// D2
	{ "Play",			VideodiscXObj::m_play,			 0, 0,	200 },	// D2
	{ "PlayRev",		VideodiscXObj::m_playRev,		 0, 0,	200 },	// D2
	{ "FastFwd",		VideodiscXObj::m_fastFwd,		 0, 0,	200 },	// D2
	{ "FastRev",		VideodiscXObj::m_fastRev,		 0, 0,	200 },	// D2
	{ "SlowFwd",		VideodiscXObj::m_slowFwd,		 0, 0,	200 },	// D2
	{ "SlowRev",		VideodiscXObj::m_slowRev,		 0, 0,	200 },	// D2
	{ "StepFwd",		VideodiscXObj::m_stepFwd,		 0, 0,	200 },	// D2
	{ "StepRev",		VideodiscXObj::m_stepRev,		 0, 0,	200 },	// D2
	{ "PlayJog",		VideodiscXObj::m_playJog,		 1, 1,	200 },	// D2
	{ "PlaySpeed",		VideodiscXObj::m_playSpeed,		 1, 1,	200 },	// D2
	{ "PlaySegment",	VideodiscXObj::m_playSegment,	 2, 2,	200 },	// D2
	{ "Pause",			VideodiscXObj::m_pause,			 0, 0,	200 },	// D2
	{ "Stop",			VideodiscXObj::m_stop,			 0, 0,	200 },	// D2
	{ "Eject",			VideodiscXObj::m_eject,			 0, 0,	200 },	// D2
	{ "StopAtFrame",	VideodiscXObj::m_stopAtFrame,	 1, 1,	200 },	// D2
	{ "SearchWait",		VideodiscXObj::m_searchWait,	 1, 1,	200 },	// D2
	{ "ReadPos",		VideodiscXObj::m_readPos,		 0, 0,	200 },	// D2
	{ "ShowDisplay",	VideodiscXObj::m_showDisplay,	 0, 0,	200 },	// D2
	{ "Clear",			VideodiscXObj::m_clear,			 0, 0,	200 },	// D2
	{ "VideoControl",	VideodiscXObj::m_videoControl,	 1, 1,	200 },	// D2
	{ "AudioControl",	VideodiscXObj::m_audioControl,	 1, 1,	200 },	// D2
	{ "Status",			VideodiscXObj::m_status,		 0, 0,	200 },	// D2
	{ 0, 0, 0, 0, 0 }
};

void VideodiscXObj::open(int type) {
	if (type == kXObj) {
		VideodiscXObject::initMethods(xlibMethods);
		VideodiscXObject *xobj = new VideodiscXObject(kXObj);
		g_lingo->_globalvars[xlibName] = xobj;
	}

void VideodiscXObj::close(int type) {
	if (type == kXObj) {
		VideodiscXObject::cleanupMethods();
		g_lingo->_globalvars[xlibName] = Datum();
	}
}

VideodiscXObject::VideodiscXObject(ObjectType ObjectType) :Object<VideodiscXObject>("LaserDisc") {
	_objType = ObjectType;
}

void VideodiscXObj::m_new(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_new", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(g_lingo->_currentMe);
}

void VideodiscXObj::m_name(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_name", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_player(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_player", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_play(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_play", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playJog(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playJog", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSpeed(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSpeed", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSegment(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSegment", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_pause(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_pause", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stop(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stop", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_eject(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_eject", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stopAtFrame(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stopAtFrame", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_searchWait(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_searchWait", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_readPos(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_readPos", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_showDisplay(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_showDisplay", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_clear(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_clear", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_videoControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_videoControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_audioControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_audioControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_status(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_status", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

} // End of namespace Director


/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 *
 */

/*
 * mNew, portObject, baudRate, playerType  creates a
 *    new instance and returns error code
 *    portObject is an instance from SerialPort XObject.
 *    baudRate should be the same as machine setting.
 *        9600(default for Pioneer 8000),
 *        4800(preferred for Pioneer 2200, 4200),
 *        2400, and 1200.
 *    playerType:
 *        0 for Pioneer 2200, 4200 and 8000
 *        1 for Sony Laser Max 1200, 1500, and 2000
 *    Error codes:
 *        -1 : incorrect BaudRate.
 *        -2 : memory error.
 *        -3 : SerialPort Drivers would not open.
 *
 * mDispose  frees this instance from memory.
 * mName  returns my name.
 * mPlayer  returns the player.
 *
 * Note: all of the following methods will return either "OK" or an error message. Possible error messages include:
 *     "No Response" -- bad connection or wrong baud rate.
 *     "Not Ready"    -- disc ejected or motor stopped.
 *
 * mPlay  normal playback mode in the forward direction.
 * mPlayRev  playback mode in the reverse direction.
 *
 * mFastFwd  fast forward playback mode.
 *     3 times normal speed.
 * mFastRev  fast reverse playback mode.
 *     3 times normal speed.
 *
 * mSlowFwd  slow forward playback mode.
 *     1/5 times normal speed.
 * mSlowRev  slow reverse playback mode
 *     1/5 times normal speed.
 *
 * mStepFwd  step forward a single frame.
 * mStepRev  step reverse a single frame.
 *
 * mPlayJog, nFrame  step multiple frames either forward
 *     or reverse
 *
 * mPlaySpeed, rate  play at slower than normal speed.
 *     rate can be any of the following:
 *         30 is 1x; 15 is 1/2x; 10 is 1/3x; 5 is 1/6x
 *     Example: -10 is one third normal speed, backwards.
 *
 * mPlaySegment, start, end  play a segment of video disc.
 *     Start and end are frame numbers.
 *
 * mPause  set player to display freeze picture (STILL)
 *     When this method is called a second time, this will
 *     continue the mode prior to first call.
 * mStop  halts playback of videodisc.
 * mEject  opens disc compartment and ejects disc.
 *
 * mStopAtFrame, frameNum  set to stop at frameNum
 *
 * mSearchWait, frameNum  search for frameNum and
 *     returns "OK" when search is completed.
 *
 * mReadPos  return the current frame position
 * mShowDisplay, flag  enable/disable frame display
 *
 * mClear  clear all modes of player. Remove Stop markers
 *
 * mVideoControl, videoState  control squelch condition
 *     of video image.
 *
 * mAudioControl, audioState
 *     audioState is one of the following
 *         0 : Turn off both audio channels.
 *         1 : Turn on channel 1 only.
 *         2 : Turn on channel 2 only.
 *         3 : Turn on both audio channels.
 *
 * mStatus  return either "OK" or error message
 *     See the mDescribe for a full list of errors.
 */

#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/xlibs/videodiscxobj.h"

namespace Director {

const char *VideodiscXObj::xlibName = "LaserDisc";
const char *VideodiscXObj::fileNames[] = {
	"Videodisc XObj",
	0
};

static MethodProto xlibMethods[] = {
	{ "new",			VideodiscXObj::m_new,			 3, 3,	200 },	// D2
	{ "Name",			VideodiscXObj::m_name,			 0, 0,	200 },	// D2
	{ "Player",			VideodiscXObj::m_player,		 0, 0,	200 },	// D2
	{ "Play",			VideodiscXObj::m_play,			 0, 0,	200 },	// D2
	{ "PlayRev",		VideodiscXObj::m_playRev,		 0, 0,	200 },	// D2
	{ "FastFwd",		VideodiscXObj::m_fastFwd,		 0, 0,	200 },	// D2
	{ "FastRev",		VideodiscXObj::m_fastRev,		 0, 0,	200 },	// D2
	{ "SlowFwd",		VideodiscXObj::m_slowFwd,		 0, 0,	200 },	// D2
	{ "SlowRev",		VideodiscXObj::m_slowRev,		 0, 0,	200 },	// D2
	{ "StepFwd",		VideodiscXObj::m_stepFwd,		 0, 0,	200 },	// D2
	{ "StepRev",		VideodiscXObj::m_stepRev,		 0, 0,	200 },	// D2
	{ "PlayJog",		VideodiscXObj::m_playJog,		 1, 1,	200 },	// D2
	{ "PlaySpeed",		VideodiscXObj::m_playSpeed,		 1, 1,	200 },	// D2
	{ "PlaySegment",	VideodiscXObj::m_playSegment,	 2, 2,	200 },	// D2
	{ "Pause",			VideodiscXObj::m_pause,			 0, 0,	200 },	// D2
	{ "Stop",			VideodiscXObj::m_stop,			 0, 0,	200 },	// D2
	{ "Eject",			VideodiscXObj::m_eject,			 0, 0,	200 },	// D2
	{ "StopAtFrame",	VideodiscXObj::m_stopAtFrame,	 1, 1,	200 },	// D2
	{ "SearchWait",		VideodiscXObj::m_searchWait,	 1, 1,	200 },	// D2
	{ "ReadPos",		VideodiscXObj::m_readPos,		 0, 0,	200 },	// D2
	{ "ShowDisplay",	VideodiscXObj::m_showDisplay,	 0, 0,	200 },	// D2
	{ "Clear",			VideodiscXObj::m_clear,			 0, 0,	200 },	// D2
	{ "VideoControl",	VideodiscXObj::m_videoControl,	 1, 1,	200 },	// D2
	{ "AudioControl",	VideodiscXObj::m_audioControl,	 1, 1,	200 },	// D2
	{ "Status",			VideodiscXObj::m_status,		 0, 0,	200 },	// D2
	{ 0, 0, 0, 0, 0 }
};

void VideodiscXObj::open(int type) {
	if (type == kXObj) {
		VideodiscXObject::initMethods(xlibMethods);
		VideodiscXObject *xobj = new VideodiscXObject(kXObj);
		g_lingo->_globalvars[xlibName] = xobj;
	}
}

void VideodiscXObj::close(int type) {
	if (type == kXObj) {
		VideodiscXObject::cleanupMethods();
		g_lingo->_globalvars[xlibName] = Datum();
	}
}

VideodiscXObject::VideodiscXObject(ObjectType ObjectType) :Object<VideodiscXObject>("LaserDisc") {
	_objType = ObjectType;
}

void VideodiscXObj::m_new(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_new", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(g_lingo->_currentMe);
}

void VideodiscXObj::m_name(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_name", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_player(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_player", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_play(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_play", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_fastFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_fastRev(int nargs) {
	g_lingo->printS

	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_slowRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_slowRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepFwd(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepFwd", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stepRev(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stepRev", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playJog(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playJog", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSpeed(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSpeed", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_playSegment(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_playSegment", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_pause(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_pause", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stop(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stop", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_eject(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_eject", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_stopAtFrame(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_stopAtFrame", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_searchWait(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_searchWait", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_readPos(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_readPos", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_showDisplay(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_showDisplay", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_clear(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_clear", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_videoControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_videoControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_audioControl(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_audioControl", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

void VideodiscXObj::m_status(int nargs) {
	g_lingo->printSTUBWithArglist("VideodiscXObj::m_status", nargs);
	g_lingo->dropStack(nargs);
	g_lingo->push(Datum());
}

} // End of namespace Director


// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )

	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}

// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;

	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EX

}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}
}


if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}

// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;
	while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);


while(1)
	{
		cin >> n;
		HANDLE hThread = CreateThread(NULL, 0, // 1MB Stack Memory
				ThreadFunc, (void*)n, 0, 0);

		cout << "잠시 대기"  << endl;
		WaitForSingleObject( hThread, INFINITE);

		DWORD code;
		GetExitCodeThread(hThread, &code);
		if( code == -1 )
		{
			cout << "값이 너무 크다. " << endl;
		}
		else
		{
			cout << "결과 : " << code << endl;
		}
		CloseHandle(hThread);
	}

// Thread Stack

#include <windows.h>
#include <iostream>
using namespace std;

/*
스레드 생성시 IMB stack이 만들어짐
PAGE_READWRITE 영역 : 4K 사용할 수 있는 영역
PAGE_GUARD			: 사용 불가능, 이동 영역
PAGE_RESERVER		: 예약 영역

=> 사용량이 늘어날때마다 4K 단위로
   PAGE_READWRITE와 PAGE_GUARD 영역이 이동함

만약 끝까지 차게 되면 Exception 에러 발생(overflow)
*/
int Sum( int n )
{
	// Sum을 재귀적 호출
	return n == 0 ? 0 : ( n + Sum(n - 1) );
}

DWORD Handler( DWORD e )
{
	if ( e == EXCEPTION_STACK_OVERFLOW)
		cout << "stack overflow" << endl;
	return EXCEPTION_EXECUTE_HANDLER;
}
DWORD WINAPI ThreadFunc( LPVOID p)
{
	int n= (int)p;

	int s = -1;
	__try{
		// s에서 n까지의 합계를 저장
		s = Sum(n);
	}
	__except( Handler(GetExceptionCode()) )
	{
		cout << " 예외 발생 " << endl;
	}
	return s;
}

void main()
{
	int n;


template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {

{
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


{
    return 1; // expected-error{{void function 'g' should not return a value}}
  }

template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const

};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l)

    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }

template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {

  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }

};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Labe

  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }

template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {
    while (t) {
    }

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {

  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}


template<typename T, typename U>
struct X0 {
  void f(T x, U y) {
    (void)(x + y); // expected-error{{invalid operands}}
  }
};

struct X1 { };

template struct X0<int, float>;
template struct X0<int*, int>;
template struct X0<int X1::*, int>; // expected-note{{instantiation of}}

template<typename T>
struct X2 {
  void f(T);

  T g(T x, T y) {
    /* DeclStmt */;
    T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
    /* NullStmt */;
  }
};

template struct X2<int>;
template struct X2<int&>; // expected-note{{instantiation of}}

template<typename T>
struct X3 {
  void f(T) {
    Label:
    T x;
    goto Label;
  }
};

template struct X3<int>;

template <typename T> struct X4 {
  T f() const {
    return; // expected-error{{non-void function 'f' should return a value}}
  }

  T g() const {
    return 1; // expected-error{{void function 'g' should not return a value}}
  }
};

template struct X4<void>; // expected-note{{in instantiation of}}
template struct X4<int>; // expected-note{{in instantiation of}}

struct Incomplete; // expected-note 2{{forward declaration}}

template<typename T> struct X5 {
  T f() { } // expected-error{{incomplete result type}}
};
void test_X5(X5<Incomplete> x5); // okay!

template struct X5<Incomplete>; // expected-note{{instantiation}}

template<typename T, typename U, typename V> struct X6 {
  U f(T t, U u, V v) {
    // IfStmt
    if (t > 0)
      return u;
    else {
      if (t < 0)
        return v; // expected-error{{cannot initialize return object of type}}
    }

    if (T x = t) {
      t = x;
    }
    return v; // expected-error{{cannot initialize return object of type}}
  }
};

struct ConvertibleToInt {
  operator int() const;
};

template struct X6<ConvertibleToInt, float, char>;
template struct X6<bool, int, int*>; // expected-note{{instantiation}}

template <typename T> struct X7 {
  void f() {
    void *v = this;
  }
};

template struct X7<int>;

template<typename T> struct While0 {
  void f(T t) {

    while (T t2 = T()) ;
  }
};

template struct While0<float>;

template<typename T> struct Do0 {
  void f(T t) {
    do {
    } while (t); // expected-error{{not contextually}}
  }
};

struct NotConvertibleToBool { };
template struct Do0<ConvertibleToInt>;
template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}

template<typename T> struct For0 {
  void f(T f, T l) {
    for (; f != l; ++f) {
      if (*f)
        continue;
      else if (*f == 17)
        break;
    }
  }
};

template struct For0<int*>;

template<typename T> struct Member0 {
  void f(T t) {
    t;
    t.f;
    t->f;

    T* tp;
    tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
    tp->f;

    this->f;
    this.f; // expected-error{{member reference base type 'Member0<T> *' is not a structure or union}}
  }
};

template<typename T, typename U> struct Switch0 {
  U f(T value, U v0, U v1, U v2) {
    switch (value) {
    case 0: return v0;

    case 1: return v1;

    case 2: // fall through

    default:
      return  v2;
    }
  }
};

template struct Switch0<int, float>;

template<typename T, int I1, int I2> struct Switch1 {
  T f(T x, T y, T z) {
    switch (x) {
    case I1: return y; // expected-note{{previous}}
    case I2: return z; // expected-error{{duplicate}}
    default: return x;
    }
  }
};

template struct Switch1<int, 1, 2>;
template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}

template<typename T> struct IndirectGoto0 {
  void f(T x) {
    // FIXME: crummy error message below
    goto *x; // expected-error{{incompatible}}

  prior:
    T prior_label;
    prior_label = &&prior; // expected-error{{assigning to 'int'}}

    T later_label;
    later_label = &&later; // expected-error{{assigning to 'int'}}

  later:
    (void)(1+1);
  }
};

template struct IndirectGoto0<void*>;
template struct IndirectGoto0<int>; // expected-note{{instantiation}}

template<typename T> struct TryCatch0 {
  void f() {
    try {
    } catch (T t) { // expected-error{{incomplete type}} \
    } catch (...) {
    }
  }
};

struct Abstract {
  virtual void foo() = 0; // expected-note{{pure virtual}}
};

template struct TryCatch0<int>; // okay
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}

// PR4383
template<typename T> struct X;
template<typename T> struct Y : public X<T> {
  Y& x() { return *this; }
};

// Make sure our assertions don't get too uppity.
namespace test0 {
  template <class T> class A { void foo(T array[10]); };
  template class A<int>;
}

namespace PR7016 {
  template<typename T> void f() { T x = x; }
  template void f<int>();
}

namespace PR9880 {
  struct lua_State;
  struct no_tag { char a; };			// (A)
  struct yes_tag { long a; long b; };	// (A)

  template <typename T>
  struct HasIndexMetamethod {
    template <typename U>
    static no_tag check(...);
    template <typename U>
    static yes_tag check(char[sizeof(&U::luaIndex)]);
    enum { value = sizeof(check<T>(0)) == sizeof(yes_tag) };
  };

  class SomeClass {
  public:
    int luaIndex(lua_State* L);
  };

  int i = HasIndexMetamethod<SomeClass>::value;
}