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