1/***************************************************************************
2 *                                  _   _ ____  _
3 *  Project                     ___| | | |  _ \| |
4 *                             / __| | | | |_) | |
5 *                            | (__| |_| |  _ <| |___
6 *                             \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22#include "tool_setup.h"
23
24#ifndef CURL_DISABLE_LIBCURL_OPTION
25
26#define ENABLE_CURLX_PRINTF
27/* use our own printf() functions */
28#include "curlx.h"
29
30#include "tool_cfgable.h"
31#include "tool_easysrc.h"
32#include "tool_msgs.h"
33
34#include "memdebug.h" /* keep this as LAST include */
35
36/* global variable definitions, for easy-interface source code generation */
37
38struct curl_slist *easysrc_decl = NULL; /* Variable declarations */
39struct curl_slist *easysrc_data = NULL; /* Build slists, forms etc. */
40struct curl_slist *easysrc_code = NULL; /* Setopt calls */
41struct curl_slist *easysrc_toohard = NULL; /* Unconvertible setopt */
42struct curl_slist *easysrc_clean = NULL;  /* Clean up allocated data */
43int easysrc_form_count = 0;
44int easysrc_slist_count = 0;
45
46static const char *const srchead[]={
47  "/********* Sample code generated by the curl command line tool **********",
48  " * All curl_easy_setopt() options are documented at:",
49  " * http://curl.haxx.se/libcurl/c/curl_easy_setopt.html",
50  " ************************************************************************/",
51  "#include <curl/curl.h>",
52  "",
53  "int main(int argc, char *argv[])",
54  "{",
55  "  CURLcode ret;",
56  "  CURL *hnd;",
57  NULL
58};
59/* easysrc_decl declarations come here */
60/* easysrc_data initialisations come here */
61/* easysrc_code statements come here */
62static const char *const srchard[]={
63  "/* Here is a list of options the curl code used that cannot get generated",
64  "   as source easily. You may select to either not use them or implement",
65  "   them yourself.",
66  "",
67  NULL
68};
69static const char *const srcend[]={
70  "",
71  "  return (int)ret;",
72  "}",
73  "/**** End of sample code ****/",
74  NULL
75};
76
77/* Clean up all source code if we run out of memory */
78static void easysrc_free(void)
79{
80  curl_slist_free_all(easysrc_decl);
81  easysrc_decl = NULL;
82  curl_slist_free_all(easysrc_data);
83  easysrc_data = NULL;
84  curl_slist_free_all(easysrc_code);
85  easysrc_code = NULL;
86  curl_slist_free_all(easysrc_toohard);
87  easysrc_toohard = NULL;
88  curl_slist_free_all(easysrc_clean);
89  easysrc_clean = NULL;
90}
91
92/* Add a source line to the main code or remarks */
93CURLcode easysrc_add(struct curl_slist **plist, const char *line)
94{
95  CURLcode ret = CURLE_OK;
96  struct curl_slist *list =
97    curl_slist_append(*plist, line);
98  if(!list) {
99    easysrc_free();
100    ret = CURLE_OUT_OF_MEMORY;
101  }
102  else
103    *plist = list;
104  return ret;
105}
106
107CURLcode easysrc_addf(struct curl_slist **plist, const char *fmt, ...)
108{
109  CURLcode ret;
110  char *bufp;
111  va_list ap;
112  va_start(ap, fmt);
113  bufp = curlx_mvaprintf(fmt, ap);
114  va_end(ap);
115  if(! bufp) {
116    ret = CURLE_OUT_OF_MEMORY;
117  }
118  else {
119    ret = easysrc_add(plist, bufp);
120    curl_free(bufp);
121  }
122  return ret;
123}
124
125#define CHKRET(v) do {CURLcode ret = (v); if(ret) return ret;} WHILE_FALSE
126
127CURLcode easysrc_init(void)
128{
129  CHKRET(easysrc_add(&easysrc_code,
130                     "hnd = curl_easy_init();"));
131  return CURLE_OK;
132}
133
134CURLcode easysrc_perform(void)
135{
136  /* Note any setopt calls which we could not convert */
137  if(easysrc_toohard) {
138    int i;
139    struct curl_slist *ptr;
140    const char *c;
141    CHKRET(easysrc_add(&easysrc_code, ""));
142    /* Preamble comment */
143    for(i=0; ((c = srchard[i]) != NULL); i++)
144      CHKRET(easysrc_add(&easysrc_code, c));
145    /* Each unconverted option */
146    for(ptr=easysrc_toohard; ptr; ptr = ptr->next)
147      CHKRET(easysrc_add(&easysrc_code, ptr->data));
148    CHKRET(easysrc_add(&easysrc_code, ""));
149    CHKRET(easysrc_add(&easysrc_code, "*/"));
150
151    curl_slist_free_all(easysrc_toohard);
152    easysrc_toohard = NULL;
153  }
154
155  CHKRET(easysrc_add(&easysrc_code, ""));
156  CHKRET(easysrc_add(&easysrc_code, "ret = curl_easy_perform(hnd);"));
157  return CURLE_OK;
158}
159
160CURLcode easysrc_cleanup(void)
161{
162  CHKRET(easysrc_add(&easysrc_code, ""));
163  CHKRET(easysrc_add(&easysrc_code, "curl_easy_cleanup(hnd);"));
164  CHKRET(easysrc_add(&easysrc_code, "hnd = NULL;"));
165  return CURLE_OK;
166}
167
168void dumpeasysrc(struct Configurable *config)
169{
170  struct curl_slist *ptr;
171  char *o = config->libcurl;
172
173  if(o) {
174    FILE *out;
175    bool fopened = FALSE;
176    if(strcmp(o, "-")) {
177      out = fopen(o, "w");
178      fopened = TRUE;
179    }
180    else
181      out = stdout;
182    if(!out)
183      warnf(config, "Failed to open %s to write libcurl code!\n", o);
184    else {
185      int i;
186      const char *c;
187
188      for(i=0; ((c = srchead[i]) != NULL); i++)
189        fprintf(out, "%s\n", c);
190
191      /* Declare variables used for complex setopt values */
192      for(ptr=easysrc_decl; ptr; ptr = ptr->next)
193        fprintf(out, "  %s\n", ptr->data);
194
195      /* Set up complex values for setopt calls */
196      if(easysrc_data) {
197        fprintf(out, "\n");
198
199        for(ptr=easysrc_data; ptr; ptr = ptr->next)
200          fprintf(out, "  %s\n", ptr->data);
201      }
202
203      fprintf(out, "\n");
204      for(ptr=easysrc_code; ptr; ptr = ptr->next) {
205        if(ptr->data[0]) {
206          fprintf(out, "  %s\n", ptr->data);
207        }
208        else {
209          fprintf(out, "\n");
210        }
211      }
212
213      for(ptr=easysrc_clean; ptr; ptr = ptr->next)
214        fprintf(out, "  %s\n", ptr->data);
215
216      for(i=0; ((c = srcend[i]) != NULL); i++)
217        fprintf(out, "%s\n", c);
218
219      if(fopened)
220        fclose(out);
221    }
222  }
223
224  easysrc_free();
225}
226
227#endif /* CURL_DISABLE_LIBCURL_OPTION */
228