summaryrefslogtreecommitdiffstats
path: root/pacman-c++
diff options
context:
space:
mode:
Diffstat (limited to 'pacman-c++')
-rw-r--r--pacman-c++/anyoption.cpp1174
-rw-r--r--pacman-c++/anyoption.h270
-rw-r--r--pacman-c++/audio.cpp2
-rw-r--r--pacman-c++/pacman.server.pro6
-rw-r--r--pacman-c++/server.cpp146
-rw-r--r--pacman-c++/server.h11
6 files changed, 1594 insertions, 15 deletions
diff --git a/pacman-c++/anyoption.cpp b/pacman-c++/anyoption.cpp
new file mode 100644
index 0000000..5d11508
--- /dev/null
+++ b/pacman-c++/anyoption.cpp
@@ -0,0 +1,1174 @@
1/*
2 * AnyOption 1.3
3 *
4 * kishan at hackorama dot com www.hackorama.com JULY 2001
5 *
6 * + Acts as a common facade class for reading
7 * commandline options as well as options from
8 * an optionfile with delimited type value pairs
9 *
10 * + Handles the POSIX style single character options ( -w )
11 * as well as the newer GNU long options ( --width )
12 *
13 * + The option file assumes the traditional format of
14 * first character based comment lines and type value
15 * pairs with a delimiter , and flags which are not pairs
16 *
17 * # this is a coment
18 * # next line is an option value pair
19 * width : 100
20 * # next line is a flag
21 * noimages
22 *
23 * + Supports printing out Help and Usage
24 *
25 * + Why not just use getopt() ?
26 *
27 * getopt() Its a POSIX standard not part of ANSI-C.
28 * So it may not be available on platforms like Windows.
29 *
30 * + Why it is so long ?
31 *
32 * The actual code which does command line parsing
33 * and option file parsing are done in few methods.
34 * Most of the extra code are for providing a flexible
35 * common public interface to both a resourcefile and
36 * and command line supporting POSIX style and
37 * GNU long option as well as mixing of both.
38 *
39 * + Please see "anyoption.h" for public method descriptions
40 *
41 */
42
43/* Updated Auguest 2004
44 * Fix from Michael D Peters (mpeters at sandia.gov)
45 * to remove static local variables, allowing multiple instantiations
46 * of the reader (for using multiple configuration files). There is
47 * an error in the destructor when using multiple instances, so you
48 * cannot delete your objects (it will crash), but not calling the
49 * destructor only introduces a small memory leak, so I
50 * have not bothered tracking it down.
51 *
52 * Also updated to use modern C++ style headers, rather than
53 * depricated iostream.h (it was causing my compiler problems)
54*/
55
56/*
57 * Updated September 2006
58 * Fix from Boyan Asenov for a bug in mixing up option indexes
59 * leading to exception when mixing different options types
60 */
61
62#include "anyoption.h"
63
64AnyOption::AnyOption()
65{
66 init();
67}
68
69AnyOption::AnyOption(int maxopt)
70{
71 init( maxopt , maxopt );
72}
73
74AnyOption::AnyOption(int maxopt, int maxcharopt)
75{
76 init( maxopt , maxcharopt );
77}
78
79AnyOption::~AnyOption()
80{
81 if( mem_allocated )
82 cleanup();
83}
84
85void
86AnyOption::init()
87{
88 init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS );
89}
90
91void
92AnyOption::init(int maxopt, int maxcharopt )
93{
94
95 max_options = maxopt;
96 max_char_options = maxcharopt;
97 max_usage_lines = DEFAULT_MAXUSAGE;
98 usage_lines = 0 ;
99 argc = 0;
100 argv = NULL;
101 posix_style = true;
102 verbose = false;
103 filename = NULL;
104 appname = NULL;
105 option_counter = 0;
106 optchar_counter = 0;
107 new_argv = NULL;
108 new_argc = 0 ;
109 max_legal_args = 0 ;
110 command_set = false;
111 file_set = false;
112 values = NULL;
113 g_value_counter = 0;
114 mem_allocated = false;
115 command_set = false;
116 file_set = false;
117 opt_prefix_char = '-';
118 file_delimiter_char = ':';
119 file_comment_char = '#';
120 equalsign = '=';
121 comment = '#' ;
122 delimiter = ':' ;
123 endofline = '\n';
124 whitespace = ' ' ;
125 nullterminate = '\0';
126 set = false;
127 once = true;
128 hasoptions = false;
129 autousage = false;
130
131 strcpy( long_opt_prefix , "--" );
132
133 if( alloc() == false ){
134 cout << endl << "OPTIONS ERROR : Failed allocating memory" ;
135 cout << endl ;
136 cout << "Exiting." << endl ;
137 exit (0);
138 }
139}
140
141bool
142AnyOption::alloc()
143{
144 int i = 0 ;
145 int size = 0 ;
146
147 if( mem_allocated )
148 return true;
149
150 size = (max_options+1) * sizeof(const char*);
151 options = (const char**)malloc( size );
152 optiontype = (int*) malloc( (max_options+1)*sizeof(int) );
153 optionindex = (int*) malloc( (max_options+1)*sizeof(int) );
154 if( options == NULL || optiontype == NULL || optionindex == NULL )
155 return false;
156 else
157 mem_allocated = true;
158 for( i = 0 ; i < max_options ; i++ ){
159 options[i] = NULL;
160 optiontype[i] = 0 ;
161 optionindex[i] = -1 ;
162 }
163 optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) );
164 optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) );
165 optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) );
166 if( optionchars == NULL ||
167 optchartype == NULL ||
168 optcharindex == NULL )
169 {
170 mem_allocated = false;
171 return false;
172 }
173 for( i = 0 ; i < max_char_options ; i++ ){
174 optionchars[i] = '0';
175 optchartype[i] = 0 ;
176 optcharindex[i] = -1 ;
177 }
178
179 size = (max_usage_lines+1) * sizeof(const char*) ;
180 usage = (const char**) malloc( size );
181
182 if( usage == NULL ){
183 mem_allocated = false;
184 return false;
185 }
186 for( i = 0 ; i < max_usage_lines ; i++ )
187 usage[i] = NULL;
188
189 return true;
190}
191
192bool
193AnyOption::doubleOptStorage()
194{
195 options = (const char**)realloc( options,
196 ((2*max_options)+1) * sizeof( const char*) );
197 optiontype = (int*) realloc( optiontype ,
198 ((2 * max_options)+1)* sizeof(int) );
199 optionindex = (int*) realloc( optionindex,
200 ((2 * max_options)+1) * sizeof(int) );
201 if( options == NULL || optiontype == NULL || optionindex == NULL )
202 return false;
203 /* init new storage */
204 for( int i = max_options ; i < 2*max_options ; i++ ){
205 options[i] = NULL;
206 optiontype[i] = 0 ;
207 optionindex[i] = -1 ;
208 }
209 max_options = 2 * max_options ;
210 return true;
211}
212
213bool
214AnyOption::doubleCharStorage()
215{
216 optionchars = (char*) realloc( optionchars,
217 ((2*max_char_options)+1)*sizeof(char) );
218 optchartype = (int*) realloc( optchartype,
219 ((2*max_char_options)+1)*sizeof(int) );
220 optcharindex = (int*) realloc( optcharindex,
221 ((2*max_char_options)+1)*sizeof(int) );
222 if( optionchars == NULL ||
223 optchartype == NULL ||
224 optcharindex == NULL )
225 return false;
226 /* init new storage */
227 for( int i = max_char_options ; i < 2*max_char_options ; i++ ){
228 optionchars[i] = '0';
229 optchartype[i] = 0 ;
230 optcharindex[i] = -1 ;
231 }
232 max_char_options = 2 * max_char_options;
233 return true;
234}
235
236bool
237AnyOption::doubleUsageStorage()
238{
239 usage = (const char**)realloc( usage,
240 ((2*max_usage_lines)+1) * sizeof( const char*) );
241 if ( usage == NULL )
242 return false;
243 for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ )
244 usage[i] = NULL;
245 max_usage_lines = 2 * max_usage_lines ;
246 return true;
247
248}
249
250
251void
252AnyOption::cleanup()
253{
254 free (options);
255 free (optiontype);
256 free (optionindex);
257 free (optionchars);
258 free (optchartype);
259 free (optcharindex);
260 free (usage);
261 if( values != NULL )
262 free (values);
263 if( new_argv != NULL )
264 free (new_argv);
265}
266
267void
268AnyOption::setCommandPrefixChar( char _prefix )
269{
270 opt_prefix_char = _prefix;
271}
272
273void
274AnyOption::setCommandLongPrefix( char *_prefix )
275{
276 if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){
277 *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0';
278 }
279
280 strcpy (long_opt_prefix, _prefix);
281}
282
283void
284AnyOption::setFileCommentChar( char _comment )
285{
286 file_delimiter_char = _comment;
287}
288
289
290void
291AnyOption::setFileDelimiterChar( char _delimiter )
292{
293 file_comment_char = _delimiter ;
294}
295
296bool
297AnyOption::CommandSet()
298{
299 return( command_set );
300}
301
302bool
303AnyOption::FileSet()
304{
305 return( file_set );
306}
307
308void
309AnyOption::noPOSIX()
310{
311 posix_style = false;
312}
313
314bool
315AnyOption::POSIX()
316{
317 return posix_style;
318}
319
320
321void
322AnyOption::setVerbose()
323{
324 verbose = true ;
325}
326
327void
328AnyOption::printVerbose()
329{
330 if( verbose )
331 cout << endl ;
332}
333void
334AnyOption::printVerbose( const char *msg )
335{
336 if( verbose )
337 cout << msg ;
338}
339
340void
341AnyOption::printVerbose( char *msg )
342{
343 if( verbose )
344 cout << msg ;
345}
346
347void
348AnyOption::printVerbose( char ch )
349{
350 if( verbose )
351 cout << ch ;
352}
353
354bool
355AnyOption::hasOptions()
356{
357 return hasoptions;
358}
359
360void
361AnyOption::autoUsagePrint(bool _autousage)
362{
363 autousage = _autousage;
364}
365
366void
367AnyOption::useCommandArgs( int _argc, char **_argv )
368{
369 argc = _argc;
370 argv = _argv;
371 command_set = true;
372 appname = argv[0];
373 if(argc > 1) hasoptions = true;
374}
375
376void
377AnyOption::useFiileName( const char *_filename )
378{
379 filename = _filename;
380 file_set = true;
381}
382
383/*
384 * set methods for options
385 */
386
387void
388AnyOption::setCommandOption( const char *opt )
389{
390 addOption( opt , COMMAND_OPT );
391 g_value_counter++;
392}
393
394void
395AnyOption::setCommandOption( char opt )
396{
397 addOption( opt , COMMAND_OPT );
398 g_value_counter++;
399}
400
401void
402AnyOption::setCommandOption( const char *opt , char optchar )
403{
404 addOption( opt , COMMAND_OPT );
405 addOption( optchar , COMMAND_OPT );
406 g_value_counter++;
407}
408
409void
410AnyOption::setCommandFlag( const char *opt )
411{
412 addOption( opt , COMMAND_FLAG );
413 g_value_counter++;
414}
415
416void
417AnyOption::setCommandFlag( char opt )
418{
419 addOption( opt , COMMAND_FLAG );
420 g_value_counter++;
421}
422
423void
424AnyOption::setCommandFlag( const char *opt , char optchar )
425{
426 addOption( opt , COMMAND_FLAG );
427 addOption( optchar , COMMAND_FLAG );
428 g_value_counter++;
429}
430
431void
432AnyOption::setFileOption( const char *opt )
433{
434 addOption( opt , FILE_OPT );
435 g_value_counter++;
436}
437
438void
439AnyOption::setFileOption( char opt )
440{
441 addOption( opt , FILE_OPT );
442 g_value_counter++;
443}
444
445void
446AnyOption::setFileOption( const char *opt , char optchar )
447{
448 addOption( opt , FILE_OPT );
449 addOption( optchar, FILE_OPT );
450 g_value_counter++;
451}
452
453void
454AnyOption::setFileFlag( const char *opt )
455{
456 addOption( opt , FILE_FLAG );
457 g_value_counter++;
458}
459
460void
461AnyOption::setFileFlag( char opt )
462{
463 addOption( opt , FILE_FLAG );
464 g_value_counter++;
465}
466
467void
468AnyOption::setFileFlag( const char *opt , char optchar )
469{
470 addOption( opt , FILE_FLAG );
471 addOption( optchar , FILE_FLAG );
472 g_value_counter++;
473}
474
475void
476AnyOption::setOption( const char *opt )
477{
478 addOption( opt , COMMON_OPT );
479 g_value_counter++;
480}
481
482void
483AnyOption::setOption( char opt )
484{
485 addOption( opt , COMMON_OPT );
486 g_value_counter++;
487}
488
489void
490AnyOption::setOption( const char *opt , char optchar )
491{
492 addOption( opt , COMMON_OPT );
493 addOption( optchar , COMMON_OPT );
494 g_value_counter++;
495}
496
497void
498AnyOption::setFlag( const char *opt )
499{
500 addOption( opt , COMMON_FLAG );
501 g_value_counter++;
502}
503
504void
505AnyOption::setFlag( const char opt )
506{
507 addOption( opt , COMMON_FLAG );
508 g_value_counter++;
509}
510
511void
512AnyOption::setFlag( const char *opt , char optchar )
513{
514 addOption( opt , COMMON_FLAG );
515 addOption( optchar , COMMON_FLAG );
516 g_value_counter++;
517}
518
519void
520AnyOption::addOption( const char *opt, int type )
521{
522 if( option_counter >= max_options ){
523 if( doubleOptStorage() == false ){
524 addOptionError( opt );
525 return;
526 }
527 }
528 options[ option_counter ] = opt ;
529 optiontype[ option_counter ] = type ;
530 optionindex[ option_counter ] = g_value_counter;
531 option_counter++;
532}
533
534void
535AnyOption::addOption( char opt, int type )
536{
537 if( !POSIX() ){
538 printVerbose("Ignoring the option character \"");
539 printVerbose( opt );
540 printVerbose( "\" ( POSIX options are turned off )" );
541 printVerbose();
542 return;
543 }
544
545
546 if( optchar_counter >= max_char_options ){
547 if( doubleCharStorage() == false ){
548 addOptionError( opt );
549 return;
550 }
551 }
552 optionchars[ optchar_counter ] = opt ;
553 optchartype[ optchar_counter ] = type ;
554 optcharindex[ optchar_counter ] = g_value_counter;
555 optchar_counter++;
556}
557
558void
559AnyOption::addOptionError( const char *opt )
560{
561 cout << endl ;
562 cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
563 cout << "While adding the option : \""<< opt << "\"" << endl;
564 cout << "Exiting." << endl ;
565 cout << endl ;
566 exit(0);
567}
568
569void
570AnyOption::addOptionError( char opt )
571{
572 cout << endl ;
573 cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
574 cout << "While adding the option: \""<< opt << "\"" << endl;
575 cout << "Exiting." << endl ;
576 cout << endl ;
577 exit(0);
578}
579
580void
581AnyOption::processOptions()
582{
583 if( ! valueStoreOK() )
584 return;
585}
586
587void
588AnyOption::processCommandArgs(int max_args)
589{
590 max_legal_args = max_args;
591 processCommandArgs();
592}
593
594void
595AnyOption::processCommandArgs( int _argc, char **_argv, int max_args )
596{
597 max_legal_args = max_args;
598 processCommandArgs( _argc, _argv );
599}
600
601void
602AnyOption::processCommandArgs( int _argc, char **_argv )
603{
604 useCommandArgs( _argc, _argv );
605 processCommandArgs();
606}
607
608void
609AnyOption::processCommandArgs()
610{
611 if( ! ( valueStoreOK() && CommandSet() ) )
612 return;
613
614 if( max_legal_args == 0 )
615 max_legal_args = argc;
616 new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) );
617 for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */
618 if( argv[i][0] == long_opt_prefix[0] &&
619 argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */
620 int match_at = parseGNU( argv[i]+2 ); /* skip -- */
621 if( match_at >= 0 && i < argc-1 ) /* found match */
622 setValue( options[match_at] , argv[++i] );
623 }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */
624 if( POSIX() ){
625 char ch = parsePOSIX( argv[i]+1 );/* skip - */
626 if( ch != '0' && i < argc-1 ) /* matching char */
627 setValue( ch , argv[++i] );
628 } else { /* treat it as GNU option with a - */
629 int match_at = parseGNU( argv[i]+1 ); /* skip - */
630 if( match_at >= 0 && i < argc-1 ) /* found match */
631 setValue( options[match_at] , argv[++i] );
632 }
633 }else { /* not option but an argument keep index */
634 if( new_argc < max_legal_args ){
635 new_argv[ new_argc ] = i ;
636 new_argc++;
637 }else{ /* ignore extra arguments */
638 printVerbose( "Ignoring extra argument: " );
639 printVerbose( argv[i] );
640 printVerbose( );
641 printAutoUsage();
642 }
643 printVerbose( "Unknown command argument option : " );
644 printVerbose( argv[i] );
645 printVerbose( );
646 printAutoUsage();
647 }
648 }
649}
650
651char
652AnyOption::parsePOSIX( char* arg )
653{
654
655 for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
656 char ch = arg[i] ;
657 if( matchChar(ch) ) { /* keep matching flags till an option */
658 /*if last char argv[++i] is the value */
659 if( i == strlen(arg)-1 ){
660 return ch;
661 }else{/* else the rest of arg is the value */
662 i++; /* skip any '=' and ' ' */
663 while( arg[i] == whitespace
664 || arg[i] == equalsign )
665 i++;
666 setValue( ch , arg+i );
667 return '0';
668 }
669 }
670 }
671 printVerbose( "Unknown command argument option : " );
672 printVerbose( arg );
673 printVerbose( );
674 printAutoUsage();
675 return '0';
676}
677
678int
679AnyOption::parseGNU( char *arg )
680{
681 int split_at = 0;
682 /* if has a '=' sign get value */
683 for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){
684 if(arg[i] == equalsign ){
685 split_at = i ; /* store index */
686 i = strlen(arg); /* get out of loop */
687 }
688 }
689 if( split_at > 0 ){ /* it is an option value pair */
690 char* tmp = (char*) malloc( (split_at+1)*sizeof(char) );
691 for( int i = 0 ; i < split_at ; i++ )
692 tmp[i] = arg[i];
693 tmp[split_at] = '\0';
694
695 if ( matchOpt( tmp ) >= 0 ){
696 setValue( options[matchOpt(tmp)] , arg+split_at+1 );
697 free (tmp);
698 }else{
699 printVerbose( "Unknown command argument option : " );
700 printVerbose( arg );
701 printVerbose( );
702 printAutoUsage();
703 free (tmp);
704 return -1;
705 }
706 }else{ /* regular options with no '=' sign */
707 return matchOpt(arg);
708 }
709 return -1;
710}
711
712
713int
714AnyOption::matchOpt( char *opt )
715{
716 for( int i = 0 ; i < option_counter ; i++ ){
717 if( strcmp( options[i], opt ) == 0 ){
718 if( optiontype[i] == COMMON_OPT ||
719 optiontype[i] == COMMAND_OPT )
720 { /* found option return index */
721 return i;
722 }else if( optiontype[i] == COMMON_FLAG ||
723 optiontype[i] == COMMAND_FLAG )
724 { /* found flag, set it */
725 setFlagOn( opt );
726 return -1;
727 }
728 }
729 }
730 printVerbose( "Unknown command argument option : " );
731 printVerbose( opt ) ;
732 printVerbose( );
733 printAutoUsage();
734 return -1;
735}
736bool
737AnyOption::matchChar( char c )
738{
739 for( int i = 0 ; i < optchar_counter ; i++ ){
740 if( optionchars[i] == c ) { /* found match */
741 if(optchartype[i] == COMMON_OPT ||
742 optchartype[i] == COMMAND_OPT )
743 { /* an option store and stop scanning */
744 return true;
745 }else if( optchartype[i] == COMMON_FLAG ||
746 optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */
747 setFlagOn( c );
748 return true;
749 }
750 }
751 }
752 //printVerbose( "Unknown command argument option : " );
753 //printVerbose( c ) ;
754 //printVerbose( );
755 printAutoUsage();
756 return false;
757}
758
759bool
760AnyOption::valueStoreOK( )
761{
762 int size= 0;
763 if( !set ){
764 if( g_value_counter > 0 ){
765 size = g_value_counter * sizeof(char*);
766 values = (char**)malloc( size );
767 for( int i = 0 ; i < g_value_counter ; i++)
768 values[i] = NULL;
769 set = true;
770 }
771 }
772 return set;
773}
774
775/*
776 * public get methods
777 */
778char*
779AnyOption::getValue( const char *option )
780{
781 if( !valueStoreOK() )
782 return NULL;
783
784 for( int i = 0 ; i < option_counter ; i++ ){
785 if( strcmp( options[i], option ) == 0 )
786 return values[ optionindex[i] ];
787 }
788 return NULL;
789}
790
791bool
792AnyOption::getFlag( const char *option )
793{
794 if( !valueStoreOK() )
795 return false;
796 for( int i = 0 ; i < option_counter ; i++ ){
797 if( strcmp( options[i], option ) == 0 )
798 return findFlag( values[ optionindex[i] ] );
799 }
800 return false;
801}
802
803char*
804AnyOption::getValue( char option )
805{
806 if( !valueStoreOK() )
807 return NULL;
808 for( int i = 0 ; i < optchar_counter ; i++ ){
809 if( optionchars[i] == option )
810 return values[ optcharindex[i] ];
811 }
812 return NULL;
813}
814
815bool
816AnyOption::getFlag( char option )
817{
818 if( !valueStoreOK() )
819 return false;
820 for( int i = 0 ; i < optchar_counter ; i++ ){
821 if( optionchars[i] == option )
822 return findFlag( values[ optcharindex[i] ] ) ;
823 }
824 return false;
825}
826
827bool
828AnyOption::findFlag( char* val )
829{
830 if( val == NULL )
831 return false;
832
833 if( strcmp( TRUE_FLAG , val ) == 0 )
834 return true;
835
836 return false;
837}
838
839/*
840 * private set methods
841 */
842bool
843AnyOption::setValue( const char *option , char *value )
844{
845 if( !valueStoreOK() )
846 return false;
847 for( int i = 0 ; i < option_counter ; i++ ){
848 if( strcmp( options[i], option ) == 0 ){
849 values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
850 strcpy( values[ optionindex[i] ], value );
851 return true;
852 }
853 }
854 return false;
855}
856
857bool
858AnyOption::setFlagOn( const char *option )
859{
860 if( !valueStoreOK() )
861 return false;
862 for( int i = 0 ; i < option_counter ; i++ ){
863 if( strcmp( options[i], option ) == 0 ){
864 values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
865 strcpy( values[ optionindex[i] ] , TRUE_FLAG );
866 return true;
867 }
868 }
869 return false;
870}
871
872bool
873AnyOption::setValue( char option , char *value )
874{
875 if( !valueStoreOK() )
876 return false;
877 for( int i = 0 ; i < optchar_counter ; i++ ){
878 if( optionchars[i] == option ){
879 values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char));
880 strcpy( values[ optcharindex[i] ], value );
881 return true;
882 }
883 }
884 return false;
885}
886
887bool
888AnyOption::setFlagOn( char option )
889{
890 if( !valueStoreOK() )
891 return false;
892 for( int i = 0 ; i < optchar_counter ; i++ ){
893 if( optionchars[i] == option ){
894 values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char));
895 strcpy( values[ optcharindex[i] ] , TRUE_FLAG );
896 return true;
897 }
898 }
899 return false;
900}
901
902
903int
904AnyOption::getArgc( )
905{
906 return new_argc;
907}
908
909char*
910AnyOption::getArgv( int index )
911{
912 if( index < new_argc ){
913 return ( argv[ new_argv[ index ] ] );
914 }
915 return NULL;
916}
917
918/* dotfile sub routines */
919
920bool
921AnyOption::processFile()
922{
923 if( ! (valueStoreOK() && FileSet()) )
924 return false;
925 return ( consumeFile(readFile()) );
926}
927
928bool
929AnyOption::processFile( const char *filename )
930{
931 useFiileName(filename );
932 return ( processFile() );
933}
934
935char*
936AnyOption::readFile()
937{
938 return ( readFile(filename) );
939}
940
941/*
942 * read the file contents to a character buffer
943 */
944
945char*
946AnyOption::readFile( const char* fname )
947{
948 int length;
949 char *buffer;
950 ifstream is;
951 is.open ( fname , ifstream::in );
952 if( ! is.good() ){
953 is.close();
954 return NULL;
955 }
956 is.seekg (0, ios::end);
957 length = is.tellg();
958 is.seekg (0, ios::beg);
959 buffer = (char*) malloc(length*sizeof(char));
960 is.read (buffer,length);
961 is.close();
962 return buffer;
963}
964
965/*
966 * scans a char* buffer for lines that does not
967 * start with the specified comment character.
968 */
969bool
970AnyOption::consumeFile( char *buffer )
971{
972
973 if( buffer == NULL )
974 return false;
975
976 char *cursor = buffer;/* preserve the ptr */
977 char *pline = NULL ;
978 int linelength = 0;
979 bool newline = true;
980 for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){
981 if( *cursor == endofline ) { /* end of line */
982 if( pline != NULL ) /* valid line */
983 processLine( pline, linelength );
984 pline = NULL;
985 newline = true;
986 }else if( newline ){ /* start of line */
987 newline = false;
988 if( (*cursor != comment ) ){ /* not a comment */
989 pline = cursor ;
990 linelength = 0 ;
991 }
992 }
993 cursor++; /* keep moving */
994 linelength++;
995 }
996 free (buffer);
997 return true;
998}
999
1000
1001/*
1002 * find a valid type value pair separated by a delimiter
1003 * character and pass it to valuePairs()
1004 * any line which is not valid will be considered a value
1005 * and will get passed on to justValue()
1006 *
1007 * assuming delimiter is ':' the behaviour will be,
1008 *
1009 * width:10 - valid pair valuePairs( width, 10 );
1010 * width : 10 - valid pair valuepairs( width, 10 );
1011 *
1012 * :::: - not valid
1013 * width - not valid
1014 * :10 - not valid
1015 * width: - not valid
1016 * :: - not valid
1017 * : - not valid
1018 *
1019 */
1020
1021void
1022AnyOption::processLine( char *theline, int length )
1023{
1024 bool found = false;
1025 char *pline = (char*) malloc( (length+1)*sizeof(char) );
1026 for( int i = 0 ; i < length ; i ++ )
1027 pline[i]= *(theline++);
1028 pline[length] = nullterminate;
1029 char *cursor = pline ; /* preserve the ptr */
1030 if( *cursor == delimiter || *(cursor+length-1) == delimiter ){
1031 justValue( pline );/* line with start/end delimiter */
1032 }else{
1033 for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */
1034 if( *cursor == delimiter ){
1035 *(cursor-1) = nullterminate; /* two strings */
1036 found = true;
1037 valuePairs( pline , cursor+1 );
1038 }
1039 cursor++;
1040 }
1041 cursor++;
1042 if( !found ) /* not a pair */
1043 justValue( pline );
1044 }
1045 free (pline);
1046}
1047
1048/*
1049 * removes trailing and preceeding whitespaces from a string
1050 */
1051char*
1052AnyOption::chomp( char *str )
1053{
1054 while( *str == whitespace )
1055 str++;
1056 char *end = str+strlen(str)-1;
1057 while( *end == whitespace )
1058 end--;
1059 *(end+1) = nullterminate;
1060 return str;
1061}
1062
1063void
1064AnyOption::valuePairs( char *type, char *value )
1065{
1066 if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
1067 for( int i = 0 ; i < optchar_counter ; i++ ){
1068 if( optionchars[i] == type[0] ){ /* match */
1069 if( optchartype[i] == COMMON_OPT ||
1070 optchartype[i] == FILE_OPT )
1071 {
1072 setValue( type[0] , chomp(value) );
1073 return;
1074 }
1075 }
1076 }
1077 }
1078 /* if no char options matched */
1079 for( int i = 0 ; i < option_counter ; i++ ){
1080 if( strcmp( options[i], type ) == 0 ){ /* match */
1081 if( optiontype[i] == COMMON_OPT ||
1082 optiontype[i] == FILE_OPT )
1083 {
1084 setValue( type , chomp(value) );
1085 return;
1086 }
1087 }
1088 }
1089 printVerbose( "Unknown option in resourcefile : " );
1090 printVerbose( type );
1091 printVerbose( );
1092}
1093
1094void
1095AnyOption::justValue( char *type )
1096{
1097
1098 if ( strlen(chomp(type)) == 1 ){ /* this is a char option */
1099 for( int i = 0 ; i < optchar_counter ; i++ ){
1100 if( optionchars[i] == type[0] ){ /* match */
1101 if( optchartype[i] == COMMON_FLAG ||
1102 optchartype[i] == FILE_FLAG )
1103 {
1104 setFlagOn( type[0] );
1105 return;
1106 }
1107 }
1108 }
1109 }
1110 /* if no char options matched */
1111 for( int i = 0 ; i < option_counter ; i++ ){
1112 if( strcmp( options[i], type ) == 0 ){ /* match */
1113 if( optiontype[i] == COMMON_FLAG ||
1114 optiontype[i] == FILE_FLAG )
1115 {
1116 setFlagOn( type );
1117 return;
1118 }
1119 }
1120 }
1121 printVerbose( "Unknown option in resourcefile : " );
1122 printVerbose( type );
1123 printVerbose( );
1124}
1125
1126/*
1127 * usage and help
1128 */
1129
1130
1131void
1132AnyOption::printAutoUsage()
1133{
1134 if( autousage ) printUsage();
1135}
1136
1137void
1138AnyOption::printUsage()
1139{
1140
1141 if( once ) {
1142 once = false ;
1143 cout << endl ;
1144 for( int i = 0 ; i < usage_lines ; i++ )
1145 cout << usage[i] << endl ;
1146 cout << endl ;
1147 }
1148}
1149
1150
1151void
1152AnyOption::addUsage( const char *line )
1153{
1154 if( usage_lines >= max_usage_lines ){
1155 if( doubleUsageStorage() == false ){
1156 addUsageError( line );
1157 exit(1);
1158 }
1159 }
1160 usage[ usage_lines ] = line ;
1161 usage_lines++;
1162}
1163
1164void
1165AnyOption::addUsageError( const char *line )
1166{
1167 cout << endl ;
1168 cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ;
1169 cout << "While adding the usage/help : \""<< line << "\"" << endl;
1170 cout << "Exiting." << endl ;
1171 cout << endl ;
1172 exit(0);
1173
1174}
diff --git a/pacman-c++/anyoption.h b/pacman-c++/anyoption.h
new file mode 100644
index 0000000..3f7a5de
--- /dev/null
+++ b/pacman-c++/anyoption.h
@@ -0,0 +1,270 @@
1#ifndef _ANYOPTION_H
2#define _ANYOPTION_H
3
4#include <iostream>
5#include <fstream>
6#include <stdlib.h>
7#include <string>
8
9#define COMMON_OPT 1
10#define COMMAND_OPT 2
11#define FILE_OPT 3
12#define COMMON_FLAG 4
13#define COMMAND_FLAG 5
14#define FILE_FLAG 6
15
16#define COMMAND_OPTION_TYPE 1
17#define COMMAND_FLAG_TYPE 2
18#define FILE_OPTION_TYPE 3
19#define FILE_FLAG_TYPE 4
20#define UNKNOWN_TYPE 5
21
22#define DEFAULT_MAXOPTS 10
23#define MAX_LONG_PREFIX_LENGTH 2
24
25#define DEFAULT_MAXUSAGE 3
26#define DEFAULT_MAXHELP 10
27
28#define TRUE_FLAG "true"
29
30using namespace std;
31
32class AnyOption
33{
34
35public: /* the public interface */
36 AnyOption();
37 AnyOption(int maxoptions );
38 AnyOption(int maxoptions , int maxcharoptions);
39 ~AnyOption();
40
41 /*
42 * following set methods specifies the
43 * special characters and delimiters
44 * if not set traditional defaults will be used
45 */
46
47 void setCommandPrefixChar( char _prefix ); /* '-' in "-w" */
48 void setCommandLongPrefix( char *_prefix ); /* '--' in "--width" */
49 void setFileCommentChar( char _comment ); /* '#' in shellscripts */
50 void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */
51
52 /*
53 * provide the input for the options
54 * like argv[] for commndline and the
55 * option file name to use;
56 */
57
58 void useCommandArgs( int _argc, char **_argv );
59 void useFiileName( const char *_filename );
60
61 /*
62 * turn off the POSIX style options
63 * this means anything starting with a '-' or "--"
64 * will be considered a valid option
65 * which alo means you cannot add a bunch of
66 * POIX options chars together like "-lr" for "-l -r"
67 *
68 */
69
70 void noPOSIX();
71
72 /*
73 * prints warning verbose if you set anything wrong
74 */
75 void setVerbose();
76
77
78 /*
79 * there are two types of options
80 *
81 * Option - has an associated value ( -w 100 )
82 * Flag - no value, just a boolean flag ( -nogui )
83 *
84 * the options can be either a string ( GNU style )
85 * or a character ( traditional POSIX style )
86 * or both ( --width, -w )
87 *
88 * the options can be common to the commandline and
89 * the optionfile, or can belong only to either of
90 * commandline and optionfile
91 *
92 * following set methods, handle all the aboove
93 * cases of options.
94 */
95
96 /* options comman to command line and option file */
97 void setOption( const char *opt_string );
98 void setOption( char opt_char );
99 void setOption( const char *opt_string , char opt_char );
100 void setFlag( const char *opt_string );
101 void setFlag( char opt_char );
102 void setFlag( const char *opt_string , char opt_char );
103
104 /* options read from commandline only */
105 void setCommandOption( const char *opt_string );
106 void setCommandOption( char opt_char );
107 void setCommandOption( const char *opt_string , char opt_char );
108 void setCommandFlag( const char *opt_string );
109 void setCommandFlag( char opt_char );
110 void setCommandFlag( const char *opt_string , char opt_char );
111
112 /* options read from an option file only */
113 void setFileOption( const char *opt_string );
114 void setFileOption( char opt_char );
115 void setFileOption( const char *opt_string , char opt_char );
116 void setFileFlag( const char *opt_string );
117 void setFileFlag( char opt_char );
118 void setFileFlag( const char *opt_string , char opt_char );
119
120 /*
121 * process the options, registerd using
122 * useCommandArgs() and useFileName();
123 */
124 void processOptions();
125 void processCommandArgs();
126 void processCommandArgs( int max_args );
127 bool processFile();
128
129 /*
130 * process the specified options
131 */
132 void processCommandArgs( int _argc, char **_argv );
133 void processCommandArgs( int _argc, char **_argv, int max_args );
134 bool processFile( const char *_filename );
135
136 /*
137 * get the value of the options
138 * will return NULL if no value is set
139 */
140 char *getValue( const char *_option );
141 bool getFlag( const char *_option );
142 char *getValue( char _optchar );
143 bool getFlag( char _optchar );
144
145 /*
146 * Print Usage
147 */
148 void printUsage();
149 void printAutoUsage();
150 void addUsage( const char *line );
151 void printHelp();
152 /* print auto usage printing for unknown options or flag */
153 void autoUsagePrint(bool flag);
154
155 /*
156 * get the argument count and arguments sans the options
157 */
158 int getArgc();
159 char* getArgv( int index );
160 bool hasOptions();
161
162private: /* the hidden data structure */
163 int argc; /* commandline arg count */
164 char **argv; /* commndline args */
165 const char* filename; /* the option file */
166 char* appname; /* the application name from argv[0] */
167
168 int *new_argv; /* arguments sans options (index to argv) */
169 int new_argc; /* argument count sans the options */
170 int max_legal_args; /* ignore extra arguments */
171
172
173 /* option strings storage + indexing */
174 int max_options; /* maximum number of options */
175 const char **options; /* storage */
176 int *optiontype; /* type - common, command, file */
177 int *optionindex; /* index into value storage */
178 int option_counter; /* counter for added options */
179
180 /* option chars storage + indexing */
181 int max_char_options; /* maximum number options */
182 char *optionchars; /* storage */
183 int *optchartype; /* type - common, command, file */
184 int *optcharindex; /* index into value storage */
185 int optchar_counter; /* counter for added options */
186
187 /* values */
188 char **values; /* common value storage */
189 int g_value_counter; /* globally updated value index LAME! */
190
191 /* help and usage */
192 const char **usage; /* usage */
193 int max_usage_lines; /* max usage lines reseverd */
194 int usage_lines; /* number of usage lines */
195
196 bool command_set; /* if argc/argv were provided */
197 bool file_set; /* if a filename was provided */
198 bool mem_allocated; /* if memory allocated in init() */
199 bool posix_style; /* enables to turn off POSIX style options */
200 bool verbose; /* silent|verbose */
201 bool print_usage; /* usage verbose */
202 bool print_help; /* help verbose */
203
204 char opt_prefix_char; /* '-' in "-w" */
205 char long_opt_prefix[MAX_LONG_PREFIX_LENGTH]; /* '--' in "--width" */
206 char file_delimiter_char; /* ':' in width : 100 */
207 char file_comment_char; /* '#' in "#this is a comment" */
208 char equalsign;
209 char comment;
210 char delimiter;
211 char endofline;
212 char whitespace;
213 char nullterminate;
214
215 bool set; //was static member
216 bool once; //was static member
217
218 bool hasoptions;
219 bool autousage;
220
221private: /* the hidden utils */
222 void init();
223 void init(int maxopt, int maxcharopt );
224 bool alloc();
225 void cleanup();
226 bool valueStoreOK();
227
228 /* grow storage arrays as required */
229 bool doubleOptStorage();
230 bool doubleCharStorage();
231 bool doubleUsageStorage();
232
233 bool setValue( const char *option , char *value );
234 bool setFlagOn( const char *option );
235 bool setValue( char optchar , char *value);
236 bool setFlagOn( char optchar );
237
238 void addOption( const char* option , int type );
239 void addOption( char optchar , int type );
240 void addOptionError( const char *opt);
241 void addOptionError( char opt);
242 bool findFlag( char* value );
243 void addUsageError( const char *line );
244 bool CommandSet();
245 bool FileSet();
246 bool POSIX();
247
248 char parsePOSIX( char* arg );
249 int parseGNU( char *arg );
250 bool matchChar( char c );
251 int matchOpt( char *opt );
252
253 /* dot file methods */
254 char *readFile();
255 char *readFile( const char* fname );
256 bool consumeFile( char *buffer );
257 void processLine( char *theline, int length );
258 char *chomp( char *str );
259 void valuePairs( char *type, char *value );
260 void justValue( char *value );
261
262 void printVerbose( const char *msg );
263 void printVerbose( char *msg );
264 void printVerbose( char ch );
265 void printVerbose( );
266
267
268};
269
270#endif /* ! _ANYOPTION_H */
diff --git a/pacman-c++/audio.cpp b/pacman-c++/audio.cpp
index c0cc5b0..ad6eed1 100644
--- a/pacman-c++/audio.cpp
+++ b/pacman-c++/audio.cpp
@@ -282,6 +282,8 @@ bool GaplessAudioPlayer::isWorking() const
282 282
283void GaplessAudioPlayer::setMuted(bool mute) 283void GaplessAudioPlayer::setMuted(bool mute)
284{ 284{
285 if (!m_working)
286 return;
285 m_player1->setMuted(mute); 287 m_player1->setMuted(mute);
286 m_player2->setMuted(mute); 288 m_player2->setMuted(mute);
287} 289}
diff --git a/pacman-c++/pacman.server.pro b/pacman-c++/pacman.server.pro
index 2224d9a..f42fa62 100644
--- a/pacman-c++/pacman.server.pro
+++ b/pacman-c++/pacman.server.pro
@@ -16,7 +16,8 @@ SOURCES += pixmapitem.cpp \
16 sceneholder.cpp \ 16 sceneholder.cpp \
17 util.cpp \ 17 util.cpp \
18 clicklabel.cpp \ 18 clicklabel.cpp \
19 gameentity.cpp 19 gameentity.cpp \
20 anyoption.cpp
20HEADERS += pixmapitem.h \ 21HEADERS += pixmapitem.h \
21 actor.h \ 22 actor.h \
22 block.h \ 23 block.h \
@@ -28,7 +29,8 @@ HEADERS += pixmapitem.h \
28 sceneholder.h \ 29 sceneholder.h \
29 util.h \ 30 util.h \
30 clicklabel.h \ 31 clicklabel.h \
31 gameentity.h 32 gameentity.h \
33 anyoption.h
32RESOURCES += pacman.qrc 34RESOURCES += pacman.qrc
33 35
34OBJECTS_DIR = .obj 36OBJECTS_DIR = .obj
diff --git a/pacman-c++/server.cpp b/pacman-c++/server.cpp
index 51dcc24..50ee3b7 100644
--- a/pacman-c++/server.cpp
+++ b/pacman-c++/server.cpp
@@ -1,18 +1,24 @@
1#include "server.h" 1#include "server.h"
2
3#include <QtNetwork/QTcpServer>
4#include <QtNetwork/QTcpSocket>
5#include "util.h" 2#include "util.h"
6#include "pacman.pb.h" 3#include "pacman.pb.h"
7#include "block.h" 4#include "block.h"
5#include "anyoption.h"
6#include <QtNetwork/QTcpServer>
7#include <QtNetwork/QTcpSocket>
8#include <QTextStream>
8 9
9Server::Server(QWidget *parent) 10Server::Server(QWidget *parent)
10 : SceneHolder(parent) 11 : SceneHolder(parent), m_bindaddress(QHostAddress::Any),
12 m_port(Constants::Networking::port), m_numbots(0)
11{ 13{
14 /* determine max players by using order array */
15 for(m_maxplayers = 0; Color::order[m_maxplayers] != Color::none; ++m_maxplayers);
16}
12 17
13 qDebug() << "[Server] Waiting for clients"; 18bool Server::run()
14 waitForClientConnections(); 19{
15 qDebug() << "[Server] All Clients connected"; 20 if (!waitForClientConnections())
21 return false;
16 22
17 Transmission::map_t map = Util::createDemoMap(); 23 Transmission::map_t map = Util::createDemoMap();
18 updateMap(map); 24 updateMap(map);
@@ -22,6 +28,7 @@ Server::Server(QWidget *parent)
22 QTimer *timer = new QTimer(this); 28 QTimer *timer = new QTimer(this);
23 connect(timer, SIGNAL(timeout()), this, SLOT(tick())); 29 connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
24 timer->start(Constants::tick); 30 timer->start(Constants::tick);
31 return true;
25} 32}
26 33
27void Server::tick() 34void Server::tick()
@@ -147,12 +154,21 @@ invalid_direction:
147 return map; 154 return map;
148} 155}
149 156
150void Server::waitForClientConnections() 157bool Server::waitForClientConnections()
151{ 158{
152 QTcpServer *tcpSrv = new QTcpServer(this);
153 // server must stay alive as long as sockets (qt parent mem mechanism) 159 // server must stay alive as long as sockets (qt parent mem mechanism)
154 tcpSrv->listen(QHostAddress::Any, Constants::Networking::port); 160 QTcpServer *tcpSrv = new QTcpServer(this);
161 tcpSrv->listen(m_bindaddress, m_port);
162 if (!tcpSrv->isListening())
163 {
164 qCritical() << "Error while creating socket:" << qPrintable(tcpSrv->errorString());
165 return false;
166 }
155 167
168 qDebug() << "[Server] Listening on:"
169 << qPrintable(QString("%1:%2").arg(tcpSrv->serverAddress().toString())
170 .arg(tcpSrv->serverPort()));
171 qDebug() << "[Server] Waiting for clients";
156 ProtoBuf::WhoAmI packet; 172 ProtoBuf::WhoAmI packet;
157#define SINGLE 173#define SINGLE
158#ifdef SINGLE 174#ifdef SINGLE
@@ -177,6 +193,9 @@ void Server::waitForClientConnections()
177 193
178 qDebug() << "[Connect] New Player: color=" << color; 194 qDebug() << "[Connect] New Player: color=" << color;
179 } 195 }
196
197 qDebug() << "[Server] All Clients connected";
198 return true;
180} 199}
181 200
182void Server::sendUpdate(Transmission::map_t map) 201void Server::sendUpdate(Transmission::map_t map)
@@ -229,6 +248,103 @@ void Server::keyPressUpdate()
229 } 248 }
230} 249}
231 250
251bool Server::parseCommandline()
252{
253 AnyOption opt;
254 opt.setVerbose();
255
256 /* usage strings must remain valid until parsing is done */
257 QString exec = QFileInfo(qApp->applicationFilePath()).fileName();
258 QByteArray usage;
259 QTextStream out(&usage, QIODevice::ReadWrite | QIODevice::Text);
260 out << "Usage: " << exec << " [OPTION]" << endl
261 << "Usage: " << exec << " -h" << endl
262 << endl;
263 out << " -b, --bind <bind_address>" << endl
264 << " Specifies the ip address on which the server listens for connections" << endl
265 << " Default: " << m_bindaddress.toString() << endl
266 << endl;
267 opt.setOption("bind", 'b');
268 out << " -p, --port <port>" << endl
269 << " Specifies the port on which the server listens for connections" << endl
270 << " Default: " << m_port << endl
271 << endl;
272 opt.setOption("port", 'p');
273 out << " -m, --maxplayers [1.." << m_maxplayers << "]" << endl
274 << " Specifies the maximum number of players/pacmans" << endl
275 << " Default: " << m_maxplayers << endl
276 << endl;
277 opt.setOption("maxplayers", 'm');
278 out << " --bots [0..maxplayers-1]" << endl
279 << " Specifies the number of AI pacmans/bots" << endl
280 << " Default: " << m_numbots << endl
281 << endl;
282 opt.setOption("bots");
283 out << " -h, --help" << endl
284 << " Prints this help message" << endl;
285 opt.setFlag("help", 'h');
286 out.flush();
287 opt.addUsage(usage.constData());
288 opt.processCommandArgs(qApp->argc(), qApp->argv());
289
290 if (opt.getFlag("help") || opt.getFlag('h'))
291 {
292 opt.printUsage();
293 return false;
294 }
295
296 if (opt.getValue("port") != NULL)
297 {
298 bool ok;
299 m_port = QString(opt.getValue("port")).toUInt(&ok);
300 if (!ok || m_port < 1 || m_port > 65535)
301 {
302 qCritical() << "Invalid port-option:" << opt.getValue("port") << endl
303 << "Port must be between 1 and 65535";
304 return false;
305 }
306 }
307
308 if (opt.getValue("bind") != NULL)
309 {
310 m_bindaddress = opt.getValue("bind");
311 if (m_bindaddress.isNull())
312 {
313 qCritical() << "Invalid bind-option:" << opt.getValue("bind") << endl
314 << "Bind address must be an ip address";
315 return false;
316 }
317 }
318
319 if (opt.getValue("maxplayers") != NULL)
320 {
321 bool ok;
322 unsigned int maxplayers = QString(opt.getValue("maxplayers")).toUInt(&ok);
323 if (!ok || maxplayers < 1 || maxplayers > m_maxplayers)
324 {
325 qCritical() << "Invalid maxplayers-option:" << opt.getValue("maxplayers") << endl
326 << "Maxplayers must be between 1 and" << m_maxplayers;
327 return false;
328 }
329 m_maxplayers = maxplayers;
330 }
331
332 if (opt.getValue("bots") != NULL)
333 {
334 bool ok;
335 unsigned int numbots = QString(opt.getValue("bots")).toUInt(&ok);
336 if (!ok || numbots >= m_maxplayers)
337 {
338 qCritical() << "Invalid numbots-options:" << opt.getValue("bots") << endl
339 << "AI pacmans/bots must be between 0 and" << m_maxplayers - 1;
340 return false;
341 }
342 m_numbots = numbots;
343 }
344
345 return true;
346}
347
232bool Constants::server = true; 348bool Constants::server = true;
233 349
234int main(int argc, char ** argv) 350int main(int argc, char ** argv)
@@ -244,8 +360,14 @@ int main(int argc, char ** argv)
244 360
245 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); 361 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
246 362
247 Server Server; 363 int ret = 0;
248 int ret = app.exec(); 364 Server server;
365 if (!ret && !server.parseCommandline())
366 ret = 1;
367 if (!ret && !server.run())
368 ret = 1;
369 if (!ret)
370 ret = app.exec();
249 371
250 /* Delete all global objects allocated by libprotobuf */ 372 /* Delete all global objects allocated by libprotobuf */
251 google::protobuf::ShutdownProtobufLibrary(); 373 google::protobuf::ShutdownProtobufLibrary();
diff --git a/pacman-c++/server.h b/pacman-c++/server.h
index 8c9e741..dac5d1c 100644
--- a/pacman-c++/server.h
+++ b/pacman-c++/server.h
@@ -5,6 +5,7 @@
5#include "actor.h" 5#include "actor.h"
6#include "pacman.pb.h" 6#include "pacman.pb.h"
7#include <QtGui> 7#include <QtGui>
8#include <QHostAddress>
8 9
9class QTcpSocket; 10class QTcpSocket;
10 11
@@ -14,6 +15,8 @@ class Server
14 Q_OBJECT 15 Q_OBJECT
15public: 16public:
16 Server(QWidget *parent = 0); 17 Server(QWidget *parent = 0);
18 bool parseCommandline();
19 bool run();
17 20
18protected slots: 21protected slots:
19 void tick(); 22 void tick();
@@ -23,7 +26,7 @@ protected slots:
23 26
24protected: 27protected:
25 /* block until we have connections from all clients */ 28 /* block until we have connections from all clients */
26 void waitForClientConnections(); 29 bool waitForClientConnections();
27 30
28 /* calculate updates of current tick for sending to client */ 31 /* calculate updates of current tick for sending to client */
29 Transmission::map_t calculateUpdates(); 32 Transmission::map_t calculateUpdates();
@@ -31,6 +34,7 @@ protected:
31 /* update client maps */ 34 /* update client maps */
32 void sendUpdate(Transmission::map_t map); 35 void sendUpdate(Transmission::map_t map);
33 36
37protected:
34 QMap<Color::Color, QTcpSocket *> m_clientConnections; 38 QMap<Color::Color, QTcpSocket *> m_clientConnections;
35 39
36 /* current movements. required to make pacmans continue their movement */ 40 /* current movements. required to make pacmans continue their movement */
@@ -38,6 +42,11 @@ protected:
38 42
39 /* allocate as member variable as this packet is large and used often */ 43 /* allocate as member variable as this packet is large and used often */
40 ProtoBuf::MapUpdate m_updatepacket; 44 ProtoBuf::MapUpdate m_updatepacket;
45
46 QHostAddress m_bindaddress;
47 unsigned int m_port;
48 unsigned int m_maxplayers;
49 unsigned int m_numbots;
41}; 50};
42 51
43#endif // SERVER_H 52#endif // SERVER_H