Hi, all. I previously started a thread on how to get a code review. Based on the responses, I've started an extensive refactorization of my code, and I'd like some advice on how I'm going. Here's my main() function, and the next function deep. This is a Wikipedia bot, which works perfectly. I have open sourced it.
I find this style of programming far more difficult to understand than the scheme I was using before. Also, because the program is so complicated, I am worried about the sheer number of variables that are going to exist by the time I get to main3 () and main4(). Am I on the right track here, or not?
Code:
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "Printtime.h"
#include "Preferences.h"
#include "Managelogfile.h"
#include "Main2.h"
#include "Safeprint.h"
#include "Variables.h"
// TODO : Remove global variables.
static int shutdownmessage ( void ) ;
int main ( int argc , char* argv [] )
{
/* If any of these is set to 1, we will exit without improving Wikipedia. */
unsigned int uidisplayversion = 0 , uidisplayhelp = 0 , uibadparameter = 0 ;
struct preferencesstruct preferences ; /* All our preferences go here. */
memset ( &preferences , 0 , sizeof ( struct preferencesstruct ) ) ;
for ( int arg = 1 ; arg < argc ; arg ++ ) /* Parse command line options. */
{
if ( strcmp ( argv [ arg ] , "highmaxlag" ) == 0 ) /* highmaxlag */
{ strcpy ( szmaxlag , "20" ) ; preferences.highmaxlag = 1 ; }
else if ( strcmp ( argv [ arg ] , "nodump" ) == 0 ) /* nodump */
{ uidumpbuffers = 0 ; preferences.nodump = 1 ; }
else if ( strcmp ( argv [ arg ] , "nolog" ) == 0 ) /* nolog */
{ uinolog = 1 ; preferences.nolog = 1 ; }
else if ( strcmp ( argv [ arg ] , "noloop" ) == 0 ) /* noloop */
{ uiimprovementscanloop = 0 ; preferences.noloop = 1 ; }
else if ( strcmp ( argv [ arg ] , "noshutoff" ) == 0 ) /* noshutoff */
{ uinoshutoff = 1 ; preferences.noshutoff = 1 ; }
else if ( strcmp ( argv [ arg ] , "nostatus" ) == 0 ) /* nostatus */
{ uistatusupdate = 0 ; preferences.nostatus = 1 ; }
else if ( strcmp ( argv [ arg ] , "persevere" ) == 0 ) /* persevere */
preferences.persevere = 1 ;
else if ( strcmp ( argv [ arg ] , "progressmeter" ) == 0 ) /* progressmeter */
{ uiprogressmeter = 1 ; preferences.progressmeter = 1 ; }
else if ( strcmp ( argv [ arg ] , "quick" ) == 0 ) /* quick */
{
uisecondsbetweenimprovements = 2 ;
uisecondsbetweenimprovementscans = 2 ;
uisecondsbetweenfailedhttprequests = 5 ;
uiextrasecondsbetweenthrottledloginrequests = 120 ;
preferences.quick = 1 ;
}
else if ( strcmp ( argv [ arg ] , "silent" ) == 0 ) /* silent */
{ uisilentmode = 1 ; preferences.silent = 1 ; }
else if ( strcmp ( argv [ arg ] , "simulate" ) == 0 ) /* simulate */
{ uisimulate = 1 ; preferences.simulate = 1 ; }
else if ( strcmp ( argv [ arg ] , "verbose" ) == 0 ) /* verbose */
{ uiverbose = 1 ; preferences.verbose = 1 ; }
else if ( ( strcmp ( argv [ arg ] , "v" ) == 0 ) /* version (or one of 5 synonyms) */
|| ( strcmp ( argv [ arg ] , "version" ) == 0 )
|| ( strcmp ( argv [ arg ] , "-v" ) == 0 )
|| ( strcmp ( argv [ arg ] , "-version" ) == 0 )
|| ( strcmp ( argv [ arg ] , "--v" ) == 0 )
|| ( strcmp ( argv [ arg ] , "--version" ) == 0 ) )
uidisplayversion = 1 ;
else if ( ( strcmp ( argv [ arg ] , "h" ) == 0 ) /* help (or one of 5 synonyms) */
|| ( strcmp ( argv [ arg ] , "help" ) == 0 )
|| ( strcmp ( argv [ arg ] , "-h" ) == 0 )
|| ( strcmp ( argv [ arg ] , "-help" ) == 0 )
|| ( strcmp ( argv [ arg ] , "--h" ) == 0 )
|| ( strcmp ( argv [ arg ] , "--help" ) == 0 ) )
uidisplayhelp = 1 ;
else
{
if ( safeprintf ( "Unrecognized command line option : %s\n" , argv [ arg ] ) < 0 )
return EXIT_FAILURE ;
uibadparameter = 1 ;
}
}
if ( uibadparameter )
{
uisilentmode = 0 ;
preferences.silent = 0 ;
if ( uidisplayversion ) { safeprint ( szversionmessage ) ;
safeprintf ( "Libcurl version : %s\n" , curl_version() ) ; }
safeprint ( szusagemessage ) ;
return EXIT_FAILURE ; /* Exit without improving Wikipedia. */
}
if ( uidisplayversion )
{
uisilentmode = 0 ;
preferences.silent = 0 ;
if ( safeprint ( szversionmessage ) < 0 ) return EXIT_FAILURE ;
if ( safeprintf ( "Libcurl version : %s\n" , curl_version() ) < 0 ) return EXIT_FAILURE ;
if ( ( uidisplayhelp ) && ( safeprint ( szusagemessage ) < 0 ) ) return EXIT_FAILURE ;
return EXIT_SUCCESS ; /* Exit without improving Wikipedia. */
}
if ( uidisplayhelp )
{
uisilentmode = 0 ;
preferences.silent = 0 ;
if ( safeprint ( szusagemessage ) < 0 ) return EXIT_FAILURE ;
return EXIT_SUCCESS ; /* Exit without improving Wikipedia. */
}
if ( ( safeprint ( szstartupmessage ) < 0 )
|| ( safeprint ( szbuildmessage ) < 0 )
|| ( safeprint ( "Bot started at : " ) < 0 )
|| ( printtime () < 0 ) ) /* Produces a terminating '\n'. */
return EXIT_FAILURE ;
if ( eraseoldlogfiles () < 0 ) { shutdownmessage () ; return EXIT_FAILURE ; }
FILE *logfile = 0 ;
if ( preferences.nolog == 0 )
if ( ( logfile = startuplogfile () ) == NULL ) { shutdownmessage () ; return EXIT_FAILURE ; }
if ( main2 ( logfile , preferences ) < 0 ) /* Go one level deeper. */
{
shutdownmessage () ;
if ( preferences.nolog == 0 ) shutdownlogfile ( logfile ) ;
return EXIT_FAILURE ;
}
if ( shutdownmessage () < 0 )
{
if ( preferences.nolog == 0 ) shutdownlogfile ( logfile ) ;
return EXIT_FAILURE ;
}
if ( preferences.nolog == 0 )
if ( shutdownlogfile ( logfile ) < 0 ) return EXIT_FAILURE ;
return EXIT_SUCCESS ;
}
static int shutdownmessage ( void )
{
if ( ( safeprint ( szshutdownmessage ) < 0 )
|| ( safeprint ( "Bot shutdown at : " ) < 0 )
|| ( printtime () < 0 ) ) /* Produces a terminating '\n'. */
return -1 ;
return 0 ;
}
// Main2.c
#include <stdlib.h>
#include <stdio.h>
#include <curl/curl.h>
#include "Preferences.h"
#include "Buffers.h"
#include "Httpdatamemorystruct.h"
#include "Httpdatamemorystructs.h"
#include "Startupandshutdownbot.h"
#include "Improvewikipedia.h"
#include "Safeprint.h"
#include "Error.h"
int main2 ( FILE *logfile , struct preferencesstruct preferences )
{
pheaderbuffer = ( char* ) malloc ( buffersize ) ;
if ( pheaderbuffer == NULL )
{
error ( "HTML header buffer could not be allocated." ) ;
return -1 ;
}
pheaderbuffer [ 0 ] = 0 ;
pbodybuffer = ( char* ) malloc ( buffersize ) ;
if ( pbodybuffer == NULL )
{
error ( "HTML body buffer could not be allocated." ) ;
free ( pheaderbuffer ) ;
return -1 ;
}
pbodybuffer [ 0 ] = 0 ;
pwikitextbuffer = ( char* ) malloc ( buffersize ) ;
if ( pwikitextbuffer == NULL )
{
error ( "Wikitext buffer could not be allocated." ) ;
free ( pheaderbuffer ) ;
free ( pbodybuffer ) ;
return -1 ;
}
pwikitextbuffer [ 0 ] = 0 ;
phtmlrenderbuffer = ( char* ) malloc ( buffersize ) ;
if ( phtmlrenderbuffer == NULL )
{
error ( "HTML render buffer could not be allocated." ) ;
free ( pheaderbuffer ) ;
free ( pbodybuffer ) ;
free ( pwikitextbuffer ) ;
return -1 ;
}
phtmlrenderbuffer [ 0 ] = 0 ;
ppastrevidbuffer = ( char* ) malloc ( buffersize ) ;
if ( ppastrevidbuffer == NULL )
{
error ( "Past revision buffer could not be allocated." ) ;
free ( pheaderbuffer ) ;
free ( pbodybuffer ) ;
free ( pwikitextbuffer ) ;
free ( phtmlrenderbuffer ) ;
return -1 ;
}
ppastrevidbuffer [ 0 ] = 0 ;
peditbuffer = ( char* ) malloc ( buffersize ) ;
if ( peditbuffer == NULL )
{
error ( "Edit buffer could not be allocated." ) ;
free ( pheaderbuffer ) ;
free ( pbodybuffer ) ;
free ( pwikitextbuffer ) ;
free ( phtmlrenderbuffer ) ;
free ( ppastrevidbuffer ) ;
return -1 ;
}
peditbuffer [ 0 ] = 0 ;
// TODO : Eliminate these globals.
szeditsummary [ 0 ] = 0 ; /* Set all of our strings to "". */
szedittoken [ 0 ] = 0 ;
szlogintoken [ 0 ] = 0 ;
sztimestamp [ 0 ] = 0 ;
szauthor [ 0 ] = 0 ;
szpastauthor [ 0 ] = 0 ;
szpastrevid [ 0 ] = 0 ;
uiedittokenexists = 0 ; /* Once set, these persist from one HTTP request to the next. */
uilogintokenexists = 0 ;
uieditsummaryvalid = 0 ;
uitimestampvalid = 0 ;
uiauthorvalid = 0 ;
uipastauthorvalid = 0 ;
headerchunk.stdatasize = 0 ; /* Reset the pointers to our HTTP data buffers. */
bodychunk.stdatasize = 0 ;
int res = 0 ;
if ( ( safeprint ( "We are using libcurl. Version information :\n" ) == 0 )
&& ( safeprintf ( "%s\n" , curl_version () ) == 0 ) )
{
if ( curl_global_init ( CURL_GLOBAL_ALL ) == 0 )
{
if ( safeprint ( "Libcurl initialized successfully.\n" ) == 0 ) /* Announce our success. */
{
if ( startupbot () == 0 )
{
do
{
res = improvewikipedia () ; /* The main stuff. */
} while ( ( res == -1 ) && ( preferences.persevere ) ) ;
/* If we're persevering, ignore fatal return codes. */
}
}
else
error ( "Couldn't deliver message." ) ;
curl_global_cleanup () ; /* (void) */
if ( safeprint ( "Libcurl cleaned up successfully.\n" ) < 0 ) /* Announce our success. */
{
error ( "Couldn't deliver message." ) ;
free ( pheaderbuffer ) ;
free ( pbodybuffer ) ;
free ( pwikitextbuffer ) ;
free ( phtmlrenderbuffer ) ;
free ( ppastrevidbuffer ) ;
free ( peditbuffer ) ;
shutdownbot () ;
return -1 ;
}
}
else
error ( "Couldn't initialize libcurl." ) ;
}
else
error ( "Couldn't deliver message." ) ;
free ( pheaderbuffer ) ;
free ( pbodybuffer ) ;
free ( pwikitextbuffer ) ;
free ( phtmlrenderbuffer ) ;
free ( ppastrevidbuffer ) ;
free ( peditbuffer ) ;
if ( shutdownbot () < 0 ) return -1 ;
if ( res < 0 )
{
return -1 ;
}
return 0 ;
}