#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cassert>
#include<cstdio>
#include<iomanip>
#include<queue>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define MAX 300
#define all(n) (n).begin(),(n).end()

using namespace std;

// ----------------------------------------

class Point
{
  public:
  double x,y;

  Point(double x = -inf,double y = -inf): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}

  bool operator < (const Point& p) const
  {
    return !equals(x,p.x)?x<p.x:y<p.y;
  }

  bool operator == (const Point& p)const
  {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }

};

struct Segment
{
  Point p1,p2;
  Segment(Point p1 = Point(-inf,-inf),Point p2 = Point(-inf,-inf)):p1(p1),p2(p2){}
  bool operator == (const Segment& p)const
  {
    return p.p1 == p1 && p.p2 == p2;
  }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a)
{
  os << "(" << a.x << "," << a.y << ")";
}

ostream& operator << (ostream& os,const Segment& a)
{
  os << "( " << a.p1 << " , " << a.p2 << " )";
}

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

int ccw(Point p0,Point p1,Point p2)
{
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}
Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) return m.p1; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m.p1 +   (m.p2 - m.p1) * (B / A);
}

struct Edge
{
  int from,to;
  double cost;
  Edge(int from=inf,int to=inf,double cost=inf):from(from),to(to),cost(cost){}
  bool operator < (const Edge& a)const
  {
    return cost < a.cost;
  }
};


Point start,goal;
vector<vector<Edge> > segmentArrangement(vector<Segment> vs,vector<Point> &ps)
{
/*
端点もいれたいなら
ここであらかじめ端点だけpsにいれる
*/
  rep(i,vs.size())
    REP(j,i+1,vs.size())
      if(intersectSS(vs[i],vs[j]))
        ps.push_back(Point(crosspoint(vs[i],vs[j])));

  //
  ps.push_back(start);
  ps.push_back(goal);
  //

  sort(ps.begin(),ps.end());  
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  vector<vector<Edge> > ret(ps.size());

  for(int i=0;i<vs.size();i++)
    {
      vector<pair<double,int> > list;
      rep(j,ps.size())
	if(intersectSP(vs[i],ps[j]))
	  list.push_back(pair<double,int>(norm(vs[i].p1-ps[j]),j));

      sort(list.begin(),list.end());

      //for(int j=0;j<list.size()-1;++j) is not good
      for(int j=0;j+1<list.size();++j)
	{
	  int from = list[j].second, to = list[j+1].second;
	  double cost = abs(ps[from]-ps[to]);
	  ret[from].push_back(Edge(from,to,cost));
	  ret[to].push_back(Edge(to,from,cost));
	}
    }  
  return ret;
}


// --------------------------------------------------


struct Pox
{
  int cur;
  double cost;
  Pox(int cur=inf,double cost=inf):cur(cur),cost(cost){}
  bool operator < (const Pox &a)const
  {
    return cost > a.cost;
  }
};

int n;
Segment seg[MAX];
vector<Segment> road,sign;

double getArg(Point A,Point B,Point C)
{
  double a = abs(B-C);
  double b = abs(A-C);
  double c = abs(A-B);
  return acos((b*b+c*c-a*a)/(2.0*b*c));
}

bool check(Segment s)
{
  rep(i,sign.size())
    if(intersectSS(sign[i],s))
      {
	Point a = crosspoint(sign[i],s);
	Point b = s.p1;
	Point c = (a==sign[i].p1?sign[i].p2:sign[i].p1);
	double arg = getArg(a,b,c);
	if(equals(arg,toRad(90.0)))return false;
	if(arg > toRad(90.0))return false;
      }
  return true;
}

void compute()
{
  vector<Point> ps;
  vector<vector<Edge> > g = segmentArrangement(road,ps);



  int size = ps.size();
  double mincost[size];
  int path[size];
  rep(i,size)mincost[i] = path[i] = inf;

  int s,t;
  s = t = -1;
  rep(i,size)
    if(ps[i] == start)s = i;
    else if(ps[i] == goal)t = i;
  assert(s != -1 && t != -1);

  mincost[s] = 0;
  priority_queue<Pox> Q;
  Q.push(Pox(s,0));

  while(!Q.empty())
    {
      Pox pox = Q.top(); Q.pop();

      if(pox.cur == t)
	{
	  vector<Point> ans;
	  for(int p=t;;p=path[p])
	    {
	      ans.push_back(ps[p]);
	      if(p == s)break;
	    }
	  reverse(all(ans));
	  rep(i,ans.size())
	    printf("%.0lf %.0lf\n",ans[i].x,ans[i].y);
	  puts("0");
	  return;
	}

      rep(i,g[pox.cur].size())
	{
	  int to = g[pox.cur][i].to;
	  double cost = g[pox.cur][i].cost;
	  Segment s = Segment(ps[pox.cur],ps[to]);
	  if(!check(s))continue;

	  if(mincost[to] > pox.cost + cost)
	    {
	      mincost[to] = pox.cost + cost;
	      path[to] = pox.cur;
	      Q.push(Pox(to,mincost[to]));
	    }
	}

    }
  cout << -1 << endl;
}

void split_seg()
{
  road.clear();
  sign.clear();

  rep(i,n)
    {
      bool L,R;
      L = R = false;
      rep(j,n)
	{
	  if(i == j)continue;
	  if(intersectSP(seg[j],seg[i].p1))L = true;
	  if(intersectSP(seg[j],seg[i].p2))R = true;
	  if(L&R)break;
	}
      if(L&R)road.push_back(seg[i]);
      else   sign.push_back(seg[i]);
      //cout << "seg : " << seg[i] << " is " << (L&R?"road":"sign") << endl;
    }

}

int main()
{
  while(scanf("%d",&n),n)
    {
      scanf("%lf %lf",&start.x,&start.y);
      scanf("%lf %lf",&goal.x ,&goal.y);
      rep(i,n)
	{
	  double x1,y1,x2,y2;
	  scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
	  seg[i] = Segment(Point(x1,y1),Point(x2,y2));
	}	

      split_seg();
	
      compute();

    }
  return 0;
}

Measured memory_bytes: 1416