f9f3b529a1040a7b5021b7ebe9b569b3cc4388f2
[matches/honours.git] / course / semester2 / pprog / assignment1 / single-thread / main.c
1 /**
2  * @file main.c
3  * @author Sam Moore (20503628) - 2012
4  * @purpose Contains main function, argument handling
5  * NOTE: This file is identical for both the single-threaded and multi-threaded versions of the program
6  */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <time.h>
11 #include <signal.h>
12
13 #include "nbody.h"
14 #include "graphics.h"
15
16 // --- Variable definitions --- //
17 System universe; // global variable declared in "nbody.h" - The universe of bodies
18 Options options; // global variable declared in "nbody.h" - Options passed to program through arguments
19
20
21 // --- Function forward declarations --- //
22 void HandleArguments(int argc, char ** argv); //Interprets program arguments and sets up the "options" variable
23 void UnsignedArgument(unsigned * i, int argc, char ** argv, unsigned * store); //Helper function to get switch value for unsigned
24 void FloatArgument(unsigned * i, int argc, char ** argv, float * store); //Helper function to get switch value for float
25 void DisplayStatistics(); //Called on exit of program, displays information about computation time, steps computed, etc
26 void Interrupt(int dummy); // Interrupt handler function, called when SIGINT (Ctrl-C) is sent to program
27
28 // --- Function implementations --- //
29
30 /**
31  * @function main
32  * @purpose The main function. Calls HandleArguments to set up options, 
33  *              sets up functions to call at exit, starts simulation and graphics loops
34  * @param argc - Number of arguments
35  * @param argv - The argument strings
36  */
37 int main(int argc, char** argv)
38 {
39         //Set default options values here
40         options.program = argv[0];
41         options.input = NULL;
42         options.output = NULL;
43         options.num_threads = 0;
44         options.num_steps = 0;
45         options.timeout = 0;
46         options.draw_graphics = true;
47         options.print_positions = false;
48         options.verbosity = 0;
49
50         //If there are no arguments, print information about usage
51         if (argc == 1)
52         {
53                 printf("Usage: %s [OPTIONS] field\n", argv[0]);
54                 printf("Controls:\n X - exit\n I, J, K, M - rotate\n W, Z, A, S - move to view"
55                         " point\n ./, - zoom in/out\n +/- - scaled zoom in/out\n");
56                 exit(EXIT_SUCCESS);
57         }
58
59         //Parse the arguments
60         HandleArguments(argc, argv);
61         
62         //Check there is an initial field.
63         if (options.input == NULL)
64         {
65                 fprintf(stderr, "Usage: %s [OPTIONS] field\n", argv[0]);
66                 fprintf(stderr, " (You did not provide a file for the initial field of bodies)\n");
67                 exit(EXIT_FAILURE);
68         }
69
70         signal(SIGINT, Interrupt); //Handle SIGINT signals
71         atexit(Universe_Cleanup); //On exit, cleanup universe (and write positions of bodies to file if supplied).
72         atexit(DisplayStatistics); //On exit, print information about the computations done
73         System_Init(&universe,options.input); //Initialise the universe from the initial field
74         
75         //Setup the time of day at which the simulation starts
76         if (gettimeofday(&(options.start_time), NULL) != 0)
77         {
78                 perror("Couldn't get time of day");
79                 exit(EXIT_FAILURE);
80         }
81         
82         options.start_clock = clock(); //Get CPU cycles executed before simulation starts
83         Simulation_Run(); // Start the simulation
84         Graphics_Run(argc, argv); //Start the graphics loop
85
86         exit(EXIT_FAILURE); //Should never get to this line
87 }
88
89
90 /**
91  * @function HandleArguments
92  * @purpose Fill the "options" variable by parsing command line arguments
93  * @param argc - Number of arguments
94  * @param argv - Argument strings
95  */
96 void HandleArguments(int argc, char ** argv)
97 {
98         for (unsigned i = 1; i < argc; ++i) //For all arguments
99         {
100                 if (argv[i][0] != '-') //If the argument is not a switch value...
101                 {
102                         //Interpret first non switch as input file, and second as output file.
103                         //If there are too many non switch arguments, give an error.
104                         if (options.input == NULL) 
105                                 options.input = argv[i];
106                         else if (options.output == NULL)
107                                 options.output = argv[i];
108                         else
109                         {
110                                 fprintf(stderr,"Usage: %s [OPTIONS] field [output]\n", argv[0]);
111                                 fprintf(stderr," (You provided too many file names)\n");
112                                 exit(EXIT_FAILURE);
113                         }
114                         continue;
115                 }
116                 switch (argv[i][1]) //The argument is a switch if we get here
117                 {
118                         case 'n': //Number of threads switch
119                                 UnsignedArgument(&i, argc, argv, &(options.num_threads));
120                                 #ifdef SINGLE_THREADED
121                                 fprintf(stderr, "Warning: -%c switch has no effect in the single-threaded program.\n", argv[i][1]);
122                                 options.num_threads = 1;
123                                 #endif //SINGLE_THREADED
124                                 break;
125                         case 's': //Number of steps switch
126                                 UnsignedArgument(&i, argc, argv, &(options.num_steps));
127                                 break;
128                         case 't': //Timeout switch (in seconds)
129                                 UnsignedArgument(&i, argc, argv, &(options.timeout));
130                                 break;
131                         case 'g': //Graphics switch
132                                 options.draw_graphics = !options.draw_graphics;
133                                 break;
134                         case 'v': //Verbosity switch
135                                 UnsignedArgument(&i, argc, argv, &(options.verbosity));
136                                 break;
137
138                         default:
139                                 fprintf(stderr, "Unrecognised switch -%c\n", argv[i][1]);
140                                 exit(EXIT_FAILURE);
141                                 break;
142                 }
143                 
144         }
145 }
146
147 /**
148  * @function UnsignedArgument
149  * @purpose Helper function to get an unsigned integer following a argument switch
150  * @param i - position in the argument array, will be updated after this function
151  * @param argc - number of arguments
152  * @param argv - argument strings
153  * @param store - pointer to unsigned to store result in
154  */
155 void UnsignedArgument(unsigned * i, int argc, char ** argv, unsigned * store)
156 {
157         if (*i >= argc-1)
158         {
159                 fprintf(stderr,"Supply a positive integer for the -%c switch.\n", argv[*i][1]);
160                 exit(EXIT_FAILURE);
161         }
162         int val = atoi(argv[*i+1]);
163         if (val <= 0)
164         {
165                 fprintf(stderr,"Supply a positive integer for the -%c switch. %s is invalid.\n", argv[*i][1], argv[*i+1]);
166                 exit(EXIT_FAILURE);
167         }
168         *store = val;
169         *i += 1;
170 }
171 /**
172  * @function FloatArgument
173  * @purpose Helper function to get a float following a argument switch
174  * @param i - position in the argument array, will be updated after this function
175  * @param argc - number of arguments
176  * @param argv - argument strings
177  * @param store - pointer to float to store result in
178  */
179 void FloatArgument(unsigned * i, int argc, char ** argv, float * store)
180 {
181         if (*i >= argc-1)
182         {
183                 fprintf(stderr,"Supply a float for the -%c switch.\n", argv[*i][1]);
184                 exit(EXIT_FAILURE);
185         }
186         *store = atof(argv[*i+1]);
187         if (*store == 0.0 && argv[*i+1][0] != '0')
188         {
189                 fprintf(stderr,"Supply a float for the -%c switch.\n", argv[*i][1]);
190                 exit(EXIT_FAILURE);
191         }
192         *i += 1;
193 }
194
195
196
197 /**
198  * @function Interrupt
199  * @purpose Handle SIGINT signal; quit the program gracefully, so that statistics are still displayed
200  * @param dummy - a dummy
201  */
202
203 void Interrupt(int dummy)
204 {
205         QuitProgram(false);
206 }
207

UCC git Repository :: git.ucc.asn.au