xref: /curl/src/tool_easysrc.c (revision 573e7e82)
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 #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 
40 struct slist_wc *easysrc_decl = NULL; /* Variable declarations */
41 struct slist_wc *easysrc_data = NULL; /* Build slists, forms etc. */
42 struct slist_wc *easysrc_code = NULL; /* Setopt calls */
43 struct slist_wc *easysrc_toohard = NULL; /* Unconvertible setopt */
44 struct slist_wc *easysrc_clean = NULL;  /* Clean up allocated data */
45 int easysrc_mime_count = 0;
46 int easysrc_slist_count = 0;
47 
48 static 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.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 initialization come here */
63 /* easysrc_code statements come here */
64 static 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 choose to either not use them or implement",
67   "   them yourself.",
68   "",
69   NULL
70 };
71 static 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 */
easysrc_free(void)80 static 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 */
easysrc_add(struct slist_wc ** plist,const char * line)95 CURLcode 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 
easysrc_addf(struct slist_wc ** plist,const char * fmt,...)108 CURLcode 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 = vaprintf(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(0)
127 
easysrc_init(void)128 CURLcode easysrc_init(void)
129 {
130   CHKRET(easysrc_add(&easysrc_code,
131                      "hnd = curl_easy_init();"));
132   return CURLE_OK;
133 }
134 
easysrc_perform(void)135 CURLcode 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 
easysrc_cleanup(void)165 CURLcode 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 
dumpeasysrc(struct GlobalConfig * config)173 void 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", 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