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 <stdio.h> 25#include <curl/curl.h> 26 27/* 28 * Use this tool to generate an updated table for the Curl_getn_scheme_handler 29 * function in url.c. 30 */ 31 32struct detail { 33 const char *n; 34 const char *ifdef; 35}; 36 37static const struct detail scheme[] = { 38 {"dict", "#ifndef CURL_DISABLE_DICT" }, 39 {"file", "#ifndef CURL_DISABLE_FILE" }, 40 {"ftp", "#ifndef CURL_DISABLE_FTP" }, 41 {"ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" }, 42 {"gopher", "#ifndef CURL_DISABLE_GOPHER" }, 43 {"gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" }, 44 {"http", "#ifndef CURL_DISABLE_HTTP" }, 45 {"https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, 46 {"imap", "#ifndef CURL_DISABLE_IMAP" }, 47 {"imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" }, 48 {"ldap", "#ifndef CURL_DISABLE_LDAP" }, 49 {"ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n" 50 " !defined(CURL_DISABLE_LDAPS) && \\\n" 51 " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n" 52 " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" }, 53 {"mqtt", "#ifndef CURL_DISABLE_MQTT" }, 54 {"pop3", "#ifndef CURL_DISABLE_POP3" }, 55 {"pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" }, 56 {"rtmp", "#ifdef USE_LIBRTMP" }, 57 {"rtmpt", "#ifdef USE_LIBRTMP" }, 58 {"rtmpe", "#ifdef USE_LIBRTMP" }, 59 {"rtmpte", "#ifdef USE_LIBRTMP" }, 60 {"rtmps", "#ifdef USE_LIBRTMP" }, 61 {"rtmpts", "#ifdef USE_LIBRTMP" }, 62 {"rtsp", "#ifndef CURL_DISABLE_RTSP" }, 63 {"scp", "#if defined(USE_SSH) && !defined(USE_WOLFSSH)" }, 64 {"sftp", "#if defined(USE_SSH)" }, 65 {"smb", "#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \\\n" 66 " (SIZEOF_CURL_OFF_T > 4)" }, 67 {"smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n" 68 " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" }, 69 {"smtp", "#ifndef CURL_DISABLE_SMTP" }, 70 {"smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" }, 71 {"telnet", "#ifndef CURL_DISABLE_TELNET" }, 72 {"tftp", "#ifndef CURL_DISABLE_TFTP" }, 73 {"ws", "#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" }, 74 {"wss", "#if defined(USE_WEBSOCKETS) && \\\n" 75 " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, 76 { NULL, NULL } 77}; 78 79unsigned int calc(const char *s, int add, int shift) 80{ 81 const char *so = s; 82 unsigned int c = add; 83 while(*s) { 84 c <<= shift; 85 c += *s; 86 s++; 87 } 88 return c; 89} 90 91unsigned int num[100]; 92unsigned int ix[100]; 93 94static void showtable(int try, int init, int shift) 95{ 96 int nulls = 0; 97 int i; 98 for(i = 0; scheme[i].n; ++i) 99 num[i] = calc(scheme[i].n, init, shift); 100 for(i = 0; scheme[i].n; ++i) 101 ix[i] = num[i] % try; 102 printf("/*\n" 103 " unsigned int c = %d\n" 104 " while(l) {\n" 105 " c <<= %d;\n" 106 " c += Curl_raw_tolower(*s);\n" 107 " s++;\n" 108 " l--;\n" 109 " }\n" 110 "*/\n", init, shift); 111 112 printf(" static const struct Curl_handler * const protocols[%d] = {", try); 113 114 /* generate table */ 115 for(i=0; i < try; i++) { 116 int match = 0; 117 int j; 118 for(j=0; scheme[j].n; j++) { 119 if(ix[j] == i) { 120 printf("\n"); 121 printf("%s\n", scheme[j].ifdef); 122 printf(" &Curl_handler_%s,\n", scheme[j].n); 123 printf("#else\n NULL,\n"); 124 printf("#endif"); 125 match = 1; 126 nulls = 0; 127 break; 128 } 129 } 130 if(!match) { 131 if(!nulls || (nulls>10)) { 132 printf("\n "); 133 nulls = 0; 134 } 135 printf(" NULL,", nulls); 136 nulls++; 137 } 138 } 139 printf("\n };\n"); 140} 141 142int main(void) 143{ 144 int i; 145 int try; 146 int besttry = 9999; 147 int bestadd = 0; 148 int bestshift = 0; 149 int add; 150 int shift; 151 for(shift = 0; shift < 8; shift++) { 152 for(add = 0; add < 999; add++) { 153 for(i = 0; scheme[i].n; ++i) { 154 unsigned int v = calc(scheme[i].n, add, shift); 155 int j; 156 int badcombo = 0; 157 for(j=0; j < i; j++) { 158 159 if(num[j] == v) { 160 /* 161 printf("NOPE: %u is a dupe (%s and %s)\n", 162 v, scheme[i], scheme[j]); 163 */ 164 badcombo = 1; 165 break; 166 } 167 } 168 if(badcombo) 169 break; 170 num[i] = v; 171 } 172#if 0 173 for(i = 0; scheme[i].n; ++i) { 174 printf("%u - %s\n", num[i], scheme[i].n); 175 } 176#endif 177 /* try different remainders to find smallest possible table */ 178 for(try = 28; try < 199; try++) { 179 int good = 1; 180 for(i = 0; scheme[i].n; ++i) { 181 ix[i] = num[i] % try; 182 } 183 /* check for dupes */ 184 for(i = 0; scheme[i].n && good; ++i) { 185 int j; 186 for(j=0; j < i; j++) { 187 if(ix[j] == ix[i]) { 188 /* printf("NOPE, try %u causes dupes (%d and %d)\n", try, j, i); */ 189 good = 0; 190 break; 191 } 192 } 193 } 194 if(good) { 195 if(try < besttry) { 196 besttry = try; 197 bestadd = add; 198 bestshift = shift; 199 } 200 break; 201 } 202 } 203 } 204 } 205 206 showtable(besttry, bestadd, bestshift); 207} 208