| /*************************************************************************** |
| * _ _ ____ _ |
| * Project ___| | | | _ \| | |
| * / __| | | | |_) | | |
| * | (__| |_| | _ <| |___ |
| * \___|\___/|_| \_\_____| |
| * |
| * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. |
| * |
| * This software is licensed as described in the file COPYING, which |
| * you should have received as part of this distribution. The terms |
| * are also available at https://curl.se/docs/copyright.html. |
| * |
| * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| * copies of the Software, and permit persons to whom the Software is |
| * furnished to do so, under the terms of the COPYING file. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| * SPDX-License-Identifier: curl |
| * |
| ***************************************************************************/ |
| #include <stdio.h> |
| #include <curl/curl.h> |
| |
| /* |
| * Use this tool to generate an updated table for the Curl_getn_scheme_handler |
| * function in url.c. |
| */ |
| |
| struct detail { |
| const char *n; |
| const char *ifdef; |
| }; |
| |
| static const struct detail scheme[] = { |
| {"dict", "#ifndef CURL_DISABLE_DICT" }, |
| {"file", "#ifndef CURL_DISABLE_FILE" }, |
| {"ftp", "#ifndef CURL_DISABLE_FTP" }, |
| {"ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" }, |
| {"gopher", "#ifndef CURL_DISABLE_GOPHER" }, |
| {"gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" }, |
| {"http", "#ifndef CURL_DISABLE_HTTP" }, |
| {"https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, |
| {"imap", "#ifndef CURL_DISABLE_IMAP" }, |
| {"imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" }, |
| {"ldap", "#ifndef CURL_DISABLE_LDAP" }, |
| {"ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n" |
| " !defined(CURL_DISABLE_LDAPS) && \\\n" |
| " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n" |
| " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" }, |
| {"mqtt", "#ifndef CURL_DISABLE_MQTT" }, |
| {"pop3", "#ifndef CURL_DISABLE_POP3" }, |
| {"pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" }, |
| {"rtmp", "#ifdef USE_LIBRTMP" }, |
| {"rtmpt", "#ifdef USE_LIBRTMP" }, |
| {"rtmpe", "#ifdef USE_LIBRTMP" }, |
| {"rtmpte", "#ifdef USE_LIBRTMP" }, |
| {"rtmps", "#ifdef USE_LIBRTMP" }, |
| {"rtmpts", "#ifdef USE_LIBRTMP" }, |
| {"rtsp", "#ifndef CURL_DISABLE_RTSP" }, |
| {"scp", "#if defined(USE_SSH) && !defined(USE_WOLFSSH)" }, |
| {"sftp", "#if defined(USE_SSH)" }, |
| {"smb", "#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \\\n" |
| " (SIZEOF_CURL_OFF_T > 4)" }, |
| {"smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n" |
| " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" }, |
| {"smtp", "#ifndef CURL_DISABLE_SMTP" }, |
| {"smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" }, |
| {"telnet", "#ifndef CURL_DISABLE_TELNET" }, |
| {"tftp", "#ifndef CURL_DISABLE_TFTP" }, |
| {"ws", "#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" }, |
| {"wss", "#if defined(USE_WEBSOCKETS) && \\\n" |
| " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, |
| { NULL, NULL } |
| }; |
| |
| unsigned int calc(const char *s, int add, int shift) |
| { |
| const char *so = s; |
| unsigned int c = add; |
| while(*s) { |
| c <<= shift; |
| c += *s; |
| s++; |
| } |
| return c; |
| } |
| |
| unsigned int num[100]; |
| unsigned int ix[100]; |
| |
| static void showtable(int try, int init, int shift) |
| { |
| int nulls = 0; |
| int i; |
| for(i = 0; scheme[i].n; ++i) |
| num[i] = calc(scheme[i].n, init, shift); |
| for(i = 0; scheme[i].n; ++i) |
| ix[i] = num[i] % try; |
| printf("/*\n" |
| " unsigned int c = %d\n" |
| " while(l) {\n" |
| " c <<= %d;\n" |
| " c += Curl_raw_tolower(*s);\n" |
| " s++;\n" |
| " l--;\n" |
| " }\n" |
| "*/\n", init, shift); |
| |
| printf(" static const struct Curl_handler * const protocols[%d] = {", try); |
| |
| /* generate table */ |
| for(i=0; i < try; i++) { |
| int match = 0; |
| int j; |
| for(j=0; scheme[j].n; j++) { |
| if(ix[j] == i) { |
| printf("\n"); |
| printf("%s\n", scheme[j].ifdef); |
| printf(" &Curl_handler_%s,\n", scheme[j].n); |
| printf("#else\n NULL,\n"); |
| printf("#endif"); |
| match = 1; |
| nulls = 0; |
| break; |
| } |
| } |
| if(!match) { |
| if(!nulls || (nulls>10)) { |
| printf("\n "); |
| nulls = 0; |
| } |
| printf(" NULL,", nulls); |
| nulls++; |
| } |
| } |
| printf("\n };\n"); |
| } |
| |
| int main(void) |
| { |
| int i; |
| int try; |
| int besttry = 9999; |
| int bestadd = 0; |
| int bestshift = 0; |
| int add; |
| int shift; |
| for(shift = 0; shift < 8; shift++) { |
| for(add = 0; add < 999; add++) { |
| for(i = 0; scheme[i].n; ++i) { |
| unsigned int v = calc(scheme[i].n, add, shift); |
| int j; |
| int badcombo = 0; |
| for(j=0; j < i; j++) { |
| |
| if(num[j] == v) { |
| /* |
| printf("NOPE: %u is a dupe (%s and %s)\n", |
| v, scheme[i], scheme[j]); |
| */ |
| badcombo = 1; |
| break; |
| } |
| } |
| if(badcombo) |
| break; |
| num[i] = v; |
| } |
| #if 0 |
| for(i = 0; scheme[i].n; ++i) { |
| printf("%u - %s\n", num[i], scheme[i].n); |
| } |
| #endif |
| /* try different remainders to find smallest possible table */ |
| for(try = 28; try < 199; try++) { |
| int good = 1; |
| for(i = 0; scheme[i].n; ++i) { |
| ix[i] = num[i] % try; |
| } |
| /* check for dupes */ |
| for(i = 0; scheme[i].n && good; ++i) { |
| int j; |
| for(j=0; j < i; j++) { |
| if(ix[j] == ix[i]) { |
| /* printf("NOPE, try %u causes dupes (%d and %d)\n", try, j, i); */ |
| good = 0; |
| break; |
| } |
| } |
| } |
| if(good) { |
| if(try < besttry) { |
| besttry = try; |
| bestadd = add; |
| bestshift = shift; |
| } |
| break; |
| } |
| } |
| } |
| } |
| |
| showtable(besttry, bestadd, bestshift); |
| } |