1/* A stupid little spinning wheel designed to make it look like useful work
2   is being done.
3
4Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
5
6This file is part of the GNU MP Library.
7
8The GNU MP Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MP Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
20
21#include "config.h"
22
23#include <signal.h>
24#include <stdio.h>
25#include <stdlib.h>
26#if HAVE_UNISTD_H
27#include <unistd.h>     /* for isatty */
28#endif
29
30#include "gmp.h"
31#include "gmp-impl.h"
32
33#include "tests.h"
34
35
36/* "alarm" is not available on mingw32, and the SIGALRM constant is not
37   defined.  Don't bother with a spinner in this case.  */
38#if ! HAVE_ALARM || ! defined (SIGALRM)
39#define alarm(n)          abort()
40#define signal(sig,func)  SIG_ERR
41#endif
42
43
44/* An application can update this to get a count printed with the spinner.
45   If left at 0, no count is printed. */
46
47unsigned long  spinner_count = 0;
48
49
50int  spinner_wanted = -1;  /* -1 uninitialized, 1 wanted, 0 not */
51int  spinner_tick = 1;     /* 1 ready to print, 0 not */
52
53
54/*ARGSUSED*/
55RETSIGTYPE
56spinner_signal (int signum)
57{
58  spinner_tick = 1;
59
60  if (signal (SIGALRM, spinner_signal) == SIG_ERR)
61    {
62      printf ("spinner_signal(): Oops, cannot reinstall SIGALRM\n");
63      abort ();
64    }
65  alarm (1);
66}
67
68
69/* Initialize the spinner.
70
71   This is done the first time spinner() is called, so an application
72   doesn't need to call this directly.
73
74   The spinner is only wanted if the output is a tty.  */
75
76#define SPINNER_WANTED_INIT() \
77  if (spinner_wanted < 0) spinner_init ()
78
79void
80spinner_init (void)
81{
82  spinner_wanted = isatty (fileno (stdout));
83  if (spinner_wanted == -1)
84    abort ();
85
86  if (!spinner_wanted)
87    return;
88
89  if (signal (SIGALRM, spinner_signal) == SIG_ERR)
90    {
91      printf ("(no spinner)\r");
92      spinner_tick = 0;
93      return;
94    }
95  alarm (1);
96
97  /* unbufferred output so the spinner will show up */
98  setbuf (stdout, NULL);
99}
100
101
102void
103spinner (void)
104{
105  static const char  data[] = { '|', '/', '-', '\\' };
106  static int         pos = 0;
107
108  char  buf[128];
109
110  SPINNER_WANTED_INIT ();
111
112  if (spinner_tick)
113    {
114      buf[0] = data[pos];
115      pos = (pos + 1) % numberof (data);
116      spinner_tick = 0;
117
118      if (spinner_count != 0)
119	{
120	  sprintf (buf+1, " %lu\r", spinner_count);
121	}
122      else
123	{
124	  buf[1] = '\r';
125	  buf[2] = '\0';
126	}
127      fputs (buf, stdout);
128    }
129}
130