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