1#!/usr/bin/env perl
2#***************************************************************************
3#                                  _   _ ____  _
4#  Project                     ___| | | |  _ \| |
5#                             / __| | | | |_) | |
6#                            | (__| |_| |  _ <| |___
7#                             \___|\___/|_| \_\_____|
8#
9# Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
10#
11# This software is licensed as described in the file COPYING, which
12# you should have received as part of this distribution. The terms
13# are also available at https://curl.haxx.se/docs/copyright.html.
14#
15# You may opt to use, copy, modify, merge, publish, distribute and/or sell
16# copies of the Software, and permit persons to whom the Software is
17# furnished to do so, under the terms of the COPYING file.
18#
19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20# KIND, either express or implied.
21#
22###########################################################################
23
24# Yeah, I know, probably 1000 other persons already wrote a script like
25# this, but I'll tell ya:
26
27# THEY DON'T FIT ME :-)
28
29# Get readme file as parameter:
30
31if($ARGV[0] eq "-c") {
32    $c=1;
33    shift @ARGV;
34}
35
36my $README = $ARGV[0];
37
38if($README eq "") {
39    print "usage: mkhelp.pl [-c] <README> < manpage\n";
40    exit;
41}
42
43
44push @out, "                                  _   _ ____  _\n";
45push @out, "  Project                     ___| | | |  _ \\| |\n";
46push @out, "                             / __| | | | |_) | |\n";
47push @out, "                            | (__| |_| |  _ <| |___\n";
48push @out, "                             \\___|\\___/|_| \\_\\_____|\n";
49
50my $olen=0;
51while (<STDIN>) {
52    my $line = $_;
53
54    # this should be removed:
55    $line =~ s/(.|_)//g;
56
57    # remove trailing CR from line. msysgit checks out files as line+CRLF
58    $line =~ s/\r$//;
59
60    if($line =~ /^([ \t]*\n|curl)/i) {
61        # cut off headers and empty lines
62        $wline++; # count number of cut off lines
63        next;
64    }
65
66    my $text = $line;
67    $text =~ s/^\s+//g; # cut off preceding...
68    $text =~ s/\s+$//g; # and trailing whitespaces
69
70    $tlen = length($text);
71
72    if($wline && ($olen == $tlen)) {
73        # if the previous line with contents was exactly as long as
74        # this line, then we ignore the newlines!
75
76        # We do this magic because a header may abort a paragraph at
77        # any line, but we don't want that to be noticed in the output
78        # here
79        $wline=0;
80    }
81    $olen = $tlen;
82
83    if($wline) {
84        # we only make one empty line max
85        $wline = 0;
86        push @out, "\n";
87    }
88    push @out, $line;
89}
90push @out, "\n"; # just an extra newline
91
92open(READ, "<$README") ||
93    die "couldn't read the README infile $README";
94
95while(<READ>) {
96    my $line = $_;
97
98    # remove trailing CR from line. msysgit checks out files as line+CRLF
99    $line =~ s/\r$//;
100
101    push @out, $line;
102}
103close(READ);
104
105print <<HEAD
106/*
107 * NEVER EVER edit this manually, fix the mkhelp.pl script instead!
108 */
109#ifdef USE_MANUAL
110#include "tool_hugehelp.h"
111HEAD
112    ;
113if($c) {
114    # If compression requested, check that the Gzip module is available
115    # or else disable compression
116    $c = eval
117    {
118      require IO::Compress::Gzip;
119      IO::Compress::Gzip->import();
120      1;
121    };
122    print STDERR "Warning: compression requested but Gzip is not available\n" if (!$c)
123}
124
125if($c)
126{
127    my $content = join("", @out);
128    my $gzippedContent;
129    IO::Compress::Gzip::gzip(
130        \$content, \$gzippedContent, Level => 9, TextFlag => 1, Time=>0) or die "gzip failed:";
131    $gzip = length($content);
132    $gzipped = length($gzippedContent);
133
134    print <<HEAD
135#include <zlib.h>
136#include "memdebug.h" /* keep this as LAST include */
137static const unsigned char hugehelpgz[] = {
138  /* This mumbo-jumbo is the huge help text compressed with gzip.
139     Thanks to this operation, the size of this data shrank from $gzip
140     to $gzipped bytes. You can disable the use of compressed help
141     texts by NOT passing -c to the mkhelp.pl tool. */
142HEAD
143;
144
145    my $c=0;
146    print " ";
147    for(split(//, $gzippedContent)) {
148        my $num=ord($_);
149        printf(" 0x%02x,", 0+$num);
150        if(!(++$c % 12)) {
151            print "\n ";
152        }
153    }
154    print "\n};\n";
155
156    print <<EOF
157#define BUF_SIZE 0x10000
158static voidpf zalloc_func(voidpf opaque, unsigned int items, unsigned int size)
159{
160  (void) opaque;
161  /* not a typo, keep it calloc() */
162  return (voidpf) calloc(items, size);
163}
164static void zfree_func(voidpf opaque, voidpf ptr)
165{
166  (void) opaque;
167  free(ptr);
168}
169/* Decompress and send to stdout a gzip-compressed buffer */
170void hugehelp(void)
171{
172  unsigned char* buf;
173  int status,headerlen;
174  z_stream z;
175
176  /* Make sure no gzip options are set */
177  if (hugehelpgz[3] & 0xfe)
178    return;
179
180  headerlen = 10;
181  memset(&z, 0, sizeof(z_stream));
182  z.zalloc = (alloc_func)zalloc_func;
183  z.zfree = (free_func)zfree_func;
184  z.avail_in = (unsigned int)(sizeof(hugehelpgz) - headerlen);
185  z.next_in = (unsigned char *)hugehelpgz + headerlen;
186
187  if (inflateInit2(&z, -MAX_WBITS) != Z_OK)
188    return;
189
190  buf = malloc(BUF_SIZE);
191  if (buf) {
192    while(1) {
193      z.avail_out = BUF_SIZE;
194      z.next_out = buf;
195      status = inflate(&z, Z_SYNC_FLUSH);
196      if (status == Z_OK || status == Z_STREAM_END) {
197        fwrite(buf, BUF_SIZE - z.avail_out, 1, stdout);
198        if (status == Z_STREAM_END)
199          break;
200      }
201      else
202        break;    /* Error */
203    }
204    free(buf);
205  }
206  inflateEnd(&z);
207}
208EOF
209    ;
210foot();
211exit;
212}
213else {
214    print <<HEAD
215void hugehelp(void)
216{
217   fputs(
218HEAD
219         ;
220}
221
222$outsize=0;
223for(@out) {
224    chop;
225
226    $new = $_;
227
228    $outsize += length($new)+1; # one for the newline
229
230    $new =~ s/\\/\\\\/g;
231    $new =~ s/\"/\\\"/g;
232
233    # gcc 2.96 claims ISO C89 only is required to support 509 letter strings
234    if($outsize > 500) {
235        # terminate and make another fputs() call here
236        print ", stdout);\n fputs(\n";
237        $outsize=length($new)+1;
238    }
239    printf("\"%s\\n\"\n", $new);
240
241}
242
243print ", stdout) ;\n}\n";
244
245foot();
246
247sub foot {
248  print <<FOOT
249#else /* !USE_MANUAL */
250/* built-in manual is disabled, blank function */
251#include "tool_hugehelp.h"
252void hugehelp(void) {}
253#endif /* USE_MANUAL */
254FOOT
255  ;
256}
257