Lightened the stack in wc_statemach to permit deeper recursion

Also, added a few hints to help compilers to perform tail call
recursion optimization.
This commit is contained in:
Dan Fandrich 2010-10-20 18:15:14 -07:00
parent e214cd4a73
commit 59f07ddf28

View File

@ -3562,14 +3562,12 @@ static CURLcode init_wc_data(struct connectdata *conn)
return CURLE_OK; return CURLE_OK;
} }
/* This is called recursively */
static CURLcode wc_statemach(struct connectdata *conn) static CURLcode wc_statemach(struct connectdata *conn)
{ {
struct ftp_conn *ftpc = &conn->proto.ftpc; struct WildcardData * const wildcard = &(conn->data->wildcard);
struct WildcardData *wildcard = &(conn->data->wildcard);
struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
char *tmp_path;
CURLcode ret = CURLE_OK; CURLcode ret = CURLE_OK;
long userresponse = 0;
switch (wildcard->state) { switch (wildcard->state) {
case CURLWC_INIT: case CURLWC_INIT:
ret = init_wc_data(conn); ret = init_wc_data(conn);
@ -3580,10 +3578,10 @@ static CURLcode wc_statemach(struct connectdata *conn)
wildcard->state = ret ? CURLWC_ERROR : CURLWC_MATCHING; wildcard->state = ret ? CURLWC_ERROR : CURLWC_MATCHING;
break; break;
case CURLWC_MATCHING: case CURLWC_MATCHING: {
/* In this state is LIST response successfully parsed, so lets restore /* In this state is LIST response successfully parsed, so lets restore
previous WRITEFUNCTION callback and WRITEDATA pointer */ previous WRITEFUNCTION callback and WRITEDATA pointer */
ftp_tmp = wildcard->tmp; struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
conn->data->set.fwrite_func = ftp_tmp->backup.write_function; conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
conn->data->set.out = ftp_tmp->backup.file_descriptor; conn->data->set.out = ftp_tmp->backup.file_descriptor;
wildcard->state = CURLWC_DOWNLOADING; wildcard->state = CURLWC_DOWNLOADING;
@ -3598,13 +3596,14 @@ static CURLcode wc_statemach(struct connectdata *conn)
wildcard->state = CURLWC_CLEAN; wildcard->state = CURLWC_CLEAN;
return CURLE_REMOTE_FILE_NOT_FOUND; return CURLE_REMOTE_FILE_NOT_FOUND;
} }
ret = wc_statemach(conn); return wc_statemach(conn);
break; } break;
case CURLWC_DOWNLOADING: { case CURLWC_DOWNLOADING: {
/* filelist has at least one file, lets get first one */ /* filelist has at least one file, lets get first one */
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct curl_fileinfo *finfo = wildcard->filelist->head->ptr; struct curl_fileinfo *finfo = wildcard->filelist->head->ptr;
tmp_path = malloc(strlen(conn->data->state.path) + char *tmp_path = malloc(strlen(conn->data->state.path) +
strlen(finfo->filename) + 1); strlen(finfo->filename) + 1);
if(!tmp_path) { if(!tmp_path) {
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -3623,7 +3622,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) { if(conn->data->set.chunk_bgn) {
userresponse = conn->data->set.chunk_bgn( long userresponse = conn->data->set.chunk_bgn(
finfo, wildcard->customptr, (int)wildcard->filelist->size); finfo, wildcard->customptr, (int)wildcard->filelist->size);
switch(userresponse) { switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP: case CURL_CHUNK_BGN_FUNC_SKIP:
@ -3666,16 +3665,17 @@ static CURLcode wc_statemach(struct connectdata *conn)
Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
wildcard->state = (wildcard->filelist->size == 0) ? wildcard->state = (wildcard->filelist->size == 0) ?
CURLWC_CLEAN : CURLWC_DOWNLOADING; CURLWC_CLEAN : CURLWC_DOWNLOADING;
ret = wc_statemach(conn); return wc_statemach(conn);
} break; } break;
case CURLWC_CLEAN: case CURLWC_CLEAN: {
struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
ret = CURLE_OK; ret = CURLE_OK;
if(ftp_tmp) { if(ftp_tmp) {
ret = Curl_ftp_parselist_geterror(ftp_tmp->parser); ret = Curl_ftp_parselist_geterror(ftp_tmp->parser);
} }
wildcard->state = ret ? CURLWC_ERROR : CURLWC_DONE; wildcard->state = ret ? CURLWC_ERROR : CURLWC_DONE;
break; } break;
case CURLWC_DONE: case CURLWC_DONE:
case CURLWC_ERROR: case CURLWC_ERROR: