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